def update_properties(self, sources_information): # Set Resolution count properties self.setProperty('4k_sources', g.UNICODE(sources_information["torrents_quality"][0] + sources_information["hosters_quality"][0])) self.setProperty('1080p_sources', g.UNICODE(sources_information["torrents_quality"][1] + sources_information["hosters_quality"][1])) self.setProperty('720p_sources', g.UNICODE(sources_information["torrents_quality"][2] + sources_information["hosters_quality"][2])) self.setProperty('SD_sources', g.UNICODE(sources_information["torrents_quality"][3] + sources_information["hosters_quality"][3])) # Set total source type counts self.setProperty('total_torrents', g.UNICODE(len(sources_information["allTorrents"]))) self.setProperty('cached_torrents', g.UNICODE(len(sources_information["torrentCacheSources"]))) self.setProperty('hosters_sources', g.UNICODE(len(sources_information["hosterSources"]))) self.setProperty('cloud_sources', g.UNICODE(len(sources_information["cloudFiles"]))) self.setProperty('adaptive_sources', g.UNICODE(len(sources_information["adaptiveSources"]))) # Set remaining providers string self.setProperty("remaining_providers_count", g.UNICODE((len(sources_information["remainingProviders"])))) self.setProperty("remaining_providers_list", g.color_string(' | ') .join([i.upper() for i in sources_information["remainingProviders"]])) try: remaining_providers_list = self.getControlList(2000) remaining_providers_list.reset() remaining_providers_list.addItems(sources_information["remainingProviders"]) except Exception: pass
def onInit(self): """ Callback method for Kodi :return: None """ self.display_list = self.getControlList(1000) self.display_list.reset() for idx, i in enumerate(self.sources): menu_item = self.get_list_item_with_properties( self.item_information, i['release_title']) for info in i.keys(): try: value = i[info] if isinstance(value, list): value = [g.UNICODE(k) for k in value] value = ' '.join(sorted(value)) if info == 'size' and value != 'Variable': value = tools.source_size_display(value) menu_item.setProperty(info, g.UNICODE(value).replace('_', ' ')) except UnicodeEncodeError: menu_item.setProperty(info, i[info]) struct_info = source_utils.info_list_to_dict(i.get('info', [])) for prop in struct_info.keys(): menu_item.setProperty('info.{}'.format(prop), struct_info[prop]) self.display_list.addItem(menu_item) self.setFocusId(1000)
def onInit(self): super(ManualCacheWindow, self).onInit() self.display_list = self.getControlList(1000) self.display_list.reset() # self.sources = sorted(self.sources, key=lambda x: int(x['seeds']), reverse=True) for idx, i in enumerate(self.sources): menu_item = xbmcgui.ListItem(label='{}'.format(i['release_title'])) for info in i.keys(): try: value = i[info] if isinstance(value, list): value = ' '.join(sorted([g.UNICODE(k) for k in value])) if info == 'size': value = tools.source_size_display(value) menu_item.setProperty(info, g.UNICODE(value).replace('_', ' ')) except UnicodeEncodeError: menu_item.setProperty(info, i[info]) struct_info = source_utils.info_list_to_dict(i.get('info', [])) for property in struct_info.keys(): menu_item.setProperty('info.{}'.format(property), struct_info[property]) self.display_list.addItem(menu_item) self.setFocusId(1000)
def add_date_properties(self): info = deepcopy(self.item_information['info']) media_type = info.get("mediatype", None) if media_type in [g.MEDIA_SHOW, g.MEDIA_SEASON, g.MEDIA_EPISODE]: # Convert dates to localtime for display g.convert_info_dates(info) try: year, month, day = self.item_information['info'].get( 'aired', '0000-00-00').split('-') self.setProperty('item.info.aired.year', year) self.setProperty('item.info.aired.month', month) self.setProperty('item.info.aired.day', day) except ValueError: pass if 'aired' in info: aired_date = info['aired'] aired_date = tools.parse_datetime(aired_date, g.DATE_TIME_FORMAT) aired_date = aired_date.strftime(xbmc.getRegion('dateshort')) try: aired_date = aired_date[:10] except IndexError: aired_date = "TBA" self.setProperty('item.info.aired', g.UNICODE(aired_date)) if 'premiered' in info: premiered = info['premiered'] premiered = tools.parse_datetime(premiered, g.DATE_TIME_FORMAT) premiered = premiered.strftime(xbmc.getRegion('dateshort')) try: premiered = premiered[:10] except IndexError: premiered = "TBA" self.setProperty('item.info.premiered', g.UNICODE(premiered))
def _flip_info(self, list_item): label = list_item.getLabel() if label in self.current_filters: self.current_filters.remove(label) list_item.setProperty("value", g.UNICODE(False)) else: self.current_filters.add(label) list_item.setProperty("value", g.UNICODE(True))
def _set_menu_item_properties(menu_item, download_info): menu_item.setProperty('speed', download_info['speed']) menu_item.setProperty('progress', g.UNICODE(download_info['progress'])) menu_item.setProperty('filename', download_info['filename']) menu_item.setProperty('eta', download_info['eta']) menu_item.setProperty('filesize', g.UNICODE(download_info['filesize'])) menu_item.setProperty('downloaded', g.UNICODE(download_info['downloaded'])) menu_item.setProperty('hash', g.UNICODE(download_info.get('hash', '')))
def _try_update_mixed_episodes(self, trakt_items): self.insert_trakt_shows( self.filter_trakt_items_that_needs_updating( [i.get("show") for i in trakt_items if i.get("show")], "shows", ) ) if [i for i in trakt_items if not i.get("show")]: [ self.task_queue.put(self._get_single_show_meta, i["trakt_show_id"]) for i in trakt_items if not i.get("show") ] self.task_queue.wait_completion() shows = self.fetchall( """SELECT value as trakt_object, s.trakt_id, s.tvdb_id, s.tmdb_id FROM shows as s INNER JOIN shows_meta as m on m.id = s.trakt_id and m.type='trakt' where s.trakt_id in ({})""".format( ",".join(g.UNICODE(i.get("trakt_show_id")) for i in trakt_items) ) ) self._update_mill_format_shows(shows, True) seasons_to_update = self.filter_items_that_needs_updating( self.fetchall( """SELECT value as trakt_object, se.trakt_id, se.trakt_show_id, sh.tmdb_id as tmdb_show_id, sh.tvdb_id as tvdb_show_id FROM seasons as se INNER JOIN shows as sh on se.trakt_show_id = sh.trakt_id INNER JOIN seasons_meta as sm on sm.id = se.trakt_id and sm.type='trakt' where se.trakt_id in (select e.trakt_season_id FROM episodes e where e.trakt_id in ({}))""".format( ",".join(g.UNICODE(i.get("trakt_id")) for i in trakt_items) ) ), "seasons", ) episodes_to_update = self.filter_items_that_needs_updating( self.fetchall( """SELECT value as trakt_object, e.trakt_id, e.trakt_show_id, sh.tmdb_id as tmdb_show_id, sh.tvdb_id as tvdb_show_id FROM episodes as e INNER JOIN shows as sh on e.trakt_show_id = sh.trakt_id INNER JOIN episodes_meta as em on em.id = e.trakt_id and em.type='trakt' where e.trakt_id in ({})""".format( ",".join(g.UNICODE(i.get("trakt_id")) for i in trakt_items) ) ), "episodes", ) self.parent_task_queue.put(self._update_seasons, seasons_to_update) self.parent_task_queue.put(self._update_episodes, episodes_to_update) self.parent_task_queue.wait_completion() self._format_seasons(seasons_to_update) self._format_episodes(episodes_to_update)
def set_text(self, text, progress, sources_information, runtime): if self.silent: return if self.display_style == 0 and self.dialog: if text is not None: self.dialog.set_property('notification_text', text) self.dialog.update_properties(sources_information) self.dialog.set_property('progress', g.UNICODE(progress)) self.dialog.set_property('runtime', g.UNICODE(runtime)) elif self.display_style == 1 and self.background_dialog: self.background_dialog.update(progress, message=text)
def add_info_properties(self): for i in self.item_information['info'].keys(): value = self.item_information['info'][i] if i == 'aired' or i == 'premiered': continue if i == 'duration': hours, minutes = divmod(value, 60 * 60) self.setProperty('item.info.{}.minutes'.format(i), g.UNICODE(minutes // 60)) self.setProperty('item.info.{}.hours'.format(i), g.UNICODE(hours)) try: self.setProperty('item.info.{}'.format(i), g.UNICODE(value)) except UnicodeEncodeError: self.setProperty('item.info.{}'.format(i), value)
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)
def shows_years(self, year=None): if year is None: current_year = int( tools.parse_datetime(datetime.datetime.today().strftime( g.DATE_FORMAT)).year) all_years = reversed( [year for year in range(1900, current_year + 1)]) menu_items = [] for year in all_years: menu_items.append( g.add_directory_item(g.UNICODE(year), action="showYears", action_args=year, bulk_add=True)) xbmcplugin.addDirectoryItems(g.PLUGIN_HANDLE, menu_items, len(menu_items)) g.close_directory(g.CONTENT_SHOW) else: trakt_list = self.shows_database.extract_trakt_page( "shows/popular", years=year, page=g.PAGE, extended="full", hide_watched=False) self.list_builder.show_list_builder(trakt_list)
def check_for_addon_update(): """ Perform checks for addon updates and notify user of any available updates :return: None :rtype: None """ if not g.get_bool_setting("general.checkAddonUpdates"): return if "-" in g.VERSION: g.set_setting("addon.updateCheckTimeStamp", g.UNICODE(time.time())) return update_timestamp = g.get_float_setting("addon.updateCheckTimeStamp") if time.time() > (update_timestamp + (24 * (60 * 60))): repo_xml = requests.get( "https://github.com/Newf276/Newf276/raw/master/packages/addons.xml" ) if not repo_xml.status_code == 200: g.log( "Could not connect to repo XML, status: {}".format( repo_xml.status_code ), "error", ) return try: xml = tools.ElementTree.fromstring(repo_xml.text) for dir_tag in xml.iterfind("./addon[@id='repository.Newf276']/extension/dir"): minversion = dir_tag.get('minversion') maxversion = dir_tag.get('maxversion') if ( ( minversion is None and maxversion is None ) or ( minversion and maxversion and tools.compare_version_numbers(minversion, g.KODI_FULL_VERSION, include_same=True) and tools.compare_version_numbers(g.KODI_FULL_VERSION, maxversion, include_same=True) ) or ( maxversion is None and minversion and tools.compare_version_numbers(minversion, g.KODI_FULL_VERSION, include_same=True) ) or ( minversion is None and maxversion and tools.compare_version_numbers(g.KODI_FULL_VERSION, maxversion, include_same=True) ) ): repo_version = _get_latest_repo_version(dir_tag.find('info').text) if tools.compare_version_numbers(g.CLEAN_VERSION, repo_version): xbmcgui.Dialog().ok( g.ADDON_NAME, g.get_language_string(30199).format(repo_version) ) except tools.ElementTree.ParseError as pe: g.log("Could not parse repo XML", "error") finally: g.set_setting("addon.updateCheckTimeStamp", str(time.time()))
def _get_progress_string(self): return self.progress_message.format( g.color_string(self.status.title()), g.color_string(g.UNICODE(self.current_percent) + ' %'), g.color_string(self.get_display_speed()), g.color_string(self.seeds), )
def set_property(self, key, value): if self.silent: return if self.display_style == 0 and self.dialog: self.dialog.set_property(key, g.UNICODE(value)) elif self.display_style == 1: return
def set_progress(self, progress): if self.silent: return if self.display_style == 0 and self.dialog: self.dialog.set_property('progress', g.UNICODE(progress)) elif self.display_style == 1 and self.background_dialog: self.background_dialog.update(progress)
def setSetting(self, key, value): if not self._current_user_settings: self._load_user_settings() self._current_user_settings.update( {key: { "value": g.UNICODE(value) }})
def run(self): """ Executes the workload :return: :rtype: """ while not self.tasks.empty() and not self.stop_flag.is_set(): try: func, result_callback, args, kwargs = self.tasks.get( timeout=0.1) self.name = g.UNICODE(func) result_callback(func(*args, **kwargs)) except Empty: break except BaseException as ex: g.log_stacktrace() self.exception_handler(ex) break finally: try: self.tasks.task_done() except Exception as e: print("task done error: {}".format(repr(e))) pass
def _connection_failure_dialog(): if (g.get_float_setting("general.trakt.failure.timeout") + (2 * 60 * (60 * 60)) < time.time() and not xbmc.Player().isPlaying()): xbmcgui.Dialog().notification( g.ADDON_NAME, g.get_language_string(30024).format("Trakt")) g.set_setting("general.trakt.failure.timeout", g.UNICODE(time.time()))
def get_mixed_episode_list(self, trakt_items, **params): """ Returns a list of mixed episodes from different or same show :param trakt_items: List of show & episodes object pairs :type trakt_items: list :return: List of episode objects with full meta :rtype: list """ g.log("Fetching mixed episode list from sync database", "debug") self._try_update_mixed_episodes(trakt_items) in_predicate = ",".join([ g.UNICODE(i["trakt_id"]) for i in trakt_items if i["trakt_id"] is not None ]) if g.get_bool_setting("general.showRemainingUnwatched"): query = """SELECT e.trakt_id, e.info, e.cast, e.art, e.args, e.watched as play_count, b.resume_time as resume_time, b.percent_played as percent_played, se.watched_episodes, se.unwatched_episodes, se.episode_count FROM episodes as e INNER JOIN seasons se on e.trakt_season_id = se.trakt_id LEFT JOIN bookmarks as b on e.Trakt_id = b.Trakt_id WHERE e.trakt_id in ({})""".format( in_predicate) else: query = """SELECT e.trakt_id, e.info, e.cast, e.art, e.args, e.watched as play_count, b.resume_time as resume_time, b.percent_played as percent_played FROM episodes as e LEFT JOIN bookmarks as b on e.Trakt_id = b.Trakt_id WHERE e.trakt_id in ({})""".format(in_predicate) if params.pop("hide_unaired", self.hide_unaired): query += " AND Datetime(e.air_date) < Datetime('now') " if params.pop("hide_specials", self.hide_specials): query += " AND e.season != 0" if params.pop("hide_watched", self.hide_watched): query += " AND e.watched = 0" return MetadataHandler.sort_list_items( self.execute_sql(query).fetchall(), trakt_items)
def get_show_list(self, trakt_list, **params): """ Takes in a list of shows from a Trakt endpoint, updates meta where required and returns the formatted list :param trakt_list: List of shows to retrieve :type trakt_list: list :return: List of updated shows with full meta :rtype: list """ g.log("Fetching show list from sync database", "debug") trakt_list = [i for i in trakt_list if i.get("trakt_id")] self.insert_trakt_shows( self.filter_trakt_items_that_needs_updating(trakt_list, "shows") ) self._update_mill_format_shows(trakt_list, False) g.log("Show list update and milling compelete", "debug") statement = """SELECT s.trakt_id, s.info, s.cast, s.art, s.args, s.watched_episodes, s.unwatched_episodes, s.episode_count, s.season_count FROM shows as s WHERE s.trakt_id in ({}) """.format( ",".join((g.UNICODE(i.get("trakt_id")) for i in trakt_list)) ) if params.pop("hide_unaired", self.hide_unaired): statement += " AND Datetime(s.air_date) < Datetime('now')" if params.pop("hide_watched", self.hide_watched): statement += " AND s.watched_episodes < s.episode_count" return MetadataHandler.sort_list_items( self.fetchall(statement), trakt_list )
def add_id_properties(self): id_dict = {} [ id_dict.update({i.split('_')[0]: self.item_information['info'][i]}) for i in self.item_information['info'].keys() if i.endswith('id') ] for id, value in id_dict.items(): self.setProperty('item.ids.{}_id'.format(id), g.UNICODE(value))
def set_stats_property(source_type, quality, filtered=False): property = "{}_{}".format(source_type, quality) if filtered: property += "_filtered" stat = source_statistics['filtered'][source_type][quality] else: stat = source_statistics[source_type][quality] self.setProperty(property, g.UNICODE(stat))
def add_id_properties(self): id_dict = { k: self.item_information["info"][k] for k in self.item_information["info"] if k.endswith("_id") } for key, value in id_dict.items(): self.setProperty("item.ids.{}".format(key), g.UNICODE(value))
def _retry_handler(self, exception): if (isinstance(exception, sqlite3.OperationalError) and # pylint: disable=no-member "database is locked" in g.UNICODE(exception)): g.log( "database is locked waiting: {}".format(self.path), "warning", ) g.wait_for_abort(0.1) else: super(SQLiteConnection, self)._retry_handler(exception)
def movies_years(): from datetime import datetime year = int(datetime.today().year) for year in range(year, 1899, -1): g.add_directory_item(g.UNICODE(year), action="movieYearsMovies", action_args=year) g.close_directory(g.CONTENT_MENU)
def execute_sql(self, query, data=None): retries = 0 self._register_pickler_adapters() monitor = xbmc.Monitor() with self._get_connection() as connection: while not retries == 50 and not monitor.abortRequested( ) and not self._exit: try: if isinstance(query, list) or isinstance( query, types.GeneratorType): if g.PLATFORM == 'xbox': results = [] for i in query: results.append( self._execute_query( data, connection.cursor(), i)) connection.commit() return results else: return [ self._execute_query(data, connection.cursor(), i) for i in query ] if g.PLATFORM == "xbox": results = self._execute_query(data, connection.cursor(), query) connection.commit() return results else: return self._execute_query(data, connection.cursor(), query) except sqlite3.OperationalError as error: if "database is locked" in g.UNICODE(error): g.log( "database is locked waiting: {}".format( self._db_file), "warning", ) monitor.waitForAbort(0.1) else: self._log_error(query, data) raise except (RuntimeError, InterfaceError): if retries >= 2: self._log_error(query, data) raise monitor.waitForAbort(0.1) except: self._log_error(query, data) raise retries += 1 connection.commit() return None
def _handle_episode_title_appending(name, item, title_append_style): if title_append_style == "1": name = "{}x{} {}".format( g.UNICODE(item["info"]["season"]).zfill(2), g.UNICODE(item["info"]["episode"]).zfill(2), name, ) elif title_append_style == "2": name = "{}: {}".format(g.color_string(item["info"]["tvshowtitle"]), name) elif title_append_style == "3": name = "{}: {}x{} {}".format( g.color_string(item["info"]["tvshowtitle"]), g.UNICODE(item["info"]["season"]).zfill(2), g.UNICODE(item["info"]["episode"]).zfill(2), name, ) return name
def list_rd_transfers(self): from resources.lib.debrid import real_debrid transfer_list = real_debrid.RealDebrid().list_torrents() if len(transfer_list) == 0: g.close_directory(self.view_type) return for i in transfer_list: title = '{} - {}% : {}' \ .format(g.color_string(i['status'].title()), g.UNICODE(i['progress']), i['filename'][:50] + "...") g.add_directory_item(title) g.close_directory(self.view_type)
def list_premiumize_transfers(self): from resources.lib.debrid import premiumize transfer_list = premiumize.Premiumize().list_transfers() if len(transfer_list['transfers'] ) == 0 or 'transfers' not in transfer_list: g.close_directory(self.view_type) return for i in transfer_list['transfers']: title = '{} - {}% : {}' \ .format(g.color_string(i['status'].title()), g.UNICODE(i['progress'] * 100), i['name'][:50] + "...") g.add_directory_item(title) g.close_directory(self.view_type)
def _save_settings(self, response): if "access_token" in response: g.set_setting("trakt.auth", response["access_token"]) self.access_token = response["access_token"] if "refresh_token" in response: g.set_setting("trakt.refresh", response["refresh_token"]) self.refresh_token = response["refresh_token"] if "expires_in" in response and "created_at" in response: g.set_setting( "trakt.expires", g.UNICODE(response["created_at"] + response["expires_in"])) self.token_expires = float(response["created_at"] + response["expires_in"])