mirror of
https://gitlab.com/foxixus/neomovies-api.git
synced 2025-12-15 20:16:10 +05:00
simplify proxy
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"neomovies-api/pkg/models"
|
||||
"neomovies-api/pkg/models"
|
||||
)
|
||||
|
||||
func MapKPFilmToTMDBMovie(kpFilm *KPFilm) *models.Movie {
|
||||
@@ -66,24 +66,24 @@ func MapKPFilmToTMDBMovie(kpFilm *KPFilm) *models.Movie {
|
||||
}
|
||||
|
||||
return &models.Movie{
|
||||
ID: kpFilm.KinopoiskId,
|
||||
Title: title,
|
||||
OriginalTitle: originalTitle,
|
||||
Overview: overview,
|
||||
PosterPath: posterPath,
|
||||
BackdropPath: backdropPath,
|
||||
ReleaseDate: releaseDate,
|
||||
VoteAverage: kpFilm.RatingKinopoisk,
|
||||
VoteCount: kpFilm.RatingKinopoiskVoteCount,
|
||||
Popularity: float64(kpFilm.RatingKinopoisk * 100),
|
||||
Adult: false,
|
||||
OriginalLanguage: detectLanguage(kpFilm),
|
||||
Runtime: kpFilm.FilmLength,
|
||||
Genres: genres,
|
||||
Tagline: kpFilm.Slogan,
|
||||
ID: kpFilm.KinopoiskId,
|
||||
Title: title,
|
||||
OriginalTitle: originalTitle,
|
||||
Overview: overview,
|
||||
PosterPath: posterPath,
|
||||
BackdropPath: backdropPath,
|
||||
ReleaseDate: releaseDate,
|
||||
VoteAverage: kpFilm.RatingKinopoisk,
|
||||
VoteCount: kpFilm.RatingKinopoiskVoteCount,
|
||||
Popularity: float64(kpFilm.RatingKinopoisk * 100),
|
||||
Adult: false,
|
||||
OriginalLanguage: detectLanguage(kpFilm),
|
||||
Runtime: kpFilm.FilmLength,
|
||||
Genres: genres,
|
||||
Tagline: kpFilm.Slogan,
|
||||
ProductionCountries: countries,
|
||||
IMDbID: kpFilm.ImdbId,
|
||||
KinopoiskID: kpFilm.KinopoiskId,
|
||||
IMDbID: kpFilm.ImdbId,
|
||||
KinopoiskID: kpFilm.KinopoiskId,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,106 +148,106 @@ func MapKPFilmToTVShow(kpFilm *KPFilm) *models.TVShow {
|
||||
}
|
||||
|
||||
return &models.TVShow{
|
||||
ID: kpFilm.KinopoiskId,
|
||||
Name: name,
|
||||
OriginalName: originalName,
|
||||
Overview: overview,
|
||||
PosterPath: posterPath,
|
||||
BackdropPath: backdropPath,
|
||||
FirstAirDate: firstAirDate,
|
||||
LastAirDate: lastAirDate,
|
||||
VoteAverage: kpFilm.RatingKinopoisk,
|
||||
VoteCount: kpFilm.RatingKinopoiskVoteCount,
|
||||
Popularity: float64(kpFilm.RatingKinopoisk * 100),
|
||||
ID: kpFilm.KinopoiskId,
|
||||
Name: name,
|
||||
OriginalName: originalName,
|
||||
Overview: overview,
|
||||
PosterPath: posterPath,
|
||||
BackdropPath: backdropPath,
|
||||
FirstAirDate: firstAirDate,
|
||||
LastAirDate: lastAirDate,
|
||||
VoteAverage: kpFilm.RatingKinopoisk,
|
||||
VoteCount: kpFilm.RatingKinopoiskVoteCount,
|
||||
Popularity: float64(kpFilm.RatingKinopoisk * 100),
|
||||
OriginalLanguage: detectLanguage(kpFilm),
|
||||
Genres: genres,
|
||||
Status: status,
|
||||
InProduction: !kpFilm.Completed,
|
||||
KinopoiskID: kpFilm.KinopoiskId,
|
||||
Genres: genres,
|
||||
Status: status,
|
||||
InProduction: !kpFilm.Completed,
|
||||
KinopoiskID: kpFilm.KinopoiskId,
|
||||
}
|
||||
}
|
||||
|
||||
// Unified mappers with prefixed IDs
|
||||
func MapKPToUnified(kpFilm *KPFilm) *models.UnifiedContent {
|
||||
if kpFilm == nil {
|
||||
return nil
|
||||
}
|
||||
if kpFilm == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
releaseDate := FormatKPDate(kpFilm.Year)
|
||||
endDate := (*string)(nil)
|
||||
if kpFilm.EndYear > 0 {
|
||||
v := FormatKPDate(kpFilm.EndYear)
|
||||
endDate = &v
|
||||
}
|
||||
releaseDate := FormatKPDate(kpFilm.Year)
|
||||
endDate := (*string)(nil)
|
||||
if kpFilm.EndYear > 0 {
|
||||
v := FormatKPDate(kpFilm.EndYear)
|
||||
endDate = &v
|
||||
}
|
||||
|
||||
genres := make([]models.UnifiedGenre, 0)
|
||||
for _, g := range kpFilm.Genres {
|
||||
genres = append(genres, models.UnifiedGenre{ID: strings.ToLower(g.Genre), Name: g.Genre})
|
||||
}
|
||||
genres := make([]models.UnifiedGenre, 0)
|
||||
for _, g := range kpFilm.Genres {
|
||||
genres = append(genres, models.UnifiedGenre{ID: strings.ToLower(g.Genre), Name: g.Genre})
|
||||
}
|
||||
|
||||
poster := kpFilm.PosterUrlPreview
|
||||
if poster == "" {
|
||||
poster = kpFilm.PosterUrl
|
||||
}
|
||||
poster := kpFilm.PosterUrlPreview
|
||||
if poster == "" {
|
||||
poster = kpFilm.PosterUrl
|
||||
}
|
||||
|
||||
country := ""
|
||||
if len(kpFilm.Countries) > 0 {
|
||||
country = kpFilm.Countries[0].Country
|
||||
}
|
||||
country := ""
|
||||
if len(kpFilm.Countries) > 0 {
|
||||
country = kpFilm.Countries[0].Country
|
||||
}
|
||||
|
||||
title := kpFilm.NameRu
|
||||
if title == "" {
|
||||
title = kpFilm.NameEn
|
||||
}
|
||||
originalTitle := kpFilm.NameOriginal
|
||||
if originalTitle == "" {
|
||||
originalTitle = kpFilm.NameEn
|
||||
}
|
||||
title := kpFilm.NameRu
|
||||
if title == "" {
|
||||
title = kpFilm.NameEn
|
||||
}
|
||||
originalTitle := kpFilm.NameOriginal
|
||||
if originalTitle == "" {
|
||||
originalTitle = kpFilm.NameEn
|
||||
}
|
||||
|
||||
var budgetPtr *int64
|
||||
var revenuePtr *int64
|
||||
var budgetPtr *int64
|
||||
var revenuePtr *int64
|
||||
|
||||
external := models.UnifiedExternalIDs{KP: &kpFilm.KinopoiskId, TMDB: nil, IMDb: kpFilm.ImdbId}
|
||||
external := models.UnifiedExternalIDs{KP: &kpFilm.KinopoiskId, TMDB: nil, IMDb: kpFilm.ImdbId}
|
||||
|
||||
return &models.UnifiedContent{
|
||||
ID: strconv.Itoa(kpFilm.KinopoiskId),
|
||||
SourceID: "kp_" + strconv.Itoa(kpFilm.KinopoiskId),
|
||||
Title: title,
|
||||
OriginalTitle: originalTitle,
|
||||
Description: firstNonEmpty(kpFilm.Description, kpFilm.ShortDescription),
|
||||
ReleaseDate: releaseDate,
|
||||
EndDate: endDate,
|
||||
Type: mapKPTypeToUnified(kpFilm),
|
||||
Genres: genres,
|
||||
Rating: kpFilm.RatingKinopoisk,
|
||||
PosterURL: BuildAPIImageProxyURL(poster, "w500"),
|
||||
BackdropURL: BuildAPIImageProxyURL(kpFilm.CoverUrl, "w1280"),
|
||||
Director: "",
|
||||
Cast: []models.UnifiedCastMember{},
|
||||
Duration: kpFilm.FilmLength,
|
||||
Country: country,
|
||||
Language: detectLanguage(kpFilm),
|
||||
Budget: budgetPtr,
|
||||
Revenue: revenuePtr,
|
||||
IMDbID: kpFilm.ImdbId,
|
||||
ExternalIDs: external,
|
||||
}
|
||||
return &models.UnifiedContent{
|
||||
ID: strconv.Itoa(kpFilm.KinopoiskId),
|
||||
SourceID: "kp_" + strconv.Itoa(kpFilm.KinopoiskId),
|
||||
Title: title,
|
||||
OriginalTitle: originalTitle,
|
||||
Description: firstNonEmpty(kpFilm.Description, kpFilm.ShortDescription),
|
||||
ReleaseDate: releaseDate,
|
||||
EndDate: endDate,
|
||||
Type: mapKPTypeToUnified(kpFilm),
|
||||
Genres: genres,
|
||||
Rating: kpFilm.RatingKinopoisk,
|
||||
PosterURL: BuildAPIImageProxyURL(poster, "w300"),
|
||||
BackdropURL: BuildAPIImageProxyURL(kpFilm.CoverUrl, "w1280"),
|
||||
Director: "",
|
||||
Cast: []models.UnifiedCastMember{},
|
||||
Duration: kpFilm.FilmLength,
|
||||
Country: country,
|
||||
Language: detectLanguage(kpFilm),
|
||||
Budget: budgetPtr,
|
||||
Revenue: revenuePtr,
|
||||
IMDbID: kpFilm.ImdbId,
|
||||
ExternalIDs: external,
|
||||
}
|
||||
}
|
||||
|
||||
func mapKPTypeToUnified(kp *KPFilm) string {
|
||||
if kp.Serial || kp.Type == "TV_SERIES" || kp.Type == "MINI_SERIES" {
|
||||
return "tv"
|
||||
}
|
||||
return "movie"
|
||||
if kp.Serial || kp.Type == "TV_SERIES" || kp.Type == "MINI_SERIES" {
|
||||
return "tv"
|
||||
}
|
||||
return "movie"
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, v := range values {
|
||||
if strings.TrimSpace(v) != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
for _, v := range values {
|
||||
if strings.TrimSpace(v) != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func MapKPSearchToTMDBResponse(kpSearch *KPSearchResponse) *models.TMDBResponse {
|
||||
@@ -321,17 +321,17 @@ func mapKPFilmShortToMovie(film KPFilmShort) *models.Movie {
|
||||
}
|
||||
|
||||
return &models.Movie{
|
||||
ID: film.FilmId,
|
||||
Title: title,
|
||||
OriginalTitle: originalTitle,
|
||||
Overview: film.Description,
|
||||
PosterPath: posterPath,
|
||||
ReleaseDate: releaseDate,
|
||||
VoteAverage: rating,
|
||||
VoteCount: film.RatingVoteCount,
|
||||
Popularity: rating * 100,
|
||||
Genres: genres,
|
||||
KinopoiskID: film.FilmId,
|
||||
ID: film.FilmId,
|
||||
Title: title,
|
||||
OriginalTitle: originalTitle,
|
||||
Overview: film.Description,
|
||||
PosterPath: posterPath,
|
||||
ReleaseDate: releaseDate,
|
||||
VoteAverage: rating,
|
||||
VoteCount: film.RatingVoteCount,
|
||||
Popularity: rating * 100,
|
||||
Genres: genres,
|
||||
KinopoiskID: film.FilmId,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,12 +369,12 @@ func NormalizeLanguage(language string) string {
|
||||
if language == "" {
|
||||
return "en-US"
|
||||
}
|
||||
|
||||
|
||||
lang := strings.ToLower(language)
|
||||
if strings.HasPrefix(lang, "ru") {
|
||||
return "ru-RU"
|
||||
}
|
||||
|
||||
|
||||
return "en-US"
|
||||
}
|
||||
|
||||
@@ -394,12 +394,12 @@ func EnrichKPWithTMDBID(content *models.UnifiedContent, tmdbService *TMDBService
|
||||
if content == nil || content.IMDbID == "" || content.ExternalIDs.TMDB != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
mediaType := "movie"
|
||||
if content.Type == "tv" {
|
||||
mediaType = "tv"
|
||||
}
|
||||
|
||||
|
||||
if tmdbID, err := tmdbService.FindTMDBIdByIMDB(content.IMDbID, mediaType, "ru-RU"); err == nil {
|
||||
content.ExternalIDs.TMDB = &tmdbID
|
||||
}
|
||||
@@ -411,12 +411,12 @@ func EnrichKPSearchItemsWithTMDBID(items []models.UnifiedSearchItem, tmdbService
|
||||
if items[i].ExternalIDs.IMDb == "" || items[i].ExternalIDs.TMDB != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
mediaType := "movie"
|
||||
if items[i].Type == "tv" {
|
||||
mediaType = "tv"
|
||||
}
|
||||
|
||||
|
||||
if tmdbID, err := tmdbService.FindTMDBIdByIMDB(items[i].ExternalIDs.IMDb, mediaType, "ru-RU"); err == nil {
|
||||
items[i].ExternalIDs.TMDB = &tmdbID
|
||||
}
|
||||
|
||||
@@ -1,275 +1,291 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"neomovies-api/pkg/models"
|
||||
"neomovies-api/pkg/models"
|
||||
)
|
||||
|
||||
const tmdbImageBase = "https://image.tmdb.org/t/p"
|
||||
|
||||
// BuildAPIImageProxyURL строит относительный URL до нашего прокси-эндпоинта изображений.
|
||||
// Если передан абсолютный URL (KP и пр.) — он кодируется и передаётся как path параметр.
|
||||
// Если передан относительный TMDB-путь, он используется как есть (без ведущего '/').
|
||||
func BuildAPIImageProxyURL(pathOrURL string, size string) string {
|
||||
if strings.TrimSpace(pathOrURL) == "" {
|
||||
return ""
|
||||
}
|
||||
if size == "" {
|
||||
size = "w500"
|
||||
}
|
||||
// Абсолютные ссылки (Kinopoisk и пр.) — кодируем целиком
|
||||
if strings.HasPrefix(pathOrURL, "http://") || strings.HasPrefix(pathOrURL, "https://") {
|
||||
return fmt.Sprintf("/api/v1/images/%s/%s", size, url.QueryEscape(pathOrURL))
|
||||
}
|
||||
// TMDB относительный путь
|
||||
clean := pathOrURL
|
||||
if strings.HasPrefix(clean, "/") {
|
||||
clean = clean[1:]
|
||||
}
|
||||
return fmt.Sprintf("/api/v1/images/%s/%s", size, clean)
|
||||
if strings.TrimSpace(pathOrURL) == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Extract type and ID from Kinopoisk URL pattern
|
||||
// https://kinopoiskapiunofficial.tech/images/posters/{type}/{id}.jpg
|
||||
if strings.Contains(pathOrURL, "kinopoiskapiunofficial.tech") {
|
||||
parts := strings.Split(pathOrURL, "/")
|
||||
if len(parts) >= 2 {
|
||||
// Find "posters" index
|
||||
for i, part := range parts {
|
||||
if part == "posters" && i+2 < len(parts) {
|
||||
imageType := parts[i+1] // kp, kp_small, kp_big
|
||||
idWithExt := parts[i+2] // 326.jpg
|
||||
imageID := strings.TrimSuffix(idWithExt, ".jpg")
|
||||
|
||||
// Map size to type if needed
|
||||
if size == "w1280" || size == "original" {
|
||||
imageType = "kp_big"
|
||||
} else if size == "w300" || size == "w185" {
|
||||
imageType = "kp_small"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("/api/v1/images/%s/%s", imageType, imageID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Yandex/other absolute URLs - return empty for now
|
||||
if strings.HasPrefix(pathOrURL, "http://") || strings.HasPrefix(pathOrURL, "https://") {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TMDB relative path - not supported in new format
|
||||
return ""
|
||||
}
|
||||
|
||||
func MapTMDBToUnifiedMovie(movie *models.Movie, external *models.ExternalIDs) *models.UnifiedContent {
|
||||
if movie == nil {
|
||||
return nil
|
||||
}
|
||||
if movie == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
genres := make([]models.UnifiedGenre, 0, len(movie.Genres))
|
||||
for _, g := range movie.Genres {
|
||||
name := strings.TrimSpace(g.Name)
|
||||
id := strings.ToLower(strings.ReplaceAll(name, " ", "-"))
|
||||
if id == "" {
|
||||
id = strconv.Itoa(g.ID)
|
||||
}
|
||||
genres = append(genres, models.UnifiedGenre{ID: id, Name: name})
|
||||
}
|
||||
genres := make([]models.UnifiedGenre, 0, len(movie.Genres))
|
||||
for _, g := range movie.Genres {
|
||||
name := strings.TrimSpace(g.Name)
|
||||
id := strings.ToLower(strings.ReplaceAll(name, " ", "-"))
|
||||
if id == "" {
|
||||
id = strconv.Itoa(g.ID)
|
||||
}
|
||||
genres = append(genres, models.UnifiedGenre{ID: id, Name: name})
|
||||
}
|
||||
|
||||
var imdb string
|
||||
if external != nil {
|
||||
imdb = external.IMDbID
|
||||
}
|
||||
var imdb string
|
||||
if external != nil {
|
||||
imdb = external.IMDbID
|
||||
}
|
||||
|
||||
var budgetPtr *int64
|
||||
if movie.Budget > 0 {
|
||||
v := movie.Budget
|
||||
budgetPtr = &v
|
||||
}
|
||||
var revenuePtr *int64
|
||||
if movie.Revenue > 0 {
|
||||
v := movie.Revenue
|
||||
revenuePtr = &v
|
||||
}
|
||||
var budgetPtr *int64
|
||||
if movie.Budget > 0 {
|
||||
v := movie.Budget
|
||||
budgetPtr = &v
|
||||
}
|
||||
var revenuePtr *int64
|
||||
if movie.Revenue > 0 {
|
||||
v := movie.Revenue
|
||||
revenuePtr = &v
|
||||
}
|
||||
|
||||
ext := models.UnifiedExternalIDs{
|
||||
KP: nil,
|
||||
TMDB: &movie.ID,
|
||||
IMDb: imdb,
|
||||
}
|
||||
ext := models.UnifiedExternalIDs{
|
||||
KP: nil,
|
||||
TMDB: &movie.ID,
|
||||
IMDb: imdb,
|
||||
}
|
||||
|
||||
return &models.UnifiedContent{
|
||||
ID: strconv.Itoa(movie.ID),
|
||||
SourceID: "tmdb_" + strconv.Itoa(movie.ID),
|
||||
Title: movie.Title,
|
||||
OriginalTitle: movie.OriginalTitle,
|
||||
Description: movie.Overview,
|
||||
ReleaseDate: movie.ReleaseDate,
|
||||
EndDate: nil,
|
||||
Type: "movie",
|
||||
Genres: genres,
|
||||
Rating: movie.VoteAverage,
|
||||
PosterURL: BuildAPIImageProxyURL(movie.PosterPath, "w500"),
|
||||
BackdropURL: BuildAPIImageProxyURL(movie.BackdropPath, "w1280"),
|
||||
Director: "",
|
||||
Cast: []models.UnifiedCastMember{},
|
||||
Duration: movie.Runtime,
|
||||
Country: firstCountry(movie.ProductionCountries),
|
||||
Language: movie.OriginalLanguage,
|
||||
Budget: budgetPtr,
|
||||
Revenue: revenuePtr,
|
||||
IMDbID: imdb,
|
||||
ExternalIDs: ext,
|
||||
}
|
||||
return &models.UnifiedContent{
|
||||
ID: strconv.Itoa(movie.ID),
|
||||
SourceID: "tmdb_" + strconv.Itoa(movie.ID),
|
||||
Title: movie.Title,
|
||||
OriginalTitle: movie.OriginalTitle,
|
||||
Description: movie.Overview,
|
||||
ReleaseDate: movie.ReleaseDate,
|
||||
EndDate: nil,
|
||||
Type: "movie",
|
||||
Genres: genres,
|
||||
Rating: movie.VoteAverage,
|
||||
PosterURL: BuildAPIImageProxyURL(movie.PosterPath, "w300"),
|
||||
BackdropURL: BuildAPIImageProxyURL(movie.BackdropPath, "w1280"),
|
||||
Director: "",
|
||||
Cast: []models.UnifiedCastMember{},
|
||||
Duration: movie.Runtime,
|
||||
Country: firstCountry(movie.ProductionCountries),
|
||||
Language: movie.OriginalLanguage,
|
||||
Budget: budgetPtr,
|
||||
Revenue: revenuePtr,
|
||||
IMDbID: imdb,
|
||||
ExternalIDs: ext,
|
||||
}
|
||||
}
|
||||
|
||||
func MapTMDBTVToUnified(tv *models.TVShow, external *models.ExternalIDs) *models.UnifiedContent {
|
||||
if tv == nil {
|
||||
return nil
|
||||
}
|
||||
if tv == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
genres := make([]models.UnifiedGenre, 0, len(tv.Genres))
|
||||
for _, g := range tv.Genres {
|
||||
name := strings.TrimSpace(g.Name)
|
||||
id := strings.ToLower(strings.ReplaceAll(name, " ", "-"))
|
||||
if id == "" {
|
||||
id = strconv.Itoa(g.ID)
|
||||
}
|
||||
genres = append(genres, models.UnifiedGenre{ID: id, Name: name})
|
||||
}
|
||||
genres := make([]models.UnifiedGenre, 0, len(tv.Genres))
|
||||
for _, g := range tv.Genres {
|
||||
name := strings.TrimSpace(g.Name)
|
||||
id := strings.ToLower(strings.ReplaceAll(name, " ", "-"))
|
||||
if id == "" {
|
||||
id = strconv.Itoa(g.ID)
|
||||
}
|
||||
genres = append(genres, models.UnifiedGenre{ID: id, Name: name})
|
||||
}
|
||||
|
||||
var imdb string
|
||||
if external != nil {
|
||||
imdb = external.IMDbID
|
||||
}
|
||||
var imdb string
|
||||
if external != nil {
|
||||
imdb = external.IMDbID
|
||||
}
|
||||
|
||||
endDate := (*string)(nil)
|
||||
if strings.TrimSpace(tv.LastAirDate) != "" {
|
||||
v := tv.LastAirDate
|
||||
endDate = &v
|
||||
}
|
||||
endDate := (*string)(nil)
|
||||
if strings.TrimSpace(tv.LastAirDate) != "" {
|
||||
v := tv.LastAirDate
|
||||
endDate = &v
|
||||
}
|
||||
|
||||
ext := models.UnifiedExternalIDs{
|
||||
KP: nil,
|
||||
TMDB: &tv.ID,
|
||||
IMDb: imdb,
|
||||
}
|
||||
ext := models.UnifiedExternalIDs{
|
||||
KP: nil,
|
||||
TMDB: &tv.ID,
|
||||
IMDb: imdb,
|
||||
}
|
||||
|
||||
duration := 0
|
||||
if len(tv.EpisodeRunTime) > 0 {
|
||||
duration = tv.EpisodeRunTime[0]
|
||||
}
|
||||
duration := 0
|
||||
if len(tv.EpisodeRunTime) > 0 {
|
||||
duration = tv.EpisodeRunTime[0]
|
||||
}
|
||||
|
||||
unified := &models.UnifiedContent{
|
||||
ID: strconv.Itoa(tv.ID),
|
||||
SourceID: "tmdb_" + strconv.Itoa(tv.ID),
|
||||
Title: tv.Name,
|
||||
OriginalTitle: tv.OriginalName,
|
||||
Description: tv.Overview,
|
||||
ReleaseDate: tv.FirstAirDate,
|
||||
EndDate: endDate,
|
||||
Type: "tv",
|
||||
Genres: genres,
|
||||
Rating: tv.VoteAverage,
|
||||
PosterURL: BuildAPIImageProxyURL(tv.PosterPath, "w500"),
|
||||
BackdropURL: BuildAPIImageProxyURL(tv.BackdropPath, "w1280"),
|
||||
Director: "",
|
||||
Cast: []models.UnifiedCastMember{},
|
||||
Duration: duration,
|
||||
Country: firstCountry(tv.ProductionCountries),
|
||||
Language: tv.OriginalLanguage,
|
||||
Budget: nil,
|
||||
Revenue: nil,
|
||||
IMDbID: imdb,
|
||||
ExternalIDs: ext,
|
||||
}
|
||||
unified := &models.UnifiedContent{
|
||||
ID: strconv.Itoa(tv.ID),
|
||||
SourceID: "tmdb_" + strconv.Itoa(tv.ID),
|
||||
Title: tv.Name,
|
||||
OriginalTitle: tv.OriginalName,
|
||||
Description: tv.Overview,
|
||||
ReleaseDate: tv.FirstAirDate,
|
||||
EndDate: endDate,
|
||||
Type: "tv",
|
||||
Genres: genres,
|
||||
Rating: tv.VoteAverage,
|
||||
PosterURL: BuildAPIImageProxyURL(tv.PosterPath, "w300"),
|
||||
BackdropURL: BuildAPIImageProxyURL(tv.BackdropPath, "w1280"),
|
||||
Director: "",
|
||||
Cast: []models.UnifiedCastMember{},
|
||||
Duration: duration,
|
||||
Country: firstCountry(tv.ProductionCountries),
|
||||
Language: tv.OriginalLanguage,
|
||||
Budget: nil,
|
||||
Revenue: nil,
|
||||
IMDbID: imdb,
|
||||
ExternalIDs: ext,
|
||||
}
|
||||
|
||||
// Map seasons basic info
|
||||
if len(tv.Seasons) > 0 {
|
||||
unified.Seasons = make([]models.UnifiedSeason, 0, len(tv.Seasons))
|
||||
for _, s := range tv.Seasons {
|
||||
unified.Seasons = append(unified.Seasons, models.UnifiedSeason{
|
||||
ID: strconv.Itoa(s.ID),
|
||||
SourceID: "tmdb_" + strconv.Itoa(s.ID),
|
||||
Name: s.Name,
|
||||
SeasonNumber: s.SeasonNumber,
|
||||
EpisodeCount: s.EpisodeCount,
|
||||
ReleaseDate: s.AirDate,
|
||||
PosterURL: BuildAPIImageProxyURL(s.PosterPath, "w500"),
|
||||
})
|
||||
}
|
||||
}
|
||||
// Map seasons basic info
|
||||
if len(tv.Seasons) > 0 {
|
||||
unified.Seasons = make([]models.UnifiedSeason, 0, len(tv.Seasons))
|
||||
for _, s := range tv.Seasons {
|
||||
unified.Seasons = append(unified.Seasons, models.UnifiedSeason{
|
||||
ID: strconv.Itoa(s.ID),
|
||||
SourceID: "tmdb_" + strconv.Itoa(s.ID),
|
||||
Name: s.Name,
|
||||
SeasonNumber: s.SeasonNumber,
|
||||
EpisodeCount: s.EpisodeCount,
|
||||
ReleaseDate: s.AirDate,
|
||||
PosterURL: BuildAPIImageProxyURL(s.PosterPath, "w300"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return unified
|
||||
return unified
|
||||
}
|
||||
|
||||
func MapTMDBMultiToUnifiedItems(m *models.MultiSearchResponse) []models.UnifiedSearchItem {
|
||||
if m == nil {
|
||||
return []models.UnifiedSearchItem{}
|
||||
}
|
||||
items := make([]models.UnifiedSearchItem, 0, len(m.Results))
|
||||
for _, r := range m.Results {
|
||||
if r.MediaType != "movie" && r.MediaType != "tv" {
|
||||
continue
|
||||
}
|
||||
title := r.Title
|
||||
if r.MediaType == "tv" {
|
||||
title = r.Name
|
||||
}
|
||||
release := r.ReleaseDate
|
||||
if r.MediaType == "tv" {
|
||||
release = r.FirstAirDate
|
||||
}
|
||||
poster := BuildAPIImageProxyURL(r.PosterPath, "w500")
|
||||
tmdbId := r.ID
|
||||
items = append(items, models.UnifiedSearchItem{
|
||||
ID: strconv.Itoa(tmdbId),
|
||||
SourceID: "tmdb_" + strconv.Itoa(tmdbId),
|
||||
Title: title,
|
||||
Type: map[string]string{"movie":"movie","tv":"tv"}[r.MediaType],
|
||||
ReleaseDate: release,
|
||||
PosterURL: poster,
|
||||
Rating: r.VoteAverage,
|
||||
Description: r.Overview,
|
||||
ExternalIDs: models.UnifiedExternalIDs{KP: nil, TMDB: &tmdbId, IMDb: ""},
|
||||
})
|
||||
}
|
||||
return items
|
||||
if m == nil {
|
||||
return []models.UnifiedSearchItem{}
|
||||
}
|
||||
items := make([]models.UnifiedSearchItem, 0, len(m.Results))
|
||||
for _, r := range m.Results {
|
||||
if r.MediaType != "movie" && r.MediaType != "tv" {
|
||||
continue
|
||||
}
|
||||
title := r.Title
|
||||
if r.MediaType == "tv" {
|
||||
title = r.Name
|
||||
}
|
||||
release := r.ReleaseDate
|
||||
if r.MediaType == "tv" {
|
||||
release = r.FirstAirDate
|
||||
}
|
||||
poster := BuildAPIImageProxyURL(r.PosterPath, "w300")
|
||||
tmdbId := r.ID
|
||||
items = append(items, models.UnifiedSearchItem{
|
||||
ID: strconv.Itoa(tmdbId),
|
||||
SourceID: "tmdb_" + strconv.Itoa(tmdbId),
|
||||
Title: title,
|
||||
Type: map[string]string{"movie": "movie", "tv": "tv"}[r.MediaType],
|
||||
ReleaseDate: release,
|
||||
PosterURL: poster,
|
||||
Rating: r.VoteAverage,
|
||||
Description: r.Overview,
|
||||
ExternalIDs: models.UnifiedExternalIDs{KP: nil, TMDB: &tmdbId, IMDb: ""},
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func MapKPSearchToUnifiedItems(kps *KPSearchResponse) []models.UnifiedSearchItem {
|
||||
if kps == nil {
|
||||
return []models.UnifiedSearchItem{}
|
||||
}
|
||||
items := make([]models.UnifiedSearchItem, 0, len(kps.Films))
|
||||
for _, f := range kps.Films {
|
||||
title := f.NameRu
|
||||
if strings.TrimSpace(title) == "" {
|
||||
title = f.NameEn
|
||||
}
|
||||
poster := f.PosterUrlPreview
|
||||
if poster == "" {
|
||||
poster = f.PosterUrl
|
||||
}
|
||||
poster = BuildAPIImageProxyURL(poster, "w500")
|
||||
rating := 0.0
|
||||
if strings.TrimSpace(f.Rating) != "" {
|
||||
if v, err := strconv.ParseFloat(f.Rating, 64); err == nil {
|
||||
rating = v
|
||||
}
|
||||
}
|
||||
kpId := f.FilmId
|
||||
items = append(items, models.UnifiedSearchItem{
|
||||
ID: strconv.Itoa(kpId),
|
||||
SourceID: "kp_" + strconv.Itoa(kpId),
|
||||
Title: title,
|
||||
Type: mapKPTypeToUnifiedShort(f.Type),
|
||||
OriginalType: strings.ToUpper(strings.TrimSpace(f.Type)),
|
||||
ReleaseDate: yearToDate(f.Year),
|
||||
PosterURL: poster,
|
||||
Rating: rating,
|
||||
Description: f.Description,
|
||||
ExternalIDs: models.UnifiedExternalIDs{KP: &kpId, TMDB: nil, IMDb: ""},
|
||||
})
|
||||
}
|
||||
return items
|
||||
if kps == nil {
|
||||
return []models.UnifiedSearchItem{}
|
||||
}
|
||||
items := make([]models.UnifiedSearchItem, 0, len(kps.Films))
|
||||
for _, f := range kps.Films {
|
||||
title := f.NameRu
|
||||
if strings.TrimSpace(title) == "" {
|
||||
title = f.NameEn
|
||||
}
|
||||
poster := f.PosterUrlPreview
|
||||
if poster == "" {
|
||||
poster = f.PosterUrl
|
||||
}
|
||||
poster = BuildAPIImageProxyURL(poster, "w300")
|
||||
rating := 0.0
|
||||
if strings.TrimSpace(f.Rating) != "" {
|
||||
if v, err := strconv.ParseFloat(f.Rating, 64); err == nil {
|
||||
rating = v
|
||||
}
|
||||
}
|
||||
kpId := f.FilmId
|
||||
items = append(items, models.UnifiedSearchItem{
|
||||
ID: strconv.Itoa(kpId),
|
||||
SourceID: "kp_" + strconv.Itoa(kpId),
|
||||
Title: title,
|
||||
Type: mapKPTypeToUnifiedShort(f.Type),
|
||||
OriginalType: strings.ToUpper(strings.TrimSpace(f.Type)),
|
||||
ReleaseDate: yearToDate(f.Year),
|
||||
PosterURL: poster,
|
||||
Rating: rating,
|
||||
Description: f.Description,
|
||||
ExternalIDs: models.UnifiedExternalIDs{KP: &kpId, TMDB: nil, IMDb: ""},
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func mapKPTypeToUnifiedShort(t string) string {
|
||||
switch strings.ToUpper(strings.TrimSpace(t)) {
|
||||
case "TV_SERIES", "MINI_SERIES":
|
||||
return "tv"
|
||||
default:
|
||||
return "movie"
|
||||
}
|
||||
switch strings.ToUpper(strings.TrimSpace(t)) {
|
||||
case "TV_SERIES", "MINI_SERIES":
|
||||
return "tv"
|
||||
default:
|
||||
return "movie"
|
||||
}
|
||||
}
|
||||
|
||||
func yearToDate(y string) string {
|
||||
y = strings.TrimSpace(y)
|
||||
if y == "" {
|
||||
return ""
|
||||
}
|
||||
return y + "-01-01"
|
||||
y = strings.TrimSpace(y)
|
||||
if y == "" {
|
||||
return ""
|
||||
}
|
||||
return y + "-01-01"
|
||||
}
|
||||
|
||||
func firstCountry(countries []models.ProductionCountry) string {
|
||||
if len(countries) == 0 {
|
||||
return ""
|
||||
}
|
||||
if strings.TrimSpace(countries[0].Name) != "" {
|
||||
return countries[0].Name
|
||||
}
|
||||
return countries[0].ISO31661
|
||||
if len(countries) == 0 {
|
||||
return ""
|
||||
}
|
||||
if strings.TrimSpace(countries[0].Name) != "" {
|
||||
return countries[0].Name
|
||||
}
|
||||
return countries[0].ISO31661
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user