def action(action, tmdb_id=None, tmdb_type=None, season=None, episode=None, label=None, cache_refresh=False): _traktapi = TraktAPI() if action == 'history': func = _traktapi.sync_history elif action == 'collection': func = _traktapi.sync_collection elif action == 'watchlist': func = _traktapi.sync_watchlist elif action == 'add_to_userlist': return sync_userlist() elif action == 'remove_from_userlist': return sync_userlist(remove_item=True) elif action == 'library_userlist': return library_userlist() elif action == 'library': return library() elif action == 'play': return play() elif action == 'open': return browse() else: return with utils.busy_dialog(): if tmdb_type == 'episode' and (not season or not episode): return elif tmdb_id and tmdb_type: dbtype = utils.type_convert(tmdb_type, 'dbtype') label = label or 'this {}'.format(utils.type_convert(tmdb_type, 'trakt')) else: label = sys.listitem.getLabel() dbtype = sys.listitem.getVideoInfoTag().getMediaType() tmdb_id = sys.listitem.getProperty('tmdb_id') if not dbtype == 'episode' else sys.listitem.getProperty('tvshow.tmdb_id') season = sys.listitem.getVideoInfoTag().getSeason() if dbtype == 'episode' else None episode = sys.listitem.getVideoInfoTag().getEpisode() if dbtype == 'episode' else None tmdb_type = 'movie' if dbtype == 'movie' else 'tv' trakt_ids = func(utils.type_convert(tmdb_type, 'trakt'), 'tmdb', cache_refresh=cache_refresh) boolean = 'remove' if int(tmdb_id) in trakt_ids else 'add' dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32065) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32064) dialog_text = dialog_text.format(utils.try_decode_string(label), action.capitalize(), tmdb_type, tmdb_id) dialog_text = dialog_text + ' Season: {} Episode: {}'.format(season, episode) if dbtype == 'episode' else dialog_text if not xbmcgui.Dialog().yesno(dialog_header, dialog_text): return with utils.busy_dialog(): trakt_type = 'episode' if dbtype == 'episode' else utils.type_convert(tmdb_type, 'trakt') slug_type = 'show' if dbtype == 'episode' else trakt_type slug = _traktapi.get_traktslug(slug_type, 'tmdb', tmdb_id) item = _traktapi.get_details(slug_type, slug, season=season, episode=episode) items = {trakt_type + 's': [item]} func(slug_type, mode=boolean, items=items) dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32062) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32063) dialog_text = dialog_text.format(tmdb_id, action.capitalize()) xbmcgui.Dialog().ok(dialog_header, dialog_text) xbmc.executebuiltin('Container.Refresh')
def get_extracted_zip(self): if not self.download_url or not self.extract_to: return with utils.busy_dialog(): response = self.open_url(self.download_url) if not response: xbmcgui.Dialog().ok(self.addon.getAddonInfo('name'), self.addon.getLocalizedString(32058)) return if not os.path.exists(self.extract_to): os.makedirs(self.extract_to) if xbmcgui.Dialog().yesno(self.addon.getAddonInfo('name'), self.msg_cleardir): with utils.busy_dialog(): self.clear_dir(self.extract_to) with utils.busy_dialog(): num_files = 0 with zipfile.ZipFile(BytesIO(response.content)) as downloaded_zip: for item in [ x for x in downloaded_zip.namelist() if x.endswith('.json') ]: filename = os.path.basename(item) if not filename: continue _file = downloaded_zip.open(item) with open(os.path.join(self.extract_to, filename), 'w') as target: target.write(_file.read()) num_files += 1 try: _tempzip = os.path.join(self.extract_to, 'temp.zip') os.remove(_tempzip) except Exception as e: utils.kodi_log('Could not delete package {0}: {1}'.format( _tempzip, str(e))) if num_files: xbmcgui.Dialog().ok( self.addon.getAddonInfo('name'), '{0}\n\n{1} {2}.'.format(self.addon.getLocalizedString(32059), num_files, self.addon.getLocalizedString(32060)))
def play(): with utils.busy_dialog(): suffix = 'force_dialog=True' tmdb_id, season, episode = None, None, None dbtype = sys.listitem.getVideoInfoTag().getMediaType() if dbtype == 'episode': tmdb_id = sys.listitem.getProperty('tvshow.tmdb_id') season = sys.listitem.getVideoInfoTag().getSeason() episode = sys.listitem.getVideoInfoTag().getEpisode() suffix += ',season={},episode={}'.format(season, episode) elif dbtype == 'movie': tmdb_id = sys.listitem.getProperty('tmdb_id') or sys.listitem.getUniqueID('tmdb') # Try to lookup ID if we don't have it if not tmdb_id and dbtype == 'episode': id_details = TraktAPI().get_item_idlookup( 'episode', parent=True, tvdb_id=sys.listitem.getUniqueID('tvdb'), tmdb_id=sys.listitem.getUniqueID('tmdb'), imdb_id=sys.listitem.getUniqueID('imdb')) tmdb_id = id_details.get('show', {}).get('ids', {}).get('tmdb') elif not tmdb_id and dbtype == 'movie': tmdb_id = Plugin().get_tmdb_id( itemtype='movie', imdb_id=sys.listitem.getUniqueID('imdb'), query=sys.listitem.getVideoInfoTag().getTitle(), year=sys.listitem.getVideoInfoTag().getYear()) if not tmdb_id or not dbtype: return xbmcgui.Dialog().ok('TheMovieDb Helper', _addon.getLocalizedString(32157)) xbmc.executebuiltin('RunScript(plugin.video.themoviedb.helper,play={},tmdb_id={},{})'.format(dbtype, tmdb_id, suffix))
def monitor_userlist(self): monitor_userlist = self.params.get('monitor_userlist') with utils.busy_dialog(): user_slug = TraktAPI().get_usernameslug() # Get the user's slug user_lists = TraktAPI().get_response_json( 'users', user_slug, 'lists') # Get the user's lists if not user_lists: return user_list_labels = [i.get('name') for i in user_lists ] # Build select dialog to choose list user_list_labels.append(xbmc.getLocalizedString(231)) user_choice = xbmcgui.Dialog().select( self.addon.getLocalizedString(32133), user_list_labels) # Choose the list if user_choice == -1: # User cancelled return elif user_list_labels[user_choice] == xbmc.getLocalizedString( 231): # User opted to clear setting self.addon.setSettingString(monitor_userlist, '') return user_list = user_lists[user_choice].get('ids', {}).get('slug') if not user_list: return self.addon.setSettingString(monitor_userlist, user_list) if xbmcgui.Dialog().yesno(xbmc.getLocalizedString(653), self.addon.getLocalizedString(32132)): self.library_autoupdate(list_slug=user_list, user_slug=user_slug)
def get_userlist(user_slug=None, list_slug=None, confirm=True, busy_dialog=True): if busy_dialog: with utils.busy_dialog(): request = TraktAPI().get_response_json('users', user_slug, 'lists', list_slug, 'items') else: request = TraktAPI().get_response_json('users', user_slug, 'lists', list_slug, 'items') if not request: return if confirm: d_head = _addon.getLocalizedString(32125) i_check_limits = check_overlimit(request) if i_check_limits: # List over limit so inform user that it is too large to add d_body = [ _addon.getLocalizedString(32168).format(list_slug, user_slug), _addon.getLocalizedString(32170).format(i_check_limits.get('shows'), i_check_limits.get('movies')), '', _addon.getLocalizedString(32164).format(LIBRARY_ADD_LIMIT_TVSHOWS, LIBRARY_ADD_LIMIT_MOVIES)] xbmcgui.Dialog().ok(d_head, '\n'.join(d_body)) return elif confirm != 2: # Set confirm param to 2 to only check limits # List is within limits so ask for confirmation before adding it d_body = [ _addon.getLocalizedString(32168).format(list_slug, user_slug), _addon.getLocalizedString(32171).format(len(request)) if len(request) > 20 else '', '', _addon.getLocalizedString(32126)] if not xbmcgui.Dialog().yesno(d_head, '\n'.join(d_body)): return return request
def player_resolveurl(self, player=None): if not player or not player[1] or not isinstance(player[1], list): return player # No player configured or not a list of actions so return keyboard_input = None player_actions = player[1] player = (False, player_actions[0] ) # player tuple is: isPlayable flag; path URI to call. for action in player_actions[1:]: # If playable item was found in last action then let's break and play it if player[0]: break # Start thread with keyboard inputter if needed if action.get('keyboard'): if action.get('keyboard') in [ 'Up', 'Down', 'Left', 'Right', 'Select' ]: keyboard_input = KeyboardInputter( action="Input.{}".format(action.get('keyboard'))) else: keyboard_input = KeyboardInputter(text=string_format_map( action.get('keyboard', ''), self.item)) keyboard_input.setName('keyboard_input') keyboard_input.start() continue # Go to next action # Get the next folder from the plugin with utils.busy_dialog(): folder = KodiLibrary().get_directory( string_format_map(player[1], self.item)) # Kill our keyboard inputter thread if keyboard_input: keyboard_input.exit = True keyboard_input = None # Special option to show dialog of items to select from if action.get('dialog'): auto = True if action.get('dialog', '').lower() == 'auto' else False return self.player_dialogselect(folder, auto=auto) utils.kodi_log( 'Player -- Retrieved Folder\n{}'.format( string_format_map(player[1], self.item)), 2) # Iterate through plugin folder looking for item that matches rules player = self.player_applyrules(folder, action) or player if player == -1: break return player
def action(action): _traktapi = TraktAPI() if action == 'history': func = _traktapi.sync_history elif action == 'collection': func = _traktapi.sync_collection elif action == 'watchlist': func = _traktapi.sync_watchlist elif action == 'library': return library() else: return with utils.busy_dialog(): label = sys.listitem.getLabel() dbtype = sys.listitem.getVideoInfoTag().getMediaType() tmdb_id = sys.listitem.getProperty('tmdb_id') tmdb_type = 'movie' if dbtype == 'movie' else 'tv' trakt_ids = func(utils.type_convert(tmdb_type, 'trakt'), 'tmdb') boolean = 'remove' if int(tmdb_id) in trakt_ids else 'add' dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32065) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32064) dialog_text = dialog_text.format(label, action.capitalize(), dbtype.capitalize(), tmdb_id) if not xbmcgui.Dialog().yesno(dialog_header, dialog_text): return with utils.busy_dialog(): trakt_type = utils.type_convert(tmdb_type, 'trakt') slug_type = 'show' if dbtype == 'episode' else trakt_type slug = _traktapi.get_traktslug(slug_type, 'tmdb', tmdb_id) season = sys.listitem.getVideoInfoTag().getSeason() if dbtype == 'episode' else None episode = sys.listitem.getVideoInfoTag().getEpisode() if dbtype == 'episode' else None item = _traktapi.get_details(slug_type, slug, season=season, episode=episode) items = {trakt_type + 's': [item]} func(slug_type, mode=boolean, items=items) dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32062) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32063) dialog_text = dialog_text.format(tmdb_id, action.capitalize()) xbmcgui.Dialog().ok(dialog_header, dialog_text) xbmc.executebuiltin('Container.Refresh')
def monitor_userlist(self): with utils.busy_dialog(): user_slug = TraktAPI().get_usernameslug() # Get the user's slug user_lists = TraktAPI().get_response_json( 'users', user_slug, 'lists') or [ ] # Get the user's custom lists user_lists += [ i.get('list') for i in TraktAPI().get_response_json( 'users', 'likes', 'lists') if i.get('type') == 'list' ] # Get the user's liked lists if not user_lists: return monitor_userlist = self.addon.getSettingString( 'monitor_userlist') or '' monitor_userlist = monitor_userlist.split(' | ') user_list_labels, preselect = [], [] for idx, i in enumerate(user_lists): user_list_labels.append(i.get('name')) preselect.append(idx) if i.get( 'ids', {}).get('slug') in monitor_userlist else None # Choose lists user_choice = xbmcgui.Dialog().multiselect( self.addon.getLocalizedString(32133), user_list_labels, preselect=preselect) if not user_choice: # User cancelled return # Check lists are within limits before adding selected_slugs, selected_lists = [], [] for i in user_choice: i_slug = user_lists[i].get('user', {}).get('ids', {}).get('slug') i_list = user_lists[i].get('ids', {}).get('slug') if libraryupdate.get_userlist( user_slug=i_slug, list_slug=i_list, confirm=2): # Set confirm(2) to only check within limits selected_lists.append(i_list) selected_slugs.append(i_slug) user_list = ' | '.join(selected_lists) user_slug = ' | '.join(selected_slugs) if not user_list or not user_slug: return self.addon.setSettingString('monitor_userlist', user_list) self.addon.setSettingString('monitor_userslug', user_slug) if xbmcgui.Dialog().yesno(xbmc.getLocalizedString(653), self.addon.getLocalizedString(32132)): self.library_autoupdate(list_slug=user_list, user_slug=user_slug)
def library(): with utils.busy_dialog(): title = utils.validify_filename(sys.listitem.getVideoInfoTag().getTitle()) dbtype = sys.listitem.getVideoInfoTag().getMediaType() basedir_movie = _addon.getSettingString('movies_library') or 'special://profile/addon_data/plugin.video.skin.info.provider/movies/' basedir_tv = _addon.getSettingString('tvshows_library') or 'special://profile/addon_data/plugin.video.skin.info.provider/tvshows/' auto_update = _addon.getSettingBool('auto_update') or False # Setup our folders and file names if dbtype == 'movie': folder = '{} ({})'.format(title, sys.listitem.getVideoInfoTag().getYear()) movie_name = '{} ({})'.format(title, sys.listitem.getVideoInfoTag().getYear()) library_createfile(movie_name, sys.listitem.getPath(), folder, basedir=basedir_movie) library_create_nfo('movie', sys.listitem.getProperty('tmdb_id'), folder, basedir=basedir_movie) xbmc.executebuiltin('UpdateLibrary(video, {})'.format(basedir_movie)) if auto_update else None elif dbtype == 'episode': folder = sys.listitem.getVideoInfoTag().getTVShowTitle() season_name = 'Season {}'.format(sys.listitem.getVideoInfoTag().getSeason()) episode_name = 'S{:02d}E{:02d} - {}'.format( utils.try_parse_int(sys.listitem.getVideoInfoTag().getSeason()), utils.try_parse_int(sys.listitem.getVideoInfoTag().getEpisode()), title) library_createfile(episode_name, sys.listitem.getPath(), folder, season_name, basedir=basedir_tv) library_create_nfo('tv', sys.listitem.getProperty('tvshow.tmdb_id'), folder, basedir=basedir_tv) xbmc.executebuiltin('UpdateLibrary(video, {})'.format(basedir_tv)) if auto_update else None elif dbtype == 'tvshow': folder = sys.listitem.getVideoInfoTag().getTVShowTitle() or title library_addtvshow( basedir=basedir_tv, folder=folder, url=sys.listitem.getPath(), tmdb_id=sys.listitem.getProperty('tmdb_id')) xbmc.executebuiltin('UpdateLibrary(video, {})'.format(basedir_tv)) if auto_update else None elif dbtype == 'season': folder = sys.listitem.getVideoInfoTag().getTVShowTitle() episodes = KodiLibrary().get_directory(sys.listitem.getPath()) season_name = 'Season {}'.format(sys.listitem.getVideoInfoTag().getSeason()) for episode in episodes: if not episode.get('episode'): continue # Skip special episodes E00 episode_path = library_cleancontent(episode.get('file')) episode_name = 'S{:02d}E{:02d} - {}'.format( utils.try_parse_int(episode.get('season')), utils.try_parse_int(episode.get('episode')), utils.validify_filename(episode.get('title'))) library_createfile(episode_name, episode_path, folder, season_name, basedir=basedir_tv) library_create_nfo('tv', sys.listitem.getProperty('tvshow.tmdb_id'), folder, basedir=basedir_tv) xbmc.executebuiltin('UpdateLibrary(video, {})'.format(basedir_tv)) if auto_update else None else: return
def get_gzip_text(self): if not self.download_url: return with utils.busy_dialog(): response = self.open_url(self.download_url) if not response: xbmcgui.Dialog().ok(self.addon.getAddonInfo('name'), self.addon.getLocalizedString(32058)) return with gzip.GzipFile(fileobj=BytesIO(response.content)) as downloaded_gzip: content = downloaded_gzip.read() return content
def play(self): utils.kodi_log( 'Script -- Attempting to play item:\n{0}'.format(self.params), 2) if not self.params.get('play') or not self.params.get('tmdb_id'): return with utils.busy_dialog(): Player().play(itemtype=self.params.get('play'), tmdb_id=self.params.get('tmdb_id'), season=self.params.get('season'), episode=self.params.get('episode'), force_dialog=self.params.get('force_dialog')) self.home.clearProperty( 'TMDbHelper.Player.ResolvedUrl') # Clear our lock property
def play(self, itemtype, tmdb_id, season=None, episode=None, force_dialog=False): """ Entry point for player method """ if not tmdb_id or not itemtype: return with utils.busy_dialog(): # Get the details for the item self.itemtype, self.tmdb_id, self.season, self.episode = itemtype, tmdb_id, season, episode self.tmdbtype = 'tv' if self.itemtype in ['episode', 'tv' ] else 'movie' self.details = self.tmdb.get_detailed_item(self.tmdbtype, tmdb_id, season=season, episode=episode) self.item['tmdb_id'] = self.tmdb_id self.item['imdb_id'] = self.details.get( 'infoproperties', {}).get('tvshow.imdb_id') or self.details.get( 'infoproperties', {}).get('imdb_id') self.item['tvdb_id'] = self.details.get( 'infoproperties', {}).get('tvshow.tvdb_id') or self.details.get( 'infoproperties', {}).get('tvdb_id') self.item['originaltitle'] = self.details.get( 'infolabels', {}).get('originaltitle') self.item['title'] = self.details.get( 'infolabels', {}).get('tvshowtitle') or self.details.get( 'infolabels', {}).get('title') self.item['year'] = self.details.get('infolabels', {}).get('year') # Check if we have a local file # TODO: Add option to auto play local if self.details and self.itemtype == 'movie': self.is_local = self.localmovie() if self.details and self.itemtype == 'episode': self.is_local = self.localepisode() self.setup_players(details=True) if not self.itemlist: return False return self.play_external(force_dialog=force_dialog)
def play(): with utils.busy_dialog(): tmdb_id, season, episode = None, None, None dbtype = sys.listitem.getVideoInfoTag().getMediaType() if dbtype == 'episode': tmdb_id = sys.listitem.getProperty('tvshow.tmdb_id') season = sys.listitem.getVideoInfoTag().getSeason() episode = sys.listitem.getVideoInfoTag().getEpisode() xbmc.executebuiltin('RunScript(plugin.video.skin.info.provider,play={},tmdb_id={},season={},episode={},force_dialog=True)'.format( dbtype, tmdb_id, season, episode)) elif dbtype == 'movie': tmdb_id = sys.listitem.getProperty('tmdb_id') xbmc.executebuiltin('RunScript(plugin.video.skin.info.provider,play={},tmdb_id={},force_dialog=True)'.format( dbtype, tmdb_id))
def add_query(self): with utils.busy_dialog(): query = utils.try_decode_string(self.params.get('add_query', '')) item = utils.dialog_select_item(query) if not item: return tmdb_id = self.tmdb.get_tmdb_id(self.params.get('type'), query=item, selectdialog=True) if not tmdb_id: utils.kodi_log(u'Unable to find TMDb ID!\nQuery: {0} Type: {1}'.format(self.params.get('add_query'), self.params.get('type')), 1) return url = 'plugin://plugin.video.skin.info.provider/?info=details&type={0}&tmdb_id={1}'.format(self.params.get('type'), tmdb_id) if url == self.home.getProperty(self.prefixcurrent): return # Already added so let's quit as user probably clicked twice self.position = self.get_position() + 1 self.set_props(self.position, url) self.lock_path(self.params.get('prevent_del')) self.call_auto()
def get_itemindex(self, force_dialog=False): default_player_movies = self.addon.getSettingString( 'default_player_movies') default_player_episodes = self.addon.getSettingString( 'default_player_episodes') if force_dialog or (self.itemtype == 'movie' and not default_player_movies) or ( self.itemtype == 'episode' and not default_player_episodes): return xbmcgui.Dialog().select( self.addon.getLocalizedString(32042), self.itemlist) itemindex = -1 with utils.busy_dialog(): for index in range(0, len(self.itemlist)): label = self.itemlist[index].getLabel() if (label == default_player_movies and self.itemtype == 'movie') or (label == default_player_episodes and self.itemtype == 'episode'): return index return itemindex
def monitor_userlist(self): with utils.busy_dialog(): user_slug = TraktAPI().get_usernameslug() # Get the user's slug user_lists = TraktAPI().get_response_json( 'users', user_slug, 'lists') # Get the user's lists if not user_lists: return monitor_userlist = self.addon.getSettingString( 'monitor_userlist') or '' monitor_userlist = monitor_userlist.split(' | ') user_list_labels, preselect = [], [] for idx, i in enumerate(user_lists): user_list_labels.append(i.get('name')) preselect.append(idx) if i.get( 'ids', {}).get('slug') in monitor_userlist else None user_choice = xbmcgui.Dialog().multiselect( self.addon.getLocalizedString(32133), user_list_labels, preselect=preselect) # Choose the list if not user_choice: # User cancelled return user_list = '' for i in user_choice: user_list += ' | ' if user_list else '' user_list += user_lists[i].get('ids', {}).get('slug') if not user_list: return self.addon.setSettingString('monitor_userlist', user_list) if xbmcgui.Dialog().yesno(xbmc.getLocalizedString(653), self.addon.getLocalizedString(32132)): self.library_autoupdate(list_slug=user_list, user_slug=user_slug)
def play(self, itemtype, tmdb_id, season=None, episode=None, force_dialog=False, kodi_db=False): """ Entry point for player method """ if not tmdb_id or not itemtype: return xbmcgui.Window(10000).clearProperty('TMDbHelper.PlayerInfoString') with utils.busy_dialog(): # Get the details for the item self.itemtype, self.tmdb_id, self.season, self.episode = itemtype, tmdb_id, season, episode self.tmdbtype = 'tv' if self.itemtype in ['episode', 'tv'] else 'movie' self.details = self.tmdb.get_detailed_item(self.tmdbtype, tmdb_id, season=season, episode=episode) self.item['tmdb_id'] = self.tmdb_id self.item['imdb_id'] = self.details.get('infoproperties', {}).get('tvshow.imdb_id') or self.details.get('infoproperties', {}).get('imdb_id') self.item['tvdb_id'] = self.details.get('infoproperties', {}).get('tvshow.tvdb_id') or self.details.get('infoproperties', {}).get('tvdb_id') self.item['originaltitle'] = self.details.get('infolabels', {}).get('originaltitle') self.item['title'] = self.details.get('infolabels', {}).get('tvshowtitle') or self.details.get('infolabels', {}).get('title') self.item['year'] = self.details.get('infolabels', {}).get('year') # Check if we have a local file # TODO: Add option to auto play local if self.details and self.itemtype == 'movie': self.is_local = self.localmovie() if self.details and self.itemtype == 'episode': self.is_local = self.localepisode() self.setup_players(details=True) if not self.itemlist: return False if kodi_db: self.playerstring = dumps({ 'tmdbtype': 'episode' if itemtype in ['episode', 'tv'] else 'movie', 'season': season, 'episode': episode, 'tmdb_id': self.tmdb_id, 'tvdb_id': self.item.get('tvdb_id'), 'imdb_id': self.item.get('imdb_id')}) return self.play_external(force_dialog=force_dialog)
def play(self, itemtype, tmdb_id, season=None, episode=None): """ Entry point for player method """ if not tmdb_id or not itemtype: return # Get the details for the item self.itemtype, self.tmdb_id, self.season, self.episode = itemtype, tmdb_id, season, episode self.tmdbtype = 'tv' if self.itemtype in ['episode', 'tv'] else 'movie' self.details = self.tmdb.get_detailed_item(self.tmdbtype, tmdb_id, season=season, episode=episode) self.item['imdb_id'] = self.details.get('infolabels', {}).get('imdbnumber') self.item['originaltitle'] = self.details.get('infolabels', {}).get('originaltitle') self.item['title'] = self.details.get( 'infolabels', {}).get('tvshowtitle') or self.details.get( 'infolabels', {}).get('title') self.item['year'] = self.details.get('infolabels', {}).get('year') # Attempt to play local file first is_local = False if self.details and self.itemtype == 'movie': is_local = self.playmovie() if self.details and self.itemtype == 'episode': is_local = self.playepisode() if is_local: return is_local with utils.busy_dialog(): self.setup_players(details=True) if not self.itemlist: return False return self.play_external()
def library_userlist(user_slug=None, list_slug=None, confirmation_dialog=True): user_slug = user_slug or sys.listitem.getProperty('Item.user_slug') list_slug = list_slug or sys.listitem.getProperty('Item.list_slug') with utils.busy_dialog(): request = TraktAPI().get_response_json('users', user_slug, 'lists', list_slug, 'items') if not request: return i_count = 0 i_total = len(request) if confirmation_dialog: d_head = _addon.getLocalizedString(32125) d_body = _addon.getLocalizedString(32126) d_body += '\n[B]{}[/B] {} [B]{}[/B]'.format(list_slug, _addon.getLocalizedString(32127), user_slug) d_body += '\n\n[B][COLOR=red]{}[/COLOR][/B] '.format(xbmc.getLocalizedString(14117)) if i_total > 20 else '\n\n' d_body += '{} [B]{}[/B] {}.'.format(_addon.getLocalizedString(32128), i_total, _addon.getLocalizedString(32129)) if not xbmcgui.Dialog().yesno(d_head, d_body): return p_dialog = xbmcgui.DialogProgressBG() p_dialog.create('TMDbHelper', 'Adding items to library...') basedir_movie = _addon.getSettingString('movies_library') or 'special://profile/addon_data/plugin.video.skin.info.provider/movies/' basedir_tv = _addon.getSettingString('tvshows_library') or 'special://profile/addon_data/plugin.video.skin.info.provider/tvshows/' auto_update = _addon.getSettingBool('auto_update') or False all_movies = [] all_tvshows = [] for i in request: i_count += 1 i_type = i.get('type') if i_type not in ['movie', 'show']: continue # Only get movies or tvshows item = i.get(i_type, {}) tmdb_id = item.get('ids', {}).get('tmdb') imdb_id = item.get('ids', {}).get('imdb') tvdb_id = item.get('ids', {}).get('tvdb') if not tmdb_id: continue # Don't bother if there isn't a tmdb_id as lookup is too expensive for long lists if i_type == 'movie': # Add any movies all_movies.append(item.get('title')) content = 'plugin://plugin.video.skin.info.provider/?info=play&tmdb_id={}&type=movie'.format(tmdb_id) folder = u'{} ({})'.format(item.get('title'), item.get('year')) movie_name = u'{} ({})'.format(item.get('title'), item.get('year')) db_file = _plugin.get_db_info(info='file', tmdbtype='movie', imdb_id=imdb_id, tmdb_id=tmdb_id) if db_file: all_movies.append(('filename', db_file.replace('\\', '/').split('/')[-1])) p_dialog.update((i_count * 100) // i_total, message=u'Found {} in library. Skipping...'.format(movie_name)) utils.kodi_log(u'Trakt List Add to Library\nFound {} in library. Skipping...'.format(movie_name), 0) continue p_dialog.update((i_count * 100) // i_total, message=u'Adding {} to library...'.format(movie_name)) utils.kodi_log(u'Adding {} to library...'.format(movie_name), 0) db_file = library_createfile(movie_name, content, folder, basedir=basedir_movie) library_create_nfo('movie', tmdb_id, folder, basedir=basedir_movie) all_movies.append(('filename', db_file.split('/')[-1])) if i_type == 'show': # Add whole tvshows all_tvshows.append(('title', item.get('title'))) content = 'plugin://plugin.video.skin.info.provider/?info=seasons&nextpage=True&tmdb_id={}&type=tv'.format(tmdb_id) folder = u'{}'.format(item.get('title')) p_dialog.update((i_count * 100) // i_total, message=u'Adding {} to library...'.format(item.get('title'))) library_addtvshow(basedir=basedir_tv, folder=folder, url=content, tmdb_id=tmdb_id, imdb_id=imdb_id, tvdb_id=tvdb_id, p_dialog=p_dialog) p_dialog.close() create_playlist(all_movies, 'movies', user_slug, list_slug) if all_movies else None create_playlist(all_tvshows, 'tvshows', user_slug, list_slug) if all_tvshows else None xbmc.executebuiltin('UpdateLibrary(video)') if auto_update else None
def play_external(self, force_dialog=False, playerindex=-1): if playerindex > -1: # Previous iteration didn't find an item to play so remove it and retry xbmcgui.Dialog().notification( self.itemlist[playerindex].getLabel(), self.addon.getLocalizedString(32040)) del self.actions[ playerindex] # Item not found so remove the player's action list del self.itemlist[ playerindex] # Item not found so remove the player's select dialog entry del self.identifierlist[ playerindex] # Item not found so remove the player's index playerindex = self.get_playerindex(force_dialog=force_dialog) # User cancelled dialog if not playerindex > -1: utils.kodi_log(u'Player -- User cancelled', 2) return False player = self.actions[playerindex] if not player or not player[1]: utils.kodi_log(u'Player -- Player not found!', 2) return False # External player has list of actions so let's iterate through them to find our item resolve_url = False if isinstance(player[1], list): actionlist = player[1] player = (False, actionlist[0]) for d in actionlist[1:]: if player[0]: break # Playable item was found in last action so let's break and play it with utils.busy_dialog(): folder = KodiLibrary().get_directory( string_format_map( player[1], self.item)) # Get the next folder from the plugin if d.get( 'dialog' ): # Special option to show dialog of items to select from d_items = [] for f in folder: # Create our list of items if not f.get('label') or f.get('label') == 'None': continue lb_list = [] label_a = f.get('label') if f.get('year') and f.get('year') != 1601: label_a = u'{} ({})'.format(label_a, f.get('year')) if utils.try_parse_int(f.get( 'season', 0)) > 0 and utils.try_parse_int( f.get('episode', 0)) > 0: label_a = u'{}x{}. {}'.format( f.get('season'), f.get('episode'), label_a) if f.get('streamdetails'): sdv_list = f.get('streamdetails', {}).get( 'video', [{}]) or [{}] sda_list = f.get('streamdetails', {}).get( 'audio', [{}]) or [{}] sdv, sda = sdv_list[0], sda_list[0] if sdv.get('width') or sdv.get('height'): lb_list.append(u'{}x{}'.format( sdv.get('width'), sdv.get('height'))) if sdv.get('codec'): lb_list.append(u'{}'.format( sdv.get('codec', '').upper())) if sda.get('codec'): lb_list.append(u'{}'.format( sda.get('codec', '').upper())) if sda.get('channels'): lb_list.append(u'{} CH'.format( sda.get('channels', ''))) for i in sda_list: if i.get('language'): lb_list.append(u'{}'.format( i.get('language', '').upper())) if sdv.get('duration'): lb_list.append(u'{} mins'.format( utils.try_parse_int(sdv.get('duration', 0)) // 60)) if f.get('size'): lb_list.append(u'{}'.format( utils.normalise_filesize(f.get('size', 0)))) label_b = ' | '.join(lb_list) if lb_list else '' d_items.append( ListItem(label=label_a, label2=label_b, icon=f.get('thumbnail')).set_listitem()) if d_items: idx = 0 if d.get('dialog', '').lower() != 'auto' or len(d_items) != 1: idx = xbmcgui.Dialog().select('Select Item', d_items, useDetails=True) if idx == -1: # User exited the dialog so return and do nothing return resolve_url = True if folder[idx].get( 'filetype' ) == 'file' else False # Set true for files so we can play player = (resolve_url, folder[idx].get('file') ) # Set the folder path to open/play break # Move onto next action else: # Ask user to select a different player if no items in dialog return self.play_external(force_dialog=force_dialog, playerindex=playerindex) x = 0 utils.kodi_log( 'Player -- Retrieved Folder\n{}'.format( string_format_map(player[1], self.item)), 2) for f in folder: # Iterate through plugin folder looking for a matching item x += 1 # Keep an index for position matching for k, v in d.items( ): # Iterate through our key (infolabel) / value (infolabel must match) pairs of our action if k == 'position': # We're looking for an item position not an infolabel if utils.try_parse_int( string_format_map(v, self.item) ) != x: # Format our position value break # Not the item position we want so let's go to next item in folder elif not f.get(k) or not re.match( string_format_map(v, self.item), u'{}'.format( f.get(k, '')) ): # Format our value and check if it regex matches the infolabel key break # Item's key value doesn't match value we are looking for so let's got to next item in folder else: # Item matched our criteria so let's open it up utils.kodi_log('Player -- Found Match!\n{}'.format(f), 2) resolve_url = True if f.get( 'filetype' ) == 'file' else False # Set true for files so we can play player = (resolve_url, f.get('file') ) # Get ListItem.FolderPath for item break # Move onto next action (either open next folder or play file) else: utils.kodi_log( 'Player -- Failed to find match!\n{}'.format(d), 2) return self.play_external( force_dialog=force_dialog, playerindex=playerindex ) # Ask user to select a different player # Play/Search found item if player and player[1]: action = string_format_map(player[1], self.item) if player[0] and action.endswith( '.strm'): # Action is play and is a strm so PlayMedia utils.kodi_log( u'Player -- Found strm.\nAttempting PLAYMEDIA({})'.format( action), 2) xbmc.executebuiltin( utils.try_decode_string(u'PlayMedia({0})'.format(action))) elif player[ 0]: # Action is play and not a strm so play with player utils.kodi_log( u'Player -- Found file.\nAttempting to PLAY: {}'.format( action), 2) xbmc.Player().play( action, ListItem(library='video', **self.details).set_listitem()) else: action = u'Container.Update({0})'.format( action) if xbmc.getCondVisibility( "Window.IsMedia" ) else u'ActivateWindow(videos,{0},return)'.format(action) utils.kodi_log( u'Player -- Found folder.\nAttempting to OPEN: {}'.format( action), 2) xbmc.executebuiltin(utils.try_decode_string(action)) return action
def action(action, tmdb_id=None, tmdb_type=None, season=None, episode=None, label=None): _traktapi = TraktAPI() if action == 'history': func = _traktapi.sync_history elif action == 'collection': func = _traktapi.sync_collection elif action == 'watchlist': func = _traktapi.sync_watchlist elif action == 'add_to_userlist': return sync_userlist() elif action == 'remove_from_userlist': return sync_userlist(remove_item=True) elif action == 'library_userlist': return library_userlist() elif action == 'library': return library() elif action == 'refresh_item': return refresh_item() elif action == 'play': return play() elif action == 'open': return browse() else: return with utils.busy_dialog(): if tmdb_id and tmdb_type: # Passed details via script dbtype = utils.type_convert(tmdb_type, 'dbtype') label = label or 'this {}'.format(utils.type_convert(tmdb_type, 'trakt')) parent_tmdb_id = tmdb_id else: # Context menu so retrieve details from listitem label = sys.listitem.getLabel() dbtype = sys.listitem.getVideoInfoTag().getMediaType() tmdb_id = sys.listitem.getProperty('tmdb_id') parent_tmdb_id = sys.listitem.getProperty('tvshow.tmdb_id') if dbtype == 'episode' else tmdb_id season = sys.listitem.getVideoInfoTag().getSeason() if dbtype == 'episode' else None episode = sys.listitem.getVideoInfoTag().getEpisode() if dbtype == 'episode' else None if tmdb_type == 'episode': # Passed episode details via script if not season or not episode: # Need season and episode for episodes return # Need season and episode if run from script so leave # Retrieve episode details so that we can get tmdb_id for episode episode_details = _plugin.tmdb.get_detailed_item(tmdb_type, parent_tmdb_id, season=season, episode=episode) tmdb_id = episode_details.get('infoproperties', {}).get('imdb_id') if dbtype == 'movie': tmdb_type = 'movie' elif dbtype == 'tvshow': tmdb_type = 'tv' elif dbtype == 'episode': tmdb_type = 'episode' else: return # Check if we're adding or removing the item and confirm with the user that they want to do that trakt_ids = func(utils.type_convert(tmdb_type, 'trakt'), 'tmdb', cache_refresh=True) boolean = 'remove' if int(tmdb_id) in trakt_ids else 'add' dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32065) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32064) dialog_text = dialog_text.format(utils.try_decode_string(label), action.capitalize(), tmdb_type, tmdb_id) dialog_text = dialog_text + ' Season: {} Episode: {}'.format(season, episode) if dbtype == 'episode' else dialog_text if not xbmcgui.Dialog().yesno(dialog_header, dialog_text): return with utils.busy_dialog(): slug_type = 'show' if tmdb_type == 'episode' else utils.type_convert(tmdb_type, 'trakt') trakt_type = utils.type_convert(tmdb_type, 'trakt') slug = _traktapi.get_traktslug(slug_type, 'tmdb', parent_tmdb_id) item = _traktapi.get_details(slug_type, slug, season=season, episode=episode) items = {trakt_type + 's': [item]} func(slug_type, mode=boolean, items=items) dialog_header = 'Trakt {0}'.format(action.capitalize()) dialog_text = xbmcaddon.Addon().getLocalizedString(32062) if boolean == 'add' else xbmcaddon.Addon().getLocalizedString(32063) dialog_text = dialog_text.format(tmdb_id, action.capitalize()) xbmcgui.Dialog().ok(dialog_header, dialog_text) xbmc.executebuiltin('Container.Refresh')
def play_external(self, force_dialog=False): itemindex = self.get_itemindex(force_dialog=force_dialog) # User cancelled dialog if not itemindex > -1: return False player = self.actions[itemindex] if not player or not player[1]: return False # External player has list of actions so let's iterate through them to find our item resolve_url = False if isinstance(player[1], list): actionlist = player[1] player = (False, actionlist[0]) with utils.busy_dialog(): for d in actionlist[1:]: if player[0]: break # Playable item was found in last action so let's break and play it folder = KodiLibrary().get_directory( string_format_map( player[1], self.item)) # Get the next folder from the plugin x = 0 for f in folder: # Iterate through plugin folder looking for a matching item x += 1 # Keep an index for position matching for k, v in d.items( ): # Iterate through our key (infolabel) / value (infolabel must match) pairs of our action if k == 'position': # We're looking for an item position not an infolabel if utils.try_parse_int( string_format_map(v, self.item) ) != x: # Format our position value break # Not the item position we want so let's go to next item in folder elif not f.get(k) or string_format_map( v, self.item ) not in u'{}'.format( f.get(k, '') ): # Format our value and check if it matches the infolabel key break # Item's key value doesn't match value we are looking for so let's got to next item in folder else: # Item matched our criteria so let's open it up resolve_url = True if f.get( 'filetype' ) == 'file' else False # Set true for files so we can play player = (resolve_url, f.get('file') ) # Get ListItem.FolderPath for item break # Move onto next action (either open next folder or play file) else: xbmcgui.Dialog().notification( self.itemlist[itemindex].getLabel(), self.addon.getLocalizedString(32040)) del self.actions[ itemindex] # Item not found so remove the player's action list del self.itemlist[ itemindex] # Item not found so remove the player's select dialog entry return self.play_external( force_dialog=True ) # Ask user to select a different player # Play/Search found item if player and player[1]: action = string_format_map(player[1], self.item) if player[0]: # Action is play so let's play the item and return xbmc.Player().play( action, ListItem(library='video', **self.details).set_listitem()) return action # Action is search so let's load the plugin path action = u'Container.Update({0})'.format( action) if xbmc.getCondVisibility( "Window.IsMedia" ) else u'ActivateWindow(videos,{0},return)'.format(action) xbmc.executebuiltin(utils.try_decode_string(action)) return action