2026-03-03 16:53:54 +00:00
|
|
|
package tmdb
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/url"
|
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
|
|
"github.com/lucperkins/rek"
|
|
|
|
|
|
|
|
|
|
"github.com/l3uddz/nabarr/util"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var ErrItemNotFound = errors.New("not found")
|
|
|
|
|
|
|
|
|
|
func (c *Client) SearchMovies(title string, year int) (int, error) {
|
|
|
|
|
vals := url.Values{
|
|
|
|
|
"api_key": []string{c.apiKey},
|
|
|
|
|
"query": []string{title},
|
|
|
|
|
}
|
|
|
|
|
if year > 0 {
|
|
|
|
|
vals.Set("year", strconv.Itoa(year))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "search", "movie"), vals)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("generate search movie url: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp, err := rek.Get(reqUrl, rek.Client(c.http))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("request search movie: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer resp.Body().Close()
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode() != 200 {
|
|
|
|
|
return 0, fmt.Errorf("validate search movie response: %s", resp.Status())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b := new(movieSearchResponse)
|
|
|
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
|
|
|
return 0, fmt.Errorf("decode search movie response: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(b.Results) < 1 {
|
|
|
|
|
return 0, ErrItemNotFound
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.Results[0].Id, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-03 18:44:56 +00:00
|
|
|
func (c *Client) GetMovieExternalIds(tmdbId int) (string, error) {
|
|
|
|
|
reqUrl := util.JoinURL(c.apiURL, "movie", strconv.Itoa(tmdbId), "external_ids") + "?api_key=" + c.apiKey
|
|
|
|
|
|
|
|
|
|
resp, err := rek.Get(reqUrl, rek.Client(c.http))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", fmt.Errorf("request movie external ids: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer resp.Body().Close()
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode() != 200 {
|
|
|
|
|
return "", fmt.Errorf("validate movie external ids response: %s", resp.Status())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b := new(externalIdsResponse)
|
|
|
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
|
|
|
return "", fmt.Errorf("decode movie external ids response: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.ImdbId, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *Client) GetShowExternalIds(tmdbId int) (string, error) {
|
|
|
|
|
reqUrl := util.JoinURL(c.apiURL, "tv", strconv.Itoa(tmdbId), "external_ids") + "?api_key=" + c.apiKey
|
|
|
|
|
|
|
|
|
|
resp, err := rek.Get(reqUrl, rek.Client(c.http))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", fmt.Errorf("request show external ids: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer resp.Body().Close()
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode() != 200 {
|
|
|
|
|
return "", fmt.Errorf("validate show external ids response: %s", resp.Status())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b := new(externalIdsResponse)
|
|
|
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
|
|
|
return "", fmt.Errorf("decode show external ids response: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.ImdbId, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-03 16:53:54 +00:00
|
|
|
func (c *Client) SearchShows(title string, year int) (int, error) {
|
|
|
|
|
vals := url.Values{
|
|
|
|
|
"api_key": []string{c.apiKey},
|
|
|
|
|
"query": []string{title},
|
|
|
|
|
}
|
|
|
|
|
if year > 0 {
|
|
|
|
|
vals.Set("first_air_date_year", strconv.Itoa(year))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "search", "tv"), vals)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("generate search tv url: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp, err := rek.Get(reqUrl, rek.Client(c.http))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("request search tv: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer resp.Body().Close()
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode() != 200 {
|
|
|
|
|
return 0, fmt.Errorf("validate search tv response: %s", resp.Status())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b := new(tvSearchResponse)
|
|
|
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
|
|
|
return 0, fmt.Errorf("decode search tv response: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(b.Results) < 1 {
|
|
|
|
|
return 0, ErrItemNotFound
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return b.Results[0].Id, nil
|
|
|
|
|
}
|