def request_query(query, variables, force_refresh=False, retry=3): tenant = 'sexy-hot' url = 'https://products-jarvis.globo.com/graphql?query={query}&variables={variables}'.format( query=query, variables=urllib.quote_plus(variables)) headers = { 'x-tenant-id': tenant, 'x-platform-id': 'web', 'x-device-id': 'desktop', 'x-client-version': '1.4.1', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36', 'authorization': auth_helper.get_globosat_token() } control.log('{} - GET {}'.format(tenant, url)) response = cache.get(requests.get, 1, url, headers=headers, force_refresh=force_refresh, table='sexyhot') if response.status_code >= 500 and retry > 0: return request_query(query, variables, True, retry - 1) response.raise_for_status() json_response = response.json() control.log(json_response) return json_response
def del_watch_later(video_id): token = auth_helper.get_globosat_token() url = GLOBOSAT_DEL_WATCH_LATER % (token, video_id) headers = { "Accept-Encoding": "gzip", "Content-Type": "application/x-www-form-urlencoded", "version": "2", "Authorization": GLOBOSAT_API_AUTHORIZATION } requests.delete(url=url, headers=headers)
def get_watch_history(page=1): page_size = 50 headers = { 'Accept-Encoding': 'gzip', 'Authorization': GLOBOSAT_API_AUTHORIZATION, 'Version': 2 } token = auth_helper.get_globosat_token() watch_later_list = client.request(GLOBOSAT_WATCH_HISTORY % (token, page, page_size), headers=headers) results = watch_later_list['data'] while watch_later_list['next'] is not None: watch_later_list = client.request(GLOBOSAT_WATCH_HISTORY % (token, watch_later_list['next'], page_size), headers=headers) results += watch_later_list['data'] videos = [] results = sorted(results, key=lambda x: x['watched_date'], reverse=True) for item in results: channel_title = item['channel']['title'] or '' program_title = item['program']['title'] if 'program' in item and item['program'] else '' title = item['title'] or 'No Title' label = channel_title + (' - ' + program_title) + ' - ' + title video = { 'id': item['id_globo_videos'], 'label': label, 'title': item['title'], 'tvshowtitle': item['program']['title'] if 'program' in item and item['program'] else item['title'], 'studio': channel_title, 'plot': item['description'], 'tagline': None, 'duration': float(item['duration_in_milliseconds']) / 1000.0, 'logo': item['program']['logo_image'] if 'program' in item and item['program'] else item['channel']['color_logo'], 'clearlogo': item['program']['logo_image'] if 'program' in item and item['program'] else item['channel']['color_logo'], 'poster': item['program']['poster_image'] if 'program' in item and item['program'] else item['card_image'], 'thumb': item['thumb_image'], 'fanart': item['program']['background_image_tv_cropped'] if 'program' in item and item['program'] else item['background_image'], 'mediatype': 'episode', 'brplayprovider': 'globosat', 'milliseconds_watched': int(item['watched_seconds']) * 1000 } videos.append(video) return videos
def add_watch_later(video_id): post_data = {'id': video_id} token = auth_helper.get_globosat_token() url = GLOBOSAT_BASE_WATCH_LATER % token headers = { "Accept-Encoding": "gzip", "Content-Type": "application/x-www-form-urlencoded", "version": "2", "Authorization": GLOBOSAT_API_AUTHORIZATION } post_data = urllib.urlencode(post_data) client.request(url, headers=headers, post=post_data)
def get_favorites(page=1): headers = { 'Accept-Encoding': 'gzip', 'Authorization': GLOBOSAT_API_AUTHORIZATION, 'Version': 2 } token = auth_helper.get_globosat_token() favorites_list = client.request(GLOBOSAT_FAVORITES % (token, page, 50), headers=headers) results = favorites_list['data'] while favorites_list['next'] is not None: favorites_list = client.request(favorites_list['next'], headers=headers) results += favorites_list['data'] videos = [] for item in results: video = { 'id': item['id_globo_videos'], 'label': item['channel']['title'] + (' - ' + item['program']['title'] if 'program' in item and item['program'] else '') + ' - ' + item['title'], 'title': item['title'], 'tvshowtitle': item['program']['title'] if 'program' in item and item['program'] else item['title'], 'studio': item['channel']['title'], 'plot': item['description'], 'tagline': item['subtitle'], 'duration': float(item['duration_in_milliseconds']) / 1000.0, 'logo': item['program']['logo_image'] if 'program' in item and item['program'] else item['channel'][ 'color_logo'], 'clearlogo': item['program']['logo_image'] if 'program' in item and item['program'] else item['channel']['color_logo'], 'poster': item['program']['poster_image'] if 'program' in item and item['program'] else item[ 'card_image'], 'thumb': item['thumb_image'], 'fanart': item['program']['background_image_tv_cropped'] if 'program' in item and item['program'] else item[ 'background_image_tv_cropped'], 'mediatype': 'episode', 'brplayprovider': 'globosat' } videos.append(video) return videos
def get_authorized_channels(): token = auth_helper.get_globosat_token() if not token: return [] client_id = "85014160-e953-4ddb-bbce-c8271e4fde74" channels_url = "https://gsatmulti.globo.com/oauth/sso/login/?chave=%s&token=%s" % ( client_id, token) channels = [] pkgs_response = client.request(channels_url, headers={"Accept-Encoding": "gzip"}) # control.log("-- PACKAGES: %s" % repr(pkgs_response)) pkgs = pkgs_response['pacotes'] channel_ids = [] for pkg in pkgs: for channel in pkg['canais']: if channel['id_globo_videos'] not in channel_ids: channel_ids.append(channel['id_globo_videos']) channels.append({ "id": channel['id_globo_videos'], # "channel_id": channel['id_globo_videos'], "id_cms": channel['id_cms'], "logo": channel['logo_fundo_claro'], "name": channel['nome'], "slug": channel['slug'], "adult": channel['slug'] == 'sexyhot' or channel['slug'] == 'sexy-hot', "vod": "vod" in channel['acls'], "live": "live" in channel['acls'] }) return channels
def get_authorized_channels(retry=1): token = auth_helper.get_globosat_token() if not token: return [] channels_url = "https://gsatmulti.globo.com/apis/user/%s/" % token channels = [] pkgs_response = client.request(channels_url, headers={"Accept-Encoding": "gzip"}) if not pkgs_response or 'provider_accounts' not in pkgs_response: if retry > 0: retry = retry - 1 control.clear_globosat_credentials() return get_authorized_channels(retry) else: return channels # control.log("-- PACKAGES: %s" % repr(pkgs_response)) pkgs = pkgs_response['provider_accounts'] channel_ids = [] for pkg in pkgs: for channel in pkg['channels']: if channel['id_globo_videos'] not in channel_ids: channel_ids.append(channel['id_globo_videos']) channels.append({ "id": channel['id_globo_videos'], "service_id": channel['service_id'], "name": channel['name'], "adult": channel['id_globo_videos'] in [2065,2006], 'slug': '', 'logo': '', 'color': '', }) broadcasts_url = 'https://products-jarvis.globo.com/graphql?query=query%20getChannelsList%28%24page%3A%20Int%2C%20%24perPage%3A%20Int%29%20%7B%0A%20%20broadcastChannels%28page%3A%20%24page%2C%20perPage%3A%20%24perPage%29%20%7B%0A%20%20%20%20page%0A%20%20%20%20perPage%0A%20%20%20%20hasNextPage%0A%20%20%20%20nextPage%0A%20%20%20%20resources%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20slug%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20logo%28format%3A%20PNG%29%0A%20%20%20%20%20%20color%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A&operationName=getChannelsList&variables=%7B%22page%22%3A1%2C%22perPage%22%3A200%7D' query_response = client.request(broadcasts_url, headers={"Accept-Encoding": "gzip", "x-tenant-id": "globosat-play"}) resources = [] resources.extend(query_response['data']['broadcastChannels']['resources']) query_response = client.request(broadcasts_url, headers={"Accept-Encoding": "gzip", "x-tenant-id": "sexy-hot"}) resources.extend(query_response['data']['broadcastChannels']['resources']) for broadcast in resources: channel = next((channel for channel in channels if int(broadcast['id']) == int(channel['id']) and int(channel['id']) > 0 or (CHANNEL_MAP.get(int(channel['id']), -1) == int(broadcast['id']))), None) if channel: channel.update({ 'slug': broadcast['slug'], 'logo': broadcast['logo'], 'color': broadcast['color'], "name": broadcast['name'] }) # result = list(filter(lambda x: 'slug' in x, channels)) return channels
def playlive(self, id, meta): meta = meta or {} control.log("Globosat Play - play_stream: id=%s | meta=%s" % (id, meta)) if id is None: return self.isLive = meta.get('livefeed', False) cdn = control.setting('globosat_cdn') if cdn: cdn = cdn.lower() if cdn.lower() != 'auto' else None if meta.get('geofencing') and meta.get('lat') and meta.get('long'): info = resourceshelper.get_geofence_video_info( id, meta.get('lat'), meta.get('long'), auth_helper.get_credentials(), cdn) elif not meta.get('router', True) or cdn: info = resourceshelper.get_video_info(id, cdn=cdn) else: info = resourceshelper.get_video_router(id, self.isLive, cdn) if not info: info = resourceshelper.get_video_info(id, cdn=cdn) control.log("INFO: %s" % repr(info)) if not info or info is None or 'channel' not in info: return try: hash_token = info.get('hash_token') user = info.get('user') if not hash_token: control.log('Signing resource: %s' % info['resource_id']) hash_token, user, credentials = self.sign_resource( info['provider_id'], info['resource_id'], id, info['player'], info['version'], cdn) except Exception as ex: control.log(traceback.format_exc(), control.LOGERROR) control.log("PLAYER ERROR: %s" % repr(ex)) return encrypted = 'encrypted' in info and info['encrypted'] if encrypted and not control.is_inputstream_available(): control.okDialog(control.lang(31200), control.lang(34103).encode('utf-8')) return query_string = re.sub(r'{{(\w*)}}', r'%(\1)s', info['query_string_template']) query_string = query_string % { 'hash': hash_token, 'key': 'app', 'openClosed': 'F' if info['subscriber_only'] and user else 'A', 'user': user if info['subscriber_only'] and user else '', 'token': hash_token } url = '?'.join([info['url'], query_string]) control.log("live media url: %s" % url) self.offset = float(meta['milliseconds_watched'] ) / 1000.0 if 'milliseconds_watched' in meta else 0 parsed_url = urlparse(url) if parsed_url.path.endswith(".m3u8"): self.url, mime_type, stop_event, cookies = hlshelper.pick_bandwidth( url) elif parsed_url.path.endswith(".mpd") and not self.isLive: proxy_handler = MediaProxy() self.url = proxy_handler.resolve(url) stop_event = proxy_handler.stop_event mime_type = None cookies = None else: self.url = url mime_type, stop_event, cookies = 'video/mp4', None, None if self.url is None: if stop_event: control.log("Setting stop event for proxy player") stop_event.set() control.infoDialog(control.lang(34100).encode('utf-8'), icon='ERROR') return control.log("Resolved URL: %s" % repr(self.url)) control.log("Parsed URL: %s" % repr(parsed_url)) if control.supports_offscreen: item = control.item(path=self.url, offscreen=True) else: item = control.item(path=self.url) item.setArt(meta.get('art', {})) item.setProperty('IsPlayable', 'true') item.setInfo(type='Video', infoLabels=control.filter_info_labels(meta)) item.setContentLookup(False) if parsed_url.path.endswith(".mpd"): mime_type = 'application/dash+xml' item.setProperty('inputstream.adaptive.manifest_type', 'mpd') if self.isLive: item.setProperty( 'inputstream.adaptive.manifest_update_parameter', 'full') elif parsed_url.path.endswith(".ism/manifest"): mime_type = 'application/vnd.ms-sstr+xml' item.setProperty('inputstream.adaptive.manifest_type', 'ism') else: item.setProperty('inputstream.adaptive.manifest_type', 'hls') if encrypted: control.log("DRM: %s" % info['drm_scheme']) licence_url = info['protection_url'] item.setProperty('inputstream.adaptive.license_type', info['drm_scheme']) if info['drm_scheme'] == 'com.widevine.alpha' or info[ 'drm_scheme'] == 'com.microsoft.playready': item.setProperty('inputstream.adaptive.license_key', licence_url + "||R{SSM}|") if mime_type: item.setMimeType(mime_type) control.log("MIME TYPE: %s" % repr(mime_type)) if not cookies and control.is_inputstream_available(): item.setProperty('inputstreamaddon', 'inputstream.adaptive') # reqCookies = client.request(url=self.url,output='cookiejar',headRequest=True) # cookie_string = "; ".join([str(x) + "=" + str(y) for x, y in reqCookies.items()]) # item.setProperty('inputstream.adaptive.stream_headers', 'cookie=%s' % cookie_string) # control.log("COOKIE STRING: %s" % cookie_string) if 'subtitles' in info and info['subtitles'] and len( info['subtitles']) > 0: control.log("FOUND SUBTITLES: %s" % repr([sub['url'] for sub in info['subtitles']])) item.setSubtitles([sub['url'] for sub in info['subtitles']]) control.resolve(int(sys.argv[1]), True, item) self.stopPlayingEvent = threading.Event() self.stopPlayingEvent.clear() self.token = auth_helper.get_globosat_token() self.video_id = info['id'] if 'id' in info else None first_run = True last_time = 0.0 while not self.stopPlayingEvent.isSet(): if control.monitor.abortRequested(): control.log("Abort requested") break if self.isPlaying(): if first_run: self.showSubtitles(False) first_run = False if not self.isLive: current_time = self.getTime() if current_time - last_time > 5 or (last_time == 0 and current_time > 1): last_time = current_time self.save_video_progress(self.token, self.video_id, current_time) control.sleep(1000) if stop_event: control.log("Setting stop event for proxy player") stop_event.set() control.log("Done playing. Quitting...")
def playlive(self, id, meta): if id is None: return info = resourceshelper.get_video_info(id) control.log("INFO: %s" % repr(info)) if not info or info is None or 'channel' not in info: return try: hash, user, credentials = self.sign_resource( info['provider_id'], info['resource_id'], id, info['player'], info['version']) except Exception as ex: control.log("ERROR: %s" % repr(ex)) return encrypted = 'encrypted' in info and info['encrypted'] if encrypted and not control.is_inputstream_available(): control.infoDialog(message=control.lang(34103).encode('utf-8'), icon='Wr') return title = info['channel'] query_string = re.sub(r'{{(\w*)}}', r'%(\1)s', info['query_string_template']) query_string = query_string % { 'hash': hash, 'key': 'app', 'openClosed': 'F' if info['subscriber_only'] else 'A', 'user': user if info['subscriber_only'] else '' } url = '?'.join([info['url'], query_string]) control.log("live media url: %s" % url) try: meta = json.loads(meta) except: meta = { "playcount": 0, "overlay": 6, "title": title, "thumb": info["thumbUri"], "mediatype": "video", "aired": info["exhibited_at"] } meta.update({ "genre": info["category"], "plot": info["title"], "plotoutline": info["title"] }) poster = meta['poster'] if 'poster' in meta else control.addonPoster() thumb = meta['thumb'] if 'thumb' in meta else info["thumbUri"] self.offset = float(meta['milliseconds_watched'] ) / 1000.0 if 'milliseconds_watched' in meta else 0 self.isLive = 'livefeed' in meta and meta['livefeed'] == 'true' parsed_url = urlparse(url) if parsed_url.path.endswith(".m3u8"): self.url, mime_type, stopEvent, cookies = hlshelper.pick_bandwidth( url) else: self.url = url mime_type, stopEvent, cookies = 'video/mp4', None, None if self.url is None: if stopEvent: control.log("Setting stop event for proxy player") stopEvent.set() control.infoDialog(control.lang(34100).encode('utf-8'), icon='ERROR') return control.log("Resolved URL: %s" % repr(self.url)) control.log("Parsed URL: %s" % repr(parsed_url)) item = control.item(path=self.url) item.setArt({ 'icon': thumb, 'thumb': thumb, 'poster': poster, 'tvshow.poster': poster, 'season.poster': poster }) item.setProperty('IsPlayable', 'true') item.setInfo(type='Video', infoLabels=meta) item.setContentLookup(False) if parsed_url.path.endswith(".mpd"): mime_type = 'application/dash+xml' item.setProperty('inputstream.adaptive.manifest_type', 'mpd') item.setProperty('inputstream.adaptive.manifest_update_parameter', 'full') elif parsed_url.path.endswith(".ism/manifest"): mime_type = 'application/vnd.ms-sstr+xml' item.setProperty('inputstream.adaptive.manifest_type', 'ism') else: item.setProperty('inputstream.adaptive.manifest_type', 'hls') if encrypted: control.log("DRM: %s" % info['drm_scheme']) licence_url = info['protection_url'] item.setProperty('inputstream.adaptive.license_type', info['drm_scheme']) if info['drm_scheme'] == 'com.widevine.alpha' or info[ 'drm_scheme'] == 'com.microsoft.playready': item.setProperty('inputstream.adaptive.license_key', licence_url + "||R{SSM}|") if mime_type: item.setMimeType(mime_type) control.log("MIME TYPE: %s" % repr(mime_type)) if not cookies and not control.disable_inputstream_adaptive: item.setProperty('inputstreamaddon', 'inputstream.adaptive') if 'subtitles' in info and info['subtitles'] and len( info['subtitles']) > 0: control.log("FOUND SUBTITLES: %s" % repr([sub['url'] for sub in info['subtitles']])) item.setSubtitles([sub['url'] for sub in info['subtitles']]) control.resolve(int(sys.argv[1]), True, item) self.stopPlayingEvent = threading.Event() self.stopPlayingEvent.clear() self.token = auth_helper.get_globosat_token() self.video_id = info['id'] if 'id' in info else None first_run = True last_time = 0.0 while not self.stopPlayingEvent.isSet(): if control.monitor.abortRequested(): control.log("Abort requested") break if self.isPlaying(): if first_run: self.showSubtitles(False) first_run = False if not self.isLive: current_time = self.getTime() if current_time - last_time > 5 or (last_time == 0 and current_time > 1): last_time = current_time self.save_video_progress(self.token, self.video_id, current_time) control.sleep(1000) if stopEvent: control.log("Setting stop event for proxy player") stopEvent.set() control.log("Done playing. Quitting...")