fix kinopoisk api

This commit is contained in:
2025-11-21 17:34:18 +02:00
parent 084d9fb09b
commit 1ca20bb7a7
4 changed files with 65 additions and 37 deletions

View File

@@ -120,28 +120,31 @@ func Handler(w http.ResponseWriter, r *http.Request) {
api.HandleFunc("/images/{type}/{id}", imagesHandler.GetImage).Methods("GET")
// Movies routes - specific paths first, then parameterized
api.HandleFunc("/movies/search", movieHandler.Search).Methods("GET")
api.HandleFunc("/movies/popular", movieHandler.Popular).Methods("GET")
api.HandleFunc("/movies/top-rated", movieHandler.TopRated).Methods("GET")
api.HandleFunc("/movies/upcoming", movieHandler.Upcoming).Methods("GET")
api.HandleFunc("/movies/{id}", movieHandler.GetByID).Methods("GET")
// Unified prefixed routes
api.HandleFunc("/movie/{id}", unifiedHandler.GetMovie).Methods("GET")
api.HandleFunc("/tv/{id}", unifiedHandler.GetTV).Methods("GET")
api.HandleFunc("/search", unifiedHandler.Search).Methods("GET")
api.HandleFunc("/movies/{id}/recommendations", movieHandler.GetRecommendations).Methods("GET")
api.HandleFunc("/movies/{id}/similar", movieHandler.GetSimilar).Methods("GET")
api.HandleFunc("/movies/{id}/external-ids", movieHandler.GetExternalIDs).Methods("GET")
api.HandleFunc("/movies/{id}", movieHandler.GetByID).Methods("GET")
// TV routes - specific paths first, then parameterized
api.HandleFunc("/tv/search", tvHandler.Search).Methods("GET")
api.HandleFunc("/tv/popular", tvHandler.Popular).Methods("GET")
api.HandleFunc("/tv/top-rated", tvHandler.TopRated).Methods("GET")
api.HandleFunc("/tv/on-the-air", tvHandler.OnTheAir).Methods("GET")
api.HandleFunc("/tv/airing-today", tvHandler.AiringToday).Methods("GET")
api.HandleFunc("/tv/{id}", tvHandler.GetByID).Methods("GET")
api.HandleFunc("/tv/{id}/recommendations", tvHandler.GetRecommendations).Methods("GET")
api.HandleFunc("/tv/{id}/similar", tvHandler.GetSimilar).Methods("GET")
api.HandleFunc("/tv/{id}/external-ids", tvHandler.GetExternalIDs).Methods("GET")
api.HandleFunc("/tv/{id}", tvHandler.GetByID).Methods("GET")
// Unified prefixed routes - register last so they don't interfere with specific routes
api.HandleFunc("/movie/{id}", unifiedHandler.GetMovie).Methods("GET")
api.HandleFunc("/tv/{id}", unifiedHandler.GetTV).Methods("GET")
api.HandleFunc("/search", unifiedHandler.Search).Methods("GET")
protected := api.PathPrefix("").Subrouter()
protected.Use(middleware.JWTAuth(globalCfg.JWTSecret))

14
main.go
View File

@@ -96,28 +96,30 @@ func main() {
api.HandleFunc("/images/{type}/{id}", imagesHandler.GetImage).Methods("GET")
// Movies routes - specific paths first, then parameterized
api.HandleFunc("/movies/search", movieHandler.Search).Methods("GET")
api.HandleFunc("/movies/popular", movieHandler.Popular).Methods("GET")
api.HandleFunc("/movies/top-rated", movieHandler.TopRated).Methods("GET")
api.HandleFunc("/movies/upcoming", movieHandler.Upcoming).Methods("GET")
api.HandleFunc("/movies/{id}", movieHandler.GetByID).Methods("GET")
// Unified prefixed routes
api.HandleFunc("/movie/{id}", unifiedHandler.GetMovie).Methods("GET")
api.HandleFunc("/tv/{id}", unifiedHandler.GetTV).Methods("GET")
api.HandleFunc("/search", unifiedHandler.Search).Methods("GET")
api.HandleFunc("/movies/{id}/recommendations", movieHandler.GetRecommendations).Methods("GET")
api.HandleFunc("/movies/{id}/similar", movieHandler.GetSimilar).Methods("GET")
api.HandleFunc("/movies/{id}/external-ids", movieHandler.GetExternalIDs).Methods("GET")
api.HandleFunc("/movies/{id}", movieHandler.GetByID).Methods("GET")
// TV routes - specific paths first, then parameterized
api.HandleFunc("/tv/search", tvHandler.Search).Methods("GET")
api.HandleFunc("/tv/popular", tvHandler.Popular).Methods("GET")
api.HandleFunc("/tv/top-rated", tvHandler.TopRated).Methods("GET")
api.HandleFunc("/tv/on-the-air", tvHandler.OnTheAir).Methods("GET")
api.HandleFunc("/tv/airing-today", tvHandler.AiringToday).Methods("GET")
api.HandleFunc("/tv/{id}", tvHandler.GetByID).Methods("GET")
api.HandleFunc("/tv/{id}/recommendations", tvHandler.GetRecommendations).Methods("GET")
api.HandleFunc("/tv/{id}/similar", tvHandler.GetSimilar).Methods("GET")
api.HandleFunc("/tv/{id}/external-ids", tvHandler.GetExternalIDs).Methods("GET")
api.HandleFunc("/tv/{id}", tvHandler.GetByID).Methods("GET")
api.HandleFunc("/movie/{id}", unifiedHandler.GetMovie).Methods("GET")
api.HandleFunc("/tv/{id}", unifiedHandler.GetTV).Methods("GET")
api.HandleFunc("/search", unifiedHandler.Search).Methods("GET")
protected := api.PathPrefix("").Subrouter()
protected.Use(middleware.JWTAuth(cfg.JWTSecret))

View File

@@ -9,6 +9,44 @@ import (
"time"
)
// FlexibleInt can unmarshal int, string, and null JSON values
type FlexibleInt int
func (fi *FlexibleInt) UnmarshalJSON(data []byte) error {
// Handle null values
if string(data) == "null" {
*fi = 0
return nil
}
var i int
var s string
// Try to unmarshal as int first
if err := json.Unmarshal(data, &i); err == nil {
*fi = FlexibleInt(i)
return nil
}
// Try to unmarshal as string
if err := json.Unmarshal(data, &s); err == nil {
if s == "" || s == "null" {
*fi = 0
return nil
}
parsed, err := strconv.Atoi(s)
if err != nil {
// If parsing fails, return 0 instead of error
*fi = 0
return nil
}
*fi = FlexibleInt(parsed)
return nil
}
return fmt.Errorf("cannot unmarshal %s into FlexibleInt", string(data))
}
type KinopoiskService struct {
apiKey string
baseURL string
@@ -84,7 +122,7 @@ type KPFilmShort struct {
NameOriginal string `json:"nameOriginal"`
ImdbId string `json:"imdbId"`
Type string `json:"type"`
Year string `json:"year"`
Year FlexibleInt `json:"year"`
Description string `json:"description"`
FilmLength string `json:"filmLength"`
Countries []KPCountry `json:"countries"`
@@ -183,6 +221,7 @@ func (s *KinopoiskService) SearchFilms(keyword string, page int) (*KPSearchRespo
func (s *KinopoiskService) GetCollection(collectionType string, page int) (*KPSearchResponse, error) {
endpoint := fmt.Sprintf("%s/v2.2/films/collections?type=%s&page=%d", s.baseURL, collectionType, page)
// Try new format first
var responseNew struct {
Total int `json:"total"`
TotalPages int `json:"totalPages"`
@@ -190,11 +229,7 @@ func (s *KinopoiskService) GetCollection(collectionType string, page int) (*KPSe
}
err := s.makeRequest(endpoint, &responseNew)
if err != nil {
return nil, err
}
if len(responseNew.Items) > 0 {
if err == nil && len(responseNew.Items) > 0 {
return &KPSearchResponse{
PagesCount: responseNew.TotalPages,
Films: responseNew.Items,
@@ -202,6 +237,7 @@ func (s *KinopoiskService) GetCollection(collectionType string, page int) (*KPSe
}, nil
}
// Try old format if new format failed or returned empty
var responseOld struct {
PagesCount int `json:"pagesCount"`
Films []KPFilmShort `json:"films"`

View File

@@ -321,17 +321,10 @@ func mapKPFilmShortToMovie(film KPFilmShort) *models.Movie {
})
}
// Year is a string, convert to int
year := 0
if film.Year != "" {
if parsedYear, err := strconv.Atoi(film.Year); err == nil {
year = parsedYear
}
}
// Year is FlexibleInt, convert to int
releaseDate := ""
if year > 0 {
releaseDate = fmt.Sprintf("%d-01-01", year)
if int(film.Year) > 0 {
releaseDate = fmt.Sprintf("%d-01-01", int(film.Year))
}
// Приоритет: PosterUrlPreview > PosterUrl
@@ -397,16 +390,10 @@ func mapKPFilmShortToTVShow(film KPFilmShort) *models.TVShow {
})
}
// Year is a string, convert to int
year := 0
if film.Year != "" {
if parsedYear, err := strconv.Atoi(film.Year); err == nil {
year = parsedYear
}
}
// Year is FlexibleInt, convert to int
releaseDate := ""
if year > 0 {
releaseDate = fmt.Sprintf("%d-01-01", year)
if int(film.Year) > 0 {
releaseDate = fmt.Sprintf("%d-01-01", int(film.Year))
}
posterPath := film.PosterUrlPreview