nyanimedb/modules/backend/handlers/titles.go

287 lines
7.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"context"
"encoding/json"
"fmt"
oapi "nyanimedb/api"
"nyanimedb/modules/backend/rmq"
sqlc "nyanimedb/sql"
"strconv"
"time"
"github.com/jackc/pgx/v5"
log "github.com/sirupsen/logrus"
)
func Word2Sqlc(s *string) *string {
if s == nil || *s == "" {
return nil
}
return s
}
func TitleStatus2oapi(s *sqlc.TitleStatusT) (*oapi.TitleStatus, error) {
if s == nil {
return nil, nil
}
var t oapi.TitleStatus
switch *s {
case sqlc.TitleStatusTFinished:
t = oapi.TitleStatusFinished
case sqlc.TitleStatusTOngoing:
t = oapi.TitleStatusOngoing
case sqlc.TitleStatusTPlanned:
t = oapi.TitleStatusPlanned
default:
return nil, fmt.Errorf("unexpected tittle status: %s", *s)
}
return &t, nil
}
func ReleaseSeason2sqlc(s *oapi.ReleaseSeason) (*sqlc.ReleaseSeasonT, error) {
if s == nil {
return nil, nil
}
var t sqlc.ReleaseSeasonT
switch *s {
case oapi.Winter:
t = sqlc.ReleaseSeasonTWinter
case oapi.Spring:
t = sqlc.ReleaseSeasonTSpring
case oapi.Summer:
t = sqlc.ReleaseSeasonTSummer
case oapi.Fall:
t = sqlc.ReleaseSeasonTFall
default:
return nil, fmt.Errorf("unexpected release season: %s", *s)
}
return &t, nil
}
func (s Server) GetTagsByTitleId(ctx context.Context, id int64) (oapi.Tags, error) {
sqlc_title_tags, err := s.db.GetTitleTags(ctx, id)
if err != nil {
if err == pgx.ErrNoRows {
return nil, nil
}
return nil, fmt.Errorf("query GetTitleTags: %v", err)
}
oapi_tag_names := make(oapi.Tags, 1)
for _, title_tag := range sqlc_title_tags {
oapi_tag_name := make(map[string]string, 1)
err = json.Unmarshal(title_tag, &oapi_tag_name)
if err != nil {
return nil, fmt.Errorf("unmarshalling title_tag: %v", err)
}
oapi_tag_names = append(oapi_tag_names, oapi_tag_name)
}
return oapi_tag_names, nil
}
// func (s Server) GetImage(ctx context.Context, id int64) (*oapi.Image, error) {
// var oapi_image oapi.Image
// sqlc_image, err := s.db.GetImageByID(ctx, id)
// if err != nil {
// if err == pgx.ErrNoRows {
// return nil, nil //todo: error reference in db
// }
// return &oapi_image, fmt.Errorf("query GetImageByID: %v", err)
// }
// //can cast and dont use brain cause all this fields required in image table
// oapi_image.Id = &sqlc_image.ID
// oapi_image.ImagePath = &sqlc_image.ImagePath
// storageTypeStr := string(sqlc_image.StorageType)
// oapi_image.StorageType = string(storageTypeStr)
// return &oapi_image, nil
// }
// func (s Server) GetStudio(ctx context.Context, id int64) (*oapi.Studio, error) {
// var oapi_studio oapi.Studio
// sqlc_studio, err := s.db.GetStudioByID(ctx, id)
// if err != nil {
// if err == pgx.ErrNoRows {
// return nil, nil
// }
// return &oapi_studio, fmt.Errorf("query GetStudioByID: %v", err)
// }
// oapi_studio.Id = sqlc_studio.ID
// oapi_studio.Name = sqlc_studio.StudioName
// oapi_studio.Description = sqlc_studio.StudioDesc
// if sqlc_studio.IllustID == nil {
// return &oapi_studio, nil
// }
// oapi_illust, err := s.GetImage(ctx, *sqlc_studio.IllustID)
// if err != nil {
// return &oapi_studio, fmt.Errorf("GetImage: %v", err)
// }
// if oapi_illust != nil {
// oapi_studio.Poster = oapi_illust
// }
// return &oapi_studio, nil
// }
func (s Server) GetTitle(ctx context.Context, request oapi.GetTitleRequestObject) (oapi.GetTitleResponseObject, error) {
var oapi_title oapi.Title
sqlc_title, err := s.db.GetTitleByID(ctx, request.TitleId)
if err != nil {
if err == pgx.ErrNoRows {
return oapi.GetTitle204Response{}, nil
}
log.Errorf("%v", err)
return oapi.GetTitle500Response{}, nil
}
oapi_title, err = s.mapTitle(sqlc_title)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitle500Response{}, nil
}
return oapi.GetTitle200JSONResponse(oapi_title), nil
}
func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObject) (oapi.GetTitlesResponseObject, error) {
if request.Params.ExtSearch != nil && *request.Params.ExtSearch {
// Публикуем событие — как и просили
event := rmq.RabbitRequest{
Name: "Attack on titans",
// Status oapi.TitleStatus `json:"titlestatus,omitempty"`
// Rating float64 `json:"titleraring,omitempty"`
// Year int32 `json:"year,omitempty"`
// Season oapi.ReleaseSeason `json:"season,omitempty"`
Timestamp: time.Now(),
}
// Контекст с таймаутом (не блокируем ответ)
publishCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
if err := s.publisher.Publish(publishCtx, "events.user", event); err != nil {
log.Errorf("RMQ publish failed (non-critical): %v", err)
} else {
log.Infof("RMQ publish succeed %v", err)
}
}
opai_titles := make([]oapi.Title, 0)
word := Word2Sqlc(request.Params.Word)
season, err := ReleaseSeason2sqlc(request.Params.ReleaseSeason)
if err != nil {
log.Errorf("%v", err)
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,
Rating: request.Params.Rating,
ReleaseYear: request.Params.ReleaseYear,
ReleaseSeason: season,
Forward: true, // default
SortBy: "id", // default
Limit: request.Params.Limit,
}
if request.Params.SortForward != nil {
params.Forward = *request.Params.SortForward
}
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)
return oapi.GetTitles400Response{}, nil
}
}
}
// param = nil means it will not be used
titles, err := s.db.SearchTitles(ctx, params)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitles500Response{}, nil
}
if len(titles) == 0 {
return oapi.GetTitles204Response{}, nil
}
var new_cursor oapi.CursorObj
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,
TitleNames: title.TitleNames,
TagNames: title.TagNames,
StudioName: title.StudioName,
// StudioIllustID: title.StudioIllustID,
// StudioDesc: title.StudioDesc,
// StudioStorageType: title.StudioStorageType,
// StudioImagePath: title.StudioImagePath,
}
// if title.TitleStorageType != nil {
// s := *title.TitleStorageType
// _title.TitleStorageType = string(s)
// }
t, err := s.mapTitle(_title)
if err != nil {
log.Errorf("%v", err)
return oapi.GetTitles500Response{}, nil
}
opai_titles = append(opai_titles, t)
new_cursor.Id = t.Id
if request.Params.Sort != nil {
switch string(*request.Params.Sort) {
case "year":
tmp := fmt.Sprint(*t.ReleaseYear)
new_cursor.Param = &tmp
case "rating":
tmp := strconv.FormatFloat(*t.Rating, 'f', -1, 64)
new_cursor.Param = &tmp
}
}
}
return oapi.GetTitles200JSONResponse{Cursor: new_cursor, Data: opai_titles}, nil
}