192 lines
4.9 KiB
Go
192 lines
4.9 KiB
Go
package radarr
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/lucperkins/rek"
|
|
|
|
"github.com/l3uddz/nabarr"
|
|
"github.com/l3uddz/nabarr/media"
|
|
"github.com/l3uddz/nabarr/util"
|
|
)
|
|
|
|
var (
|
|
ErrItemNotFound = errors.New("not found")
|
|
)
|
|
|
|
func (c *Client) getSystemStatus() (*systemStatus, error) {
|
|
// send request
|
|
resp, err := rek.Get(util.JoinURL(c.apiURL, "system", "status"), rek.Client(c.http), rek.Headers(c.apiHeaders))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request system status: %w", err)
|
|
}
|
|
defer resp.Body().Close()
|
|
|
|
// validate response
|
|
if resp.StatusCode() != 200 {
|
|
return nil, fmt.Errorf("validate system status response: %s", resp.Status())
|
|
}
|
|
|
|
// decode response
|
|
b := new(systemStatus)
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
return nil, fmt.Errorf("decode system status response: %w", err)
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
func (c *Client) getQualityProfileId(profileName string) (int, error) {
|
|
// send request
|
|
resp, err := rek.Get(util.JoinURL(c.apiURL, "qualityprofile"), rek.Client(c.http), rek.Headers(c.apiHeaders))
|
|
if err != nil {
|
|
return 0, fmt.Errorf("request quality profiles: %w", err)
|
|
}
|
|
defer resp.Body().Close()
|
|
|
|
// validate response
|
|
if resp.StatusCode() != 200 {
|
|
return 0, fmt.Errorf("validate quality profiles response: %s", resp.Status())
|
|
}
|
|
|
|
// decode response
|
|
b := new([]qualityProfile)
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
return 0, fmt.Errorf("decode quality profiles response: %w", err)
|
|
}
|
|
|
|
// find quality profile
|
|
for _, profile := range *b {
|
|
if strings.EqualFold(profile.Name, profileName) {
|
|
return profile.Id, nil
|
|
}
|
|
}
|
|
|
|
return 0, errors.New("quality profile not found")
|
|
}
|
|
|
|
func (c *Client) lookupMediaItem(item *media.Item) (*lookupRequest, error) {
|
|
// retrieve and validate media provider data
|
|
mdp, mdi := item.GetProviderData()
|
|
if mdp == "" || mdi == "" {
|
|
return nil, fmt.Errorf("no media provider details found")
|
|
}
|
|
|
|
// prepare request
|
|
reqUrl, err := util.URLWithQuery(util.JoinURL(c.apiURL, "movie", "lookup"),
|
|
url.Values{"term": []string{fmt.Sprintf("%s:%s", mdp, mdi)}})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("generate movie lookup request url: %w", err)
|
|
}
|
|
|
|
// send request
|
|
resp, err := rek.Get(reqUrl, rek.Client(c.http), rek.Headers(c.apiHeaders))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request movie lookup: %w", err)
|
|
}
|
|
defer resp.Body().Close()
|
|
|
|
// validate response
|
|
if resp.StatusCode() != 200 {
|
|
return nil, fmt.Errorf("validate movie lookup response: %s", resp.Status())
|
|
}
|
|
|
|
// decode response
|
|
b := new([]lookupRequest)
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
return nil, fmt.Errorf("decode movie lookup response: %w", err)
|
|
}
|
|
|
|
// find movie
|
|
for _, s := range *b {
|
|
switch mdp {
|
|
case "tmdb":
|
|
if strconv.Itoa(s.TmdbId) == mdi {
|
|
return &s, nil
|
|
}
|
|
default:
|
|
if s.ImdbId == mdi {
|
|
return &s, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("movie lookup %sId: %v: %w", mdp, mdi, ErrItemNotFound)
|
|
}
|
|
|
|
func (c *Client) getExclusions() (map[int]exclusion, error) {
|
|
// send request
|
|
resp, err := rek.Get(util.JoinURL(c.apiURL, "exclusions"), rek.Client(c.http), rek.Headers(c.apiHeaders))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("request exclusions: %w", err)
|
|
}
|
|
defer resp.Body().Close()
|
|
|
|
// validate response
|
|
if resp.StatusCode() != 200 {
|
|
return nil, fmt.Errorf("validate exclusions response: %s", resp.Status())
|
|
}
|
|
|
|
// decode response
|
|
b := new([]exclusion)
|
|
if err := json.NewDecoder(resp.Body()).Decode(b); err != nil {
|
|
return nil, fmt.Errorf("decode exclusions response: %w", err)
|
|
}
|
|
|
|
// generate exclusion map
|
|
exclusions := make(map[int]exclusion)
|
|
for n := range *b {
|
|
e := (*b)[n]
|
|
exclusions[e.TmdbId] = e
|
|
}
|
|
|
|
return exclusions, nil
|
|
}
|
|
|
|
func (c *Client) AddMediaItem(item *media.Item, opts ...nabarr.PvrOption) error {
|
|
// prepare options
|
|
o, err := nabarr.BuildPvrOptions(opts...)
|
|
if err != nil {
|
|
return fmt.Errorf("build options: %v: %w", item.TmdbId, err)
|
|
}
|
|
|
|
// prepare request
|
|
req := addRequest{
|
|
Title: item.Title,
|
|
TitleSlug: item.Slug,
|
|
Year: item.Year,
|
|
QualityProfileId: c.qualityProfileId,
|
|
Images: []string{},
|
|
Monitored: o.AddMonitored,
|
|
RootFolderPath: c.rootFolder,
|
|
MinimumAvailability: "released",
|
|
AddOptions: addOptions{
|
|
SearchForMovie: o.SearchMissing,
|
|
IgnoreEpisodesWithFiles: false,
|
|
IgnoreEpisodesWithoutFiles: false,
|
|
},
|
|
TmdbId: util.Atoi(item.TmdbId, 0),
|
|
ImdbId: item.ImdbId,
|
|
}
|
|
|
|
// send request
|
|
resp, err := rek.Post(util.JoinURL(c.apiURL, "movie"), rek.Client(c.http), rek.Headers(c.apiHeaders),
|
|
rek.Json(req))
|
|
if err != nil {
|
|
return fmt.Errorf("request add movie: %w", err)
|
|
}
|
|
defer resp.Body().Close()
|
|
|
|
// validate response
|
|
if resp.StatusCode() != 200 && resp.StatusCode() != 201 {
|
|
return fmt.Errorf("validate add movie response: %s", resp.Status())
|
|
}
|
|
|
|
return nil
|
|
}
|