112 lines
2.5 KiB
Go
112 lines
2.5 KiB
Go
package bot
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
|
|
"codeberg.org/nextgo/dbots/internal/db"
|
|
"codeberg.org/nextgo/dbots/internal/errorutil"
|
|
"codeberg.org/nextgo/dbots/internal/middleware"
|
|
"codeberg.org/nextgo/dbots/internal/paginate"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/render"
|
|
)
|
|
|
|
type contextKey string
|
|
|
|
const botKey contextKey = "bot"
|
|
|
|
type Router struct {
|
|
bots *Service
|
|
router chi.Router
|
|
}
|
|
|
|
func NewRouter(q *db.Queries) *Router {
|
|
return &Router{
|
|
bots: NewService(q),
|
|
router: chi.NewRouter(),
|
|
}
|
|
}
|
|
|
|
func (r *Router) Routes() http.Handler {
|
|
r.router.
|
|
With(middleware.AuthGuardMiddleware).
|
|
Post("/", r.submitBot)
|
|
r.router.Get("/", r.listBots)
|
|
r.router.Route("/{botID}", func(router chi.Router) {
|
|
router.Use(r.BotContext)
|
|
router.With(r.BotCache).Get("/", r.getBot)
|
|
})
|
|
|
|
return r.router
|
|
}
|
|
|
|
func (r *Router) submitBot(w http.ResponseWriter, req *http.Request) {
|
|
data := &CreateBotRequest{}
|
|
|
|
if err := render.Bind(req, data); err != nil {
|
|
render.Render(w, req, errorutil.ErrInvalidRequest(err))
|
|
return
|
|
}
|
|
|
|
ctx := req.Context()
|
|
bot, err := r.bots.Submit(ctx, *data)
|
|
if errors.Is(err, errorutil.ErrBotAlreadyExists) {
|
|
render.Render(w, req, errorutil.ErrInvalidRequest(err))
|
|
} else {
|
|
render.Render(w, req, errorutil.ErrInternal(err))
|
|
}
|
|
|
|
render.Status(req, http.StatusCreated)
|
|
render.JSON(w, req, bot)
|
|
}
|
|
|
|
func (r *Router) getBot(w http.ResponseWriter, req *http.Request) {
|
|
ctx := req.Context()
|
|
|
|
bot, ok := ctx.Value(botKey).(*db.Bot)
|
|
if !ok {
|
|
render.Render(w, req, errorutil.ErrInvalidRequest(nil))
|
|
return
|
|
}
|
|
|
|
render.JSON(w, req, bot)
|
|
}
|
|
|
|
func (r *Router) listBots(w http.ResponseWriter, req *http.Request) {
|
|
ctx := req.Context()
|
|
query := req.URL.Query().Get("q")
|
|
p := paginate.ParseParams(req)
|
|
|
|
page, err := r.bots.List(ctx, query, p)
|
|
if err != nil {
|
|
render.Render(w, req, errorutil.ErrInvalidRequest(err))
|
|
return
|
|
}
|
|
|
|
render.JSON(w, req, page)
|
|
}
|
|
|
|
func (r *Router) BotContext(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
ctx := req.Context()
|
|
botID := chi.URLParam(req, "botID")
|
|
bot, err := r.bots.Get(ctx, botID)
|
|
if err != nil {
|
|
render.Render(w, req, errorutil.ErrNotFound)
|
|
return
|
|
}
|
|
|
|
ctx = context.WithValue(ctx, botKey, bot)
|
|
next.ServeHTTP(w, req.WithContext(ctx))
|
|
})
|
|
}
|
|
|
|
func (r *Router) BotCache(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
w.Header().Add("Cache-Control", "max-age=3600")
|
|
next.ServeHTTP(w, req)
|
|
})
|
|
}
|