Files
neomovies-api/pkg/services/movie.go

151 lines
5.2 KiB
Go
Raw Normal View History

2025-08-07 13:47:42 +00:00
package services
import (
fix: Remove TMDB fallback and add ID conversion for strict id_type handling ПРОБЛЕМА: - При id_type='kp' код делал fallback на TMDB если фильм не найден - Если передан TMDB ID с id_type='kp', возвращались данные из TMDB - Нарушалась явная логика выбора источника РЕШЕНИЕ: 1. Убран автоматический fallback на TMDB при id_type='kp' 2. Добавлена конвертация ID: - Если id_type='kp' и фильм не найден напрямую - Пробуем конвертировать TMDB ID → KP ID через TmdbIdToKPId - Запрашиваем данные по сконвертированному KP ID 3. Если конвертация не удалась → возвращаем ошибку ЛОГИКА: - id_type='kp' + ID=550 (TMDB): 1. Поиск KP фильма с id=550 → не найдено 2. Конвертация 550 (TMDB) → получаем KP ID (например 326) 3. Поиск KP фильма с id=326 → успех 4. Возврат данных из Kinopoisk ✅ - id_type='kp' + несуществующий ID: 1. Поиск KP фильма → не найдено 2. Конвертация → не удалась 3. Возврат ошибки (НЕ fallback на TMDB) ✅ ИЗМЕНЕНИЯ: - pkg/services/movie.go: добавлена конвертация и удален fallback - pkg/services/tv.go: добавлена конвертация и удален fallback - Добавлен import fmt для форматирования ошибок РЕЗУЛЬТАТ: ✅ Строгое соблюдение id_type параметра ✅ Умная конвертация между TMDB и KP ID ✅ Нет неожиданного fallback на другой источник
2025-10-18 23:55:42 +00:00
"fmt"
2025-08-07 13:47:42 +00:00
"go.mongodb.org/mongo-driver/mongo"
"neomovies-api/pkg/models"
)
type MovieService struct {
tmdb *TMDBService
kpService *KinopoiskService
2025-08-07 13:47:42 +00:00
}
func NewMovieService(db *mongo.Database, tmdb *TMDBService, kpService *KinopoiskService) *MovieService {
2025-08-07 13:47:42 +00:00
return &MovieService{
tmdb: tmdb,
kpService: kpService,
2025-08-07 13:47:42 +00:00
}
}
func (s *MovieService) Search(query string, page int, language, region string, year int) (*models.TMDBResponse, error) {
if ShouldUseKinopoisk(language) && s.kpService != nil {
kpSearch, err := s.kpService.SearchFilms(query, page)
if err == nil {
return MapKPSearchToTMDBResponse(kpSearch), nil
}
}
2025-08-07 13:47:42 +00:00
return s.tmdb.SearchMovies(query, page, language, region, year)
}
func (s *MovieService) GetByID(id int, language string, idType string) (*models.Movie, error) {
// Строго уважаем явный id_type, без скрытого fallback на TMDB
switch idType {
case "kp":
if s.kpService == nil {
return nil, fmt.Errorf("kinopoisk service not configured")
}
// Сначала пробуем как Kinopoisk ID
if kpFilm, err := s.kpService.GetFilmByKinopoiskId(id); err == nil {
// Попробуем обогатить TMDB фильмом через IMDb -> TMDB find
if kpFilm.ImdbId != "" {
if tmdbID, fErr := s.tmdb.FindTMDBIdByIMDB(kpFilm.ImdbId, "movie", NormalizeLanguage(language)); fErr == nil {
if tmdbMovie, mErr := s.tmdb.GetMovie(tmdbID, NormalizeLanguage(language)); mErr == nil {
return tmdbMovie, nil
}
}
}
return MapKPFilmToTMDBMovie(kpFilm), nil
}
// Возможно пришел TMDB ID — пробуем конвертировать TMDB -> KP
if kpId, convErr := TmdbIdToKPId(s.tmdb, s.kpService, id); convErr == nil {
if kpFilm, err := s.kpService.GetFilmByKinopoiskId(kpId); err == nil {
if kpFilm.ImdbId != "" {
if tmdbID, fErr := s.tmdb.FindTMDBIdByIMDB(kpFilm.ImdbId, "movie", NormalizeLanguage(language)); fErr == nil {
if tmdbMovie, mErr := s.tmdb.GetMovie(tmdbID, NormalizeLanguage(language)); mErr == nil {
return tmdbMovie, nil
}
}
}
return MapKPFilmToTMDBMovie(kpFilm), nil
}
}
// Явно указан KP, но ничего не нашли — возвращаем ошибку
return nil, fmt.Errorf("film not found in Kinopoisk with id %d", id)
case "tmdb":
return s.tmdb.GetMovie(id, language)
}
// Если id_type не указан — старая логика по языку
if ShouldUseKinopoisk(language) && s.kpService != nil {
if kpFilm, err := s.kpService.GetFilmByKinopoiskId(id); err == nil {
return MapKPFilmToTMDBMovie(kpFilm), nil
}
}
return s.tmdb.GetMovie(id, language)
2025-08-07 13:47:42 +00:00
}
func (s *MovieService) GetPopular(page int, language, region string) (*models.TMDBResponse, error) {
if ShouldUseKinopoisk(language) && s.kpService != nil {
kpTop, err := s.kpService.GetTopFilms("TOP_100_POPULAR_FILMS", page)
if err == nil {
return MapKPSearchToTMDBResponse(kpTop), nil
}
}
2025-08-07 13:47:42 +00:00
return s.tmdb.GetPopularMovies(page, language, region)
}
func (s *MovieService) GetTopRated(page int, language, region string) (*models.TMDBResponse, error) {
if ShouldUseKinopoisk(language) && s.kpService != nil {
kpTop, err := s.kpService.GetTopFilms("TOP_250_BEST_FILMS", page)
if err == nil {
return MapKPSearchToTMDBResponse(kpTop), nil
}
}
2025-08-07 13:47:42 +00:00
return s.tmdb.GetTopRatedMovies(page, language, region)
}
func (s *MovieService) GetUpcoming(page int, language, region string) (*models.TMDBResponse, error) {
return s.tmdb.GetUpcomingMovies(page, language, region)
}
func (s *MovieService) GetNowPlaying(page int, language, region string) (*models.TMDBResponse, error) {
return s.tmdb.GetNowPlayingMovies(page, language, region)
}
func (s *MovieService) GetRecommendations(id, page int, language string) (*models.TMDBResponse, error) {
return s.tmdb.GetMovieRecommendations(id, page, language)
}
func (s *MovieService) GetSimilar(id, page int, language string) (*models.TMDBResponse, error) {
return s.tmdb.GetSimilarMovies(id, page, language)
}
func (s *MovieService) GetExternalIDs(id int) (*models.ExternalIDs, error) {
if s.kpService != nil {
kpFilm, err := s.kpService.GetFilmByKinopoiskId(id)
if err == nil && kpFilm != nil {
externalIDs := MapKPExternalIDsToTMDB(kpFilm)
externalIDs.ID = id
// Пытаемся получить TMDB ID через IMDB ID
if kpFilm.ImdbId != "" && s.tmdb != nil {
if tmdbID, tmdbErr := s.tmdb.FindTMDBIdByIMDB(kpFilm.ImdbId, "movie", "ru-RU"); tmdbErr == nil {
externalIDs.TMDBID = tmdbID
}
}
return externalIDs, nil
}
}
tmdbIDs, err := s.tmdb.GetMovieExternalIDs(id)
if err != nil {
return nil, err
}
if s.kpService != nil && tmdbIDs.IMDbID != "" {
kpFilm, err := s.kpService.GetFilmByImdbId(tmdbIDs.IMDbID)
if err == nil && kpFilm != nil {
tmdbIDs.KinopoiskID = kpFilm.KinopoiskId
}
}
return tmdbIDs, nil
}