connect get threads controller

This commit is contained in:
Yanislav Igonin 2022-04-06 11:45:39 +03:00
parent 67fbcf8c17
commit b0727315fe
2 changed files with 323 additions and 336 deletions

View File

@ -1,403 +1,392 @@
package controllers package controllers
import ( import (
"context"
"log" "log"
"math" "math"
"net/http"
"path/filepath"
"strconv" "strconv"
"strings"
"github.com/dchest/captcha" "github.com/dchest/captcha"
"github.com/gin-gonic/gin" "github.com/gofiber/fiber/v2"
Config "micrach/config" "micrach/config"
Db "micrach/db" "micrach/repositories"
Repositories "micrach/repositories"
Utils "micrach/utils"
) )
func GetThreads(c *gin.Context) { func GetThreads(c *fiber.Ctx) error {
pageString := c.DefaultQuery("page", "1") pageString := c.Query("page", "1")
page, err := strconv.Atoi(pageString) page, err := strconv.Atoi(pageString)
if err != nil { if err != nil {
c.HTML(http.StatusNotFound, "404.html", nil) return c.Status(fiber.StatusNotFound).Render("pages/404", nil)
return
} }
if page <= 0 { if page <= 0 {
c.HTML(http.StatusNotFound, "404.html", nil) return c.Status(fiber.StatusNotFound).Render("pages/404", nil)
return
} }
limit := 10 limit := 10
offset := limit * (page - 1) offset := limit * (page - 1)
threads, err := Repositories.Posts.Get(limit, offset) threads, err := repositories.Posts.Get(limit, offset)
if err != nil { if err != nil {
log.Println("error:", err) log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) return c.Status(fiber.StatusInternalServerError).Render("pages/500", nil)
return
} }
count, err := Repositories.Posts.GetThreadsCount() count, err := repositories.Posts.GetThreadsCount()
if err != nil { if err != nil {
log.Println("error:", err) log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) return c.Status(fiber.StatusInternalServerError).Render("pages/500", nil)
return
} }
pagesCount := int(math.Ceil(float64(count) / 10)) pagesCount := int(math.Ceil(float64(count) / 10))
if page > pagesCount && count != 0 { if page > pagesCount && count != 0 {
c.HTML(http.StatusNotFound, "404.html", nil) return c.Status(fiber.StatusNotFound).Render("pages/404", nil)
return
} }
captchaID := captcha.New() captchaID := captcha.New()
htmlData := Repositories.GetThreadsHtmlData{ htmlData := repositories.GetThreadsHtmlData{
Threads: threads, Threads: threads,
Pagination: Repositories.HtmlPaginationData{ Pagination: repositories.HtmlPaginationData{
PagesCount: pagesCount, PagesCount: pagesCount,
Page: page, Page: page,
}, },
FormData: Repositories.HtmlFormData{ FormData: repositories.HtmlFormData{
CaptchaID: captchaID, CaptchaID: captchaID,
IsCaptchaActive: Config.App.IsCaptchaActive, IsCaptchaActive: config.App.IsCaptchaActive,
}, },
} }
c.HTML(http.StatusOK, "index.html", htmlData) return c.Status(fiber.StatusOK).Render("pages/index", htmlData)
} }
func GetThread(c *gin.Context) { // func GetThread(c *gin.Context) {
threadIDString := c.Param("threadID") // threadIDString := c.Param("threadID")
threadID, err := strconv.Atoi(threadIDString) // threadID, err := strconv.Atoi(threadIDString)
if err != nil { // if err != nil {
c.HTML(http.StatusNotFound, "404.html", nil) // c.HTML(http.StatusNotFound, "404.html", nil)
return // return
} // }
thread, err := Repositories.Posts.GetThreadByPostID(threadID) // thread, err := Repositories.Posts.GetThreadByPostID(threadID)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
if thread == nil { // if thread == nil {
c.HTML(http.StatusNotFound, "404.html", nil) // c.HTML(http.StatusNotFound, "404.html", nil)
return // return
} // }
firstPost := thread[0] // firstPost := thread[0]
captchaID := captcha.New() // captchaID := captcha.New()
htmlData := Repositories.GetThreadHtmlData{ // htmlData := Repositories.GetThreadHtmlData{
Thread: thread, // Thread: thread,
FormData: Repositories.HtmlFormData{ // FormData: Repositories.HtmlFormData{
FirstPostID: firstPost.ID, // FirstPostID: firstPost.ID,
CaptchaID: captchaID, // CaptchaID: captchaID,
IsCaptchaActive: Config.App.IsCaptchaActive, // IsCaptchaActive: Config.App.IsCaptchaActive,
}, // },
} // }
c.HTML(http.StatusOK, "thread.html", htmlData) // c.HTML(http.StatusOK, "thread.html", htmlData)
} // }
func CreateThread(c *gin.Context) { // func CreateThread(c *gin.Context) {
form, err := c.MultipartForm() // form, err := c.MultipartForm()
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
// TODO: dat shit crashes if no fields in request // // TODO: dat shit crashes if no fields in request
text := form.Value["text"][0] // text := form.Value["text"][0]
title := form.Value["title"][0] // title := form.Value["title"][0]
filesInRequest := form.File["files"] // filesInRequest := form.File["files"]
validationErrorMessage := Utils.ValidatePost(title, text, filesInRequest) // validationErrorMessage := Utils.ValidatePost(title, text, filesInRequest)
if validationErrorMessage != "" { // if validationErrorMessage != "" {
errorHtmlData := Repositories.BadRequestHtmlData{ // errorHtmlData := Repositories.BadRequestHtmlData{
Message: validationErrorMessage, // Message: validationErrorMessage,
} // }
c.HTML(http.StatusBadRequest, "400.html", errorHtmlData) // c.HTML(http.StatusBadRequest, "400.html", errorHtmlData)
return // return
} // }
if Config.App.IsCaptchaActive { // if Config.App.IsCaptchaActive {
captchaID := form.Value["captchaId"][0] // captchaID := form.Value["captchaId"][0]
captchaString := form.Value["captcha"][0] // captchaString := form.Value["captcha"][0]
isCaptchaValid := captcha.VerifyString(captchaID, captchaString) // isCaptchaValid := captcha.VerifyString(captchaID, captchaString)
if !isCaptchaValid { // if !isCaptchaValid {
errorHtmlData := Repositories.BadRequestHtmlData{ // errorHtmlData := Repositories.BadRequestHtmlData{
Message: Repositories.InvalidCaptchaErrorMessage, // Message: Repositories.InvalidCaptchaErrorMessage,
} // }
c.HTML(http.StatusBadRequest, "400.html", errorHtmlData) // c.HTML(http.StatusBadRequest, "400.html", errorHtmlData)
return // return
} // }
} // }
conn, err := Db.Pool.Acquire(context.TODO()) // conn, err := Db.Pool.Acquire(context.TODO())
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
defer conn.Release() // defer conn.Release()
threadsCount, err := Repositories.Posts.GetThreadsCount() // threadsCount, err := Repositories.Posts.GetThreadsCount()
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
if threadsCount >= Config.App.ThreadsMaxCount { // if threadsCount >= Config.App.ThreadsMaxCount {
oldestThreadUpdatedAt, err := Repositories.Posts.GetOldestThreadUpdatedAt() // oldestThreadUpdatedAt, err := Repositories.Posts.GetOldestThreadUpdatedAt()
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
err = Repositories.Posts.ArchiveThreadsFrom(oldestThreadUpdatedAt) // err = Repositories.Posts.ArchiveThreadsFrom(oldestThreadUpdatedAt)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
} // }
tx, err := conn.Begin(context.TODO()) // tx, err := conn.Begin(context.TODO())
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
defer tx.Rollback(context.TODO()) // defer tx.Rollback(context.TODO())
post := Repositories.Post{ // post := Repositories.Post{
IsParent: true, // IsParent: true,
Title: title, // Title: title,
Text: text, // Text: text,
IsSage: false, // IsSage: false,
} // }
threadID, err := Repositories.Posts.CreateInTx(tx, post) // threadID, err := Repositories.Posts.CreateInTx(tx, post)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
err = Utils.CreateThreadFolder(threadID) // err = Utils.CreateThreadFolder(threadID)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
for _, fileInRequest := range filesInRequest { // for _, fileInRequest := range filesInRequest {
file := Repositories.File{ // file := Repositories.File{
PostID: threadID, // PostID: threadID,
Name: fileInRequest.Filename, // Name: fileInRequest.Filename,
// image/jpeg -> jpeg // // image/jpeg -> jpeg
Ext: strings.Split(fileInRequest.Header["Content-Type"][0], "/")[1], // Ext: strings.Split(fileInRequest.Header["Content-Type"][0], "/")[1],
Size: int(fileInRequest.Size), // Size: int(fileInRequest.Size),
} // }
fileID, err := Repositories.Files.CreateInTx(tx, file) // fileID, err := Repositories.Files.CreateInTx(tx, file)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
path := filepath.Join( // path := filepath.Join(
Utils.UPLOADS_DIR_PATH, // Utils.UPLOADS_DIR_PATH,
strconv.Itoa(threadID), // strconv.Itoa(threadID),
"o", // "o",
strconv.Itoa(fileID)+"."+file.Ext, // strconv.Itoa(fileID)+"."+file.Ext,
) // )
err = c.SaveUploadedFile(fileInRequest, path) // err = c.SaveUploadedFile(fileInRequest, path)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
// creating thumbnail // // creating thumbnail
thumbImg, err := Utils.MakeImageThumbnail(path, file.Ext, threadID, fileID) // thumbImg, err := Utils.MakeImageThumbnail(path, file.Ext, threadID, fileID)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
// saving thumbnail // // saving thumbnail
err = Utils.SaveImageThumbnail(thumbImg, threadID, fileID, file.Ext) // err = Utils.SaveImageThumbnail(thumbImg, threadID, fileID, file.Ext)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
} // }
tx.Commit(context.TODO()) // tx.Commit(context.TODO())
c.Redirect(http.StatusFound, "/"+strconv.Itoa(threadID)) // c.Redirect(http.StatusFound, "/"+strconv.Itoa(threadID))
} // }
// Add new post in thread // // Add new post in thread
func UpdateThread(c *gin.Context) { // func UpdateThread(c *gin.Context) {
threadIDString := c.Param("threadID") // threadIDString := c.Param("threadID")
threadID, err := strconv.Atoi(threadIDString) // threadID, err := strconv.Atoi(threadIDString)
if err != nil { // if err != nil {
c.HTML(http.StatusNotFound, "500.html", nil) // c.HTML(http.StatusNotFound, "500.html", nil)
return // return
} // }
isArchived, err := Repositories.Posts.GetIfThreadIsArchived(threadID) // isArchived, err := Repositories.Posts.GetIfThreadIsArchived(threadID)
if isArchived { // if isArchived {
errorHtmlData := Repositories.BadRequestHtmlData{ // errorHtmlData := Repositories.BadRequestHtmlData{
Message: Repositories.ThreadIsArchivedErrorMessage, // Message: Repositories.ThreadIsArchivedErrorMessage,
} // }
c.HTML(http.StatusBadRequest, "400.html", errorHtmlData) // c.HTML(http.StatusBadRequest, "400.html", errorHtmlData)
return // return
} // }
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
form, err := c.MultipartForm() // form, err := c.MultipartForm()
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
// TODO: dat shit crashes if no fields in request // // TODO: dat shit crashes if no fields in request
text := form.Value["text"][0] // text := form.Value["text"][0]
filesInRequest := form.File["files"] // filesInRequest := form.File["files"]
validationErrorMessage := Utils.ValidatePost("", text, filesInRequest) // validationErrorMessage := Utils.ValidatePost("", text, filesInRequest)
if validationErrorMessage != "" { // if validationErrorMessage != "" {
errorHtmlData := Repositories.BadRequestHtmlData{ // errorHtmlData := Repositories.BadRequestHtmlData{
Message: validationErrorMessage, // Message: validationErrorMessage,
} // }
c.HTML(http.StatusBadRequest, "400.html", errorHtmlData) // c.HTML(http.StatusBadRequest, "400.html", errorHtmlData)
return // return
} // }
if Config.App.IsCaptchaActive { // if Config.App.IsCaptchaActive {
captchaID := form.Value["captchaId"][0] // captchaID := form.Value["captchaId"][0]
captchaString := form.Value["captcha"][0] // captchaString := form.Value["captcha"][0]
isCaptchaValid := captcha.VerifyString(captchaID, captchaString) // isCaptchaValid := captcha.VerifyString(captchaID, captchaString)
if !isCaptchaValid { // if !isCaptchaValid {
errorHtmlData := Repositories.BadRequestHtmlData{ // errorHtmlData := Repositories.BadRequestHtmlData{
Message: Repositories.InvalidCaptchaErrorMessage, // Message: Repositories.InvalidCaptchaErrorMessage,
} // }
c.HTML(http.StatusBadRequest, "400.html", errorHtmlData) // c.HTML(http.StatusBadRequest, "400.html", errorHtmlData)
return // return
} // }
} // }
isSageField := form.Value["sage"] // isSageField := form.Value["sage"]
var isSageString string // var isSageString string
if len(isSageField) != 0 { // if len(isSageField) != 0 {
isSageString = isSageField[0] // isSageString = isSageField[0]
} // }
isSage := isSageString == "on" // isSage := isSageString == "on"
conn, err := Db.Pool.Acquire(context.TODO()) // conn, err := Db.Pool.Acquire(context.TODO())
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
defer conn.Release() // defer conn.Release()
tx, err := conn.Begin(context.TODO()) // tx, err := conn.Begin(context.TODO())
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
defer tx.Rollback(context.TODO()) // defer tx.Rollback(context.TODO())
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
post := Repositories.Post{ // post := Repositories.Post{
IsParent: false, // IsParent: false,
ParentID: &threadID, // ParentID: &threadID,
Title: "", // Title: "",
Text: text, // Text: text,
IsSage: isSage, // IsSage: isSage,
} // }
postID, err := Repositories.Posts.CreateInTx(tx, post) // postID, err := Repositories.Posts.CreateInTx(tx, post)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
postsCountInThread, err := Repositories.Posts.GetThreadPostsCount(threadID) // postsCountInThread, err := Repositories.Posts.GetThreadPostsCount(threadID)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
isBumpLimit := postsCountInThread >= Config.App.ThreadBumpLimit // isBumpLimit := postsCountInThread >= Config.App.ThreadBumpLimit
isThreadBumped := !isBumpLimit && !isSage && !post.IsParent // isThreadBumped := !isBumpLimit && !isSage && !post.IsParent
if isThreadBumped { // if isThreadBumped {
err = Repositories.Posts.BumpThreadInTx(tx, threadID) // err = Repositories.Posts.BumpThreadInTx(tx, threadID)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
} // }
for _, fileInRequest := range filesInRequest { // for _, fileInRequest := range filesInRequest {
file := Repositories.File{ // file := Repositories.File{
PostID: postID, // PostID: postID,
Name: fileInRequest.Filename, // Name: fileInRequest.Filename,
// image/jpeg -> jpeg // // image/jpeg -> jpeg
Ext: strings.Split(fileInRequest.Header["Content-Type"][0], "/")[1], // Ext: strings.Split(fileInRequest.Header["Content-Type"][0], "/")[1],
Size: int(fileInRequest.Size), // Size: int(fileInRequest.Size),
} // }
fileID, err := Repositories.Files.CreateInTx(tx, file) // fileID, err := Repositories.Files.CreateInTx(tx, file)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
path := filepath.Join( // path := filepath.Join(
Utils.UPLOADS_DIR_PATH, // Utils.UPLOADS_DIR_PATH,
strconv.Itoa(threadID), // strconv.Itoa(threadID),
"o", // "o",
strconv.Itoa(fileID)+"."+file.Ext, // strconv.Itoa(fileID)+"."+file.Ext,
) // )
err = c.SaveUploadedFile(fileInRequest, path) // err = c.SaveUploadedFile(fileInRequest, path)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
// creating thumbnail // // creating thumbnail
thumbImg, err := Utils.MakeImageThumbnail(path, file.Ext, threadID, fileID) // thumbImg, err := Utils.MakeImageThumbnail(path, file.Ext, threadID, fileID)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
// saving thumbnail // // saving thumbnail
err = Utils.SaveImageThumbnail(thumbImg, threadID, fileID, file.Ext) // err = Utils.SaveImageThumbnail(thumbImg, threadID, fileID, file.Ext)
if err != nil { // if err != nil {
log.Println("error:", err) // log.Println("error:", err)
c.HTML(http.StatusInternalServerError, "500.html", nil) // c.HTML(http.StatusInternalServerError, "500.html", nil)
return // return
} // }
} // }
tx.Commit(context.TODO()) // tx.Commit(context.TODO())
c.Header("Refresh", "0") // c.Header("Refresh", "0")
} // }

View File

@ -12,6 +12,7 @@ import (
"micrach/build" "micrach/build"
"micrach/config" "micrach/config"
"micrach/controllers"
"micrach/db" "micrach/db"
"micrach/repositories" "micrach/repositories"
"micrach/templates" "micrach/templates"
@ -132,10 +133,7 @@ func main() {
app.Static("/uploads", "./uploads") app.Static("/uploads", "./uploads")
app.Static("/static", "./static") app.Static("/static", "./static")
app.Get("/", func(c *fiber.Ctx) error { app.Get("/", controllers.GetThreads)
// return c.Render("components/index", fiber.Map{})
return c.SendString("get threads")
})
app.Post("/", func(c *fiber.Ctx) error { app.Post("/", func(c *fiber.Ctx) error {
return c.SendString("create thread") return c.SendString("create thread")
}) })