images: implemented ListImages handler
This commit is contained in:
parent
0fec03adbc
commit
9e1a192f93
|
@ -50,35 +50,30 @@ type ImageListRequest struct {
|
|||
// - Author's url
|
||||
var imagesFTSBM25 = fmt.Sprintf("bm25(%s, 25, 20, 10, 5, 3, 3)", ImagesFts5.TableName())
|
||||
|
||||
func (request ImageListRequest) Statement() Statement {
|
||||
queriedImages := CTE("queried_images")
|
||||
|
||||
return WITH(
|
||||
queriedImages.AS(request.SelectStatement()),
|
||||
)(
|
||||
SELECT(queriedImages.AllColumns()).
|
||||
FROM(queriedImages).
|
||||
ORDER_BY(
|
||||
Images.Device.ASC(),
|
||||
Images.Subreddit.ASC(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (request ImageListRequest) SelectStatement() SelectStatement {
|
||||
func (request ImageListRequest) Statement() SelectStatement {
|
||||
cond := request.WhereExpression()
|
||||
from := Images
|
||||
|
||||
if len(request.Search) > 0 {
|
||||
cond.AND(ImagesFts5.ImagesFts5.EQ(String(request.Search)))
|
||||
from.INNER_JOIN(ImagesFts5, Images.PostName.EQ(ImagesFts5.PostName))
|
||||
stmt := SELECT(Images.AllColumns).FROM(from).WHERE(cond)
|
||||
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).FROM(from).WHERE(cond)
|
||||
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)
|
||||
}
|
||||
|
@ -132,10 +127,15 @@ func (request ImageListRequest) WhereExpression() BoolExpression {
|
|||
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 []model.Images, err error) {
|
||||
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) }()
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"slices"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/tigorlazuardi/bluemage/go/api"
|
||||
|
@ -17,6 +19,13 @@ type ImageHandler struct {
|
|||
var imageConverter = converter.ImageConverterImpl{}
|
||||
|
||||
func (im *ImageHandler) ListImages(ctx context.Context, request *connect.Request[images.ListImagesRequest]) (*connect.Response[images.ListImagesResponse], error) {
|
||||
if request.Msg.Limit < 1 {
|
||||
request.Msg.Limit = 50
|
||||
}
|
||||
if request.Msg.Limit > 1000 {
|
||||
request.Msg.Limit = 1000
|
||||
}
|
||||
|
||||
listRequest := imageConverter.ProtoListImagesRequestToAPIImagesRequest(request.Msg)
|
||||
|
||||
list, err := im.API.ImageList(ctx, listRequest)
|
||||
|
@ -24,9 +33,19 @@ func (im *ImageHandler) ListImages(ctx context.Context, request *connect.Request
|
|||
return nil, errs.IntoConnectError(err)
|
||||
}
|
||||
|
||||
_ = list
|
||||
group := jetImagesToProtoGroupedByDeviceImages(list)
|
||||
resp := &images.ListImagesResponse{
|
||||
Devices: group,
|
||||
}
|
||||
if request.Msg.After > 0 && len(group) >= int(request.Msg.Limit) {
|
||||
resp.After = &list[len(list)-1].CreatedAt
|
||||
}
|
||||
|
||||
panic("not implemented") // TODO: Implement
|
||||
if request.Msg.Before > 0 && len(group) >= int(request.Msg.Limit) {
|
||||
resp.Before = &list[0].CreatedAt
|
||||
}
|
||||
|
||||
return connect.NewResponse(resp), nil
|
||||
}
|
||||
|
||||
func (im *ImageHandler) DeleteImages(ctx context.Context, request *connect.Request[images.DeleteImagesRequest]) (*connect.Response[images.DeleteImagesResponse], error) {
|
||||
|
@ -36,3 +55,62 @@ func (im *ImageHandler) DeleteImages(ctx context.Context, request *connect.Reque
|
|||
func (im *ImageHandler) GetImage(ctx context.Context, request *connect.Request[images.GetImageRequest]) (*connect.Response[images.GetImageResponse], error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
func jetImagesToProtoGroupedByDeviceImages(jetImages []api.ImageListResponse) (out []*images.GroupedByDeviceImages) {
|
||||
if jetImages == nil {
|
||||
return nil
|
||||
}
|
||||
if len(jetImages) == 0 {
|
||||
return []*images.GroupedByDeviceImages{}
|
||||
}
|
||||
|
||||
type device struct {
|
||||
slug string
|
||||
name string
|
||||
}
|
||||
|
||||
grouped := map[device]map[string][]*images.Image{}
|
||||
|
||||
for _, jetImage := range jetImages {
|
||||
device := device{
|
||||
slug: jetImage.Device,
|
||||
name: jetImage.DeviceName,
|
||||
}
|
||||
subreddit := jetImage.Subreddit
|
||||
if grouped[device] == nil {
|
||||
grouped[device] = map[string][]*images.Image{}
|
||||
}
|
||||
|
||||
if grouped[device][subreddit] == nil {
|
||||
grouped[device][subreddit] = []*images.Image{}
|
||||
}
|
||||
|
||||
grouped[device][subreddit] = append(grouped[device][subreddit], imageConverter.JetImageToProtoImage(jetImage.Images))
|
||||
}
|
||||
|
||||
out = make([]*images.GroupedByDeviceImages, 0, len(grouped))
|
||||
|
||||
for device, subreddits := range grouped {
|
||||
group := &images.GroupedByDeviceImages{
|
||||
Slug: device.slug,
|
||||
Name: device.name,
|
||||
Subreddits: make([]*images.GroupedBySubredditImages, 0, len(subreddits)),
|
||||
}
|
||||
for subreddit, img := range subreddits {
|
||||
group.Subreddits = append(group.Subreddits, &images.GroupedBySubredditImages{
|
||||
Subreddit: subreddit,
|
||||
Images: img,
|
||||
})
|
||||
}
|
||||
slices.SortFunc(group.Subreddits, func(a, b *images.GroupedBySubredditImages) int {
|
||||
return cmp.Compare(a.Subreddit, b.Subreddit)
|
||||
})
|
||||
out = append(out, group)
|
||||
}
|
||||
|
||||
slices.SortFunc(out, func(a, b *images.GroupedByDeviceImages) int {
|
||||
return cmp.Compare(a.Name, b.Name)
|
||||
})
|
||||
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -71,6 +71,12 @@ message ListImagesRequest {
|
|||
|
||||
message ListImagesResponse {
|
||||
repeated GroupedByDeviceImages devices = 1;
|
||||
|
||||
// after is set if there are more images
|
||||
// after the last given image.
|
||||
optional int64 after = 2;
|
||||
|
||||
// before is set if there are more images
|
||||
// before the first image in the result.
|
||||
optional int64 before = 3;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue