Compare commits

...

4 commits

8 changed files with 496 additions and 309 deletions

View file

@ -146,11 +146,17 @@ paths:
summary: Get user titles
parameters:
- $ref: '#/components/parameters/cursor'
- $ref: '#/components/parameters/title_sort'
- in: path
name: user_id
required: true
schema:
type: string
- in: query
name: sort_forward
schema:
type: boolean
default: true
- in: query
name: word
schema:
@ -167,12 +173,21 @@ paths:
- in: query
name: watch_status
schema:
$ref: '#/components/schemas/UserTitleStatus'
type: array
items:
$ref: '#/components/schemas/UserTitleStatus'
style: form
explode: false
- in: query
name: rating
schema:
type: number
format: double
- in: query
name: my_rate
schema:
type: integer
format: int32
- in: query
name: release_year
schema:
@ -199,9 +214,17 @@ paths:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/UserTitle'
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/UserTitle'
cursor:
$ref: '#/components/schemas/CursorObj'
required:
- data
- cursor
'204':
description: No titles found
'400':

View file

@ -183,17 +183,20 @@ type GetUsersUserIdParams struct {
// GetUsersUserIdTitlesParams defines parameters for GetUsersUserIdTitles.
type GetUsersUserIdTitlesParams struct {
Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"`
Word *string `form:"word,omitempty" json:"word,omitempty"`
Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"`
Sort *TitleSort `form:"sort,omitempty" json:"sort,omitempty"`
SortForward *bool `form:"sort_forward,omitempty" json:"sort_forward,omitempty"`
Word *string `form:"word,omitempty" json:"word,omitempty"`
// Status List of title statuses to filter
Status *[]TitleStatus `form:"status,omitempty" json:"status,omitempty"`
WatchStatus *UserTitleStatus `form:"watch_status,omitempty" json:"watch_status,omitempty"`
Rating *float64 `form:"rating,omitempty" json:"rating,omitempty"`
ReleaseYear *int32 `form:"release_year,omitempty" json:"release_year,omitempty"`
ReleaseSeason *ReleaseSeason `form:"release_season,omitempty" json:"release_season,omitempty"`
Limit *int32 `form:"limit,omitempty" json:"limit,omitempty"`
Fields *string `form:"fields,omitempty" json:"fields,omitempty"`
Status *[]TitleStatus `form:"status,omitempty" json:"status,omitempty"`
WatchStatus *[]UserTitleStatus `form:"watch_status,omitempty" json:"watch_status,omitempty"`
Rating *float64 `form:"rating,omitempty" json:"rating,omitempty"`
MyRate *int32 `form:"my_rate,omitempty" json:"my_rate,omitempty"`
ReleaseYear *int32 `form:"release_year,omitempty" json:"release_year,omitempty"`
ReleaseSeason *ReleaseSeason `form:"release_season,omitempty" json:"release_season,omitempty"`
Limit *int32 `form:"limit,omitempty" json:"limit,omitempty"`
Fields *string `form:"fields,omitempty" json:"fields,omitempty"`
}
// Getter for additional properties for Title. Returns the specified
@ -803,6 +806,22 @@ func (siw *ServerInterfaceWrapper) GetUsersUserIdTitles(c *gin.Context) {
return
}
// ------------- Optional query parameter "sort" -------------
err = runtime.BindQueryParameter("form", true, false, "sort", c.Request.URL.Query(), &params.Sort)
if err != nil {
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter sort: %w", err), http.StatusBadRequest)
return
}
// ------------- Optional query parameter "sort_forward" -------------
err = runtime.BindQueryParameter("form", true, false, "sort_forward", c.Request.URL.Query(), &params.SortForward)
if err != nil {
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter sort_forward: %w", err), http.StatusBadRequest)
return
}
// ------------- Optional query parameter "word" -------------
err = runtime.BindQueryParameter("form", true, false, "word", c.Request.URL.Query(), &params.Word)
@ -821,7 +840,7 @@ func (siw *ServerInterfaceWrapper) GetUsersUserIdTitles(c *gin.Context) {
// ------------- Optional query parameter "watch_status" -------------
err = runtime.BindQueryParameter("form", true, false, "watch_status", c.Request.URL.Query(), &params.WatchStatus)
err = runtime.BindQueryParameter("form", false, false, "watch_status", c.Request.URL.Query(), &params.WatchStatus)
if err != nil {
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter watch_status: %w", err), http.StatusBadRequest)
return
@ -835,6 +854,14 @@ func (siw *ServerInterfaceWrapper) GetUsersUserIdTitles(c *gin.Context) {
return
}
// ------------- Optional query parameter "my_rate" -------------
err = runtime.BindQueryParameter("form", true, false, "my_rate", c.Request.URL.Query(), &params.MyRate)
if err != nil {
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter my_rate: %w", err), http.StatusBadRequest)
return
}
// ------------- Optional query parameter "release_year" -------------
err = runtime.BindQueryParameter("form", true, false, "release_year", c.Request.URL.Query(), &params.ReleaseYear)
@ -1057,7 +1084,10 @@ type GetUsersUserIdTitlesResponseObject interface {
VisitGetUsersUserIdTitlesResponse(w http.ResponseWriter) error
}
type GetUsersUserIdTitles200JSONResponse []UserTitle
type GetUsersUserIdTitles200JSONResponse struct {
Cursor CursorObj `json:"cursor"`
Data []UserTitle `json:"data"`
}
func (response GetUsersUserIdTitles200JSONResponse) VisitGetUsersUserIdTitlesResponse(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/json")

View file

@ -2,11 +2,17 @@ get:
summary: Get user titles
parameters:
- $ref: '../parameters/cursor.yaml'
- $ref: "../parameters/title_sort.yaml"
- in: path
name: user_id
required: true
schema:
type: string
- in: query
name: sort_forward
schema:
type: boolean
default: true
- in: query
name: word
schema:
@ -23,12 +29,21 @@ get:
- in: query
name: watch_status
schema:
$ref: '../schemas/enums/UserTitleStatus.yaml'
type: array
items:
$ref: '../schemas/enums/UserTitleStatus.yaml'
style: form
explode: false
- in: query
name: rating
schema:
type: number
format: double
- in: query
name: my_rate
schema:
type: integer
format: int32
- in: query
name: release_year
schema:
@ -55,9 +70,17 @@ get:
content:
application/json:
schema:
type: array
items:
$ref: '../schemas/UserTitle.yaml'
type: object
properties:
data:
type: array
items:
$ref: '../schemas/UserTitle.yaml'
cursor:
$ref: '../schemas/CursorObj.yaml'
required:
- data
- cursor
'204':
description: No titles found
'400':

View file

@ -17,7 +17,24 @@ func NewServer(db *sqlc.Queries) Server {
return Server{db: db}
}
func (s Server) mapTitle(ctx context.Context, title sqlc.SearchTitlesRow) (oapi.Title, error) {
func (s Server) mapTitle(ctx context.Context, title sqlc.GetTitleByIDRow) (oapi.Title, error) {
oapi_title := oapi.Title{
EpisodesAired: title.EpisodesAired,
EpisodesAll: title.EpisodesAired,
// EpisodesLen: &episodes_lens,
Id: title.ID,
// Poster: &oapi_image,
Rating: title.Rating,
RatingCount: title.RatingCount,
// ReleaseSeason: &release_season,
ReleaseYear: title.ReleaseYear,
// Studio: &oapi_studio,
// Tags: oapi_tag_names,
// TitleNames: title_names,
// TitleStatus: oapi_status,
// AdditionalProperties:
}
title_names := make(map[string][]string, 0)
err := json.Unmarshal(title.TitleNames, &title_names)
@ -25,10 +42,13 @@ func (s Server) mapTitle(ctx context.Context, title sqlc.SearchTitlesRow) (oapi.
return oapi.Title{}, fmt.Errorf("unmarshal TitleNames: %v", err)
}
episodes_lens := make(map[string]float64, 0)
err = json.Unmarshal(title.EpisodesLen, &episodes_lens)
if err != nil {
return oapi.Title{}, fmt.Errorf("unmarshal EpisodesLen: %v", err)
if len(title.EpisodesLen) > 0 {
episodes_lens := make(map[string]float64, 0)
err = json.Unmarshal(title.EpisodesLen, &episodes_lens)
if err != nil {
return oapi.Title{}, fmt.Errorf("unmarshal EpisodesLen: %v", err)
}
oapi_title.EpisodesLen = &episodes_lens
}
oapi_tag_names := make(oapi.Tags, 0)
@ -38,17 +58,20 @@ func (s Server) mapTitle(ctx context.Context, title sqlc.SearchTitlesRow) (oapi.
}
var oapi_studio oapi.Studio
oapi_studio.Id = title.StudioID
if title.StudioName != nil {
oapi_studio.Name = *title.StudioName
}
oapi_studio.Description = title.StudioDesc
if title.StudioIllustID != nil {
oapi_studio.Poster.Id = title.StudioIllustID
oapi_studio.Poster.ImagePath = title.StudioImagePath
oapi_studio.Poster.StorageType = &title.StudioStorageType
if title.StudioID != 0 {
oapi_studio.Id = title.StudioID
oapi_studio.Description = title.StudioDesc
if title.StudioIllustID != nil {
oapi_studio.Poster = &oapi.Image{}
oapi_studio.Poster.Id = title.StudioIllustID
oapi_studio.Poster.ImagePath = title.StudioImagePath
oapi_studio.Poster.StorageType = &title.StudioStorageType
}
}
oapi_title.Studio = &oapi_studio
var oapi_image oapi.Image
@ -62,27 +85,13 @@ func (s Server) mapTitle(ctx context.Context, title sqlc.SearchTitlesRow) (oapi.
if title.ReleaseSeason != nil {
release_season = oapi.ReleaseSeason(*title.ReleaseSeason)
}
oapi_title.ReleaseSeason = &release_season
oapi_status, err := TitleStatus2oapi(&title.TitleStatus)
if err != nil {
return oapi.Title{}, fmt.Errorf("TitleStatus2oapi: %v", err)
}
oapi_title := oapi.Title{
EpisodesAired: title.EpisodesAired,
EpisodesAll: title.EpisodesAired,
EpisodesLen: &episodes_lens,
Id: title.ID,
Poster: &oapi_image,
Rating: title.Rating,
RatingCount: title.RatingCount,
ReleaseSeason: &release_season,
ReleaseYear: title.ReleaseYear,
Studio: &oapi_studio,
Tags: oapi_tag_names,
TitleNames: title_names,
TitleStatus: oapi_status,
// AdditionalProperties:
}
oapi_title.TitleStatus = oapi_status
return oapi_title, nil
}
@ -91,3 +100,23 @@ func parseInt64(s string) (int32, error) {
i, err := strconv.ParseInt(s, 10, 64)
return int32(i), err
}
func TitleStatus2Sqlc(s *[]oapi.TitleStatus) ([]sqlc.TitleStatusT, error) {
var sqlc_status []sqlc.TitleStatusT
if s == nil {
return nil, nil
}
for _, t := range *s {
switch t {
case oapi.TitleStatusFinished:
sqlc_status = append(sqlc_status, sqlc.TitleStatusTFinished)
case oapi.TitleStatusOngoing:
sqlc_status = append(sqlc_status, sqlc.TitleStatusTOngoing)
case oapi.TitleStatusPlanned:
sqlc_status = append(sqlc_status, sqlc.TitleStatusTPlanned)
default:
return nil, fmt.Errorf("unexpected tittle status: %s", t)
}
}
return sqlc_status, nil
}

View file

@ -20,32 +20,6 @@ func Word2Sqlc(s *string) *string {
return s
}
type SqlcStatus struct {
ongoing string
finished string
planned string
}
func TitleStatus2Sqlc(s *[]oapi.TitleStatus) (*SqlcStatus, error) {
var sqlc_status SqlcStatus
if s == nil {
return &sqlc_status, nil
}
for _, t := range *s {
switch t {
case oapi.TitleStatusFinished:
sqlc_status.finished = "finished"
case oapi.TitleStatusOngoing:
sqlc_status.ongoing = "ongoing"
case oapi.TitleStatusPlanned:
sqlc_status.planned = "planned"
default:
return nil, fmt.Errorf("unexpected tittle status: %s", t)
}
}
return &sqlc_status, nil
}
func TitleStatus2oapi(s *sqlc.TitleStatusT) (*oapi.TitleStatus, error) {
if s == nil {
return nil, nil
@ -169,29 +143,8 @@ func (s Server) GetTitlesTitleId(ctx context.Context, request oapi.GetTitlesTitl
log.Errorf("%v", err)
return oapi.GetTitlesTitleId500Response{}, nil
}
_sqlc_title := sqlc.SearchTitlesRow{
ID: sqlc_title.ID,
StudioID: sqlc_title.StudioID,
PosterID: sqlc_title.PosterID,
TitleStatus: sqlc_title.TitleStatus,
Rating: sqlc_title.Rating,
RatingCount: sqlc_title.RatingCount,
ReleaseYear: sqlc_title.ReleaseYear,
ReleaseSeason: sqlc_title.ReleaseSeason,
Season: sqlc_title.Season,
EpisodesAired: sqlc_title.EpisodesAired,
EpisodesAll: sqlc_title.EpisodesAll,
EpisodesLen: sqlc_title.EpisodesLen,
TitleStorageType: sqlc_title.TitleStorageType,
TitleImagePath: sqlc_title.TitleImagePath,
TagNames: sqlc_title.TitleNames,
StudioName: sqlc_title.StudioName,
StudioIllustID: sqlc_title.StudioIllustID,
StudioDesc: sqlc_title.StudioDesc,
StudioStorageType: sqlc_title.StudioStorageType,
StudioImagePath: sqlc_title.StudioImagePath,
}
oapi_title, err = s.mapTitle(ctx, _sqlc_title)
oapi_title, err = s.mapTitle(ctx, sqlc_title)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitlesTitleId500Response{}, nil
@ -204,11 +157,6 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje
opai_titles := make([]oapi.Title, 0)
word := Word2Sqlc(request.Params.Word)
status, err := TitleStatus2Sqlc(request.Params.Status)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitles400Response{}, err
}
season, err := ReleaseSeason2sqlc(request.Params.ReleaseSeason)
if err != nil {
@ -216,16 +164,20 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje
return oapi.GetTitles400Response{}, err
}
title_statuses, err := TitleStatus2Sqlc(request.Params.Status)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitles400Response{}, err
}
params := sqlc.SearchTitlesParams{
Word: word,
Ongoing: status.ongoing,
Finished: status.finished,
Planned: status.planned,
TitleStatuses: title_statuses,
Rating: request.Params.Rating,
ReleaseYear: request.Params.ReleaseYear,
ReleaseSeason: season,
Forward: true,
SortBy: "id",
Forward: true, // default
SortBy: "id", // default
Limit: request.Params.Limit,
}
@ -235,6 +187,7 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje
if request.Params.Sort != nil {
params.SortBy = string(*request.Params.Sort)
if request.Params.Cursor != nil {
// here we set CursorYear CursorID CursorRating fields
err := ParseCursorInto(string(*request.Params.Sort), string(*request.Params.Cursor), &params)
if err != nil {
log.Errorf("%v", err)
@ -256,7 +209,30 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje
for _, title := range titles {
t, err := s.mapTitle(ctx, title)
_title := sqlc.GetTitleByIDRow{
ID: title.ID,
// StudioID: title.StudioID,
PosterID: title.PosterID,
TitleStatus: title.TitleStatus,
Rating: title.Rating,
RatingCount: title.RatingCount,
ReleaseYear: title.ReleaseYear,
ReleaseSeason: title.ReleaseSeason,
Season: title.Season,
EpisodesAired: title.EpisodesAired,
EpisodesAll: title.EpisodesAll,
// EpisodesLen: title.EpisodesLen,
TitleStorageType: title.TitleStorageType,
TitleImagePath: title.TitleImagePath,
TagNames: title.TitleNames,
StudioName: title.StudioName,
// StudioIllustID: title.StudioIllustID,
// StudioDesc: title.StudioDesc,
// StudioStorageType: title.StudioStorageType,
// StudioImagePath: title.StudioImagePath,
}
t, err := s.mapTitle(ctx, _title)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitles500Response{}, nil

View file

@ -5,6 +5,7 @@ import (
"fmt"
oapi "nyanimedb/api"
sqlc "nyanimedb/sql"
"strconv"
"time"
"github.com/jackc/pgx/v5"
@ -53,37 +54,124 @@ func (s Server) GetUsersUserId(ctx context.Context, req oapi.GetUsersUserIdReque
return oapi.GetUsersUserId200JSONResponse(mapUser(user)), nil
}
func sqlDate2oapi(p_date pgtype.Timestamptz) (time.Time, error) {
return time.Time{}, nil
func sqlDate2oapi(p_date pgtype.Timestamptz) *time.Time {
if p_date.Valid {
t := p_date.Time
return &t
}
return nil
}
type SqlcUserStatus struct {
dropped string
finished string
planned string
in_progress string
// func UserTitleStatus2Sqlc(s *[]oapi.UserTitleStatus) (*SqlcUserStatus, error) {
// var sqlc_status SqlcUserStatus
// if s == nil {
// return &sqlc_status, nil
// }
// for _, t := range *s {
// switch t {
// case oapi.UserTitleStatusFinished:
// sqlc_status.finished = "finished"
// case oapi.UserTitleStatusDropped:
// sqlc_status.dropped = "dropped"
// case oapi.UserTitleStatusPlanned:
// sqlc_status.planned = "planned"
// case oapi.UserTitleStatusInProgress:
// sqlc_status.in_progress = "in-progress"
// default:
// return nil, fmt.Errorf("unexpected tittle status: %s", t)
// }
// }
// return &sqlc_status, nil
// }
func sql2usertitlestatus(s sqlc.UsertitleStatusT) (oapi.UserTitleStatus, error) {
var status oapi.UserTitleStatus
switch status {
case "finished":
status = oapi.UserTitleStatusFinished
case "dropped":
status = oapi.UserTitleStatusDropped
case "planned":
status = oapi.UserTitleStatusPlanned
case "in-progress":
status = oapi.UserTitleStatusInProgress
default:
return status, fmt.Errorf("unexpected tittle status: %s", s)
}
return status, nil
}
func UserTitleStatus2Sqlc(s *[]oapi.UserTitleStatus) (*SqlcUserStatus, error) {
var sqlc_status SqlcUserStatus
func UserTitleStatus2Sqlc(s *[]oapi.UserTitleStatus) ([]sqlc.UsertitleStatusT, error) {
var sqlc_status []sqlc.UsertitleStatusT
if s == nil {
return &sqlc_status, nil
return nil, nil
}
for _, t := range *s {
switch t {
case oapi.UserTitleStatusFinished:
sqlc_status.finished = "finished"
case oapi.UserTitleStatusDropped:
sqlc_status.dropped = "dropped"
case oapi.UserTitleStatusPlanned:
sqlc_status.planned = "planned"
sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTFinished)
case oapi.UserTitleStatusInProgress:
sqlc_status.in_progress = "in-progress"
sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTInProgress)
case oapi.UserTitleStatusDropped:
sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTDropped)
case oapi.UserTitleStatusPlanned:
sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTPlanned)
default:
return nil, fmt.Errorf("unexpected tittle status: %s", t)
}
}
return &sqlc_status, nil
return sqlc_status, nil
}
func (s Server) mapUsertitle(ctx context.Context, t sqlc.SearchUserTitlesRow) (oapi.UserTitle, error) {
oapi_usertitle := oapi.UserTitle{
Ctime: sqlDate2oapi(t.UserCtime),
Rate: t.UserRate,
ReviewId: t.ReviewID,
// Status: ,
// Title: ,
UserId: t.UserID,
}
status, err := sql2usertitlestatus(t.UsertitleStatus)
if err != nil {
return oapi_usertitle, fmt.Errorf("mapUsertitle: %v", err)
}
oapi_usertitle.Status = status
_title := sqlc.GetTitleByIDRow{
ID: t.ID,
// StudioID: title.StudioID,
PosterID: t.PosterID,
TitleStatus: t.TitleStatus,
Rating: t.Rating,
RatingCount: t.RatingCount,
ReleaseYear: t.ReleaseYear,
ReleaseSeason: t.ReleaseSeason,
Season: t.Season,
EpisodesAired: t.EpisodesAired,
EpisodesAll: t.EpisodesAll,
// EpisodesLen: title.EpisodesLen,
TitleStorageType: t.TitleStorageType,
TitleImagePath: t.TitleImagePath,
TagNames: t.TitleNames,
StudioName: t.StudioName,
// StudioIllustID: title.StudioIllustID,
// StudioDesc: title.StudioDesc,
// StudioStorageType: title.StudioStorageType,
// StudioImagePath: title.StudioImagePath,
}
oapi_title, err := s.mapTitle(ctx, _title)
if err != nil {
return oapi_usertitle, fmt.Errorf("mapUsertitle: %v", err)
}
oapi_usertitle.Title = &oapi_title
return oapi_usertitle, nil
}
func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersUserIdTitlesRequestObject) (oapi.GetUsersUserIdTitlesResponseObject, error) {
@ -91,11 +179,6 @@ func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersU
oapi_usertitles := make([]oapi.UserTitle, 0)
word := Word2Sqlc(request.Params.Word)
status, err := TitleStatus2Sqlc(request.Params.Status)
if err != nil {
log.Errorf("%v", err)
return oapi.GetUsersUserIdTitles400Response{}, err
}
season, err := ReleaseSeason2sqlc(request.Params.ReleaseSeason)
if err != nil {
@ -103,23 +186,37 @@ func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersU
return oapi.GetUsersUserIdTitles400Response{}, err
}
// var statuses_sort []string
// if request.Params.Status != nil {
// for _, s := range *request.Params.Status {
// ss := string(s) // s type is alias for string
// statuses_sort = append(statuses_sort, ss)
// }
// }
watch_status, err := UserTitleStatus2Sqlc(request.Params.WatchStatus)
if err != nil {
log.Errorf("%v", err)
return oapi.GetUsersUserIdTitles400Response{}, err
}
title_statuses, err := TitleStatus2Sqlc(request.Params.Status)
if err != nil {
log.Errorf("%v", err)
return oapi.GetUsersUserIdTitles400Response{}, err
}
params := sqlc.SearchUserTitlesParams{
Forward: true,
SortBy: "id",
// CursorYear :
// CursorID *int64 `json:"cursor_id"`
// CursorRating *float64 `json:"cursor_rating"`
// Word *string `json:"word"`
// Ongoing string `json:"ongoing"`
// Planned string `json:"planned"`
// Dropped string `json:"dropped"`
// InProgress string `json:"in-progress"`
// Finished string `json:"finished"`
// Rate *int32 `json:"rate"`
// Rating *float64 `json:"rating"`
// ReleaseYear *int32 `json:"release_year"`
// ReleaseSeason *ReleaseSeasonT `json:"release_season"`
// Limit *int32 `json:"limit"`
Word: word,
TitleStatuses: title_statuses,
UsertitleStatuses: watch_status,
Rating: request.Params.Rating,
Rate: request.Params.MyRate,
ReleaseYear: request.Params.ReleaseYear,
ReleaseSeason: season,
Forward: true, // default
SortBy: "id", // default
Limit: request.Params.Limit,
}
if request.Params.SortForward != nil {
@ -128,6 +225,7 @@ func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersU
if request.Params.Sort != nil {
params.SortBy = string(*request.Params.Sort)
if request.Params.Cursor != nil {
// here we set CursorYear CursorID CursorRating fields
err := ParseCursorInto(string(*request.Params.Sort), string(*request.Params.Cursor), &params)
if err != nil {
log.Errorf("%v", err)
@ -144,30 +242,30 @@ func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersU
if len(titles) == 0 {
return oapi.GetUsersUserIdTitles204Response{}, nil
}
var new_cursor oapi.CursorObj
for _, title := range titles {
_sqlc_title := sqlc.SearchTitlesRow{
ID: sqlc_title.ID,
StudioID: sqlc_title.StudioID,
PosterID: sqlc_title.PosterID,
TitleStatus: sqlc_title.TitleStatus,
Rating: sqlc_title.Rating,
RatingCount: sqlc_title.RatingCount,
ReleaseYear: sqlc_title.ReleaseYear,
ReleaseSeason: sqlc_title.ReleaseSeason,
Season: sqlc_title.Season,
EpisodesAired: sqlc_title.EpisodesAired,
EpisodesAll: sqlc_title.EpisodesAll,
EpisodesLen: sqlc_title.EpisodesLen,
TitleStorageType: sqlc_title.TitleStorageType,
TitleImagePath: sqlc_title.TitleImagePath,
TagNames: sqlc_title.TitleNames,
StudioName: sqlc_title.StudioName,
StudioIllustID: sqlc_title.StudioIllustID,
StudioDesc: sqlc_title.StudioDesc,
StudioStorageType: sqlc_title.StudioStorageType,
StudioImagePath: sqlc_title.StudioImagePath,
t, err := s.mapUsertitle(ctx, title)
if err != nil {
log.Errorf("%v", err)
return oapi.GetUsersUserIdTitles500Response{}, nil
}
oapi_usertitles = append(oapi_usertitles, t)
new_cursor.Id = t.Title.Id
if request.Params.Sort != nil {
switch string(*request.Params.Sort) {
case "year":
tmp := fmt.Sprint(*t.Title.ReleaseYear)
new_cursor.Param = &tmp
case "rating":
tmp := strconv.FormatFloat(*t.Title.Rating, 'f', -1, 64)
new_cursor.Param = &tmp
}
}
}
return oapi.GetUsersUserIdTitles200JSONResponse(userTitles), nil
return oapi.GetUsersUserIdTitles200JSONResponse{Cursor: new_cursor, Data: oapi_usertitles}, nil
}

View file

@ -101,25 +101,30 @@ GROUP BY
-- name: SearchTitles :many
SELECT
t.*,
t.id as id,
t.title_names as title_names,
t.poster_id as poster_id,
t.title_status as title_status,
t.rating as rating,
t.rating_count as rating_count,
t.release_year as release_year,
t.release_season as release_season,
t.season as season,
t.episodes_aired as episodes_aired,
t.episodes_all as episodes_all,
i.storage_type::text as title_storage_type,
i.image_path as title_image_path,
COALESCE(
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
'[]'::jsonb
)::jsonb as tag_names,
s.studio_name as studio_name,
s.illust_id as studio_illust_id,
s.studio_desc as studio_desc,
si.storage_type::text as studio_storage_type,
si.image_path as studio_image_path
s.studio_name as studio_name
FROM titles as t
LEFT JOIN images as i ON (t.poster_id = i.id)
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
LEFT JOIN tags as g ON (tt.tag_id = g.id)
LEFT JOIN studios as s ON (t.studio_id = s.id)
LEFT JOIN images as si ON (s.illust_id = si.id)
WHERE
CASE
@ -188,18 +193,17 @@ WHERE
)
AND (
-- Если массив пуст (NULL или []) — не фильтруем
cardinality(sqlc.arg('title_statuses')::text[]) = 0
OR
-- Иначе: статус есть в списке
t.title_status = ANY(sqlc.arg('title_statuses')::text[])
)
'title_statuses'::title_status_t[] IS NULL
OR array_length('title_statuses'::title_status_t[], 1) IS NULL
OR array_length('title_statuses'::title_status_t[], 1) = 0
OR t.title_status = ANY('title_statuses'::title_status_t[])
)
AND (sqlc.narg('rating')::float IS NULL OR t.rating >= sqlc.narg('rating')::float)
AND (sqlc.narg('release_year')::int IS NULL OR t.release_year = sqlc.narg('release_year')::int)
AND (sqlc.narg('release_season')::release_season_t IS NULL OR t.release_season = sqlc.narg('release_season')::release_season_t)
GROUP BY
t.id, i.id, s.id, si.id
t.id, i.id, s.id
ORDER BY
CASE WHEN sqlc.arg('forward')::boolean THEN
@ -223,7 +227,17 @@ LIMIT COALESCE(sqlc.narg('limit')::int, 100); -- 100 is default limit
-- name: SearchUserTitles :many
SELECT
t.*,
t.id as id,
t.title_names as title_names,
t.poster_id as poster_id,
t.title_status as title_status,
t.rating as rating,
t.rating_count as rating_count,
t.release_year as release_year,
t.release_season as release_season,
t.season as season,
t.episodes_aired as episodes_aired,
t.episodes_all as episodes_all,
u.user_id as user_id,
u.status as usertitle_status,
u.rate as user_rate,
@ -231,20 +245,18 @@ SELECT
u.ctime as user_ctime,
i.storage_type::text as title_storage_type,
i.image_path as title_image_path,
jsonb_agg(g.tag_name)'[]'::jsonb as tag_names,
s.studio_name as studio_name,
s.illust_id as studio_illust_id,
s.studio_desc as studio_desc,
si.storage_type::text as studio_storage_type,
si.image_path as studio_image_path
COALESCE(
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
'[]'::jsonb
)::jsonb as tag_names,
s.studio_name as studio_name
FROM usertitles as u
LEFT JOIN titles as t ON (u.title_id = t.id)
LEFT JOIN images as i ON (t.poster_id = i.id)
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
LEFT JOIN tags as g ON (tt.tag_id = g.id)
LEFT JOIN studios as s ON (t.studio_id = s.id)
LEFT JOIN images as si ON (s.illust_id = si.id)
FROM usertitles as u
JOIN titles as t ON (u.title_id = t.id)
LEFT JOIN images as i ON (t.poster_id = i.id)
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
LEFT JOIN tags as g ON (tt.tag_id = g.id)
LEFT JOIN studios as s ON (t.studio_id = s.id)
WHERE
CASE
@ -312,15 +324,25 @@ WHERE
END
)
AND (u.status::text IN (sqlc.arg('ongoing')::text, sqlc.arg('planned')::text, sqlc.arg('dropped')::text, sqlc.arg('in-progress')::text))
AND (t.title_status::text IN (sqlc.arg('ongoing')::text, sqlc.arg('finished')::text, sqlc.arg('planned')::text))
AND (
'title_statuses'::title_status_t[] IS NULL
OR array_length('title_statuses'::title_status_t[], 1) IS NULL
OR array_length('title_statuses'::title_status_t[], 1) = 0
OR t.title_status = ANY('title_statuses'::title_status_t[])
)
AND (
'usertitle_statuses'::title_status_t[] IS NULL
OR array_length('usertitle_statuses'::title_status_t[], 1) IS NULL
OR array_length('usertitle_statuses'::title_status_t[], 1) = 0
OR t.title_status = ANY('usertitle_statuses'::title_status_t[])
)
AND (sqlc.narg('rate')::int IS NULL OR u.rate >= sqlc.narg('rate')::int)
AND (sqlc.narg('rating')::float IS NULL OR t.rating >= sqlc.narg('rating')::float)
AND (sqlc.narg('release_year')::int IS NULL OR t.release_year = sqlc.narg('release_year')::int)
AND (sqlc.narg('release_season')::release_season_t IS NULL OR t.release_season = sqlc.narg('release_season')::release_season_t)
GROUP BY
t.id, i.id, s.id, si.id
t.id, i.id, s.id
ORDER BY
CASE WHEN sqlc.arg('forward')::boolean THEN

View file

@ -342,25 +342,30 @@ func (q *Queries) InsertTitleTags(ctx context.Context, arg InsertTitleTagsParams
const searchTitles = `-- name: SearchTitles :many
SELECT
t.id, t.title_names, t.studio_id, t.poster_id, t.title_status, t.rating, t.rating_count, t.release_year, t.release_season, t.season, t.episodes_aired, t.episodes_all, t.episodes_len,
t.id as id,
t.title_names as title_names,
t.poster_id as poster_id,
t.title_status as title_status,
t.rating as rating,
t.rating_count as rating_count,
t.release_year as release_year,
t.release_season as release_season,
t.season as season,
t.episodes_aired as episodes_aired,
t.episodes_all as episodes_all,
i.storage_type::text as title_storage_type,
i.image_path as title_image_path,
COALESCE(
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
'[]'::jsonb
)::jsonb as tag_names,
s.studio_name as studio_name,
s.illust_id as studio_illust_id,
s.studio_desc as studio_desc,
si.storage_type::text as studio_storage_type,
si.image_path as studio_image_path
s.studio_name as studio_name
FROM titles as t
LEFT JOIN images as i ON (t.poster_id = i.id)
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
LEFT JOIN tags as g ON (tt.tag_id = g.id)
LEFT JOIN studios as s ON (t.studio_id = s.id)
LEFT JOIN images as si ON (s.illust_id = si.id)
WHERE
CASE
@ -429,18 +434,17 @@ WHERE
)
AND (
-- Если массив пуст (NULL или []) не фильтруем
cardinality($7::text[]) = 0
OR
-- Иначе: статус есть в списке
t.title_status = ANY($7::text[])
)
AND ($8::float IS NULL OR t.rating >= $8::float)
AND ($9::int IS NULL OR t.release_year = $9::int)
AND ($10::release_season_t IS NULL OR t.release_season = $10::release_season_t)
'title_statuses'::title_status_t[] IS NULL
OR array_length('title_statuses'::title_status_t[], 1) IS NULL
OR array_length('title_statuses'::title_status_t[], 1) = 0
OR t.title_status = ANY('title_statuses'::title_status_t[])
)
AND ($7::float IS NULL OR t.rating >= $7::float)
AND ($8::int IS NULL OR t.release_year = $8::int)
AND ($9::release_season_t IS NULL OR t.release_season = $9::release_season_t)
GROUP BY
t.id, i.id, s.id, si.id
t.id, i.id, s.id
ORDER BY
CASE WHEN $1::boolean THEN
@ -460,7 +464,7 @@ ORDER BY
CASE WHEN $2::text <> 'id' THEN t.id END ASC
LIMIT COALESCE($11::int, 100)
LIMIT COALESCE($10::int, 100)
`
type SearchTitlesParams struct {
@ -470,7 +474,6 @@ type SearchTitlesParams struct {
CursorID *int64 `json:"cursor_id"`
CursorRating *float64 `json:"cursor_rating"`
Word *string `json:"word"`
TitleStatuses []string `json:"title_statuses"`
Rating *float64 `json:"rating"`
ReleaseYear *int32 `json:"release_year"`
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
@ -478,27 +481,21 @@ type SearchTitlesParams struct {
}
type SearchTitlesRow struct {
ID int64 `json:"id"`
TitleNames json.RawMessage `json:"title_names"`
StudioID int64 `json:"studio_id"`
PosterID *int64 `json:"poster_id"`
TitleStatus TitleStatusT `json:"title_status"`
Rating *float64 `json:"rating"`
RatingCount *int32 `json:"rating_count"`
ReleaseYear *int32 `json:"release_year"`
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
Season *int32 `json:"season"`
EpisodesAired *int32 `json:"episodes_aired"`
EpisodesAll *int32 `json:"episodes_all"`
EpisodesLen []byte `json:"episodes_len"`
TitleStorageType string `json:"title_storage_type"`
TitleImagePath *string `json:"title_image_path"`
TagNames json.RawMessage `json:"tag_names"`
StudioName *string `json:"studio_name"`
StudioIllustID *int64 `json:"studio_illust_id"`
StudioDesc *string `json:"studio_desc"`
StudioStorageType string `json:"studio_storage_type"`
StudioImagePath *string `json:"studio_image_path"`
ID int64 `json:"id"`
TitleNames json.RawMessage `json:"title_names"`
PosterID *int64 `json:"poster_id"`
TitleStatus TitleStatusT `json:"title_status"`
Rating *float64 `json:"rating"`
RatingCount *int32 `json:"rating_count"`
ReleaseYear *int32 `json:"release_year"`
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
Season *int32 `json:"season"`
EpisodesAired *int32 `json:"episodes_aired"`
EpisodesAll *int32 `json:"episodes_all"`
TitleStorageType string `json:"title_storage_type"`
TitleImagePath *string `json:"title_image_path"`
TagNames json.RawMessage `json:"tag_names"`
StudioName *string `json:"studio_name"`
}
func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]SearchTitlesRow, error) {
@ -509,7 +506,6 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S
arg.CursorID,
arg.CursorRating,
arg.Word,
arg.TitleStatuses,
arg.Rating,
arg.ReleaseYear,
arg.ReleaseSeason,
@ -525,7 +521,6 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S
if err := rows.Scan(
&i.ID,
&i.TitleNames,
&i.StudioID,
&i.PosterID,
&i.TitleStatus,
&i.Rating,
@ -535,15 +530,10 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S
&i.Season,
&i.EpisodesAired,
&i.EpisodesAll,
&i.EpisodesLen,
&i.TitleStorageType,
&i.TitleImagePath,
&i.TagNames,
&i.StudioName,
&i.StudioIllustID,
&i.StudioDesc,
&i.StudioStorageType,
&i.StudioImagePath,
); err != nil {
return nil, err
}
@ -558,7 +548,17 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S
const searchUserTitles = `-- name: SearchUserTitles :many
SELECT
t.id, t.title_names, t.studio_id, t.poster_id, t.title_status, t.rating, t.rating_count, t.release_year, t.release_season, t.season, t.episodes_aired, t.episodes_all, t.episodes_len,
t.id as id,
t.title_names as title_names,
t.poster_id as poster_id,
t.title_status as title_status,
t.rating as rating,
t.rating_count as rating_count,
t.release_year as release_year,
t.release_season as release_season,
t.season as season,
t.episodes_aired as episodes_aired,
t.episodes_all as episodes_all,
u.user_id as user_id,
u.status as usertitle_status,
u.rate as user_rate,
@ -566,20 +566,18 @@ SELECT
u.ctime as user_ctime,
i.storage_type::text as title_storage_type,
i.image_path as title_image_path,
jsonb_agg(g.tag_name)'[]'::jsonb as tag_names,
s.studio_name as studio_name,
s.illust_id as studio_illust_id,
s.studio_desc as studio_desc,
si.storage_type::text as studio_storage_type,
si.image_path as studio_image_path
COALESCE(
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
'[]'::jsonb
)::jsonb as tag_names,
s.studio_name as studio_name
FROM usertitles as u
LEFT JOIN titles as t ON (u.title_id = t.id)
LEFT JOIN images as i ON (t.poster_id = i.id)
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
LEFT JOIN tags as g ON (tt.tag_id = g.id)
LEFT JOIN studios as s ON (t.studio_id = s.id)
LEFT JOIN images as si ON (s.illust_id = si.id)
FROM usertitles as u
JOIN titles as t ON (u.title_id = t.id)
LEFT JOIN images as i ON (t.poster_id = i.id)
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
LEFT JOIN tags as g ON (tt.tag_id = g.id)
LEFT JOIN studios as s ON (t.studio_id = s.id)
WHERE
CASE
@ -647,15 +645,25 @@ WHERE
END
)
AND (u.status::text IN ($7::text, $8::text, $9::text, $10::text))
AND (t.title_status::text IN ($7::text, $11::text, $8::text))
AND ($12::int IS NULL OR u.rate >= $12::int)
AND ($13::float IS NULL OR t.rating >= $13::float)
AND ($14::int IS NULL OR t.release_year = $14::int)
AND ($15::release_season_t IS NULL OR t.release_season = $15::release_season_t)
AND (
'title_statuses'::title_status_t[] IS NULL
OR array_length('title_statuses'::title_status_t[], 1) IS NULL
OR array_length('title_statuses'::title_status_t[], 1) = 0
OR t.title_status = ANY('title_statuses'::title_status_t[])
)
AND (
'usertitle_statuses'::title_status_t[] IS NULL
OR array_length('usertitle_statuses'::title_status_t[], 1) IS NULL
OR array_length('usertitle_statuses'::title_status_t[], 1) = 0
OR t.title_status = ANY('usertitle_statuses'::title_status_t[])
)
AND ($7::int IS NULL OR u.rate >= $7::int)
AND ($8::float IS NULL OR t.rating >= $8::float)
AND ($9::int IS NULL OR t.release_year = $9::int)
AND ($10::release_season_t IS NULL OR t.release_season = $10::release_season_t)
GROUP BY
t.id, i.id, s.id, si.id
t.id, i.id, s.id
ORDER BY
CASE WHEN $1::boolean THEN
@ -677,7 +685,7 @@ ORDER BY
CASE WHEN $2::text <> 'id' THEN t.id END ASC
LIMIT COALESCE($16::int, 100)
LIMIT COALESCE($11::int, 100)
`
type SearchUserTitlesParams struct {
@ -687,11 +695,6 @@ type SearchUserTitlesParams struct {
CursorID *int64 `json:"cursor_id"`
CursorRating *float64 `json:"cursor_rating"`
Word *string `json:"word"`
Ongoing string `json:"ongoing"`
Planned string `json:"planned"`
Dropped string `json:"dropped"`
InProgress string `json:"in-progress"`
Finished string `json:"finished"`
Rate *int32 `json:"rate"`
Rating *float64 `json:"rating"`
ReleaseYear *int32 `json:"release_year"`
@ -700,32 +703,26 @@ type SearchUserTitlesParams struct {
}
type SearchUserTitlesRow struct {
ID *int64 `json:"id"`
TitleNames []byte `json:"title_names"`
StudioID *int64 `json:"studio_id"`
PosterID *int64 `json:"poster_id"`
TitleStatus *TitleStatusT `json:"title_status"`
Rating *float64 `json:"rating"`
RatingCount *int32 `json:"rating_count"`
ReleaseYear *int32 `json:"release_year"`
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
Season *int32 `json:"season"`
EpisodesAired *int32 `json:"episodes_aired"`
EpisodesAll *int32 `json:"episodes_all"`
EpisodesLen []byte `json:"episodes_len"`
UserID int64 `json:"user_id"`
UsertitleStatus UsertitleStatusT `json:"usertitle_status"`
UserRate *int32 `json:"user_rate"`
ReviewID *int64 `json:"review_id"`
UserCtime pgtype.Timestamptz `json:"user_ctime"`
TitleStorageType string `json:"title_storage_type"`
TitleImagePath *string `json:"title_image_path"`
TagNames json.RawMessage `json:"tag_names"`
StudioName *string `json:"studio_name"`
StudioIllustID *int64 `json:"studio_illust_id"`
StudioDesc *string `json:"studio_desc"`
StudioStorageType string `json:"studio_storage_type"`
StudioImagePath *string `json:"studio_image_path"`
ID int64 `json:"id"`
TitleNames json.RawMessage `json:"title_names"`
PosterID *int64 `json:"poster_id"`
TitleStatus TitleStatusT `json:"title_status"`
Rating *float64 `json:"rating"`
RatingCount *int32 `json:"rating_count"`
ReleaseYear *int32 `json:"release_year"`
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
Season *int32 `json:"season"`
EpisodesAired *int32 `json:"episodes_aired"`
EpisodesAll *int32 `json:"episodes_all"`
UserID int64 `json:"user_id"`
UsertitleStatus UsertitleStatusT `json:"usertitle_status"`
UserRate *int32 `json:"user_rate"`
ReviewID *int64 `json:"review_id"`
UserCtime pgtype.Timestamptz `json:"user_ctime"`
TitleStorageType string `json:"title_storage_type"`
TitleImagePath *string `json:"title_image_path"`
TagNames json.RawMessage `json:"tag_names"`
StudioName *string `json:"studio_name"`
}
// 100 is default limit
@ -737,11 +734,6 @@ func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesPara
arg.CursorID,
arg.CursorRating,
arg.Word,
arg.Ongoing,
arg.Planned,
arg.Dropped,
arg.InProgress,
arg.Finished,
arg.Rate,
arg.Rating,
arg.ReleaseYear,
@ -758,7 +750,6 @@ func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesPara
if err := rows.Scan(
&i.ID,
&i.TitleNames,
&i.StudioID,
&i.PosterID,
&i.TitleStatus,
&i.Rating,
@ -768,7 +759,6 @@ func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesPara
&i.Season,
&i.EpisodesAired,
&i.EpisodesAll,
&i.EpisodesLen,
&i.UserID,
&i.UsertitleStatus,
&i.UserRate,
@ -778,10 +768,6 @@ func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesPara
&i.TitleImagePath,
&i.TagNames,
&i.StudioName,
&i.StudioIllustID,
&i.StudioDesc,
&i.StudioStorageType,
&i.StudioImagePath,
); err != nil {
return nil, err
}