From 93a398bce256fc39c3eac512c1956a48747f8286 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:47:41 -0700 Subject: [PATCH 01/19] more robust constructseriesjson --- PyArr/sonarr_api.py | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 24764b6..1666014 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -177,12 +177,28 @@ def getQualityProfiles(self): res = self.request_get(path) return res.json() - def constructSeriesJson(self, tvdbId, qualityProfileId): + def constructSeriesJson( + self, + tvdbId, + qualityProfileId, + rootDir, + seasonFolder=True, + monitored=True, + ignoreEpisodesWithFiles=False, + ignoreEpisodesWithoutFiles=False, + searchForMissingEpisodes=False, + ): """Searches for new shows on trakt and returns Series json to add Args: - Required - dbID, + Required - tvdbID (int) Required - qualityProfileId (int) + Required - rootDir (string) + Optional - seasonFolder (boolean) + Optional - monitored (boolean) + Optional - ignoreEpisodesWithFiles (boolean) + Optional - ignoreEpisodesWithoutFiles (boolean) + Optional - searchForMissingEpisodes (boolean) Return: JsonArray @@ -190,22 +206,24 @@ def constructSeriesJson(self, tvdbId, qualityProfileId): """ res = self.lookupSeries(tvdbId) s_dict = res[0] + if monitored == False: + for season in s_dict["seasons"]: + season["monitored"] = False - # get root folder path - root = self.getRoot()[0]["path"] series_json = { "title": s_dict["title"], "seasons": s_dict["seasons"], - "path": root + s_dict["title"], + "path": rootDir + s_dict["title"], "qualityProfileId": qualityProfileId, - "seasonFolder": True, - "monitored": True, + "seasonFolder": seasonFolder, + "monitored": monitored, "tvdbId": tvdbId, "images": s_dict["images"], "titleSlug": s_dict["titleSlug"], "addOptions": { - "ignoreEpisodesWithFiles": True, - "ignoreEpisodesWithoutFiles": True, + "ignoreEpisodesWithFiles": ignoreEpisodesWithFiles, + "ignoreEpisodesWithoutFiles": ignoreEpisodesWithoutFiles, + "searchForMissingEpisodes": searchForMissingEpisodes, }, } return series_json From 23fceaff02bc57ccc8b6252c06a0f554459a1bbf Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:48:49 -0700 Subject: [PATCH 02/19] more robust addSeries --- PyArr/sonarr_api.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 1666014..aa1cb35 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -244,17 +244,42 @@ def getSeries(self, *args): res = self.request_get(path) return res.json() - def addSeries(self, dbId, qualityProfileId): + def addSeries( + self, + tvdbId, + qualityProfileId, + rootDir, + seasonFolder=True, + monitored=True, + ignoreEpisodesWithFiles=False, + ignoreEpisodesWithoutFiles=False, + searchForMissingEpisodes=False, + ): """Add a new series to your collection Args: - Required - dbid - Required - qualityProfileId + Required - tvdbID (int) + Required - qualityProfileId (int) + Required - rootDir (string) + Optional - seasonFolder (boolean) + Optional - monitored (boolean) + Optional - ignoreEpisodesWithFiles (boolean) + Optional - ignoreEpisodesWithoutFiles (boolean) + Optional - searchForMissingEpisodes (boolean) Returns: json response """ - series_json = self.constructSeriesJson(dbId, qualityProfileId) + series_json = self.constructSeriesJson( + tvdbId, + qualityProfileId, + rootDir, + seasonFolder, + monitored, + ignoreEpisodesWithFiles, + ignoreEpisodesWithoutFiles, + searchForMissingEpisodes, + ) path = "/api/series" res = self.request_post(path, data=series_json) From ba92b48841a9bf48631368661b4fd831860c7e51 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:50:33 -0700 Subject: [PATCH 03/19] correct logic on update series fix #45 --- PyArr/sonarr_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index aa1cb35..af9e4d4 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -285,12 +285,11 @@ def addSeries( res = self.request_post(path, data=series_json) return res.json() - # TODO: Test def updSeries(self, data): """Update an existing series""" path = "/api/series" - res = self.request_put(path, data=series_json) + res = self.request_put(path, data) return res.json() def delSeries(self, seriesId, delFiles=False): From 6aaab2c5fe4c72665fe4de51b7b7371a536ce5de Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:52:07 -0700 Subject: [PATCH 04/19] confirm updEpisode works --- PyArr/sonarr_api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index af9e4d4..10d1530 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -405,7 +405,6 @@ def getBackup(self): res = self.request_get(path) return res.json() - # TODO: Test this def updEpisode(self, data): """Update the given episodes, currently only monitored is changed, all other modifications are ignored. All parameters (you should perform a From bff7b8d53a1994de5c78640f12edd002a42d6675 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:53:09 -0700 Subject: [PATCH 05/19] test and rename del_episode_file_by_episode_id --- PyArr/sonarr_api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 10d1530..384ce18 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -450,8 +450,7 @@ def get_episode_file_by_episode_id(self, episode_id): res = self.request_get(path) return res.json() - # TODO: Test this - def rem_episode_file_by_episode_id(self, episode_id): + def del_episode_file_by_episode_id(self, episode_id): """Delete the given episode file Kwargs: From 5ed3d98583d6851cce2decc8002a8827d7aa8cd4 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:55:13 -0700 Subject: [PATCH 06/19] remove get_series_by_series_id (duplicate of getSeries) --- PyArr/sonarr_api.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 384ce18..257652f 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -487,18 +487,3 @@ def push_release(self, **kwargs): path = "/api/release/push" res = self.request_post(path, data=kwargs) return res.json() - - # TODO: Test this - def get_series_by_series_id(self, series_id): - """Return the series with the matching ID or 404 if no matching series - is found - - Args: - series_id (int): - - Returns: - requests.models.Response: Response object form requests. - """ - path = "/api/series/{}".format(series_id) - res = self.request_get(path) - return res.json() From 21874c7794d914366e124ab6ad6a625cdd54aae7 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:56:05 -0700 Subject: [PATCH 07/19] remove serach_selected (not an API passthrough!) --- PyArr/sonarr_api.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 257652f..3b78d09 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -463,10 +463,6 @@ def del_episode_file_by_episode_id(self, episode_id): res = self.request_del(path, data=None) return res.json() - # TODO: Work in progress. - def serach_selected(self): - pass - # TODO: Test this def push_release(self, **kwargs): """Notifies Sonarr of a new release. From ae390516c399d811a1454765c2244cb2a6e83bcc Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 18:57:57 -0700 Subject: [PATCH 08/19] Public setCommand function replaces refreshSeries and rescanSeries --- PyArr/sonarr_api.py | 47 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 36 deletions(-) diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 3b78d09..568a54a 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -66,50 +66,25 @@ def getCommand(self, *args): res = self.request_get(path) return res.json() - def __setCommand(self, data): - """Private Command Method + def setCommand(self, **kwargs): + """Performs any of the predetermined Sonarr command routines. - Args: - data (dict): data payload to send to /api/command - - Returns: - json response - """ - path = "/api/command" - res = self.request_post(path, data) - return res.json() + Kwargs: + Required - name (string). - def refreshSeries(self, *args): - """RefreshSeries refreshes series information and rescans disk. + Options available: RefreshSeries, RescanSeries, EpisodeSearch, SeasonSearch, SeriesSearch, DownloadedEpisodesScan, RssSync, RenameFiles, RenameSeries, Backup, missingEpisodeSearch - Args: - Optional - seriesId (int) + Additional Parameters may be required or optional... + See https://github.com/Sonarr/Sonarr/wiki/Command Returns: json response """ - data = {} - if len(args) == 1: - data.update({"name": "RefreshSeries", "seriesId": args[0]}) - else: - data.update({"name": "RefreshSeries"}) - return self.__setCommand(data) - - def rescanSeries(self, *args): - """RescanSeries scans disk for any downloaded episodes for all or specified series. - - Args: - Optional - seriesId (int) - Returns: - json response + path = "/api/command" - """ - data = {} - if len(args) == 1: - data.update({"name": "RescanSeries", "seriesId": args[0]}) - else: - data.update({"name": "RescanSeries"}) - return self.__setCommand(data) + data = kwargs + res = self.request_post(path, data) + return res.json() def getDiskSpace(self): """GetDiskSpace retrieves info about the disk space on the server. From 6fedddbb10cb8e6e488fc6b82746d5341480e89e Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 19:04:32 -0700 Subject: [PATCH 09/19] Public setCommand function replaces refreshMovie, rescanMovie, and syncRss --- PyArr/radarr_api.py | 62 +++++++++------------------------------------ 1 file changed, 12 insertions(+), 50 deletions(-) diff --git a/PyArr/radarr_api.py b/PyArr/radarr_api.py index 9173667..9cd99b2 100644 --- a/PyArr/radarr_api.py +++ b/PyArr/radarr_api.py @@ -67,63 +67,25 @@ def getCommand(self, *args): res = self.request_get(path) return res.json() - def __setCommand(self, data): - """Private Command Method + def setCommand(self, **kwargs): + """Performs any of the predetermined Radarr command routines. - Args: - data (dict): data payload to send to /api/command - - Returns: - json response - """ - print(data) - path = "/api/command" - res = self.request_post(path, data) - return res.json() - - def refreshMovie(self, *args): - """RefreshMovie refreshes movie information and rescans disk. - - Args: - Optional - movieId (int) - Returns: - json response - - """ - data = {} - if len(args) == 1: - data.update({"name": "RefreshMovie", "movieId": args[0]}) - else: - data.update({"name": "RefreshMovie"}) - return self.__setCommand(data) + Kwargs: + Required - name (string). - def rescanMovie(self, *args): - """RescanMovie scans disk for any downloaded movie for all or specified movie. + Options available: RefreshMovie, RescanMovie, MoviesSearch, DownloadedMoviesScan, RssSync, RenameFiles, RenameMovie, CutOffUnmetMoviesSearch, NetImportSync, missingMoviesSearch - Args: - Optional - movieId (int) + Additional Parameters may be required or optional... + See https://github.com/Radarr/Radarr/wiki/API:Command Returns: - json response + json response """ - data = {} - if len(args) == 1: - data.update({"name": "RescanMovie", "movieId": args[0]}) - else: - data.update({"name": "RescanMovie"}) - return self.__setCommand(data) - - def syncRss(self): - """Instruct Sonarr to perform an RSS sync with all enabled indexers - - Args: - none - Returns: - json response + path = "/api/command" - """ - data = {"name": "RssSync"} - return self.__setCommand(data) + data = kwargs + res = self.request_post(path, data) + return res.json() def getDiskSpace(self): """GetDiskSpace retrieves info about the disk space on the server. From f86347c3eebc725c6bd6331a3f9d9daf30cb691f Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 19:05:36 -0700 Subject: [PATCH 10/19] create updMovie close #27 --- PyArr/radarr_api.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PyArr/radarr_api.py b/PyArr/radarr_api.py index 9cd99b2..95f2d88 100644 --- a/PyArr/radarr_api.py +++ b/PyArr/radarr_api.py @@ -117,6 +117,13 @@ def getMovie(self, *args): res = self.request_get(path) return res.json() + def updMovie(self, data): + """Update an existing movie""" + + path = "/api/movie" + res = self.request_put(path, data) + return res.json() + def lookupMovie(self, term): """lookupMovie serches for movie From fa015da55c00aa318fdcd1e49148bf6cd3337451 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 19:06:28 -0700 Subject: [PATCH 11/19] more robust constructMovieJson --- PyArr/radarr_api.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/PyArr/radarr_api.py b/PyArr/radarr_api.py index 95f2d88..da21ef9 100644 --- a/PyArr/radarr_api.py +++ b/PyArr/radarr_api.py @@ -156,12 +156,17 @@ def getQualityProfiles(self): res = self.request_get(path) return res.json() - def constructMovieJson(self, dbId, qualityProfileId): + def constructMovieJson( + self, dbId, qualityProfileId, rootDir, monitored=True, searchForMovie=True + ): """Searches for movie on tmdb and returns Movie json to add Args: Required - dbID, Required - qualityProfileId (int) + Required - rootDir (string) + Optional - monitored (boolean) + Optional - searchForMovie (boolean) Return: JsonArray @@ -169,18 +174,17 @@ def constructMovieJson(self, dbId, qualityProfileId): """ s_dict = self.lookupMovie(dbId) - root = self.getRoot()[0]["path"] movie_json = { "title": s_dict["title"], - "path": root + s_dict["title"], + "path": rootDir + s_dict["title"], "qualityProfileId": qualityProfileId, "profileId": qualityProfileId, "year": s_dict["year"], "tmdbId": s_dict["tmdbId"], "images": s_dict["images"], "titleSlug": s_dict["titleSlug"], - "monitored": True, - "addOptions": {"searchForMovie": True}, + "monitored": monitored, + "addOptions": {"searchForMovie": searchForMovie}, } return movie_json From 4ab4717805b0388608fe61a09c5ce97ebaacb72b Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 19:07:16 -0700 Subject: [PATCH 12/19] more robust addMovie --- PyArr/radarr_api.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PyArr/radarr_api.py b/PyArr/radarr_api.py index da21ef9..6786e72 100644 --- a/PyArr/radarr_api.py +++ b/PyArr/radarr_api.py @@ -188,17 +188,22 @@ def constructMovieJson( } return movie_json - def addMovie(self, dbId, qualityProfileId): + def addMovie( + self, dbId, qualityProfileId, rootDir, monitored=True, searchForMovie=True + ): """addMovie adds a new movie to collection Args: - Required - dbid - Required - qualityProfileId + Required - dbid + Required - qualityProfileId (int) + Required - rootDir (string) Returns: json response """ - movie_json = self.constructMovieJson(dbId, qualityProfileId) + movie_json = self.constructMovieJson( + dbId, qualityProfileId, rootDir, monitored, searchForMovie + ) path = "/api/movie" res = self.request_post(path, data=movie_json) From 4ef4b7b5198d089a09fee84e9da067d08d35f0eb Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sat, 26 Sep 2020 19:18:46 -0700 Subject: [PATCH 13/19] v0.9.4 --- docs/changelog.md | 20 ++++++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/changelog.md b/docs/changelog.md index f2c55c1..8ca4f08 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,6 +4,26 @@ title: ChangeLog nav_order: 7 --- +# v0.9.4 + +### Sonarr New Features + +- More robust addSeries +- API Calls + - setCommand + - Options Available: RefreshSeries, RescanSeries, EpisodeSearch, SeasonSearch, SeriesSearch, DownloadedEpisodesScan, RssSync, RenameFiles, RenameSeries, Backup, missingEpisodeSearch + - updSeries + - updEpisode + - del_episode_file_by_episode_id + +### Radarr New Features + +- More robust addMovie +- API Calls + - setCommand + - Options Available: RefreshMovie, RescanMovie, MoviesSearch, DownloadedMoviesScan, RssSync, RenameFiles, RenameMovie, CutOffUnmetMoviesSearch, NetImportSync, missingMoviesSearch + - updMovie + # v0.9.3 - Fixed formatting issues diff --git a/pyproject.toml b/pyproject.toml index 7af2a19..17462a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "PyArr" -version = "0.9.3" +version = "0.9.4" description = "A Sonarr and Radarr API Wrapper" authors = ["Steven Marks "] license = "MIT" From 02818f0d8dec15b573e25893098fb27dc6960d33 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sun, 27 Sep 2020 10:06:23 -0700 Subject: [PATCH 14/19] fix typo in CI name --- .github/workflows/ci_workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_workflow.yml b/.github/workflows/ci_workflow.yml index 44c01e7..1764e11 100644 --- a/.github/workflows/ci_workflow.yml +++ b/.github/workflows/ci_workflow.yml @@ -14,7 +14,7 @@ on: jobs: black: - name: Check PyArr formatting with Balck + name: Check PyArr formatting with Black runs-on: ubuntu-latest steps: - name: Getting your configuration from GitHub From 2a7ad4979ccb374a4b7be2849b87ee72aefb3962 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sun, 27 Sep 2020 10:18:36 -0700 Subject: [PATCH 15/19] radarr setCommand docs fix #25 fix #24 fix #23 fix #22 fix #21 fix #20 --- docs/RadarrAPI/refreshMovie.md | 49 ------------------- .../{rescanMovie.md => setCommand.md} | 16 +++--- 2 files changed, 9 insertions(+), 56 deletions(-) delete mode 100644 docs/RadarrAPI/refreshMovie.md rename docs/RadarrAPI/{rescanMovie.md => setCommand.md} (51%) diff --git a/docs/RadarrAPI/refreshMovie.md b/docs/RadarrAPI/refreshMovie.md deleted file mode 100644 index a89e34b..0000000 --- a/docs/RadarrAPI/refreshMovie.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -layout: default -title: refreshMovie -parent: RadarrAPI -nav_order: 4 ---- - -## Summary - -Refresh movie information from TMDb and rescan disk - -## Parameters - -Required: None - -Optional: `movieId (int)` - if not set all movies will be refreshed and scanned - -## Example - -```python -refreshMovie() -``` - -## Returns JsonArray - -```json -{ - 'name': 'RefreshMovie', - 'body': { - 'sendUpdatesToClient': True, - 'updateScheduledTask': True, - 'completionMessage': 'Completed', - 'name': 'RefreshMovie', - 'trigger': 'manual' - }, - 'priority': 'normal', - 'status': 'started', - 'queued': '2020-04-29T08:36:10.742081Z', - 'started': '2020-04-29T08:36:10.805347Z', - 'trigger': 'manual', - 'state': 'started', - 'manual': True, - 'startedOn': '2020-04-29T08:36:10.742081Z', - 'stateChangeTime': '2020-04-29T08:36:10.805347Z', - 'sendUpdatesToClient': True, - 'updateScheduledTask': True, - 'id': 1638638 -} -``` diff --git a/docs/RadarrAPI/rescanMovie.md b/docs/RadarrAPI/setCommand.md similarity index 51% rename from docs/RadarrAPI/rescanMovie.md rename to docs/RadarrAPI/setCommand.md index 3b465c2..355d44f 100644 --- a/docs/RadarrAPI/rescanMovie.md +++ b/docs/RadarrAPI/setCommand.md @@ -1,36 +1,38 @@ --- layout: default -title: rescanMovie +title: setCommand parent: RadarrAPI nav_order: 4 --- ## Summary -Rescan disk for movies +Performs any of the predetermined Radarr command routines. + +Options available: RefreshMovie, RescanMovie, MoviesSearch, DownloadedMoviesScan, RssSync, RenameFiles, RenameMovie, CutOffUnmetMoviesSearch, NetImportSync, missingMoviesSearch ## Parameters -Required: None +Required: name (string) -Optional: `movieId (int)` - if not set all movies will be scanned +Optional: Additional parameters may be required or optional. See [https://github.com/Radarr/Radarr/wiki/API:Command](https://github.com/Radarr/Radarr/wiki/API:Command) on a per command basis. ## Example ```python -rescanMovie() +setCommand(name="MoviesSearch", movieIds=movie_id) ``` ## Returns JsonArray ```json { - 'name': 'RescanMovie', + 'name': 'MoviesSearch', 'body': { 'sendUpdatesToClient': True, 'updateScheduledTask': True, 'completionMessage': 'Completed', - 'name': 'RescanMovie', + 'name': 'MoviesSearch', 'trigger': 'manual' }, 'priority': 'normal', From 6ff0cbde37f7ef6db312be11107ee88e66842335 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sun, 27 Sep 2020 10:20:10 -0700 Subject: [PATCH 16/19] sonarr setCommand docs --- docs/SonarrAPI/refreshSeries.md | 50 ------------------- .../{rescanSeries.md => setCommand.md} | 12 +++-- 2 files changed, 7 insertions(+), 55 deletions(-) delete mode 100644 docs/SonarrAPI/refreshSeries.md rename docs/SonarrAPI/{rescanSeries.md => setCommand.md} (54%) diff --git a/docs/SonarrAPI/refreshSeries.md b/docs/SonarrAPI/refreshSeries.md deleted file mode 100644 index e2a5e52..0000000 --- a/docs/SonarrAPI/refreshSeries.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -layout: default -title: refreshSeries -parent: SonarrAPI -nav_order: 4 ---- - -## Summary - -Refresh series information from trakt and rescan disk - -## Parameters - -Required: None - -Optional: `seriesId (int)` - if not set all movies will be refreshed and scanned - -## Example - -```python -refreshSeries() -``` - -## Returns JsonArray - -```json -{ - 'name': 'RefreshSeries', - 'message': 'Scanning disk for Killing Eve', - 'body': { - 'sendUpdatesToClient': True, - 'updateScheduledTask': True, - 'completionMessage': 'Completed', - 'name': 'RefreshSeries', - 'trigger': 'manual' - }, - 'priority': 'normal', - 'status': 'started', - 'queued': '2020-04-29T18:58:19.168363Z', - 'started': '2020-04-29T18:58:19.226896Z', - 'trigger': 'manual', - 'state': 'started', - 'manual': True, - 'startedOn': '2020-04-29T18:58:19.168363Z', - 'stateChangeTime': '2020-04-29T18:58:19.226896Z', - 'sendUpdatesToClient': True, - 'updateScheduledTask': True, - 'id': 2658444 -} -``` diff --git a/docs/SonarrAPI/rescanSeries.md b/docs/SonarrAPI/setCommand.md similarity index 54% rename from docs/SonarrAPI/rescanSeries.md rename to docs/SonarrAPI/setCommand.md index 9e73a86..09c955f 100644 --- a/docs/SonarrAPI/rescanSeries.md +++ b/docs/SonarrAPI/setCommand.md @@ -1,24 +1,26 @@ --- layout: default -title: rescanSeries +title: setCommand parent: SonarrAPI nav_order: 4 --- ## Summary -Refresh rescan disk for a single series +Performs any of the predetermined Sonarr command routines. + +Options available: RefreshSeries, RescanSeries, EpisodeSearch, SeasonSearch, SeriesSearch, DownloadedEpisodesScan, RssSync, RenameFiles, RenameSeries, Backup, missingEpisodeSearch ## Parameters -Required: None +Required: name (string) -Optional: `seriesId (int)` - if not set all series will be scanned +Optional: Additional parameters may be required or optional. See [https://github.com/Radarr/Radarr/wiki/API:Command](https://github.com/Radarr/Radarr/wiki/API:Command) on a per command basis. ## Example ```python -rescanSeries() +setCommand(name="RescanSeries", seriesId=series_id) ``` ## Returns JsonArray From 6e32436bb4cb03dcc7c1bf78997b4d050b4a7d13 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sun, 27 Sep 2020 11:04:17 -0700 Subject: [PATCH 17/19] updMovie docs --- PyArr/radarr_api.py | 8 +- docs/RadarrAPI/updMovie.md | 183 +++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 docs/RadarrAPI/updMovie.md diff --git a/PyArr/radarr_api.py b/PyArr/radarr_api.py index 6786e72..ffff350 100644 --- a/PyArr/radarr_api.py +++ b/PyArr/radarr_api.py @@ -118,7 +118,13 @@ def getMovie(self, *args): return res.json() def updMovie(self, data): - """Update an existing movie""" + """Update an existing movie. + + Args: + data (dictionary containing an object obtained by getMovie()) + Returns: + json response + """ path = "/api/movie" res = self.request_put(path, data) diff --git a/docs/RadarrAPI/updMovie.md b/docs/RadarrAPI/updMovie.md new file mode 100644 index 0000000..c963611 --- /dev/null +++ b/docs/RadarrAPI/updMovie.md @@ -0,0 +1,183 @@ +--- +layout: default +title: updMovie +parent: RadarrAPI +nav_order: 4 +--- + +## Summary + +Update the information of a movie currently within Radarr. + +## Parameters + +Required: data (object obtained by getMovie()) + +## Example + +```python +movie = getMovie(radarr_id) +movie["monitored"] = True +updMovie(movie) +``` + +## Returns Json + +```json +{'added': '2020-09-27T17:48:20.5583865Z', + 'alternativeTitles': [{'id': 42, + 'language': {'id': 1, 'name': 'English'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': 'Grandes Héroes', + 'voteCount': 0, + 'votes': 0}, + {'id': 43, + 'language': {'id': 1, 'name': 'English'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': '大英雄联盟', + 'voteCount': 0, + 'votes': 0}, + {'id': 44, + 'language': {'id': 1, 'name': 'English'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': '6 kangelast', + 'voteCount': 0, + 'votes': 0}, + {'id': 45, + 'language': {'id': 2, 'name': 'French'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': 'Les Nouveaux Heros', + 'voteCount': 0, + 'votes': 0}, + {'id': 46, + 'language': {'id': 1, 'name': 'English'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': '6 Giborim', + 'voteCount': 0, + 'votes': 0}, + {'id': 47, + 'language': {'id': 1, 'name': 'English'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': 'ベイマックス', + 'voteCount': 0, + 'votes': 0}, + {'id': 48, + 'language': {'id': 1, 'name': 'English'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': '빅 히어로', + 'voteCount': 0, + 'votes': 0}, + {'id': 49, + 'language': {'id': 15, 'name': 'Norwegian'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': 'Disney Klassiker 53 - Big Hero 6', + 'voteCount': 0, + 'votes': 0}, + {'id': 50, + 'language': {'id': 11, 'name': 'Russian'}, + 'movieId': 5, + 'sourceId': 0, + 'sourceType': 'tmdb', + 'title': 'Город героев', + 'voteCount': 0, + 'votes': 0}], + 'certification': 'PG', + 'cleanTitle': 'bighero6', + 'downloaded': True, + 'folderName': '/media/Movies/Big Hero 6 (2014)', + 'genres': ['Adventure', 'Family', 'Animation'], + 'hasFile': True, + 'id': 5, + 'images': [{'coverType': 'poster', + 'remoteUrl': 'https://image.tmdb.org/t/p/original/2mxS4wUimwlLmI1xp6QW6NSU361.jpg', + 'url': '/MediaCover/5/poster.jpg?lastWrite=637368257018459301'}, + {'coverType': 'fanart', + 'remoteUrl': 'https://image.tmdb.org/t/p/original/4s2d3xdyqotiVNHTlTlJjrr3q0H.jpg', + 'url': '/MediaCover/5/fanart.jpg?lastWrite=637368257026829482'}], + 'imdbId': 'tt2245084', + 'inCinemas': '2014-10-24T00:00:00Z', + 'isAvailable': True, + 'lastInfoSync': '2020-09-27T17:48:21.0322258Z', + 'minimumAvailability': 'announced', + 'monitored': True, + 'movieFile': {'dateAdded': '2020-09-27T17:48:21.1615426Z', + 'edition': '', + 'id': 4, + 'mediaInfo': {'audioAdditionalFeatures': 'LC', + 'audioBitrate': 93624, + 'audioChannelPositions': '2/0/0', + 'audioChannelPositionsText': 'Front: L R', + 'audioChannels': 2, + 'audioCodecID': 'mp4a-40-2', + 'audioCodecLibrary': '', + 'audioFormat': 'AAC', + 'audioLanguages': 'English', + 'audioProfile': '', + 'audioStreamCount': 1, + 'containerFormat': 'MPEG-4', + 'height': 808, + 'runTime': '01:41:52.6880000', + 'scanType': 'Progressive', + 'schemaRevision': 5, + 'subtitles': '', + 'videoBitDepth': 8, + 'videoBitrate': 2215000, + 'videoCodecID': 'avc1', + 'videoCodecLibrary': 'x264 - core 142 r2479 ' + 'dd79a61', + 'videoColourPrimaries': 'BT.709', + 'videoFormat': 'AVC', + 'videoFps': 23.976, + 'videoMultiViewCount': 0, + 'videoProfile': 'High@L4.1', + 'videoTransferCharacteristics': '', + 'width': 1920}, + 'movieId': 0, + 'quality': {'quality': {'id': 7, + 'modifier': 'none', + 'name': 'Bluray-1080p', + 'resolution': 1080, + 'source': 'bluray'}, + 'revision': {'isRepack': False, + 'real': 0, + 'version': 1}}, + 'relativePath': 'Big Hero 6 (2014) Bluray-1080p.mp4', + 'size': 1766948530}, + 'overview': 'The special bond that develops between plus-sized inflatable ' + 'robot Baymax, and prodigy Hiro Hamada, who team up with a group ' + 'of friends to form a band of high-tech heroes.', + 'path': '/media/Movies/Big Hero 6 (2014)', + 'physicalRelease': '2015-02-24T00:00:00Z', + 'profileId': 1, + 'qualityProfileId': 1, + 'ratings': {'value': 7.8, 'votes': 12090}, + 'runtime': 102, + 'secondaryYearSourceId': 0, + 'sizeOnDisk': 1766948530, + 'sortTitle': 'big hero 6', + 'status': 'released', + 'studio': 'Walt Disney Animation Studios', + 'tags': [], + 'title': 'Big Hero 6', + 'titleSlug': '177572', + 'tmdbId': 177572, + 'website': 'http://movies.disney.com/big-hero-6', + 'year': 2014, + 'youTubeTrailerId': 'vco0SpSz17g'} +``` From 2dc2aa5536e3031b513bd942978d7367242e0756 Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sun, 27 Sep 2020 11:09:43 -0700 Subject: [PATCH 18/19] updSeries docs --- PyArr/sonarr_api.py | 8 +- docs/SonarrAPI/updSeries.md | 143 ++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 docs/SonarrAPI/updSeries.md diff --git a/PyArr/sonarr_api.py b/PyArr/sonarr_api.py index 568a54a..dddfbcd 100644 --- a/PyArr/sonarr_api.py +++ b/PyArr/sonarr_api.py @@ -261,7 +261,13 @@ def addSeries( return res.json() def updSeries(self, data): - """Update an existing series""" + """Update an existing series. + + Args: + data (dictionary containing an object obtained by getSeries()) + Returns: + json response + """ path = "/api/series" res = self.request_put(path, data) diff --git a/docs/SonarrAPI/updSeries.md b/docs/SonarrAPI/updSeries.md new file mode 100644 index 0000000..1226fee --- /dev/null +++ b/docs/SonarrAPI/updSeries.md @@ -0,0 +1,143 @@ +--- +layout: default +title: updSeries +parent: SonarrAPI +nav_order: 4 +--- + +## Summary + +Update an existing series currently within Sonarr. + +## Parameters + +Required: data (object obtained by getSeries()) + +## Example + +```python +series = getSeries(series_id) +series["seriesType"] = "Anime" +updSeries(series) +``` + +## Returns Json + +```json +{'added': '2020-09-09T05:51:51.903196Z', + 'airTime': '17:30', + 'alternateTitles': [{'sceneSeasonNumber': -1, + 'title': 'Boku no Hero Academia'}, + {'sceneSeasonNumber': 3, 'title': 'My Hero Academia S3'}, + {'sceneSeasonNumber': 2, 'title': 'My Hero Academia S2'}, + {'sceneSeasonNumber': 3, + 'title': 'My Hero Academia 3rd Season'}, + {'sceneSeasonNumber': 4, 'title': 'My Hero Academia S4'}, + {'sceneSeasonNumber': 4, + 'title': 'Boku No Hero Academia (2019)'}, + {'sceneSeasonNumber': 4, + 'title': 'My Hero Academia 4th Season'}, + {'sceneSeasonNumber': 4, 'title': 'My Hero Academy S4'}, + {'sceneSeasonNumber': 3, 'title': 'My Hero Academy S3'}, + {'sceneSeasonNumber': 2, 'title': 'My Hero Academy S2'}, + {'sceneSeasonNumber': 4, + 'title': 'Boku no Hero Academia S4'}, + {'sceneSeasonNumber': 3, + 'title': 'Boku no Hero Academia S3'}, + {'sceneSeasonNumber': 2, + 'title': 'Boku no Hero Academia S2'}, + {'sceneSeasonNumber': 4, + 'title': 'Boku no Hero Academia 4th Season'}, + {'sceneSeasonNumber': 3, + 'title': 'Boku no Hero Academia 3rd Season'}, + {'sceneSeasonNumber': 2, + 'title': 'My Hero Academia 2nd Season'}], + 'certification': 'TV-14', + 'cleanTitle': 'myheroacademia', + 'episodeCount': 88, + 'episodeFileCount': 84, + 'firstAired': '2016-04-03T07:00:00Z', + 'genres': ['Action', 'Adventure', 'Animation', 'Anime', 'Comedy', 'Fantasy'], + 'id': 5, + 'images': [{'coverType': 'banner', + 'remoteUrl': 'https://artworks.thetvdb.com/banners/graphical/305074-g.jpg', + 'url': '/MediaCover/5/banner.jpg?lastWrite=637352275136732840'}, + {'coverType': 'poster', + 'remoteUrl': 'https://artworks.thetvdb.com/banners/posters/305074-5.jpg', + 'url': '/MediaCover/5/poster.jpg?lastWrite=637352275141422940'}, + {'coverType': 'fanart', + 'remoteUrl': 'https://artworks.thetvdb.com/banners/fanart/original/305074-4.jpg', + 'url': '/MediaCover/5/fanart.jpg?lastWrite=637352275146583050'}], + 'imdbId': 'tt5626028', + 'languageProfileId': 1, + 'lastInfoSync': '2020-09-27T16:58:37.747572Z', + 'monitored': True, + 'network': 'Nippon TV', + 'overview': 'Izuku has dreamt of being a hero all his life—a lofty goal for ' + 'anyone, but especially challenging for a kid with no ' + 'superpowers. That’s right, in a world where eighty percent of ' + 'the population has some kind of super-powered “quirk,” Izuku was ' + 'unlucky enough to be born completely normal. But that’s not ' + 'enough to stop him from enrolling in one of the world’s most ' + 'prestigious hero academies.', + 'path': '/media/TV/My Hero Academia', + 'previousAiring': '2020-04-04T21:30:00Z', + 'profileId': 1, + 'qualityProfileId': 1, + 'ratings': {'value': 8.8, 'votes': 859}, + 'runtime': 25, + 'seasonCount': 4, + 'seasonFolder': True, + 'seasons': [{'monitored': False, + 'seasonNumber': 0, + 'statistics': {'episodeCount': 0, + 'episodeFileCount': 0, + 'percentOfEpisodes': 0.0, + 'sizeOnDisk': 0, + 'totalEpisodeCount': 9}}, + {'monitored': True, + 'seasonNumber': 1, + 'statistics': {'episodeCount': 12, + 'episodeFileCount': 12, + 'percentOfEpisodes': 100.0, + 'previousAiring': '2016-06-26T21:30:00Z', + 'sizeOnDisk': 9202900588, + 'totalEpisodeCount': 13}}, + {'monitored': True, + 'seasonNumber': 2, + 'statistics': {'episodeCount': 23, + 'episodeFileCount': 23, + 'percentOfEpisodes': 100.0, + 'previousAiring': '2017-09-30T21:30:00Z', + 'sizeOnDisk': 13469966037, + 'totalEpisodeCount': 25}}, + {'monitored': True, + 'seasonNumber': 3, + 'statistics': {'episodeCount': 25, + 'episodeFileCount': 25, + 'percentOfEpisodes': 100.0, + 'previousAiring': '2018-09-29T21:30:00Z', + 'sizeOnDisk': 19980012802, + 'totalEpisodeCount': 25}}, + {'monitored': True, + 'seasonNumber': 4, + 'statistics': {'episodeCount': 24, + 'episodeFileCount': 24, + 'percentOfEpisodes': 100.0, + 'previousAiring': '2020-04-04T21:30:00Z', + 'sizeOnDisk': 34785539617, + 'totalEpisodeCount': 25}}], + 'seriesType': 'anime', + 'sizeOnDisk': 77438419044, + 'sortTitle': 'my hero academia', + 'status': 'continuing', + 'tags': [], + 'title': 'My Hero Academia', + 'titleSlug': 'my-hero-academia', + 'totalEpisodeCount': 97, + 'tvMazeId': 13615, + 'tvRageId': 0, + 'tvdbId': 305074, + 'useSceneNumbering': True, + 'year': 2016} +``` From d7e2d8a9b5bcd98f086a75fb2417a1c612475d9f Mon Sep 17 00:00:00 2001 From: Archmonger <16909269+Archmonger@users.noreply.github.com> Date: Sun, 27 Sep 2020 11:20:24 -0700 Subject: [PATCH 19/19] updEpisode docs --- docs/SonarrAPI/updEpisode.md | 100 +++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 docs/SonarrAPI/updEpisode.md diff --git a/docs/SonarrAPI/updEpisode.md b/docs/SonarrAPI/updEpisode.md new file mode 100644 index 0000000..6d9fe93 --- /dev/null +++ b/docs/SonarrAPI/updEpisode.md @@ -0,0 +1,100 @@ +--- +layout: default +title: updEpisode +parent: SonarrAPI +nav_order: 4 +--- + +## Summary + +Update an existing episode currently within Sonarr. + +## Parameters + +Required: data (object obtained by `getEpisodesBySeriesId()` or `getEpisodeByEpisodeId()`) + +## Example + +```python +episode = getEpisodesByEpisodeId(3807) +episode["monitored"] = True +updEpisode(episode) +``` + +## Returns Json + +```json +[{'absoluteEpisodeNumber': 10, + 'airDate': '2016-06-05', + 'airDateUtc': '2016-06-05T21:30:00Z', + 'episodeFileId': 0, + 'episodeNumber': 10, + 'hasFile': False, + 'id': 3807, + 'lastSearchTime': '2020-09-27T18:10:48.810014Z', + 'monitored': True, + 'overview': "Villains have attacked USJ, and it's up to Class 1-A to stop " + 'them. What are the villains after? Will All Might be able to ' + 'save the day again?', + 'sceneAbsoluteEpisodeNumber': 10, + 'sceneEpisodeNumber': 10, + 'sceneSeasonNumber': 1, + 'seasonNumber': 1, + 'series': {'added': '2020-09-09T05:51:51.903196Z', + 'airTime': '17:30', + 'certification': 'TV-14', + 'cleanTitle': 'myheroacademia', + 'firstAired': '2016-04-03T07:00:00Z', + 'genres': ['Action', + 'Adventure', + 'Animation', + 'Anime', + 'Comedy', + 'Fantasy'], + 'id': 5, + 'images': [{'coverType': 'banner', + 'url': 'https://artworks.thetvdb.com/banners/graphical/305074-g.jpg'}, + {'coverType': 'poster', + 'url': 'https://artworks.thetvdb.com/banners/posters/305074-5.jpg'}, + {'coverType': 'fanart', + 'url': 'https://artworks.thetvdb.com/banners/fanart/original/305074-4.jpg'}], + 'imdbId': 'tt5626028', + 'languageProfileId': 1, + 'lastInfoSync': '2020-09-27T16:58:37.747572Z', + 'monitored': True, + 'network': 'Nippon TV', + 'overview': 'Izuku has dreamt of being a hero all his life—a ' + 'lofty goal for anyone, but especially challenging ' + 'for a kid with no superpowers. That’s right, in a ' + 'world where eighty percent of the population has ' + 'some kind of super-powered “quirk,” Izuku was ' + 'unlucky enough to be born completely normal. But ' + 'that’s not enough to stop him from enrolling in one ' + 'of the world’s most prestigious hero academies.', + 'path': '/media/TV/My Hero Academia', + 'profileId': 1, + 'qualityProfileId': 1, + 'ratings': {'value': 8.8, 'votes': 859}, + 'runtime': 25, + 'seasonCount': 4, + 'seasonFolder': True, + 'seasons': [{'monitored': False, 'seasonNumber': 0}, + {'monitored': True, 'seasonNumber': 1}, + {'monitored': True, 'seasonNumber': 2}, + {'monitored': True, 'seasonNumber': 3}, + {'monitored': True, 'seasonNumber': 4}], + 'seriesType': 'anime', + 'sortTitle': 'my hero academia', + 'status': 'continuing', + 'tags': [], + 'title': 'My Hero Academia', + 'titleSlug': 'my-hero-academia', + 'tvMazeId': 13615, + 'tvRageId': 0, + 'tvdbId': 305074, + 'useSceneNumbering': True, + 'year': 2016}, + 'seriesId': 5, + 'title': 'Encounter With the Unknown', + 'unverifiedSceneNumbering': False}] +```