def process_mixed_product(item): title = ensure_native_str(item['title'], 'utf-8') if item['pricingPlans'][0]['availability']: if item['pricingPlans'][0]['availability']['plus']: if HIDE_PREMIUM: return False title += ' |%s|' % ensure_native_str(Script.localize(30308), 'utf-8') else: return False itemId = item['id'] productType = item['productType'] liz = Listitem() liz.label = title liz.art["poster"] = formatimg(item['image']['posterImage'], 'poster') liz.art["fanart"] = formatimg(item['image']['thumbnailImage'], 'fanart') if 'logoTitleImage' in item: liz.art["banner"] = formatimg(item['logoTitleImage'], 'banner') aired = str(item['createdDate'].split('T')[0]) liz.info.date(aired, "%Y-%m-%d") liz.info['plot'] = ensure_native_str(item['description'], 'utf-8') if productType == 'MOVIE': liz.info['duration'] = item['duration'] liz.info['mediatype'] = "movie" liz.set_callback(play_video, streamId=itemId) elif productType == 'SHOW': liz.info['mediatype'] = "show" liz.set_callback(BROWSE_SEASONS, showId=itemId) CONTEXT_MENU2(liz, itemId, title, productType) return liz
def notify(heading, message, icon=None, display_time=5000, sound=True): """ Send a notification to kodi. Options for icon are. * :attr:`Script.NOTIFY_INFO<codequick.script.Script.NOTIFY_INFO>` * :attr:`Script.NOTIFY_ERROR<codequick.script.Script.NOTIFY_ERROR>` * :attr:`Script.NOTIFY_WARNING<codequick.script.Script.NOTIFY_WARNING>` :type heading: str or unicode :param heading: Dialog heading label. :type message: str or unicode :param message: Dialog message label. :type icon: str or unicode :param icon: [opt] Icon image to use. (default => 'add-on icon image') :param int display_time: [opt] Ttime in milliseconds to show dialog. (default => 5000) :param bool sound: [opt] Whether or not to play notification sound. (default => True) """ # Ensure that heading, message and icon # is encoded into native str type heading = ensure_native_str(heading) message = ensure_native_str(message) icon = ensure_native_str(icon if icon else Script.get_info("icon")) dialog = xbmcgui.Dialog() dialog.notification(heading, message, icon, display_time, sound)
def BROWSE_EPISODES(plugin, playListId, profile_id=None, profile_type=None, is_master=False, **kwargs): plugin.add_sort_methods(xbmcplugin.SORT_METHOD_EPISODE) plugin.log('BROWSE_EPISODES playListId: %s' % playListId, lvl=plugin.DEBUG) headers = get_headers(profile_id, profile_type, is_master) page = 0 hasMore = True while hasMore: params = get_filter(requesttype='request', playListId=playListId, pageNumber=page, pageSize=30) plugin.log('Fetching url: %s' % PLAYLIST_API, lvl=plugin.DEBUG) plugin.log('Fetching params: %s' % params, lvl=plugin.DEBUG) Response = urlquick.get(PLAYLIST_API, params=params, headers=headers).json() items = Response['productList'] hasMore = items['hasMore'] showTitle = items['products'][0]['show']['title'] plugin.log('showTitle: %s' % showTitle, lvl=plugin.DEBUG) for item in items['products']: streamId = item['id'] title = item['title'] plot = title thumb = formatimg(item['image']['thumbnailImage'], 'thumbnail') episodeNumb = item['number'] seasonNumb = item['show']['season']['seasonNumber'] duration = item['duration'] aired = str(item['createdDate'].split('T')[0]) vtype = item['assetType'] liz = Listitem() # if duration is superior to 15 minutes assume it's an episode not a clip if vtype == "EPISODE" or (vtype != "EPISODE" and duration > 900): if vtype != "EPISODE": showTitle += ' %s' % item['playlist']['title'] liz.info['episode'] = episodeNumb liz.info['season'] = seasonNumb liz.info['mediatype'] = "episode" liz.label = ensure_native_str(showTitle, 'utf-8') liz.TVShowTitle = showTitle else: liz.label = ensure_native_str(title, 'utf-8') \ or ensure_native_str(item['bcmMediaID'], 'utf-8') liz.info['mediatype'] = "video" liz.info['plot'] = ensure_native_str(plot, 'utf-8') liz.art["thumb"] = thumb liz.info.date(aired, "%Y-%m-%d") liz.info.duration = duration liz.set_callback(play_video, streamId=streamId) plugin.log('Adding: %s S%sxE%s' % (showTitle, seasonNumb, episodeNumb), lvl=plugin.DEBUG) yield liz page = page + 1
def send_to_kodi(handle, session): """Handle the processing of the listitems.""" # Guess the contenty type if session["content_type"] == -1: kodi_listitems = [] folder_counter = 0.0 mediatypes = defaultdict(int) for listitem in session["listitems"]: # Build the kodi listitem listitem_tuple = listitem.build() kodi_listitems.append(listitem_tuple) # Track the mediatypes used if "mediatype" in listitem.info: mediatypes[listitem.info["mediatype"]] += 1 # Track if listitem is a folder if listitem_tuple[2]: folder_counter += 1 # Guess content type based on set mediatypes session["content_type"] = guess_content_type(mediatypes) if not session["content_type"]: # Fallback # Set content type based on type of content being listed isfolder = folder_counter > (len(kodi_listitems) / 2) session["content_type"] = "files" if isfolder else "videos" else: # Just build the kodi listitem without tracking anything kodi_listitems = [ custom_listitem.build() for custom_listitem in session["listitems"] ] # If redirect_single_item is set to True then redirect view to the first # listitem if it's the only listitem and that listitem is a folder if session["redirect"] and len( kodi_listitems) == 1 and kodi_listitems[0][2] is True: return kodi_listitems[0][0] # return the listitem path # Add sort methods for sortMethod in session["sortmethods"]: xbmcplugin.addSortMethod(handle, sortMethod) # Sets the category for skins to display if session["category"]: xbmcplugin.setPluginCategory(handle, ensure_native_str(session["category"])) # Sets the plugin category for skins to display if session["content_type"]: xbmcplugin.setContent(handle, ensure_native_str(session["content_type"])) success = xbmcplugin.addDirectoryItems(handle, kodi_listitems, len(kodi_listitems)) xbmcplugin.endOfDirectory(handle, success, session["update_listing"], session["cache_to_disc"])
def __content_type(self, isfolder, mediatypes): """Configure plugin properties, content, category and sort methods.""" # See if we can guess the content_type based on the mediatypes from the listitem if mediatypes and not self.content_type: if len(mediatypes) > 1: from operator import itemgetter # Sort mediatypes by there count, and return the highest count mediatype mediatype = sorted(mediatypes.items(), key=itemgetter(1))[-1][0] else: mediatype = list(mediatypes.keys())[0] # Convert mediatype to a content_type, not all mediatypes can be converted directly if mediatype in ("video", "movie", "tvshow", "episode", "musicvideo", "song", "album", "artist"): self.content_type = mediatype + "s" # Set the add-on content type content_type = self.content_type or ("files" if isfolder else "videos") xbmcplugin.setContent(self.handle, content_type) logger.debug("Content-type: %s", content_type) # Sets the category for skins to display modes. xbmcplugin.setPluginCategory( self.handle, ensure_native_str(re.sub(u"\(\d+\)$", u"", self._title).strip())) # Add sort methods only if not a folder(Video listing) if not isfolder: self.__add_sort_methods(self._manual_sort)
def list_videos(plugin, item_id, category_url, **kwargs): """Build videos listing""" videos_datas_xml = urlquick.get(category_url).text videos_datas_xml = utils.ensure_native_str(videos_datas_xml) xml_elements = ET.XML(videos_datas_xml) for video in xml_elements.findall(".//event"): video_links = video.findall(".//link") video_url = '' for video_link in video_links: if 'Video' in video_link.text: video_url = video_link.get('href') if video_url != '': item = Listitem() item.label = video.find("title").text if video.find("abstract").text: item.info['plot'] = utils.strip_tags( video.find("abstract").text) item.set_callback(get_video_url, item_id=item_id, video_url=video_url) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item
def build_path(path=None, query=None, **extra_query): """ Build addon url that can be passeed to kodi for kodi to use when calling listitems. :param path: [opt] The route selector path referencing the callback object. (default => current route selector) :param dict query: [opt] A set of query key/value pairs to add to plugin path. :param extra_query: [opt] Keyword arguments if given will be added to the current set of querys. :return: Plugin url for kodi. :rtype: str """ # If extra querys are given then append the # extra querys to the current set of querys if extra_query: query = dispatcher.params.copy() query.update(extra_query) # Encode the query parameters using json if query: query = "_pickle_=" + ensure_native_str( binascii.hexlify( pickle.dumps(query, protocol=pickle.HIGHEST_PROTOCOL))) # Build kodi url with new path and query parameters return urlparse.urlunsplit( ("plugin", plugin_id, path if path else dispatcher.selector, query, ""))
def list_videos(plugin, item_id, category_url): """Build videos listing""" videos_datas_xml = urlquick.get(category_url).text videos_datas_xml = utils.ensure_native_str(videos_datas_xml) xml_elements = ET.XML(videos_datas_xml) for video in xml_elements.findall(".//event"): video_links = video.findall(".//link") video_url = '' for video_link in video_links: if 'Video' in video_link.text: video_url = video_link.get('href') if video_url != '': item = Listitem() item.label = video.find("title").text if video.find("abstract").text: item.info['plot'] = utils.strip_tags( video.find("abstract").text) item.context.script(get_video_url, plugin.localize(LABELS['Download']), item_id=item_id, video_url=video_url, video_label=LABELS[item_id] + ' - ' + item.label, download_mode=True) item.set_callback(get_video_url, item_id=item_id, video_url=video_url) yield item
def local_thumb(self, image): """ Set the "thumbnail" image to a image file, located in the add-on "resources/media" directory. :param str image: Filename of the image. """ # Here we can't be sure if 'image' only contains ascii characters, so ensure_native_str is needed self.raw_dict["thumb"] = local_image.format(ensure_native_str(image))
def send_channels(self): """Return JSON-STREAMS formatted python datastructure to IPTV Manager""" channels_list = [] # Grab all live TV channels country_channels = get_all_live_tv_channels() # Grab current user settings tv_integration_settings = get_tv_integration_settings() for (country_order, country_id, country_label, country_infos, channels) in country_channels: for (channel_order, channel_id, channel_label, channel_infos, lang) in channels: channel_key = channel_id if not lang else channel_id + ' ' + lang if not tv_integration_settings['enabled_channels'].get( country_id, {}).get(channel_key, {}).get( 'enabled', False): continue json_stream = {} json_stream['name'] = channel_label resolver = channel_infos['resolver'].replace(':', '/') params = {'item_id': channel_id} if lang: params['language'] = lang lang_infos = channel_infos['available_languages'][lang] json_stream['id'] = lang_infos.get('xmltv_id') json_stream['preset'] = lang_infos.get('m3u_order') else: json_stream['id'] = channel_infos.get('xmltv_id') json_stream['preset'] = channel_infos.get('m3u_order') # It seems that in Python 2 urlencode doesn't deal well with unicode data # (see https://stackoverflow.com/a/3121311) for k, v in params.items(): params[k] = utils.ensure_native_str(v) json_stream['stream'] = utils.ensure_native_str( PLUGIN_KODI_PATH + resolver + '/?') + urlencode(params) json_stream['logo'] = get_item_media_path( channel_infos['thumb']) channels_list.append(json_stream) return dict(version=1, streams=channels_list)
def create_cache_file(): if not xbmcvfs.exists( 'special://profile/addon_data/plugin.video.shahid/exported.json'): content = '{"movies": {},"tvshows": {}}' file_handle = xbmcvfs.File( translatePath( 'special://profile/addon_data/plugin.video.shahid/exported.json' ), 'wb') file_handle.write(bytearray(ensure_native_str(content, 'utf-8')))
def list_videos(plugin, item_id, program_title, **kwargs): resp = urlquick.get(URL_VIDEOS % program_title) videos_datas_xml = utils.ensure_native_str(resp.text) xml_elements = ET.XML(videos_datas_xml) for video in xml_elements.findall(".//video"): item = Listitem()
def local_thumb(self, image): """ Set the thumbnail image to a image file, located in the add-on resources/media directory. :param image: Filename of the image. :type image: str or unicode """ # Here we can't be sure if 'image' only contains ascii characters # So ensure_native_str is needed self.raw_dict["thumb"] = local_image.format(ensure_native_str(image))
def notify(heading, message, icon=None, display_time=5000, sound=True): """ Send a notification to Kodi. Options for icon are. * :attr:`Script.NOTIFY_INFO<codequick.script.Script.NOTIFY_INFO>` * :attr:`Script.NOTIFY_ERROR<codequick.script.Script.NOTIFY_ERROR>` * :attr:`Script.NOTIFY_WARNING<codequick.script.Script.NOTIFY_WARNING>` :param str heading: Dialog heading label. :param str message: Dialog message label. :param str icon: [opt] Icon image to use. (default => 'add-on icon image') :param int display_time: [opt] Ttime in "milliseconds" to show dialog. (default => 5000) :param bool sound: [opt] Whether or not to play notification sound. (default => True) """ # Ensure that heading, message and icon # is encoded into native str type heading = ensure_native_str(heading) message = ensure_native_str(message) icon = ensure_native_str(icon if icon else Script.get_info("icon")) dialog = xbmcgui.Dialog() dialog.notification(heading, message, icon, display_time, sound)
def get_video_url(plugin, video_id, download_mode=False, **kwargs): """Get video URL and start video player""" stream_xml = urlquick.get(URL_STREAM % video_id).text stream_xml = utils.ensure_native_str(stream_xml) stream_url = '' xml_elements = ET.XML(stream_xml) for item in xml_elements.findall('./channel/item'): for child in item: if child.tag == '{http://search.yahoo.com/mrss/}content': stream_url = child.attrib['url'] if download_mode: return download.download_video(stream_url) return stream_url
def _process_results(self, raw_listitems): """Handle the processing of the listitems.""" raw_listitems = validate_listitems(raw_listitems) if raw_listitems is False: xbmcplugin.endOfDirectory(self.handle, False) return None # Create a new list containing tuples, consisting of path, listitem, isfolder. listitems = [] folder_counter = 0.0 mediatypes = defaultdict(int) for listitem in raw_listitems: if listitem: # pragma: no branch # noinspection PyProtectedMember listitem_tuple = listitem._close() listitems.append(listitem_tuple) if listitem_tuple[2]: # pragma: no branch folder_counter += 1 if "mediatype" in listitem.info: mediatypes[listitem.info["mediatype"]] += 1 # If redirect_single_item is set to True then redirect view to the first # listitem if it's the only listitem and that listitem is a folder if self.redirect_single_item and len( listitems) == 1 and listitems[0][2] is True: return listitems[0][0] # return the listitem path # Guess if this directory listing is primarily a folder or video listing. # Listings will be considered to be a folder if more that half the listitems are folder items. isfolder = folder_counter > (len(listitems) / 2) # Sets the category for skins to display modes. xbmcplugin.setPluginCategory(self.handle, ensure_native_str(self.category)) if self.content_type is not None: self.__content_type("files" if isfolder else "videos", mediatypes) # Add sort methods only if not a folder(Video listing) if not isfolder: self.__add_sort_methods(self._manual_sort) # Pass the listitems and relevant data to kodi success = xbmcplugin.addDirectoryItems(self.handle, listitems, len(listitems)) xbmcplugin.endOfDirectory(self.handle, success, self.update_listing, self.cache_to_disc)
def get_item_media_path(item_media_path): full_path = '' # Local image in ressources/media folder if type(item_media_path) is list: full_path = os.path.join(Script.get_info("path"), "resources", "media", *(item_media_path)) # Remote image with complete URL elif 'http' in item_media_path: full_path = item_media_path # Remote image on our images repo else: full_path = 'https://github.com/Catch-up-TV-and-More/images/raw/master/' + item_media_path return ensure_native_str(full_path)
def emit(self, record): # type: (logging.LogRecord) -> None """Forward the log record to kodi, lets kodi handle the logging.""" formatted_msg = ensure_native_str(self.format(record)) log_level = record.levelno # Forward the log record to kodi with translated log level xbmc.log(formatted_msg, self.log_level_map[log_level]) # Keep a history of all debug records so they can be logged later if a critical error occurred # Kodi by default, won't show debug messages unless debug logging is enabled if log_level == 10: self.debug_msgs.append(formatted_msg) # If a critical error occurred, log all debug messages as warnings elif log_level == 50 and self.debug_msgs: xbmc.log("###### debug ######", xbmc.LOGWARNING) for msg in self.debug_msgs: xbmc.log(msg, xbmc.LOGWARNING) xbmc.log("###### debug ######", xbmc.LOGWARNING)
def date(self, date, date_format): """ Set the date infolabel. :param str date: The date for the listitem. :param str date_format: The format of the date as a strftime directive e.g. "june 27, 2017" => "%B %d, %Y" .. seealso:: The full list of directives can be found at: https://docs.python.org/3.6/library/time.html#time.strftime :example: >>> item = Listitem() >>> item.info.date('june 27, 2017', '%B %d, %Y') """ converted_date = strptime(ensure_native_str(date), date_format) self.raw_dict["date"] = strftime("%d.%m.%Y", converted_date) # 27.06.2017 self.raw_dict["aired"] = strftime("%Y-%m-%d", converted_date) # 2017-06-27 self.raw_dict["year"] = strftime("%Y", converted_date) # 2017 auto_sort_add(xbmcplugin.SORT_METHOD_VIDEO_YEAR) auto_sort_add(xbmcplugin.SORT_METHOD_DATE)
def _process_results(self, raw_listitems): """Handle the processing of the listitems.""" raw_listitems = validate_listitems(raw_listitems) if raw_listitems is False: xbmcplugin.endOfDirectory(self.handle, False) return None # Create a new list containing tuples, consisting of path, listitem, isfolder. listitems = [] folder_counter = 0.0 mediatypes = defaultdict(int) for listitem in raw_listitems: if listitem: # pragma: no branch # noinspection PyProtectedMember listitem_tuple = listitem._close() listitems.append(listitem_tuple) if listitem_tuple[2]: # pragma: no branch folder_counter += 1 if "mediatype" in listitem.info: mediatypes[listitem.info["mediatype"]] += 1 # Guess if this directory listing is primarily a folder or video listing. # Listings will be considered to be a folder if more that half the listitems are folder items. isfolder = folder_counter > (len(listitems) / 2) # Sets the category for skins to display modes. xbmcplugin.setPluginCategory(self.handle, ensure_native_str(self.category)) if self.content_type is not None: self.__content_type("files" if isfolder else "videos", mediatypes) # Add sort methods only if not a folder(Video listing) if not isfolder: self.__add_sort_methods(self._manual_sort) # Pass the listitems and relevant data to kodi success = xbmcplugin.addDirectoryItems(self.handle, listitems, len(listitems)) xbmcplugin.endOfDirectory(self.handle, success, self.update_listing, self.cache_to_disc)
def list_videos(plugin, item_id, program_title, **kwargs): resp = urlquick.get(URL_VIDEOS % program_title) videos_datas_xml = utils.ensure_native_str(resp.text) xml_elements = ET.XML(videos_datas_xml) for video in xml_elements.findall(".//video"): item = Listitem() item.label = video.find(".//show").text if video.find(".//description").text: item.info['plot'] = utils.strip_tags( video.find(".//description").text) item.art['thumb'] = item.art['landscape'] = video.find( ".//screenshot").text video_id = video.find(".//pageurl").text item.set_callback(get_video_url, item_id=item_id, video_id=video_id) item_post_treatment(item, is_playable=True, is_downloadable=True) yield item
def date(self, date, date_format): """ Set the date of the listitem. :param date: The date for the listitem. :type date: str or unicode :param str date_format: The format of the date as a strftime directive e.g. 'june 27, 2017' => '%B %d, %Y' .. seealso:: The full list of directives can be found at. https://docs.python.org/3.6/library/time.html#time.strftime :example: >>> item = Listitem() >>> item.info.date('june 27, 2017', '%B %d, %Y') """ converted_date = strptime(ensure_native_str(date), date_format) self.raw_dict["date"] = strftime("%d.%m.%Y", converted_date) # 27.06.2017 self.raw_dict["aired"] = strftime("%Y-%m-%d", converted_date) # 2017-06-27 self.raw_dict["year"] = strftime("%Y", converted_date) # 2017 auto_sort_add(xbmcplugin.SORT_METHOD_VIDEO_YEAR) auto_sort_add(xbmcplugin.SORT_METHOD_DATE)
def get_item_media_path(item_media_path): """Get full path or URL of an item_media Args: item_media_path (str or list): Partial media path of the item (e.g. channels/fr/tf1.png) Returns: str: Full path or URL of the item_pedia """ full_path = '' # Local image in ressources/media folder if type(item_media_path) is list: full_path = os.path.join(Script.get_info("path"), "resources", "media", *(item_media_path)) # Remote image with complete URL elif 'http' in item_media_path: full_path = item_media_path # Remote image on our images repo else: full_path = 'https://github.com/Catch-up-TV-and-More/images/raw/master/' + item_media_path return utils.ensure_native_str(full_path)
def get_item_media_path(item_media_path): """Get full path or URL of an item_media Args: item_media_path (str or list): Partial media path of the item (e.g. channels/fr/tf1.png) Returns: str: Full path or URL of the item_pedia """ full_path = '' # Local image in ressources/media folder if type(item_media_path) is list: full_path = os.path.join(Script.get_info("path"), "resources", "media", *(item_media_path)) # Remote image with complete URL elif 'http' in item_media_path: full_path = item_media_path # Image in our resource.images add-on else: full_path = 'resource://resource.images.catchuptvandmore/' + item_media_path return utils.ensure_native_str(full_path)
def _process_results(self, results): """Process the results and return a cacheable dict of session data.""" listitems = validate_listitems(results) if listitems is False: xbmcplugin.endOfDirectory(self.handle, False) return None return { "listitems": listitems, "category": ensure_native_str(self.category), "update_listing": self.update_listing, "cache_to_disc": self.cache_to_disc, "sortmethods": build_sortmethods(self.sort_methods, auto_sort if self.autosort else None), "content_type": self.content_type, "redirect": self.redirect_single_item }
def formatimg(URL, TYPE): croppingPoint = 'mc' if TYPE == 'fanart': height = 1080 width = 1920 elif TYPE == 'poster': height = 450 width = 300 elif TYPE == 'thumbnail': height = 180 width = 320 elif TYPE == 'icon': height = 250 width = 250 elif TYPE == 'banner': height = '' width = '' URL = ensure_native_str( URL.format(height=height, width=width, croppingPoint=croppingPoint), 'utf-8') # in some case the api is returning a faulty url if not '/mediaObject' in URL: URL = URL.replace('mediaObject', '/mediaObject') return quote(URL, safe='&?=:/')
def __repr__(self): """Returns representation of the object.""" return "{}('{}')".format(self.__class__.__name__, ensure_native_str(self.label))
def __setitem__(self, key, value): if value: self.raw_dict[key] = ensure_native_str(value) else: logger.debug("Ignoring empty art value: '%s'", key)
# Kodi imports import xbmcplugin import xbmcgui # Package imports from codequick.script import Script from codequick.support import auto_sort, build_path, logger_id, dispatcher from codequick.utils import safe_path, ensure_unicode, ensure_native_str, unicode_type, long_type __all__ = ["Listitem", "Art", "Info", "Stream", "Context", "Property", "Params"] # Logger specific to this module logger = logging.getLogger("%s.listitem" % logger_id) # Listitem thumbnail locations local_image = ensure_native_str(os.path.join(Script.get_info("path"), u"resources", u"media", u"{}")) global_image = ensure_native_str(os.path.join(Script.get_info("path_global"), u"resources", u"media", u"{}")) # Prefetch fanart/icon for use later _fanart = Script.get_info("fanart") fanart = ensure_native_str(_fanart) if os.path.exists(safe_path(_fanart)) else None icon = ensure_native_str(Script.get_info("icon")) # Stream type map to ensure proper stream value types stream_type_map = {"duration": int, "channels": int, "aspect": float, "height": int, "width": int} # Listing sort methods & sort mappings.
def test_ensure_native_str_with_int(self): ret = utils.ensure_native_str(101) self.assertIsInstance(ret, str) self.assertEqual(ret, "101")
def __setitem__(self, key, value): # type: (str, str) -> None self.raw_dict[key] = ensure_native_str(value)
def BROWSE_TVSHOWS(plugin, genreId, productSubType, page='0', profile_id=None, profile_type=None, is_master=False, **kwargs): plugin.log('BROWSE_TVSHOWS genreId: %s' % genreId, lvl=plugin.DEBUG) plugin.log('BROWSE_TVSHOWS productSubType: %s' % productSubType, lvl=plugin.DEBUG) EMAIL = plugin.setting.get_string('username') PASSWORD = plugin.setting.get_string('password') headers = get_headers(profile_id, profile_type, is_master) productType = 'SHOW' hasMore = True liz = None while not liz and hasMore: plugin.log('page: %s' % page, lvl=plugin.DEBUG) params = get_filter(requesttype='filter', CATEGORY_MODE=Show_Category_Mode, pageNumber=page, pageSize=30, productType=productType, productSubType=productSubType, sorts=[{ "order": "DESC", "type": "SORTDATE" }], genreId=genreId) plugin.log('Fetching url: %s' % TVSOWS_API, lvl=plugin.DEBUG) plugin.log('Fetching params: %s' % params, lvl=plugin.DEBUG) Response = urlquick.get(TVSOWS_API, params=params, headers=headers, max_age=0).json() items = Response['productList'] hasMore = items['hasMore'] for item in items['products']: title = item['title'] plot = item['description'] if item['pricingPlans'][0]['availability']: if item['pricingPlans'][0]['availability']['plus']: if HIDE_PREMIUM: continue title += ' |%s|' % plugin.localize(30308) showId = item['id'] liz = Listitem() liz.label = ensure_native_str(title) liz.info['mediatype'] = "tvshow" liz.art["poster"] = formatimg(item['image']['posterImage'], 'poster') liz.art["fanart"] = formatimg(item['image']['thumbnailImage'], 'fanart') if 'logoTitleImage' in item: liz.art["banner"] = formatimg(item['logoTitleImage'], 'banner') aired = str(item['createdDate'].split('T')[0]) liz.info.date(aired, "%Y-%m-%d") liz.info['plot'] = ensure_native_str(plot) liz.set_callback(BROWSE_SEASONS, showId=showId, profile_id=profile_id, profile_type=profile_type, is_master=is_master) plugin.log('Adding: %s' % title, lvl=plugin.DEBUG) if EMAIL and PASSWORD: CONTEXT_MENU(liz, showId, profile_id, profile_type, is_master) CONTEXT_MENU2(liz, showId, item['title'], "SHOW") yield liz if not liz: page = int(page) + 1 if hasMore: page = int(page) + 1 yield Listitem.next_page(genreId=genreId, productSubType=productSubType, page=str(page), profile_id=profile_id, profile_type=profile_type, is_master=is_master) if not liz and not hasMore: yield False plugin.notify(plugin.localize(30208), plugin.localize(30202), display_time=5000, sound=True)
from codequick.utils import ensure_unicode, ensure_native_str, unicode_type, PY3, bold if PY3: # noinspection PyUnresolvedReferences, PyCompatibility from collections.abc import MutableMapping, MutableSequence else: # noinspection PyUnresolvedReferences, PyCompatibility from collections import MutableMapping, MutableSequence __all__ = ["Listitem"] # Logger specific to this module logger = logging.getLogger("%s.listitem" % logger_id) # Listitem thumbnail locations local_image = ensure_native_str(os.path.join(Script.get_info("path"), u"resources", u"media", u"{}")) global_image = ensure_native_str(os.path.join(Script.get_info("path_global"), u"resources", u"media", u"{}")) # Prefetch fanart/icon for use later _fanart = Script.get_info("fanart") fanart = ensure_native_str(_fanart) if os.path.exists(_fanart) else None icon = ensure_native_str(Script.get_info("icon")) # Stream type map to ensure proper stream value types stream_type_map = {"duration": int, "channels": int, "aspect": float, "height": int, "width": int} # Listing sort methods & sort mappings.
def BROWSE_MOVIES(plugin, genreId, page='0', profile_id=None, profile_type=None, is_master=False, **kwargs): plugin.log('BROWSE_MOVIES genreId: %s' % genreId, lvl=plugin.DEBUG) EMAIL = plugin.setting.get_string('username') PASSWORD = plugin.setting.get_string('password') headers = get_headers(profile_id, profile_type, is_master) productType = 'MOVIE' hasMore = True liz = None while not liz and hasMore: plugin.log('page: %s' % page, lvl=plugin.DEBUG) params = get_filter( requesttype='filter', CATEGORY_MODE=Movie_Category_Mode, pageNumber=page, pageSize=30, productType=productType, sorts=[{"order": "DESC", "type": "SORTDATE"}], genreId=genreId ) plugin.log('Fetching url: %s' % TVSOWS_API, lvl=plugin.DEBUG) plugin.log('Fetching params: %s' % params, lvl=plugin.DEBUG) Response = urlquick.get( TVSOWS_API, params=params, headers=headers, max_age=0 ).json() items = Response['productList'] hasMore = items['hasMore'] for item in items['products']: title = ensure_native_str(item['title'], 'utf-8') plot = ensure_native_str(item['description'], 'utf-8') cast = [] for person in item['persons']: actor = person['fullName'] cast.append(actor) if item['pricingPlans'][0]['availability']: movieId = item['id'] if item['pricingPlans'][0]['availability']['plus']: if HIDE_PREMIUM: continue title += ' |%s|' % ensure_native_str(plugin.localize(30308), 'utf-8') # if not available assume it's comming soon and return the trailer elif item['trailerItem']: title += ' |%s|' % ensure_native_str(plugin.localize(30309), 'utf-8') movieId = item['trailerItem']['id'] else: continue aired = str(item['createdDate'].split('T')[0]) liz = Listitem() liz.label = title if item['trailerItem']: trailerId = item['trailerItem']['id'] trailer = 'plugin://plugin.video.shahid/resources/lib/playback_resolver/play_video/?streamId=%s' % trailerId liz.info['trailer'] = trailer liz.info['mediatype'] = "movie" liz.info['cast'] = cast liz.art["poster"] = formatimg(item['image']['posterImage'], 'poster') liz.art["fanart"] = formatimg(item['image']['thumbnailImage'], 'fanart') if 'logoTitleImage' in item: liz.art["banner"] = formatimg(item['logoTitleImage'], 'banner') liz.info.date(aired, "%Y-%m-%d") liz.info['plot'] = plot liz.set_callback(play_video, streamId=movieId) plugin.log('Adding: %s' % title, lvl=plugin.DEBUG) if EMAIL and PASSWORD: CONTEXT_MENU(liz, movieId, profile_id, profile_type, is_master) CONTEXT_MENU2(liz, movieId, item['title'], "MOVIE") yield liz if not liz: page = int(page) + 1 if hasMore: page = int(page)+1 yield Listitem.next_page( genreId=genreId, page=str(page), profile_id=profile_id, profile_type=profile_type ) if not liz and not hasMore: yield False plugin.notify( plugin.localize(30208), plugin.localize(30202), display_time=5000, sound=True )