mirror of
https://gitlab.com/foxixus/neomovies-api.git
synced 2025-10-28 01:48:51 +05:00
425 lines
9.6 KiB
Go
425 lines
9.6 KiB
Go
package services
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"neomovies-api/pkg/models"
|
|
)
|
|
|
|
func MapKPFilmToTMDBMovie(kpFilm *KPFilm) *models.Movie {
|
|
if kpFilm == nil {
|
|
return nil
|
|
}
|
|
|
|
releaseDate := ""
|
|
if kpFilm.Year > 0 {
|
|
releaseDate = fmt.Sprintf("%d-01-01", kpFilm.Year)
|
|
}
|
|
|
|
genres := make([]models.Genre, 0)
|
|
for _, g := range kpFilm.Genres {
|
|
genres = append(genres, models.Genre{
|
|
ID: 0,
|
|
Name: g.Genre,
|
|
})
|
|
}
|
|
|
|
countries := make([]models.ProductionCountry, 0)
|
|
for _, c := range kpFilm.Countries {
|
|
countries = append(countries, models.ProductionCountry{
|
|
ISO31661: "",
|
|
Name: c.Country,
|
|
})
|
|
}
|
|
|
|
posterPath := ""
|
|
if kpFilm.PosterUrlPreview != "" {
|
|
posterPath = kpFilm.PosterUrlPreview
|
|
} else if kpFilm.PosterUrl != "" {
|
|
posterPath = kpFilm.PosterUrl
|
|
}
|
|
|
|
backdropPath := ""
|
|
if kpFilm.CoverUrl != "" {
|
|
backdropPath = kpFilm.CoverUrl
|
|
}
|
|
|
|
overview := kpFilm.Description
|
|
if overview == "" {
|
|
overview = kpFilm.ShortDescription
|
|
}
|
|
|
|
title := kpFilm.NameRu
|
|
if title == "" {
|
|
title = kpFilm.NameEn
|
|
}
|
|
if title == "" {
|
|
title = kpFilm.NameOriginal
|
|
}
|
|
|
|
originalTitle := kpFilm.NameOriginal
|
|
if originalTitle == "" {
|
|
originalTitle = kpFilm.NameEn
|
|
}
|
|
|
|
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,
|
|
ProductionCountries: countries,
|
|
IMDbID: kpFilm.ImdbId,
|
|
KinopoiskID: kpFilm.KinopoiskId,
|
|
}
|
|
}
|
|
|
|
func MapKPFilmToTVShow(kpFilm *KPFilm) *models.TVShow {
|
|
if kpFilm == nil {
|
|
return nil
|
|
}
|
|
|
|
firstAirDate := ""
|
|
if kpFilm.StartYear > 0 {
|
|
firstAirDate = fmt.Sprintf("%d-01-01", kpFilm.StartYear)
|
|
}
|
|
|
|
lastAirDate := ""
|
|
if kpFilm.EndYear > 0 {
|
|
lastAirDate = fmt.Sprintf("%d-01-01", kpFilm.EndYear)
|
|
}
|
|
|
|
genres := make([]models.Genre, 0)
|
|
for _, g := range kpFilm.Genres {
|
|
genres = append(genres, models.Genre{
|
|
ID: 0,
|
|
Name: g.Genre,
|
|
})
|
|
}
|
|
|
|
posterPath := ""
|
|
if kpFilm.PosterUrlPreview != "" {
|
|
posterPath = kpFilm.PosterUrlPreview
|
|
} else if kpFilm.PosterUrl != "" {
|
|
posterPath = kpFilm.PosterUrl
|
|
}
|
|
|
|
backdropPath := ""
|
|
if kpFilm.CoverUrl != "" {
|
|
backdropPath = kpFilm.CoverUrl
|
|
}
|
|
|
|
overview := kpFilm.Description
|
|
if overview == "" {
|
|
overview = kpFilm.ShortDescription
|
|
}
|
|
|
|
name := kpFilm.NameRu
|
|
if name == "" {
|
|
name = kpFilm.NameEn
|
|
}
|
|
if name == "" {
|
|
name = kpFilm.NameOriginal
|
|
}
|
|
|
|
originalName := kpFilm.NameOriginal
|
|
if originalName == "" {
|
|
originalName = kpFilm.NameEn
|
|
}
|
|
|
|
status := "Ended"
|
|
if kpFilm.Completed {
|
|
status = "Ended"
|
|
} else {
|
|
status = "Returning Series"
|
|
}
|
|
|
|
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),
|
|
OriginalLanguage: detectLanguage(kpFilm),
|
|
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
|
|
}
|
|
|
|
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})
|
|
}
|
|
|
|
poster := kpFilm.PosterUrlPreview
|
|
if poster == "" {
|
|
poster = kpFilm.PosterUrl
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
var budgetPtr *int64
|
|
var revenuePtr *int64
|
|
|
|
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,
|
|
}
|
|
}
|
|
|
|
func mapKPTypeToUnified(kp *KPFilm) string {
|
|
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 ""
|
|
}
|
|
|
|
func MapKPSearchToTMDBResponse(kpSearch *KPSearchResponse) *models.TMDBResponse {
|
|
if kpSearch == nil {
|
|
return &models.TMDBResponse{
|
|
Page: 1,
|
|
Results: []models.Movie{},
|
|
TotalPages: 0,
|
|
TotalResults: 0,
|
|
}
|
|
}
|
|
|
|
results := make([]models.Movie, 0)
|
|
for _, film := range kpSearch.Films {
|
|
movie := mapKPFilmShortToMovie(film)
|
|
if movie != nil {
|
|
results = append(results, *movie)
|
|
}
|
|
}
|
|
|
|
totalPages := kpSearch.PagesCount
|
|
if totalPages == 0 && len(results) > 0 {
|
|
totalPages = 1
|
|
}
|
|
|
|
return &models.TMDBResponse{
|
|
Page: 1,
|
|
Results: results,
|
|
TotalPages: totalPages,
|
|
TotalResults: kpSearch.SearchFilmsCountResult,
|
|
}
|
|
}
|
|
|
|
func mapKPFilmShortToMovie(film KPFilmShort) *models.Movie {
|
|
genres := make([]models.Genre, 0)
|
|
for _, g := range film.Genres {
|
|
genres = append(genres, models.Genre{
|
|
ID: 0,
|
|
Name: g.Genre,
|
|
})
|
|
}
|
|
|
|
year := 0
|
|
if film.Year != "" {
|
|
year, _ = strconv.Atoi(film.Year)
|
|
}
|
|
|
|
releaseDate := ""
|
|
if year > 0 {
|
|
releaseDate = fmt.Sprintf("%d-01-01", year)
|
|
}
|
|
|
|
posterPath := film.PosterUrlPreview
|
|
if posterPath == "" {
|
|
posterPath = film.PosterUrl
|
|
}
|
|
|
|
title := film.NameRu
|
|
if title == "" {
|
|
title = film.NameEn
|
|
}
|
|
|
|
originalTitle := film.NameEn
|
|
if originalTitle == "" {
|
|
originalTitle = film.NameRu
|
|
}
|
|
|
|
rating := 0.0
|
|
if film.Rating != "" {
|
|
rating, _ = strconv.ParseFloat(film.Rating, 64)
|
|
}
|
|
|
|
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,
|
|
}
|
|
}
|
|
|
|
func detectLanguage(film *KPFilm) string {
|
|
if film.NameRu != "" {
|
|
return "ru"
|
|
}
|
|
if film.NameEn != "" {
|
|
return "en"
|
|
}
|
|
return "ru"
|
|
}
|
|
|
|
func MapKPExternalIDsToTMDB(kpFilm *KPFilm) *models.ExternalIDs {
|
|
if kpFilm == nil {
|
|
return &models.ExternalIDs{}
|
|
}
|
|
|
|
return &models.ExternalIDs{
|
|
ID: kpFilm.KinopoiskId,
|
|
IMDbID: kpFilm.ImdbId,
|
|
KinopoiskID: kpFilm.KinopoiskId,
|
|
}
|
|
}
|
|
|
|
func ShouldUseKinopoisk(language string) bool {
|
|
if language == "" {
|
|
return false
|
|
}
|
|
lang := strings.ToLower(language)
|
|
return strings.HasPrefix(lang, "ru")
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
func ConvertKPRatingToTMDB(kpRating float64) float64 {
|
|
return kpRating
|
|
}
|
|
|
|
func FormatKPDate(year int) string {
|
|
if year <= 0 {
|
|
return time.Now().Format("2006-01-02")
|
|
}
|
|
return fmt.Sprintf("%d-01-01", year)
|
|
}
|
|
|
|
// EnrichKPWithTMDBID обогащает KP контент TMDB ID через IMDB ID
|
|
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
|
|
}
|
|
}
|
|
|
|
// EnrichKPSearchItemsWithTMDBID обогащает массив поисковых элементов TMDB ID
|
|
func EnrichKPSearchItemsWithTMDBID(items []models.UnifiedSearchItem, tmdbService *TMDBService) {
|
|
for i := range items {
|
|
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
|
|
}
|
|
}
|
|
}
|