def searchlist(self): try: from urllib import quote_plus as quote, urlencode # noqa: F401 except ImportError: from urllib.parse import quote_plus as quote, urlencode # noqa: F401 self.reset_media_type_counters() self.addCat(py2_encode(self.language(30734)), "INTERNAL_SEARCH", self.get_media_resource('search.png'), HbogoConstants.ACTION_SEARCH) self.addCat(py2_encode(self.language(30735)), "DEL_SEARCH_HISTORY", self.get_media_resource('remove.png'), HbogoConstants.ACTION_SEARCH_CLEAR_HISTORY) history_items = self.get_search_history() for history_itm in history_items: tmp_url = '%s?%s' % (self.base_url, urlencode({ 'url': "INTERNAL_SEARCH", 'mode': HbogoConstants.ACTION_SEARCH, 'name': py2_encode(self.language(30734)) + ': ' + py2_encode(history_itm[0]), 'query': py2_encode(history_itm[0]), })) liz = xbmcgui.ListItem(py2_encode(history_itm[0])) liz.setArt({'fanart': self.get_resource("fanart.jpg"), 'thumb': self.get_media_resource('search.png'), 'icon': self.get_media_resource('search.png')}) liz.setInfo(type="Video", infoLabels={"Title": py2_encode(self.language(30734)) + ': ' + py2_encode(history_itm[0])}) liz.setProperty('isPlayable', "false") runplugin = 'RunPlugin(%s?%s)' rem_search_query = urlencode({ 'url': 'REM_SEARCH_QUERY', 'mode': HbogoConstants.ACTION_SEARCH_REMOVE_HISTOY_ITEM, 'itm': py2_encode(history_itm[0]), }) rem_search = (py2_encode(self.language(30736)), runplugin % (self.base_url, rem_search_query)) liz.addContextMenuItems(items=[rem_search]) xbmcplugin.addDirectoryItem(handle=self.handle, url=tmp_url, listitem=liz, isFolder=True) KodiUtil.endDir(self.handle, None, True)
def search(self, query=None): if not self.chk_login(): self.login() search_text = "" if query is None: keyb = xbmc.Keyboard("", self.LB_SEARCH_DESC) keyb.doModal() if keyb.isConfirmed(): search_text = py2_encode(keyb.getText()) else: self.force_original_names = False search_text = py2_encode(query) if search_text == "": xbmcgui.Dialog().notification( self.LB_SEARCH_NORES, self.LB_ERROR, self.get_media_resource('search.png')) else: if query is None: self.add_to_search_history(search_text) self.log("Performing search: " + self.API_URL_SEARCH + quote(search_text)) response = self.get_from_hbogo( self.API_URL_SEARCH + quote(search_text) + "&max=30&offset=0", 'xml') if response is False: return count = 0 for item in response.findall('.//item'): count += 1 item_link = item.find('link').text if item_link: if self.lograwdata: self.log(ET.tostring(item, encoding='utf8')) item_type = py2_encode( item.find('clearleap:itemType', namespaces=self.NAMESPACES).text) if item_type != 'media': self.addDir(item) elif item_type == 'media': self.addLink(item, HbogoConstants.ACTION_PLAY) else: self.log('Unknown item type: ' + item_type) if count == 0: # No result xbmcgui.Dialog().notification( self.LB_SEARCH_NORES, self.LB_ERROR, self.get_media_resource('search.png')) KodiUtil.endDir(self.handle, self.decide_media_type())
def list(self, url, simple=False): if not self.chk_login(): self.login() self.log("List: " + str(url)) self.reset_media_type_counters() self.list_pages(url, 200, 0) if simple is False: KodiUtil.endDir(self.handle, self.decide_media_type())
def del_login(self): try: folder = KodiUtil.translatePath(self.addon.getAddonInfo('profile')) self.log("Removing stored session: " + folder + self.addon_id + "_session" + ".ecdata") os.remove(folder + self.addon_id + "_session" + ".ecdata") except Exception: self.log("Delete login error: " + traceback.format_exc())
def save_obj(self, obj, name): folder = KodiUtil.translatePath(self.addon.getAddonInfo('profile')) self.log("Saving: " + folder + name + '.ecdata') with open(folder + name + '.ecdata', 'wb') as f: try: f.write(self.encrypt_credential_v1(json.dumps(obj))) except TypeError: f.write( bytes(self.encrypt_credential_v1(json.dumps(obj)), 'utf8'))
def load_obj(self, name): folder = KodiUtil.translatePath(self.addon.getAddonInfo('profile')) self.log("Trying to load: " + folder + name + '.ecdata') try: with open(folder + name + '.ecdata', 'rb') as f: return json.loads(self.decrypt_credential_v1(f.read())) except Exception: self.log("OBJECT RELOAD ERROR") self.log("Stack trace: " + traceback.format_exc()) return None
def clean_sub_cache(self, silent=True): try: import shutil subs_folder = KodiUtil.translatePath( self.addon.getAddonInfo('profile')) subs_folder = subs_folder + 'subs' shutil.rmtree(subs_folder, ignore_errors=True) if not silent: icon = self.get_resource("icon.png") xbmcgui.Dialog().notification(self.language(30814), self.LB_INFO, icon) except Exception: self.log("Clean subtitle cache error: " + traceback.format_exc())
def play(self, content_id, retry=0): self.log("Initializing playback... " + str(content_id)) self.login() media_item = self.get_from_hbogo( self.API_URL_BROWSE + content_id + self.LANGUAGE_CODE, 'xml') if media_item is False: return media_info = self.construct_media_info(media_item.find('.//item')) if self.lograwdata: self.log("Play Media: ") self.log(ET.tostring(media_item, encoding='utf8')) mpd_pre_url = media_item.find( './/media:content[@profile="HBO-DASH-WIDEVINE"]', namespaces=self.NAMESPACES).get('url') + '&responseType=xml' mpd = self.get_from_hbogo(mpd_pre_url, 'xml', False) if mpd is False: return if self.lograwdata: self.log("Manifest: ") self.log(ET.tostring(mpd, encoding='utf8')) mpd_url = mpd.find('.//url').text self.log("Manifest url: " + str(mpd_url)) media_guid = media_item.find('.//guid').text license_headers = 'X-Clearleap-AssetID=' + media_guid + '&X-Clearleap-DeviceId=' + self.API_DEVICE_ID + \ '&X-Clearleap-DeviceToken=' + self.API_DEVICE_TOKEN + '&Content-Type=' license_url = 'https://' + self.API_HOST + '/cloffice/drm/wv/' + media_guid + '|' + license_headers + '|R{SSM}|' li = xbmcgui.ListItem(path=mpd_url) li.setArt(media_info["art"]) li.setInfo(type="Video", infoLabels=media_info["info"]) protocol = 'mpd' drm = 'com.widevine.alpha' li.setContentLookup(False) li.setMimeType('application/dash+xml') from inputstreamhelper import Helper # type: ignore is_helper = Helper(protocol, drm=drm) if is_helper.check_inputstream(): if sys.version_info < ( 3, 0 ): # if python version < 3 is safe to assume we are running on Kodi 18 li.setProperty( 'inputstreamaddon', 'inputstream.adaptive') # compatible with Kodi 18 API else: li.setProperty('inputstream', 'inputstream.adaptive' ) # compatible with recent builds Kodi 19 API li.setProperty('inputstream.adaptive.license_type', drm) li.setProperty('inputstream.adaptive.manifest_type', protocol) li.setProperty('inputstream.adaptive.license_key', license_url) # GET SUBTITLES if self.addon.getSetting('forcesubs') == 'true': folder = KodiUtil.translatePath( self.addon.getAddonInfo('profile')) folder = folder + 'subs' self.clean_sub_cache(folder) folder = folder + os.sep + media_guid + os.sep self.log( "Cache subtitles enabled, downloading and converting subtitles in: " + folder) if not os.path.exists(os.path.dirname(folder)): try: os.makedirs(os.path.dirname(folder)) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: raise try: subs = media_item.findall('.//media:subTitle', namespaces=self.NAMESPACES) subs_paths = [] for sub in subs: self.log("Processing subtitle language code: " + sub.get('lang') + " URL: " + sub.get('href')) r = requests.get(sub.get('href')) with open(folder + sub.get('lang') + ".xml", 'wb') as f: f.write(r.content) ttml = Ttml2Srt( py2_encode(folder + sub.get('lang') + ".xml"), 25) srt_file = ttml.write2file( ttml.mfn2srtfn( py2_encode(folder + sub.get('lang')), ttml.lang, False)) self.log("Subtitle converted to srt format") subs_paths.append(srt_file) self.log("Subtitle added: " + srt_file) li.setSubtitles(subs_paths) self.log("Local subtitles set") except Exception: self.log("Unexpected error in subtitles processing: " + traceback.format_exc()) self.log("Play url: " + str(li)) xbmcplugin.setResolvedUrl(self.handle, True, listitem=li) else: self.log("DRM problem playback not possible") xbmcplugin.setResolvedUrl(self.handle, False, listitem=li)
def categories(self): if not self.chk_login(): self.login() self.setDispCat(self.operator_name) if self.addon.getSetting('enforce_kids') != 'true': self.addCat(self.LB_SEARCH, "INTERNAL_SEARCH", self.get_media_resource('search.png'), HbogoConstants.ACTION_SEARCH_LIST) browse_xml = self.get_from_hbogo(self.API_URL_BROWSE + self.LANGUAGE_CODE, response_format='xml') if browse_xml is False: return home = None series = None movies = None kids = None watchlist = None for item in browse_xml.findall('.//item'): if item.find('category').text == 'Home': home = item elif item.find('category').text == 'Series': series = item elif item.find('category').text == 'Movies': movies = item elif item.find('category').text == 'Watchlist': watchlist = item elif item.find('category').text == 'Kids' or item.find( 'category').text == 'Toonix': kids = item else: pass if self.addon.getSetting('enforce_kids') == 'true': if kids is not None: self.list(kids.find('link').text, True) else: self.log("No Kids Category found") KodiUtil.endDir(self.handle, None, True) return if self.addon.getSetting('show_mylist') == 'true': if watchlist is not None: self.exclude_url_from_cache(watchlist.find('link').text) self.addCat(self.LB_MYPLAYLIST, watchlist.find('link').text, self.get_media_resource('FavoritesFolder.png'), HbogoConstants.ACTION_LIST) else: self.log("No Watchlist Category found") if series is not None: self.addCat(py2_encode(series.find('title').text), series.find('link').text, self.get_media_resource('tv.png'), HbogoConstants.ACTION_LIST) else: self.log("No Series Category found") if movies is not None: self.addCat(py2_encode(movies.find('title').text), movies.find('link').text, self.get_media_resource('movie.png'), HbogoConstants.ACTION_LIST) else: self.log("No Movies Category found") if self.addon.getSetting('show_kids') == 'true': if kids is not None: self.addCat(py2_encode(kids.find('title').text), kids.find('link').text, self.get_media_resource('kids.png'), HbogoConstants.ACTION_LIST) else: self.log("No Kids Category found") if home is not None: if self.addon.getSetting('group_home') == 'true': self.addCat(py2_encode(self.language(30733)), home.find('link').text, self.get_media_resource('DefaultFolder.png'), HbogoConstants.ACTION_LIST) else: self.list(home.find('link').text, True) else: self.log("No Home Category found") KodiUtil.endDir(self.handle, None, True)
def __init__(self, handle, base_url): self.addon = xbmcaddon.Addon() self.addon_id = self.addon.getAddonInfo('id') self.language = self.addon.getLocalizedString self.base_url = base_url self.handle = handle self.DEBUG_ID_STRING = "[" + str(self.addon_id) + "] " self.SESSION_VALIDITY = 4 # stored session valid for 4 hours self.max_comm_retry = 1 # if unauthorized del session and re-login and try again max times self.max_play_retry = 1 # max play retry on soft error self.db_version = 1 self.base_addon_cat = "" self.cur_loc = "" xbmcplugin.setPluginFanart(self.handle, image=self.get_resource("fanart.jpg")) # LABELS self.LB_SEARCH_DESC = py2_encode(self.language(30700)) self.LB_SEARCH_NORES = py2_encode(self.language(30701)) self.LB_ERROR = py2_encode(self.language(30702)) self.LB_INFO = py2_encode(self.language(30713)) self.LB_SUCESS = py2_encode(self.language(30727)) self.LB_EPISODE_UNTILL = py2_encode(self.language(30703)) self.LB_FILM_UNTILL = py2_encode(self.language(30704)) self.LB_EPISODE = py2_encode(self.language(30705)) self.LB_SEASON = py2_encode(self.language(30706)) self.LB_MYPLAYLIST = py2_encode(self.language(30707)) self.LB_NOLOGIN = py2_encode(self.language(30708)) self.LB_LOGIN_ERROR = py2_encode(self.language(30709)) self.LB_NO_OPERATOR = py2_encode(self.language(30710)) self.LB_SEARCH = py2_encode(self.language(30711)) self.n_movies = 0 self.n_tvshows = 0 self.n_seasons = 0 self.n_episodes = 0 self.force_original_names = self.addon.getSetting('origtitles') if self.force_original_names == "true": self.force_original_names = True else: self.force_original_names = False self.force_scraper_names = self.addon.getSetting('forcescrap') if self.force_scraper_names == "true": self.force_scraper_names = True else: self.force_scraper_names = False self.sensitive_debug = self.addon.getSetting('sensitivedebug') if self.sensitive_debug == "true": self.sensitive_debug = True else: self.sensitive_debug = False self.lograwdata = self.addon.getSetting('lograwdata') if self.lograwdata == "true": self.lograwdata = True else: self.lograwdata = False self.use_cache = self.addon.getSetting('use_req_cache') if self.use_cache == "true": self.use_cache = True else: self.use_cache = False self.usedevkey = self.addon.getSetting('usedevkey') if self.usedevkey == "true": self.usedevkey = True else: self.usedevkey = False if self.sensitive_debug: ret = xbmcgui.Dialog().yesno(self.LB_INFO, self.language(30712), self.language(30714), self.language(30715)) if not ret: sys.exit() self.loggedin_headers = None # DEFINE IN SPECIFIC HANDLER self.API_PLATFORM = 'COMP' self.log("Starting database connection...") self.db = sqlite3.connect( KodiUtil.translatePath(self.addon.getAddonInfo('profile')) + 'hgo.db') cur = self.db.cursor() try: cur.execute("SELECT val_int FROM settings WHERE set_id='db_ver'") r = cur.fetchone() if r[0] != self.db_version: self.log("Database version mismatch updating database.") self.ceate_db(r[0]) except Exception: self.log("Database error: " + traceback.format_exc()) self.ceate_db()
def get_media_resource(resourcefile): return py2_decode( KodiUtil.translatePath(xbmcaddon.Addon().getAddonInfo('path') + '/resources/media/' + resourcefile))