Merge branch 'dev-ars' into dev
This commit is contained in:
commit
96611825bc
6 changed files with 633 additions and 146 deletions
210
api/api.gen.go
210
api/api.gen.go
|
|
@ -31,9 +31,30 @@ const (
|
|||
Planned TitleStatus = "planned"
|
||||
)
|
||||
|
||||
// Image defines model for Image.
|
||||
type Image struct {
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
ImagePath *string `json:"image_path,omitempty"`
|
||||
StorageType *string `json:"storage_type,omitempty"`
|
||||
}
|
||||
|
||||
// ReleaseSeason Title release season
|
||||
type ReleaseSeason string
|
||||
|
||||
// Studio defines model for Studio.
|
||||
type Studio struct {
|
||||
Description *string `json:"description,omitempty"`
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Poster *Image `json:"poster,omitempty"`
|
||||
}
|
||||
|
||||
// Tag A localized tag: keys are language codes (ISO 639-1), values are tag names
|
||||
type Tag map[string]string
|
||||
|
||||
// Tags Array of localized tags
|
||||
type Tags = []Tag
|
||||
|
||||
// Title defines model for Title.
|
||||
type Title struct {
|
||||
EpisodesAired *int32 `json:"episodes_aired,omitempty"`
|
||||
|
|
@ -41,18 +62,21 @@ type Title struct {
|
|||
EpisodesLen *map[string]float64 `json:"episodes_len,omitempty"`
|
||||
|
||||
// Id Unique title ID (primary key)
|
||||
Id *int64 `json:"id,omitempty"`
|
||||
PosterId *int64 `json:"poster_id,omitempty"`
|
||||
Id int64 `json:"id"`
|
||||
Poster *Image `json:"poster,omitempty"`
|
||||
Rating *float64 `json:"rating,omitempty"`
|
||||
RatingCount *int32 `json:"rating_count,omitempty"`
|
||||
|
||||
// ReleaseSeason Title release season
|
||||
ReleaseSeason *ReleaseSeason `json:"release_season,omitempty"`
|
||||
ReleaseYear *int32 `json:"release_year,omitempty"`
|
||||
StudioId *int64 `json:"studio_id,omitempty"`
|
||||
Studio *Studio `json:"studio,omitempty"`
|
||||
|
||||
// Tags Array of localized tags
|
||||
Tags Tags `json:"tags"`
|
||||
|
||||
// TitleNames Localized titles. Key = language (ISO 639-1), value = list of names
|
||||
TitleNames *map[string][]string `json:"title_names,omitempty"`
|
||||
TitleNames map[string][]string `json:"title_names"`
|
||||
|
||||
// TitleStatus Title status
|
||||
TitleStatus *TitleStatus `json:"title_status,omitempty"`
|
||||
|
|
@ -93,11 +117,16 @@ type GetTitleParams struct {
|
|||
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 *int `form:"limit,omitempty" json:"limit,omitempty"`
|
||||
Offset *int `form:"offset,omitempty" json:"offset,omitempty"`
|
||||
Limit *int32 `form:"limit,omitempty" json:"limit,omitempty"`
|
||||
Offset *int32 `form:"offset,omitempty" json:"offset,omitempty"`
|
||||
Fields *string `form:"fields,omitempty" json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// GetTitleTitleIdParams defines parameters for GetTitleTitleId.
|
||||
type GetTitleTitleIdParams struct {
|
||||
Fields *string `form:"fields,omitempty" json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
// GetUsersUserIdParams defines parameters for GetUsersUserId.
|
||||
type GetUsersUserIdParams struct {
|
||||
Fields *string `form:"fields,omitempty" json:"fields,omitempty"`
|
||||
|
|
@ -160,12 +189,12 @@ func (a *Title) UnmarshalJSON(b []byte) error {
|
|||
delete(object, "id")
|
||||
}
|
||||
|
||||
if raw, found := object["poster_id"]; found {
|
||||
err = json.Unmarshal(raw, &a.PosterId)
|
||||
if raw, found := object["poster"]; found {
|
||||
err = json.Unmarshal(raw, &a.Poster)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading 'poster_id': %w", err)
|
||||
return fmt.Errorf("error reading 'poster': %w", err)
|
||||
}
|
||||
delete(object, "poster_id")
|
||||
delete(object, "poster")
|
||||
}
|
||||
|
||||
if raw, found := object["rating"]; found {
|
||||
|
|
@ -200,12 +229,20 @@ func (a *Title) UnmarshalJSON(b []byte) error {
|
|||
delete(object, "release_year")
|
||||
}
|
||||
|
||||
if raw, found := object["studio_id"]; found {
|
||||
err = json.Unmarshal(raw, &a.StudioId)
|
||||
if raw, found := object["studio"]; found {
|
||||
err = json.Unmarshal(raw, &a.Studio)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading 'studio_id': %w", err)
|
||||
return fmt.Errorf("error reading 'studio': %w", err)
|
||||
}
|
||||
delete(object, "studio_id")
|
||||
delete(object, "studio")
|
||||
}
|
||||
|
||||
if raw, found := object["tags"]; found {
|
||||
err = json.Unmarshal(raw, &a.Tags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading 'tags': %w", err)
|
||||
}
|
||||
delete(object, "tags")
|
||||
}
|
||||
|
||||
if raw, found := object["title_names"]; found {
|
||||
|
|
@ -264,17 +301,15 @@ func (a Title) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if a.Id != nil {
|
||||
object["id"], err = json.Marshal(a.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'id': %w", err)
|
||||
}
|
||||
object["id"], err = json.Marshal(a.Id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'id': %w", err)
|
||||
}
|
||||
|
||||
if a.PosterId != nil {
|
||||
object["poster_id"], err = json.Marshal(a.PosterId)
|
||||
if a.Poster != nil {
|
||||
object["poster"], err = json.Marshal(a.Poster)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'poster_id': %w", err)
|
||||
return nil, fmt.Errorf("error marshaling 'poster': %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -306,18 +341,21 @@ func (a Title) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if a.StudioId != nil {
|
||||
object["studio_id"], err = json.Marshal(a.StudioId)
|
||||
if a.Studio != nil {
|
||||
object["studio"], err = json.Marshal(a.Studio)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'studio_id': %w", err)
|
||||
return nil, fmt.Errorf("error marshaling 'studio': %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if a.TitleNames != nil {
|
||||
object["title_names"], err = json.Marshal(a.TitleNames)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'title_names': %w", err)
|
||||
}
|
||||
object["tags"], err = json.Marshal(a.Tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'tags': %w", err)
|
||||
}
|
||||
|
||||
object["title_names"], err = json.Marshal(a.TitleNames)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error marshaling 'title_names': %w", err)
|
||||
}
|
||||
|
||||
if a.TitleStatus != nil {
|
||||
|
|
@ -341,6 +379,9 @@ type ServerInterface interface {
|
|||
// Get titles
|
||||
// (GET /title)
|
||||
GetTitle(c *gin.Context, params GetTitleParams)
|
||||
// Get title description
|
||||
// (GET /title/{title_id})
|
||||
GetTitleTitleId(c *gin.Context, titleId int64, params GetTitleTitleIdParams)
|
||||
// Get user info
|
||||
// (GET /users/{user_id})
|
||||
GetUsersUserId(c *gin.Context, userId string, params GetUsersUserIdParams)
|
||||
|
|
@ -437,6 +478,41 @@ func (siw *ServerInterfaceWrapper) GetTitle(c *gin.Context) {
|
|||
siw.Handler.GetTitle(c, params)
|
||||
}
|
||||
|
||||
// GetTitleTitleId operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetTitleTitleId(c *gin.Context) {
|
||||
|
||||
var err error
|
||||
|
||||
// ------------- Path parameter "title_id" -------------
|
||||
var titleId int64
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "title_id", c.Param("title_id"), &titleId, runtime.BindStyledParameterOptions{Explode: false, Required: true})
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter title_id: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params GetTitleTitleIdParams
|
||||
|
||||
// ------------- Optional query parameter "fields" -------------
|
||||
|
||||
err = runtime.BindQueryParameter("form", true, false, "fields", c.Request.URL.Query(), ¶ms.Fields)
|
||||
if err != nil {
|
||||
siw.ErrorHandler(c, fmt.Errorf("Invalid format for parameter fields: %w", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
middleware(c)
|
||||
if c.IsAborted() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
siw.Handler.GetTitleTitleId(c, titleId, params)
|
||||
}
|
||||
|
||||
// GetUsersUserId operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetUsersUserId(c *gin.Context) {
|
||||
|
||||
|
|
@ -500,6 +576,7 @@ func RegisterHandlersWithOptions(router gin.IRouter, si ServerInterface, options
|
|||
}
|
||||
|
||||
router.GET(options.BaseURL+"/title", wrapper.GetTitle)
|
||||
router.GET(options.BaseURL+"/title/:title_id", wrapper.GetTitleTitleId)
|
||||
router.GET(options.BaseURL+"/users/:user_id", wrapper.GetUsersUserId)
|
||||
}
|
||||
|
||||
|
|
@ -544,6 +621,48 @@ func (response GetTitle500Response) VisitGetTitleResponse(w http.ResponseWriter)
|
|||
return nil
|
||||
}
|
||||
|
||||
type GetTitleTitleIdRequestObject struct {
|
||||
TitleId int64 `json:"title_id"`
|
||||
Params GetTitleTitleIdParams
|
||||
}
|
||||
|
||||
type GetTitleTitleIdResponseObject interface {
|
||||
VisitGetTitleTitleIdResponse(w http.ResponseWriter) error
|
||||
}
|
||||
|
||||
type GetTitleTitleId200JSONResponse Title
|
||||
|
||||
func (response GetTitleTitleId200JSONResponse) VisitGetTitleTitleIdResponse(w http.ResponseWriter) error {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
|
||||
return json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
|
||||
type GetTitleTitleId400Response struct {
|
||||
}
|
||||
|
||||
func (response GetTitleTitleId400Response) VisitGetTitleTitleIdResponse(w http.ResponseWriter) error {
|
||||
w.WriteHeader(400)
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetTitleTitleId404Response struct {
|
||||
}
|
||||
|
||||
func (response GetTitleTitleId404Response) VisitGetTitleTitleIdResponse(w http.ResponseWriter) error {
|
||||
w.WriteHeader(404)
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetTitleTitleId500Response struct {
|
||||
}
|
||||
|
||||
func (response GetTitleTitleId500Response) VisitGetTitleTitleIdResponse(w http.ResponseWriter) error {
|
||||
w.WriteHeader(500)
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetUsersUserIdRequestObject struct {
|
||||
UserId string `json:"user_id"`
|
||||
Params GetUsersUserIdParams
|
||||
|
|
@ -591,6 +710,9 @@ type StrictServerInterface interface {
|
|||
// Get titles
|
||||
// (GET /title)
|
||||
GetTitle(ctx context.Context, request GetTitleRequestObject) (GetTitleResponseObject, error)
|
||||
// Get title description
|
||||
// (GET /title/{title_id})
|
||||
GetTitleTitleId(ctx context.Context, request GetTitleTitleIdRequestObject) (GetTitleTitleIdResponseObject, error)
|
||||
// Get user info
|
||||
// (GET /users/{user_id})
|
||||
GetUsersUserId(ctx context.Context, request GetUsersUserIdRequestObject) (GetUsersUserIdResponseObject, error)
|
||||
|
|
@ -635,6 +757,34 @@ func (sh *strictHandler) GetTitle(ctx *gin.Context, params GetTitleParams) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetTitleTitleId operation middleware
|
||||
func (sh *strictHandler) GetTitleTitleId(ctx *gin.Context, titleId int64, params GetTitleTitleIdParams) {
|
||||
var request GetTitleTitleIdRequestObject
|
||||
|
||||
request.TitleId = titleId
|
||||
request.Params = params
|
||||
|
||||
handler := func(ctx *gin.Context, request interface{}) (interface{}, error) {
|
||||
return sh.ssi.GetTitleTitleId(ctx, request.(GetTitleTitleIdRequestObject))
|
||||
}
|
||||
for _, middleware := range sh.middlewares {
|
||||
handler = middleware(handler, "GetTitleTitleId")
|
||||
}
|
||||
|
||||
response, err := handler(ctx, request)
|
||||
|
||||
if err != nil {
|
||||
ctx.Error(err)
|
||||
ctx.Status(http.StatusInternalServerError)
|
||||
} else if validResponse, ok := response.(GetTitleTitleIdResponseObject); ok {
|
||||
if err := validResponse.VisitGetTitleTitleIdResponse(ctx.Writer); err != nil {
|
||||
ctx.Error(err)
|
||||
}
|
||||
} else if response != nil {
|
||||
ctx.Error(fmt.Errorf("unexpected response type: %T", response))
|
||||
}
|
||||
}
|
||||
|
||||
// GetUsersUserId operation middleware
|
||||
func (sh *strictHandler) GetUsersUserId(ctx *gin.Context, userId string, params GetUsersUserIdParams) {
|
||||
var request GetUsersUserIdRequestObject
|
||||
|
|
|
|||
135
api/openapi.yaml
135
api/openapi.yaml
|
|
@ -2,8 +2,10 @@ openapi: 3.1.1
|
|||
info:
|
||||
title: Titles, Users, Reviews, Tags, and Media API
|
||||
version: 1.0.0
|
||||
|
||||
servers:
|
||||
- url: /api/v1
|
||||
|
||||
paths:
|
||||
/title:
|
||||
get:
|
||||
|
|
@ -35,11 +37,13 @@ paths:
|
|||
name: limit
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
default: 10
|
||||
- in: query
|
||||
name: offset
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
default: 0
|
||||
- in: query
|
||||
name: fields
|
||||
|
|
@ -61,29 +65,35 @@ paths:
|
|||
description: Request params are not correct
|
||||
'500':
|
||||
description: Unknown server error
|
||||
# /title/{title_id}:
|
||||
# get:
|
||||
# summary: Get title description
|
||||
# parameters:
|
||||
# - in: path
|
||||
# name: title_id
|
||||
# required: true
|
||||
# schema:
|
||||
# type: string
|
||||
# - in: query
|
||||
# name: fields
|
||||
# schema:
|
||||
# type: string
|
||||
# default: all
|
||||
# responses:
|
||||
# '200':
|
||||
# description: Title description
|
||||
# content:
|
||||
# application/json:
|
||||
# schema:
|
||||
# $ref: '#/components/schemas/Title'
|
||||
# '404':
|
||||
# description: Title not found
|
||||
|
||||
/title/{title_id}:
|
||||
get:
|
||||
summary: Get title description
|
||||
parameters:
|
||||
- in: path
|
||||
name: title_id
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
- in: query
|
||||
name: fields
|
||||
schema:
|
||||
type: string
|
||||
default: all
|
||||
responses:
|
||||
'200':
|
||||
description: Title description
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Title'
|
||||
'404':
|
||||
description: Title not found
|
||||
'400':
|
||||
description: Request params are not correct
|
||||
'500':
|
||||
description: Unknown server error
|
||||
|
||||
# patch:
|
||||
# summary: Update title info
|
||||
|
|
@ -560,6 +570,17 @@ paths:
|
|||
|
||||
components:
|
||||
schemas:
|
||||
Image:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
storage_type:
|
||||
type: string
|
||||
image_path:
|
||||
type: string
|
||||
|
||||
TitleStatus:
|
||||
type: string
|
||||
description: Title status
|
||||
|
|
@ -567,6 +588,7 @@ components:
|
|||
- finished
|
||||
- ongoing
|
||||
- planned
|
||||
|
||||
ReleaseSeason:
|
||||
type: string
|
||||
description: Title release season
|
||||
|
|
@ -575,6 +597,7 @@ components:
|
|||
- spring
|
||||
- summer
|
||||
- fall
|
||||
|
||||
UserTitleStatus:
|
||||
type: string
|
||||
description: User's title status
|
||||
|
|
@ -583,8 +606,54 @@ components:
|
|||
- planned
|
||||
- dropped
|
||||
- in-progress
|
||||
|
||||
Review:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
||||
Tag:
|
||||
type: object
|
||||
description: "A localized tag: keys are language codes (ISO 639-1), values are tag names"
|
||||
additionalProperties:
|
||||
type: string
|
||||
example:
|
||||
en: "Shojo"
|
||||
ru: "Сёдзё"
|
||||
ja: "少女"
|
||||
|
||||
Tags:
|
||||
type: array
|
||||
description: "Array of localized tags"
|
||||
items:
|
||||
$ref: '#/components/schemas/Tag'
|
||||
example:
|
||||
- en: "Shojo"
|
||||
ru: "Сёдзё"
|
||||
ja: "少女"
|
||||
- en: "Shounen"
|
||||
ru: "Сёнен"
|
||||
ja: "少年"
|
||||
|
||||
Studio:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
poster:
|
||||
$ref: '#/components/schemas/Image'
|
||||
description:
|
||||
type: string
|
||||
|
||||
|
||||
Title:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- title_names
|
||||
- tags
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
|
|
@ -605,12 +674,12 @@ components:
|
|||
en: ["Attack on Titan", "AoT"]
|
||||
ru: ["Атака титанов", "Титаны"]
|
||||
ja: ["進撃の巨人"]
|
||||
studio_id:
|
||||
type: integer
|
||||
format: int64
|
||||
poster_id:
|
||||
type: integer
|
||||
format: int64
|
||||
studio:
|
||||
$ref: '#/components/schemas/Studio'
|
||||
tags:
|
||||
$ref: '#/components/schemas/Tags'
|
||||
poster:
|
||||
$ref: '#/components/schemas/Image'
|
||||
title_status:
|
||||
$ref: '#/components/schemas/TitleStatus'
|
||||
rating:
|
||||
|
|
@ -636,6 +705,7 @@ components:
|
|||
type: number
|
||||
format: double
|
||||
additionalProperties: true
|
||||
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
|
|
@ -679,12 +749,7 @@ components:
|
|||
- user_id
|
||||
- nickname
|
||||
# - creation_date
|
||||
|
||||
UserTitle:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
Review:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
Tag:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
|
|
|
|||
|
|
@ -25,13 +25,14 @@ func TitleStatus2Sqlc(s *oapi.TitleStatus) (*sqlc.TitleStatusT, error) {
|
|||
return nil, nil
|
||||
}
|
||||
var t sqlc.TitleStatusT
|
||||
if *s == "finished" {
|
||||
t = "finished"
|
||||
} else if *s == "ongoing" {
|
||||
t = "ongoing"
|
||||
} else if *s == "planned" {
|
||||
t = "planned"
|
||||
} else {
|
||||
switch *s {
|
||||
case oapi.Finished:
|
||||
t = sqlc.TitleStatusTFinished
|
||||
case oapi.Ongoing:
|
||||
t = sqlc.TitleStatusTOngoing
|
||||
case oapi.Planned:
|
||||
t = sqlc.TitleStatusTPlanned
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected tittle status: %s", *s)
|
||||
}
|
||||
return &t, nil
|
||||
|
|
@ -41,41 +42,153 @@ func ReleaseSeason2sqlc(s *oapi.ReleaseSeason) (*sqlc.ReleaseSeasonT, error) {
|
|||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
//TODO
|
||||
var t sqlc.ReleaseSeasonT
|
||||
if *s == oapi.Winter {
|
||||
switch *s {
|
||||
case oapi.Winter:
|
||||
t = sqlc.ReleaseSeasonTWinter
|
||||
} else if *s == "spring" {
|
||||
t = "spring"
|
||||
} else if *s == "summer" {
|
||||
t = "summer"
|
||||
} else if *s == "fall" {
|
||||
t = "fall"
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
// unmarshall jsonb to map[string][]string
|
||||
func jsonb2map4names(b []byte) (*map[string][]string, error) {
|
||||
var t map[string][]string
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return nil, fmt.Errorf("invalid title_names JSON for title: %w", err)
|
||||
// type TitleNames map[string][]string
|
||||
// type EpisodeLens map[string]float64
|
||||
// type TagNames []map[string]string
|
||||
|
||||
func (s Server) GetTagsByTitleId(ctx context.Context, id int64) (oapi.Tags, error) {
|
||||
|
||||
sqlc_title_tags, err := s.db.GetTitleTags(ctx, id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query GetTitleTags: %v", err)
|
||||
}
|
||||
return &t, nil
|
||||
|
||||
var oapi_tag_names oapi.Tags
|
||||
for _, title_tag := range sqlc_title_tags {
|
||||
var oapi_tag_name map[string]string
|
||||
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 jsonb2map4len(b []byte) (*map[string]float64, error) {
|
||||
var t map[string]float64
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return nil, fmt.Errorf("invalid episodes_len JSON for title: %w", err)
|
||||
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 {
|
||||
return oapi_image, fmt.Errorf("query GetImageByID: %v", err)
|
||||
}
|
||||
return &t, nil
|
||||
//can cast and dont use brain cause all this fiels required
|
||||
oapi_image.Id = &sqlc_image.ID
|
||||
oapi_image.ImagePath = &sqlc_image.ImagePath
|
||||
oapi_image.StorageType = (*string)(&sqlc_image.StorageType)
|
||||
|
||||
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 {
|
||||
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
|
||||
|
||||
oapi_illust, err := s.GetImage(ctx, *sqlc_studio.IllustID)
|
||||
if err != nil {
|
||||
return oapi_studio, fmt.Errorf("GetImage: %v", err)
|
||||
}
|
||||
oapi_studio.Poster = &oapi_illust
|
||||
|
||||
return oapi_studio, nil
|
||||
}
|
||||
|
||||
func (s Server) mapTitle(ctx context.Context, title sqlc.Title) (oapi.Title, error) {
|
||||
var oapi_title oapi.Title
|
||||
|
||||
var title_names map[string][]string
|
||||
err := json.Unmarshal(title.TitleNames, &title_names)
|
||||
if err != nil {
|
||||
return oapi_title, fmt.Errorf("unmarshal TitleNames: %v", err)
|
||||
}
|
||||
|
||||
var episodes_lens map[string]float64
|
||||
err = json.Unmarshal(title.EpisodesLen, &episodes_lens)
|
||||
if err != nil {
|
||||
return oapi_title, fmt.Errorf("unmarshal EpisodesLen: %v", err)
|
||||
}
|
||||
|
||||
oapi_tag_names, err := s.GetTagsByTitleId(ctx, title.ID)
|
||||
if err != nil {
|
||||
return oapi_title, fmt.Errorf("GetTagsByTitleId: %v", err)
|
||||
}
|
||||
|
||||
oapi_image, err := s.GetImage(ctx, *title.PosterID)
|
||||
if err != nil {
|
||||
return oapi_title, fmt.Errorf("GetImage: %v", err)
|
||||
}
|
||||
|
||||
oapi_studio, err := s.GetStudio(ctx, title.StudioID)
|
||||
if err != nil {
|
||||
return oapi_title, fmt.Errorf("GetStudio: %v", err)
|
||||
}
|
||||
|
||||
oapi_title = oapi.Title{
|
||||
|
||||
Id: title.ID,
|
||||
Poster: &oapi_image,
|
||||
Rating: title.Rating,
|
||||
RatingCount: title.RatingCount,
|
||||
ReleaseSeason: (*oapi.ReleaseSeason)(title.ReleaseSeason),
|
||||
ReleaseYear: title.ReleaseYear,
|
||||
Studio: &oapi_studio,
|
||||
Tags: oapi_tag_names,
|
||||
TitleNames: title_names,
|
||||
TitleStatus: (*oapi.TitleStatus)(&title.TitleStatus),
|
||||
EpisodesAired: title.EpisodesAired,
|
||||
EpisodesAll: title.EpisodesAll,
|
||||
EpisodesLen: &episodes_lens,
|
||||
}
|
||||
return oapi_title, nil
|
||||
}
|
||||
|
||||
func (s Server) GetTitleTitleId(ctx context.Context, request oapi.GetTitleTitleIdRequestObject) (oapi.GetTitleTitleIdResponseObject, error) {
|
||||
var oapi_title oapi.Title
|
||||
|
||||
sqlc_title, err := s.db.GetTitleByID(ctx, request.TitleId)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
return oapi.GetTitleTitleId500Response{}, nil
|
||||
}
|
||||
|
||||
oapi_title, err = s.mapTitle(ctx, sqlc_title)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
return oapi.GetTitleTitleId500Response{}, nil
|
||||
}
|
||||
|
||||
return oapi.GetTitleTitleId200JSONResponse(oapi_title), nil
|
||||
}
|
||||
|
||||
func (s Server) GetTitle(ctx context.Context, request oapi.GetTitleRequestObject) (oapi.GetTitleResponseObject, error) {
|
||||
var result []oapi.Title
|
||||
var opai_titles []oapi.Title
|
||||
|
||||
word := Word2Sqlc(request.Params.Word)
|
||||
status, err := TitleStatus2Sqlc(request.Params.Status)
|
||||
|
|
@ -95,8 +208,11 @@ func (s Server) GetTitle(ctx context.Context, request oapi.GetTitleRequestObject
|
|||
Rating: request.Params.Rating,
|
||||
ReleaseYear: request.Params.ReleaseYear,
|
||||
ReleaseSeason: season,
|
||||
Offset: request.Params.Offset,
|
||||
Limit: request.Params.Limit,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
return oapi.GetTitle500Response{}, nil
|
||||
}
|
||||
if len(titles) == 0 {
|
||||
|
|
@ -104,32 +220,14 @@ func (s Server) GetTitle(ctx context.Context, request oapi.GetTitleRequestObject
|
|||
}
|
||||
|
||||
for _, title := range titles {
|
||||
title_names, err := jsonb2map4names(title.TitleNames)
|
||||
|
||||
t, err := s.mapTitle(ctx, title)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
return oapi.GetTitle500Response{}, err
|
||||
return oapi.GetTitle500Response{}, nil
|
||||
}
|
||||
episodes_lens, err := jsonb2map4len(title.EpisodesLen)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
return oapi.GetTitle500Response{}, err
|
||||
}
|
||||
t := oapi.Title{
|
||||
Id: &title.ID,
|
||||
PosterId: title.PosterID,
|
||||
Rating: title.Rating,
|
||||
RatingCount: title.RatingCount,
|
||||
ReleaseSeason: (*oapi.ReleaseSeason)(title.ReleaseSeason),
|
||||
ReleaseYear: title.ReleaseYear,
|
||||
StudioId: &title.StudioID,
|
||||
TitleNames: title_names,
|
||||
TitleStatus: (*oapi.TitleStatus)(&title.TitleStatus),
|
||||
EpisodesAired: title.EpisodesAired,
|
||||
EpisodesAll: title.EpisodesAll,
|
||||
EpisodesLen: episodes_lens,
|
||||
}
|
||||
result = append(result, t)
|
||||
opai_titles = append(opai_titles, t)
|
||||
}
|
||||
|
||||
return oapi.GetTitle200JSONResponse(result), nil
|
||||
return oapi.GetTitle200JSONResponse(opai_titles), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
-- name: GetImageByID :one
|
||||
SELECT id, storage_type, image_path
|
||||
FROM images
|
||||
WHERE id = $1;
|
||||
WHERE id = sqlc.arg('illust_id');
|
||||
|
||||
-- name: CreateImage :one
|
||||
INSERT INTO images (storage_type, image_path)
|
||||
|
|
@ -13,6 +13,40 @@ SELECT id, avatar_id, mail, nickname, disp_name, user_desc, creation_date
|
|||
FROM users
|
||||
WHERE id = $1;
|
||||
|
||||
|
||||
-- name: GetStudioByID :one
|
||||
SELECT *
|
||||
FROM studios
|
||||
WHERE id = sqlc.arg('studio_id')::bigint;
|
||||
|
||||
-- name: InsertStudio :one
|
||||
INSERT INTO studios (studio_name, illust_id, studio_desc)
|
||||
VALUES (
|
||||
sqlc.arg('studio_name')::text,
|
||||
sqlc.narg('illust_id')::bigint,
|
||||
sqlc.narg('studio_desc')::text)
|
||||
RETURNING id, studio_name, illust_id, studio_desc;
|
||||
|
||||
-- name: GetTitleTags :many
|
||||
SELECT
|
||||
tag_names
|
||||
FROM tags as g
|
||||
JOIN title_tags as t ON(t.tag_id = g.id)
|
||||
WHERE t.title_id = sqlc.arg('title_id')::bigint;
|
||||
|
||||
-- name: InsertTitleTags :one
|
||||
INSERT INTO title_tags (title_id, tag_id)
|
||||
VALUES (
|
||||
sqlc.arg('title_id')::bigint,
|
||||
sqlc.arg('tag_id')::bigint)
|
||||
RETURNING title_id, tag_id;
|
||||
|
||||
-- name: InsertTag :one
|
||||
INSERT INTO tags (tag_names)
|
||||
VALUES (
|
||||
sqlc.arg('tag_names')::jsonb)
|
||||
RETURNING id, tag_names;
|
||||
|
||||
-- -- name: ListUsers :many
|
||||
-- SELECT user_id, avatar_id, passhash, mail, nickname, disp_name, user_desc, creation_date
|
||||
-- FROM users
|
||||
|
|
@ -38,6 +72,11 @@ WHERE id = $1;
|
|||
-- DELETE FROM users
|
||||
-- WHERE user_id = $1;
|
||||
|
||||
-- name: GetTitleByID :one
|
||||
SELECT *
|
||||
FROM titles
|
||||
WHERE id = sqlc.arg('title_id')::bigint;
|
||||
|
||||
-- name: SearchTitles :many
|
||||
SELECT
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ CREATE TABLE providers (
|
|||
|
||||
CREATE TABLE tags (
|
||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
-- example: { "ru": "Сёдзё", "en": "Shojo", "jp": "少女"}
|
||||
tag_names jsonb NOT NULL
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,13 +34,113 @@ FROM images
|
|||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetImageByID(ctx context.Context, id int64) (Image, error) {
|
||||
row := q.db.QueryRow(ctx, getImageByID, id)
|
||||
func (q *Queries) GetImageByID(ctx context.Context, illustID int64) (Image, error) {
|
||||
row := q.db.QueryRow(ctx, getImageByID, illustID)
|
||||
var i Image
|
||||
err := row.Scan(&i.ID, &i.StorageType, &i.ImagePath)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getStudioByID = `-- name: GetStudioByID :one
|
||||
SELECT id, studio_name, illust_id, studio_desc
|
||||
FROM studios
|
||||
WHERE id = $1::bigint
|
||||
`
|
||||
|
||||
func (q *Queries) GetStudioByID(ctx context.Context, studioID int64) (Studio, error) {
|
||||
row := q.db.QueryRow(ctx, getStudioByID, studioID)
|
||||
var i Studio
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.StudioName,
|
||||
&i.IllustID,
|
||||
&i.StudioDesc,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTitleByID = `-- name: GetTitleByID :one
|
||||
|
||||
|
||||
|
||||
|
||||
SELECT id, title_names, studio_id, poster_id, title_status, rating, rating_count, release_year, release_season, season, episodes_aired, episodes_all, episodes_len
|
||||
FROM titles
|
||||
WHERE id = $1::bigint
|
||||
`
|
||||
|
||||
// -- name: ListUsers :many
|
||||
// SELECT user_id, avatar_id, passhash, mail, nickname, disp_name, user_desc, creation_date
|
||||
// FROM users
|
||||
// ORDER BY user_id
|
||||
// LIMIT $1 OFFSET $2;
|
||||
// -- name: CreateUser :one
|
||||
// INSERT INTO users (avatar_id, passhash, mail, nickname, disp_name, user_desc, creation_date)
|
||||
// VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
// RETURNING user_id, avatar_id, nickname, disp_name, user_desc, creation_date;
|
||||
// -- name: UpdateUser :one
|
||||
// UPDATE users
|
||||
// SET
|
||||
//
|
||||
// avatar_id = COALESCE(sqlc.narg('avatar_id'), avatar_id),
|
||||
// disp_name = COALESCE(sqlc.narg('disp_name'), disp_name),
|
||||
// user_desc = COALESCE(sqlc.narg('user_desc'), user_desc),
|
||||
// passhash = COALESCE(sqlc.narg('passhash'), passhash)
|
||||
//
|
||||
// WHERE user_id = sqlc.arg('user_id')
|
||||
// RETURNING user_id, avatar_id, nickname, disp_name, user_desc, creation_date;
|
||||
// -- name: DeleteUser :exec
|
||||
// DELETE FROM users
|
||||
// WHERE user_id = $1;
|
||||
func (q *Queries) GetTitleByID(ctx context.Context, titleID int64) (Title, error) {
|
||||
row := q.db.QueryRow(ctx, getTitleByID, titleID)
|
||||
var i Title
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TitleNames,
|
||||
&i.StudioID,
|
||||
&i.PosterID,
|
||||
&i.TitleStatus,
|
||||
&i.Rating,
|
||||
&i.RatingCount,
|
||||
&i.ReleaseYear,
|
||||
&i.ReleaseSeason,
|
||||
&i.Season,
|
||||
&i.EpisodesAired,
|
||||
&i.EpisodesAll,
|
||||
&i.EpisodesLen,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTitleTags = `-- name: GetTitleTags :many
|
||||
SELECT
|
||||
tag_names
|
||||
FROM tags as g
|
||||
JOIN title_tags as t ON(t.tag_id = g.id)
|
||||
WHERE t.title_id = $1::bigint
|
||||
`
|
||||
|
||||
func (q *Queries) GetTitleTags(ctx context.Context, titleID int64) ([][]byte, error) {
|
||||
rows, err := q.db.Query(ctx, getTitleTags, titleID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items [][]byte
|
||||
for rows.Next() {
|
||||
var tag_names []byte
|
||||
if err := rows.Scan(&tag_names); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, tag_names)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getUserByID = `-- name: GetUserByID :one
|
||||
SELECT id, avatar_id, mail, nickname, disp_name, user_desc, creation_date
|
||||
FROM users
|
||||
|
|
@ -72,11 +172,68 @@ func (q *Queries) GetUserByID(ctx context.Context, id int64) (GetUserByIDRow, er
|
|||
return i, err
|
||||
}
|
||||
|
||||
const insertStudio = `-- name: InsertStudio :one
|
||||
INSERT INTO studios (studio_name, illust_id, studio_desc)
|
||||
VALUES (
|
||||
$1::text,
|
||||
$2::bigint,
|
||||
$3::text)
|
||||
RETURNING id, studio_name, illust_id, studio_desc
|
||||
`
|
||||
|
||||
type InsertStudioParams struct {
|
||||
StudioName string `json:"studio_name"`
|
||||
IllustID *int64 `json:"illust_id"`
|
||||
StudioDesc *string `json:"studio_desc"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertStudio(ctx context.Context, arg InsertStudioParams) (Studio, error) {
|
||||
row := q.db.QueryRow(ctx, insertStudio, arg.StudioName, arg.IllustID, arg.StudioDesc)
|
||||
var i Studio
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.StudioName,
|
||||
&i.IllustID,
|
||||
&i.StudioDesc,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertTag = `-- name: InsertTag :one
|
||||
INSERT INTO tags (tag_names)
|
||||
VALUES (
|
||||
$1::jsonb)
|
||||
RETURNING id, tag_names
|
||||
`
|
||||
|
||||
func (q *Queries) InsertTag(ctx context.Context, tagNames []byte) (Tag, error) {
|
||||
row := q.db.QueryRow(ctx, insertTag, tagNames)
|
||||
var i Tag
|
||||
err := row.Scan(&i.ID, &i.TagNames)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertTitleTags = `-- name: InsertTitleTags :one
|
||||
INSERT INTO title_tags (title_id, tag_id)
|
||||
VALUES (
|
||||
$1::bigint,
|
||||
$2::bigint)
|
||||
RETURNING title_id, tag_id
|
||||
`
|
||||
|
||||
type InsertTitleTagsParams struct {
|
||||
TitleID int64 `json:"title_id"`
|
||||
TagID int64 `json:"tag_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertTitleTags(ctx context.Context, arg InsertTitleTagsParams) (TitleTag, error) {
|
||||
row := q.db.QueryRow(ctx, insertTitleTags, arg.TitleID, arg.TagID)
|
||||
var i TitleTag
|
||||
err := row.Scan(&i.TitleID, &i.TagID)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const searchTitles = `-- name: SearchTitles :many
|
||||
|
||||
|
||||
|
||||
|
||||
SELECT
|
||||
id, title_names, studio_id, poster_id, title_status, rating, rating_count, release_year, release_season, season, episodes_aired, episodes_all, episodes_len
|
||||
FROM titles
|
||||
|
|
@ -121,29 +278,6 @@ type SearchTitlesParams struct {
|
|||
Limit *int32 `json:"limit"`
|
||||
}
|
||||
|
||||
// -- name: ListUsers :many
|
||||
// SELECT user_id, avatar_id, passhash, mail, nickname, disp_name, user_desc, creation_date
|
||||
// FROM users
|
||||
// ORDER BY user_id
|
||||
// LIMIT $1 OFFSET $2;
|
||||
// -- name: CreateUser :one
|
||||
// INSERT INTO users (avatar_id, passhash, mail, nickname, disp_name, user_desc, creation_date)
|
||||
// VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
// RETURNING user_id, avatar_id, nickname, disp_name, user_desc, creation_date;
|
||||
// -- name: UpdateUser :one
|
||||
// UPDATE users
|
||||
// SET
|
||||
//
|
||||
// avatar_id = COALESCE(sqlc.narg('avatar_id'), avatar_id),
|
||||
// disp_name = COALESCE(sqlc.narg('disp_name'), disp_name),
|
||||
// user_desc = COALESCE(sqlc.narg('user_desc'), user_desc),
|
||||
// passhash = COALESCE(sqlc.narg('passhash'), passhash)
|
||||
//
|
||||
// WHERE user_id = sqlc.arg('user_id')
|
||||
// RETURNING user_id, avatar_id, nickname, disp_name, user_desc, creation_date;
|
||||
// -- name: DeleteUser :exec
|
||||
// DELETE FROM users
|
||||
// WHERE user_id = $1;
|
||||
func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]Title, error) {
|
||||
rows, err := q.db.Query(ctx, searchTitles,
|
||||
arg.Word,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue