226 lines
6.1 KiB
Go
226 lines
6.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"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"
|
|
)
|
|
|
|
type Post struct {
|
|
ID int32 `json:"id"`
|
|
Content string `json:"content"`
|
|
Heart int32 `json:"heart"`
|
|
Enclosure []string `json:"enclosure"`
|
|
Signing pgtype.Text `json:"signing"`
|
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
|
IGid pgtype.Text `json:"igid"`
|
|
}
|
|
|
|
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, 10)
|
|
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: 10})
|
|
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.SendStatus(fiber.StatusBadRequest)
|
|
}
|
|
if len(rec) == 0 {
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
}
|
|
var rec_with_media []Post = make([]Post, len(rec))
|
|
for i, val := range rec {
|
|
rec_with_media[i] = Post{ID: val.ID, Content: val.Content, Signing: val.Signing, PostAt: val.PostAt, Heart: val.Heart, IGid: val.Igid}
|
|
media, err := internal.NIMDB.GetPostMedia(ctx, pgtype.Int4{Int32: val.ID, Valid: true})
|
|
if err != nil {
|
|
log.Println(err)
|
|
return fiber.ErrInternalServerError
|
|
}
|
|
rec_with_media[i].Enclosure = media
|
|
}
|
|
|
|
return c.JSON(rec_with_media)
|
|
}
|
|
|
|
func Delete_post(c *fiber.Ctx) error {
|
|
post := c.Query("post")
|
|
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, int32(post_id)); 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 Fetch_comment(c *fiber.Ctx) error {
|
|
cursor := c.Query("cursor")
|
|
post, err := strconv.Atoi(c.Query("post"))
|
|
if err != nil {
|
|
return c.Status(500).SendString("Failed to parse Int")
|
|
}
|
|
|
|
ctx := context.Background()
|
|
conn, err := internal.POOL.Acquire(ctx)
|
|
if err != nil {
|
|
return c.Status(500).SendString("Failed to Acuire DB")
|
|
}
|
|
defer conn.Release()
|
|
db := nimdb.New(conn)
|
|
|
|
var rec []nimdb.GetCommentRow
|
|
if len(cursor) == 0 {
|
|
rec, err = db.GetComment(ctx, nimdb.GetCommentParams{PostID: int32(post), Limit: 10})
|
|
} else if cursor_num, err := strconv.Atoi(cursor); err == nil {
|
|
rec_cur, err := db.GetCommentWithCursor(ctx, nimdb.GetCommentWithCursorParams{ID: int32(cursor_num), PostID: int32(post), Limit: 10})
|
|
if err != nil {
|
|
return c.Status(500).SendString("Failed to Parse Query DB")
|
|
}
|
|
rec = make([]nimdb.GetCommentRow, len(rec_cur))
|
|
for id, val := range rec_cur {
|
|
rec[id] = nimdb.GetCommentRow(val)
|
|
}
|
|
}
|
|
return c.JSON(rec)
|
|
}
|
|
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 {
|
|
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
|
|
}
|