added radarr/sonarr attributes and split add_to_arr

pull/165/head
meisnate12 4 years ago
parent 16de1a722e
commit 18dd057548

@ -1293,4 +1293,3 @@ collections:
- ~
sort_title: ~_Collectionless
collection_order: alpha
collection_order: alpha

@ -30,19 +30,28 @@ tautulli: # Can be individually specified
radarr: # Can be individually specified per library as well
url: http://192.168.1.12:7878
token: ################################
version: v2
quality_profile: HD-1080p
root_folder_path: S:/Movies
version: v3
add: false
root_folder_path: S:/Movies
monitor: true
availability: announced
quality_profile: HD-1080p
tag:
search: false
sonarr: # Can be individually specified per library as well
url: http://192.168.1.12:8989
token: ################################
version: v2
quality_profile: HD-1080p
root_folder_path: "S:/TV Shows"
version: v3
add: false
root_folder_path: "S:/TV Shows"
monitor: all
quality_profile: HD-1080p
language_profile: English
series_type: standard
season_folder: true
tag:
search: false
cutoff_search: false
omdb:
apikey: ########
trakt:

@ -1,6 +1,6 @@
import glob, logging, os, re
from datetime import datetime, timedelta
from modules import anidb, anilist, imdb, letterboxd, mal, plex, tautulli, tmdb, trakttv, tvdb, util
from modules import anidb, anilist, imdb, letterboxd, mal, plex, radarr, sonarr, tautulli, tmdb, trakttv, tvdb, util
from modules.util import Failed
from plexapi.collection import Collections
from plexapi.exceptions import BadRequest, NotFound
@ -81,13 +81,12 @@ numbered_builders = [
"trakt_collected"
]
all_details = [
"sort_title", "content_rating",
"summary", "tmdb_summary", "tmdb_description", "tmdb_biography", "tvdb_summary", "tvdb_description", "trakt_description", "letterboxd_description",
"collection_mode", "collection_order",
"sort_title", "content_rating", "collection_mode", "collection_order",
"summary", "tmdb_summary", "tmdb_description", "tmdb_biography", "tvdb_summary",
"tvdb_description", "trakt_description", "letterboxd_description",
"url_poster", "tmdb_poster", "tmdb_profile", "tvdb_poster", "file_poster",
"url_background", "tmdb_background", "tvdb_background", "file_background",
"name_mapping", "add_to_arr", "arr_tag", "arr_folder", "label",
"show_filtered", "show_missing", "save_missing"
"name_mapping", "label", "show_filtered", "show_missing", "save_missing"
]
collectionless_details = [
"sort_title", "content_rating",
@ -106,7 +105,6 @@ ignored_details = [
"tmdb_person"
]
boolean_details = [
"add_to_arr",
"show_filtered",
"show_missing",
"save_missing"
@ -152,12 +150,12 @@ class CollectionBuilder:
self.name = name
self.data = data
self.details = {
"arr_tag": None,
"arr_folder": None,
"show_filtered": library.show_filtered,
"show_missing": library.show_missing,
"save_missing": library.save_missing
}
self.radarr_options = {}
self.sonarr_options = {}
self.missing_movies = []
self.missing_shows = []
self.methods = []
@ -167,6 +165,8 @@ class CollectionBuilder:
self.summaries = {}
self.schedule = ""
self.rating_key_map = {}
self.add_to_radarr = None
self.add_to_sonarr = None
current_time = datetime.now()
current_year = current_time.year
@ -355,20 +355,28 @@ class CollectionBuilder:
else:
raise Failed("Collection Error: tmdb_person attribute is blank")
for method_name, method_data in self.data.items():
if "trakt" in method_name.lower() and not config.Trakt: raise Failed(f"Collection Error: {method_name} requires Trakt todo be configured")
elif "imdb" in method_name.lower() and not config.IMDb: raise Failed(f"Collection Error: {method_name} requires TMDb or Trakt to be configured")
elif "tautulli" in method_name.lower() and not self.library.Tautulli: raise Failed(f"Collection Error: {method_name} requires Tautulli to be configured")
elif "mal" in method_name.lower() and not config.MyAnimeList: raise Failed(f"Collection Error: {method_name} requires MyAnimeList to be configured")
for method_key, method_data in self.data.items():
if "trakt" in method_key.lower() and not config.Trakt: raise Failed(f"Collection Error: {method_key} requires Trakt todo be configured")
elif "imdb" in method_key.lower() and not config.IMDb: raise Failed(f"Collection Error: {method_key} requires TMDb or Trakt to be configured")
elif "radarr" in method_key.lower() and not self.library.Radarr: raise Failed(f"Collection Error: {method_key} requires Radarr to be configured")
elif "sonarr" in method_key.lower() and not self.library.Sonarr: raise Failed(f"Collection Error: {method_key} requires Sonarr to be configured")
elif "tautulli" in method_key.lower() and not self.library.Tautulli: raise Failed(f"Collection Error: {method_key} requires Tautulli to be configured")
elif "mal" in method_key.lower() and not config.MyAnimeList: raise Failed(f"Collection Error: {method_key} requires MyAnimeList to be configured")
elif method_data is not None:
logger.debug("")
logger.debug(f"Validating Method: {method_name}")
logger.debug(f"Validating Method: {method_key}")
logger.debug(f"Value: {method_data}")
if method_name.lower() in method_alias:
method_name = method_alias[method_name.lower()]
logger.warning(f"Collection Warning: {method_name} attribute will run as {method_name}")
else:
method_name = method_name.lower()
if method_key.lower() in method_alias:
method_name = method_alias[method_key.lower()]
logger.warning(f"Collection Warning: {method_key} attribute will run as {method_name}")
elif method_key.lower() == "add_to_arr":
method_name = "radarr_add" if self.library.is_movie else "sonarr_add"
logger.warning(f"Collection Warning: {method_key} attribute will run as {method_name}")
elif method_key.lower() in ["arr_tag", "arr_folder"]:
method_name = f"{'rad' if self.library.is_movie else 'son'}{method_key.lower()}"
logger.warning(f"Collection Warning: {method_key} attribute will run as {method_name}")
else:
method_name = method_key.lower()
if method_name in show_only_builders and self.library.is_movie:
raise Failed(f"Collection Error: {method_name} attribute only works for show libraries")
elif method_name in movie_only_builders and self.library.is_show:
@ -441,7 +449,7 @@ class CollectionBuilder:
elif method_name == "sync_mode":
if str(method_data).lower() in ["append", "sync"]: self.details[method_name] = method_data.lower()
else: raise Failed("Collection Error: sync_mode attribute must be either 'append' or 'sync'")
elif method_name in ["arr_tag", "label"]:
elif method_name == "label":
self.details[method_name] = util.get_list(method_data)
elif method_name in boolean_details:
if isinstance(method_data, bool): self.details[method_name] = method_data
@ -450,6 +458,52 @@ class CollectionBuilder:
else: raise Failed(f"Collection Error: {method_name} attribute must be either true or false")
elif method_name in all_details:
self.details[method_name] = method_data
elif method_name == "radarr_add":
self.add_to_radarr = True
elif method_name == "radarr_folder":
self.radarr_options["folder"] = method_data
elif method_name in ["radarr_monitor", "radarr_search"]:
if isinstance(method_data, bool): self.radarr_options[method_name[7:]] = method_data
elif str(method_data).lower() in ["t", "true"]: self.radarr_options[method_name[7:]] = True
elif str(method_data).lower() in ["f", "false"]: self.radarr_options[method_name[7:]] = False
else: raise Failed(f"Collection Error: {method_name} attribute must be either true or false")
elif method_name == "radarr_availability":
if str(method_data).lower() in radarr.availability_translation:
self.radarr_options["availability"] = str(method_data).lower()
else:
raise Failed(f"Collection Error: {method_name} attribute must be either announced, cinemas, released or db")
elif method_name == "radarr_quality":
self.library.Radarr.get_profile_id(method_data)
self.radarr_options["quality"] = method_data
elif method_name == "radarr_tag":
self.radarr_options["tag"] = util.get_list(method_data)
elif method_name == "sonarr_add":
self.add_to_sonarr = True
elif method_name == "sonarr_folder":
self.sonarr_options["folder"] = method_data
elif method_name == "sonarr_monitor":
if str(method_data).lower() in sonarr.monitor_translation:
self.sonarr_options["monitor"] = str(method_data).lower()
else:
raise Failed(f"Collection Error: {method_name} attribute must be either all, future, missing, existing, pilot, first, latest or none")
elif method_name == "sonarr_quality":
self.library.Sonarr.get_profile_id(method_data, "quality_profile")
self.sonarr_options["quality"] = method_data
elif method_name == "sonarr_language":
self.library.Sonarr.get_profile_id(method_data, "language_profile")
self.sonarr_options["language"] = method_data
elif method_name == "sonarr_series":
if str(method_data).lower() in sonarr.series_type:
self.sonarr_options["series"] = str(method_data).lower()
else:
raise Failed(f"Collection Error: {method_name} attribute must be either standard, daily, or anime")
elif method_name in ["sonarr_season", "sonarr_search", "sonarr_cutoff_search"]:
if isinstance(method_data, bool): self.sonarr_options[method_name[7:]] = method_data
elif str(method_data).lower() in ["t", "true"]: self.sonarr_options[method_name[7:]] = True
elif str(method_data).lower() in ["f", "false"]: self.sonarr_options[method_name[7:]] = False
else: raise Failed(f"Collection Error: {method_name} attribute must be either true or false")
elif method_name == "sonarr_tag":
self.sonarr_options["tag"] = util.get_list(method_data)
elif method_name in ["title", "title.and", "title.not", "title.begins", "title.ends"]:
self.methods.append(("plex_search", [{method_name: util.get_list(method_data, split=False)}]))
elif method_name in ["year.greater", "year.less"]:
@ -898,10 +952,10 @@ class CollectionBuilder:
self.methods.append((method_name, util.get_list(method_data)))
elif method_name not in ignored_details:
raise Failed(f"Collection Error: {method_name} attribute not supported")
elif method_name in all_builders or method_name in method_alias or method_name in plex.searches:
raise Failed(f"Collection Error: {method_name} attribute is blank")
elif method_key.lower() in all_builders or method_key.lower() in method_alias or method_key.lower() in plex.searches:
raise Failed(f"Collection Error: {method_key} attribute is blank")
else:
logger.warning(f"Collection Warning: {method_name} attribute is blank")
logger.warning(f"Collection Warning: {method_key} attribute is blank")
self.sync = self.library.sync_mode == "sync"
if "sync_mode" in methods:
@ -912,14 +966,14 @@ class CollectionBuilder:
else:
self.sync = self.data[methods["sync_mode"]].lower() == "sync"
self.do_arr = False
if self.library.Radarr:
self.do_arr = self.details["add_to_arr"] if "add_to_arr" in self.details else self.library.Radarr.add
if self.library.Sonarr:
self.do_arr = self.details["add_to_arr"] if "add_to_arr" in self.details else self.library.Sonarr.add
if self.add_to_radarr is None:
self.add_to_radarr = self.library.Radarr.add if self.library.Radarr else False
if self.add_to_sonarr is None:
self.add_to_sonarr = self.library.Sonarr.add if self.library.Sonarr else False
if self.collectionless:
self.details["add_to_arr"] = False
self.add_to_radarr = False
self.add_to_sonarr = False
self.details["collection_mode"] = "hide"
self.sync = True
@ -1001,8 +1055,11 @@ class CollectionBuilder:
logger.info(f"{len(missing_movies_with_names)} Movie{'s' if len(missing_movies_with_names) > 1 else ''} Missing")
if self.details["save_missing"] is True:
self.library.add_missing(collection_name, missing_movies_with_names, True)
if self.do_arr and self.library.Radarr:
self.library.Radarr.add_tmdb([missing_id for title, missing_id in missing_movies_with_names], tags=self.details["arr_tag"], folder=self.details["arr_folder"])
if self.add_to_radarr and self.library.Radarr:
try:
self.library.Radarr.add_tmdb([missing_id for title, missing_id in missing_movies_with_names], **self.radarr_options)
except Failed as e:
logger.error(e)
if self.run_again:
self.missing_movies.extend([missing_id for title, missing_id in missing_movies_with_names])
if len(missing_shows) > 0 and self.library.is_show:
@ -1030,8 +1087,11 @@ class CollectionBuilder:
logger.info(f"{len(missing_shows_with_names)} Show{'s' if len(missing_shows_with_names) > 1 else ''} Missing")
if self.details["save_missing"] is True:
self.library.add_missing(collection_name, missing_shows_with_names, False)
if self.do_arr and self.library.Sonarr:
self.library.Sonarr.add_tvdb([missing_id for title, missing_id in missing_shows_with_names], tags=self.details["arr_tag"], folder=self.details["arr_folder"])
if self.add_to_sonarr and self.library.Sonarr:
try:
self.library.Sonarr.add_tvdb([missing_id for title, missing_id in missing_shows_with_names], **self.sonarr_options)
except Failed as e:
logger.error(e)
if self.run_again:
self.missing_shows.extend([missing_id for title, missing_id in missing_shows_with_names])

@ -24,7 +24,28 @@ logger = logging.getLogger("Plex Meta Manager")
sync_modes = {"append": "Only Add Items to the Collection", "sync": "Add & Remove Items from the Collection"}
radarr_versions = {"v2": "For Radarr 0.2", "v3": "For Radarr 3.0"}
radarr_availabilities = {
"announced": "For Announced",
"cinemas": "For In Cinemas",
"released": "For Released",
"db": "For PreDB"
}
sonarr_versions = {"v2": "For Sonarr 0.2", "v3": "For Sonarr 3.0"}
sonarr_monitors = {
"all": "Monitor all episodes except specials",
"future": "Monitor episodes that have not aired yet",
"missing": "Monitor episodes that do not have files or have not aired yet",
"existing": "Monitor episodes that have files or have not aired yet",
"pilot": "Monitor the first episode. All other episodes will be ignored",
"first": "Monitor all episodes of the first season. All other seasons will be ignored",
"latest": "Monitor all episodes of the latest season and future seasons",
"none": "No episodes will be monitored"
}
sonarr_series_types = {
"standard": "Episodes released with SxxEyy pattern",
"daily": "Episodes released daily or less frequently that use year-month-day (2017-05-25)",
"anime": "Episodes released using an absolute episode number"
}
mass_genre_update_options = {"tmdb": "Use TMDb Metadata", "omdb": "Use IMDb Metadata through OMDb"}
library_types = {"movie": "For Movie Libraries", "show": "For Show Libraries"}
@ -257,9 +278,11 @@ class Config:
self.general["radarr"] = {}
self.general["radarr"]["url"] = check_for_attribute(self.data, "url", parent="radarr", default_is_none=True)
self.general["radarr"]["token"] = check_for_attribute(self.data, "token", parent="radarr", default_is_none=True)
self.general["radarr"]["version"] = check_for_attribute(self.data, "version", parent="radarr", test_list=radarr_versions, default="v2")
self.general["radarr"]["version"] = check_for_attribute(self.data, "version", parent="radarr", test_list=radarr_versions, default="v3")
self.general["radarr"]["add"] = check_for_attribute(self.data, "add", parent="radarr", var_type="bool", default=False)
self.general["radarr"]["root_folder_path"] = check_for_attribute(self.data, "root_folder_path", parent="radarr", default_is_none=True)
self.general["radarr"]["monitor"] = check_for_attribute(self.data, "monitor", parent="radarr", var_type="bool", default=True)
self.general["radarr"]["availability"] = check_for_attribute(self.data, "availability", parent="radarr", test_list=radarr_availabilities, default="announced")
self.general["radarr"]["quality_profile"] = check_for_attribute(self.data, "quality_profile", parent="radarr", default_is_none=True)
self.general["radarr"]["tag"] = check_for_attribute(self.data, "tag", parent="radarr", var_type="lower_list", default_is_none=True)
self.general["radarr"]["search"] = check_for_attribute(self.data, "search", parent="radarr", var_type="bool", default=False)
@ -267,14 +290,17 @@ class Config:
self.general["sonarr"] = {}
self.general["sonarr"]["url"] = check_for_attribute(self.data, "url", parent="sonarr", default_is_none=True)
self.general["sonarr"]["token"] = check_for_attribute(self.data, "token", parent="sonarr", default_is_none=True)
self.general["sonarr"]["version"] = check_for_attribute(self.data, "version", parent="sonarr", test_list=sonarr_versions, default="v2")
self.general["sonarr"]["quality_profile"] = check_for_attribute(self.data, "quality_profile", parent="sonarr", default_is_none=True)
self.general["sonarr"]["version"] = check_for_attribute(self.data, "version", parent="sonarr", test_list=sonarr_versions, default="v3")
self.general["sonarr"]["add"] = check_for_attribute(self.data, "add", parent="sonarr", var_type="bool", default=False)
self.general["sonarr"]["root_folder_path"] = check_for_attribute(self.data, "root_folder_path", parent="sonarr", default_is_none=True)
self.general["sonarr"]["monitor"] = check_for_attribute(self.data, "monitor", parent="sonarr", test_list=sonarr_monitors, default="all")
self.general["sonarr"]["quality_profile"] = check_for_attribute(self.data, "quality_profile", parent="sonarr", default_is_none=True)
self.general["sonarr"]["language_profile"] = check_for_attribute(self.data, "language_profile", parent="sonarr", default_is_none=True)
self.general["sonarr"]["add"] = check_for_attribute(self.data, "add", parent="sonarr", var_type="bool", default=False)
self.general["sonarr"]["search"] = check_for_attribute(self.data, "search", parent="sonarr", var_type="bool", default=False)
self.general["sonarr"]["series_type"] = check_for_attribute(self.data, "series_type", parent="sonarr", test_list=sonarr_series_types, default="standard")
self.general["sonarr"]["season_folder"] = check_for_attribute(self.data, "season_folder", parent="sonarr", var_type="bool", default=True)
self.general["sonarr"]["tag"] = check_for_attribute(self.data, "tag", parent="sonarr", var_type="lower_list", default_is_none=True)
self.general["sonarr"]["search"] = check_for_attribute(self.data, "search", parent="sonarr", var_type="bool", default=False)
self.general["sonarr"]["cutoff_search"] = check_for_attribute(self.data, "cutoff_search", parent="sonarr", var_type="bool", default=False)
self.general["tautulli"] = {}
self.general["tautulli"]["url"] = check_for_attribute(self.data, "url", parent="tautulli", default_is_none=True)
@ -354,6 +380,8 @@ class Config:
radarr_params["version"] = check_for_attribute(lib, "version", parent="radarr", test_list=radarr_versions, default=self.general["radarr"]["version"], save=False)
radarr_params["add"] = check_for_attribute(lib, "add", parent="radarr", var_type="bool", default=self.general["radarr"]["add"], save=False)
radarr_params["root_folder_path"] = check_for_attribute(lib, "root_folder_path", parent="radarr", default=self.general["radarr"]["root_folder_path"], req_default=True, save=False)
radarr_params["monitor"] = check_for_attribute(lib, "monitor", parent="radarr", var_type="bool", default=self.general["radarr"]["monitor"], save=False)
radarr_params["availability"] = check_for_attribute(lib, "availability", parent="radarr", test_list=radarr_availabilities, default=self.general["radarr"]["availability"], save=False)
radarr_params["quality_profile"] = check_for_attribute(lib, "quality_profile", parent="radarr", default=self.general["radarr"]["quality_profile"], req_default=True, save=False)
radarr_params["tag"] = check_for_attribute(lib, "search", parent="radarr", var_type="lower_list", default=self.general["radarr"]["tag"], default_is_none=True, save=False)
radarr_params["search"] = check_for_attribute(lib, "search", parent="radarr", var_type="bool", default=self.general["radarr"]["search"], save=False)
@ -369,16 +397,19 @@ class Config:
sonarr_params["url"] = check_for_attribute(lib, "url", parent="sonarr", default=self.general["sonarr"]["url"], req_default=True, save=False)
sonarr_params["token"] = check_for_attribute(lib, "token", parent="sonarr", default=self.general["sonarr"]["token"], req_default=True, save=False)
sonarr_params["version"] = check_for_attribute(lib, "version", parent="sonarr", test_list=sonarr_versions, default=self.general["sonarr"]["version"], save=False)
sonarr_params["quality_profile"] = check_for_attribute(lib, "quality_profile", parent="sonarr", default=self.general["sonarr"]["quality_profile"], req_default=True, save=False)
sonarr_params["add"] = check_for_attribute(lib, "add", parent="sonarr", var_type="bool", default=self.general["sonarr"]["add"], save=False)
sonarr_params["root_folder_path"] = check_for_attribute(lib, "root_folder_path", parent="sonarr", default=self.general["sonarr"]["root_folder_path"], req_default=True, save=False)
sonarr_params["monitor"] = check_for_attribute(lib, "monitor", parent="sonarr", test_list=sonarr_monitors, default=self.general["sonarr"]["monitor"], save=False)
sonarr_params["quality_profile"] = check_for_attribute(lib, "quality_profile", parent="sonarr", default=self.general["sonarr"]["quality_profile"], req_default=True, save=False)
if self.general["sonarr"]["language_profile"]:
sonarr_params["language_profile"] = check_for_attribute(lib, "language_profile", parent="sonarr", default=self.general["sonarr"]["language_profile"], save=False)
else:
sonarr_params["language_profile"] = check_for_attribute(lib, "language_profile", parent="sonarr", default_is_none=True, save=False)
sonarr_params["add"] = check_for_attribute(lib, "add", parent="sonarr", var_type="bool", default=self.general["sonarr"]["add"], save=False)
sonarr_params["search"] = check_for_attribute(lib, "search", parent="sonarr", var_type="bool", default=self.general["sonarr"]["search"], save=False)
sonarr_params["series_type"] = check_for_attribute(lib, "series_type", parent="sonarr", test_list=sonarr_series_types, default=self.general["sonarr"]["series_type"], save=False)
sonarr_params["season_folder"] = check_for_attribute(lib, "season_folder", parent="sonarr", var_type="bool", default=self.general["sonarr"]["season_folder"], save=False)
sonarr_params["tag"] = check_for_attribute(lib, "search", parent="sonarr", var_type="lower_list", default=self.general["sonarr"]["tag"], default_is_none=True, save=False)
sonarr_params["search"] = check_for_attribute(lib, "search", parent="sonarr", var_type="bool", default=self.general["sonarr"]["search"], save=False)
sonarr_params["cutoff_search"] = check_for_attribute(lib, "cutoff_search", parent="sonarr", var_type="bool", default=self.general["sonarr"]["cutoff_search"], save=False)
library.Sonarr = SonarrAPI(sonarr_params, library.Plex.language)
except Failed as e:
util.print_multiline(e, error=True)

@ -5,37 +5,46 @@ from retrying import retry
logger = logging.getLogger("Plex Meta Manager")
availability_translation = {
"announced": "announced",
"cinemas": "inCinemas",
"released": "released",
"db": "preDB"
}
class RadarrAPI:
def __init__(self, params):
self.base_url = f"{params['url']}/api{'/v3' if params['version'] == 'v3' else ''}/"
self.url = params["url"]
self.token = params["token"]
self.version = params["version"]
self.base_url = f"{self.url}/api{'/v3' if self.version == 'v3' else ''}/"
try:
result = requests.get(f"{self.base_url}system/status", params={"apikey": f"{self.token}"}).json()
except Exception:
util.print_stacktrace()
raise Failed(f"Radarr Error: Could not connect to Radarr at {params['url']}")
raise Failed(f"Radarr Error: Could not connect to Radarr at {self.url}")
if "error" in result and result["error"] == "Unauthorized":
raise Failed("Radarr Error: Invalid API Key")
if "version" not in result:
raise Failed("Radarr Error: Unexpected Response Check URL")
self.quality_profile_id = None
self.add = params["add"]
self.root_folder_path = params["root_folder_path"]
self.monitor = params["monitor"]
self.availability = params["availability"]
self.quality_profile_id = self.get_profile_id(params["quality_profile"])
self.tag = params["tag"]
self.tags = self.get_tags()
self.search = params["search"]
def get_profile_id(self, profile_name):
profiles = ""
for profile in self.send_get("qualityProfile" if params["version"] == "v3" else "profile"):
for profile in self.send_get("qualityProfile" if self.version == "v3" else "profile"):
if len(profiles) > 0:
profiles += ", "
profiles += profile["name"]
if profile["name"] == params["quality_profile"]:
self.quality_profile_id = profile["id"]
if not self.quality_profile_id:
raise Failed(f"Radarr Error: quality_profile: {params['quality_profile']} does not exist in radarr. Profiles available: {profiles}")
self.tags = self.get_tags()
self.url = params["url"]
self.version = params["version"]
self.token = params["token"]
self.root_folder_path = params["root_folder_path"]
self.add = params["add"]
self.search = params["search"]
self.tag = params["tag"]
if profile["name"] == profile_name:
return profile["id"]
raise Failed(f"Radarr Error: quality_profile: {profile_name} does not exist in radarr. Profiles available: {profiles}")
def get_tags(self):
return {tag["label"]: tag["id"] for tag in self.send_get("tag")}
@ -56,13 +65,17 @@ class RadarrAPI:
else:
raise Failed(f"Sonarr Error: TMDb ID: {tmdb_id} not found")
def add_tmdb(self, tmdb_ids, tags=None, folder=None):
def add_tmdb(self, tmdb_ids, **options):
logger.info("")
logger.debug(f"TMDb IDs: {tmdb_ids}")
tag_nums = []
add_count = 0
if tags is None:
tags = self.tag
folder = options["folder"] if "folder" in options else self.root_folder_path
monitor = options["monitor"] if "monitor" in options else self.monitor
availability = options["availability"] if "availability" in options else self.availability
quality_profile_id = self.get_profile_id(options["quality"]) if "quality" in options else self.quality_profile_id
tags = options["tag"] if "tag" in options else self.tag
search = options["search"] if "search" in options else self.search
if tags:
self.add_tags(tags)
tag_nums = [self.tags[label] for label in tags if label in self.tags]
@ -80,14 +93,15 @@ class RadarrAPI:
url_json = {
"title": movie_info["title"],
f"{'qualityProfileId' if self.version == 'v3' else 'profileId'}": self.quality_profile_id,
f"{'qualityProfileId' if self.version == 'v3' else 'profileId'}": quality_profile_id,
"year": int(movie_info["year"]),
"tmdbid": int(tmdb_id),
"titleslug": movie_info["titleSlug"],
"monitored": True,
"rootFolderPath": self.root_folder_path if folder is None else folder,
"minimumAvailability": availability_translation[availability],
"monitored": monitor,
"rootFolderPath": folder,
"images": [{"covertype": "poster", "url": poster_url}],
"addOptions": {"searchForMovie": self.search}
"addOptions": {"searchForMovie": search}
}
if tag_nums:
url_json["tags"] = tag_nums

@ -5,53 +5,65 @@ from retrying import retry
logger = logging.getLogger("Plex Meta Manager")
series_type = ["standard", "daily", "anime"]
monitor_translation = {
"all": "all",
"future": "future",
"missing": "missing",
"existing": "existing",
"pilot": "pilot",
"first": "firstSeason",
"latest": "latestSeason",
"none": "none"
}
class SonarrAPI:
def __init__(self, params, language):
self.base_url = f"{params['url']}/api{'/v3/' if params['version'] == 'v3' else '/'}"
self.url = params["url"]
self.token = params["token"]
self.version = params["version"]
self.base_url = f"{self.url}/api{'/v3/' if self.version == 'v3' else '/'}"
try:
result = requests.get(f"{self.base_url}system/status", params={"apikey": f"{self.token}"}).json()
except Exception:
util.print_stacktrace()
raise Failed(f"Sonarr Error: Could not connect to Sonarr at {params['url']}")
raise Failed(f"Sonarr Error: Could not connect to Sonarr at {self.url}")
if "error" in result and result["error"] == "Unauthorized":
raise Failed("Sonarr Error: Invalid API Key")
if "version" not in result:
raise Failed("Sonarr Error: Unexpected Response Check URL")
self.quality_profile_id = None
profiles = ""
for profile in self.send_get("qualityProfile" if params["version"] == "v3" else "profile"):
if len(profiles) > 0:
profiles += ", "
profiles += profile["name"]
if profile["name"] == params["quality_profile"]:
self.quality_profile_id = profile["id"]
if not self.quality_profile_id:
raise Failed(f"Sonarr Error: quality_profile: {params['quality_profile']} does not exist in sonarr. Profiles available: {profiles}")
self.add = params["add"]
self.root_folder_path = params["root_folder_path"]
self.monitor = params["monitor"]
self.quality_profile_id = self.get_profile_id(params["quality_profile"], "quality_profile")
self.language_profile_id = None
if params["version"] == "v3" and params["language_profile"] is not None:
profiles = ""
for profile in self.send_get("languageProfile"):
if len(profiles) > 0:
profiles += ", "
profiles += profile["name"]
if profile["name"] == params["language_profile"]:
self.language_profile_id = profile["id"]
if not self.quality_profile_id:
raise Failed(f"Sonarr Error: language_profile: {params['language_profile']} does not exist in sonarr. Profiles available: {profiles}")
if self.version == "v3" and params["language_profile"] is not None:
self.language_profile_id = self.get_profile_id(params["language_profile"], "language_profile")
if self.language_profile_id is None:
self.language_profile_id = 1
self.tags = self.get_tags()
self.language = language
self.version = params["version"]
self.root_folder_path = params["root_folder_path"]
self.add = params["add"]
self.search = params["search"]
self.series_type = params["series_type"]
self.season_folder = params["season_folder"]
self.tag = params["tag"]
self.tags = self.get_tags()
self.search = params["search"]
self.cutoff_search = params["cutoff_search"]
self.language = language
def get_profile_id(self, profile_name, profile_type):
profiles = ""
if profile_type == "quality_profile" and self.version == "v3":
endpoint = "qualityProfile"
elif profile_type == "language_profile":
endpoint = "languageProfile"
else:
endpoint = "profile"
for profile in self.send_get(endpoint):
if len(profiles) > 0:
profiles += ", "
profiles += profile["name"]
if profile["name"] == profile_name:
return profile["id"]
raise Failed(f"Sonarr Error: {profile_type}: {profile_name} does not exist in sonarr. Profiles available: {profiles}")
def get_tags(self):
return {tag["label"]: tag["id"] for tag in self.send_get("tag")}
@ -72,13 +84,20 @@ class SonarrAPI:
else:
raise Failed(f"Sonarr Error: TVDb ID: {tvdb_id} not found")
def add_tvdb(self, tvdb_ids, tags=None, folder=None):
def add_tvdb(self, tvdb_ids, **options):
logger.info("")
logger.debug(f"TVDb IDs: {tvdb_ids}")
tag_nums = []
add_count = 0
if tags is None:
tags = self.tag
folder = options["folder"] if "folder" in options else self.root_folder_path
monitor = options["monitor"] if "monitor" in options else self.monitor
quality_profile_id = self.get_profile_id(options["quality"], "quality_profile") if "quality" in options else self.quality_profile_id
language_profile_id = self.get_profile_id(options["language"], "language_profile") if "quality" in options else self.quality_profile_id
series = options["series"] if "series" in options else self.series_type
season = options["season"] if "season" in options else self.season_folder
tags = options["tag"] if "tag" in options else self.tag
search = options["search"] if "search" in options else self.search
cutoff_search = options["cutoff_search"] if "cutoff_search" in options else self.cutoff_search
if tags:
self.add_tags(tags)
tag_nums = [self.tags[label] for label in tags if label in self.tags]
@ -96,17 +115,22 @@ class SonarrAPI:
url_json = {
"title": show_info["title"],
f"{'qualityProfileId' if self.version == 'v3' else 'profileId'}": self.quality_profile_id,
"languageProfileId": self.language_profile_id,
f"{'qualityProfileId' if self.version == 'v3' else 'profileId'}": quality_profile_id,
"languageProfileId": language_profile_id,
"tvdbId": int(tvdb_id),
"titleslug": show_info["titleSlug"],
"language": self.language,
"monitored": True,
"seasonFolder": self.season_folder,
"rootFolderPath": self.root_folder_path if folder is None else folder,
"monitored": monitor != "none",
"seasonFolder": season,
"seriesType": series,
"rootFolderPath": folder,
"seasons": [],
"images": [{"covertype": "poster", "url": poster_url}],
"addOptions": {"searchForMissingEpisodes": self.search}
"addOptions": {
"searchForMissingEpisodes": search,
"searchForCutoffUnmetEpisodes": cutoff_search,
"monitor": monitor_translation[monitor]
}
}
if tag_nums:
url_json["tags"] = tag_nums

Loading…
Cancel
Save