diff --git a/api/_build/openapi.yaml b/api/_build/openapi.yaml index 215eabc..722b7af 100644 --- a/api/_build/openapi.yaml +++ b/api/_build/openapi.yaml @@ -146,17 +146,11 @@ 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: @@ -173,21 +167,12 @@ paths: - in: query name: watch_status schema: - type: array - items: - $ref: '#/components/schemas/UserTitleStatus' - style: form - explode: false + $ref: '#/components/schemas/UserTitleStatus' - 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: @@ -214,17 +199,9 @@ paths: content: application/json: schema: - type: object - properties: - data: - type: array - items: - $ref: '#/components/schemas/UserTitle' - cursor: - $ref: '#/components/schemas/CursorObj' - required: - - data - - cursor + type: array + items: + $ref: '#/components/schemas/UserTitle' '204': description: No titles found '400': diff --git a/api/api.gen.go b/api/api.gen.go index dcc2f89..54c8fc1 100644 --- a/api/api.gen.go +++ b/api/api.gen.go @@ -183,20 +183,17 @@ type GetUsersUserIdParams struct { // GetUsersUserIdTitlesParams defines parameters for GetUsersUserIdTitles. type GetUsersUserIdTitlesParams struct { - 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"` + Cursor *Cursor `form:"cursor,omitempty" json:"cursor,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"` - 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"` + 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"` } // Getter for additional properties for Title. Returns the specified @@ -806,22 +803,6 @@ func (siw *ServerInterfaceWrapper) GetUsersUserIdTitles(c *gin.Context) { return } - // ------------- Optional query parameter "sort" ------------- - - err = runtime.BindQueryParameter("form", true, false, "sort", c.Request.URL.Query(), ¶ms.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(), ¶ms.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(), ¶ms.Word) @@ -840,7 +821,7 @@ func (siw *ServerInterfaceWrapper) GetUsersUserIdTitles(c *gin.Context) { // ------------- Optional query parameter "watch_status" ------------- - err = runtime.BindQueryParameter("form", false, false, "watch_status", c.Request.URL.Query(), ¶ms.WatchStatus) + err = runtime.BindQueryParameter("form", true, false, "watch_status", c.Request.URL.Query(), ¶ms.WatchStatus) if err != nil { siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter watch_status: %w", err), http.StatusBadRequest) return @@ -854,14 +835,6 @@ 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(), ¶ms.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(), ¶ms.ReleaseYear) @@ -1084,10 +1057,7 @@ type GetUsersUserIdTitlesResponseObject interface { VisitGetUsersUserIdTitlesResponse(w http.ResponseWriter) error } -type GetUsersUserIdTitles200JSONResponse struct { - Cursor CursorObj `json:"cursor"` - Data []UserTitle `json:"data"` -} +type GetUsersUserIdTitles200JSONResponse []UserTitle func (response GetUsersUserIdTitles200JSONResponse) VisitGetUsersUserIdTitlesResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/json") diff --git a/api/paths/users-id-titles.yaml b/api/paths/users-id-titles.yaml index a76cc40..0788319 100644 --- a/api/paths/users-id-titles.yaml +++ b/api/paths/users-id-titles.yaml @@ -2,17 +2,11 @@ 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: @@ -29,21 +23,12 @@ get: - in: query name: watch_status schema: - type: array - items: - $ref: '../schemas/enums/UserTitleStatus.yaml' - style: form - explode: false + $ref: '../schemas/enums/UserTitleStatus.yaml' - 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: @@ -70,17 +55,9 @@ get: content: application/json: schema: - type: object - properties: - data: - type: array - items: - $ref: '../schemas/UserTitle.yaml' - cursor: - $ref: '../schemas/CursorObj.yaml' - required: - - data - - cursor + type: array + items: + $ref: '../schemas/UserTitle.yaml' '204': description: No titles found '400': diff --git a/modules/backend/handlers/common.go b/modules/backend/handlers/common.go index e22ce3f..6618d49 100644 --- a/modules/backend/handlers/common.go +++ b/modules/backend/handlers/common.go @@ -17,24 +17,7 @@ func NewServer(db *sqlc.Queries) Server { return Server{db: db} } -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: - } +func (s Server) mapTitle(ctx context.Context, title sqlc.SearchTitlesRow) (oapi.Title, error) { title_names := make(map[string][]string, 0) err := json.Unmarshal(title.TitleNames, &title_names) @@ -42,13 +25,10 @@ func (s Server) mapTitle(ctx context.Context, title sqlc.GetTitleByIDRow) (oapi. return oapi.Title{}, fmt.Errorf("unmarshal TitleNames: %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 + 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_tag_names := make(oapi.Tags, 0) @@ -58,20 +38,17 @@ func (s Server) mapTitle(ctx context.Context, title sqlc.GetTitleByIDRow) (oapi. } var oapi_studio oapi.Studio + + oapi_studio.Id = title.StudioID if title.StudioName != nil { oapi_studio.Name = *title.StudioName } - 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_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 } - oapi_title.Studio = &oapi_studio var oapi_image oapi.Image @@ -85,13 +62,27 @@ func (s Server) mapTitle(ctx context.Context, title sqlc.GetTitleByIDRow) (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.TitleStatus = oapi_status + 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: + } return oapi_title, nil } @@ -100,23 +91,3 @@ 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 -} diff --git a/modules/backend/handlers/titles.go b/modules/backend/handlers/titles.go index 054b745..78323f6 100644 --- a/modules/backend/handlers/titles.go +++ b/modules/backend/handlers/titles.go @@ -20,6 +20,32 @@ 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 @@ -143,8 +169,29 @@ func (s Server) GetTitlesTitleId(ctx context.Context, request oapi.GetTitlesTitl log.Errorf("%v", err) return oapi.GetTitlesTitleId500Response{}, nil } - - oapi_title, err = s.mapTitle(ctx, sqlc_title) + _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) if err != nil { log.Errorf("%v", err) return oapi.GetTitlesTitleId500Response{}, nil @@ -157,6 +204,11 @@ 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 { @@ -164,20 +216,16 @@ 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, - TitleStatuses: title_statuses, + Ongoing: status.ongoing, + Finished: status.finished, + Planned: status.planned, Rating: request.Params.Rating, ReleaseYear: request.Params.ReleaseYear, ReleaseSeason: season, - Forward: true, // default - SortBy: "id", // default + Forward: true, + SortBy: "id", Limit: request.Params.Limit, } @@ -187,7 +235,6 @@ 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), ¶ms) if err != nil { log.Errorf("%v", err) @@ -209,30 +256,7 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje for _, title := range titles { - _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) + t, err := s.mapTitle(ctx, title) if err != nil { log.Errorf("%v", err) return oapi.GetTitles500Response{}, nil diff --git a/modules/backend/handlers/users.go b/modules/backend/handlers/users.go index 3a271d7..1ea2c1a 100644 --- a/modules/backend/handlers/users.go +++ b/modules/backend/handlers/users.go @@ -5,7 +5,6 @@ import ( "fmt" oapi "nyanimedb/api" sqlc "nyanimedb/sql" - "strconv" "time" "github.com/jackc/pgx/v5" @@ -54,124 +53,37 @@ func (s Server) GetUsersUserId(ctx context.Context, req oapi.GetUsersUserIdReque return oapi.GetUsersUserId200JSONResponse(mapUser(user)), nil } -func sqlDate2oapi(p_date pgtype.Timestamptz) *time.Time { - if p_date.Valid { - t := p_date.Time - return &t - } - return nil +func sqlDate2oapi(p_date pgtype.Timestamptz) (time.Time, error) { + return time.Time{}, nil } -// 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 +type SqlcUserStatus struct { + dropped string + finished string + planned string + in_progress string } -func UserTitleStatus2Sqlc(s *[]oapi.UserTitleStatus) ([]sqlc.UsertitleStatusT, error) { - var sqlc_status []sqlc.UsertitleStatusT +func UserTitleStatus2Sqlc(s *[]oapi.UserTitleStatus) (*SqlcUserStatus, error) { + var sqlc_status SqlcUserStatus if s == nil { - return nil, nil + return &sqlc_status, nil } for _, t := range *s { switch t { case oapi.UserTitleStatusFinished: - sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTFinished) - case oapi.UserTitleStatusInProgress: - sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTInProgress) + sqlc_status.finished = "finished" case oapi.UserTitleStatusDropped: - sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTDropped) + sqlc_status.dropped = "dropped" case oapi.UserTitleStatusPlanned: - sqlc_status = append(sqlc_status, sqlc.UsertitleStatusTPlanned) + 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 (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 + return &sqlc_status, nil } func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersUserIdTitlesRequestObject) (oapi.GetUsersUserIdTitlesResponseObject, error) { @@ -179,6 +91,11 @@ 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 { @@ -186,37 +103,23 @@ 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{ - 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, + 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"` } if request.Params.SortForward != nil { @@ -225,7 +128,6 @@ 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), ¶ms) if err != nil { log.Errorf("%v", err) @@ -242,30 +144,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 { - - 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 - } + _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, } } - return oapi.GetUsersUserIdTitles200JSONResponse{Cursor: new_cursor, Data: oapi_usertitles}, nil + return oapi.GetUsersUserIdTitles200JSONResponse(userTitles), nil } diff --git a/modules/backend/queries.sql b/modules/backend/queries.sql index d064660..ee2a84a 100644 --- a/modules/backend/queries.sql +++ b/modules/backend/queries.sql @@ -101,30 +101,25 @@ GROUP BY -- name: SearchTitles :many SELECT - 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, + t.*, 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.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 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 @@ -193,17 +188,18 @@ WHERE ) 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[]) - ) + -- Если массив пуст (NULL или []) — не фильтруем + cardinality(sqlc.arg('title_statuses')::text[]) = 0 + OR + -- Иначе: статус есть в списке + t.title_status = ANY(sqlc.arg('title_statuses')::text[]) +) 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 + t.id, i.id, s.id, si.id ORDER BY CASE WHEN sqlc.arg('forward')::boolean THEN @@ -227,17 +223,7 @@ LIMIT COALESCE(sqlc.narg('limit')::int, 100); -- 100 is default limit -- name: SearchUserTitles :many SELECT - 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, + t.*, u.user_id as user_id, u.status as usertitle_status, u.rate as user_rate, @@ -245,18 +231,20 @@ SELECT u.ctime as user_ctime, 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 + 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 -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) +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) WHERE CASE @@ -324,25 +312,15 @@ WHERE END ) - 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 (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 (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 + t.id, i.id, s.id, si.id ORDER BY CASE WHEN sqlc.arg('forward')::boolean THEN diff --git a/sql/queries.sql.go b/sql/queries.sql.go index daa2b56..bf2f08a 100644 --- a/sql/queries.sql.go +++ b/sql/queries.sql.go @@ -342,30 +342,25 @@ func (q *Queries) InsertTitleTags(ctx context.Context, arg InsertTitleTagsParams const searchTitles = `-- name: SearchTitles :many SELECT - 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, + 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, 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.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 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 @@ -434,17 +429,18 @@ WHERE ) 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 ($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) + -- Если массив пуст (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) GROUP BY - t.id, i.id, s.id + t.id, i.id, s.id, si.id ORDER BY CASE WHEN $1::boolean THEN @@ -464,7 +460,7 @@ ORDER BY CASE WHEN $2::text <> 'id' THEN t.id END ASC -LIMIT COALESCE($10::int, 100) +LIMIT COALESCE($11::int, 100) ` type SearchTitlesParams struct { @@ -474,6 +470,7 @@ 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"` @@ -481,21 +478,27 @@ type SearchTitlesParams struct { } type SearchTitlesRow struct { - 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"` + 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"` } func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]SearchTitlesRow, error) { @@ -506,6 +509,7 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S arg.CursorID, arg.CursorRating, arg.Word, + arg.TitleStatuses, arg.Rating, arg.ReleaseYear, arg.ReleaseSeason, @@ -521,6 +525,7 @@ 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, @@ -530,10 +535,15 @@ 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 } @@ -548,17 +558,7 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S const searchUserTitles = `-- name: SearchUserTitles :many SELECT - 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, + 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, u.user_id as user_id, u.status as usertitle_status, u.rate as user_rate, @@ -566,18 +566,20 @@ SELECT u.ctime as user_ctime, 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 + 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 -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) +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) WHERE CASE @@ -645,25 +647,15 @@ WHERE END ) - 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) + 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) GROUP BY - t.id, i.id, s.id + t.id, i.id, s.id, si.id ORDER BY CASE WHEN $1::boolean THEN @@ -685,7 +677,7 @@ ORDER BY CASE WHEN $2::text <> 'id' THEN t.id END ASC -LIMIT COALESCE($11::int, 100) +LIMIT COALESCE($16::int, 100) ` type SearchUserTitlesParams struct { @@ -695,6 +687,11 @@ 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"` @@ -703,26 +700,32 @@ type SearchUserTitlesParams struct { } type SearchUserTitlesRow struct { - 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"` + 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"` } // 100 is default limit @@ -734,6 +737,11 @@ 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, @@ -750,6 +758,7 @@ 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, @@ -759,6 +768,7 @@ func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesPara &i.Season, &i.EpisodesAired, &i.EpisodesAll, + &i.EpisodesLen, &i.UserID, &i.UsertitleStatus, &i.UserRate, @@ -768,6 +778,10 @@ 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 }