From bac4472c3a6ef40bc6159041abe9fb5e63ec7aec Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 22 Jun 2025 02:48:02 -0400 Subject: [PATCH] Apparently for 2 weeks (yes 2 whole fucking weeks) I was using NamedExec wrong instead of MustExec so inserts haven't worked since then. Other than that, this is a more cleaned up MVC style setup than before. --- api/tools.go | 43 +++++++++++++++++++++++++++++++ data/crud.go | 40 +++++++++++++++++++++++++++++ data/models.go | 19 ++++++++++++++ main.go | 55 ++++++++++++++++++++-------------------- tools/tools.go | 69 -------------------------------------------------- 5 files changed, 130 insertions(+), 96 deletions(-) create mode 100644 api/tools.go create mode 100644 data/crud.go create mode 100644 data/models.go delete mode 100644 tools/tools.go diff --git a/api/tools.go b/api/tools.go new file mode 100644 index 0000000..d652077 --- /dev/null +++ b/api/tools.go @@ -0,0 +1,43 @@ +package api + +import ( + "log" + "github.com/gofiber/fiber/v2" + "github.com/go-playground/validator/v10" + ) + +type Failure struct { + Message string `json:"message"` +} + +func IfErrNil(err error, c *fiber.Ctx) error { + if err != nil { + log.Output(10, err.Error()) + c.SendStatus(fiber.StatusInternalServerError) + return c.JSON(Failure{err.Error()}) + } + + return err +} + +func ReceivePost[T any](c *fiber.Ctx) (*T, error) { + var result *T + result = new(T) + + if err := c.BodyParser(result); err != nil { + log.Println(err); + return result, err + } + + var validate *validator.Validate + validate = validator.New(validator.WithRequiredStructEnabled()) + + if err := validate.Struct(result); err != nil { + validationErrors := err.(validator.ValidationErrors) + log.Println(validationErrors) + return result, err + } + + return result, nil +} + diff --git a/data/crud.go b/data/crud.go new file mode 100644 index 0000000..ba5e0cb --- /dev/null +++ b/data/crud.go @@ -0,0 +1,40 @@ +package data + +import ( + "github.com/gofiber/fiber/v2" + _ "github.com/mattn/go-sqlite3" + "github.com/jmoiron/sqlx" + ) + +func SelectJson[T any](db *sqlx.DB, c *fiber.Ctx, err error, sql string, args ...interface{}) error { + var result []T + if err != nil { goto fail } + + err = db.Select(&result, sql, args...) + if err != nil { goto fail } + + return c.JSON(&result) + +fail: return err +} + +func GetJson[T any](db *sqlx.DB, c *fiber.Ctx, err error, sql string, args ...interface{}) error { + var result T + if err != nil { goto fail } + + err = db.Get(&result, sql, args...) + if err != nil { goto fail } + + return c.JSON(&result) + +fail: return err +} + +func Insert(db *sqlx.DB, err error, sql_query string, args ...interface{}) error { + if err != nil { return err } + + db.MustExec(sql_query, args...) + return err +} + + diff --git a/data/models.go b/data/models.go new file mode 100644 index 0000000..43c4e15 --- /dev/null +++ b/data/models.go @@ -0,0 +1,19 @@ +package data + +type Login struct { + Username string `db:"username" validate:"required"` + Password string `db:"password" validate:"required"` +} + +type Link struct { + Id int `db:"id" json:"id"` + StreamId int `db:"stream_id" json:"stream_id" form:"stream_id" validate:"required,numeric"` + Url string `db:"url" json:"url" form:"url" validate:"required,url"` + Description string `db:"description" json:"description" form:"description" validate:"required"` +} + +type Stream struct { + Id int `db:"id" json:"id"` + Title string `db:"title" json:"title"` + Description string `db:"description" json:"description"` +} diff --git a/main.go b/main.go index 553e177..15b9a36 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,7 @@ import ( "os" "os/signal" "syscall" - "zedshaw.games/webapp/tools" + "zedshaw.games/webapp/api" "zedshaw.games/webapp/data" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" @@ -41,51 +41,52 @@ func main() { sess.Set("fuck", "off") sql, args, err := sq.Select("*").From("stream").ToSql() - return tools.SelectJson[data.Stream](db, c, err, sql, args...) + err = data.SelectJson[data.Stream](db, c, err, sql, args...) + + return api.IfErrNil(err, c) }) app.Get("/api/stream/:id", func (c *fiber.Ctx) error { sql, args, err := sq.Select("*").From("stream").Where("id", c.Params("id")).ToSql() - return tools.GetJson[data.Stream](db, c, err, sql, args...) + + err = data.GetJson[data.Stream](db, c, err, sql, args...) + return api.IfErrNil(err, c) }) app.Get("/api/stream/:id/links", func (c *fiber.Ctx) error { sql, args, err := sq.Select("*").From("stream_link").Where("stream_id", c.Params("id")).ToSql() - return tools.SelectJson[data.Link](db, c, err, sql, args...) - }) + err = data.SelectJson[data.Link](db, c, err, sql, args...) + return api.IfErrNil(err, c) + }) app.Post("/api/login", func (c *fiber.Ctx) error { - login, err := tools.ReceivePost[data.Login](c) - - if(err != nil) { - log.Println(err) - c.Redirect("/error/") - } + login, err := api.ReceivePost[data.Login](c) + if(err != nil) { goto fail } log.Printf("username: %s; password: %s", login.Username, login.Password); return c.Redirect("/") + + fail: + return api.IfErrNil(err, c) }) app.Post("/api/link", func (c *fiber.Ctx) error { - link, err := tools.ReceivePost[data.Link](c) - if(err != nil) { - log.Println(err) - c.Redirect("/live/") - } - - sql, args, err := sq.Insert("stream_link").Columns("stream_id", "url", "description").Values(link.StreamId, link.Url, link.Description).ToSql() - - err = tools.Insert(db, err, sql, args...) - - if err != nil { - log.Println(err) - return c.Redirect("/live/") - } else { - return c.Redirect("/live/") - } + var sql string + var args []interface{} + + link, err := api.ReceivePost[data.Link](c) + if err != nil { goto fail } + + sql, args, err = sq.Insert("stream_link").Columns("stream_id", "url", "description").Values(link.StreamId, link.Url, link.Description).ToSql() + + err = data.Insert(db, err, sql, args...) + return c.Redirect("/live/") + + fail: + return api.IfErrNil(err, c) }) app.Static("/", "./public") diff --git a/tools/tools.go b/tools/tools.go deleted file mode 100644 index e70a750..0000000 --- a/tools/tools.go +++ /dev/null @@ -1,69 +0,0 @@ -package tools - -import ( - "log" - "github.com/gofiber/fiber/v2" - - _ "github.com/mattn/go-sqlite3" - "github.com/jmoiron/sqlx" - "github.com/go-playground/validator/v10" - ) - -func SelectJson[T any](db *sqlx.DB, c *fiber.Ctx, err error, sql string, args ...interface{}) error { - if(err != nil) { - log.Fatalln(err) - } - var result []T - - err = db.Select(&result, sql, args...) - if(err != nil) { - log.Fatalln(err); - } - - return c.JSON(&result); -} - -func GetJson[T any](db *sqlx.DB, c *fiber.Ctx, err error, sql string, args ...interface{}) error { - if(err != nil) { - log.Fatalln(err) - } - var result T - - err = db.Get(&result, sql, args...) - if(err != nil) { - log.Fatalln(err); - } - - return c.JSON(&result); -} - -func ReceivePost[T any](c *fiber.Ctx) (*T, error) { - var result *T - result = new(T) - - if err := c.BodyParser(result); err != nil { - log.Println(err); - return result, err - } - - var validate *validator.Validate - validate = validator.New(validator.WithRequiredStructEnabled()) - - if err := validate.Struct(result); err != nil { - validationErrors := err.(validator.ValidationErrors) - log.Println(validationErrors) - return result, err - } - - return result, nil -} - -func Insert(db *sqlx.DB, err error, sql_query string, args ...interface{}) error { - if err != nil { - log.Println(err) - return err - } - - _, exec_err := db.NamedExec(sql_query, args) - return exec_err -}