def __is_already_logged_on(self, username): """ Check if the given user is logged on and sets what packages he/she has. :param str username: :return: Indicator if the user is alreadly logged in :rtype: bool """ me = UriHandler.open("https://disco-api.dplay.se/users/me", proxy=self.proxy, no_cache=True) if UriHandler.instance().status.code >= 300: return False account_data = JsonHelper(me) signed_in_user = account_data.get_value("data", "attributes", "username") if signed_in_user is not None and signed_in_user != username: # Log out UriHandler.open("https://disco-api.dplay.se/logout", data="", proxy=self.proxy, no_cache=True) return False logged_in = not account_data.get_value("data", "attributes", "anonymous") if logged_in: Logger.debug("Already logged in") packages = account_data.get_value("data", "attributes", "packages", fallback=[]) self.__has_premium = "Premium" in packages return True else: return False
def update_video_item(self, item): """ Accepts an item. It returns an updated item. Usually retrieves the MediaURL and the Thumb! It should return a completed item. """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) # rtmpt://vrt.flash.streampower.be/een//2011/07/1000_110723_getipt_neefs_wiels_Website_EEN.flv # http://www.een.be/sites/een.be/modules/custom/vrt_video/player/player_4.3.swf # now the mediaurl is derived. First we try WMV data = UriHandler.open(item.url) part = item.create_new_empty_media_part() if "mediazone.vrt.be" not in item.url: # Extract actual media data video_id = Regexer.do_regex('data-video=[\'"]([^"\']+)[\'"]', data)[0] url = "https://mediazone.vrt.be/api/v1/een/assets/%s" % (video_id, ) data = UriHandler.open(url) json = JsonHelper(data) urls = json.get_value("targetUrls") for url_info in urls: Logger.trace(url_info) if url_info["type"].lower() != "hls": continue hls_url = url_info["url"] for s, b in M3u8.get_streams_from_m3u8(hls_url): part.append_media_stream(s, b) item.complete = True return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) if not item.url.endswith(".js"): data = UriHandler.open(item.url) data_id = Regexer.do_regex(r'data-id="(\d+)"[^>]+data-playout', data) if data_id is None: Logger.warning("Cannot find stream-id for L1 stream.") return item data_url = "https://limburg.bbvms.com/p/L1_video/c/{}.json".format(data_id[0]) else: data_url = item.url data = UriHandler.open(data_url) json = JsonHelper(data, logger=Logger.instance()) Logger.trace(json) base_url = json.get_value("publicationData", "defaultMediaAssetPath") streams = json.get_value("clipData", "assets") item.MediaItemParts = [] part = item.create_new_empty_media_part() for stream in streams: url = stream.get("src", None) if "://" not in url: url = "{}{}".format(base_url, url) bitrate = stream.get("bandwidth", None) if url: part.append_media_stream(url, bitrate) if not item.thumb and json.get_value("thumbnails"): url = json.get_value("thumbnails")[0].get("src", None) if url and "http:/" not in url: url = "%s%s" % (self.baseUrl, url) item.thumb = url item.complete = True return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) # 1 - get the overal config file guid_regex = 'http://[^:]+/mgid:[^"]+:([0-9a-f-]+)"' rtmp_regex = r'type="video/([^"]+)" bitrate="(\d+)">\W+<src>([^<]+)</src>' data = UriHandler.open(item.url, proxy=self.proxy) guids = Regexer.do_regex(guid_regex, data) item.MediaItemParts = [] for guid in guids: # get the info for this part Logger.debug("Processing part with GUID: %s", guid) # reset stuff part = None # http://www.southpark.nl/feeds/video-player/mediagen?uri=mgid%3Aarc%3Aepisode%3Acomedycentral.com%3Aeb2a53f7-e370-4049-a6a9-57c195367a92&suppressRegisterBeacon=true guid = HtmlEntityHelper.url_encode("mgid:arc:episode:comedycentral.com:%s" % (guid,)) info_url = "%s/feeds/video-player/mediagen?uri=%s&suppressRegisterBeacon=true" % (self.baseUrl, guid) # 2- Get the GUIDS for the different ACTS info_data = UriHandler.open(info_url, proxy=self.proxy) rtmp_streams = Regexer.do_regex(rtmp_regex, info_data) for rtmp_stream in rtmp_streams: # if this is the first stream for the part, create an new part if part is None: part = item.create_new_empty_media_part() part.append_media_stream(self.get_verifiable_video_url(rtmp_stream[2]), rtmp_stream[1]) item.complete = True Logger.trace("Media item updated: %s", item) return item
def update_video_item(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) from resources.lib.streams.m3u8 import M3u8 data = UriHandler.open(item.url, proxy=self.proxy) video_id = Regexer.do_regex(r'{"video":{"config":{"uri":"([^"]+)', data)[0] url = "http://media.mtvnservices.com/pmt/e1/access/index.html?uri={}&configtype=edge".format( video_id) meta_data = UriHandler.open(url, proxy=self.proxy, referer=self.baseUrl) meta = JsonHelper(meta_data) stream_parts = meta.get_value("feed", "items") for stream_part in stream_parts: stream_url = stream_part["group"]["content"] stream_url = stream_url.replace("&device={device}", "") stream_url = "%s&format=json&acceptMethods=hls" % (stream_url, ) stream_data = UriHandler.open(stream_url, proxy=self.proxy) stream = JsonHelper(stream_data) # subUrls = stream.get_value("package", "video", "item", 0, "transcript", 0, "typographic") # NOSONAR part = item.create_new_empty_media_part() hls_streams = stream.get_value("package", "video", "item", 0, "rendition") for hls_stream in hls_streams: hls_url = hls_stream["src"] item.complete |= M3u8.update_part_with_m3u8_streams( part, hls_url, proxy=self.proxy) item.complete = True Logger.trace("Media url: %s", item) return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) meta_data = UriHandler.open(item.url, proxy=self.proxy, referer=self.baseUrl) meta = JsonHelper(meta_data) stream_parts = meta.get_value("feed", "items") for stream_part in stream_parts: stream_url = stream_part["group"]["content"] stream_url = stream_url.replace("{device}", "html5") stream_url = "%s&format=json" % (stream_url, ) stream_data = UriHandler.open(stream_url, proxy=self.proxy) stream = JsonHelper(stream_data) # subUrls = stream.get_value("package", "video", "item", 0, "transcript", 0, "typographic") # NOSONAR part = item.create_new_empty_media_part() # m3u8Url = stream.get_value("package", "video", "item", 0, "rendition", 0, "src") # NOSONAR # for s, b in M3u8.get_streams_from_m3u8(m3u8Url, self.proxy): # item.complete = True # part.append_media_stream(s, b) rtmp_datas = stream.get_value("package", "video", "item", 0, "rendition") for rtmp_data in rtmp_datas: rtmp_url = rtmp_data["src"] bitrate = rtmp_data["bitrate"] part.append_media_stream(rtmp_url, bitrate) item.complete = True Logger.trace("Media url: %s", item) return item
def authenticate(self, username, password): # Step 1: First initiate an authentication request auth_request = self.__get_authentication_request(username) auth_data = JsonHelper.dump(auth_request) auth_headers = { "X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth", "Accept-Encoding": "identity", "Content-Type": "application/x-amz-json-1.1" } auth_response = UriHandler.open(self.url, proxy=self.__proxy, params=auth_data, additional_headers=auth_headers, force_text=True) auth_response_json = JsonHelper(auth_response) challenge_parameters = auth_response_json.get_value( "ChallengeParameters") if self.__logger: self.__logger.trace(challenge_parameters) challenge_name = auth_response_json.get_value("ChallengeName") if not challenge_name == "PASSWORD_VERIFIER": message = auth_response_json.get_value("message") if self.__logger: self.__logger.error( "Cannot start authentication challenge: %s", message or None) return None # Step 2: Respond to the Challenge with a valid ChallengeResponse challenge_request = self.__get_challenge_response_request( challenge_parameters, password) challenge_data = JsonHelper.dump(challenge_request) challenge_headers = { "X-Amz-Target": "AWSCognitoIdentityProviderService.RespondToAuthChallenge", "Content-Type": "application/x-amz-json-1.1" } auth_response = UriHandler.open(self.url, proxy=self.__proxy, params=challenge_data, additional_headers=challenge_headers, force_text=True) auth_response_json = JsonHelper(auth_response) if "message" in auth_response_json.json: self.__logger.error("Error logging in: %s", auth_response_json.get_value("message")) return None, None id_token = auth_response_json.get_value("AuthenticationResult", "IdToken") refresh_token = auth_response_json.get_value("AuthenticationResult", "RefreshToken") return id_token, refresh_token
def update_video_item(self, item): """Updates an existing MediaItem with more data. Arguments: item : MediaItem - the MediaItem that needs to be updated Returns: The original item with more data added to it's properties. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) data = UriHandler.open(item.url, proxy=self.proxy) # get the playlist GUID playlist_guids = Regexer.do_regex( "<div[^>]+data-playlist-id='([^']+)'[^>]+></div>", data) if not playlist_guids: # let's try the alternative then (for the new channels) playlist_guids = Regexer.do_regex( 'local_playlist[", -]+([a-f0-9]{20})"', data) playlist_guid = playlist_guids[0] play_list_url = "http://api.mtvnn.com/v2/nl/NL/local_playlists/{}.json?video_format=m3u8".format( playlist_guid) data = UriHandler.open(play_list_url, proxy=self.proxy) from resources.lib.helpers.jsonhelper import JsonHelper from resources.lib.streams.m3u8 import M3u8 json_data = JsonHelper(data) m3u8_url = json_data.get_value("local_playlist_videos", 0, "url") part = item.create_new_empty_media_part() item.complete = M3u8.update_part_with_m3u8_streams(part, m3u8_url, proxy=self.proxy, channel=self, encrypted=True) return item
def log_on(self, username, password): """ Peforms the logon of a user. :param str username: The username :param str password: The password to use :returns: a AuthenticationResult with the result of the log on :rtype: AuthenticationResult """ # first we need a random context_id R<10 numbers> context_id = int(random.random() * 8999999999) + 1000000000 # then we do an initial bootstrap call, which retrieves the `gmid` and `ucid` cookies url = "https://sso.rtl.nl/accounts.webSdkBootstrap" \ "?apiKey={}" \ "&pageURL=https%3A%2F%2Fwww.rtlxl.nl%2F" \ "&format=json" \ "&callback=gigya.callback" \ "&context=R{}".format(self.api_key, context_id) init_login = UriHandler.open(url, no_cache=True) init_data = JsonHelper(init_login) if init_data.get_value("statusCode") != 200: Logger.error("Error initiating login") return AuthenticationResult(None) # actually do the login request, which requires an async call to retrieve the result login_url = "https://sso.rtl.nl/accounts.login" \ "?context={0}".format(context_id) login_data = { "loginID": username, "password": password, # "include": "profile,data", # "includeUserInfo": "true", "pageURL": "https://www.rtlxl.nl/profiel", "format": "json", # "callback": "gigya.callback", "context": "R{}".format(context_id), "targetEnv": "jssdk", "sessionExpiration": 7776000 } login_data.update(self.__common_param_dict) login_response = UriHandler.open(login_url, data=login_data, no_cache=True) # Process the result authentication_result = self.__extract_session_data(login_response) authentication_result.existing_login = False return authentication_result
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) if "index.html" in item.url: data = UriHandler.open( item.url, additional_headers={"Referer": "http://www.{}/".format(self.__country_id)} ) json_data = JsonHelper(data) guid = json_data.get_value("feed", "items", 0, "guid") url = "https://media-utils.mtvnservices.com/services/MediaGenerator/" \ "{}?arcStage=live&format=json&acceptMethods=hls&clang=nl" \ "&https=true".format(guid) else: url = item.url data = UriHandler.open(url) json_data = JsonHelper(data) url = json_data.get_value("package", "video", "item", 0, "rendition", 0, "src") if not url: error = json_data.get_value("package", "video", "item", 0, "text") Logger.error("Error resolving url: %s", error) XbmcWrapper.show_dialog(LanguageHelper.ErrorId, error) return item item.MediaItemParts = [] part = item.create_new_empty_media_part() part.append_media_stream(url, 0) item.complete = True return item
def update_music_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_music_item for %s (%s)', item.name, self.channelName) url, data = item.url.split("?") data = UriHandler.open(url, params=data, additional_headers=item.HttpHeaders) Logger.trace(data) json_data = JsonHelper(data) url = json_data.get_value("url", fallback=None) if url: item.append_single_stream(url) item.Complete = True return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) # Get the MZID data = UriHandler.open(item.url, proxy=self.proxy, additional_headers=item.HttpHeaders) json_data = Regexer.do_regex(r'<script type="application/ld\+json">(.*?)</script>', data) json_info = JsonHelper(json_data[-1]) video_id = json_info.get_value("video", "@id") publication_id = json_info.get_value("publication", -1, "@id") mzid = "{}${}".format(publication_id, video_id) return self.update_video_for_mzid(item, mzid)
def renew_token(self, refresh_token): """ Sets a new access token on the User using the refresh token. The basic expire time of the refresh token is 30 days: http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html :param str refresh_token: Token to use for refreshing the authorization token. """ refresh_request = { "AuthParameters": { "REFRESH_TOKEN": refresh_token }, "ClientId": self.client_id, "AuthFlow": "REFRESH_TOKEN" } refresh_headers = { "X-Amz-Target": "AWSCognitoIdentityProviderService.InitiateAuth", "Content-Type": "application/x-amz-json-1.1" } refresh_request_data = JsonHelper.dump(refresh_request) refresh_response = UriHandler.open(self.url, proxy=self.__proxy, params=refresh_request_data, additional_headers=refresh_headers) refresh_json = JsonHelper(refresh_response) id_token = refresh_json.get_value("AuthenticationResult", "IdToken") return id_token
def get_movie_id(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ Logger.info("Performing Pre-Processing") items = [] movie_id = Regexer.do_regex(r"movietrailers://movie/detail/(\d+)", data)[-1] Logger.debug("Found Movie ID: %s", movie_id) url = "%s/trailers/feeds/data/%s.json" % (self.baseUrl, movie_id) data = UriHandler.open(url) # set it for logging purposes self.parentItem.url = url Logger.debug("Pre-Processing finished") return data, items
def __update_video_from_brightcove(self, item, data, use_adaptive_with_encryption): """ Updates an existing MediaItem with more data based on an MPD stream. :param str data: Stream info retrieved from BrightCove. :param bool use_adaptive_with_encryption: Do we use the Adaptive InputStream add-on? :param MediaItem item: The original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ part = item.create_new_empty_media_part() # Then try the new BrightCove JSON bright_cove_regex = '<video[^>]+data-video-id="(?<videoId>[^"]+)[^>]+data-account="(?<videoAccount>[^"]+)' bright_cove_data = Regexer.do_regex( Regexer.from_expresso(bright_cove_regex), data) if not bright_cove_data: Logger.warning("Error updating using BrightCove data: %s", item) return item Logger.info("Found new BrightCove JSON data") bright_cove_url = 'https://edge.api.brightcove.com/playback/v1/accounts/' \ '%(videoAccount)s/videos/%(videoId)s' % bright_cove_data[0] headers = { "Accept": "application/json;pk=BCpkADawqM3ve1c3k3HcmzaxBvD8lXCl89K7XEHiKutxZArg2c5RhwJHJANOwPwS_4o7UsC4RhIzXG8Y69mrwKCPlRkIxNgPQVY9qG78SJ1TJop4JoDDcgdsNrg" } bright_cove_data = UriHandler.open(bright_cove_url, additional_headers=headers) bright_cove_json = JsonHelper(bright_cove_data) streams = [ d for d in bright_cove_json.get_value("sources") if d["container"] == "M2TS" ] # Old filter # streams = filter(lambda d: d["container"] == "M2TS", bright_cove_json.get_value("sources")) if not streams: Logger.warning("Error extracting streams from BrightCove data: %s", item) return item # noinspection PyTypeChecker stream_url = streams[0]["src"] # these streams work better with the the InputStreamAddon because it removes the # "range" http header if use_adaptive_with_encryption: Logger.info("Using InputStreamAddon for playback of HLS stream") strm = part.append_media_stream(stream_url, 0) M3u8.set_input_stream_addon_input(strm) item.complete = True return item for s, b in M3u8.get_streams_from_m3u8(stream_url): item.complete = True part.append_media_stream(s, b) return item
def update_live_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_live_item for %s (%s)', item.name, self.channelName) data = UriHandler.open(item.url, proxy=self.proxy, additional_headers=self.httpHeaders) stream_root = Regexer.do_regex(r'<media href="([^"]+\.isml)', data)[0] Logger.debug("Found Live stream root: %s", stream_root) part = item.create_new_empty_media_part() for s, b in F4m.get_streams_from_f4m(item.url, self.proxy): item.complete = True s = s.replace(".f4m", ".m3u8") part.append_media_stream(s, b) return item
def update_video_api_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting UpdateChannelItem for %s (%s)', item.name, self.channelName) data = UriHandler.open(item.url, proxy=self.proxy) json = JsonHelper(data, logger=Logger.instance()) videos = json.get_value("videoReferences") subtitles = json.get_value("subtitleReferences") Logger.trace(videos) return self.__update_item_from_video_references( item, videos, subtitles)
def __update_video(self, item, data): if not item.url.startswith("https://api.viervijfzes.be/content/"): regex = 'data-video-*id="([^"]+)' m3u8_url = Regexer.do_regex(regex, data)[-1] # we either have an URL now or an uuid else: m3u8_url = item.url.rsplit("/", 1)[-1] if ".m3u8" not in m3u8_url: Logger.info("Not a direct M3u8 file. Need to log in") url = "https://api.viervijfzes.be/content/%s" % (m3u8_url, ) # We need to log in if not self.loggedOn: self.log_on() # add authorization header authentication_header = { "authorization": self.__idToken, "content-type": "application/json" } data = UriHandler.open(url, additional_headers=authentication_header) json_data = JsonHelper(data) m3u8_url = json_data.get_value("video", "S") # Geo Locked? if "/geo/" in m3u8_url.lower(): # set it for the error statistics item.isGeoLocked = True part = item.create_new_empty_media_part() item.complete = M3u8.update_part_with_m3u8_streams( part, m3u8_url, channel=self, encrypted=False) return item
def active_authentication(self): """ Check if the user with the given name is currently authenticated. :returns: a AuthenticationResult with the account data. :rtype: AuthenticationResult """ login_token = AddonSettings.get_setting(self.__setting_signature, store=LOCAL) login_cookie = UriHandler.get_cookie("gmid", domain=".sso.rtl.nl") if login_token and \ login_cookie is not None and \ not login_cookie.is_expired(): # only retrieve the account information using the cookie and the token account_info_url = "https://sso.rtl.nl/accounts.getAccountInfo?{}" \ "&login_token={}".format(self.__common_params, login_token) account_info = UriHandler.open(account_info_url, no_cache=True) # See if it was successful auth_info = self.__extract_session_data(account_info) auth_info.existing_login = True return auth_info return AuthenticationResult(None)
def update_live_channel(self, item): """ Updates an existing live stream MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ data = UriHandler.open(item.url, no_cache=True) manifest = JsonHelper(data) if "nonPlayable" in manifest.json and manifest.json["nonPlayable"]: Logger.error("Cannot update Live: %s", item) return item source = manifest.get_value("sourceMedium") if source == "audio": return self.__update_live_audio(item, manifest) else: return self.__update_live_video(item, manifest)
def load_all_episodes(self, data): episodes_json = [] data, items = self.add_live_channel(data) for i in range(0, 20): url = self.apiFormat.format(i) data = UriHandler.open(url) json_data = JsonHelper(data) item_data = json_data.get_value("category", "news", fallback=[]) episodes_json += item_data if len(item_data) < json_data.get_value("pageSize"): break amsterdam_vandaag = MediaItem( "Amsterdam Vandaag", "https://ditisdesupercooleappapi.at5.nl/api/article/p123") amsterdam_vandaag.thumb = "https://media.at5.nl/cache/i/459000/images/459628.w1600.r16-9.6ef7807.q90.jpg" now = datetime.datetime.now() - datetime.timedelta(days=1) amsterdam_vandaag.set_date(now.year, now.month, now.day) items.append(amsterdam_vandaag) dummy = JsonHelper("{}") dummy.json = episodes_json return dummy, items
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) data = UriHandler.open(item.url, proxy=self.proxy) streams = Regexer.do_regex(self.mediaUrlRegex, data) item.MediaItemParts = [] part = item.create_new_empty_media_part() for stream in streams: Logger.trace(stream) part.append_media_stream(stream[0], stream[1]) item.complete = True return item
def update_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ Logger.debug('Starting update_video_item for %s (%s)', item.name, self.channelName) # https://api.viervijfzes.be/content/c58996a6-9e3d-4195-9ecf-9931194c00bf # videoId = item.url.split("/")[-1] # url = "%s/video/v3/embed/%s" % (self.baseUrl, videoId,) url = item.url data = UriHandler.open(url, proxy=self.proxy) return self.__update_video(item, data)
def update_video_html_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ data = UriHandler.open(item.url, proxy=self.proxy) video_id = Regexer.do_regex(r'data-video-id="([^"]+)"', data)[0] item.url = "https://api.svt.se/video/{}".format(video_id) return self.update_video_api_item(item)
def add_episode_paging(self, data): """ Performs pre-process actions for data processing. Accepts an data from the process_folder_list method, BEFORE the items are processed. Allows setting of parameters (like title etc) for the channel. Inside this method the <data> could be changed and additional items can be created. The return values should always be instantiated in at least ("", []). :param str data: The retrieve data that was loaded for the current item and URL. :return: A tuple of the data and a list of MediaItems that were generated. :rtype: tuple[str|JsonHelper,list[MediaItem]] """ items = [] # we need to create page items. So let's just spoof the paging. Youtube has # a 50 max results per query limit. items_per_page = 50 data = UriHandler.open(self.mainListUri) xml = xmlhelper.XmlHelper(data) nr_items = xml.get_single_node_content("openSearch:totalResults") for index in range(1, int(nr_items), items_per_page): items.append(self.create_episode_item([index, items_per_page])) # Continue working normal! return data, items
def __iterate_results(self, url_format, results_per_page=150, max_iterations=10): """ Retrieves the full dataset for a multi-set search action. :param str url_format: The url format with start and count placeholders :param int results_per_page: The maximum results per request :param int max_iterations: The maximum number of iterations :returns A Json response with all results :rtype JsonHelper Url format should be like: https://urplay.se/api/bff/v1/search?product_type=series&rows={}&start={} """ results = None for p in range(0, max_iterations): url = url_format.format(results_per_page, p * results_per_page) data = UriHandler.open(url) json_data = JsonHelper(data) result_items = json_data.get_value("results", fallback=[]) if results is None: results = json_data else: results.json["results"] += result_items if len(result_items) < results_per_page: break return results or ""
def update_video_item_json_player(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ data = UriHandler.open(item.url, proxy=self.proxy) streams = Regexer.do_regex(r'label:\s*"([^"]+)",\W*file:\s*"([^"]+)"', data) part = item.create_new_empty_media_part() bitrates = {"720p SD": 1200} for stream in streams: part.append_media_stream(stream[1], bitrates.get(stream[0], 0)) item.complete = True return item
def update_json_video_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ headers = {} if self.localIP: headers.update(self.localIP) data = UriHandler.open(item.url, proxy=self.proxy, additional_headers=headers) video_data = JsonHelper(data) stream_data = video_data.get_value("mediaAssetsOnDemand") if not stream_data: return item use_adaptive = AddonSettings.use_adaptive_stream_add_on() stream_data = stream_data[0] part = item.create_new_empty_media_part() if "hlsUrl" in stream_data: hls_url = stream_data["hlsUrl"] if use_adaptive: stream = part.append_media_stream(hls_url, 0) M3u8.set_input_stream_addon_input(stream, self.proxy, headers=headers) item.complete = True else: for s, b in M3u8.get_streams_from_m3u8(hls_url, self.proxy, headers=headers): item.complete = True part.append_media_stream(s, b) if "timedTextSubtitlesUrl" in stream_data and stream_data[ "timedTextSubtitlesUrl"]: sub_url = stream_data["timedTextSubtitlesUrl"].replace( ".ttml", ".vtt") sub_url = HtmlEntityHelper.url_decode(sub_url) part.Subtitle = SubtitleHelper.download_subtitle(sub_url, format="webvtt") return item
def update_video_item(self, item): data = UriHandler.open(item.url, proxy=self.proxy, additional_headers=item.HttpHeaders) media_regex = 'data-media="([^"]+)"' media_info = Regexer.do_regex(media_regex, data)[0] media_info = HtmlEntityHelper.convert_html_entities(media_info) media_info = JsonHelper(media_info) Logger.trace(media_info) # sources part = item.create_new_empty_media_part() # high, web, mobile, url media_sources = media_info.json.get("sources", {}) for quality in media_sources: url = media_sources[quality] if quality == "high": bitrate = 2000 elif quality == "web": bitrate = 800 elif quality == "mobile": bitrate = 400 else: bitrate = 0 part.append_media_stream(url, bitrate) # geoLocRestriction item.isGeoLocked = not media_info.get_value( "geoLocRestriction", fallback="world") == "world" item.complete = True return item
def update_live_item(self, item): """ Updates an existing MediaItem with more data. Used to update none complete MediaItems (self.complete = False). This could include opening the item's URL to fetch more data and then process that data or retrieve it's real media-URL. The method should at least: * cache the thumbnail to disk (use self.noImage if no thumb is available). * set at least one MediaItemPart with a single MediaStream. * set self.complete = True. if the returned item does not have a MediaItemPart then the self.complete flag will automatically be set back to False. :param MediaItem item: the original MediaItem that needs updating. :return: The original item with more data added to it's properties. :rtype: MediaItem """ if "icecast" in item.url: item.type = "audio" data = UriHandler.open(item.url) stream_info = JsonHelper(data) url = stream_info.get_value("data") item.url = url return self.update_video_item(item)