package handlers import ( "context" "fmt" oapi "nyanimedb/api" sqlc "nyanimedb/sql" "strconv" "time" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/oapi-codegen/runtime/types" log "github.com/sirupsen/logrus" ) // type Server struct { // db *sqlc.Queries // } // func NewServer(db *sqlc.Queries) Server { // return Server{db: db} // } // func parseInt64(s string) (int32, error) { // i, err := strconv.ParseInt(s, 10, 64) // return int32(i), err // } func mapUser(u sqlc.GetUserByIDRow) (oapi.User, error) { i := oapi.Image{ Id: u.AvatarID, ImagePath: u.ImagePath, } s, err := sql2StorageType(u.StorageType) if err != nil { return oapi.User{}, fmt.Errorf("mapUser, storage type: %v", err) } i.StorageType = s return oapi.User{ Image: &i, CreationDate: &u.CreationDate, DispName: u.DispName, Id: &u.ID, Mail: StringToEmail(u.Mail), Nickname: u.Nickname, UserDesc: u.UserDesc, }, nil } func (s Server) GetUsersUserId(ctx context.Context, req oapi.GetUsersUserIdRequestObject) (oapi.GetUsersUserIdResponseObject, error) { userID, err := parseInt64(req.UserId) if err != nil { return oapi.GetUsersUserId404Response{}, nil } _user, err := s.db.GetUserByID(context.TODO(), userID) if err != nil { if err == pgx.ErrNoRows { return oapi.GetUsersUserId404Response{}, nil } return nil, err } user, err := mapUser(_user) if err != nil { log.Errorf("%v", err) return oapi.GetUsersUserId500Response{}, err } return oapi.GetUsersUserId200JSONResponse(user), nil } func sqlDate2oapi(p_date pgtype.Timestamptz) *time.Time { if p_date.Valid { t := p_date.Time return &t } return 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 s { case sqlc.UsertitleStatusTFinished: status = oapi.UserTitleStatusFinished case sqlc.UsertitleStatusTDropped: status = oapi.UserTitleStatusDropped case sqlc.UsertitleStatusTPlanned: status = oapi.UserTitleStatusPlanned case sqlc.UsertitleStatusTInProgress: status = oapi.UserTitleStatusInProgress default: return status, fmt.Errorf("unexpected tittle status: %s", s) } return status, nil } func UserTitleStatus2Sqlc(s *[]oapi.UserTitleStatus) ([]sqlc.UsertitleStatusT, error) { var sqlc_status []sqlc.UsertitleStatusT if s == nil { return nil, 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) 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 } func UserTitleStatus2Sqlc1(s *oapi.UserTitleStatus) (*sqlc.UsertitleStatusT, error) { var sqlc_status sqlc.UsertitleStatusT = sqlc.UsertitleStatusTFinished if s == nil { return &sqlc_status, nil } switch *s { case oapi.UserTitleStatusFinished: sqlc_status = sqlc.UsertitleStatusTFinished case oapi.UserTitleStatusInProgress: sqlc_status = sqlc.UsertitleStatusTInProgress case oapi.UserTitleStatusDropped: sqlc_status = sqlc.UsertitleStatusTDropped case oapi.UserTitleStatusPlanned: sqlc_status = sqlc.UsertitleStatusTPlanned default: return nil, fmt.Errorf("unexpected tittle status: %s", *s) } return &sqlc_status, nil } func (s Server) mapUsertitle(ctx context.Context, t sqlc.SearchUserTitlesRow) (oapi.UserTitle, error) { oapi_usertitle := oapi.UserTitle{ Ctime: &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, StudioName: t.StudioName, TitleNames: t.TitleNames, TagNames: t.TagNames, // 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) { oapi_usertitles := make([]oapi.UserTitle, 0) word := Word2Sqlc(request.Params.Word) season, err := ReleaseSeason2sqlc(request.Params.ReleaseSeason) if err != nil { log.Errorf("%v", err) 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 } userID, err := parseInt64(request.UserId) if err != nil { log.Errorf("get user titles: %v", err) return oapi.GetUsersUserIdTitles404Response{}, err } params := sqlc.SearchUserTitlesParams{ UserID: userID, 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 { 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), ¶ms) if err != nil { log.Errorf("%v", err) return oapi.GetUsersUserIdTitles400Response{}, nil } } } // param = nil means it will not be used titles, err := s.db.SearchUserTitles(ctx, params) if err != nil { log.Errorf("%v", err) return oapi.GetUsersUserIdTitles500Response{}, nil } 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 } } } return oapi.GetUsersUserIdTitles200JSONResponse{Cursor: new_cursor, Data: oapi_usertitles}, nil } func EmailToStringPtr(e *types.Email) *string { if e == nil { return nil } s := string(*e) return &s } func StringToEmail(e *string) *types.Email { if e == nil { return nil } s := types.Email(*e) return &s } // UpdateUser implements oapi.StrictServerInterface. func (s Server) UpdateUser(ctx context.Context, request oapi.UpdateUserRequestObject) (oapi.UpdateUserResponseObject, error) { params := sqlc.UpdateUserParams{ AvatarID: request.Body.AvatarId, DispName: request.Body.DispName, UserDesc: request.Body.UserDesc, Mail: EmailToStringPtr(request.Body.Mail), UserID: request.UserId, } user, err := s.db.UpdateUser(ctx, params) if err != nil { log.Errorf("%v", err) return oapi.UpdateUser500Response{}, nil } oapi_user := oapi.User{ // maybe its possible to make one sqlc type and use one map func iinstead of this shit // AvatarId: user.AvatarID, CreationDate: &user.CreationDate, DispName: user.DispName, Id: &user.ID, Mail: StringToEmail(user.Mail), Nickname: user.Nickname, UserDesc: user.UserDesc, } return oapi.UpdateUser200JSONResponse(oapi_user), nil } func (s Server) AddUserTitle(ctx context.Context, request oapi.AddUserTitleRequestObject) (oapi.AddUserTitleResponseObject, error) { status, err := UserTitleStatus2Sqlc1(&request.Body.Status) if err != nil { log.Errorf("%v", err) return oapi.AddUserTitle400Response{}, nil } params := sqlc.InsertUserTitleParams{ UserID: request.UserId, TitleID: request.Body.TitleId, Status: *status, Rate: request.Body.Rate, ReviewID: request.Body.ReviewId, } user_title, err := s.db.InsertUserTitle(ctx, params) if err != nil { log.Errorf("%v", err) return oapi.AddUserTitle500Response{}, nil } oapi_status, err := sql2usertitlestatus(user_title.Status) if err != nil { log.Errorf("%v", err) return oapi.AddUserTitle500Response{}, nil } oapi_usertitle := struct { Ctime *time.Time `json:"ctime,omitempty"` Rate *int32 `json:"rate,omitempty"` ReviewId *int64 `json:"review_id,omitempty"` // Status User's title status Status oapi.UserTitleStatus `json:"status"` TitleId int64 `json:"title_id"` UserId int64 `json:"user_id"` }{ Ctime: &user_title.Ctime, Rate: user_title.Rate, ReviewId: user_title.ReviewID, Status: oapi_status, TitleId: user_title.TitleID, UserId: user_title.UserID, } return oapi.AddUserTitle200JSONResponse{Data: &oapi_usertitle}, nil }