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): 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 __init__(self, item_information): self.list_builder = ListBuilder() if "info" not in item_information: item_information = tools.get_item_information(item_information) self.item_information = item_information if not isinstance(self.item_information, dict): raise TypeError("Item Information is not a dictionary") self.show_trakt_id = self.item_information.get("trakt_show_id") if not self.show_trakt_id and "action_args" in self.item_information: self.show_trakt_id = self._extract_show_id_from_args( self.item_information["action_args"]) self.display_style = g.get_int_setting("smartplay.displaystyle") self.trakt_api = TraktAPI()
def list_builder(self): from resources.lib.modules.list_builder import ListBuilder return ListBuilder()
class Menus: 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") self.page_start = (g.PAGE - 1) * self.page_limit self.page_end = g.PAGE * self.page_limit ###################################################### # MENUS ###################################################### @trakt_auth_guard def on_deck_shows(self): hidden_shows = self.hidden_database.get_hidden_items( "progress_watched", "tvshow") bookmarked_items = [ i for i in self.bookmark_database.get_all_bookmark_items("episode") if i["trakt_show_id"] not in hidden_shows ][self.page_start:self.page_end] self.list_builder.mixed_episode_builder(bookmarked_items) @staticmethod def discover_shows(): g.add_directory_item( g.get_language_string(30004), action="genericEndpoint", mediatype="shows", endpoint="popular", description=g.get_language_string(30438), ) g.add_directory_item( g.get_language_string(30367), action="showsPopularRecent", description=g.get_language_string(30439), ) if g.get_setting("trakt.auth"): g.add_directory_item( g.get_language_string(30005), action="showsRecommended", description=g.get_language_string(30440), ) g.add_directory_item( g.get_language_string(30006), action="genericEndpoint", mediatype="shows", endpoint="trending", description=g.get_language_string(30441), ) g.add_directory_item( g.get_language_string(30368), action="showsTrendingRecent", description=g.get_language_string(30442), ) g.add_directory_item( g.get_language_string(30046), action="showsNew", description=g.get_language_string(30443), ) g.add_directory_item( g.get_language_string(30007), action="genericEndpoint", mediatype="shows", endpoint="played", description=g.get_language_string(30444), ) g.add_directory_item( g.get_language_string(30008), action="genericEndpoint", mediatype="shows", endpoint="watched", description=g.get_language_string(30445), ) g.add_directory_item( g.get_language_string(30009), action="genericEndpoint", mediatype="shows", endpoint="collected", description=g.get_language_string(30446), ) g.add_directory_item( g.get_language_string(30374), action="TrendingLists", mediatype="shows", description=g.get_language_string(30447), ) g.add_directory_item( g.get_language_string(30376), action="PopularLists", mediatype="shows", description=g.get_language_string(30448), ) if not g.get_bool_setting("general.hideUnAired"): g.add_directory_item( g.get_language_string(30010), action="genericEndpoint", mediatype="shows", endpoint="anticipated", description=g.get_language_string(30449), ) g.add_directory_item( g.get_language_string(30011), action="showsUpdated", description=g.get_language_string(30450), ) g.add_directory_item( g.get_language_string(30182), action="showsNetworks", description=g.get_language_string(30451), ) g.add_directory_item( g.get_language_string(30184), action="showYears", description=g.get_language_string(30452), ) g.add_directory_item( g.get_language_string(30042), action="tvGenres", description=g.get_language_string(30453), ) g.add_directory_item( g.get_language_string(30203), action="showsByActor", description=g.get_language_string(30454), ) if not g.get_bool_setting("searchHistory"): g.add_directory_item( g.get_language_string(30013), action="showsSearch", description=g.get_language_string(30394), ) else: g.add_directory_item( g.get_language_string(30013), action="showsSearchHistory", description=g.get_language_string(30396), ) g.close_directory(g.CONTENT_MENU) @staticmethod @trakt_auth_guard def my_shows(): g.add_directory_item( g.get_language_string(30043), action="onDeckShows", description=g.get_language_string(30455), ) g.add_directory_item( g.get_language_string(30014), action="showsMyCollection", description=g.get_language_string(30456), ) g.add_directory_item( g.get_language_string(30015), action="showsMyWatchlist", description=g.get_language_string(30457), ) g.add_directory_item( g.get_language_string(30092), action="showsRecentlyWatched", description=g.get_language_string(30507), ) g.add_directory_item( g.get_language_string(30223), action="showsNextUp", description=g.get_language_string(30458), ) g.add_directory_item( g.get_language_string(30224), action="myUpcomingEpisodes", description=g.get_language_string(30459), ) g.add_directory_item( g.get_language_string(30225), action="showsMyProgress", description=g.get_language_string(30460), ) g.add_directory_item( g.get_language_string(30226), action="showsMyRecentEpisodes", description=g.get_language_string(30461), ) g.add_directory_item( g.get_language_string(30227), action="myTraktLists", mediatype="shows", description=g.get_language_string(30462), ) g.add_directory_item( g.get_language_string(30372), action="myLikedLists", mediatype="shows", description=g.get_language_string(30463), ) g.add_directory_item( g.get_language_string(30346), action="myWatchedEpisodes", description=g.get_language_string(30464), ) g.close_directory(g.CONTENT_MENU) def generic_endpoint(self, endpoint): trakt_list = self.shows_database.extract_trakt_page( "shows/{}".format(endpoint), page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) def shows_popular_recent(self): year_range = "{}-{}".format(datetime.datetime.now().year - 1, datetime.datetime.now().year) trakt_list = self.shows_database.extract_trakt_page("shows/popular", years=year_range, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) def shows_trending_recent(self): year_range = "{}-{}".format(datetime.datetime.now().year - 1, datetime.datetime.now().year) trakt_list = self.shows_database.extract_trakt_page("shows/trending", years=year_range, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) @trakt_auth_guard def my_shows_collection(self): no_paging = not g.get_bool_setting("general.paginatecollection") sort = "title" if g.get_int_setting( "general.sortcollection") == 1 else False trakt_list = self.trakt_database.get_collected_shows(g.PAGE) if sort == "title" and not no_paging: trakt_list = sorted( trakt_list, key=lambda k: tools.SORT_TOKEN_REGEX.sub( "", k["trakt_object"]["info"].get('title').lower())) offset = (g.PAGE - 1) * self.page_limit trakt_list = trakt_list[offset:offset + self.page_limit] self.list_builder.show_list_builder(trakt_list, no_paging=no_paging, sort=sort) @trakt_auth_guard def my_shows_watchlist(self): paginate = not g.get_bool_setting("general.paginatetraktlists") trakt_list = self.shows_database.extract_trakt_page( "users/me/watchlist/shows", extended="full", page=g.PAGE, ignore_cache=True, no_paging=paginate, pull_all=True, ) self.list_builder.show_list_builder(trakt_list, no_paging=paginate) @trakt_auth_guard 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 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: tools.SORT_TOKEN_REGEX.sub( "", k["trakt_object"]["info"].get('title').lower())) offset = (g.PAGE - 1) * self.page_limit trakt_list = trakt_list[offset:offset + self.page_limit] self.list_builder.show_list_builder(trakt_list, no_paging=no_paging, sort=sort) @trakt_auth_guard def shows_recommended(self): trakt_list = self.shows_database.extract_trakt_page( "recommendations/shows", ignore_collected=True, extended="full") self.list_builder.show_list_builder(trakt_list) def shows_new(self): hidden_items = self.hidden_database.get_hidden_items( "recommendations", "shows") date_string = datetime.datetime.today() - datetime.timedelta(days=29) trakt_list = self.shows_database.extract_trakt_page( "calendars/all/shows/new/{}/30".format( date_string.strftime("%d-%m-%Y")), languages=','.join({'en', self.language_code}), extended="full", no_paging=True, ignore_cache=True, hide_watched=False, hide_unaired=False) trakt_list = [ i for i in trakt_list if i["trakt_id"] not in hidden_items ][:self.page_limit] self.list_builder.show_list_builder(trakt_list, no_paging=True) def shows_recently_watched(self): self.list_builder.show_list_builder( self.trakt_database.get_recently_watched_shows(), no_paging=True) def my_next_up(self): episodes = self.trakt_database.get_nextup_episodes( g.get_int_setting("nextup.sort") == 1) self.list_builder.mixed_episode_builder(episodes, no_paging=True) @trakt_auth_guard def my_recent_episodes(self): hidden_shows = self.hidden_database.get_hidden_items( "calendar", "shows") date_string = datetime.datetime.today() - datetime.timedelta(days=13) trakt_list = self.trakt.get_json("calendars/my/shows/{}/14".format( date_string.strftime("%d-%m-%Y")), extended="full") trakt_list = sorted( [i for i in trakt_list if i["trakt_show_id"] not in hidden_shows], key=lambda t: t["first_aired"], reverse=True, ) self.list_builder.mixed_episode_builder(trakt_list) @trakt_auth_guard def my_upcoming_episodes(self): tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).strftime(g.DATE_FORMAT) upcoming_episodes = self.trakt.get_json( "calendars/my/shows/{}/30".format(tomorrow), extended="full")[:self.page_limit] self.list_builder.mixed_episode_builder(upcoming_episodes, prepend_date=True, no_paging=True, hide_unaired=False) def shows_networks(self): trakt_list = self.trakt.get_json_cached("networks") list_items = [] for i in trakt_list: list_items.append( g.add_directory_item( i["name"], action="showsNetworkShows", action_args=i["name"], bulk_add=True, )) xbmcplugin.addDirectoryItems(g.PLUGIN_HANDLE, list_items, len(list_items)) g.close_directory(g.CONTENT_MENU) def shows_networks_results(self, network): trakt_list = self.shows_database.extract_trakt_page("shows/popular", networks=network, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) g.close_directory(g.CONTENT_SHOW) def shows_updated(self): date = datetime.date.today() - datetime.timedelta(days=29) date = date.strftime(g.DATE_FORMAT) trakt_list = self.shows_database.extract_trakt_page( "shows/updates/{}".format(date), extended="full", ignore_cache=True, hide_watched=False, hide_unaired=False) self.list_builder.show_list_builder(trakt_list, no_paging=True) @staticmethod def shows_search_history(): history = SearchHistory().get_search_history("tvshow") g.add_directory_item( g.get_language_string(30195), action="showsSearch", description=g.get_language_string(30394), ) g.add_directory_item( g.get_language_string(30193), action="clearSearchHistory", mediatype="tvshow", is_folder=False, description=g.get_language_string(30193), ) for i in history: g.add_directory_item( i, action="showsSearchResults", action_args=tools.construct_action_args(i), ) g.close_directory(g.CONTENT_MENU) def shows_search(self, query=None): if not query: query = g.get_keyboard_input(g.get_language_string(30013)) if not query: g.cancel_directory() return if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("tvshow", query) self.shows_search_results(query) def shows_search_results(self, query): trakt_list = self.shows_database.extract_trakt_page("search/show", query=query, page=g.PAGE, extended="full", field="title", hide_unaired=False, hide_watched=False) if not trakt_list: g.cancel_directory() return self.list_builder.show_list_builder([ show for show in trakt_list if float(show["trakt_object"]["info"]["score"]) > 0 ], hide_unaired=False, hide_watched=False) def shows_by_actor(self, query): if not query: query = g.get_keyboard_input(g.get_language_string(30013)) if not query: g.cancel_directory() return if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("showActor", query) query = g.transliterate_string(query) # Try to deal with transliterated chinese actor names as some character -> word transliterations can be joined # I have no idea of the rules and it could well be arbitrary # This approach will only work if only one pair of adjoining transliterated chars are joined name_parts = query.split() for i in range(len(name_parts), 0, -1): query = "-".join(name_parts[:i]) + "-".join(name_parts[i:i + 1]) query = tools.quote_plus(query) trakt_list = self.shows_database.extract_trakt_page( "people/{}/shows".format(query), extended="full", page=g.PAGE, hide_watched=False, hide_unaired=False, ) if not trakt_list: continue else: break try: if not trakt_list or 'trakt_id' not in trakt_list[0]: raise KeyError except KeyError: g.cancel_directory() return self.list_builder.show_list_builder(trakt_list, hide_watched=False, hide_unaired=False) def show_seasons(self, args): self.list_builder.season_list_builder(args["trakt_id"], no_paging=True) def season_episodes(self, args): self.list_builder.episode_list_builder(args["trakt_show_id"], args["trakt_id"], no_paging=True) def flat_episode_list(self, args): self.list_builder.episode_list_builder(args["trakt_id"], no_paging=True) def shows_genres(self): g.add_directory_item( g.get_language_string(30045), action="showsGenresGet", menu_item={ "art": dict.fromkeys(['icon', 'poster', 'thumb', 'fanart'], g.GENRES_PATH + "list.png") }) genres = self.trakt.get_json_cached("genres/shows", extended="full") if genres is None: g.cancel_directory() return for i in genres: g.add_directory_item( i["name"], action="showGenresGet", action_args=i["slug"], menu_item={ "art": dict.fromkeys(['icon', 'poster', 'thumb', 'fanart'], "{}{}.png".format(g.GENRES_PATH, i["slug"])) }) g.close_directory(g.CONTENT_GENRES) 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: 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(30320)), genre_display_list, useDetails=True) 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 shows_related(self, args): trakt_list = self.shows_database.extract_trakt_page( "shows/{}/related".format(args), extended="full") self.list_builder.show_list_builder(trakt_list) 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) @trakt_auth_guard def my_watched_episode(self): watched_episodes = self.trakt_database.get_watched_episodes(g.PAGE) self.list_builder.mixed_episode_builder(watched_episodes)
class SmartPlay: """ Provides smart operations for playback """ def __init__(self, item_information): self.list_builder = ListBuilder() if "info" not in item_information: item_information = tools.get_item_information(item_information) self.item_information = item_information if not isinstance(self.item_information, dict): raise TypeError("Item Information is not a dictionary") self.show_trakt_id = self.item_information.get("trakt_show_id") if not self.show_trakt_id and "action_args" in self.item_information: self.show_trakt_id = self._extract_show_id_from_args( self.item_information["action_args"] ) self.display_style = g.get_int_setting("smartplay.displaystyle") self.trakt_api = TraktAPI() @staticmethod def _extract_show_id_from_args(action_args): if action_args["mediatype"] in ["tvshow", "movie"]: return action_args["trakt_id"] elif action_args["mediatype"] in ["episode", "season"]: return action_args["trakt_show_id"] def get_season_info(self): """ Fetches all season information for current show from database :return: :rtype: """ return TraktSyncDatabase().get_season_list(self.show_trakt_id) def resume_show(self): """ Identifies resume point for a show and plays from there :return: :rtype: """ g.cancel_playback() g.close_all_dialogs() g.PLAYLIST.clear() window = self._get_window() window.set_text(g.get_language_string(30060)) window.show() window.set_text(g.get_language_string(30061)) season_id, episode = self.get_resume_episode() window.set_text(g.get_language_string(30062)) window.set_text(g.get_language_string(30063)) self.build_playlist(season_id, episode) window.set_text(g.get_language_string(30311)) g.log( "Begining play from Season ID {} Episode {}".format(season_id, episode), "info", ) window.close() del window xbmc.Player().play(g.PLAYLIST) def build_playlist(self, season_id=None, minimum_episode=None): """ Uses available information to add relevant episodes to the current playlist :param season_id: Trakt ID of season to build :type season_id: int :param minimum_episode: Minimum episodes to add from :type minimum_episode: int :return: :rtype: """ if season_id is None: season_id = self.item_information["info"]["trakt_season_id"] if minimum_episode is None: minimum_episode = int(self.item_information["info"]["episode"]) + 1 try: [ g.PLAYLIST.add(url=i[0], listitem=i[1]) for i in self.list_builder.episode_list_builder( self.show_trakt_id, season_id, minimum_episode=minimum_episode, smart_play=True, hide_unaired=True, ) ] except TypeError: g.log( "Unable to add more episodes to the playlist, they may not be available for the requested season", "warning", ) return def get_resume_episode(self): """ Fetches playback information for current show and identifies the next episode to be resumed/watched :return: (Season, Episode) tuple :rtype: tuple """ get = MetadataHandler().get_trakt_info info = MetadataHandler().info try: playback_history = self.trakt_api.get_json( "sync/history/shows/{}".format(self.show_trakt_id), extended="full", limit=1 )[0] action = playback_history["action"] episode_info = playback_history["episode"] season = get(episode_info, "season") episode = get(episode_info, "episode") except IndexError: # Capture failure to get old playback and resume from first episode action = "watch" season = 1 episode = 1 if action != "watch": episode += 1 all_seasons = self.get_season_info() season_info = [i for i in all_seasons if info(i).get("season") == season][0] if episode >= info(season_info).get("episode_count"): season += 1 episode = 1 if self.final_episode_check(season, episode): season = 1 episode = 1 season_id = info( [i for i in all_seasons if info(i).get("season") == season][0]).get("trakt_id") return season_id, episode def final_episode_check(self, season, episode): """ Checks to see if the current item is the last episode aired for the show :param season: Season number of item to check :type season: int :param episode: Episode number of item to check :type episode: int :return: True if item is last aired episode else false :rtype: bool """ get = MetadataHandler().get_trakt_info season = int(season) episode = int(episode) last_aired = self.trakt_api.get_json( "shows/{}/last_episode".format(self.show_trakt_id) ) if season > get(last_aired, "season"): return True if season == get(last_aired, "season") and episode == get(last_aired, "number"): return True return False def append_next_season(self): """ Checks if current episode is the last episode for the season, if true adds next seasons episodes to playlist :return: :rtype: """ episode = self.item_information["info"]["episode"] season = self.item_information["info"]["season"] season_info = self.get_season_info() current_season_info = [i for i in season_info if season == i["info"]["season"]][0] if episode != current_season_info["episode_count"]: return next_season = [i for i in season_info if i["info"]["season"] == season + 1] if len(next_season) == 0: return season_id = next_season[0]["trakt_id"] self.build_playlist(season_id, 1) @staticmethod def pre_scrape(): """ Checks whether a item exists in the current playlist after current item and then pre-fetches results :return: :rtype: """ next_position = g.PLAYLIST.getposition() + 1 if next_position >= g.PLAYLIST.size(): return url = g.PLAYLIST[ # pylint: disable=unsubscriptable-object next_position ].getPath() if not url: return url = url.replace("getSources", "preScrape") g.set_runtime_setting("tempSilent", True) g.log("Running Pre-Scrape: {}".format(url)) xbmc.executebuiltin('RunPlugin("{}")'.format(url)) def shuffle_play(self): """ Creates a playlist of shuffled episodes for selected show and plays it :return: :rtype: """ g.PLAYLIST.clear() window = self._get_window() window.show() window.set_text(g.get_language_string(30062)) season_list = self.trakt_api.get_json( "shows/{}/seasons".format(self.show_trakt_id), extended="episodes" ) if season_list[0]["trakt_object"]["info"]["season"] == 0: season_list.pop(0) window.set_text(g.get_language_string(30063)) episode_list = [ episode for season in season_list for episode in season["trakt_object"]["info"]["episodes"] ] random.shuffle(episode_list) episode_list = episode_list[:40] [ episode.update({"trakt_show_id": self.show_trakt_id}) for episode in episode_list ] playlist = self.list_builder.mixed_episode_builder( episode_list, smart_play=True ) window.set_text(g.get_language_string(30064)) for episode in playlist: if episode is not None: g.PLAYLIST.add(url=episode[0], listitem=episode[1]) window.close() del window g.PLAYLIST.shuffle() xbmc.Player().play(g.PLAYLIST) def play_from_random_point(self): """ Select a random episode for show and plays from that point onwards :return: :rtype: """ import random g.PLAYLIST.clear() season_id = random.choice(self.get_season_info())["trakt_id"] playlist = self.list_builder.episode_list_builder( self.show_trakt_id, trakt_season=season_id, smart_play=True ) random_episode = random.randint(0, len(playlist) - 1) playlist = playlist[random_episode] g.PLAYLIST.add(url=playlist[0], listitem=playlist[1]) xbmc.Player().play(g.PLAYLIST) def create_single_item_playlist_from_info(self): g.cancel_playback() name = self.item_information["info"]["title"] item = g.add_directory_item( name, action="getSources", menu_item=self.item_information, action_args=tools.construct_action_args(self.item_information), bulk_add=True, is_playable=True, ) g.PLAYLIST.add(url=g.BASE_URL + "/?" + g.PARAM_STRING, listitem=item[1]) return g.PLAYLIST def playlist_present_check(self, ignore_setting=False): """ Confirms if a playlist is currently present. If not or playlist is for a different item, clear current list and build a new one :param ignore_setting: Force playlist building if setting is disabled :type ignore_setting: bool :return: Playlist if playlist is present else False :rtype: any """ if g.get_bool_setting("smartplay.playlistcreate") or ignore_setting: if not self.item_information["info"]["mediatype"] == "episode": g.log("Movie playback requested, clearing playlist") g.PLAYLIST.clear() return False playlist_uris = [ g.PLAYLIST[i].getPath() # pylint: disable=unsubscriptable-object for i in range(g.PLAYLIST.size()) ] # Check to see if we are just starting playback and kodi has created a playlist if len(playlist_uris) == 1 and playlist_uris[0].split('/')[-1].lstrip('?') == g.PARAM_STRING: return False if g.PLAYLIST.getposition() == -1: return self.create_single_item_playlist_from_info() if [i for i in playlist_uris if g.ADDON_NAME.lower() not in i]: g.log("Cleaning up other addon items from playlsit", "debug") playlist_uris = [] action_args = [ g.legacy_action_args_converter( g.legacy_params_converter( dict(tools.parse_qsl(i.split("?")[-1])) ) )["action_args"] for i in playlist_uris] show_ids = set(tools.deconstruct_action_args(i).get('trakt_show_id') for i in action_args) if len(show_ids) > 1 and self.show_trakt_id not in show_ids: g.log("Cleaning up items from other shows", "debug") playlist_uris = [] if (len(playlist_uris) == 0 or (len(playlist_uris) > 1 and not any(g.PARAM_STRING in i for i in playlist_uris))) or \ g.PLAYLIST.getposition() == -1: return self.create_single_item_playlist_from_info() return False def is_season_final(self): """ Checks if episode in question is the final for the season :return: bool :rtype: True if last episode of season, else False """ season = [i for i in self.get_season_info() if int(self.item_information["info"]["season"]) == int(i["info"]["season"])][0] if self.item_information["info"]["episode"] == season["episode_count"]: return True else: return False @staticmethod 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 def _get_window(self): if self.display_style == 0: # not sure about this one either return PersistentBackground( *SkinManager().confirm_skin_path("persistent_background.xml"), item_information=self.item_information ) else: return BackgroundWindowAdapter()
class Menus: 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") ###################################################### # MENUS ###################################################### @trakt_auth_guard def on_deck_shows(self): hidden_shows = self.hidden_database.get_hidden_items( "progress_watched", "tvshow") bookmarked_items = [ i for i in self.bookmark_database.get_all_bookmark_items("episode") if i["trakt_show_id"] not in hidden_shows ][:self.page_limit] self.list_builder.mixed_episode_builder(bookmarked_items) @staticmethod def discover_shows(): g.add_directory_item( g.get_language_string(30004), action="genericEndpoint", mediatype="shows", endpoint="popular", description=g.get_language_string(30450), ) g.add_directory_item( g.get_language_string(30378), action="showsPopularRecent", description=g.get_language_string(30451), ) if g.get_setting("trakt.auth"): g.add_directory_item( g.get_language_string(30005), action="showsRecommended", description=g.get_language_string(30452), ) g.add_directory_item( g.get_language_string(30006), action="genericEndpoint", mediatype="shows", endpoint="trending", description=g.get_language_string(30453), ) g.add_directory_item( g.get_language_string(30379), action="showsTrendingRecent", description=g.get_language_string(30454), ) g.add_directory_item( g.get_language_string(30047), action="showsNew", description=g.get_language_string(30455), ) g.add_directory_item( g.get_language_string(30007), action="genericEndpoint", mediatype="shows", endpoint="played", description=g.get_language_string(30456), ) g.add_directory_item( g.get_language_string(30008), action="genericEndpoint", mediatype="shows", endpoint="watched", description=g.get_language_string(30457), ) g.add_directory_item( g.get_language_string(30009), action="genericEndpoint", mediatype="shows", endpoint="collected", description=g.get_language_string(30458), ) g.add_directory_item( g.get_language_string(30385), action="TrendingLists", mediatype="shows", description=g.get_language_string(30459), ) g.add_directory_item( g.get_language_string(30387), action="PopularLists", mediatype="shows", description=g.get_language_string(30460), ) if not g.get_bool_setting("general.hideUnAired"): g.add_directory_item( g.get_language_string(30010), action="genericEndpoint", mediatype="shows", endpoint="anticipated", description=g.get_language_string(30461), ) g.add_directory_item( g.get_language_string(30011), action="showsUpdated", description=g.get_language_string(30462), ) g.add_directory_item( g.get_language_string(30186), action="showsNetworks", description=g.get_language_string(30463), ) g.add_directory_item( g.get_language_string(30188), action="showYears", description=g.get_language_string(30464), ) g.add_directory_item( g.get_language_string(30043), action="tvGenres", description=g.get_language_string(30465), ) g.add_directory_item( g.get_language_string(30212), action="showsByActor", description=g.get_language_string(30466), ) if not g.get_bool_setting("searchHistory"): g.add_directory_item( g.get_language_string(30013), action="showsSearch", description=g.get_language_string(30405), ) else: g.add_directory_item( g.get_language_string(30013), action="showsSearchHistory", description=g.get_language_string(30407), ) g.close_directory(g.CONTENT_FOLDER) @staticmethod @trakt_auth_guard def my_shows(): g.add_directory_item( g.get_language_string(30044), action="onDeckShows", description=g.get_language_string(30467), ) g.add_directory_item( g.get_language_string(30014), action="showsMyCollection", description=g.get_language_string(30468), ) g.add_directory_item( g.get_language_string(30015), action="showsMyWatchlist", description=g.get_language_string(30469), ) g.add_directory_item( g.get_language_string(30096), action="showsRecentlyWatched", description=g.get_language_string(30521), ) g.add_directory_item( g.get_language_string(30232), action="showsNextUp", description=g.get_language_string(30470), ) g.add_directory_item( g.get_language_string(30233), action="myUpcomingEpisodes", description=g.get_language_string(30471), ) g.add_directory_item( g.get_language_string(30234), action="showsMyProgress", description=g.get_language_string(30472), ) g.add_directory_item( g.get_language_string(30235), action="showsMyRecentEpisodes", description=g.get_language_string(30473), ) g.add_directory_item( g.get_language_string(30236), action="myTraktLists", mediatype="shows", description=g.get_language_string(30474), ) g.add_directory_item( g.get_language_string(30383), action="myLikedLists", mediatype="shows", description=g.get_language_string(30475), ) g.add_directory_item( g.get_language_string(30356), action="myWatchedEpisodes", description=g.get_language_string(30476), ) g.close_directory(g.CONTENT_FOLDER) def generic_endpoint(self, endpoint): trakt_list = self.shows_database.extract_trakt_page( "shows/{}".format(endpoint), page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) def shows_popular_recent(self): year_range = "{}-{}".format(datetime.datetime.now().year - 1, datetime.datetime.now().year) trakt_list = self.shows_database.extract_trakt_page("shows/popular", years=year_range, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) def shows_trending_recent(self): year_range = "{}-{}".format(datetime.datetime.now().year - 1, datetime.datetime.now().year) trakt_list = self.shows_database.extract_trakt_page("shows/trending", years=year_range, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) @trakt_auth_guard def my_shows_collection(self): paginate = not g.get_bool_setting("general.paginatecollection") sort = "title" if paginate else False trakt_list = self.trakt_database.get_collected_shows(g.PAGE) self.list_builder.show_list_builder(trakt_list, no_paging=paginate, sort=sort) @trakt_auth_guard def my_shows_watchlist(self): paginate = not g.get_bool_setting("general.paginatetraktlists") trakt_list = self.shows_database.extract_trakt_page( "users/me/watchlist/shows", extended="full", page=g.PAGE, ignore_cache=True, no_paging=paginate, pull_all=True, ) self.list_builder.show_list_builder(trakt_list, no_paging=paginate) @trakt_auth_guard def my_show_progress(self): trakt_list = self.trakt_database.get_unfinished_collected_shows(g.PAGE) self.list_builder.show_list_builder(trakt_list) @trakt_auth_guard def shows_recommended(self): trakt_list = self.shows_database.extract_trakt_page( "recommendations/shows", ignore_collected=True, extended="full") self.list_builder.show_list_builder(trakt_list) def shows_new(self): hidden_items = self.hidden_database.get_hidden_items( "recommendations", "shows") date_string = datetime.datetime.today() - datetime.timedelta(days=29) trakt_list = self.trakt.get_json( "calendars/all/shows/new/{}/30".format( date_string.strftime("%d-%m-%Y")), languages=self.language_code, extended="full", ) trakt_list = [ i for i in trakt_list if i["trakt_show_id"] not in hidden_items ] self.list_builder.show_list_builder(trakt_list[:40]) def shows_recently_watched(self): self.list_builder.show_list_builder( self.trakt_database.get_recently_watched_shows()) def my_next_up(self): episodes = self.trakt_database.get_nextup_episodes( g.get_int_setting("nextup.sort") == 1) self.list_builder.mixed_episode_builder(episodes) @trakt_auth_guard def my_recent_episodes(self): hidden_shows = self.hidden_database.get_hidden_items( "calendar", "shows") date_string = datetime.datetime.today() - datetime.timedelta(days=13) trakt_list = self.trakt.get_json("calendars/my/shows/{}/14".format( date_string.strftime("%d-%m-%Y"), extended="full")) trakt_list = sorted( [i for i in trakt_list if i["trakt_show_id"] not in hidden_shows], key=lambda t: t["first_aired"], reverse=True, ) self.list_builder.mixed_episode_builder(trakt_list) @trakt_auth_guard def my_upcoming_episodes(self): tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).strftime("%Y-%m-%d") upcoming_episodes = self.trakt.get_json( "calendars/my/shows/{}/30".format(tomorrow), extended="full")[:self.page_limit] self.list_builder.mixed_episode_builder(upcoming_episodes, prepend_date=True, no_paging=True, hide_unaired=False) def shows_networks(self): trakt_list = self.trakt.get_json_cached("networks") list_items = [] for i in trakt_list: list_items.append( g.add_directory_item( i["name"], action="showsNetworkShows", action_args=i["name"], bulk_add=True, )) xbmcplugin.addDirectoryItems(g.PLUGIN_HANDLE, list_items, len(list_items)) g.close_directory(g.CONTENT_FOLDER) def shows_networks_results(self, network): trakt_list = self.shows_database.extract_trakt_page("shows/popular", networks=network, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) g.close_directory(g.CONTENT_SHOW) def shows_updated(self): date = datetime.date.today() - datetime.timedelta(days=31) date = date.strftime("%Y-%m-%d") trakt_list = self.trakt.get_json("shows/updates/{}".format(date), extended="full") self.list_builder.show_list_builder(trakt_list, no_paging=True) @staticmethod def shows_search_history(): history = SearchHistory().get_search_history("tvshow") g.add_directory_item( g.get_language_string(30204), action="showsSearch", description=g.get_language_string(30405), ) g.add_directory_item( g.get_language_string(30202), action="clearSearchHistory", mediatype="tvshow", is_folder=False, description=g.get_language_string(30202), ) for i in history: g.add_directory_item( i, action="showsSearchResults", action_args=tools.construct_action_args(i), ) g.close_directory(g.CONTENT_FOLDER) def shows_search(self, query=None): if not query: k = xbmc.Keyboard("", g.get_language_string(30013)) k.doModal() query = k.getText() if k.isConfirmed() else None del k if not query: g.cancel_directory() return query = g.decode_py2(query) if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("tvshow", query) query = g.deaccent_string(g.display_string(query)) self.shows_search_results(query) def shows_search_results(self, query): trakt_list = self.trakt.get_json_paged( "search/show", query=tools.unquote(query), page=g.PAGE, extended="full", field="title", ) self.list_builder.show_list_builder([ show for show in trakt_list if float(show["trakt_object"]["info"]["score"]) > 0 ]) def shows_by_actor(self, actor): if not actor: k = xbmc.Keyboard("", g.get_language_string(30013)) k.doModal() query = k.getText() if k.isConfirmed() else None del k if not query: g.cancel_directory() return else: query = tools.unquote(actor) if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("showActor", query) query = g.deaccent_string(query) query = query.replace(" ", "-") query = tools.quote_plus(query) self.list_builder.show_list_builder( self.trakt.get_json_paged("people/{}/shows".format(query), extended="full", page=g.PAGE), hide_watched=False, hide_unaired=False, ) def show_seasons(self, args): self.list_builder.season_list_builder(args["trakt_id"], no_paging=True) def season_episodes(self, args): self.list_builder.episode_list_builder(args["trakt_show_id"], args["trakt_id"], no_paging=True) def flat_episode_list(self, args): self.list_builder.episode_list_builder(args["trakt_id"], no_paging=True) def shows_genres(self): g.add_directory_item(g.get_language_string(30046), action="showGenresGet") genres = self.trakt.get_json_cached("genres/shows", extended="full") if genres is None: g.cancel_directory() return for i in genres: g.add_directory_item(i["name"], action="showGenresGet", action_args=i["slug"]) g.close_directory(g.CONTENT_GENRES) 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 = 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) def shows_related(self, args): trakt_list = self.trakt.get_json("shows/{}/related".format(args), extended="full") self.list_builder.show_list_builder(trakt_list) def shows_years(self, year=None): if year is None: current_year = int( tools.parse_datetime( datetime.datetime.today().strftime("%Y-%m-%d")).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(str(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.trakt.get_json("shows/popular", years=year, page=g.PAGE, extended="full") self.list_builder.show_list_builder(trakt_list) @trakt_auth_guard def my_watched_episode(self): watched_episodes = self.trakt_database.get_watched_episodes(g.PAGE) self.list_builder.mixed_episode_builder(watched_episodes)
def __init__(self): self.title_appends = g.get_setting('general.appendListTitles') self.lists_database = lists.TraktSyncDatabase() self.builder = ListBuilder() self.no_paging = not g.get_bool_setting('general.paginatetraktlists')
class ListsHelper: def __init__(self): self.title_appends = g.get_setting('general.appendListTitles') self.lists_database = lists.TraktSyncDatabase() self.builder = ListBuilder() self.no_paging = not g.get_bool_setting('general.paginatetraktlists') def get_list_items(self): arguments = g.REQUEST_PARAMS['action_args'] media_type = g.REQUEST_PARAMS.get('media_type', arguments.get('type')) ignore_cache = True if g.REQUEST_PARAMS.get('from_widget') and g.REQUEST_PARAMS.get( 'from_widget').lower() == "true": widget_loaded_setting = "widget_loaded.{}.{}".format( media_type, arguments) if not g.get_bool_runtime_setting(widget_loaded_setting): ignore_cache = False g.set_runtime_setting(widget_loaded_setting, True) list_items = self.lists_database.get_list_content( arguments['username'], arguments['trakt_id'], self._backwards_compatibility(media_type), ignore_cache=ignore_cache, page=g.PAGE, no_paging=self.no_paging) if not list_items: g.log( 'Failed to pull list {} from Trakt/Database'.format( arguments['trakt_id']), 'error') g.cancel_directory() return if media_type in ['tvshow', 'shows']: self.builder.show_list_builder(list_items, no_paging=self.no_paging) elif media_type in ['movie', 'movies']: self.builder.movie_menu_builder(list_items, no_paging=self.no_paging) def my_trakt_lists(self, media_type): self._create_list_menu(self.lists_database.extract_trakt_page( 'users/me/lists', media_type, page=g.PAGE, no_paging=self.no_paging, pull_all=True, ignore_cache=True), media_type=media_type) def my_liked_lists(self, media_type): self._create_list_menu(self.lists_database.extract_trakt_page( 'users/likes/lists', media_type, page=g.PAGE, no_paging=self.no_paging, pull_all=True, ignore_cache=True), media_type=media_type) def trending_lists(self, media_type): self._create_list_menu(self.lists_database.extract_trakt_page( 'lists/trending', media_type, page=g.PAGE), media_type=media_type) def popular_lists(self, media_type): self._create_list_menu(self.lists_database.extract_trakt_page( 'lists/popular', media_type, page=g.PAGE), media_type=media_type) def _create_list_menu(self, trakt_lists, **params): trakt_object = MetadataHandler.trakt_object get = MetadataHandler.get_trakt_info if not trakt_lists: trakt_lists = [] self.builder.lists_menu_builder([ tools.smart_merge_dictionary( trakt_object(trakt_list), { 'args': { 'trakt_id': get(trakt_list, 'trakt_id'), 'username': get(trakt_list, 'username') } }) for trakt_list in trakt_lists ], **params) @staticmethod def _backwards_compatibility(media_type): if media_type == 'movie': return 'movies' if media_type in ['tvshow', 'show']: return 'shows' return media_type
class Menus: 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 ###################################################### # MENUS ###################################################### @trakt_auth_guard def on_deck_movies(self): hidden_movies = HiddenDatabase().get_hidden_items("progress_watched", "movies") bookmark_sync = BookmarkDatabase() bookmarked_items = [ i for i in bookmark_sync.get_all_bookmark_items("movie") if i["trakt_id"] not in hidden_movies ][self.page_start:self.page_end] self.list_builder.movie_menu_builder(bookmarked_items) @staticmethod def discover_movies(): g.add_directory_item( g.get_language_string(30004), action="genericEndpoint", mediatype="movies", endpoint="popular", description=g.get_language_string(30429), ) g.add_directory_item( g.get_language_string(30380), action="moviePopularRecent", description=g.get_language_string(30430), ) if g.get_setting("trakt.auth"): g.add_directory_item( g.get_language_string(30005), action="moviesRecommended", description=g.get_language_string(30431), ) g.add_directory_item( g.get_language_string(30006), action="genericEndpoint", mediatype="movies", endpoint="trending", description=g.get_language_string(30432), ) g.add_directory_item( g.get_language_string(30381), action="movieTrendingRecent", description=g.get_language_string(30433), ) g.add_directory_item( g.get_language_string(30007), action="genericEndpoint", mediatype="movies", endpoint="played", description=g.get_language_string(30434), ) g.add_directory_item( g.get_language_string(30008), action="genericEndpoint", mediatype="movies", endpoint="watched", description=g.get_language_string(30435), ) g.add_directory_item( g.get_language_string(30009), action="genericEndpoint", mediatype="movies", endpoint="collected", description=g.get_language_string(30436), ) g.add_directory_item( g.get_language_string(30386), action="TrendingLists", mediatype="movies", description=g.get_language_string(30437), ) g.add_directory_item( g.get_language_string(30388), action="PopularLists", mediatype="movies", description=g.get_language_string(30438), ) if not g.get_bool_setting("general.hideUnAired"): g.add_directory_item( g.get_language_string(30010), action="genericEndpoint", mediatype="movies", endpoint="anticipated", description=g.get_language_string(30439), ) g.add_directory_item( g.get_language_string(30012), action="genericEndpoint", mediatype="movies", endpoint="boxoffice", description=g.get_language_string(30440), ) g.add_directory_item( g.get_language_string(30011), action="moviesUpdated", description=g.get_language_string(30441), ) g.add_directory_item( g.get_language_string(30043), action="movieGenres", description=g.get_language_string(30442), ) g.add_directory_item( g.get_language_string(30188), action="movieYears", description=g.get_language_string(30443), ) g.add_directory_item( g.get_language_string(30212), action="movieByActor", description=g.get_language_string(30408), ) if not g.get_bool_setting("searchHistory"): g.add_directory_item( g.get_language_string(30013), action="moviesSearch", description=g.get_language_string(30404), ) else: g.add_directory_item( g.get_language_string(30013), action="moviesSearchHistory", description=g.get_language_string(30406), ) g.close_directory(g.CONTENT_FOLDER) @staticmethod @trakt_auth_guard def my_movies(): g.add_directory_item( g.get_language_string(30044), action="onDeckMovies", description=g.get_language_string(30444), ) g.add_directory_item( g.get_language_string(30014), action="moviesMyCollection", description=g.get_language_string(30445), ) g.add_directory_item( g.get_language_string(30015), action="moviesMyWatchlist", description=g.get_language_string(30446), ) g.add_directory_item( g.get_language_string(30045), action="myTraktLists", mediatype="movies", description=g.get_language_string(30447), ) g.add_directory_item( g.get_language_string(30384), action="myLikedLists", mediatype="movies", description=g.get_language_string(30448), ) g.add_directory_item( g.get_language_string(30357), action="myWatchedMovies", description=g.get_language_string(30449), ) g.close_directory(g.CONTENT_FOLDER) def generic_endpoint(self, endpoint): trakt_list = self.movies_database.extract_trakt_page( "movies/{}".format(endpoint), extended="full", page=g.PAGE ) self.list_builder.movie_menu_builder(trakt_list) def movie_popular_recent(self): year_range = "{}-{}".format( datetime.datetime.now().year - 1, datetime.datetime.now().year ) trakt_list = self.movies_database.extract_trakt_page( "movies/popular", years=year_range, page=g.PAGE, extended="full" ) self.list_builder.movie_menu_builder(trakt_list) def movie_trending_recent(self): year_range = "{}-{}".format( datetime.datetime.now().year - 1, datetime.datetime.now().year ) trakt_list = self.movies_database.extract_trakt_page( "movies/trending", years=year_range, page=g.PAGE, extended="full" ) self.list_builder.movie_menu_builder(trakt_list) @trakt_auth_guard def my_movie_collection(self): paginate = not g.get_bool_setting("general.paginatecollection") sort = "title" if paginate else False self.list_builder.movie_menu_builder( movies.TraktSyncDatabase().get_collected_movies(g.PAGE), no_paging=paginate, sort=sort, ) @trakt_auth_guard def my_movie_watchlist(self): paginate = not g.get_bool_setting("general.paginatetraktlists") trakt_list = self.movies_database.extract_trakt_page( "users/me/watchlist/movies", extended="full", page=g.PAGE, ignore_cache=True, no_paging=paginate, pull_all=True, ) self.list_builder.movie_menu_builder(trakt_list, no_paging=paginate) @trakt_auth_guard def movies_recommended(self): trakt_list = self.movies_database.extract_trakt_page( "recommendations/movies", ignore_collected=True, extended="full", page=g.PAGE, ) self.list_builder.movie_menu_builder(trakt_list) def movies_updated(self): import datetime date = datetime.date.today() - datetime.timedelta(days=31) date = date.strftime(g.DATE_FORMAT) trakt_list = self.movies_database.extract_trakt_page( "movies/updates/{}".format(date), page=g.PAGE, extended="full" ) self.list_builder.movie_menu_builder(trakt_list) @staticmethod def movies_search_history(): history = SearchHistory().get_search_history("movie") g.add_directory_item( g.get_language_string(30203), action="moviesSearch", description=g.get_language_string(30404), ) g.add_directory_item( g.get_language_string(30202), action="clearSearchHistory", mediatype="movie", is_folder=False, description=g.get_language_string(30414), ) for i in history: g.add_directory_item(i, action="moviesSearchResults", action_args=i) g.close_directory(g.CONTENT_FOLDER) def movies_search(self, query=None): if query is None: k = xbmc.Keyboard("", g.get_language_string(30013)) k.doModal() query = k.getText() if k.isConfirmed() else None del k if not query: g.cancel_directory() return query = g.decode_py2(query) if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("movie", query) query = g.deaccent_string(g.display_string(query)) query = tools.quote(query) self.movies_search_results(query) def movies_search_results(self, query): trakt_list = self.trakt.get_json_paged( "search/movie", query=tools.unquote(query), extended="full", page=g.PAGE ) if not trakt_list: g.cancel_directory() return self.list_builder.movie_menu_builder( [ movie for movie in trakt_list if float(movie["trakt_object"]["info"]["score"]) > 0 ], hide_watched=False, hide_unaired=False, ) def movies_related(self, args): trakt_list = self.movies_database.extract_trakt_page( "movies/{}/related".format(args), page=g.PAGE, extended="full" ) self.list_builder.movie_menu_builder(trakt_list) @staticmethod def movies_years(): from datetime import datetime year = int(datetime.today().year) years = [] for i in range(year - 100, year + 1): years.append(i) years = sorted(years, reverse=True) [ g.add_directory_item(str(i), action="movieYearsMovies", action_args=i) for i in years ] g.close_directory(g.CONTENT_FOLDER) def movie_years_results(self, year): trakt_list = self.movies_database.extract_trakt_page( "movies/popular", years=year, page=g.PAGE, extended="full" ) self.list_builder.movie_menu_builder(trakt_list) def movies_by_actor(self, actor): if actor is None: k = xbmc.Keyboard("", g.get_language_string(30013)) k.doModal() query = k.getText() if k.isConfirmed() else None if not query: g.cancel_directory() return else: query = tools.unquote(actor) if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("movieActor", query) query = g.deaccent_string(query) query = query.replace(" ", "-") query = tools.quote_plus(query) self.list_builder.movie_menu_builder( self.trakt.get_json_paged( "people/{}/movies".format(query), extended="full", page=g.PAGE ), hide_watched=False, hide_unaired=False, ) def movies_genres(self): g.add_directory_item(g.get_language_string(30046), action="movieGenresGet") genres = self.trakt.get_json("genres/movies") if genres is None: g.cancel_directory() return for i in genres: g.add_directory_item( i["name"], action="movieGenresGet", action_args=i["slug"] ) g.close_directory(g.CONTENT_GENRES) 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) @trakt_auth_guard def my_watched_movies(self): watched_movies = movies.TraktSyncDatabase().get_watched_movies(g.PAGE) self.list_builder.movie_menu_builder(watched_movies)
class Menus: 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 ###################################################### # MENUS ###################################################### @trakt_auth_guard def on_deck_movies(self): hidden_movies = HiddenDatabase().get_hidden_items( "progress_watched", "movies") bookmark_sync = BookmarkDatabase() bookmarked_items = [ i for i in bookmark_sync.get_all_bookmark_items("movie") if i["trakt_id"] not in hidden_movies ][self.page_start:self.page_end] self.list_builder.movie_menu_builder(bookmarked_items) @staticmethod def discover_movies(): g.add_directory_item( g.get_language_string(30004), action="genericEndpoint", mediatype="movies", endpoint="popular", description=g.get_language_string(30417), ) g.add_directory_item( g.get_language_string(30369), action="moviePopularRecent", description=g.get_language_string(30418), ) if g.get_setting("trakt.auth"): g.add_directory_item( g.get_language_string(30005), action="moviesRecommended", description=g.get_language_string(30419), ) g.add_directory_item( g.get_language_string(30006), action="genericEndpoint", mediatype="movies", endpoint="trending", description=g.get_language_string(30420), ) g.add_directory_item( g.get_language_string(30370), action="movieTrendingRecent", description=g.get_language_string(30421), ) g.add_directory_item( g.get_language_string(30007), action="genericEndpoint", mediatype="movies", endpoint="played", description=g.get_language_string(30422), ) g.add_directory_item( g.get_language_string(30008), action="genericEndpoint", mediatype="movies", endpoint="watched", description=g.get_language_string(30423), ) g.add_directory_item( g.get_language_string(30009), action="genericEndpoint", mediatype="movies", endpoint="collected", description=g.get_language_string(30424), ) g.add_directory_item( g.get_language_string(30375), action="TrendingLists", mediatype="movies", description=g.get_language_string(30425), ) g.add_directory_item( g.get_language_string(30377), action="PopularLists", mediatype="movies", description=g.get_language_string(30426), ) if not g.get_bool_setting("general.hideUnAired"): g.add_directory_item( g.get_language_string(30010), action="genericEndpoint", mediatype="movies", endpoint="anticipated", description=g.get_language_string(30427), ) g.add_directory_item( g.get_language_string(30012), action="genericEndpoint", mediatype="movies", endpoint="boxoffice", description=g.get_language_string(30428), ) g.add_directory_item( g.get_language_string(30011), action="moviesUpdated", description=g.get_language_string(30429), ) g.add_directory_item( g.get_language_string(30042), action="movieGenres", description=g.get_language_string(30430), ) g.add_directory_item( g.get_language_string(30184), action="movieYears", description=g.get_language_string(30431), ) g.add_directory_item( g.get_language_string(30203), action="movieByActor", description=g.get_language_string(30397), ) if not g.get_bool_setting("searchHistory"): g.add_directory_item( g.get_language_string(30013), action="moviesSearch", description=g.get_language_string(30393), ) else: g.add_directory_item( g.get_language_string(30013), action="moviesSearchHistory", description=g.get_language_string(30395), ) g.close_directory(g.CONTENT_MENU) @staticmethod @trakt_auth_guard def my_movies(): g.add_directory_item( g.get_language_string(30043), action="onDeckMovies", description=g.get_language_string(30432), ) g.add_directory_item( g.get_language_string(30014), action="moviesMyCollection", description=g.get_language_string(30433), ) g.add_directory_item( g.get_language_string(30015), action="moviesMyWatchlist", description=g.get_language_string(30434), ) g.add_directory_item( g.get_language_string(30044), action="myTraktLists", mediatype="movies", description=g.get_language_string(30435), ) g.add_directory_item( g.get_language_string(30373), action="myLikedLists", mediatype="movies", description=g.get_language_string(30436), ) g.add_directory_item( g.get_language_string(30347), action="myWatchedMovies", description=g.get_language_string(30437), ) g.close_directory(g.CONTENT_MENU) def generic_endpoint(self, endpoint): trakt_list = self.movies_database.extract_trakt_page( "movies/{}".format(endpoint), extended="full", page=g.PAGE) self.list_builder.movie_menu_builder(trakt_list) def movie_popular_recent(self): year_range = "{}-{}".format(datetime.datetime.now().year - 1, datetime.datetime.now().year) trakt_list = self.movies_database.extract_trakt_page("movies/popular", years=year_range, page=g.PAGE, extended="full") self.list_builder.movie_menu_builder(trakt_list) def movie_trending_recent(self): year_range = "{}-{}".format(datetime.datetime.now().year - 1, datetime.datetime.now().year) trakt_list = self.movies_database.extract_trakt_page("movies/trending", years=year_range, page=g.PAGE, extended="full") self.list_builder.movie_menu_builder(trakt_list) @trakt_auth_guard def my_movie_collection(self): paginate = not g.get_bool_setting("general.paginatecollection") sort = "title" if paginate else False self.list_builder.movie_menu_builder( movies.TraktSyncDatabase().get_collected_movies(g.PAGE), no_paging=paginate, sort=sort, ) @trakt_auth_guard def my_movie_watchlist(self): paginate = not g.get_bool_setting("general.paginatetraktlists") trakt_list = self.movies_database.extract_trakt_page( "users/me/watchlist/movies", extended="full", page=g.PAGE, ignore_cache=True, no_paging=paginate, pull_all=True, ) self.list_builder.movie_menu_builder(trakt_list, no_paging=paginate) @trakt_auth_guard def movies_recommended(self): trakt_list = self.movies_database.extract_trakt_page( "recommendations/movies", ignore_collected=True, extended="full", page=g.PAGE, ) self.list_builder.movie_menu_builder(trakt_list) def movies_updated(self): import datetime date = datetime.date.today() - datetime.timedelta(days=29) date = date.strftime(g.DATE_FORMAT) trakt_list = self.movies_database.extract_trakt_page( "movies/updates/{}".format(date), page=g.PAGE, extended="full") self.list_builder.movie_menu_builder(trakt_list) @staticmethod def movies_search_history(): history = SearchHistory().get_search_history("movie") g.add_directory_item( g.get_language_string(30194), action="moviesSearch", description=g.get_language_string(30393), ) g.add_directory_item( g.get_language_string(30193), action="clearSearchHistory", mediatype="movie", is_folder=False, description=g.get_language_string(30403), ) for i in history: g.add_directory_item(i, action="moviesSearchResults", action_args=i) g.close_directory(g.CONTENT_MENU) def movies_search(self, query=None): if query is None: query = g.get_keyboard_input(heading=g.get_language_string(30013)) if not query: g.cancel_directory() return if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("movie", query) self.movies_search_results(query) def movies_search_results(self, query): trakt_list = self.movies_database.extract_trakt_page( "search/movie", query=query, extended="full", page=g.PAGE, hide_watched=False, hide_unaired=False, ) if not trakt_list: g.cancel_directory() return self.list_builder.movie_menu_builder( [ movie for movie in trakt_list if float(movie["trakt_object"]["info"]["score"]) > 0 ], hide_watched=False, hide_unaired=False, ) def movies_related(self, args): trakt_list = self.movies_database.extract_trakt_page( "movies/{}/related".format(args), page=g.PAGE, extended="full") self.list_builder.movie_menu_builder(trakt_list) @staticmethod def movies_years(): from datetime import datetime year = int(datetime.today().year) years = [] for i in range(year - 100, year + 1): years.append(i) years = sorted(years, reverse=True) [ g.add_directory_item(str(i), action="movieYearsMovies", action_args=i) for i in years ] g.close_directory(g.CONTENT_MENU) def movie_years_results(self, year): trakt_list = self.movies_database.extract_trakt_page("movies/popular", years=year, page=g.PAGE, extended="full") self.list_builder.movie_menu_builder(trakt_list) def movies_by_actor(self, query): if query is None: query = g.get_keyboard_input(g.get_language_string(30013)) if not query: g.cancel_directory() return if g.get_bool_setting("searchHistory"): SearchHistory().add_search_history("movieActor", query) query = g.transliterate_string(query) # Try to deal with transliterated chinese actor names as some character -> word transliterations can be joined # I have no idea of the rules and it could well be arbitrary # This approach will only work if only one pair of adjoining transliterated chars are joined name_parts = query.split() for i in range(len(name_parts), 0, -1): query = "-".join(name_parts[:i]) + "-".join(name_parts[i:i + 1]) query = tools.quote_plus(query) trakt_list = self.movies_database.extract_trakt_page( "people/{}/movies".format(query), extended="full", page=g.PAGE, hide_watched=False, hide_unaired=False) if not trakt_list: continue else: break try: if not trakt_list or 'trakt_id' not in trakt_list[0]: raise KeyError except KeyError: g.cancel_directory() return self.list_builder.movie_menu_builder(trakt_list, hide_watched=False, hide_unaired=False) def movies_genres(self): g.add_directory_item( g.get_language_string(30045), action="movieGenresGet", menu_item={ "art": dict.fromkeys(['icon', 'poster', 'thumb', 'fanart'], g.GENRES_PATH + "list.png") }) genres = self.trakt.get_json_cached("genres/movies") if genres is None: g.cancel_directory() return for i in genres: g.add_directory_item( i["name"], action="movieGenresGet", action_args=i["slug"], menu_item={ "art": dict.fromkeys(['icon', 'poster', 'thumb', 'fanart'], "{}{}.png".format(g.GENRES_PATH, i["slug"])) }) g.close_directory(g.CONTENT_GENRES) 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_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(30320)), 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(trakt_endpoint), 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) @trakt_auth_guard def my_watched_movies(self): watched_movies = movies.TraktSyncDatabase().get_watched_movies(g.PAGE) self.list_builder.movie_menu_builder(watched_movies)