Compare commits
2 commits
596118b535
...
50690f9f94
Author | SHA1 | Date | |
---|---|---|---|
50690f9f94 | |||
604b54df1a |
7 changed files with 145 additions and 210 deletions
|
@ -1,7 +1,6 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"log"
|
"log"
|
||||||
|
@ -18,16 +17,6 @@ import (
|
||||||
"nim.jasinco.work/app/nimdb"
|
"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"}
|
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 {
|
func find_supported(mimetype string) bool {
|
||||||
|
@ -47,13 +36,13 @@ func Fetch_post(c *fiber.Ctx) error {
|
||||||
var rec []nimdb.GetPostRow
|
var rec []nimdb.GetPostRow
|
||||||
var err error
|
var err error
|
||||||
if len(cursor) == 0 {
|
if len(cursor) == 0 {
|
||||||
rec, err = internal.NIMDB.GetPost(ctx, 10)
|
rec, err = internal.NIMDB.GetPost(ctx, internal.FETCH_LENGTH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return fiber.ErrInternalServerError
|
return fiber.ErrInternalServerError
|
||||||
}
|
}
|
||||||
} else if cursor_num, err := strconv.Atoi(cursor); err == nil {
|
} 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})
|
rec_cur, err := internal.NIMDB.GetPostWithCursor(ctx, nimdb.GetPostWithCursorParams{ID: int32(cursor_num), Limit: internal.FETCH_LENGTH})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return c.Status(500).SendString("Failed to Query DB")
|
return c.Status(500).SendString("Failed to Query DB")
|
||||||
|
@ -63,27 +52,18 @@ func Fetch_post(c *fiber.Ctx) error {
|
||||||
rec[id] = nimdb.GetPostRow(val)
|
rec[id] = nimdb.GetPostRow(val)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return c.SendStatus(fiber.StatusBadRequest)
|
return c.Status(fiber.StatusBadRequest).SendString("Can't parse cursor")
|
||||||
}
|
}
|
||||||
if len(rec) == 0 {
|
if len(rec) == 0 {
|
||||||
return c.SendStatus(fiber.StatusNoContent)
|
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)
|
return c.JSON(rec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Delete_post(c *fiber.Ctx) error {
|
func Delete_post(c *fiber.Ctx) error {
|
||||||
post := c.Query("post")
|
post := c.Query("post")
|
||||||
|
hash := c.Query("hash")
|
||||||
ctx := c.Context()
|
ctx := c.Context()
|
||||||
post_id, err := strconv.Atoi(post)
|
post_id, err := strconv.Atoi(post)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -96,7 +76,7 @@ func Delete_post(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
defer tx.Rollback(ctx)
|
defer tx.Rollback(ctx)
|
||||||
qtx := internal.NIMDB.WithTx(tx)
|
qtx := internal.NIMDB.WithTx(tx)
|
||||||
if err = qtx.DeletePost(ctx, int32(post_id)); err != nil {
|
if err = qtx.DeletePost(ctx, nimdb.DeletePostParams{ID: int32(post_id), Hash: hash}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = qtx.InvalidateMedia(ctx, pgtype.Int4{Int32: int32(post_id)}); err != nil {
|
if err = qtx.InvalidateMedia(ctx, pgtype.Int4{Int32: int32(post_id)}); err != nil {
|
||||||
|
@ -110,36 +90,6 @@ func Delete_post(c *fiber.Ctx) error {
|
||||||
return c.SendStatus(200)
|
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 {
|
func Insert_Post(c *fiber.Ctx) error {
|
||||||
ctx := c.Context()
|
ctx := c.Context()
|
||||||
|
|
||||||
|
@ -203,6 +153,7 @@ func Insert_Post(c *fiber.Ctx) error {
|
||||||
|
|
||||||
fxnamepath := filetype + "/" + mid.String()
|
fxnamepath := filetype + "/" + mid.String()
|
||||||
if err = c.SaveFile(file, path.Join("./static", fxnamepath)); err != nil {
|
if err = c.SaveFile(file, path.Join("./static", fxnamepath)); err != nil {
|
||||||
|
log.Println("Can't save to ./static", err.Error())
|
||||||
return fiber.ErrInternalServerError
|
return fiber.ErrInternalServerError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,17 @@ package internal
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
SALT string
|
SALT string
|
||||||
POSTGRES_URL string
|
POSTGRES_URL string
|
||||||
JWT_SECRET string
|
JWT_SECRET string
|
||||||
|
FETCH_LENGTH int32
|
||||||
|
PREFORK bool
|
||||||
|
err error
|
||||||
|
conv int64
|
||||||
)
|
)
|
||||||
|
|
||||||
func ReadFromENV() error {
|
func ReadFromENV() error {
|
||||||
|
@ -24,5 +29,28 @@ func ReadFromENV() error {
|
||||||
if len(JWT_SECRET) < 10 {
|
if len(JWT_SECRET) < 10 {
|
||||||
return errors.New("INVALID JWT SECRET")
|
return errors.New("INVALID JWT SECRET")
|
||||||
}
|
}
|
||||||
|
fetch_len_str := os.Getenv("FETCH_LENGTH")
|
||||||
|
if len(fetch_len_str) == 0 {
|
||||||
|
FETCH_LENGTH = 10
|
||||||
|
} else {
|
||||||
|
conv, err = strconv.ParseInt(fetch_len_str, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if conv < 1 {
|
||||||
|
return errors.New("FETCH_LENGTH should be a positive number as well over 0")
|
||||||
|
}
|
||||||
|
FETCH_LENGTH = int32(conv)
|
||||||
|
|
||||||
|
}
|
||||||
|
prefork_str := os.Getenv("PREFORK")
|
||||||
|
if len(prefork_str) == 0 {
|
||||||
|
PREFORK = false
|
||||||
|
} else {
|
||||||
|
PREFORK, err = strconv.ParseBool(prefork_str)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@ func (e *PostPhase) Scan(src interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type NullPostPhase struct {
|
type NullPostPhase struct {
|
||||||
PostPhase PostPhase
|
PostPhase PostPhase `json:"post_phase"`
|
||||||
Valid bool // Valid is true if PostPhase is not NULL
|
Valid bool `json:"valid"` // Valid is true if PostPhase is not NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan implements the Scanner interface.
|
// Scan implements the Scanner interface.
|
||||||
|
@ -57,36 +57,36 @@ func (ns NullPostPhase) Value() (driver.Value, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Admin struct {
|
type Admin struct {
|
||||||
Username string
|
Username string `json:"username"`
|
||||||
Password string
|
Password string `json:"password"`
|
||||||
Totp string
|
Totp string `json:"totp"`
|
||||||
Super bool
|
Super bool `json:"super"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Comment struct {
|
type Comment struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
PostID int32
|
PostID int32 `json:"post_id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
Hash string
|
Hash string `json:"hash"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
Heart int32
|
Heart int32 `json:"heart"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Medium struct {
|
type Medium struct {
|
||||||
Url string
|
Url string `json:"url"`
|
||||||
PostID pgtype.Int4
|
PostID pgtype.Int4 `json:"post_id"`
|
||||||
CommentID pgtype.Int4
|
CommentID pgtype.Int4 `json:"comment_id"`
|
||||||
Visible pgtype.Bool
|
Visible pgtype.Bool `json:"visible"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Post struct {
|
type Post struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
Hash string
|
Hash string `json:"hash"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
Heart int32
|
Heart int32 `json:"heart"`
|
||||||
Phase PostPhase
|
Phase PostPhase `json:"phase"`
|
||||||
Igid pgtype.Text
|
Igid pgtype.Text `json:"igid"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,9 @@ INSERT INTO admin (username, password, totp) VALUES ($1, $2,$3)
|
||||||
`
|
`
|
||||||
|
|
||||||
type AdminCreateAccountParams struct {
|
type AdminCreateAccountParams struct {
|
||||||
Username string
|
Username string `json:"username"`
|
||||||
Password string
|
Password string `json:"password"`
|
||||||
Totp string
|
Totp string `json:"totp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) AdminCreateAccount(ctx context.Context, arg AdminCreateAccountParams) error {
|
func (q *Queries) AdminCreateAccount(ctx context.Context, arg AdminCreateAccountParams) error {
|
||||||
|
@ -77,10 +77,10 @@ SELECT id, content, signing, post_at FROM posts WHERE phase = 'pending' ORDER BY
|
||||||
`
|
`
|
||||||
|
|
||||||
type AdminGetPostRow struct {
|
type AdminGetPostRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) AdminGetPost(ctx context.Context) ([]AdminGetPostRow, error) {
|
func (q *Queries) AdminGetPost(ctx context.Context) ([]AdminGetPostRow, error) {
|
||||||
|
@ -113,13 +113,13 @@ SELECT totp, super FROM admin WHERE username = $1 AND password = $2
|
||||||
`
|
`
|
||||||
|
|
||||||
type AdminLoginGetTOTPParams struct {
|
type AdminLoginGetTOTPParams struct {
|
||||||
Username string
|
Username string `json:"username"`
|
||||||
Password string
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AdminLoginGetTOTPRow struct {
|
type AdminLoginGetTOTPRow struct {
|
||||||
Totp string
|
Totp string `json:"totp"`
|
||||||
Super bool
|
Super bool `json:"super"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) AdminLoginGetTOTP(ctx context.Context, arg AdminLoginGetTOTPParams) (AdminLoginGetTOTPRow, error) {
|
func (q *Queries) AdminLoginGetTOTP(ctx context.Context, arg AdminLoginGetTOTPParams) (AdminLoginGetTOTPRow, error) {
|
||||||
|
@ -143,8 +143,8 @@ UPDATE posts SET phase = $1 WHERE id=$2 AND phase = 'pending' RETURNING id
|
||||||
`
|
`
|
||||||
|
|
||||||
type AdminVerifyParams struct {
|
type AdminVerifyParams struct {
|
||||||
Phase PostPhase
|
Phase PostPhase `json:"phase"`
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32, error) {
|
func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32, error) {
|
||||||
|
@ -155,11 +155,16 @@ func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32
|
||||||
}
|
}
|
||||||
|
|
||||||
const deletePost = `-- name: DeletePost :exec
|
const deletePost = `-- name: DeletePost :exec
|
||||||
UPDATE posts SET phase = 'deleted' WHERE id = $1
|
UPDATE posts SET phase = 'deleted' WHERE id = $1 AND hash=$2
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) DeletePost(ctx context.Context, id int32) error {
|
type DeletePostParams struct {
|
||||||
_, err := q.db.Exec(ctx, deletePost, id)
|
ID int32 `json:"id"`
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) DeletePost(ctx context.Context, arg DeletePostParams) error {
|
||||||
|
_, err := q.db.Exec(ctx, deletePost, arg.ID, arg.Hash)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,15 +177,15 @@ LIMIT $2
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetCommentParams struct {
|
type GetCommentParams struct {
|
||||||
PostID int32
|
PostID int32 `json:"post_id"`
|
||||||
Limit int32
|
Limit int32 `json:"limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetCommentRow struct {
|
type GetCommentRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCommentRow, error) {
|
func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCommentRow, error) {
|
||||||
|
@ -208,32 +213,6 @@ func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCo
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCommentMedia = `-- name: GetCommentMedia :many
|
|
||||||
SELECT url
|
|
||||||
FROM media
|
|
||||||
WHERE comment_id=$1 AND visible = true
|
|
||||||
`
|
|
||||||
|
|
||||||
func (q *Queries) GetCommentMedia(ctx context.Context, commentID pgtype.Int4) ([]string, error) {
|
|
||||||
rows, err := q.db.Query(ctx, getCommentMedia, commentID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var items []string
|
|
||||||
for rows.Next() {
|
|
||||||
var url string
|
|
||||||
if err := rows.Scan(&url); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, url)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCommentWithCursor = `-- name: GetCommentWithCursor :many
|
const getCommentWithCursor = `-- name: GetCommentWithCursor :many
|
||||||
SELECT id, content, signing, post_at
|
SELECT id, content, signing, post_at
|
||||||
FROM comment
|
FROM comment
|
||||||
|
@ -243,16 +222,16 @@ LIMIT $3
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetCommentWithCursorParams struct {
|
type GetCommentWithCursorParams struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
PostID int32
|
PostID int32 `json:"post_id"`
|
||||||
Limit int32
|
Limit int32 `json:"limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetCommentWithCursorRow struct {
|
type GetCommentWithCursorRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCursorParams) ([]GetCommentWithCursorRow, error) {
|
func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCursorParams) ([]GetCommentWithCursorRow, error) {
|
||||||
|
@ -281,20 +260,23 @@ func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCu
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPost = `-- name: GetPost :many
|
const getPost = `-- name: GetPost :many
|
||||||
SELECT id, content, signing, post_at, heart, igid
|
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
|
||||||
FROM posts
|
FROM posts
|
||||||
|
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
|
||||||
WHERE phase = 'ok'
|
WHERE phase = 'ok'
|
||||||
|
GROUP BY id
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT $1
|
LIMIT $1
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetPostRow struct {
|
type GetPostRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
Heart int32
|
Heart int32 `json:"heart"`
|
||||||
Igid pgtype.Text
|
Igid pgtype.Text `json:"igid"`
|
||||||
|
Enclosure interface{} `json:"enclosure"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error) {
|
func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error) {
|
||||||
|
@ -313,6 +295,7 @@ func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error
|
||||||
&i.PostAt,
|
&i.PostAt,
|
||||||
&i.Heart,
|
&i.Heart,
|
||||||
&i.Igid,
|
&i.Igid,
|
||||||
|
&i.Enclosure,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -324,52 +307,29 @@ func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPostMedia = `-- name: GetPostMedia :many
|
|
||||||
SELECT url
|
|
||||||
FROM media
|
|
||||||
WHERE post_id=$1 AND visible = true
|
|
||||||
`
|
|
||||||
|
|
||||||
func (q *Queries) GetPostMedia(ctx context.Context, postID pgtype.Int4) ([]string, error) {
|
|
||||||
rows, err := q.db.Query(ctx, getPostMedia, postID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var items []string
|
|
||||||
for rows.Next() {
|
|
||||||
var url string
|
|
||||||
if err := rows.Scan(&url); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, url)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const getPostWithCursor = `-- name: GetPostWithCursor :many
|
const getPostWithCursor = `-- name: GetPostWithCursor :many
|
||||||
SELECT id, content, signing, post_at, heart, igid
|
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
|
||||||
FROM posts
|
FROM posts
|
||||||
|
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
|
||||||
WHERE id <= $1 AND phase = 'ok'
|
WHERE id <= $1 AND phase = 'ok'
|
||||||
|
GROUP BY id
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT $2
|
LIMIT $2
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetPostWithCursorParams struct {
|
type GetPostWithCursorParams struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Limit int32
|
Limit int32 `json:"limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetPostWithCursorRow struct {
|
type GetPostWithCursorRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
Heart int32
|
Heart int32 `json:"heart"`
|
||||||
Igid pgtype.Text
|
Igid pgtype.Text `json:"igid"`
|
||||||
|
Enclosure interface{} `json:"enclosure"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorParams) ([]GetPostWithCursorRow, error) {
|
func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorParams) ([]GetPostWithCursorRow, error) {
|
||||||
|
@ -388,6 +348,7 @@ func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorPa
|
||||||
&i.PostAt,
|
&i.PostAt,
|
||||||
&i.Heart,
|
&i.Heart,
|
||||||
&i.Igid,
|
&i.Igid,
|
||||||
|
&i.Enclosure,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -404,8 +365,8 @@ INSERT INTO media (url, comment_id) VALUES ($1, $2)
|
||||||
`
|
`
|
||||||
|
|
||||||
type InsertCommentImageParams struct {
|
type InsertCommentImageParams struct {
|
||||||
Url string
|
Url string `json:"url"`
|
||||||
CommentID pgtype.Int4
|
CommentID pgtype.Int4 `json:"comment_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) InsertCommentImage(ctx context.Context, arg InsertCommentImageParams) error {
|
func (q *Queries) InsertCommentImage(ctx context.Context, arg InsertCommentImageParams) error {
|
||||||
|
@ -420,14 +381,14 @@ RETURNING id,hash
|
||||||
`
|
`
|
||||||
|
|
||||||
type InsertPostParams struct {
|
type InsertPostParams struct {
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
Hash string
|
Hash string `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type InsertPostRow struct {
|
type InsertPostRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Hash string
|
Hash string `json:"hash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (InsertPostRow, error) {
|
func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (InsertPostRow, error) {
|
||||||
|
@ -442,8 +403,8 @@ INSERT INTO media (url, post_id) VALUES ($1, $2)
|
||||||
`
|
`
|
||||||
|
|
||||||
type InsertPostImageParams struct {
|
type InsertPostImageParams struct {
|
||||||
Url string
|
Url string `json:"url"`
|
||||||
PostID pgtype.Int4
|
PostID pgtype.Int4 `json:"post_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) InsertPostImage(ctx context.Context, arg InsertPostImageParams) error {
|
func (q *Queries) InsertPostImage(ctx context.Context, arg InsertPostImageParams) error {
|
||||||
|
@ -465,11 +426,11 @@ SELECT id, content, signing, post_at, phase FROM posts WHERE phase = 'pending' O
|
||||||
`
|
`
|
||||||
|
|
||||||
type SuperAdminGetPostRow struct {
|
type SuperAdminGetPostRow struct {
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
Content string
|
Content string `json:"content"`
|
||||||
Signing pgtype.Text
|
Signing pgtype.Text `json:"signing"`
|
||||||
PostAt pgtype.Timestamptz
|
PostAt pgtype.Timestamptz `json:"post_at"`
|
||||||
Phase PostPhase
|
Phase PostPhase `json:"phase"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SuperAdminGetPost(ctx context.Context) ([]SuperAdminGetPostRow, error) {
|
func (q *Queries) SuperAdminGetPost(ctx context.Context) ([]SuperAdminGetPostRow, error) {
|
||||||
|
@ -503,8 +464,8 @@ UPDATE posts SET phase = $1 WHERE id=$2 AND (phase = 'pending' OR phase = 'rejec
|
||||||
`
|
`
|
||||||
|
|
||||||
type SuperAdminVerifyParams struct {
|
type SuperAdminVerifyParams struct {
|
||||||
Phase PostPhase
|
Phase PostPhase `json:"phase"`
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SuperAdminVerify(ctx context.Context, arg SuperAdminVerifyParams) (int32, error) {
|
func (q *Queries) SuperAdminVerify(ctx context.Context, arg SuperAdminVerifyParams) (int32, error) {
|
||||||
|
@ -519,8 +480,8 @@ UPDATE posts set igid = $1 WHERE id = $2
|
||||||
`
|
`
|
||||||
|
|
||||||
type UpdatePostIGIDParams struct {
|
type UpdatePostIGIDParams struct {
|
||||||
Igid pgtype.Text
|
Igid pgtype.Text `json:"igid"`
|
||||||
ID int32
|
ID int32 `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) UpdatePostIGID(ctx context.Context, arg UpdatePostIGIDParams) error {
|
func (q *Queries) UpdatePostIGID(ctx context.Context, arg UpdatePostIGIDParams) error {
|
||||||
|
|
|
@ -30,7 +30,7 @@ func main() {
|
||||||
internal.POOL = dbpool
|
internal.POOL = dbpool
|
||||||
internal.NIMDB = nimdb.New(dbpool)
|
internal.NIMDB = nimdb.New(dbpool)
|
||||||
|
|
||||||
app := fiber.New()
|
app := fiber.New(fiber.Config{Prefork: internal.PREFORK})
|
||||||
|
|
||||||
app.Get("/", func(c *fiber.Ctx) error {
|
app.Get("/", func(c *fiber.Ctx) error {
|
||||||
return c.SendString("Hello, World!")
|
return c.SendString("Hello, World!")
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
-- name: GetPost :many
|
-- name: GetPost :many
|
||||||
SELECT id, content, signing, post_at, heart, igid
|
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
|
||||||
FROM posts
|
FROM posts
|
||||||
|
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
|
||||||
WHERE phase = 'ok'
|
WHERE phase = 'ok'
|
||||||
|
GROUP BY id
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT $1;
|
LIMIT $1;
|
||||||
|
|
||||||
-- name: GetPostWithCursor :many
|
-- name: GetPostWithCursor :many
|
||||||
SELECT id, content, signing, post_at, heart, igid
|
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
|
||||||
FROM posts
|
FROM posts
|
||||||
|
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
|
||||||
WHERE id <= $1 AND phase = 'ok'
|
WHERE id <= $1 AND phase = 'ok'
|
||||||
|
GROUP BY id
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT $2;
|
LIMIT $2;
|
||||||
|
|
||||||
|
@ -21,7 +25,7 @@ RETURNING id,hash;
|
||||||
UPDATE posts set igid = $1 WHERE id = $2;
|
UPDATE posts set igid = $1 WHERE id = $2;
|
||||||
|
|
||||||
-- name: DeletePost :exec
|
-- name: DeletePost :exec
|
||||||
UPDATE posts SET phase = 'deleted' WHERE id = $1;
|
UPDATE posts SET phase = 'deleted' WHERE id = $1 AND hash=$2;
|
||||||
|
|
||||||
-- name: InvalidateMedia :exec
|
-- name: InvalidateMedia :exec
|
||||||
UPDATE media SET visible = false WHERE post_id = $1;
|
UPDATE media SET visible = false WHERE post_id = $1;
|
||||||
|
@ -40,15 +44,6 @@ WHERE id <= $1 AND phase = 'ok' AND post_id = $2
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
LIMIT $3;
|
LIMIT $3;
|
||||||
|
|
||||||
-- name: GetPostMedia :many
|
|
||||||
SELECT url
|
|
||||||
FROM media
|
|
||||||
WHERE post_id=$1 AND visible = true;
|
|
||||||
|
|
||||||
-- name: GetCommentMedia :many
|
|
||||||
SELECT url
|
|
||||||
FROM media
|
|
||||||
WHERE comment_id=$1 AND visible = true;
|
|
||||||
|
|
||||||
-- name: InsertPostImage :exec
|
-- name: InsertPostImage :exec
|
||||||
INSERT INTO media (url, post_id) VALUES ($1, $2);
|
INSERT INTO media (url, post_id) VALUES ($1, $2);
|
||||||
|
|
2
sqlc.yml
2
sqlc.yml
|
@ -8,4 +8,4 @@ sql:
|
||||||
package: "nimdb"
|
package: "nimdb"
|
||||||
out: "nimdb"
|
out: "nimdb"
|
||||||
sql_package: "pgx/v5"
|
sql_package: "pgx/v5"
|
||||||
|
emit_json_tags: true
|
||||||
|
|
Loading…
Add table
Reference in a new issue