diff --git a/Makefile b/Makefile index 15c9e29..de2973a 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ build: build-dependencies prepare prepare: gen mkdir -p public - tailwindcss -i views/styles.css -o public/styles.css + tailwindcss -i views/style.css -o public/style.css templ generate gen: diff --git a/api/api.go b/api/api.go index b44bd20..f504f8e 100644 --- a/api/api.go +++ b/api/api.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/robfig/cron/v3" + "github.com/stephenafamo/bob" "github.com/teivah/broadcast" "github.com/tigorlazuardi/redmage/api/bmessage" "github.com/tigorlazuardi/redmage/api/reddit" @@ -18,6 +19,7 @@ import ( type API struct { queries *queries.Queries db *sql.DB + exec bob.Executor scheduler *cron.Cron scheduleMap map[cron.EntryID]queries.Subreddit @@ -43,6 +45,7 @@ func New(deps Dependencies) *API { return &API{ queries: deps.Queries, db: deps.DB, + exec: bob.New(deps.DB), scheduler: cron.New(), scheduleMap: make(map[cron.EntryID]queries.Subreddit, 8), downloadBroadcast: broadcast.NewRelay[bmessage.ImageDownloadMessage](), diff --git a/api/subreddits_list.go b/api/subreddits_list.go index ba5a2b4..4a3ec10 100644 --- a/api/subreddits_list.go +++ b/api/subreddits_list.go @@ -3,54 +3,68 @@ package api import ( "context" - "github.com/tigorlazuardi/redmage/db/queries" + "github.com/stephenafamo/bob" + "github.com/stephenafamo/bob/dialect/sqlite/dialect" + "github.com/stephenafamo/bob/dialect/sqlite/sm" + "github.com/tigorlazuardi/redmage/models" "github.com/tigorlazuardi/redmage/pkg/errs" ) type ListSubredditsParams struct { - Name string `json:"name"` - Limit int64 `json:"limit"` - Offset int64 `json:"offset"` + Name string `json:"name"` + Limit int64 `json:"limit"` + Offset int64 `json:"offset"` + OrderBy string `json:"order_by"` + Sort string `json:"sort"` +} + +func (l ListSubredditsParams) Query() (expr []bob.Mod[*dialect.SelectQuery]) { + if l.Name != "" { + expr = append(expr, models.SelectWhere.Subreddits.Name.Like("%"+l.Name+"%")) + } + if l.Limit > 0 { + expr = append(expr, sm.Limit(l.Limit)) + } + if l.Offset > 0 { + expr = append(expr, sm.Offset(l.Offset)) + } + if l.OrderBy != "" { + if l.Sort == "desc" { + expr = append(expr, sm.OrderBy(l.OrderBy).Desc()) + } else { + expr = append(expr, sm.OrderBy(l.OrderBy).Asc()) + } + } + + return expr +} + +func (l ListSubredditsParams) CountQuery() (expr []bob.Mod[*dialect.SelectQuery]) { + if l.Name != "" { + expr = append(expr, models.SelectWhere.Subreddits.Name.Like("%"+l.Name+"%")) + } + + return expr } type ListSubredditsResult struct { Total int64 - Data []queries.Subreddit + Data models.SubredditSlice } func (api *API) ListSubreddits(ctx context.Context, arg ListSubredditsParams) (result ListSubredditsResult, err error) { ctx, span := tracer.Start(ctx, "api.ListSubreddits") defer span.End() - if arg.Name != "" { - result.Data, err = api.queries.SubredditsSearch(ctx, queries.SubredditsSearchParams{ - Name: "%" + arg.Name + "%", - Limit: arg.Limit, - Offset: arg.Offset, - }) - if err != nil { - return result, errs.Wrapw(err, "failed to search subreddit", "query", arg) - } - result.Total, err = api.queries.SubredditsSearchCount(ctx, queries.SubredditsSearchCountParams{ - Name: "%" + arg.Name + "%", - Limit: arg.Limit, - Offset: arg.Offset, - }) - if err != nil { - return result, errs.Wrapw(err, "failed to count subreddit search", "query", arg) - } - return result, err + + result.Data, err = models.Subreddits.Query(ctx, api.exec, arg.Query()...).All() + if err != nil { + return result, errs.Wrapw(err, "failed to list subreddits", "query", arg) } - result.Data, err = api.queries.SubredditsList(ctx, queries.SubredditsListParams{ - Limit: arg.Limit, - Offset: arg.Offset, - }) + result.Total, err = models.Subreddits.Query(ctx, api.exec, arg.CountQuery()...).Count() if err != nil { - return result, errs.Wrapw(err, "failed to list subreddit", "query", arg) + return result, errs.Wrapw(err, "failed to count subreddits", "query", arg) } - result.Total, err = api.queries.SubredditsListCount(ctx) - if err != nil { - return result, errs.Wrapw(err, "failed to count subreddit list", "query", arg) - } - return result, err + + return result, nil } diff --git a/server/routes/middleware/logger.go b/server/routes/middleware/logger.go index c78934d..711a746 100644 --- a/server/routes/middleware/logger.go +++ b/server/routes/middleware/logger.go @@ -26,7 +26,7 @@ func (ch *ChiEntry) Write(status int, bytes int, header http.Header, elapsed tim message := fmt.Sprintf("%s %s %d %s", ch.request.Method, ch.request.URL, status, elasedStr) requestLog := slog.Attr{Key: "request", Value: ch.extractRequestLog()} - responseLog := slog.Group("response", "status", status, "headers", flatHeader(header), "bytes", bytes) + responseLog := slog.Group("response", "status", status, "headers", flat(header), "bytes", bytes) roundtripLog := slog.String("elapsed", elasedStr) group := slog.Group("http", requestLog, responseLog, roundtripLog) @@ -57,13 +57,13 @@ func (ch *ChiEntry) extractRequestLog() slog.Value { ) queries := ch.request.URL.Query() if len(queries) > 0 { - values = append(values, slog.Any("query", queries)) + values = append(values, slog.Any("query", flat(queries))) } - values = append(values, slog.Any("headers", flatHeader(ch.request.Header))) + values = append(values, slog.Any("headers", flat(ch.request.Header))) return slog.GroupValue(values...) } -func flatHeader(header http.Header) map[string]string { +func flat(header map[string][]string) map[string]string { m := make(map[string]string, len(header)) for k := range header { diff --git a/server/routes/routes.go b/server/routes/routes.go index 0e844a5..d782e57 100644 --- a/server/routes/routes.go +++ b/server/routes/routes.go @@ -40,6 +40,7 @@ func (routes *Routes) registerV1APIRoutes(router chi.Router) { } func (routes *Routes) registerWWWRoutes(router chi.Router) { + router.Use(chimiddleware.Compress(5, "text/html", "text/css", "application/javascript")) router.Mount("/public", http.StripPrefix("/public", http.FileServer(http.FS(routes.PublicDir)))) router.Group(func(r chi.Router) {