diff --git a/core/auto_process/books.py b/core/auto_process/books.py index 26771b13..510e7c33 100644 --- a/core/auto_process/books.py +++ b/core/auto_process/books.py @@ -23,10 +23,10 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', apikey = cfg['apikey'] ssl = int(cfg.get('ssl', 0)) web_root = cfg.get('web_root', '') - protocol = 'https://' if ssl else 'http://' + scheme = 'https' if ssl else 'http' remote_path = int(cfg.get('remote_path', 0)) - url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root) + url = core.utils.common.create_url(scheme, host, port, web_root) if not server_responding(url): logger.error('Server did not respond. Exiting', section) return ProcessResult( diff --git a/core/auto_process/comics.py b/core/auto_process/comics.py index e8059d71..d89468a3 100644 --- a/core/auto_process/comics.py +++ b/core/auto_process/comics.py @@ -22,9 +22,9 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', ssl = int(cfg.get('ssl', 0)) web_root = cfg.get('web_root', '') remote_path = int(cfg.get('remote_path'), 0) - protocol = 'https://' if ssl else 'http://' + scheme = 'https' if ssl else 'http' - url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root) + url = core.utils.common.create_url(scheme, host, port, web_root) if not server_responding(url): logger.error('Server did not respond. Exiting', section) return ProcessResult( diff --git a/core/auto_process/games.py b/core/auto_process/games.py index 502ca9ba..7a91678f 100644 --- a/core/auto_process/games.py +++ b/core/auto_process/games.py @@ -22,9 +22,9 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', library = cfg.get('library') ssl = int(cfg.get('ssl', 0)) web_root = cfg.get('web_root', '') - protocol = 'https://' if ssl else 'http://' + scheme = 'https' if ssl else 'http' - url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root) + url = core.utils.common.create_url(scheme, host, port, web_root) if not server_responding(url): logger.error('Server did not respond. Exiting', section) return ProcessResult( diff --git a/core/auto_process/managers/pymedusa.py b/core/auto_process/managers/pymedusa.py index 0a280596..4809f6ab 100644 --- a/core/auto_process/managers/pymedusa.py +++ b/core/auto_process/managers/pymedusa.py @@ -1,5 +1,6 @@ import time +import core.utils.common from core import logger from core.auto_process.common import ProcessResult from core.auto_process.managers.sickbeard import SickBeard @@ -14,7 +15,13 @@ class PyMedusa(SickBeard): super(PyMedusa, self).__init__(sb_init) def _create_url(self): - return '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root) + route = f'{self.sb_init.web_root}/home/postprocess/processEpisode' + return core.utils.common.create_url( + self.sb_init.protocol, + self.sb_init.host, + self.sb_init.port, + route, + ) class PyMedusaApiV1(SickBeard): @@ -24,7 +31,13 @@ class PyMedusaApiV1(SickBeard): super(PyMedusaApiV1, self).__init__(sb_init) def _create_url(self): - return '{0}{1}:{2}{3}/api/{4}/'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root, self.sb_init.apikey) + route = f'{self.sb_init.web_root}/api/{self.sb_init.apikey}/' + return core.utils.common.create_url( + self.sb_init.protocol, + self.sb_init.host, + self.sb_init.port, + route, + ) def api_call(self): self._process_fork_prarams() @@ -69,7 +82,13 @@ class PyMedusaApiV2(SickBeard): raise Exception('For the section SickBeard `fork = medusa-apiv2` you also need to configure an `apikey`') def _create_url(self): - return '{0}{1}:{2}{3}/api/v2/postprocess'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root) + route = f'{self.sb_init.web_root}/api/v2/postprocess' + return core.utils.common.create_url( + self.sb_init.protocol, + self.sb_init.host, + self.sb_init.port, + route, + ) def _get_identifier_status(self, url): # Loop through requesting medusa for the status on the queueitem. diff --git a/core/auto_process/managers/sickbeard.py b/core/auto_process/managers/sickbeard.py index 5a085a3b..dc565bc3 100644 --- a/core/auto_process/managers/sickbeard.py +++ b/core/auto_process/managers/sickbeard.py @@ -15,9 +15,9 @@ from requests_oauthlib import OAuth2Session class InitSickBeard: - """Sickbeard init class. + """SickBeard init class. - Used to determin which sickbeard fork object to initialize. + Used to determine which SickBeard fork object to initialize. """ def __init__(self, cfg, section, input_category): @@ -302,6 +302,7 @@ class InitSickBeard: class SickBeard: """Sickbeard base class.""" + sb_init: InitSickBeard def __init__(self, sb_init): """SB constructor.""" @@ -345,10 +346,17 @@ class SickBeard: if client_agent == core.TORRENT_CLIENT_AGENT and core.USE_LINK == 'move-sym': self.process_method = 'symlink' - def _create_url(self): + def _create_url(self) -> str: if self.sb_init.apikey: - return '{0}{1}:{2}{3}/api/{4}/'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root, self.sb_init.apikey) - return '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root) + route = f'{self.sb_init.web_root}/api/{self.sb_init.apikey}/' + else: + route = f'{self.sb_init.web_root}/home/postprocess/processEpisode' + return core.utils.common.create_url( + self.sb_init.protocol, + self.sb_init.host, + self.sb_init.port, + route + ) def _process_fork_prarams(self): # configure SB params to pass @@ -432,7 +440,13 @@ class SickBeard: try: if not self.sb_init.apikey and self.sb_init.username and self.sb_init.password: # If not using the api, we need to login using user/pass first. - login = '{0}{1}:{2}{3}/login'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root) + route = f'{self.sb_init.web_root}/login' + login = core.utils.common.create_url( + self.sb_init.protocol, + self.sb_init.host, + self.sb_init.port, + route, + ) login_params = {'username': self.sb_init.username, 'password': self.sb_init.password} r = self.session.get(login, verify=False, timeout=(30, 60)) if r.status_code in [401, 403] and r.cookies.get('_xsrf'): diff --git a/core/auto_process/movies.py b/core/auto_process/movies.py index 9d0c7b3d..77d9d756 100644 --- a/core/auto_process/movies.py +++ b/core/auto_process/movies.py @@ -48,7 +48,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', ssl = int(cfg.get('ssl', 0)) web_root = cfg.get('web_root', '') remote_path = int(cfg.get('remote_path', 0)) - protocol = 'https://' if ssl else 'http://' + scheme = 'https' if ssl else 'http' omdbapikey = cfg.get('omdbapikey', '') no_status_check = int(cfg.get('no_status_check', 0)) status = int(status) @@ -59,13 +59,17 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', imdbid = find_imdbid(dir_name, input_name, omdbapikey) if section == 'CouchPotato': - base_url = '{0}{1}:{2}{3}/api/{4}/'.format(protocol, host, port, web_root, apikey) - if section == 'Radarr': - base_url = '{0}{1}:{2}{3}/api/v3/command'.format(protocol, host, port, web_root) - url2 = '{0}{1}:{2}{3}/api/v3/config/downloadClient'.format(protocol, host, port, web_root) + route = f'{web_root}/api/{apikey}/' + elif section == 'Radarr': + route = f'{web_root}/api/v3/command' + route2 = f'{web_root}/api/v3/config/downloadClient' + url2 = core.utils.common.create_url(scheme, host, port, route2) headers = {'X-Api-Key': apikey, 'Content-Type': 'application/json'} - if section == 'Watcher3': - base_url = '{0}{1}:{2}{3}/postprocessing'.format(protocol, host, port, web_root) + elif section == 'Watcher3': + route = f'{web_root}/postprocessing' + else: + route = web_root + base_url = core.utils.common.create_url(scheme, host, port, route) if not apikey: logger.info('No CouchPotato or Radarr apikey entered. Performing transcoder functions only') release = None @@ -389,7 +393,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', return ProcessResult( status_code=0, message='{0}: Successfully processed but no change in status confirmed'.format(section), - ) + ) # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing. timeout = time.time() + 60 * wait_for @@ -470,7 +474,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', '{0} does not appear to have changed status after {1} minutes, Please check your logs.'.format(input_name, wait_for), section, ) - + return ProcessResult( status_code=1, message='{0}: Failed to post-process - No change in status'.format(section), diff --git a/core/auto_process/music.py b/core/auto_process/music.py index c4fd61e2..2002f8b1 100644 --- a/core/auto_process/music.py +++ b/core/auto_process/music.py @@ -26,17 +26,15 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', delete_failed = int(cfg['delete_failed']) web_root = cfg.get('web_root', '') remote_path = int(cfg.get('remote_path', 0)) - protocol = 'https://' if ssl else 'http://' + scheme = 'https' if ssl else 'http' status = int(status) if status > 0 and core.NOEXTRACTFAILED: extract = 0 else: extract = int(cfg.get('extract', 0)) - if section == 'Lidarr': - url = '{0}{1}:{2}{3}/api/v1'.format(protocol, host, port, web_root) - else: - url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root) + route = f'{web_root}/api/v1' if section == 'Lidarr' else f'{web_root}/api' + url = core.utils.common.create_url(scheme, host, port, route) if not server_responding(url): logger.error('Server did not respond. Exiting', section) return ProcessResult( @@ -96,7 +94,8 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual', ) elif status == 0 and section == 'Lidarr': - url = '{0}{1}:{2}{3}/api/v1/command'.format(protocol, host, port, web_root) + route = f'{web_root}/api/v1/command' + url = core.utils.common.create_url(scheme, host, port, route) headers = {'X-Api-Key': apikey} if remote_path: logger.debug('remote_path: {0}'.format(remote_dir(dir_name)), section) diff --git a/core/auto_process/tv.py b/core/auto_process/tv.py index 927d3fb2..664e5e4e 100644 --- a/core/auto_process/tv.py +++ b/core/auto_process/tv.py @@ -39,7 +39,7 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu port = cfg['port'] ssl = int(cfg.get('ssl', 0)) web_root = cfg.get('web_root', '') - protocol = 'https://' if ssl else 'http://' + scheme = 'https' if ssl else 'http' username = cfg.get('username', '') password = cfg.get('password', '') apikey = cfg.get('apikey', '') @@ -51,7 +51,8 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu # For now let's do botch the OO and the serialized code, until everything has been migrated. init_sickbeard = InitSickBeard(cfg, section, input_category) - if server_responding('{0}{1}:{2}{3}'.format(protocol, host, port, web_root)): + url = core.utils.common.create_url(scheme, host, port, web_root) + if server_responding(url): # auto-detect correct fork # During reactor we also return fork, fork_params. But these are also stored in the object. # Should be changed after refactor. @@ -289,27 +290,25 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu status_code=1, # Return as failed to flag this in the downloader. ) - url = None + route = '' if section == 'SickBeard': if apikey: - url = '{0}{1}:{2}{3}/api/{4}/'.format(protocol, host, port, web_root, apikey) - if not 'cmd' in fork_params: - if 'SickGear' in fork: - fork_params['cmd'] = 'sg.postprocess' - else: - fork_params['cmd'] = 'postprocess' + route = f'{web_root}/api/{apikey}/' + if 'cmd' not in fork_params: + prefix = '' if 'SickGear' not in fork else 'sg.' + fork_params['cmd'] = f'{prefix}postprocess' elif fork == 'Stheno': - url = '{0}{1}:{2}{3}/home/postprocess/process_episode'.format(protocol, host, port, web_root) + route = f'{web_root}/home/postprocess/process_episode' else: - url = '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(protocol, host, port, web_root) + route = f'{web_root}/home/postprocess/processEpisode' elif section == 'SiCKRAGE': if api_version >= 2: - url = '{0}{1}:{2}{3}/api/v{4}/postprocess'.format(protocol, host, port, web_root, api_version) + route = f'{web_root}/api/v{api_version}/postprocess' else: - url = '{0}{1}:{2}{3}/api/v{4}/{5}/'.format(protocol, host, port, web_root, api_version, apikey) + route = f'{web_root}/api/v{api_version}/{apikey}/' elif section == 'NzbDrone': - url = '{0}{1}:{2}{3}/api/command'.format(protocol, host, port, web_root) - url2 = '{0}{1}:{2}{3}/api/config/downloadClient'.format(protocol, host, port, web_root) + route = f'{web_root}/api/command' + route2 = f'{web_root}/api/config/downloadClient' headers = {'X-Api-Key': apikey} # params = {'sortKey': 'series.title', 'page': 1, 'pageSize': 1, 'sortDir': 'asc'} if remote_path: @@ -321,7 +320,7 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu if not download_id: data.pop('downloadClientId') data = json.dumps(data) - + url = core.utils.common.create_url(scheme, host, port, route) try: if section == 'SickBeard': if init_sickbeard.fork_obj: @@ -331,7 +330,7 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu logger.debug('Opening URL: {0} with params: {1}'.format(url, fork_params), section) if not apikey and username and password: - login = '{0}{1}:{2}{3}/login'.format(protocol, host, port, web_root) + login = f'{web_root}/login' login_params = {'username': username, 'password': password} r = s.get(login, verify=False, timeout=(30, 60)) if r.status_code in [401, 403] and r.cookies.get('_xsrf'): @@ -457,6 +456,8 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu # message='{0}: Failed to post-process {1}'.format(section, input_name), # status_code=1, # ) + + url2 = core.utils.common.create_url(scheme, host, port, route) if completed_download_handling(url2, headers, section=section): logger.debug('The Scan command did not return status completed, but complete Download Handling is enabled. Passing back to {0}.'.format(section), section) diff --git a/core/utils/common.py b/core/utils/common.py index 6583830d..06595525 100644 --- a/core/utils/common.py +++ b/core/utils/common.py @@ -1,4 +1,6 @@ import os.path +import typing +import urllib.parse import core from core import logger @@ -109,3 +111,16 @@ def get_dirs(section, subsection, link='hard'): logger.debug('No directories identified in {0}:{1} for post-processing'.format(section, subsection)) return list(set(to_return)) + + +def create_url( + scheme: str, + host: str, + port: typing.Optional[int] = None, + path: str = '', + query: str = '', +) -> str: + """Create a url from its component parts.""" + netloc = host if port is None else f'{host}:{port}' + fragments = '' + return urllib.parse.urlunsplit([scheme, netloc, path, query, fragments])