Compare commits

..

No commits in common. "50690f9f94e884957740e3a47cd29870a20e89d7" and "596118b535d5dec7e7180bdb2f0bb118d7dd2b79" have entirely different histories.

7 changed files with 210 additions and 145 deletions

View file

@ -1,6 +1,7 @@
package handlers
import (
"context"
"crypto/sha256"
"encoding/base64"
"log"
@ -17,6 +18,16 @@ import (
"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 {
@ -36,13 +47,13 @@ func Fetch_post(c *fiber.Ctx) error {
var rec []nimdb.GetPostRow
var err error
if len(cursor) == 0 {
rec, err = internal.NIMDB.GetPost(ctx, internal.FETCH_LENGTH)
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: internal.FETCH_LENGTH})
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")
@ -52,18 +63,27 @@ func Fetch_post(c *fiber.Ctx) error {
rec[id] = nimdb.GetPostRow(val)
}
} else {
return c.Status(fiber.StatusBadRequest).SendString("Can't parse cursor")
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)
return c.JSON(rec_with_media)
}
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 {
@ -76,7 +96,7 @@ func Delete_post(c *fiber.Ctx) error {
}
defer tx.Rollback(ctx)
qtx := internal.NIMDB.WithTx(tx)
if err = qtx.DeletePost(ctx, nimdb.DeletePostParams{ID: int32(post_id), Hash: hash}); err != nil {
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 {
@ -90,6 +110,36 @@ func Delete_post(c *fiber.Ctx) error {
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()
@ -153,7 +203,6 @@ func Insert_Post(c *fiber.Ctx) error {
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
}

View file

@ -3,17 +3,12 @@ package internal
import (
"errors"
"os"
"strconv"
)
var (
SALT string
POSTGRES_URL string
JWT_SECRET string
FETCH_LENGTH int32
PREFORK bool
err error
conv int64
)
func ReadFromENV() error {
@ -29,28 +24,5 @@ func ReadFromENV() error {
if len(JWT_SECRET) < 10 {
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
}

View file

@ -34,8 +34,8 @@ func (e *PostPhase) Scan(src interface{}) error {
}
type NullPostPhase struct {
PostPhase PostPhase `json:"post_phase"`
Valid bool `json:"valid"` // Valid is true if PostPhase is not NULL
PostPhase PostPhase
Valid bool // Valid is true if PostPhase is not NULL
}
// Scan implements the Scanner interface.
@ -57,36 +57,36 @@ func (ns NullPostPhase) Value() (driver.Value, error) {
}
type Admin struct {
Username string `json:"username"`
Password string `json:"password"`
Totp string `json:"totp"`
Super bool `json:"super"`
Username string
Password string
Totp string
Super bool
}
type Comment struct {
ID int32 `json:"id"`
PostID int32 `json:"post_id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
Hash string `json:"hash"`
PostAt pgtype.Timestamptz `json:"post_at"`
Heart int32 `json:"heart"`
ID int32
PostID int32
Content string
Signing pgtype.Text
Hash string
PostAt pgtype.Timestamptz
Heart int32
}
type Medium struct {
Url string `json:"url"`
PostID pgtype.Int4 `json:"post_id"`
CommentID pgtype.Int4 `json:"comment_id"`
Visible pgtype.Bool `json:"visible"`
Url string
PostID pgtype.Int4
CommentID pgtype.Int4
Visible pgtype.Bool
}
type Post struct {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
Hash string `json:"hash"`
PostAt pgtype.Timestamptz `json:"post_at"`
Heart int32 `json:"heart"`
Phase PostPhase `json:"phase"`
Igid pgtype.Text `json:"igid"`
ID int32
Content string
Signing pgtype.Text
Hash string
PostAt pgtype.Timestamptz
Heart int32
Phase PostPhase
Igid pgtype.Text
}

View file

@ -38,9 +38,9 @@ INSERT INTO admin (username, password, totp) VALUES ($1, $2,$3)
`
type AdminCreateAccountParams struct {
Username string `json:"username"`
Password string `json:"password"`
Totp string `json:"totp"`
Username string
Password string
Totp string
}
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 {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
PostAt pgtype.Timestamptz `json:"post_at"`
ID int32
Content string
Signing pgtype.Text
PostAt pgtype.Timestamptz
}
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 {
Username string `json:"username"`
Password string `json:"password"`
Username string
Password string
}
type AdminLoginGetTOTPRow struct {
Totp string `json:"totp"`
Super bool `json:"super"`
Totp string
Super bool
}
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 {
Phase PostPhase `json:"phase"`
ID int32 `json:"id"`
Phase PostPhase
ID int32
}
func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32, error) {
@ -155,16 +155,11 @@ func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32
}
const deletePost = `-- name: DeletePost :exec
UPDATE posts SET phase = 'deleted' WHERE id = $1 AND hash=$2
UPDATE posts SET phase = 'deleted' WHERE id = $1
`
type DeletePostParams struct {
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)
func (q *Queries) DeletePost(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deletePost, id)
return err
}
@ -177,15 +172,15 @@ LIMIT $2
`
type GetCommentParams struct {
PostID int32 `json:"post_id"`
Limit int32 `json:"limit"`
PostID int32
Limit int32
}
type GetCommentRow struct {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
PostAt pgtype.Timestamptz `json:"post_at"`
ID int32
Content string
Signing pgtype.Text
PostAt pgtype.Timestamptz
}
func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCommentRow, error) {
@ -213,6 +208,32 @@ func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCo
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
SELECT id, content, signing, post_at
FROM comment
@ -222,16 +243,16 @@ LIMIT $3
`
type GetCommentWithCursorParams struct {
ID int32 `json:"id"`
PostID int32 `json:"post_id"`
Limit int32 `json:"limit"`
ID int32
PostID int32
Limit int32
}
type GetCommentWithCursorRow struct {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
PostAt pgtype.Timestamptz `json:"post_at"`
ID int32
Content string
Signing pgtype.Text
PostAt pgtype.Timestamptz
}
func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCursorParams) ([]GetCommentWithCursorRow, error) {
@ -260,23 +281,20 @@ func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCu
}
const getPost = `-- name: GetPost :many
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
SELECT id, content, signing, post_at, heart, igid
FROM posts
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
WHERE phase = 'ok'
GROUP BY id
ORDER BY id DESC
LIMIT $1
`
type GetPostRow struct {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
PostAt pgtype.Timestamptz `json:"post_at"`
Heart int32 `json:"heart"`
Igid pgtype.Text `json:"igid"`
Enclosure interface{} `json:"enclosure"`
ID int32
Content string
Signing pgtype.Text
PostAt pgtype.Timestamptz
Heart int32
Igid pgtype.Text
}
func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error) {
@ -295,7 +313,6 @@ func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error
&i.PostAt,
&i.Heart,
&i.Igid,
&i.Enclosure,
); err != nil {
return nil, err
}
@ -307,29 +324,52 @@ func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error
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
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
SELECT id, content, signing, post_at, heart, igid
FROM posts
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
WHERE id <= $1 AND phase = 'ok'
GROUP BY id
ORDER BY id DESC
LIMIT $2
`
type GetPostWithCursorParams struct {
ID int32 `json:"id"`
Limit int32 `json:"limit"`
ID int32
Limit int32
}
type GetPostWithCursorRow struct {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
PostAt pgtype.Timestamptz `json:"post_at"`
Heart int32 `json:"heart"`
Igid pgtype.Text `json:"igid"`
Enclosure interface{} `json:"enclosure"`
ID int32
Content string
Signing pgtype.Text
PostAt pgtype.Timestamptz
Heart int32
Igid pgtype.Text
}
func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorParams) ([]GetPostWithCursorRow, error) {
@ -348,7 +388,6 @@ func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorPa
&i.PostAt,
&i.Heart,
&i.Igid,
&i.Enclosure,
); err != nil {
return nil, err
}
@ -365,8 +404,8 @@ INSERT INTO media (url, comment_id) VALUES ($1, $2)
`
type InsertCommentImageParams struct {
Url string `json:"url"`
CommentID pgtype.Int4 `json:"comment_id"`
Url string
CommentID pgtype.Int4
}
func (q *Queries) InsertCommentImage(ctx context.Context, arg InsertCommentImageParams) error {
@ -381,14 +420,14 @@ RETURNING id,hash
`
type InsertPostParams struct {
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
Hash string `json:"hash"`
Content string
Signing pgtype.Text
Hash string
}
type InsertPostRow struct {
ID int32 `json:"id"`
Hash string `json:"hash"`
ID int32
Hash string
}
func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (InsertPostRow, error) {
@ -403,8 +442,8 @@ INSERT INTO media (url, post_id) VALUES ($1, $2)
`
type InsertPostImageParams struct {
Url string `json:"url"`
PostID pgtype.Int4 `json:"post_id"`
Url string
PostID pgtype.Int4
}
func (q *Queries) InsertPostImage(ctx context.Context, arg InsertPostImageParams) error {
@ -426,11 +465,11 @@ SELECT id, content, signing, post_at, phase FROM posts WHERE phase = 'pending' O
`
type SuperAdminGetPostRow struct {
ID int32 `json:"id"`
Content string `json:"content"`
Signing pgtype.Text `json:"signing"`
PostAt pgtype.Timestamptz `json:"post_at"`
Phase PostPhase `json:"phase"`
ID int32
Content string
Signing pgtype.Text
PostAt pgtype.Timestamptz
Phase PostPhase
}
func (q *Queries) SuperAdminGetPost(ctx context.Context) ([]SuperAdminGetPostRow, error) {
@ -464,8 +503,8 @@ UPDATE posts SET phase = $1 WHERE id=$2 AND (phase = 'pending' OR phase = 'rejec
`
type SuperAdminVerifyParams struct {
Phase PostPhase `json:"phase"`
ID int32 `json:"id"`
Phase PostPhase
ID int32
}
func (q *Queries) SuperAdminVerify(ctx context.Context, arg SuperAdminVerifyParams) (int32, error) {
@ -480,8 +519,8 @@ UPDATE posts set igid = $1 WHERE id = $2
`
type UpdatePostIGIDParams struct {
Igid pgtype.Text `json:"igid"`
ID int32 `json:"id"`
Igid pgtype.Text
ID int32
}
func (q *Queries) UpdatePostIGID(ctx context.Context, arg UpdatePostIGIDParams) error {

View file

@ -30,7 +30,7 @@ func main() {
internal.POOL = dbpool
internal.NIMDB = nimdb.New(dbpool)
app := fiber.New(fiber.Config{Prefork: internal.PREFORK})
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")

View file

@ -1,18 +1,14 @@
-- name: GetPost :many
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
SELECT id, content, signing, post_at, heart, igid
FROM posts
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
WHERE phase = 'ok'
GROUP BY id
ORDER BY id DESC
LIMIT $1;
-- name: GetPostWithCursor :many
SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure
SELECT id, content, signing, post_at, heart, igid
FROM posts
LEFT JOIN media ON post_id is not null AND post_id = id AND visible
WHERE id <= $1 AND phase = 'ok'
GROUP BY id
ORDER BY id DESC
LIMIT $2;
@ -25,7 +21,7 @@ RETURNING id,hash;
UPDATE posts set igid = $1 WHERE id = $2;
-- name: DeletePost :exec
UPDATE posts SET phase = 'deleted' WHERE id = $1 AND hash=$2;
UPDATE posts SET phase = 'deleted' WHERE id = $1;
-- name: InvalidateMedia :exec
UPDATE media SET visible = false WHERE post_id = $1;
@ -44,6 +40,15 @@ WHERE id <= $1 AND phase = 'ok' AND post_id = $2
ORDER BY id DESC
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
INSERT INTO media (url, post_id) VALUES ($1, $2);

View file

@ -8,4 +8,4 @@ sql:
package: "nimdb"
out: "nimdb"
sql_package: "pgx/v5"
emit_json_tags: true