golift.io/starr@v1.0.0/radarr/movie.go (about)

     1  package radarr
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/json"
     7  	"fmt"
     8  	"net/url"
     9  	"path"
    10  	"time"
    11  
    12  	"golift.io/starr"
    13  )
    14  
    15  const bpMovie = APIver + "/movie"
    16  
    17  // Movie is the /api/v3/movie endpoint.
    18  type Movie struct {
    19  	ID                    int64               `json:"id"`
    20  	Title                 string              `json:"title,omitempty"`
    21  	Path                  string              `json:"path,omitempty"`
    22  	MinimumAvailability   Availability        `json:"minimumAvailability,omitempty"`
    23  	QualityProfileID      int64               `json:"qualityProfileId,omitempty"`
    24  	TmdbID                int64               `json:"tmdbId,omitempty"`
    25  	OriginalTitle         string              `json:"originalTitle,omitempty"`
    26  	AlternateTitles       []*AlternativeTitle `json:"alternateTitles,omitempty"`
    27  	SecondaryYearSourceID int                 `json:"secondaryYearSourceId,omitempty"`
    28  	SortTitle             string              `json:"sortTitle,omitempty"`
    29  	SizeOnDisk            int64               `json:"sizeOnDisk,omitempty"`
    30  	Status                string              `json:"status,omitempty"`
    31  	Overview              string              `json:"overview,omitempty"`
    32  	InCinemas             time.Time           `json:"inCinemas,omitempty"`
    33  	PhysicalRelease       time.Time           `json:"physicalRelease,omitempty"`
    34  	DigitalRelease        time.Time           `json:"digitalRelease,omitempty"`
    35  	Images                []*starr.Image      `json:"images,omitempty"`
    36  	Website               string              `json:"website,omitempty"`
    37  	Year                  int                 `json:"year,omitempty"`
    38  	YouTubeTrailerID      string              `json:"youTubeTrailerId,omitempty"`
    39  	Studio                string              `json:"studio,omitempty"`
    40  	FolderName            string              `json:"folderName,omitempty"`
    41  	Runtime               int                 `json:"runtime,omitempty"`
    42  	CleanTitle            string              `json:"cleanTitle,omitempty"`
    43  	ImdbID                string              `json:"imdbId,omitempty"`
    44  	TitleSlug             string              `json:"titleSlug,omitempty"`
    45  	Certification         string              `json:"certification,omitempty"`
    46  	Genres                []string            `json:"genres,omitempty"`
    47  	Tags                  []int               `json:"tags,omitempty"`
    48  	Added                 time.Time           `json:"added,omitempty"`
    49  	Ratings               starr.OpenRatings   `json:"ratings,omitempty"`
    50  	MovieFile             *MovieFile          `json:"movieFile,omitempty"`
    51  	Collection            *Collection         `json:"collection,omitempty"`
    52  	HasFile               bool                `json:"hasFile,omitempty"`
    53  	IsAvailable           bool                `json:"isAvailable,omitempty"`
    54  	Monitored             bool                `json:"monitored"`
    55  	Popularity            float64             `json:"popularity"`
    56  	OriginalLanguage      *starr.Value        `json:"originalLanguage,omitempty"`
    57  	AddOptions            *AddMovieOptions    `json:"addOptions,omitempty"` // only available upon adding a movie.
    58  }
    59  
    60  // Collection belongs to a Movie.
    61  type Collection struct {
    62  	Name   string         `json:"name"`
    63  	TmdbID int64          `json:"tmdbId"`
    64  	Images []*starr.Image `json:"images"`
    65  }
    66  
    67  // AddMovieInput is the input for a new movie.
    68  type AddMovieInput struct {
    69  	Title               string           `json:"title,omitempty"`
    70  	TitleSlug           string           `json:"titleSlug,omitempty"`
    71  	MinimumAvailability Availability     `json:"minimumAvailability,omitempty"`
    72  	RootFolderPath      string           `json:"rootFolderPath"`
    73  	TmdbID              int64            `json:"tmdbId"`
    74  	QualityProfileID    int64            `json:"qualityProfileId"`
    75  	ProfileID           int64            `json:"profileId,omitempty"`
    76  	Year                int              `json:"year,omitempty"`
    77  	Images              []*starr.Image   `json:"images,omitempty"`
    78  	AddOptions          *AddMovieOptions `json:"addOptions"`
    79  	Tags                []int            `json:"tags,omitempty"`
    80  	Monitored           bool             `json:"monitored"`
    81  }
    82  
    83  // AddMovieOptions are the options for finding a new movie.
    84  type AddMovieOptions struct {
    85  	SearchForMovie bool `json:"searchForMovie"`
    86  	// Allowed values: "movieOnly", "movieAndCollection", "none"
    87  	Monitor string `json:"monitor,omitempty"`
    88  }
    89  
    90  // AlternativeTitle is part of a Movie.
    91  type AlternativeTitle struct {
    92  	MovieMetadataID int64        `json:"movieMetadataId"`
    93  	MovieID         int64        `json:"movieId"`
    94  	Title           string       `json:"title"`
    95  	SourceType      string       `json:"sourceType"`
    96  	SourceID        int64        `json:"sourceId"`
    97  	Votes           int          `json:"votes"`
    98  	VoteCount       int          `json:"voteCount"`
    99  	Language        *starr.Value `json:"language"`
   100  	ID              int64        `json:"id"`
   101  }
   102  
   103  // GetMovie grabs a movie from the queue, or all movies if tmdbId is 0.
   104  func (r *Radarr) GetMovie(tmdbID int64) ([]*Movie, error) {
   105  	return r.GetMovieContext(context.Background(), tmdbID)
   106  }
   107  
   108  // GetMovieContext grabs a movie from the queue, or all movies if tmdbId is 0.
   109  func (r *Radarr) GetMovieContext(ctx context.Context, tmdbID int64) ([]*Movie, error) {
   110  	params := make(url.Values)
   111  	if tmdbID != 0 {
   112  		params.Set("tmdbId", fmt.Sprint(tmdbID))
   113  	}
   114  
   115  	var output []*Movie
   116  
   117  	req := starr.Request{URI: bpMovie, Query: params}
   118  	if err := r.GetInto(ctx, req, &output); err != nil {
   119  		return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
   120  	}
   121  
   122  	return output, nil
   123  }
   124  
   125  // GetMovieByID grabs a movie from the database by DB [movie] ID.
   126  func (r *Radarr) GetMovieByID(movieID int64) (*Movie, error) {
   127  	return r.GetMovieByIDContext(context.Background(), movieID)
   128  }
   129  
   130  // GetMovieByIDContext grabs a movie from the database by DB [movie] ID.
   131  func (r *Radarr) GetMovieByIDContext(ctx context.Context, movieID int64) (*Movie, error) {
   132  	var output Movie
   133  
   134  	req := starr.Request{URI: path.Join(bpMovie, fmt.Sprint(movieID))}
   135  	if err := r.GetInto(ctx, req, &output); err != nil {
   136  		return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
   137  	}
   138  
   139  	return &output, nil
   140  }
   141  
   142  // UpdateMovie sends a PUT request to update a movie in place.
   143  func (r *Radarr) UpdateMovie(movieID int64, movie *Movie, moveFiles bool) (*Movie, error) {
   144  	return r.UpdateMovieContext(context.Background(), movieID, movie, moveFiles)
   145  }
   146  
   147  // UpdateMovieContext sends a PUT request to update a movie in place.
   148  func (r *Radarr) UpdateMovieContext(ctx context.Context, movieID int64, movie *Movie, moveFiles bool) (*Movie, error) {
   149  	var body bytes.Buffer
   150  	if err := json.NewEncoder(&body).Encode(movie); err != nil {
   151  		return nil, fmt.Errorf("json.Marshal(%s): %w", bpMovie, err)
   152  	}
   153  
   154  	var output Movie
   155  
   156  	req := starr.Request{
   157  		URI:   path.Join(bpMovie, fmt.Sprint(movieID)),
   158  		Query: make(url.Values),
   159  		Body:  &body,
   160  	}
   161  	req.Query.Add("moveFiles", fmt.Sprint(moveFiles))
   162  
   163  	if err := r.PutInto(ctx, req, &output); err != nil {
   164  		return nil, fmt.Errorf("api.Put(%s): %w", &req, err)
   165  	}
   166  
   167  	return &output, nil
   168  }
   169  
   170  // AddMovie adds a movie to the queue.
   171  func (r *Radarr) AddMovie(movie *AddMovieInput) (*Movie, error) {
   172  	return r.AddMovieContext(context.Background(), movie)
   173  }
   174  
   175  // AddMovieContext adds a movie to the queue.
   176  func (r *Radarr) AddMovieContext(ctx context.Context, movie *AddMovieInput) (*Movie, error) {
   177  	var body bytes.Buffer
   178  	if err := json.NewEncoder(&body).Encode(movie); err != nil {
   179  		return nil, fmt.Errorf("json.Marshal(%s): %w", bpMovie, err)
   180  	}
   181  
   182  	var output Movie
   183  
   184  	req := starr.Request{URI: bpMovie, Query: make(url.Values), Body: &body}
   185  	if err := r.PostInto(ctx, req, &output); err != nil {
   186  		return nil, fmt.Errorf("api.Post(%s): %w", &req, err)
   187  	}
   188  
   189  	return &output, nil
   190  }
   191  
   192  // Lookup will search for movies matching the specified search term.
   193  func (r *Radarr) Lookup(term string) ([]*Movie, error) {
   194  	return r.LookupContext(context.Background(), term)
   195  }
   196  
   197  // LookupContext will search for movies matching the specified search term.
   198  func (r *Radarr) LookupContext(ctx context.Context, term string) ([]*Movie, error) {
   199  	var output []*Movie
   200  
   201  	if term == "" {
   202  		return output, nil
   203  	}
   204  
   205  	req := starr.Request{URI: path.Join(bpMovie, "lookup"), Query: make(url.Values)}
   206  	req.Query.Set("term", term)
   207  
   208  	if err := r.GetInto(ctx, req, &output); err != nil {
   209  		return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
   210  	}
   211  
   212  	return output, nil
   213  }
   214  
   215  // LookupID will return a movie by its ID.
   216  func (r *Radarr) LookupID(movieID int64) (*Movie, error) {
   217  	return r.LookupIDContext(context.Background(), movieID)
   218  }
   219  
   220  // LookupIDContext will return a movie by its ID using a context.
   221  func (r *Radarr) LookupIDContext(ctx context.Context, movieID int64) (*Movie, error) {
   222  	return r.lookupSubContext(ctx, fmt.Sprint(movieID), "", "")
   223  }
   224  
   225  // LookupIMDB will search IMDB for the imdbId provided.
   226  func (r *Radarr) LookupIMDB(imdbID string) (*Movie, error) {
   227  	return r.LookupIMDBContext(context.Background(), imdbID)
   228  }
   229  
   230  // LookupIMDBContext will search IMDB for the imdbId provided using a context.
   231  func (r *Radarr) LookupIMDBContext(ctx context.Context, imdbID string) (*Movie, error) {
   232  	return r.lookupSubContext(ctx, "imdb", "imdbId", imdbID)
   233  }
   234  
   235  // LookupTMDB will search TMDB for the tmdbID provided.
   236  func (r *Radarr) LookupTMDB(tmdbID int64) (*Movie, error) {
   237  	return r.LookupTMDBContext(context.Background(), tmdbID)
   238  }
   239  
   240  // LookupTMDBContext will search TMDB for the tmdbID provided using a context.
   241  func (r *Radarr) LookupTMDBContext(ctx context.Context, tmdbID int64) (*Movie, error) {
   242  	return r.lookupSubContext(ctx, "tmdb", "tmdbId", fmt.Sprint(tmdbID))
   243  }
   244  
   245  // lookupSubContext abstracts lookup requests.
   246  func (r *Radarr) lookupSubContext(ctx context.Context, sub, name, val string) (*Movie, error) {
   247  	var output *Movie
   248  
   249  	req := starr.Request{URI: path.Join(bpMovie, "lookup", sub), Query: make(url.Values)}
   250  
   251  	if name != "" {
   252  		req.Query.Set(name, val)
   253  	}
   254  
   255  	if err := r.GetInto(ctx, req, &output); err != nil {
   256  		return nil, fmt.Errorf("api.Get(%s): %w", &req, err)
   257  	}
   258  
   259  	return output, nil
   260  }
   261  
   262  // DeleteMovie removes a movie from the database. Setting deleteFiles true will delete all content for the movie.
   263  func (r *Radarr) DeleteMovie(movieID int64, deleteFiles, addImportExclusion bool) error {
   264  	return r.DeleteMovieContext(context.Background(), movieID, deleteFiles, addImportExclusion)
   265  }
   266  
   267  // DeleteMovieContext removes a movie from the database. Setting deleteFiles true will delete all content for the movie.
   268  func (r *Radarr) DeleteMovieContext(ctx context.Context, movieID int64, deleteFiles, addImportExclusion bool) error {
   269  	req := starr.Request{URI: path.Join(bpMovie, fmt.Sprint(movieID)), Query: make(url.Values)}
   270  	req.Query.Set("deleteFiles", fmt.Sprint(deleteFiles))
   271  	req.Query.Set("addImportExclusion", fmt.Sprint(addImportExclusion))
   272  
   273  	if err := r.DeleteAny(ctx, req); err != nil {
   274  		return fmt.Errorf("api.Delete(%s): %w", &req, err)
   275  	}
   276  
   277  	return nil
   278  }