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
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()