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 }