Exemple #1
0
    def __init__(self, item_information):
        self.hash_regex = re.compile(r'btih:(.*?)(?:&|$)')
        self.canceled = False
        self.torrent_cache = TorrentCache()
        self.torrent_threads = ThreadPool()
        self.hoster_threads = ThreadPool()
        self.adaptive_threads = ThreadPool()
        self.item_information = item_information
        self.media_type = self.item_information['info']['mediatype']
        self.torrent_providers = []
        self.hoster_providers = []
        self.adaptive_providers = []
        self.running_providers = []
        self.duration = 0
        self.language = 'en'
        self.sources_information = {
            "adaptiveSources": [],
            "torrentCacheSources": {},
            "hosterSources": {},
            "cloudFiles": [],
            "remainingProviders": [],
            "allTorrents": {},
            "torrents_quality": [0, 0, 0, 0],
            "hosters_quality": [0, 0, 0, 0],
            "cached_hashes": []
        }

        self.hoster_domains = {}
        self.progress = 1
        self.runtime = 0
        self.host_domains = []
        self.host_names = []
        self.timeout = g.get_int_setting('general.timeout')
        self.window = SourceWindowAdapter(self.item_information, self)
        self.session = requests.Session()

        self.silent = g.get_bool_runtime_setting('tempSilent')
