def get_unfinished_collected_shows(self, page=1): """ Returns a list of shows the user has collected but not completed watching :param page: Page to request :type page: int :return: List of show objects :rtype: list """ paginate = g.get_bool_setting("general.paginatecollection") sort = g.get_int_setting("general.sortcollection") sort_direction = g.get_int_setting("general.sortcollection.direction") query = """select m.id as trakt_id, value as trakt_object from shows_meta as m inner join( select ep.trakt_show_id, max(ep.collected_at) as collected_at from episodes as ep where ep.season != 0 and ep.watched = 0 and ep.collected = 1 GROUP BY ep.trakt_show_id HAVING count(*) > 0) as u on u.trakt_show_id = m.id and m.type='trakt'""" if sort_direction == 0: sort_direction = "asc" elif sort_direction == 1: sort_direction = "desc" if sort == 0: query += " ORDER BY collected_at " + sort_direction if paginate and not sort == 1: query += " LIMIT {} OFFSET {}".format(self.page_limit, self.page_limit * (page - 1)) return self.execute_sql(query).fetchall()
def _apply_size_limits(self): if g.get_bool_setting("general.enablesizelimit"): if self.media_type == "episode": size_limit = g.get_int_setting( "general.sizelimit.episode") * 1024 size_minimum = int( g.get_float_setting("general.sizeminimum.episode") * 1024) else: size_limit = g.get_int_setting( "general.sizelimit.movie") * 1024 size_minimum = int( g.get_float_setting("general.sizeminimum.movie") * 1024) self._filter_all_by_methods([ lambda i: size_limit >= int(i.get("size", 0)) >= size_minimum ]) if g.get_bool_setting("general.sizeperminlimit"): if self.media_type == "episode": sizepermin_limit = g.get_int_setting( "general.sizeperminlimit.episode") else: sizepermin_limit = g.get_int_setting( "general.sizeperminlimit.movie") self._filter_all_by_methods([ lambda i: (int(i.get('size', 0)) / self.duration) < sizepermin_limit ])
def get_debrid_priorities(): """ Gets priorities of each debrid provider :return: Returns a list of dictionaries providing priorities of each debrid provider """ p = [] if g.get_bool_setting('premiumize.enabled'): p.append({ 'slug': 'premiumize', 'priority': g.get_int_setting('premiumize.priority') }) if g.get_bool_setting('realdebrid.enabled'): p.append({ 'slug': 'real_debrid', 'priority': g.get_int_setting('rd.priority') }) if g.get_bool_setting('alldebrid.enabled'): p.append({ 'slug': 'all_debrid', 'priority': g.get_int_setting('alldebrid.priority') }) p = sorted(p, key=lambda i: i['priority']) return p
def get_collected_shows(self, page=1, force_all=False): """ Returns all shows marked as collected from the database :param page: Page to pull :type page: int :param force_all: Enforce pulling of all items :type force_all: bool :return: List of show records :rtype: list """ paginate = g.get_bool_setting("general.paginatecollection") sort = g.get_int_setting("general.sortcollection") sort_direction = g.get_int_setting("general.sortcollection.direction") query = """select e.trakt_show_id as trakt_id, m.value as trakt_object from episodes as e left join shows as sh on sh.trakt_id = e.trakt_show_id left join shows_meta as m on m.id = e.trakt_show_id and m.type='trakt' where e.collected = 1 group by e.trakt_show_id""" if sort_direction == 0: sort_direction = "asc" elif sort_direction == 1: sort_direction = "desc" if sort == 0: query += " ORDER BY max(e.collected_at) " + sort_direction if paginate and not (force_all or sort == 1): query += " LIMIT {} OFFSET {}".format(self.page_limit, self.page_limit * (page - 1)) return self.execute_sql(query).fetchall()
def _apply_size_limits(self): if g.get_bool_setting("general.enablesizelimit"): if self.media_type == "episode": size_limit = g.get_int_setting( "general.sizelimit.episode") * 1024 else: size_limit = g.get_int_setting( "general.sizelimit.movie") * 1024 self._filter_all_by_methods( [lambda i: int(i.get("size", 0)) < size_limit])
def __init__(self): self.date_delay = g.get_bool_setting("general.datedelay") self.title_appends_mixed = g.get_setting("general.appendtitles") self.title_appends_general = g.get_setting( "general.appendepisodegeneral") self.flatten_episodes = g.get_bool_setting("general.flatten.episodes") self.page_limit = g.get_int_setting("item.limit") self.hide_unaired = g.get_bool_setting("general.hideUnAired") self.list_title_appends = g.get_int_setting("general.appendListTitles") self.show_original_title = g.get_bool_setting( "general.meta.showoriginaltitle", False)
def get_accepted_resolution_set(): """ Fetches set of accepted resolutions per settings :return: set of resolutions :rtype set """ resolutions = ["4K", "1080p", "720p", "SD"] max_res = g.get_int_setting("general.maxResolution") min_res = g.get_int_setting("general.minResolution") return set(resolutions[max_res:min_res + 1])
def __init__(self): self.date_delay = g.get_bool_setting("general.datedelay") self.title_appends_mixed = g.get_setting("general.appendtitles") self.title_appends_general = g.get_setting( "general.appendepisodegeneral") self.flatten_episodes = g.get_bool_setting("general.flatten.episodes") self.page_limit = g.get_int_setting("item.limit") self.movie_action = g.get_int_setting("general.movieDefaultAction") self.episode_action = g.get_int_setting("general.episodeDefaultAction") self.hide_unaired = g.get_bool_setting("general.hideUnAired") self.list_title_appends = g.get_setting("general.appendListTitles")
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() prem_resolutions = approved_resolutions[prem_min:] limit = g.get_int_setting('preem.limit') type = g.get_int_setting('preem.type') try: if 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 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 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
def my_show_progress(self): no_paging = not g.get_bool_setting("general.paginatecollection") sort = "title" if g.get_int_setting("general.sortcollection") == 1 else False sort_direction = g.get_int_setting("general.sortcollection.direction") trakt_list = self.trakt_database.get_unfinished_collected_shows(g.PAGE) if sort == "title" and not no_paging: trakt_list = sorted(trakt_list, key=lambda k: re.sub(r"^a |^the |^an ", "", k["trakt_object"]["info"].get('title').lower())) offset = (g.PAGE - 1) * self.page_limit trakt_list = trakt_list[offset:offset + self.page_limit] if sort == "title" and sort_direction == 1: trakt_list.reverse() self.list_builder.show_list_builder(trakt_list, no_paging=no_paging, sort=sort)
def movies_genre_list(self, args): trakt_endpoint = ( "trending" if g.get_int_setting("general.genres.endpoint") == 0 else "popular" ) if args is None: genre_display_list = [] genres = self.trakt.get_json("genres/movies") for genre in genres: genre_display_list.append(genre["name"]) genre_multiselect = xbmcgui.Dialog().multiselect( "{}: {}".format(g.ADDON_NAME, g.get_language_string(30330)), genre_display_list, ) if genre_multiselect is None: return genre_string = ",".join([genres[i]["slug"] for i in genre_multiselect]) else: genre_string = tools.unquote(args) trakt_list = self.trakt.get_json_cached( "movies/{}".format(trakt_endpoint), page=g.PAGE, extended="full" ) if trakt_list is None: g.cancel_directory() return self.list_builder.movie_menu_builder(trakt_list, next_args=genre_string)
def __init__(self): self.apiKey = g.get_setting("tmdb.apikey", "9f3ca569aa46b6fb13931ec96ab8ae7e") self.lang_code = g.get_language_code() self.lang_full_code = g.get_language_code(True) self.lang_region_code = self.lang_full_code.split("-")[1] if self.lang_region_code == "": self.lang_full_code = self.lang_full_code.strip("-") self.include_languages = [ self.lang_code, "en", "null" ] if not self.lang_code == "en" else ["en", "null"] self.preferred_artwork_size = g.get_int_setting( "artwork.preferredsize") self.artwork_size = {} self._set_artwork() self.art_normalization = [ ("backdrops", "fanart", None), ( "posters", "poster", lambda x: x["iso_639_1"] != "xx" and x["iso_639_1"] is not None, ), ( "posters", "keyart", lambda x: x["iso_639_1"] == "xx" or x["iso_639_1"] is None, ), ("stills", "fanart", None), ]
def __init__(self): self.session = requests.Session() self.session.mount("https://", HTTPAdapter(max_retries=self.retries)) self._load_settings() self.lang_code = g.get_language_code(False) self.languages = ([None, self.lang_code] if self.lang_code != "en" and any(self.lang_code == i["abbreviation"] for i in self.supported_languages) else [None]) if not self.jwToken: self.init_token() else: self.try_refresh_token() self.preferred_artwork_size = g.get_int_setting( "artwork.preferredsize") self.meta_hash = tools.md5_hash(( self.lang_code, self.art_map, self.baseUrl, self.imageBaseUrl, self.preferred_artwork_size, ))
def __init__(self, item_information): """ Handles sorting of sources according to users preference """ self.item_information = item_information self.mediatype = self.item_information['info']['mediatype'] # Filter settings self.resolution_set = get_accepted_resolution_set() self.disable_dv = False self.disable_hdr = False self.filter_set = self._get_filters() # Size filter settings self.enable_size_limit = g.get_bool_setting("general.enablesizelimit") setting_mediatype = g.MEDIA_EPISODE if self.mediatype == g.MEDIA_EPISODE else g.MEDIA_MOVIE self.size_limit = g.get_int_setting("general.sizelimit.{}".format(setting_mediatype)) * 1024 self.size_minimum = int(g.get_float_setting("general.sizeminimum.{}".format(setting_mediatype)) * 1024) # Sort Settings self.quality_priorities = { "4K": 3, "1080p": 2, "720p": 1, "SD": 0 } # Sort Methods self._get_sort_methods()
def __init__(self): self.apiKey = g.get_setting("tvdb.apikey", "43VPI0R8323FB7TI") self.jwToken = g.get_setting("tvdb.jw") self.tokenExpires = g.get_float_setting("tvdb.expiry") self.lang_code = g.get_language_code(False) self.languages = ([None, self.lang_code] if self.lang_code != "en" and any(self.lang_code == i["abbreviation"] for i in self.supported_languages) else [None]) if not self.jwToken: self.init_token() else: self.try_refresh_token() self.preferred_artwork_size = g.get_int_setting( "artwork.preferredsize") self.meta_hash = tools.md5_hash(( self.lang_code, self.art_map, self.baseUrl, self.imageBaseUrl, self.preferred_artwork_size, ))
def __init__(self, xml_file, xml_location, item_information=None): try: super(SkipIntro, self).__init__(xml_file, xml_location, item_information=item_information) self.playing_file = self.getPlayingFile() self.duration = g.get_int_setting("skip.intro.open.time") self.closed = False self.skip_intro = g.get_bool_setting("skip.intro.dialog") self.skip_intro_open_time = g.get_int_setting( "skip.intro.open.time") self.skip_intro_time = g.get_int_setting("skip.intro.time") self.skip_intro_activated_time = 0 except: g.log_stacktrace()
def movies_genre_list(self, args): if args is None: genre_display_list = [] genres = self.trakt_api.get_json_cached("genres/movies") for genre in genres: gi = xbmcgui.ListItem(genre["name"]) gi.setArt( {"thumb": "{}{}.png".format(g.GENRES_PATH, genre["slug"])}) genre_display_list.append(gi) genre_multiselect = xbmcgui.Dialog().multiselect( "{}: {}".format(g.ADDON_NAME, g.get_language_string(30303)), genre_display_list, useDetails=True) if genre_multiselect is None: return genre_string = ",".join( [genres[i]["slug"] for i in genre_multiselect]) else: genre_string = tools.unquote(args) trakt_list = self.movies_database.extract_trakt_page( "movies/{}".format("trending" if g.get_int_setting( "general.genres.endpoint.movies") == 0 else "popular"), genres=genre_string, page=g.PAGE, extended="full") if trakt_list is None: g.cancel_directory() return self.list_builder.movie_menu_builder(trakt_list, next_args=genre_string)
def __init__(self): self.trakt = TraktAPI() self.movies_database = movies.TraktSyncDatabase() self.list_builder = ListBuilder() self.page_limit = g.get_int_setting("item.limit") self.page_start = (g.PAGE-1)*self.page_limit self.page_end = g.PAGE*self.page_limit
def __init__(self, ): super(TraktSyncDatabase, self).__init__(g.TRAKT_SYNC_DB_PATH, schema, migrate_db_lock) self.metadataHandler = MetadataHandler() self.trakt_api = TraktAPI() self.activities = {} self.item_list = [] self.base_date = "1970-01-01T00:00:00" self.task_queue = ThreadPool() self.mill_task_queue = ThreadPool() self.parent_task_queue = ThreadPool() self.refresh_activities() # If you make changes to the required meta in any indexer that is cached in this database # You will need to update the below version number to match the new addon version # This will ensure that the metadata required for operations is available self.last_meta_update = "2.0.0" if self.activities is None: self.clear_all_meta(False) self.set_base_activities() if self.activities is not None: self._check_database_version() self.notification_prefix = "{}: Trakt".format(g.ADDON_NAME) self.hide_unaired = g.get_bool_setting("general.hideUnAired") self.hide_specials = g.get_bool_setting("general.hideSpecials") self.hide_watched = g.get_bool_setting("general.hideWatched") self.date_delay = g.get_bool_setting("general.datedelay") self.page_limit = g.get_int_setting("item.limit")
def premiumize_transfer_cleanup(): """ Cleanup transfers created by Seren at Premiumize :return: None :rtype: NOne """ service = premiumize.Premiumize() premiumize_transfers = PremiumizeTransfers() fair_usage = int(service.get_used_space()) threshold = g.get_int_setting("premiumize.threshold") if fair_usage < threshold: g.log("Premiumize Fair Usage below threshold, no cleanup required") return seren_transfers = premiumize_transfers.get_premiumize_transfers() if seren_transfers is None: g.log("Failed to cleanup transfers, API error", "error") return if len(seren_transfers) == 0: g.log("No Premiumize transfers have been created") return g.log( "Premiumize Fair Usage is above threshold, cleaning up Seren transfers" ) for i in seren_transfers: service.delete_transfer(i["transfer_id"]) premiumize_transfers.remove_premiumize_transfer(i["transfer_id"])
def shows_genre_list(self, args): trakt_endpoint = ("trending" if g.get_int_setting("general.genres.endpoint") == 0 else "popular") if args is None: genre_display_list = [] genre_string = "" genres = self.trakt.get_json_cached("genres/shows") for genre in genres: genre_display_list.append(genre["name"]) genre_multiselect = xbmcgui.Dialog().multiselect( "{}: {}".format(g.ADDON_NAME, g.get_language_string(30330)), genre_display_list, ) if genre_multiselect is None: return for selection in genre_multiselect: genre_string += ", {}".format(genres[selection]["slug"]) genre_string = genre_string[2:] else: genre_string = tools.unquote(args) trakt_list = self.shows_database.extract_trakt_page( "shows/{}".format(trakt_endpoint), genres=genre_string, page=g.PAGE, extended="full") if trakt_list is None: g.cancel_directory() return self.list_builder.show_list_builder(trakt_list, next_args=genre_string)
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__(self, media_type, uncached=False): """ Handles sorting of sources according to users preference :param media_type: Type of media to be sorted (movie/episode) :type media_type: str :param uncached: Whether to include uncached torrents or not :type uncached: bool """ self.sort_method = g.get_int_setting("general.sortsources") self.resolution_list = reversed(get_accepted_resolution_list()) self.media_type = media_type self.torrent_list = [] self.hoster_list = [] self.cloud_files = [] self.source_types = ["torrent_list", "hoster_list", "cloud_files"] self.debrid_priorities = get_debrid_priorities() self._resolution_lambda = lambda i, j, k: i == k["quality"] and \ (j["slug"] == k.get("debrid_provider", "") or (not k.get("debrid_provider", "") and uncached)) self.group_style = [ self._group_method_zero, self._group_method_one, self._group_method_two, lambda: self.torrent_list + self.hoster_list + self.cloud_files ]
def auto_cache(self, torrent_list): """ NOTE: This entry is locking :param torrent_list: LIST :return: None """ if not torrent_list: return debrid_class = self.locations[g.get_int_setting( "general.cachelocation")][1] if len(torrent_list) == 0: selected_source = torrent_list[0] else: selected_source = _approx_best_source(torrent_list) try: debrid_class = debrid_class(selected_source) debrid_class.status_update_loop() except DebridNotEnabled: tools.log( "Failed to start cache assist as selected debrid provider is not enabled or setup correctly", "error", ) return xbmcgui.Dialog().notification(g.ADDON_NAME, g.get_language_string(30483))
def __init__(self): super(SerenPlayer, self).__init__() self._trakt_api = trakt.TraktAPI() self.trakt_id = None self.mediatype = None self.offset = None self.playing_file = None self.scrobbling_enabled = g.get_bool_setting("trakt.scrobbling") self.item_information = None self.smart_playlists = g.get_bool_setting("smartplay.playlistcreate") self.default_action = g.get_int_setting("smartplay.defaultaction") self.smart_module = None self.current_time = 0 self.total_time = 0 self.watched_percentage = 0 self.ignoreSecondsAtStart = g.get_int_setting( "trakt.ignoreSecondsAtStart") self.min_time_before_scrape = max(self.total_time * 0.2, 600) self.playCountMinimumPercent = g.get_int_setting( "trakt.playCountMinimumPercent") self.intro_dialog_enabled = g.get_bool_setting("skip.intro.dialog") self.intro_dialog_delay = g.get_int_setting("skip.intro.dialog.delay") self.playing_next_dialog_enabled = g.get_bool_setting( "smartplay.playingnextdialog") self.still_watching_dialog_enabled = g.get_bool_setting( "smartplay.stillwatching") self.intro_dialog_open_time = g.get_int_setting("skip.intro.open.time") self.pre_scrape_enabled = g.get_bool_setting("smartPlay.preScrape") self.playing_next_time = g.get_int_setting("playingnext.time") self.skip_intro = g.get_bool_setting("skip.intro") self.skip_intro_from = g.get_int_setting("skip.intro.from") self.skip_intro_to = g.get_int_setting("skip.intro.to") self.force_skip = g.get_bool_setting("skip.intro.force") self.bookmark_sync = bookmark.TraktSyncDatabase() self.trakt_enabled = True if g.get_setting("trakt.auth", "") else False self._running_path = None # Flags self.default_pause = False self.default_exit = False self.resumed = False self.playback_started = False self.playback_error = False self.playback_ended = False self.playback_stopped = False self.scrobbled = False self.scrobble_started = False self._force_marked_watched = False self.intro_dialog_triggered = False self.playing_next_dialog_triggered = False self.still_watching_dialog_triggered = False self.pre_scrape_initiated = False self.playback_timestamp = 0 self.intro_skipped = False
def __init__(self): self.torrent_resolve_failure_style = g.get_int_setting('general.resolvefailurehandling') sys.path.append(g.ADDON_USERDATA_PATH) self.return_data = None self.resolvers = { "all_debrid": AllDebridResolver, "premiumize": PremiumizeResolver, "real_debrid": RealDebridResolver, }
def __init__(self): self.trakt = TraktAPI() self.language_code = g.get_language_code() self.trakt_database = TraktSyncDatabase() self.hidden_database = hidden.TraktSyncDatabase() self.bookmark_database = bookmark.TraktSyncDatabase() self.shows_database = shows.TraktSyncDatabase() self.list_builder = ListBuilder() self.page_limit = g.get_int_setting("item.limit")
def _get_cache_location(self): debrid_class = self.locations[g.get_int_setting("general.cachelocation")] if not debrid_class[3]: enabled_locations = [i for i in self.locations if i[3]] if enabled_locations: return enabled_locations[0] else: return None else: return debrid_class
def __init__(self): self.limiter = g.get_runtime_setting("threadpool.limiter") self.workers = self.scaled_workers[g.get_int_setting("general.threadpoolScale", -1) + 1] self.tasks = ClearableQueue(2 * self.workers) self.stop_event = threading.Event() self.results = None self.worker_pool = [] self.max_workers = 1 if self.limiter else self.workers self.exception = None self.result_threading_lock = threading.Lock() self.workers_threading_lock = threading.Lock()
def handle_resume_prompt(resume_switch, force_resume_off=False, force_resume_on=False, force_resume_check=False): """ Handles displaying of resume prompt for item if required :param resume_switch: Resume param from arg string :type resume_switch: any :param force_resume_off: Disable resuming of item :type force_resume_off: bool :param force_resume_on: Force try resuming item :type force_resume_on: bool :param force_resume_check: Force a database check for item resume point :type force_resume_check: bool :return: Resume time in seconds for item :rtype: int """ bookmark_style = g.get_int_setting("general.bookmarkstyle") if force_resume_check and not resume_switch: from resources.lib.database.trakt_sync.bookmark import TraktSyncDatabase trakt_id = g.REQUEST_PARAMS.get("action_args").get("trakt_id") bookmark = TraktSyncDatabase().get_bookmark(trakt_id) if bookmark: g.log("bookmark: {}".format(bookmark)) resume_switch = bookmark["resume_time"] if ( g.PLAYLIST.size() <= 1 and resume_switch is not None and bookmark_style != 2 and not force_resume_off ): if bookmark_style == 0 and not force_resume_on: import datetime selection = xbmcgui.Dialog().contextmenu( [ "{} {}".format( g.get_language_string(30059), datetime.timedelta(seconds=int(resume_switch)), ), g.get_language_string(30331), ] ) if selection == -1: g.cancel_playback() sys.exit() elif selection != 0: resume_switch = None else: resume_switch = None return resume_switch