mercury/web/api/posts/create_post.go

97 lines
2.3 KiB
Go

package posts
import (
"net/http"
"git.sleepycat.moe/sam/mercury/internal/database"
"git.sleepycat.moe/sam/mercury/internal/database/sql"
"git.sleepycat.moe/sam/mercury/internal/utils"
"git.sleepycat.moe/sam/mercury/web/api"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/oklog/ulid/v2"
"github.com/rs/zerolog/log"
)
type createPostParams struct {
Content string `json:"content"`
Visibility database.PostVisibility `json:"visibility"`
}
func (p createPostParams) Validate(cfg database.Config) bool {
if p.Content == "" { // TODO: allow empty content if the post has attachments
return false
}
if p.Visibility == "" {
return false
}
if utils.StringLength(p.Content) > cfg.PostCharacterLimit {
return false
}
switch p.Visibility {
case database.PublicVisibility, database.UnlistedVisibility, database.FollowersVisibility, database.DirectVisibility:
default:
return false
}
// everything checks out
return true
}
func (app *App) Create(w http.ResponseWriter, r *http.Request) (api.Post, error) {
ctx := r.Context()
token, _ := app.TokenFromContext(ctx)
var req createPostParams
err := render.Decode(r, &req)
if err != nil {
return api.Post{}, api.Error{Code: api.ErrBadRequest}
}
if !req.Validate(app.DBConfig.Get()) {
return api.Post{}, api.Error{Code: api.ErrBadRequest}
}
blogID, err := ulid.Parse(chi.URLParam(r, "blogID"))
if err != nil {
return api.Post{}, api.Error{Code: api.ErrBlogNotFound}
}
conn, err := app.Database.Acquire(ctx)
if err != nil {
log.Err(err).Msg("acquiring connection")
return api.Post{}, err
}
defer conn.Release()
blog, err := app.Blog(conn).ByID(ctx, blogID)
if err != nil {
if err == sql.ErrNotFound {
return api.Post{}, api.Error{Code: api.ErrBlogNotFound}
}
log.Err(err).Msg("fetching blog")
return api.Post{}, err
}
acct, err := app.Account(conn).ByID(ctx, blog.AccountID)
if err != nil {
log.Err(err).Msg("fetching account")
return api.Post{}, err
}
if blog.AccountID != token.UserID {
return api.Post{}, api.Error{Code: api.ErrNotYourObject}
}
// create post
post, err := app.Post(conn).Create(ctx, blog, req.Content, req.Visibility)
if err != nil {
log.Err(err).Msg("creating post")
return api.Post{}, err
}
go app.Processor.HandlePost(post)
return api.DBPostToPost(post, blog, acct), nil
}