177 lines
4.5 KiB
Go
177 lines
4.5 KiB
Go
package handlers
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"log"
|
|
"mime"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
"nim.jasinco.work/app/internal"
|
|
"nim.jasinco.work/app/nimdb"
|
|
)
|
|
|
|
var supported_filetype = []string{"image/png", "image/jpeg", "image/webp", "image/gif", "image/heif", "video/H264", "video/H265", "video/mp4"}
|
|
|
|
func find_supported(mimetype string) bool {
|
|
for _, supported := range supported_filetype {
|
|
if strings.Compare(supported, mimetype) == 0 {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func Fetch_post(c *fiber.Ctx) error {
|
|
cursor := c.Query("cursor")
|
|
|
|
ctx := c.Context()
|
|
|
|
var rec []nimdb.GetPostRow
|
|
var err error
|
|
if len(cursor) == 0 {
|
|
rec, err = internal.NIMDB.GetPost(ctx, internal.FETCH_LENGTH)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return fiber.ErrInternalServerError
|
|
}
|
|
} else if cursor_num, err := strconv.Atoi(cursor); err == nil {
|
|
rec_cur, err := internal.NIMDB.GetPostWithCursor(ctx, nimdb.GetPostWithCursorParams{ID: int32(cursor_num), Limit: internal.FETCH_LENGTH})
|
|
if err != nil {
|
|
log.Println(err)
|
|
return c.Status(500).SendString("Failed to Query DB")
|
|
}
|
|
rec = make([]nimdb.GetPostRow, len(rec_cur))
|
|
for id, val := range rec_cur {
|
|
rec[id] = nimdb.GetPostRow(val)
|
|
}
|
|
} else {
|
|
return c.Status(fiber.StatusBadRequest).SendString("Can't parse cursor")
|
|
}
|
|
if len(rec) == 0 {
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
}
|
|
|
|
return c.JSON(rec)
|
|
}
|
|
|
|
func Delete_post(c *fiber.Ctx) error {
|
|
post := c.Query("post")
|
|
hash := c.Query("hash")
|
|
ctx := c.Context()
|
|
post_id, err := strconv.Atoi(post)
|
|
if err != nil {
|
|
return c.Status(500).SendString("Failed to Parse Int")
|
|
}
|
|
|
|
tx, err := internal.POOL.Begin(ctx)
|
|
if err != nil {
|
|
return c.Status(500).SendString("Failed to Start Transaction")
|
|
}
|
|
defer tx.Rollback(ctx)
|
|
qtx := internal.NIMDB.WithTx(tx)
|
|
if err = qtx.DeletePost(ctx, nimdb.DeletePostParams{ID: int32(post_id), Hash: hash}); err != nil {
|
|
return err
|
|
}
|
|
if err = qtx.InvalidateMedia(ctx, pgtype.Int4{Int32: int32(post_id)}); err != nil {
|
|
return err
|
|
}
|
|
|
|
if tx.Commit(ctx) != nil {
|
|
return c.Status(500).SendString("Failed to Commit")
|
|
}
|
|
|
|
return c.SendStatus(200)
|
|
}
|
|
|
|
func Insert_Post(c *fiber.Ctx) error {
|
|
ctx := c.Context()
|
|
|
|
tx, err := internal.POOL.Begin(ctx)
|
|
if err != nil {
|
|
return c.Status(500).SendString("Failed to Start Transaction")
|
|
}
|
|
defer tx.Rollback(ctx)
|
|
qtx := internal.NIMDB.WithTx(tx)
|
|
|
|
if form, err := c.MultipartForm(); err == nil {
|
|
|
|
content := form.Value["content"]
|
|
signing := form.Value["signing"]
|
|
files := form.File["enclosure"]
|
|
if len(content) == 0 || len(content[0]) == 0 {
|
|
return fiber.ErrBadRequest
|
|
}
|
|
post_hash := sha256.New()
|
|
post_hash.Write([]byte(content[0]))
|
|
signing_pgt := new(pgtype.Text)
|
|
signing_pgt.Valid = false
|
|
if len(signing) > 0 && len(signing[0]) > 0 {
|
|
post_hash.Write([]byte(signing[0]))
|
|
signing_pgt.Valid = true
|
|
signing_pgt.String = signing[0]
|
|
}
|
|
now, err := time.Now().MarshalBinary()
|
|
if err != nil {
|
|
c.SendString("Failed to get time")
|
|
return c.SendStatus(500)
|
|
}
|
|
|
|
credential, err := qtx.InsertPost(ctx,
|
|
nimdb.InsertPostParams{
|
|
Content: content[0],
|
|
Signing: *signing_pgt,
|
|
Hash: base64.StdEncoding.EncodeToString(post_hash.Sum(now)),
|
|
},
|
|
)
|
|
if err != nil {
|
|
log.Println(err.Error())
|
|
return c.Status(500).SendString("Failed to insert post")
|
|
}
|
|
|
|
for _, file := range files {
|
|
filemime, _, err := mime.ParseMediaType(file.Header.Get("Content-Type"))
|
|
if err != nil {
|
|
return c.Status(fiber.ErrBadRequest.Code).SendString("Failed to parse content type")
|
|
}
|
|
if !find_supported(filemime) {
|
|
return c.Status(fiber.ErrBadRequest.Code).SendString("Unsupported Type")
|
|
}
|
|
|
|
filetype := strings.Split(filemime, "/")[0]
|
|
mid, err := uuid.NewRandom()
|
|
if err != nil {
|
|
c.SendString("Faild to generate UUIDv4")
|
|
return c.SendStatus(500)
|
|
}
|
|
|
|
fxnamepath := filetype + "/" + mid.String()
|
|
if err = c.SaveFile(file, path.Join("./static", fxnamepath)); err != nil {
|
|
log.Println("Can't save to ./static", err.Error())
|
|
return fiber.ErrInternalServerError
|
|
}
|
|
|
|
if err := qtx.InsertPostImage(ctx, nimdb.InsertPostImageParams{
|
|
Url: fxnamepath,
|
|
PostID: pgtype.Int4{Int32: credential.ID, Valid: true},
|
|
}); err != nil {
|
|
log.Println(err.Error())
|
|
return c.Status(500).SendString("Failed to insert image")
|
|
}
|
|
}
|
|
if err = tx.Commit(ctx); err != nil {
|
|
log.Println(err.Error())
|
|
c.SendString("Failed to send Commit")
|
|
return c.SendStatus(500)
|
|
}
|
|
return c.JSON(credential)
|
|
}
|
|
|
|
return fiber.ErrBadRequest
|
|
}
|