class Sources(object):
    """
    Handles fetching and processing of available sources for provided meta data
    """

    def __init__(self, item_information):
        self.hash_regex = re.compile(r'btih:(.*?)(?:&|$)')
        self.canceled = False
        self.torrent_cache = TorrentCache()
        self.torrent_threads = ThreadPool()
        self.hoster_threads = ThreadPool()
        self.adaptive_threads = ThreadPool()
        self.item_information = item_information
        self.media_type = self.item_information['info']['mediatype']
        self.torrent_providers = []
        self.hoster_providers = []
        self.adaptive_providers = []
        self.running_providers = []
        self.language = 'en'
        self.sources_information = {
            "adaptiveSources": [],
            "torrentCacheSources": {},
            "hosterSources": {},
            "cloudFiles": [],
            "remainingProviders": [],
            "allTorrents": {},
            "torrents_quality": [0, 0, 0, 0],
            "hosters_quality": [0, 0, 0, 0],
            "cached_hashes": []
        }

        self.hoster_domains = {}
        self.progress = 1
        self.runtime = 0
        self.host_domains = []
        self.host_names = []
        self.timeout = g.get_int_setting('general.timeout')
        self.window = SourceWindowAdapter(self.item_information, self)
        self.session = requests.Session()

        self.silent = g.get_bool_runtime_setting('tempSilent')

    def get_sources(self, overwrite_torrent_cache=False):
        """
        Main endpoint to initiate scraping process
        :param overwrite_cache:
        :return: Returns (uncached_sources, sorted playable sources, items metadata)
        :rtype: tuple
        """
        try:
            g.log('Starting Scraping', 'debug')
            g.log("Timeout: {}".format(self.timeout), 'debug')
            g.log("Pre-term-enabled: {}".format(g.get_setting("preem.enabled")), 'debug')
            g.log("Pre-term-limit: {}".format(g.get_setting("preem.limit")), 'debug')
            g.log("Pre-term-movie-res: {}".format(g.get_setting("preem.movieres")), 'debug')
            g.log("Pre-term-show-res: {}".format(g.get_setting("preem.tvres")), 'debug')
            g.log("Pre-term-type: {}".format(g.get_setting("preem.type")), 'debug')
            g.log("Pre-term-cloud-files: {}".format(g.get_setting("preem.cloudfiles")), 'debug')
            g.log("Pre-term-adaptive-files: {}".format(g.get_setting("preem.adaptiveSources")), 'debug')

            self._handle_pre_scrape_modifiers()
            self._get_imdb_info()

            if overwrite_torrent_cache:
                self._clear_local_torrent_results()
            else:
                self._check_local_torrent_database()

            self._update_progress()
            if self._prem_terminate():
                return self._finalise_results()

            self._init_providers()

            # Add the users cloud inspection to the threads to be run
            self.torrent_threads.put(self._user_cloud_inspection)

            # Load threads for all sources
            self._create_torrent_threads()
            self._create_hoster_threads()
            self._create_adaptive_threads()

            self.window.create()
            self.window.set_text(g.get_language_string(30054), self.progress, self.sources_information, self.runtime)
            self.window.set_property('process_started', 'true')

            # Keep alive for gui display and threading
            g.log('Entering Keep Alive', 'info')
            start_time = time.time()

            while self.progress < 100 and not g.abort_requested():
                g.log('Remaining Providers {}'.format(self.sources_information["remainingProviders"]))
                if self._prem_terminate() is True or (len(self.sources_information["remainingProviders"]) == 0
                                                      and self.runtime > 5):
                    # Give some time for scrapers to initiate
                    break

                if self.canceled:
                    monkey_requests.PRE_TERM_BLOCK = True
                    break

                self._update_progress()

                try:
                    self.window.set_text("4K: {} | 1080: {} | 720: {} | SD: {}".format(
                        g.color_string(self.sources_information["torrents_quality"][0] +
                                       self.sources_information["hosters_quality"][0]),
                        g.color_string(self.sources_information["torrents_quality"][1] +
                                       self.sources_information["hosters_quality"][1]),
                        g.color_string(self.sources_information["torrents_quality"][2] +
                                       self.sources_information["hosters_quality"][2]),
                        g.color_string(self.sources_information["torrents_quality"][3] +
                                       self.sources_information["hosters_quality"][3]),
                    ), self.progress, self.sources_information, self.runtime)

                except (KeyError, IndexError) as e:
                    g.log('Failed to set window text, {}'.format(e), 'error')

                # Update Progress
                xbmc.sleep(200)
                self.runtime = time.time() - start_time
                self.progress = int(100 - float(1 - (self.runtime / float(self.timeout))) * 100)

            g.log('Exited Keep Alive', 'info')

            return self._finalise_results()

        finally:
            self.window.close()

    def _handle_pre_scrape_modifiers(self):
        """
        Detects preScrape, disables pre-termination and sets timeout to maximum value
        :return:
        :rtype:
        """
        if g.REQUEST_PARAMS.get('action', '') == "preScrape":
            self.silent = True
            self.timeout = 180
            self._prem_terminate = lambda: False  # pylint: disable=method-hidden

    def _create_hoster_threads(self):
        if self._hosters_enabled():
            random.shuffle(self.hoster_providers)
            for i in self.hoster_providers:
                self.hoster_threads.put(self._get_hosters, self.item_information, i)

    def _create_torrent_threads(self):
        if self._torrents_enabled():
            random.shuffle(self.torrent_providers)
            for i in self.torrent_providers:
                self.torrent_threads.put(self._get_torrent, self.item_information, i)

    def _create_adaptive_threads(self):
        for i in self.adaptive_providers:
            self.adaptive_threads.put(self._get_adaptive_sources, self.item_information, i)

    def _check_local_torrent_database(self):
        if g.get_bool_setting('general.torrentCache'):
            self.window.set_text(g.get_language_string(30053), self.progress, self.sources_information, self.runtime)
            self._get_local_torrent_results()

    def _is_playable_source(self):
        source_types = ['cloudFiles', 'adaptiveSources', 'hosterSources', 'torrentCacheSources']
        all_sources = [k for i in [self.sources_information[stype] for stype in source_types] for k in i]
        return False if not len(all_sources) else True

    def _finalise_results(self):
        monkey_requests.allow_provider_requests = False
        self._send_provider_stop_event()

        uncached = [i for i in self.sources_information["allTorrents"].values()
                    if i['hash'] not in self.sources_information['cached_hashes']]

        if not self._is_playable_source():
            self._build_cache_assist()
            g.cancel_playback()
            if self.silent:
                g.notification(g.ADDON_NAME, g.get_language_string(30055))
            return uncached, [], self.item_information

        sorted_sources = SourceSorter(self.media_type).sort_sources(
            list(self.sources_information["torrentCacheSources"].values()),
            list(self.sources_information['hosterSources'].values()),
            self.sources_information['cloudFiles'])
        sorted_sources = self.sources_information['adaptiveSources'] + sorted_sources
        return uncached, sorted_sources, self.item_information

    def _get_imdb_info(self):
        if self.media_type == 'movie':
            # Confirm movie year against IMDb's information
            imdb_id = self.item_information["info"].get("imdb_id")
            if imdb_id is None:
                return
            resp = self._imdb_suggestions(imdb_id)
            year = resp.get('y', self.item_information['info']['year'])
            # title = resp['l']
            # if title != self.item_information['info']['title']:
            #     self.item_information['info'].get('aliases', []).append(self.item_information['info']['title'])
            #     self.item_information['info']['title'] = title
            #     self.item_information['info']['originaltitle'] = title
            if year is not None and year != self.item_information['info']['year']:
                self.item_information['info']['year'] = g.UNICODE(year)

        # else:
        #     resp = self._imdb_suggestions(self.item_information['info']['tvshow.imdb_id'])
        #     year = resp['y']
        #     title = resp['l']
        #     if year != self.item_information['info']['year']:
        #         self.item_information['info']['year'] = g.UNICODE(year)
        #     if self.item_information['info']['tvshowtitle'] != title:
        #         self.item_information['info'].get('aliases', []).append(
        #             self.item_information['info']['tvshowtitle'])
        #         self.item_information['info']['tvshowtitle'] = title
        #         self.item_information['info']['originaltitle'] = title

    def _imdb_suggestions(self, imdb_id):
        try:
            resp = self.session.get('https://v2.sg.media-imdb.com/suggestion/t/{}.json'.format(imdb_id))
            resp = json.loads(resp.text)['d'][0]
            return resp
        except (ValueError, KeyError):
            g.log('Failed to get IMDB suggestion')
            return {}

    def _send_provider_stop_event(self):
        for provider in self.running_providers:
            if hasattr(provider, 'cancel_operations') and callable(provider.cancel_operations):
                provider.cancel_operations()

    @staticmethod
    def _torrents_enabled():
        if (g.get_bool_setting('premiumize.torrents') and g.premiumize_enabled()) \
                or (g.get_bool_setting('rd.torrents') and g.real_debrid_enabled()) \
                or (g.get_bool_setting('alldebrid.torrents') and g.all_debrid_enabled()):
            return True
        else:
            return False

    @staticmethod
    def _hosters_enabled():
        if (g.get_bool_setting('premiumize.hosters') and g.premiumize_enabled()) \
                or (g.get_bool_setting('rd.hosters') and g.real_debrid_enabled()) \
                or (g.get_bool_setting('alldebrid.hosters') and g.all_debrid_enabled()):
            return True
        else:
            return False

    def _store_torrent_results(self, torrent_list):
        if len(torrent_list) == 0:
            return
        self.torrent_cache.add_torrent(self.item_information, torrent_list)

    def _clear_local_torrent_results(self):
        if g.get_bool_setting('general.torrentCache'):
            g.log("Clearing existing local torrent cache items", "info")
            self.torrent_cache.clear_item(self.item_information)

    def _get_local_torrent_results(self):
        relevant_torrents = self.torrent_cache.get_torrents(self.item_information)[:100]

        if len(relevant_torrents) > 0:
            for torrent in relevant_torrents:
                torrent['provider'] = '{} (Local Cache)'.format(torrent['provider'])

                self.sources_information["allTorrents"].update({torrent['hash']: torrent})

            TorrentCacheCheck(self).torrent_cache_check(relevant_torrents, self.item_information)

    @staticmethod
    def _get_best_torrent_to_cache(sources):
        quality_list = ['1080p', '720p', 'SD']
        sources = [i for i in sources if i.get('seeds', 0) != 0 and i.get("magnet")]

        for quality in quality_list:
            quality_filter = [i for i in sources if i['quality'] == quality]
            if len(quality_filter) > 0:
                packtype_filter = [i for i in quality_filter if
                                   i['package'] == 'show' or i['package'] == 'season']
                sorted_list = sorted(packtype_filter, key=lambda k: k['seeds'], reverse=True)
                if len(sorted_list) > 0:
                    return sorted_list[0]
                else:
                    package_type_list = [i for i in quality_filter if i['package'] == 'single']
                    sorted_list = sorted(package_type_list, key=lambda k: k['seeds'], reverse=True)
                    if len(sorted_list) > 0:
                        return sorted_list[0]

        return None

    def _build_cache_assist(self):
        if len(self.sources_information["allTorrents"]) == 0:
            return
        valid_packages = ['show', 'season', 'single']

        if self.media_type == 'episode' and self.item_information['is_airing']:
            valid_packages.remove('show')
            if int(self.item_information['info']['season']) >= int(
                    self.item_information['season_count']):
                valid_packages.remove('season')

        sources = [i for i in self.sources_information['allTorrents'].values() if i['package'] in valid_packages]

        if g.get_bool_setting("general.autocache") and g.get_int_setting('general.cacheAssistMode') == 0:
            sources = self._get_best_torrent_to_cache(sources)
            if sources:
                action_args = tools.quote(json.dumps(sources))
                xbmc.executebuiltin(
                    'RunPlugin({}?action=cacheAssist&action_args={})'.format(g.BASE_URL, action_args))
        elif not self.silent:
            confirmation = xbmcgui.Dialog().yesno('{} - {}'.format(g.ADDON_NAME, g.get_language_string(30325)),
                                                  g.get_language_string(30056))
            if confirmation:
                window = ManualCacheWindow(*SkinManager().confirm_skin_path('manual_caching.xml'),
                                           item_information=self.item_information, sources=sources)
                window.doModal()
                del window

    def _init_providers(self):
        sys.path.append(g.ADDON_USERDATA_PATH)
        try:
            if g.ADDON_USERDATA_PATH not in sys.path:
                sys.path.append(g.ADDON_USERDATA_PATH)
                providers = importlib.import_module("providers")
            else:
                providers = reload_module(importlib.import_module("providers"))
        except ValueError:
            g.notification(g.ADDON_NAME, g.get_language_string(30465))
            g.log('No providers installed', 'warning')
            return

        providers_dict = providers.get_relevant(self.language)

        torrent_providers = providers_dict['torrent']
        hoster_providers = providers_dict['hosters']
        adaptive_providers = providers_dict['adaptive']

        hoster_providers, torrent_providers = self._remove_duplicate_providers(torrent_providers, hoster_providers)

        self.hoster_domains = resolver.Resolver.get_hoster_list()
        self.torrent_providers = torrent_providers
        self.hoster_providers = hoster_providers
        self.adaptive_providers = adaptive_providers
        self.host_domains = OrderedDict.fromkeys([host[0].lower() for provider in self.hoster_domains['premium']
                                                  for host in self.hoster_domains['premium'][provider]])
        self.host_names = OrderedDict.fromkeys([host[1].lower() for provider in self.hoster_domains['premium']
                                                for host in self.hoster_domains['premium'][provider]])

    @staticmethod
    def _remove_duplicate_providers(torrent, hosters):
        temp_list = []
        filter_list = []
        for i in torrent:
            if not i[1] in filter_list:
                temp_list.append(i)
                filter_list.append(i[1])

        torrent = temp_list
        temp_list = []
        for i in hosters:
            if not i[1] in filter_list:
                temp_list.append(i)
                filter_list.append(i[1])

        hosters = temp_list

        return hosters, torrent

    def _exit_thread(self, provider_name):
        if provider_name in self.sources_information["remainingProviders"]:
            self.sources_information["remainingProviders"].remove(provider_name)

    def _process_provider_torrent(self, torrent, provider_name, info):
        torrent['type'] = 'torrent'

        if not torrent.get('info'):
            torrent['info'] = source_utils.get_info(torrent['release_title'])

        torrent['quality'] = torrent.get('quality', '')
        if torrent['quality'] not in approved_qualities:
            torrent['quality'] = source_utils.get_quality(torrent['release_title'])

        torrent['hash'] = torrent.get('hash', self.hash_regex.findall(torrent['magnet'])[0]).lower()
        torrent['size'] = torrent.get('size', 0)
        torrent['size'] = self._torrent_filesize(torrent, info)

        if 'provider_name_override' in torrent:
            torrent['provider'] = torrent['provider_name_override']
        else:
            torrent['provider'] = provider_name

    def _get_adaptive_sources(self, info, provider):
        provider_name = provider[1].upper()
        try:
            self.sources_information["remainingProviders"].append(provider_name)
            provider_module = importlib.import_module('{}.{}'.format(provider[0], provider[1]))
            if not hasattr(provider_module, "sources"):
                g.log('Invalid provider, Source Class missing')
                return
            provider_source = provider_module.sources()

            if not hasattr(provider_source, self.media_type):
                g.log('Skipping provider: {} - Does not support {} types'.format(provider_name, self.media_type),
                      'warning')
                return

            self.running_providers.append(provider_source)

            if self.media_type == 'episode':
                simple_info = self._build_simple_show_info(info)
                results = provider_source.episode(simple_info, info)
            else:
                try:
                    results = provider_source.movie(info['info']['title'],
                                                    g.UNICODE(info['info']['year']),
                                                    info['info'].get('imdb_id'))
                except TypeError:
                    results = provider_source.movie(info['info']['title'],
                                                    g.UNICODE(info['info']['year']))

            if results is None:
                self.sources_information["remainingProviders"].remove(provider_name)
                return

            if self.canceled:
                return

            if len(results) > 0:
                # Begin filling in optional dictionary returns
                for result in results:
                    self._process_adaptive_source(result, provider_name, provider)

                self.sources_information['adaptiveSources'] += results

            self.running_providers.remove(provider_source)

            return
        finally:
            self.sources_information["remainingProviders"].remove(provider_name)

    @staticmethod
    def _process_adaptive_source(source, provider_name, provider_module):
        source['type'] = 'Adaptive'
        source['release_title'] = source.get('release_title', provider_name)
        source['source'] = provider_name.upper()
        source['quality'] = 'Variable'
        source['size'] = 'Variable'
        source['info'] = source.get('info', ['Adaptive Stream'])
        source['debrid_provider'] = provider_name
        source['provider_imports'] = provider_module
        source['provider'] = source.get('provider_name_override', provider_name.upper())
        return source

    def _get_torrent(self, info, provider):
        # Extract provider name from Tuple
        provider_name = provider[1].upper()

        # Begin Scraping Torrent Sources
        try:
            self.sources_information["remainingProviders"].append(provider_name)

            provider_module = importlib.import_module('{}.{}'.format(provider[0], provider[1]))
            if not hasattr(provider_module, "sources"):
                g.log('Invalid provider, Source Class missing')
                return
            provider_source = provider_module.sources()

            if not hasattr(provider_source, self.media_type):
                g.log('Skipping provider: {} - Does not support {} types'.format(provider_name, self.media_type),
                      'warning')
                return

            self.running_providers.append(provider_source)

            if self.media_type == 'episode':
                simple_info = self._build_simple_show_info(info)

                torrent_results = provider_source.episode(simple_info, info)
            else:
                try:
                    torrent_results = provider_source.movie(info['info']['title'],
                                                            g.UNICODE(info['info']['year']),
                                                            info['info'].get('imdb_id'))
                except TypeError:
                    torrent_results = provider_source.movie(info['info']['title'],
                                                            g.UNICODE(info['info']['year']))

            if torrent_results is None:
                self.sources_information["remainingProviders"].remove(provider_name)
                return

            if self.canceled:
                return

            if len(torrent_results) > 0:
                # Begin filling in optional dictionary returns
                for torrent in torrent_results:
                    self._process_provider_torrent(torrent, provider_name, info)

                torrent_results = {value['hash']: value for value in torrent_results}.values()
                start_time = time.time()

                # Check Debrid Providers for cached copies
                self._store_torrent_results(torrent_results)

                if self.canceled:
                    return

                [self.sources_information["allTorrents"].update({torrent['hash']: torrent})
                 for torrent in torrent_results]

                TorrentCacheCheck(self).torrent_cache_check([i for i in torrent_results], info)

                g.log('{} cache check took {} seconds'.format(provider_name, time.time() - start_time))

            self.running_providers.remove(provider_source)

            return
        finally:
            self.sources_information["remainingProviders"].remove(provider_name)

    def _do_hoster_episode(self, provider_source, provider_name, info):
        if not hasattr(provider_source, 'tvshow'):
            return
        imdb, tvdb, title, localtitle, aliases, year = self._build_hoster_variables(info, 'tvshow')

        if self.canceled:
            self._exit_thread(provider_name)
            return

        url = provider_source.tvshow(imdb, tvdb, title, localtitle, aliases, year)

        if self.canceled:
            self._exit_thread(provider_name)
            return

        imdb, tvdb, title, premiered, season, episode = self._build_hoster_variables(info, 'episode')

        if self.canceled:
            self._exit_thread(provider_name)
            return

        url = provider_source.episode(url, imdb, tvdb, title, premiered, season, episode)

        if self.canceled:
            self._exit_thread(provider_name)
            return

        return url

    def _do_hoster_movie(self, provider_source, provider_name, info):
        if not getattr(provider_source, 'movie'):
            self._exit_thread(provider_name)
            return
        imdb, title, localtitle, aliases, year = self._build_hoster_variables(info, 'movie')
        return provider_source.movie(imdb, title, localtitle, aliases, year)

    def _get_hosters(self, info, provider):
        provider_name = provider[1].upper()
        self.sources_information["remainingProviders"].append(provider_name.upper())
        try:
            provider_module = importlib.import_module('{}.{}'.format(provider[0], provider[1]))
            if hasattr(provider_module, "source"):
                provider_class = provider_module.source()
            else:
                self._exit_thread(provider_name)
                return

            self.running_providers.append(provider_class)

            if self.media_type == 'episode':
                sources = self._do_hoster_episode(provider_class, provider_name, info)
            else:
                sources = self._do_hoster_movie(provider_class, provider_name, info)

            if not sources:
                self._exit_thread(provider_name)
                return

            host_dict, hostpr_dict = self._build_hoster_variables(info, 'sources')

            if self.canceled:
                self._exit_thread(provider_name)
                return

            sources = provider_class.sources(sources, host_dict, hostpr_dict)

            if not sources:
                g.log('{}: Found No Sources'.format(provider_name), 'info')
                return

            if self.media_type == 'episode':
                title = '{} - {}'.format(self.item_information['info']['tvshowtitle'],
                                         self.item_information['info']['title'])
            else:
                title = '{} ({})'.format(self.item_information['info']['title'], self.item_information['info']['year'])

            for source in sources:
                source['type'] = 'hoster'
                source['release_title'] = source.get('release_title', title)
                source['source'] = source['source'].upper().split('.')[0]
                source['size'] = source.get('size', '0')
                source['info'] = source.get('info', [])
                source['provider_imports'] = provider
                source['provider'] = source.get('provider_name_override', provider_name.upper())

            sources1 = [i for i in sources for host in self.host_domains if host in i['url']]
            sources2 = [i for i in sources if i['source'].lower() not in self.host_names and i['direct']]

            sources = sources1 + sources2

            self._debrid_hoster_duplicates(sources)
            self._exit_thread(provider_name)

        finally:
            try:
                self.sources_information["remainingProviders"].remove(provider_name)
            except ValueError:
                pass

    def _user_cloud_inspection(self):
        self.sources_information["remainingProviders"].append("Cloud Inspection")
        try:
            thread_pool = ThreadPool()
            if self.media_type == "episode":
                simple_info = self._build_simple_show_info(self.item_information)
            else:
                simple_info = None

            cloud_scrapers = [
                {"setting": "premiumize.cloudInspection", "provider": PremiumizeCloudScaper,
                 "enabled": g.premiumize_enabled()},
                {"setting": "rd.cloudInspection", "provider": RealDebridCloudScraper,
                 "enabled": g.real_debrid_enabled()},
                {"setting": "alldebrid.cloudInspection", "provider": AllDebridCloudScraper,
                 "enabled": g.all_debrid_enabled()},
            ]

            for cloud_scraper in cloud_scrapers:
                if cloud_scraper["enabled"] and g.get_bool_setting(cloud_scraper["setting"]):
                    thread_pool.put(cloud_scraper["provider"](self._prem_terminate).get_sources, self.item_information,
                                    simple_info)

            sources = thread_pool.wait_completion()
            self.sources_information["cloudFiles"] = sources if sources else []

        finally:
            self.sources_information["remainingProviders"].remove("Cloud Inspection")

    @staticmethod
    def _color_number(number):

        if int(number) > 0:
            return g.color_string(number, 'green')
        else:
            return g.color_string(number, 'red')

    def _update_progress(self):
        list1 = [
            len([key for key, value in self.sources_information["torrentCacheSources"].items() if
                 value['quality'] == '4K']),
            len([key for key, value in self.sources_information["torrentCacheSources"].items() if
                 value['quality'] == '1080p']),
            len([key for key, value in self.sources_information["torrentCacheSources"].items() if
                 value['quality'] == '720p']),
            len([key for key, value in self.sources_information["torrentCacheSources"].items() if
                 value['quality'] == 'SD']),
        ]

        self.sources_information["torrents_quality"] = list1

        list2 = [
            len([key for key, value in self.sources_information["hosterSources"].items() if
                 value['quality'] == '4K']),
            len([key for key, value in self.sources_information["hosterSources"].items() if
                 value['quality'] == '1080p']),
            len([key for key, value in self.sources_information["hosterSources"].items() if
                 value['quality'] == '720p']),
            len([key for key, value in self.sources_information["hosterSources"].items() if
                 value['quality'] == 'SD']),

        ]
        self.sources_information["hosters_quality"] = list2

        # string1 = u'{} - 4K: {} | 1080: {} | 720: {} | SD: {}'.format(g.get_language_string(30057),
        #                                                              self._color_number(list1[0]),
        #                                                              self._color_number(list1[1]),
        #                                                              self._color_number(list1[2]),
        #                                                              self._color_number(list1[3]))
        # string2 = u'{} - 4k: {} | 1080: {} | 720: {} | SD: {}'.format(g.get_language_string(30058),
        #                                                              self._color_number(list2[0]),
        #                                                              self._color_number(list2[1]),
        #                                                              self._color_number(list2[2]),
        #                                                              self._color_number(list2[3]))
        #
        # string4 = '{} - 4k: 0 | 1080: 0 | 720: 0 | SD: 0'.format(g.get_language_string(30059))
        # provider_string = ', '.join(g.color_string(i for i in self.sources_information["remainingProviders"]))
        # string3 = '{} - {}'.format(g.get_language_string(30060), provider_string[2:])
        # return [string1, string2, string3, string4]

    @staticmethod
    def _build_simple_show_info(info):
        simple_info = {'show_title': info['info'].get('tvshowtitle', ''),
                       'episode_title': info['info'].get('originaltitle', ''),
                       'year': g.UNICODE(info['info'].get('tvshow.year', info['info'].get('year', ''))),
                       'season_number': g.UNICODE(info['info']['season']),
                       'episode_number': g.UNICODE(info['info']['episode']),
                       'show_aliases': info['info'].get('aliases', []),
                       'country': info['info'].get('country_origin', ''),
                       'no_seasons': g.UNICODE(info.get('season_count', '')),
                       'absolute_number': g.UNICODE(info.get('absoluteNumber', '')),
                       'is_airing': info.get('is_airing', False),
                       'no_episodes': g.UNICODE(info.get('episode_count', '')),
                       'isanime': False}

        if '.' in simple_info['show_title']:
            simple_info['show_aliases'].append(source_utils.clean_title(simple_info['show_title'].replace('.', '')))
        if any(x in i.lower() for i in info['info'].get('genre', ['']) for x in ['anime', 'animation']):
            simple_info['isanime'] = True

        return simple_info

    def _build_hoster_variables(self, info, media_type):

        info = copy.deepcopy(info)

        if media_type == 'tvshow':
            imdb = info['info'].get('imdb_id')
            tvdb = info['info'].get('tvdb_id')
            title = info['info'].get('tvshowtitle')
            localtitle = ''
            aliases = info['info'].get('aliases', [])
            if '.' in title:
                aliases.append(source_utils.clean_title(title.replace('.', '')))
            year = g.UNICODE(info['info']['year'])
            return imdb, tvdb, title, localtitle, aliases, year

        elif media_type == 'episode':
            imdb = info['info'].get('imdb_id')
            tvdb = info['info'].get('tvdb_id')
            title = info['info'].get('title')
            premiered = info['info'].get('premiered')
            season = g.UNICODE(info['info'].get('season'))
            episode = g.UNICODE(info['info'].get('episode'))
            return imdb, tvdb, title, premiered, season, episode
        elif media_type == 'movie':
            imdb = info['info'].get('imdb_id')
            title = info['info'].get('originaltitle')
            localtitle = info['info'].get('title')
            aliases = info['info'].get('aliases', [])
            year = g.UNICODE(info['info'].get('year'))
            return imdb, title, localtitle, aliases, year
        elif media_type == 'sources':
            hostpr_dict = [host[0]
                           for debrid in self.hoster_domains['premium'].values()
                           for host in debrid]
            host_dict = self.hoster_domains['free']
            return host_dict, hostpr_dict

    def _debrid_hoster_duplicates(self, sources):
        updated_sources = {}
        for provider in self.hoster_domains['premium']:
            for hoster in self.hoster_domains['premium'][provider]:
                for source in sources:
                    if hoster[1].lower() == source['source'].lower() or hoster[0].lower() in g.UNICODE(source['url']).lower():
                        source['debrid_provider'] = provider
                        updated_sources.update({"{}_{}".format(provider, source["url"].lower()): source})
        self.sources_information["hosterSources"].update(updated_sources)

    def _get_pre_term_min(self):
        if self.media_type == 'episode':
            prem_min = g.get_int_setting('preem.tvres') + 1
        else:
            prem_min = g.get_int_setting('preem.movieres') + 1
        return prem_min

    def _get_sources_by_resolution(self, resolutions, source_type):
        return [i for i in list(self.sources_information[source_type].values())
                if i and
                'quality' in i and
                any(i['quality'].lower() == r.lower() for r in resolutions)]

    def _prem_terminate(self):  # pylint: disable=method-hidden
        if self.canceled:
            monkey_requests.PRE_TERM_BLOCK = True
            return True

        if g.get_bool_setting('preem.cloudfiles') and len(self.sources_information["cloudFiles"]) > 0:
            monkey_requests.PRE_TERM_BLOCK = True
            return True
        if g.get_bool_setting('preem.adaptiveSources') and len(self.sources_information["adaptiveSources"]) > 0:
            monkey_requests.PRE_TERM_BLOCK = True
            return True
        if not g.get_bool_setting('preem.enabled'):
            return False

        prem_min = self._get_pre_term_min()
        pre_term_log_string = 'Pre-emptively Terminated'

        approved_resolutions = source_utils.get_accepted_resolution_list()
        approved_resolutions.reverse()
        prem_resolutions = approved_resolutions[:prem_min]
        limit = g.get_int_setting('preem.limit')
        preem_type = g.get_int_setting('preem.type')
        try:
            if preem_type == 0 and len(self._get_sources_by_resolution(prem_resolutions, "torrentCacheSources")) >= limit:
                g.log(pre_term_log_string, 'info')
                monkey_requests.PRE_TERM_BLOCK = True
                return True
            if preem_type == 1 and len(self._get_sources_by_resolution(prem_resolutions, "hosterSources")) >= limit:
                g.log(pre_term_log_string, 'info')
                monkey_requests.PRE_TERM_BLOCK = True
                return True
            if preem_type == 2:
                # Terminating on both hosters and torrents
                sources = self._get_sources_by_resolution(prem_resolutions, "hosterSources")
                sources.append(self._get_sources_by_resolution(prem_resolutions, "torrentCacheSources"))

                if len(sources) >= limit:
                    g.log(pre_term_log_string, 'info')
                    monkey_requests.PRE_TERM_BLOCK = True
                    return True

        except (ValueError, KeyError, IndexError):
            pass

        return False

    @staticmethod
    def _torrent_filesize(torrent, info):

        if not torrent.get('size', 0):
            return 0
        size = int(torrent['size'])

        if torrent['package'] == 'show':
            size = size / int(info['show_episode_count'])
        elif torrent['package'] == 'season':
            size = size / int(info['episode_count'])
        return size
