Commit 90fe2d3d authored by echel0n's avatar echel0n

Refactored dynamic loading of metadata providers.

Refactored dynamic loading of notifier providers.
Refactored dynamic loading of NZB providers.
Refactored dynamic loading of Torrent providers.
Refactored metadata provider config property and added default value.
Refactored web handler arguments to return string instead of None for default value.
parent c5ca8dae
......@@ -60,6 +60,8 @@ sickrage.egg-info
/build/
pre-commit-hook.sh
/venv-*/
/.vagrant/
Vagrantfile
# OS Generated Files #
######################
......
......@@ -41,6 +41,7 @@ from keycloak.realm import KeycloakRealm
from tornado.ioloop import IOLoop
import sickrage
from sickrage.core.api import API
from sickrage.core.api.account import AccountAPI
from sickrage.core.caches.name_cache import NameCache
from sickrage.core.caches.quicksearch_cache import QuicksearchCache
......@@ -330,6 +331,16 @@ class Core(object):
if self.config.showupdate_hour < 0 or self.config.showupdate_hour > 23:
self.config.showupdate_hour = 0
# add API token refresh job
self.scheduler.add_job(
API().refresh_token,
IntervalTrigger(
hours=1,
),
name='SR-API',
id='SR-API'
)
# add version checker job
self.scheduler.add_job(
self.version_updater.run,
......
......@@ -13,6 +13,7 @@ from sickrage.core.api.exceptions import ApiUnauthorized, ApiError
class API(object):
def __init__(self):
self.name = 'SR-API'
self.api_url = 'https://www.sickrage.ca/api/v1/'
self.client_id = sickrage.app.oidc_client_id
self.client_secret = sickrage.app.oidc_client_secret
......@@ -87,7 +88,7 @@ class API(object):
try:
self.token = self.session.refresh_token(self.token_url, **extras)
except InvalidGrantError as e:
self.token = ''
self.token = {}
return self.token
......
......@@ -1879,9 +1879,7 @@ class Config(object):
sickrage.app.search_providers.provider_order = self.check_setting_str('Providers', 'providers_order')
for metadataProviderID, metadataProviderObj in sickrage.app.metadata_providers.items():
metadataProviderObj.set_config(
self.check_setting_str('MetadataProviders', metadataProviderID, '0|0|0|0|0|0|0|0|0|0|0')
)
metadataProviderObj.config = self.check_setting_str('MetadataProviders', metadataProviderID, '0|0|0|0|0|0|0|0|0|0|0')
# mark config settings loaded
self.loaded = True
......
......@@ -50,47 +50,47 @@ class ConfigPostProcessingHandler(BaseHandler, ABC):
class SavePostProcessingHandler(BaseHandler, ABC):
@authenticated
async def post(self, *args, **kwargs):
naming_pattern = self.get_argument('naming_pattern', None)
naming_multi_ep = self.get_argument('naming_multi_ep', None)
kodi_data = self.get_argument('kodi_data', None)
kodi_12plus_data = self.get_argument('kodi_12plus_data', None)
mediabrowser_data = self.get_argument('mediabrowser_data', None)
sony_ps3_data = self.get_argument('sony_ps3_data', None)
wdtv_data = self.get_argument('wdtv_data', None)
tivo_data = self.get_argument('tivo_data', None)
mede8er_data = self.get_argument('mede8er_data', None)
keep_processed_dir = self.get_argument('keep_processed_dir', None)
process_method = self.get_argument('process_method', None)
del_rar_contents = self.get_argument('del_rar_contents', None)
process_automatically = self.get_argument('process_automatically', None)
no_delete = self.get_argument('no_delete', None)
rename_episodes = self.get_argument('rename_episodes', None)
airdate_episodes = self.get_argument('airdate_episodes', None)
file_timestamp_timezone = self.get_argument('file_timestamp_timezone', None)
unpack = self.get_argument('unpack', None)
move_associated_files = self.get_argument('move_associated_files', None)
sync_files = self.get_argument('sync_files', None)
postpone_if_sync_files = self.get_argument('postpone_if_sync_files', None)
nfo_rename = self.get_argument('nfo_rename', None)
tv_download_dir = self.get_argument('tv_download_dir', None)
naming_custom_abd = self.get_argument('naming_custom_abd', None)
naming_anime = self.get_argument('naming_anime', None)
create_missing_show_dirs = self.get_argument('create_missing_show_dirs', None)
add_shows_wo_dir = self.get_argument('add_shows_wo_dir', None)
naming_abd_pattern = self.get_argument('naming_abd_pattern', None)
naming_strip_year = self.get_argument('naming_strip_year', None)
delete_failed = self.get_argument('delete_failed', None)
extra_scripts = self.get_argument('extra_scripts', None)
naming_custom_sports = self.get_argument('naming_custom_sports', None)
naming_sports_pattern = self.get_argument('naming_sports_pattern', None)
naming_custom_anime = self.get_argument('naming_custom_anime', None)
naming_anime_pattern = self.get_argument('naming_anime_pattern', None)
naming_anime_multi_ep = self.get_argument('naming_anime_multi_ep', None)
autopostprocessor_frequency = self.get_argument('autopostprocessor_frequency', None)
delete_non_associated_files = self.get_argument('delete_non_associated_files', None)
allowed_extensions = self.get_argument('allowed_extensions', None)
processor_follow_symlinks = self.get_argument('processor_follow_symlinks', None)
unpack_dir = self.get_argument('unpack_dir', None)
naming_pattern = self.get_argument('naming_pattern', '')
naming_multi_ep = self.get_argument('naming_multi_ep', '')
kodi_data = self.get_argument('kodi_data', '')
kodi_12plus_data = self.get_argument('kodi_12plus_data', '')
mediabrowser_data = self.get_argument('mediabrowser_data', '')
sony_ps3_data = self.get_argument('sony_ps3_data', '')
wdtv_data = self.get_argument('wdtv_data', '')
tivo_data = self.get_argument('tivo_data', '')
mede8er_data = self.get_argument('mede8er_data', '')
keep_processed_dir = self.get_argument('keep_processed_dir', '')
process_method = self.get_argument('process_method', '')
del_rar_contents = self.get_argument('del_rar_contents', '')
process_automatically = self.get_argument('process_automatically', '')
no_delete = self.get_argument('no_delete', '')
rename_episodes = self.get_argument('rename_episodes', '')
airdate_episodes = self.get_argument('airdate_episodes', '')
file_timestamp_timezone = self.get_argument('file_timestamp_timezone', '')
unpack = self.get_argument('unpack', '')
move_associated_files = self.get_argument('move_associated_files', '')
sync_files = self.get_argument('sync_files', '')
postpone_if_sync_files = self.get_argument('postpone_if_sync_files', '')
nfo_rename = self.get_argument('nfo_rename', '')
tv_download_dir = self.get_argument('tv_download_dir', '')
naming_custom_abd = self.get_argument('naming_custom_abd', '')
naming_anime = self.get_argument('naming_anime', '')
create_missing_show_dirs = self.get_argument('create_missing_show_dirs', '')
add_shows_wo_dir = self.get_argument('add_shows_wo_dir', '')
naming_abd_pattern = self.get_argument('naming_abd_pattern', '')
naming_strip_year = self.get_argument('naming_strip_year', '')
delete_failed = self.get_argument('delete_failed', '')
extra_scripts = self.get_argument('extra_scripts', '')
naming_custom_sports = self.get_argument('naming_custom_sports', '')
naming_sports_pattern = self.get_argument('naming_sports_pattern', '')
naming_custom_anime = self.get_argument('naming_custom_anime', '')
naming_anime_pattern = self.get_argument('naming_anime_pattern', '')
naming_anime_multi_ep = self.get_argument('naming_anime_multi_ep', '')
autopostprocessor_frequency = self.get_argument('autopostprocessor_frequency', '')
delete_non_associated_files = self.get_argument('delete_non_associated_files', '')
allowed_extensions = self.get_argument('allowed_extensions', '')
processor_follow_symlinks = self.get_argument('processor_follow_symlinks', '')
unpack_dir = self.get_argument('unpack_dir', '')
results = []
......@@ -126,8 +126,7 @@ class SavePostProcessingHandler(BaseHandler, ABC):
sickrage.app.config.move_associated_files = checkbox_to_value(move_associated_files)
sickrage.app.config.sync_files = sync_files
sickrage.app.config.postpone_if_sync_files = checkbox_to_value(postpone_if_sync_files)
sickrage.app.config.allowed_extensions = ','.join(
{x.strip() for x in allowed_extensions.split(',') if x.strip()})
sickrage.app.config.allowed_extensions = ','.join({x.strip() for x in allowed_extensions.split(',') if x.strip()})
sickrage.app.config.naming_custom_abd = checkbox_to_value(naming_custom_abd)
sickrage.app.config.naming_custom_sports = checkbox_to_value(naming_custom_sports)
sickrage.app.config.naming_custom_anime = checkbox_to_value(naming_custom_anime)
......@@ -190,13 +189,13 @@ class SavePostProcessingHandler(BaseHandler, ABC):
else:
results.append(_("You tried saving an invalid sports naming config, not saving your sports settings"))
sickrage.app.metadata_providers['kodi'].set_config(kodi_data)
sickrage.app.metadata_providers['kodi_12plus'].set_config(kodi_12plus_data)
sickrage.app.metadata_providers['mediabrowser'].set_config(mediabrowser_data)
sickrage.app.metadata_providers['sony_ps3'].set_config(sony_ps3_data)
sickrage.app.metadata_providers['wdtv'].set_config(wdtv_data)
sickrage.app.metadata_providers['tivo'].set_config(tivo_data)
sickrage.app.metadata_providers['mede8er'].set_config(mede8er_data)
sickrage.app.metadata_providers['kodi'].config = kodi_data
sickrage.app.metadata_providers['kodi_12plus'].config = kodi_12plus_data
sickrage.app.metadata_providers['mediabrowser'].config = mediabrowser_data
sickrage.app.metadata_providers['sony_ps3'].config = sony_ps3_data
sickrage.app.metadata_providers['wdtv'].config = wdtv_data
sickrage.app.metadata_providers['tivo'].config = tivo_data
sickrage.app.metadata_providers['mede8er'].config = mede8er_data
sickrage.app.config.save()
......
......@@ -20,7 +20,9 @@
import importlib
import inspect
import os
import pkgutil
import re
import sys
from xml.etree.ElementTree import ElementTree
import fanart
......@@ -104,19 +106,18 @@ class GenericMetadata(object):
def id(self):
return str(re.sub(r"[^\w\d_]", "_", str(re.sub(r"[+]", "plus", self.name))).lower())
def set_config(self, string):
config_list = [bool(int(x)) for x in string.split('|')]
self.show_metadata = config_list[0]
self.episode_metadata = config_list[1]
self.fanart = config_list[2]
self.poster = config_list[3]
self.banner = config_list[4]
self.episode_thumbnails = config_list[5]
self.season_posters = config_list[6]
self.season_banners = config_list[7]
self.season_all_poster = config_list[8]
self.season_all_banner = config_list[9]
self.enabled = config_list[10]
@property
def config(self):
return "|".join(map(str, map(int, [self.show_metadata, self.episode_metadata, self.fanart, self.poster, self.banner, self.episode_thumbnails,
self.season_posters, self.season_banners, self.season_all_poster, self.season_all_banner, self.enabled])))
@config.setter
def config(self, value):
if not value:
value = '0|0|0|0|0|0|0|0|0|0|0'
self.show_metadata, self.episode_metadata, self.fanart, self.poster, self.banner, self.episode_thumbnails, self.season_posters, \
self.season_banners, self.season_all_poster, self.season_all_banner, self.enabled = tuple(map(bool, value.split('|')))
@staticmethod
def _check_exists(location):
......@@ -869,25 +870,9 @@ class GenericMetadata(object):
class MetadataProviders(dict):
def __init__(self):
super(MetadataProviders, self).__init__()
pregex = re.compile('^(.*)\.py$', re.IGNORECASE)
names = [pregex.match(m) for m in os.listdir(os.path.dirname(__file__)) if "__" not in m]
for name in names:
if not name:
continue
klass = self._get_klass(name.group(1))
if klass:
for (__, name, __) in pkgutil.iter_modules([os.path.dirname(__file__)]):
imported_module = importlib.import_module('.' + name, package='sickrage.metadata')
for __, klass in inspect.getmembers(imported_module,
predicate=lambda o: inspect.isclass(o) and issubclass(o, GenericMetadata) and o is not GenericMetadata):
self[klass().id] = klass()
@staticmethod
def _get_klass(name):
try:
return list(dict(
inspect.getmembers(
importlib.import_module('.{}'.format(name), 'sickrage.metadata'),
predicate=lambda o: inspect.isclass(o) and issubclass(o, GenericMetadata) and o is not GenericMetadata)
).values())[0]
except IndexError:
pass
break
......@@ -23,6 +23,7 @@
import importlib
import inspect
import os
import pkgutil
import re
import sickrage
......@@ -102,25 +103,9 @@ class Notifiers(object):
class NotifierProviders(dict):
def __init__(self):
super(NotifierProviders, self).__init__()
pregex = re.compile('^(.*)\.py$', re.IGNORECASE)
names = [pregex.match(m) for m in os.listdir(os.path.dirname(__file__)) if "__" not in m]
for name in names:
if not name:
continue
klass = self._get_klass(name.group(1))
if klass:
for (__, name, __) in pkgutil.iter_modules([os.path.dirname(__file__)]):
imported_module = importlib.import_module('.' + name, package='sickrage.notifiers')
for __, klass in inspect.getmembers(imported_module,
predicate=lambda o: inspect.isclass(o) and issubclass(o, Notifiers) and o is not Notifiers):
self[klass().id] = klass()
@staticmethod
def _get_klass(name):
try:
return list(dict(
inspect.getmembers(
importlib.import_module('.{}'.format(name), 'sickrage.notifiers'),
predicate=lambda o: inspect.isclass(o) and issubclass(o, Notifiers) and o is not Notifiers)
).values())[0]
except IndexError:
pass
break
......@@ -22,8 +22,10 @@
import datetime
import importlib
import inspect
import itertools
import os
import pkgutil
import random
import re
from base64 import b16encode, b32decode, b64decode
......@@ -511,41 +513,36 @@ class GenericProvider(object):
@classmethod
def getProvider(cls, name):
providerMatch = [x for x in cls.getProviders() if x.name == name]
providerMatch = [x for x in cls.get_providers() if x.name == name]
if len(providerMatch) == 1:
return providerMatch[0]
@classmethod
def getProviderByID(cls, id):
providerMatch = [x for x in cls.getProviders() if x.id == id]
providerMatch = [x for x in cls.get_providers() if x.id == id]
if len(providerMatch) == 1:
return providerMatch[0]
@classmethod
def getProviders(cls):
def get_providers(cls):
modules = [TorrentProvider.type, NZBProvider.type]
for type in []:
modules += cls.loadProviders(type)
modules += cls.load_providers(type)
return modules
@classmethod
def loadProviders(cls, type):
def load_providers(cls, provider_type):
providers = []
pregex = re.compile('^([^_]*?)\.py$', re.IGNORECASE)
path = os.path.join(os.path.dirname(__file__), type)
names = [pregex.match(m) for m in os.listdir(path)]
providers += [cls.loadProvider(name.group(1), type) for name in names if name]
return providers
@classmethod
def loadProvider(cls, name, type, *args, **kwargs):
import inspect
members = dict(
inspect.getmembers(
importlib.import_module('.{}.{}'.format(type, name), 'sickrage.providers'),
lambda x: hasattr(x, 'type') and x not in [NZBProvider, TorrentProvider])
)
return [v for v in members.values() if hasattr(v, 'type') and v.type == type][0](*args, **kwargs)
for (__, name, __) in pkgutil.iter_modules([os.path.join(os.path.dirname(__file__), provider_type)]):
imported_module = importlib.import_module('.{}.{}'.format(provider_type, name), package='sickrage.providers')
for __, klass in inspect.getmembers(imported_module, predicate=lambda o: all([inspect.isclass(o) and issubclass(o, GenericProvider),
o is not NZBProvider, o is not TorrentProvider,
getattr(o, 'type', None) == provider_type])):
providers += [klass()]
break
return providers
class TorrentProvider(GenericProvider):
......@@ -693,8 +690,8 @@ class TorrentProvider(GenericProvider):
return result
@classmethod
def getProviders(cls):
return super(TorrentProvider, cls).loadProviders(cls.type)
def get_providers(cls):
return super(TorrentProvider, cls).load_providers(cls.type)
class NZBProvider(GenericProvider):
......@@ -771,8 +768,8 @@ class NZBProvider(GenericProvider):
return os.path.join(sickrage.app.config.nzb_dir, '{}.nzb'.format(sanitize_file_name(name)))
@classmethod
def getProviders(cls):
return super(NZBProvider, cls).loadProviders(cls.type)
def get_providers(cls):
return super(NZBProvider, cls).load_providers(cls.type)
class TorrentRssProvider(TorrentProvider):
......@@ -887,7 +884,7 @@ class TorrentRssProvider(TorrentProvider):
return True
@classmethod
def getProviders(cls):
def get_providers(cls):
providers = cls.getDefaultProviders()
try:
......@@ -1181,7 +1178,7 @@ class NewznabProvider(NZBProvider):
return results
@classmethod
def getProviders(cls):
def get_providers(cls):
providers = cls.getDefaultProviders()
try:
......@@ -1250,10 +1247,10 @@ class SearchProviders(dict):
self[TorrentRssProvider.type] = {}
def load(self):
self[NZBProvider.type] = dict([(p.id, p) for p in NZBProvider.getProviders()])
self[TorrentProvider.type] = dict([(p.id, p) for p in TorrentProvider.getProviders()])
self[NewznabProvider.type] = dict([(p.id, p) for p in NewznabProvider.getProviders()])
self[TorrentRssProvider.type] = dict([(p.id, p) for p in TorrentRssProvider.getProviders()])
self[NZBProvider.type] = dict([(p.id, p) for p in NZBProvider.get_providers()])
self[TorrentProvider.type] = dict([(p.id, p) for p in TorrentProvider.get_providers()])
self[NewznabProvider.type] = dict([(p.id, p) for p in NewznabProvider.get_providers()])
self[TorrentRssProvider.type] = dict([(p.id, p) for p in TorrentRssProvider.get_providers()])
def sort(self, key=None, randomize=False):
sorted_providers = []
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment