package internal import ( "fmt" "net/http" "strconv" "exporter/database/telegram_resource/public/model" "exporter/database/telegram_resource/public/table" "exporter/frontend" . "github.com/go-jet/jet/v2/postgres" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/favicon" "github.com/gofiber/fiber/v2/middleware/filesystem" log "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/recover" "github.com/spf13/cobra" ) func ServeCmd() *cobra.Command { cmd := &cobra.Command{ Use: "serve", Short: "http server", RunE: serveCmd, } return cmd } func serveCmd(cmd *cobra.Command, args []string) error { var err error var port int64 = 3000 if len(args) > 0 { port, err = strconv.ParseInt(args[0], 10, 64) if err != nil { return err } } app := fiber.New() app.Static("/medias", "/share/telegram/outputs") app.Use(log.New()) app.Use(favicon.New(favicon.Config{ Data: frontend.Favicon, })) app.Use("/assets", filesystem.New(filesystem.Config{ Root: http.FS(frontend.StaticDist), PathPrefix: "dist/assets", })) // Initialize default config app.Use(recover.New()) indexFunc := func(c *fiber.Ctx) error { c.Context().SetContentType("text/html") return c.SendString(frontend.IndexPage) } app.Get("/", indexFunc) group := app.Group("/api") // get channel list group.Get("/channels", func(c *fiber.Ctx) error { var channels []model.Channels tbl := table.Channels if err := tbl.SELECT(tbl.AllColumns).QueryContext(c.Context(), db, &channels); err != nil { return err } return c.JSON(channels) }) // get channel info group.Get("/channels/:channel", func(c *fiber.Ctx) error { channelID, err := c.ParamsInt("channel") if err != nil { return err } var channel model.Channels tbl := table.Channels err = tbl. SELECT(tbl.AllColumns). WHERE(tbl.UUID.EQ(Int64(int64(channelID)))). QueryContext(c.Context(), db, &channel) if err != nil { return err } return c.JSON(channel) }) // get channel's post list group.Get("/channels/:channel/messages", func(c *fiber.Ctx) error { channelID, err := c.ParamsInt("channel") if err != nil { return err } offsetPk := c.QueryInt("offset", 0) var messages []model.ChannelMessages tbl := table.ChannelMessages cond := tbl.ChannelID.EQ(Int64(int64(channelID))) if offsetPk > 0 { cond = cond.AND(tbl.ID.LT(Int64(int64(offsetPk)))) } err = tbl. SELECT(tbl.AllColumns). WHERE(cond). LIMIT(5). ORDER_BY(tbl.ID.DESC()). QueryContext(c.Context(), db, &messages) if err != nil { return err } return c.JSON(messages) }) // favorite messages group.Get("/favorites", func(c *fiber.Ctx) error { offsetPk := c.QueryInt("offset", 0) tbl := table.ChannelMessages cond := tbl.Favorite.EQ(Bool(true)) if offsetPk > 0 { cond = cond.AND(tbl.ID.LT(Int64(int64(offsetPk)))) } var messages []model.ChannelMessages err = tbl. SELECT(tbl.AllColumns). WHERE(cond). LIMIT(5). ORDER_BY(tbl.ID.DESC()). QueryContext(c.Context(), db, &messages) if err != nil { return err } return c.JSON(messages) }) // toggle favorite message group.Patch("messages/:message/favorite", func(c *fiber.Ctx) error { messageID, err := c.ParamsInt("message") if err != nil { return err } var msg model.ChannelMessages tbl := table.ChannelMessages err = tbl. SELECT(tbl.AllColumns). WHERE(tbl.ID.EQ(Int64(int64(messageID)))). ORDER_BY(tbl.ID.DESC()). LIMIT(1). QueryContext(c.Context(), db, &msg) if err != nil { return err } stmt := tbl. UPDATE(). SET(tbl.Favorite.SET(Bool(!msg.Favorite))). WHERE(tbl.ID.EQ(Int64(int64(messageID)))) _, err = stmt.ExecContext(c.Context(), db) if err != nil { return err } return nil }) // delete message group.Delete("/messages/:message", func(c *fiber.Ctx) error { msgID, err := c.ParamsInt("message") if err != nil { return err } tbl := table.ChannelMessages _, err = tbl. DELETE(). WHERE(tbl.ID.EQ(Int64(int64(msgID)))). ExecContext(c.Context(), db) if err != nil { return err } return nil }) // not found route use frontend router // handle 404 app.Use(indexFunc) return app.Listen(fmt.Sprintf(":%d", port)) }