163 lines
3.6 KiB
Go
163 lines
3.6 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/tigorlazuardi/bluemage/go/gen/jet/model"
|
|
"github.com/tigorlazuardi/bluemage/go/pkg/errs"
|
|
"github.com/tigorlazuardi/bluemage/go/pkg/telemetry"
|
|
|
|
. "github.com/go-jet/jet/v2/sqlite"
|
|
. "github.com/tigorlazuardi/bluemage/go/gen/jet/table"
|
|
)
|
|
|
|
type ImageListRequest struct {
|
|
Subreddits []string
|
|
Devices []string
|
|
Limit int64
|
|
After int64
|
|
Before int64
|
|
OrderBy string
|
|
Sort Sort
|
|
Search string
|
|
NSFW *bool
|
|
Blacklist *bool
|
|
}
|
|
|
|
// CREATE VIRTUAL TABLE images_fts5 USING fts5(
|
|
//
|
|
// post_author,
|
|
// post_title,
|
|
// post_name,
|
|
// image_relative_path,
|
|
// post_url,
|
|
// post_author_url,
|
|
// content='images',
|
|
// content_rowid='id'
|
|
//
|
|
// );
|
|
//
|
|
// matching list:
|
|
//
|
|
// - Author's name
|
|
// - Post Title
|
|
// - Post ID
|
|
// - Author's ID
|
|
// - Image filename (url path suffix to get this image from web browser)
|
|
// - Image original url
|
|
// - Post url
|
|
// - Author's url
|
|
var imagesFTSBM25 = fmt.Sprintf("bm25(%s, 25, 20, 10, 5, 3, 3)", ImagesFts5.TableName())
|
|
|
|
func (request ImageListRequest) Statement() SelectStatement {
|
|
cond := request.WhereExpression()
|
|
|
|
if len(request.Search) > 0 {
|
|
cond.AND(ImagesFts5.ImagesFts5.EQ(String(request.Search)))
|
|
stmt := SELECT(
|
|
Images.AllColumns, Devices.Slug, Devices.Name,
|
|
).
|
|
FROM(
|
|
Images.
|
|
INNER_JOIN(Devices, Devices.Slug.EQ(Images.Device)).
|
|
INNER_JOIN(ImagesFts5, Images.PostName.EQ(ImagesFts5.PostName)),
|
|
).
|
|
WHERE(cond)
|
|
if request.Limit > 0 {
|
|
stmt.LIMIT(request.Limit)
|
|
}
|
|
return stmt.ORDER_BY(RawString(imagesFTSBM25).DESC())
|
|
}
|
|
stmt := SELECT(
|
|
Images.AllColumns, Devices.Slug, Devices.Name,
|
|
).
|
|
FROM(Images.INNER_JOIN(Devices, Devices.Slug.EQ(Images.Device))).
|
|
WHERE(cond)
|
|
if request.Limit > 0 {
|
|
stmt.LIMIT(request.Limit)
|
|
}
|
|
|
|
if request.OrderBy == "" {
|
|
return stmt.ORDER_BY(Images.CreatedAt.DESC())
|
|
}
|
|
|
|
orderBy := StringColumn(request.OrderBy)
|
|
if request.Sort == SortDesc {
|
|
return stmt.ORDER_BY(orderBy.DESC())
|
|
}
|
|
return stmt.ORDER_BY(orderBy.ASC())
|
|
}
|
|
|
|
func (request ImageListRequest) WhereExpression() BoolExpression {
|
|
cond := Bool(true)
|
|
if len(request.Devices) > 0 {
|
|
cond.AND(Images.Device.IN(stringSliceExpressions(request.Devices)...))
|
|
}
|
|
|
|
if len(request.Subreddits) > 0 {
|
|
cond.AND(Images.Subreddit.IN(stringSliceExpressions(request.Subreddits)...))
|
|
}
|
|
|
|
if request.NSFW != nil {
|
|
n := *request.NSFW
|
|
if n {
|
|
cond.AND(Images.Nsfw.EQ(Int(1)))
|
|
} else {
|
|
cond.AND(Images.Nsfw.EQ(Int(0)))
|
|
}
|
|
}
|
|
|
|
if request.Blacklist != nil {
|
|
b := *request.Blacklist
|
|
if b {
|
|
cond.AND(Images.Blacklisted.EQ(Int(1)))
|
|
} else {
|
|
cond.AND(Images.Blacklisted.EQ(Int(0)))
|
|
}
|
|
}
|
|
|
|
if request.After > 0 {
|
|
cond.AND(Images.CreatedAt.LT_EQ(Int(request.After)))
|
|
}
|
|
|
|
if request.Before > 0 {
|
|
cond.AND(Images.CreatedAt.GT_EQ(Int(request.Before)))
|
|
}
|
|
return cond
|
|
}
|
|
|
|
type ImageListResponse struct {
|
|
model.Images
|
|
DeviceName string
|
|
}
|
|
|
|
// ImageList list images by request.
|
|
//
|
|
// Results are always grouped by device then grouped by subreddit after sorting.
|
|
func (api *API) ImageList(ctx context.Context, request ImageListRequest) (images []ImageListResponse, err error) {
|
|
ctx, span := tracer.Start(ctx, "ImageList")
|
|
defer func() { telemetry.EndWithStatus(span, err) }()
|
|
|
|
stmt := request.Statement()
|
|
if err := stmt.QueryContext(ctx, api.DB, &images); err != nil {
|
|
return images, errs.Wrapw(err, "failed to list images",
|
|
"request", request,
|
|
"query", stmt.DebugSql(),
|
|
)
|
|
}
|
|
|
|
return images, err
|
|
}
|
|
|
|
func stringSliceExpressions(s []string) []Expression {
|
|
var expr []Expression
|
|
if s != nil {
|
|
expr = make([]Expression, len(s))
|
|
for i, str := range s {
|
|
expr[i] = String(str)
|
|
}
|
|
}
|
|
return expr
|
|
}
|