kv-netflix/backend/internal/service/tmdb.go

137 lines
3.2 KiB
Go

package service
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"time"
)
const (
TMDBBaseURL = "https://api.themoviedb.org/3"
TMDBImageBaseURL = "https://image.tmdb.org/t/p"
)
type TMDBService struct {
client *http.Client
apiKey string
}
func NewTMDBService() *TMDBService {
return &TMDBService{
client: &http.Client{Timeout: 10 * time.Second},
apiKey: os.Getenv("TMDB_API_KEY"),
}
}
type TMDBMovieResult struct {
ID int `json:"id"`
Title string `json:"title"`
Overview string `json:"overview"`
PosterPath string `json:"poster_path"`
BackdropPath string `json:"backdrop_path"`
ReleaseDate string `json:"release_date"`
VoteAverage float64 `json:"vote_average"`
}
type TMDBSearchResponse struct {
Results []TMDBMovieResult `json:"results"`
}
type TMDBMovieDetails struct {
ID int `json:"id"`
Title string `json:"title"`
Overview string `json:"overview"`
Runtime int `json:"runtime"`
Budget int64 `json:"budget"`
Revenue int64 `json:"revenue"`
Tagline string `json:"tagline"`
VoteAverage float64 `json:"vote_average"`
PosterPath string `json:"poster_path"`
BackdropPath string `json:"backdrop_path"`
Credits struct {
Cast []struct {
Name string `json:"name"`
Character string `json:"character"`
ProfilePath string `json:"profile_path"`
} `json:"cast"`
Crew []struct {
Name string `json:"name"`
Job string `json:"job"`
} `json:"crew"`
} `json:"credits"`
}
func (s *TMDBService) SearchMovie(title string, year int) (*TMDBMovieResult, error) {
if s.apiKey == "" {
return nil, fmt.Errorf("TMDB_API_KEY not set")
}
params := url.Values{}
params.Add("api_key", s.apiKey)
params.Add("query", title)
params.Add("language", "en-US")
if year > 0 {
params.Add("year", fmt.Sprintf("%d", year))
}
resp, err := s.client.Get(fmt.Sprintf("%s/search/movie?%s", TMDBBaseURL, params.Encode()))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("TMDB API returned status: %d", resp.StatusCode)
}
var searchResp TMDBSearchResponse
if err := json.NewDecoder(resp.Body).Decode(&searchResp); err != nil {
return nil, err
}
if len(searchResp.Results) > 0 {
return &searchResp.Results[0], nil
}
return nil, nil
}
func (s *TMDBService) GetMovieDetails(tmdbID int) (*TMDBMovieDetails, error) {
if s.apiKey == "" {
return nil, fmt.Errorf("TMDB_API_KEY not set")
}
params := url.Values{}
params.Add("api_key", s.apiKey)
params.Add("append_to_response", "credits")
params.Add("language", "en-US")
resp, err := s.client.Get(fmt.Sprintf("%s/movie/%d?%s", TMDBBaseURL, tmdbID, params.Encode()))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("TMDB API returned status: %d", resp.StatusCode)
}
var details TMDBMovieDetails
if err := json.NewDecoder(resp.Body).Decode(&details); err != nil {
return nil, err
}
return &details, nil
}
func (s *TMDBService) GetPosterURL(path string, size string) string {
if path == "" {
return ""
}
if size == "" {
size = "w500"
}
return fmt.Sprintf("%s/%s%s", TMDBImageBaseURL, size, path)
}