Exemple #3
0
def dispatch(params):
    url = params.get("url")
    action = params.get("action")
    action_args = params.get("action_args")
    pack_select = params.get("packSelect")
    source_select = params.get("source_select") == "true"
    overwrite_cache = params.get("seren_reload") == "true"
    resume = params.get("resume")
    force_resume_check = params.get("forceresumecheck") == "true"
    force_resume_off = params.get("forceresumeoff") == "true"
    force_resume_on = params.get("forceresumeon") == "true"
    smart_url_arg = params.get("smartPlay") == "true"
    mediatype = params.get("mediatype")
    endpoint = params.get("endpoint")

    g.log("Seren, Running Path - {}".format(g.REQUEST_PARAMS))

    if action is None:
        from resources.lib.gui import homeMenu

        homeMenu.Menus().home()

    if action == "genericEndpoint":
        if mediatype == "movies":
            from resources.lib.gui.movieMenus import Menus
        else:
            from resources.lib.gui.tvshowMenus import Menus
        Menus().generic_endpoint(endpoint)

    elif action == "forceResumeShow":
        from resources.lib.modules import smartPlay
        from resources.lib.common import tools

        smartPlay.SmartPlay(
            tools.get_item_information(action_args)).resume_show()

    elif action == "moviesHome":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().discover_movies()

    elif action == "moviesUpdated":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_updated()

    elif action == "moviesRecommended":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_recommended()

    elif action == "moviesSearch":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_search(action_args)

    elif action == "moviesSearchResults":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_search_results(action_args)

    elif action == "moviesSearchHistory":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_search_history()

    elif action == "myMovies":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().my_movies()

    elif action == "moviesMyCollection":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().my_movie_collection()

    elif action == "moviesMyWatchlist":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().my_movie_watchlist()

    elif action == "moviesRelated":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_related(action_args)

    elif action == "colorPicker":
        g.color_picker()

    elif action == "authTrakt":
        from resources.lib.indexers import trakt

        trakt.TraktAPI().auth()

    elif action == "revokeTrakt":
        from resources.lib.indexers import trakt

        trakt.TraktAPI().revoke_auth()

    elif action == "getSources" or action == "smartPlay":
        from resources.lib.modules.smartPlay import SmartPlay
        from resources.lib.common import tools
        from resources.lib.modules import helpers

        item_information = tools.get_item_information(action_args)
        smart_play = SmartPlay(item_information)
        background = None
        resolver_window = None

        try:
            # Check to confirm user has a debrid provider authenticated and enabled
            if not g.premium_check():
                xbmcgui.Dialog().ok(
                    g.ADDON_NAME,
                    tools.create_multiline_message(
                        line1=g.get_language_string(30208),
                        line2=g.get_language_string(30209),
                    ),
                )
                return None

            # workaround for widgets not generating a playlist on playback request
            play_list = smart_play.playlist_present_check(smart_url_arg)

            if play_list:
                g.log("Cancelling non playlist playback", "warning")
                xbmc.Player().play(g.PLAYLIST)
                return

            resume_time = smart_play.handle_resume_prompt(
                resume, force_resume_off, force_resume_on, force_resume_check)
            background = helpers.show_persistent_window_if_required(
                item_information)
            sources = helpers.SourcesHelper().get_sources(
                action_args, overwrite_cache=overwrite_cache)

            if sources is None:
                return
            if item_information["info"]["mediatype"] == "episode":
                source_select_style = "Episodes"
            else:
                source_select_style = "Movie"

            if (g.get_int_setting(
                    "general.playstyle{}".format(source_select_style)) == 1
                    or source_select):

                if background:
                    background.set_text(g.get_language_string(30198))
                from resources.lib.modules import sourceSelect

                stream_link = sourceSelect.source_select(
                    sources[0], sources[1], item_information)
            else:
                if background:
                    background.set_text(g.get_language_string(30032))
                stream_link = helpers.Resolverhelper(
                ).resolve_silent_or_visible(sources[1], sources[2],
                                            pack_select)
                if stream_link is None:
                    g.close_busy_dialog()
                    g.notification(g.ADDON_NAME,
                                   g.get_language_string(30033),
                                   time=5000)

            g.show_busy_dialog()

            if background:
                background.close()
                del background

            if not stream_link:
                raise NoPlayableSourcesException

            from resources.lib.modules import player

            player.SerenPlayer().play_source(stream_link,
                                             item_information,
                                             resume_time=resume_time)

        except NoPlayableSourcesException:
            try:
                background.close()
                del background
            except (UnboundLocalError, AttributeError):
                pass
            try:
                resolver_window.close()
                del resolver_window
            except (UnboundLocalError, AttributeError):
                pass

            g.cancel_playback()

    elif action == "preScrape":

        from resources.lib.database.skinManager import SkinManager
        from resources.lib.modules import helpers

        try:
            from resources.lib.common import tools

            item_information = tools.get_item_information(action_args)

            if item_information["info"]["mediatype"] == "episode":
                source_select_style = "Episodes"
            else:
                source_select_style = "Movie"

            sources = helpers.SourcesHelper().get_sources(action_args)
            if (g.get_int_setting(
                    "general.playstyle{}".format(source_select_style)) == 0
                    and sources):
                from resources.lib.modules import resolver

                helpers.Resolverhelper().resolve_silent_or_visible(
                    sources[1], sources[2], pack_select)
        finally:
            g.set_setting("general.tempSilent", "false")

        g.log("Pre-scraping completed")

    elif action == "authRealDebrid":
        from resources.lib.debrid import real_debrid

        real_debrid.RealDebrid().auth()

    elif action == "showsHome":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().discover_shows()

    elif action == "myShows":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_shows()

    elif action == "showsMyCollection":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_shows_collection()

    elif action == "showsMyWatchlist":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_shows_watchlist()

    elif action == "showsMyProgress":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_show_progress()

    elif action == "showsMyRecentEpisodes":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_recent_episodes()

    elif action == "showsRecommended":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_recommended()

    elif action == "showsUpdated":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_updated()

    elif action == "showsSearch":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_search(action_args)

    elif action == "showsSearchResults":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_search_results(action_args)

    elif action == "showsSearchHistory":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_search_history()

    elif action == "showSeasons":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().show_seasons(action_args)

    elif action == "seasonEpisodes":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().season_episodes(action_args)

    elif action == "showsRelated":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_related(action_args)

    elif action == "showYears":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_years(action_args)

    elif action == "searchMenu":
        from resources.lib.gui import homeMenu

        homeMenu.Menus().search_menu()

    elif action == "toolsMenu":
        from resources.lib.gui import homeMenu

        homeMenu.Menus().tools_menu()

    elif action == "clearCache":
        from resources.lib.common import tools

        g.clear_cache()

    elif action == "traktManager":
        from resources.lib.indexers import trakt
        from resources.lib.common import tools

        trakt.TraktManager(tools.get_item_information(action_args))

    elif action == "onDeckShows":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().on_deck_shows()

    elif action == "onDeckMovies":
        from resources.lib.gui.movieMenus import Menus

        Menus().on_deck_movies()

    elif action == "cacheAssist":
        from resources.lib.modules.cacheAssist import CacheAssistHelper

        CacheAssistHelper().auto_cache(action_args)

    elif action == "tvGenres":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_genres()

    elif action == "showGenresGet":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_genre_list(action_args)

    elif action == "movieGenres":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_genres()

    elif action == "movieGenresGet":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_genre_list(action_args)

    elif action == "shufflePlay":
        from resources.lib.modules import smartPlay

        smartPlay.SmartPlay(action_args).shuffle_play()

    elif action == "resetSilent":
        g.set_setting("general.tempSilent", "false")
        g.notification(
            "{}: {}".format(g.ADDON_NAME, g.get_language_string(30329)),
            g.get_language_string(30034),
            time=5000,
        )

    elif action == "clearTorrentCache":
        from resources.lib.database.torrentCache import TorrentCache

        TorrentCache().clear_all()

    elif action == "openSettings":
        xbmc.executebuiltin("Addon.OpenSettings({})".format(g.ADDON_ID))

    elif action == "myTraktLists":
        from resources.lib.modules.listsHelper import ListsHelper

        ListsHelper().my_trakt_lists(mediatype)

    elif action == "myLikedLists":
        from resources.lib.modules.listsHelper import ListsHelper

        ListsHelper().my_liked_lists(mediatype)

    elif action == "TrendingLists":
        from resources.lib.modules.listsHelper import ListsHelper

        ListsHelper().trending_lists(mediatype)

    elif action == "PopularLists":
        from resources.lib.modules.listsHelper import ListsHelper

        ListsHelper().popular_lists(mediatype)

    elif action == "traktList":
        from resources.lib.modules.listsHelper import ListsHelper

        ListsHelper().get_list_items()

    elif action == "nonActiveAssistClear":
        from resources.lib.gui import debridServices

        debridServices.Menus().assist_non_active_clear()

    elif action == "debridServices":
        from resources.lib.gui import debridServices

        debridServices.Menus().home()

    elif action == "cacheAssistStatus":
        from resources.lib.gui import debridServices

        debridServices.Menus().get_assist_torrents()

    elif action == "premiumize_transfers":
        from resources.lib.gui import debridServices

        debridServices.Menus().list_premiumize_transfers()

    elif action == "showsNextUp":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_next_up()

    elif action == "runMaintenance":
        from resources.lib.common import maintenance

        maintenance.run_maintenance()

    elif action == "providerTools":
        from resources.lib.gui import homeMenu

        homeMenu.Menus().provider_menu()

    elif action == "installProviders":
        from resources.lib.modules.providers.install_manager import (
            ProviderInstallManager, )

        ProviderInstallManager().install_package(action_args)

    elif action == "uninstallProviders":
        from resources.lib.modules.providers.install_manager import (
            ProviderInstallManager, )

        ProviderInstallManager().uninstall_package()

    elif action == "showsNew":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_new()

    elif action == "realdebridTransfers":
        from resources.lib.gui import debridServices

        debridServices.Menus().list_rd_transfers()

    elif action == "cleanInstall":
        from resources.lib.common import maintenance

        maintenance.wipe_install()

    elif action == "premiumizeCleanup":
        from resources.lib.common import maintenance

        maintenance.premiumize_transfer_cleanup()

    elif action == "manualProviderUpdate":
        from resources.lib.modules.providers.install_manager import (
            ProviderInstallManager, )

        ProviderInstallManager().manual_update()

    elif action == "clearSearchHistory":
        from resources.lib.database.searchHistory import SearchHistory

        SearchHistory().clear_search_history(mediatype)

    elif action == "externalProviderInstall":
        from resources.lib.modules.providers.install_manager import (
            ProviderInstallManager, )

        confirmation = xbmcgui.Dialog().yesno(g.ADDON_NAME,
                                              g.get_language_string(30182))
        if confirmation == 0:
            return
        ProviderInstallManager().install_package(1, url=url)

    elif action == "externalProviderUninstall":
        from resources.lib.modules.providers.install_manager import (
            ProviderInstallManager, )

        confirmation = xbmcgui.Dialog().yesno(
            g.ADDON_NAME,
            g.get_language_string(30184).format(url))
        if confirmation == 0:
            return
        ProviderInstallManager().uninstall_package(package=url, silent=False)

    elif action == "showsNetworks":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_networks()

    elif action == "showsNetworkShows":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_networks_results(action_args)

    elif action == "movieYears":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_years()

    elif action == "movieYearsMovies":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movie_years_results(action_args)

    elif action == "syncTraktActivities":
        from resources.lib.database.trakt_sync.activities import TraktSyncDatabase

        TraktSyncDatabase().sync_activities()

    elif action == "traktSyncTools":
        from resources.lib.gui import homeMenu

        homeMenu.Menus().trakt_sync_tools()

    elif action == "flushTraktActivities":
        from resources.lib.database import trakt_sync

        trakt_sync.TraktSyncDatabase().flush_activities()

    elif action == "flushTraktDBMeta":
        from resources.lib.database import trakt_sync

        trakt_sync.TraktSyncDatabase().clear_all_meta()

    elif action == "myFiles":
        from resources.lib.gui import myFiles

        myFiles.Menus().home()

    elif action == "myFilesFolder":
        from resources.lib.gui import myFiles

        myFiles.Menus().my_files_folder(action_args)

    elif action == "myFilesPlay":
        from resources.lib.gui import myFiles

        myFiles.Menus().my_files_play(action_args)

    elif action == "forceTraktSync":
        from resources.lib.database.trakt_sync.activities import TraktSyncDatabase

        trakt_db = TraktSyncDatabase()
        trakt_db.flush_activities()
        trakt_db.sync_activities()

    elif action == "rebuildTraktDatabase":
        from resources.lib.database.trakt_sync import TraktSyncDatabase

        TraktSyncDatabase().re_build_database()

    elif action == "myUpcomingEpisodes":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_upcoming_episodes()

    elif action == "myWatchedEpisodes":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().my_watched_episode()

    elif action == "myWatchedMovies":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().my_watched_movies()

    elif action == "showsByActor":
        from resources.lib.gui import tvshowMenus

        tvshowMenus.Menus().shows_by_actor(action_args)

    elif action == "movieByActor":
        from resources.lib.gui import movieMenus

        movieMenus.Menus().movies_by_actor(action_args)

    elif action == "playFromRandomPoint":
        from resources.lib.modules import smartPlay

        smartPlay.SmartPlay(action_args).play_from_random_point()

    elif action == "refreshProviders":
        from resources.lib.modules.providers import CustomProviders

        providers = CustomProviders()
        providers.update_known_providers()
        providers.poll_database()

    elif action == "installSkin":
        from resources.lib.database.skinManager import SkinManager

        SkinManager().install_skin()

    elif action == "uninstallSkin":
        from resources.lib.database.skinManager import SkinManager

        SkinManager().uninstall_skin()

    elif action == "switchSkin":
        from resources.lib.database.skinManager import SkinManager

        SkinManager().switch_skin()

    elif action == "manageProviders":
        g.show_busy_dialog()
        from resources.lib.gui.windows.provider_packages import ProviderPackages
        from resources.lib.database.skinManager import SkinManager

        window = ProviderPackages(
            *SkinManager().confirm_skin_path("provider_packages.xml"))
        window.doModal()
        del window

    elif action == "flatEpisodes":
        from resources.lib.gui.tvshowMenus import Menus

        Menus().flat_episode_list(action_args)

    elif action == "runPlayerDialogs":
        from resources.lib.modules.player import PlayerDialogs

        PlayerDialogs().display_dialog()

    elif action == "authAllDebrid":
        from resources.lib.debrid.all_debrid import AllDebrid

        AllDebrid().auth()

    elif action == "checkSkinUpdates":
        from resources.lib.database.skinManager import SkinManager

        SkinManager().check_for_updates()

    elif action == "authPremiumize":
        from resources.lib.debrid.premiumize import Premiumize

        Premiumize().auth()

    elif action == "testWindows":
        from resources.lib.gui.homeMenu import Menus

        Menus().test_windows()

    elif action == "testPlayingNext":
        from resources.lib.gui import mock_windows

        mock_windows.mock_playing_next()

    elif action == "testStillWatching":
        from resources.lib.gui import mock_windows

        mock_windows.mock_still_watching()

    elif action == "testResolverWindow":
        from resources.lib.gui import mock_windows

        mock_windows.mock_resolver()

    elif action == "testSourceSelectWindow":
        from resources.lib.gui import mock_windows

        mock_windows.mock_source_select()

    elif action == "testManualCacheWindow":
        from resources.lib.gui import mock_windows

        mock_windows.mock_cache_assist()

    elif action == "showsPopularRecent":
        from resources.lib.gui.tvshowMenus import Menus

        Menus().shows_popular_recent()

    elif action == "showsTrendingRecent":
        from resources.lib.gui.tvshowMenus import Menus

        Menus().shows_trending_recent()

    elif action == "moviePopularRecent":
        from resources.lib.gui.movieMenus import Menus

        Menus().movie_popular_recent()

    elif action == "movieTrendingRecent":
        from resources.lib.gui.movieMenus import Menus

        Menus().movie_trending_recent()

    elif action == "setDownloadLocation":
        from resources.lib.modules.download_manager import set_download_location

        set_download_location()

    elif action == "downloadManagerView":
        from resources.lib.gui.windows.download_manager import DownloadManager
        from resources.lib.database.skinManager import SkinManager

        window = DownloadManager(
            *SkinManager().confirm_skin_path("download_manager.xml"))
        window.doModal()
        del window

    elif action == "longLifeServiceManager":
        from resources.lib.modules.providers.service_manager import (
            ProvidersServiceManager, )

        ProvidersServiceManager().run_long_life_manager()

    elif action == "showsRecentlyWatched":
        from resources.lib.gui.tvshowMenus import Menus

        Menus().shows_recently_watched()

    elif action == "toggleLanguageInvoker":
        from resources.lib.common.maintenance import toggle_reuselanguageinvoker
        toggle_reuselanguageinvoker()