def onPlayBackStopped(self): # Will be called when user stops xbmc playing a file control.log("setting event in onPlayBackStopped") if self.stopPlayingEvent: self.stopPlayingEvent.set()
def onPlayBackStarted(self): # Will be called when xbmc starts playing a file control.log("Playback has started!")
def play_vod(self, id, meta): self.retry = 0 control.log("PLAY SEXYHOT - ID: %s" % id) if id is None: return id = self.__get_globo_id(id) control.log('globo_midia_id: %s' % str(id)) if id is None: return info = self.__get_video_info(id) if info is None: return title = info['title'] signed_hashes = get_signed_hashes(info['hash']) query_string = re.sub(r'{{(\w*)}}', r'%(\1)s', info['query_string_template']) query_string = query_string % { 'hash': signed_hashes[0], 'key': 'html5' } 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": None, "mediatype": "video" } meta.update({ "genre": info["category"], }) poster = meta['poster'] if 'poster' in meta else control.addonPoster() thumb = meta['thumb'] if 'thumb' in meta else info["thumbUri"] url, mime_type, stopEvent = hlshelper.pick_bandwidth(url) control.log("Resolved URL: %s" % repr(url)) item = control.item(path=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) if mime_type: item.setMimeType(mime_type) item.setContentLookup(False) control.resolve(int(sys.argv[1]), id != None, item) self.stopPlayingEvent = threading.Event() self.stopPlayingEvent.clear() while not self.stopPlayingEvent.isSet(): if control.monitor.abortRequested(): control.log("Abort requested") break control.sleep(500) if stopEvent: control.log("Setting stop event for proxy player") stopEvent.set()
def log(msg): # pass control.log(msg)
def play_stream(self, id, meta): if id == None: return try: meta = json.loads(meta) except: meta = { "playcount": 0, "overlay": 6, "mediatype": "video", "aired": None } is_live = False if 'live' in meta and meta['live'] == True: is_live = True info = self.__getLiveVideoInfo( id, meta['affiliate'] if 'affiliate' in meta else None) else: info = self.__getVideoInfo(id) title = meta['title'] if 'title' in meta else info['title'] signed_hashes = get_signed_hashes(info['hash']) query_string = re.sub(r'{{(\w*)}}', r'%(\1)s', info['query_string_template']) query_string = query_string % { 'hash': signed_hashes[0], 'key': 'app', 'openClosed': 'F', 'user': info['user'] if info['subscriber_only'] else '' } url = '?'.join([info['url'], query_string]) control.log("live media url: %s" % url) meta.update({ "genre": info["category"], "plot": info["title"], "plotoutline": info["title"], "title": title }) poster = meta['poster'] if 'poster' in meta else control.addonPoster() thumb = meta['thumb'] if 'thumb' in meta else info["thumbUri"] syshandle = int(sys.argv[1]) # self.offset = float(meta['milliseconds_watched']) / 1000.0 if 'milliseconds_watched' in meta else 0 self.isLive = 'live' in meta and meta['live'] == True self.url, mime_type, stopEvent = hlshelper.pickBandwidth(url) control.log("Resolved URL: %s" % repr(self.url)) item = control.item(path=self.url) item.setInfo(type='video', infoLabels=meta) item.setArt({ 'icon': thumb, 'thumb': thumb, 'poster': poster, 'tvshow.poster': poster, 'season.poster': poster }) item.setProperty('IsPlayable', 'true') if mime_type: item.setMimeType(mime_type) item.setContentLookup(False) control.resolve(syshandle, True, item) self.stopPlayingEvent = threading.Event() self.stopPlayingEvent.clear() last_time = 0.0 while not self.stopPlayingEvent.isSet(): if control.monitor.abortRequested(): control.log("Abort requested") break control.log("IS PLAYING: %s" % self.isPlaying()) if not is_live and self.isPlaying(): total_time = self.getTotalTime() current_time = self.getTime() if current_time - last_time > 10 or (last_time == 0 and current_time > 1): last_time = current_time percentage_watched = current_time / total_time if total_time > 0 else 1.0 / 1000000.0 self.save_video_progress( info['credentials'], info['program_id'], info['id'], current_time / 1000.0, fully_watched=percentage_watched > 0.9 and percentage_watched <= 1) control.sleep(1000) if stopEvent: control.log("Setting stop event for proxy player") stopEvent.set() control.log("Done playing. Quitting...")
def run(self, argv): try: from resources.lib.modules import control control.log('ARGV: %s' % argv) params = dict(urlparse.parse_qsl(argv)) #Parameters action = params.get('action') id_globo_videos = params.get('id_globo_videos') id_cms = params.get('id_cms') id = params.get('id') kind = params.get('kind') slug = params.get('slug') letter = params.get('letter') id_sexyhot = params.get('id_sexyhot') meta = params.get('meta') provider = params.get('provider') metaJson = json.loads(meta) if meta is not None else None isFolder = params.get('isFolder') url = params.get('url') page = params.get('page') q = params.get('q') category = params.get('category') program_id = params.get('program_id') season_id = params.get('season_id') date = params.get('date') poster = params.get('poster') fanart = params.get('fanart') bingewatch = (params.get('bingewatch') or 'false').lower() == "true" children_id = params.get('children_id') state = params.get('state') region = params.get('region') subcategory = params.get('subcategory') #Actions if action is None: from resources.lib.indexers import navigator navigator.navigator().root() elif action == 'settings': from resources.lib.indexers import navigator navigator.navigator().openSettings() elif action == 'clear': from resources.lib.indexers import navigator navigator.navigator().clear_cache() elif action == 'clearAuth': from resources.lib.indexers import navigator navigator.navigator().clear_credentials() elif action == 'login': from resources.lib.indexers import navigator navigator.navigator().cache_auth() elif action == 'refresh': from resources.lib.modules import control control.refresh() elif action == 'searchMenu': from resources.lib.indexers import navigator navigator.navigator().searchMenu() elif action == 'search': from resources.lib.indexers import navigator navigator.navigator().search(q, page) elif action == 'featured': from resources.lib.indexers import vod vod.Vod().get_extras() elif action == 'favorites': from resources.lib.indexers import vod vod.Vod().get_favorites() elif action == 'addFavorites': from resources.lib.indexers import vod vod.Vod().add_favorites(id_globo_videos) elif action == 'delFavorites': from resources.lib.indexers import vod vod.Vod().del_favorites(id_globo_videos) elif action == 'watchlater': from resources.lib.indexers import vod vod.Vod().get_watch_later() elif action == 'addwatchlater': from resources.lib.indexers import vod vod.Vod().add_watch_later(id_globo_videos) elif action == 'delwatchlater': from resources.lib.indexers import vod vod.Vod().del_watch_later(id_globo_videos) elif action == 'watchhistory': from resources.lib.indexers import vod vod.Vod().get_watch_history() elif action == 'liveChannels': from resources.lib.indexers import live live.Live().get_channels() elif action == 'vodChannels': from resources.lib.indexers import vod vod.Vod().get_vod_channels_directory() ## COMMON elif action == 'showdates': from resources.lib.indexers import vod page = page or 1 vod.Vod().get_program_dates(program_id, poster, provider) elif action == 'openvideos' and date: from resources.lib.indexers import vod vod.Vod().get_videos_by_program_date(program_id, date, poster, provider, bingewatch, fanart) ###GLOBOSAT PLAY #PREMIER FC elif action == 'playlive' and provider == 'premierefc': from resources.lib.indexers import live live.Live().get_subitems_pfc(metaJson) #LIVE CHANNELS elif action == 'playlive' and provider == 'globosat': from resources.lib.modules.globosat import player player.Player().playlive(id_globo_videos, meta) #VOD CHANNELS elif action == 'openchannel' and provider == 'globosat': from resources.lib.indexers import vod if slug == 'combate': vod.Vod().get_channel_categories(slug=slug) elif id_globo_videos: vod.Vod().get_channel_programs(channel_id=id_globo_videos) elif action == 'openvideos' and provider == 'globosat': from resources.lib.indexers import vod # page = page or 1 # vod.Vod().get_videos_by_program(program_id, id_globo_videos, int(page), poster, 'globosat', bingewatch, fanart) vod.Vod().get_seasons_by_program(id_globo_videos) elif action == 'openepisodes' and provider == 'globosat': from resources.lib.indexers import vod vod.Vod().get_episodes_by_program(program_id, season_id) elif action == 'playvod' and provider == 'globosat': from resources.lib.modules.globosat import player player.Player().playlive(id_globo_videos, meta) elif action == 'opencategory' and provider == 'combate': from resources.lib.indexers import vod vod.Vod().get_events_by_categories(category) elif action == 'openevent' and provider == 'combate': from resources.lib.indexers import vod vod.Vod().get_event_videos(category, url) elif action == 'openfighters': from resources.lib.indexers import vod vod.Vod().get_fighters(letter) elif action == 'openfighter': from resources.lib.indexers import vod vod.Vod().get_fighter_videos(slug, page) elif action == 'openfeatured' and provider == 'globosat': from resources.lib.indexers import vod vod.Vod().get_featured() elif action == 'openextra' and provider == 'globosat': from resources.lib.indexers import vod vod.Vod().get_track(id, kind) ###GLOBO PLAY elif action == 'playlive' and provider == 'multicam' and ( isFolder is True or str(isFolder).lower() == 'true'): from resources.lib.indexers import live live.Live().get_subitems_bbb(id_globo_videos) elif action == 'playlive' and provider == 'globoplay': from resources.lib.modules.globoplay import player player.Player().play_stream(id_globo_videos, meta) elif action == 'openchannel' and provider == 'globoplay': from resources.lib.indexers import vod if slug == 'futura': vod.Vod().get_channel_categories(slug=slug) else: vod.Vod().get_channel_categories() elif action == 'openextra' and provider == 'globoplay': from resources.lib.indexers import vod vod.Vod().get_videos_by_category(category, int(page or 1), poster) elif action == 'opencategory' and provider == 'futura': from resources.lib.indexers import vod vod.Vod().open_futura_menu(category) elif action == 'opencategory' and provider == 'globoplay' and subcategory is not None: from resources.lib.indexers import vod vod.Vod().get_programs_by_subcategory(category, subcategory) elif action == 'opencategory' and provider == 'globoplay': from resources.lib.indexers import vod vod.Vod().get_programs_by_category(category) elif action == 'openlocal' and region is not None and provider == 'globoplay': from resources.lib.indexers import vod vod.Vod().get_programs_by_region(region) elif action == 'openlocal' and state is not None and provider == 'globoplay': from resources.lib.indexers import vod vod.Vod().get_regions(state) elif action == 'openlocal' and provider == 'globoplay': from resources.lib.indexers import vod vod.Vod().get_states() elif action == 'openvideos' and provider == 'globoplay': from resources.lib.indexers import vod page = page or 1 vod.Vod().get_videos_by_program(program_id, id_globo_videos, int(page), poster, 'globoplay', bingewatch, fanart) elif action == 'playvod' and provider == 'globoplay': from resources.lib.modules.globoplay import player player.Player().play_stream(id_globo_videos, meta) elif action == 'playvod' and provider == 'globoplay': from resources.lib.modules.globoplay import player player.Player().play_stream(id_globo_videos, meta, children_id) elif action == 'open4k' and provider == 'globoplay': from resources.lib.indexers import vod vod.Vod().get_4k() ###SEXY HOT elif action == 'openchannel' and provider == 'sexyhot': from resources.lib.modules.sexyhotplay import indexer # indexer.indexer().get_categories() indexer.indexer().get_videos(1) elif action == 'getVideos' and provider == 'sexyhot': from resources.lib.modules.sexyhotplay import indexer indexer.indexer().get_videos(page) elif action == 'playvod' and provider == 'sexyhot': from resources.lib.modules.sexyhotplay import player player.Player().play_vod(id_sexyhot, meta) except Exception: buggalo.onExceptionRaised()
def get_instance_id(self): globoplay_instance_id = control.setting('globoplay_instance_id') if not globoplay_instance_id: checkin_url = 'https://device-provisioning.googleapis.com/checkin' post_data = { "checkin": { "iosbuild": { "model": "iPhone10,6", "os_version": "IOS_14.4" }, "last_checkin_msec": 0, "type": 2, "user_number": 0 }, "digest": "", "fragment": 0, "id": 0, "locale": "pt", "security_token": 0, "time_zone": "America/Sao_Paulo", "user_serial_number": 0, "version": 2 } control.log('POST %s' % checkin_url) response = requests.post( checkin_url, json=post_data, headers={ 'User-Agent': 'Globoplay/1 CFNetwork/1220.1 Darwin/20.3.0' }) control.log(response.content) response.raise_for_status() response = response.json() security_token = response.get('security_token') android_id = response.get('android_id') version_info = response.get('version_info') installations_url = 'https://firebaseinstallations.googleapis.com/v1/projects/globo-play/installations/' post_data = { "appId": "1:846115935537:ios:c91952b14380e445", "authVersion": "FIS_v2", "sdkVersion": "i:7.1.0" } control.log('POST %s' % installations_url) response = requests.post( installations_url, json=post_data, headers={ 'User-Agent': 'Globoplay/1 CFNetwork/1220.1 Darwin/20.3.0', 'x-goog-api-key': 'AIzaSyDbGxO8Bw7cfT5BYiAQTnReVItGEXlpnhY', 'x-firebase-client': 'apple-platform/ios apple-sdk/18B79 appstore/true deploy/cocoapods device/iPhone10,6 fire-abt/7.1.0 fire-analytics/7.3.0 fire-fcm/7.1.0 fire-iid/7.1.0 fire-install/7.1.0 fire-ios/7.1.0 fire-perf/7.0.1 fire-rc/7.1.0 firebase-crashlytics/7.1.0 os-version/14.4 swift/true xcode/12B45b', 'x-firebase-client-log-type': '3', 'x-ios-bundle-identifier': 'com.globo.hydra' }) control.log(response.content) response.raise_for_status() response = response.json() fid = response.get('fid') auth_token = response.get('authToken', {}).get('token') register_url = 'https://fcmtoken.googleapis.com/register' post_data = { 'X-osv': '14.4', 'device': android_id, 'X-scope': '*', 'plat': '2', 'app': 'com.globo.hydra', 'app_ver': '3.91.0', 'X-cliv': 'fiid-7.1.0', 'sender': '846115935537', 'X-subtype': '846115935537', 'appid': fid, 'gmp_app_id': '1:846115935537:ios:c91952b14380e445' } headers = { 'x-firebase-client': 'apple-platform/ios apple-sdk/18B79 appstore/true deploy/cocoapods device/iPhone10,6 fire-abt/7.1.0 fire-analytics/7.3.0 fire-fcm/7.1.0 fire-iid/7.1.0 fire-install/7.1.0 fire-ios/7.1.0 fire-perf/7.0.1 fire-rc/7.1.0 firebase-crashlytics/7.1.0 os-version/14.4 swift/true xcode/12B45b', 'authorization': 'AidLogin %s:%s' % (android_id, security_token), 'x-firebase-client-log-type': '1', 'app': 'com.globo.hydra', 'user-agent': 'Globoplay/1 CFNetwork/1220.1 Darwin/20.3.0', 'info': version_info, 'x-goog-firebase-installations-auth': auth_token, 'content-type': 'application/x-www-form-urlencoded' } control.log('POST %s' % register_url) control.log(headers) control.log(post_data) response = requests.post(register_url, data=post_data, headers=headers).content if not response.startswith('token='): raise Exception(response) globoplay_instance_id = response.replace('token=', '') control.log('NEW INSTANCE_ID: %s' % globoplay_instance_id) control.setSetting('globoplay_instance_id', globoplay_instance_id) return globoplay_instance_id
def onPlayBackEnded(self): control.log("PLAYBACK ENDED") if self.stopPlayingEvent: self.stopPlayingEvent.set()
def __login(user, password): control.log('LOGIN OIPLAY') session = requests.session() url = 'https://apim.oi.net.br/oic?state=eyJzdGF0ZSI6InN0YXRlIiwidGFyZ2V0X3VyaSI6Ii9kby1sb2dpbiJ9&client_id=e722caf1-7c47-4398-ac7f-f75a5f843906&response_type=code&scope=openid%20customer_info%20oob&redirect_uri=https://oiplay.tv/login' response = session.get(url) url = re.findall(r'action="([^"]+)"', response.content)[0] url = 'https://logintv.oi.com.br' + url session.post(url) url_login = '******' response = session.post( url_login, data={ 'option': 'credential', 'urlRedirect': 'https://logintv.oi.com.br/nidp/wsfed/ep?sid=0', 'Ecom_User_ID': user, 'Ecom_Password': password }) # control.log(response.content) url = re.findall(r"window.location.href='([^']+)';", response.content)[0] control.log('GET %s' % url) response = session.get(url) html = BeautifulSoup(response.content) url = html.find('form')['action'] inputs = html.findAll('input') post = {} for input in inputs: post[input['name']] = input['value'] response = session.post(url, data=post, allow_redirects=False) url_parsed = urlparse.urlparse(response.headers['Location']) qs = urlparse.parse_qs(url_parsed.query) code = qs['code'] post = { 'client_id': 'e722caf1-7c47-4398-ac7f-f75a5f843906', 'client_secret': 'b1e75e98-0833-4c67-aed7-9f1f232c8e0f', 'code': code, 'grant_type': 'authorization_code', 'redirect_uri': 'https://oiplay.tv/login' } token_response = session.post(ACCESS_TOKEN_URL, data=post) return json.loads(token_response.content, object_hook=as_python_object)
def get_account_details(account, deviceid, token): details = { 'oiplay_default_profile': control.setting('oiplay_default_profile') } if details['oiplay_default_profile']: control.log('ACCOUNT DETAILS FROM CACHE: ' + json.dumps(details)) return details headers = { 'Accept': 'application/json', 'X-Forwarded-For': '189.1.125.97', 'User-Agent': 'OiPlay-Store/5.1.1 (iPhone; iOS 13.3.1; Scale/3.00)', # if format == 'm3u8' else 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36', 'Authorization': 'Bearer ' + token } url = PROFILES_URL.format(account=account, deviceid=deviceid) control.log('GET %s' % url) response_full = requests.get(url, headers=headers) control.log(response_full.content) response = response_full.json() or {} if not response.get('upmProfiles'): control.log(response_full.status_code) control.log(response_full.content) return details profiles = sorted(response['upmProfiles'], key=lambda k: k['upmProfileType']['id']) for profile in profiles: if profile['upmProfileStatus']['name'] == 'Active': default_profile = profile['id'] break response['oiplay_default_profile'] = default_profile control.setSetting('oiplay_default_profile', str(default_profile)) control.log('ACCOUNT DETAILS FROM URL: ' + json.dumps(response)) return response
def playlive(self, meta): meta = meta or {} control.log("SBT - play_stream | meta=%s" % meta) self.isLive = True url = self.get_url() control.log("live media url: %s" % url) if not url: control.infoDialog(control.lang(34100).encode('utf-8'), icon='ERROR') return if control.proxy_url: http_proxy = MediaProxy(control.proxy_url) self.url = http_proxy.resolve(url) stop_event = http_proxy.stop_event else: self.url = url stop_event = 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 parsed_url = urlparse(url) 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') else: mime_type = 'application/vnd.apple.mpegurl' item.setProperty('inputstream.adaptive.manifest_type', 'hls') if mime_type: item.setMimeType(mime_type) control.log("MIME TYPE: %s" % repr(mime_type)) if control.is_inputstream_available(): item.setProperty('inputstreamaddon', 'inputstream.adaptive') control.resolve(int(sys.argv[1]), True, item) self.stopPlayingEvent = threading.Event() self.stopPlayingEvent.clear() while not self.stopPlayingEvent.isSet(): if control.monitor.abortRequested(): control.log("Abort requested") break control.sleep(1000) if stop_event: control.log("Setting stop event for proxy player") stop_event.set() control.log("Done playing. Quitting...")
def __get_full_day_schedule(today, affiliate='RJ'): url = "https://api.globoplay.com.br/v1/epg/%s/praca/%s?api_key=%s" % (today, affiliate, GLOBOPLAY_APIKEY) headers = {'Accept-Encoding': 'gzip'} slots = client.request(url, headers=headers)['gradeProgramacao']['slots'] result = [] for index, slot in enumerate(slots): cast = None castandrole = None if 'elenco' in slot: try: cast_raw = slot['elenco'].split('||') cast = [c.strip() for c in cast_raw[0].split(',')] if cast_raw is not None and len(cast_raw) > 0 else None if cast_raw is not None and len(cast_raw) > 1 and cast_raw[1].strip().startswith('Elenco de dublagem:'): castandrole_raw = cast_raw[1].strip().split('Elenco de dublagem:') if len(castandrole_raw) > 1: #Dubladores e seus personagens castandrole_raw = castandrole_raw[1].split('Outras Vozes:') castandrole = [(c.strip().split(':')[1].strip(), c.strip().split(':')[0].strip()) for c in castandrole_raw[0].split('/')] if len(castandrole_raw) > 1: #Outros dubladores sem papel definido castandrole = [(c.strip(), 'Outros') for c in castandrole_raw[1].split('/')] except Exception as ex: control.log("ERROR POPULATING CAST: %s" % repr(ex)) pass program_datetime_utc = util.strptime_workaround(slot['data_exibicao_e_horario']) + datetime.timedelta(hours=3) program_datetime = program_datetime_utc + util.get_utc_delta() # program_local_date_string = datetime.datetime.strftime(program_datetime, '%d/%m/%Y %H:%M') title = slot['nome_programa'] if 'nome_programa' in slot else None if slot["tipo"] == "confronto": showtitle = slot['confronto']['titulo_confronto'] + ' - ' + slot['confronto']['participantes'][0]['nome'] + ' X ' + slot['confronto']['participantes'][1]['nome'] else: showtitle = slot['nome'] if 'nome' in slot else None next_start = slots[index+1]['data_exibicao_e_horario'] if index+1 < len(slots) else None next_start = (util.strptime_workaround(next_start) + datetime.timedelta(hours=3) + util.get_utc_delta()) if next_start else datetime.datetime.now() item = { "tagline": slot['chamada'] if 'chamada' in slot else slot['nome'], "closed_caption": slot['closed_caption'], "facebook": slot['facebook'], "twitter": slot['twitter'], "hd": slot['hd'], "id": slot['id'], "id_programa": slot['id_programa'], "id_webmedia": slot['id_webmedia'], "fanart": 'https://s02.video.glbimg.com/x720/%s.jpg' % get_globo_live_id(), "thumb": slot['imagem'], "logo": slot['logo'], "clearlogo": slot['logo'], "poster": slot['poster'] if 'poster' in slot else 'None', "subtitle": slot['nome'], "title": title, "plot": slot['resumo'] if 'resumo' in slot else None, #program_local_date_string + ' - ' + (slot['resumo'] if 'resumo' in slot else showtitle.replace(' - ', '\n') if showtitle and len(showtitle) > 0 else slot['nome_programa']), "plotoutline": datetime.datetime.strftime(program_datetime, '%H:%M') + ' - ' + datetime.datetime.strftime(next_start, '%H:%M'), "mediatype": 'episode' if showtitle and len(showtitle) > 0 else 'video', "genre": slot['tipo_programa'], "datetimeutc": program_datetime_utc, "dateadded": datetime.datetime.strftime(program_datetime, '%Y-%m-%d %H:%M:%S'), # 'StartTime': datetime.datetime.strftime(program_datetime, '%H:%M:%S'), # 'EndTime': datetime.datetime.strftime(next_start, '%H:%M:%S'), 'duration': util.get_total_seconds(next_start - program_datetime) } if showtitle and len(showtitle) > 0: item.update({ 'tvshowtitle': showtitle }) if slot['tipo'] == 'filme': item.update({ "originaltitle": slot['titulo_original'] if 'titulo_original' in slot else None, 'genre': slot['genero'] if 'genero' in slot else None, 'year': slot['ano'] if 'ano' in slot else None, 'director': slot['direcao'] if 'direcao' in slot else None }) if cast: item.update({ 'cast': cast }) if castandrole: item.update({ 'castandrole': castandrole, }) result.append(item) return result
def __get_affiliate_live_channels(affiliate): liveglobo = get_globo_live_id() if affiliate == "Sao Paulo": code, geo_position = "SP1", 'lat=-23.5505&long=-46.6333' elif affiliate == "Brasilia": code, geo_position = "DF", 'lat=-15.7942&long=-47.8825' elif affiliate == "Belo Horizonte": code, geo_position = "BH", 'lat=-19.9245&long=-43.9352' elif affiliate == "Recife": code, geo_position = "PE1", 'lat=-8.0476&long=-34.8770' # elif affiliate == "Salvador": # code, geo_position = "SAL", 'lat=-12.9722&long=-38.5014' # elif affiliate == "Fortaleza": # code, geo_position = "CE1", 'lat=-3.7319&long=-38.5267' # elif affiliate == "Aracaju": # code, geo_position = "SER", 'lat=-10.9472&long=-37.0731' # elif affiliate == "Maceio": # code, geo_position = "MAC", 'lat=-9.6498&long=-35.7089' # elif affiliate == "Cuiaba": # code, geo_position = "MT", 'lat=-15.6014&long=-56.0979' # elif affiliate == "Porto Alegre": # code, geo_position = "RS1", 'lat=-30.0347&long=-51.2177' # elif affiliate == "Florianopolis": # code, geo_position = "SC1", 'lat=-27.5949&long=-48.5482' # elif affiliate == "Curitiba": # code, geo_position = "CUR", 'lat=-25.4244&long=-49.2654' # elif affiliate == "Vitoria": # code, geo_position = "VIT", 'lat=-20.2976&long=-40.2958' # elif affiliate == "Goiania": # code, geo_position = "GO01", 'lat=-16.6869&long=-49.2648' # elif affiliate == "Campo Grande": # code, geo_position = "MS1", 'lat=-20.4697&long=-54.6201' # elif affiliate == "Manaus": # code, geo_position = "MAN", 'lat=-3.1190&long=-60.0217' # elif affiliate == "Belem": # code, geo_position = "BEL", 'lat=-1.4558&long=-48.4902' # elif affiliate == "Macapa": # code, geo_position = "AMP", 'lat=-0.0356&long=-51.0705' # elif affiliate == "Palmas": # code, geo_position = "PAL", 'lat=-10.2491&long=-48.3243' # elif affiliate == "Rio Branco": # code, geo_position = "ACR", 'lat=-9.9754&long=-67.8249' # elif affiliate == "Teresina": # code, geo_position = "TER", 'lat=-5.0920&long=-42.8038' # elif affiliate == "Sao Luis": # code, geo_position = "MA1", 'lat=-2.5391&long=-44.2829' # elif affiliate == "Joao Pessoa": # code, geo_position = "JP", 'lat=-7.1195&long=-34.8450' # elif affiliate == "Natal": # code, geo_position = "NAT", 'lat=-5.7793&long=-35.2009' else: code, geo_position = "RJ", 'lat=-22.900&long=-43.172' live_program = __get_live_program(code) if not live_program: return None program_description = get_program_description(live_program['program_id_epg'], live_program['program_id'], code) control.log("program_description: %s" % repr(program_description)) item = { 'plot': None, 'duration': None, 'affiliate': geo_position, 'brplayprovider': 'globoplay', 'affiliate_code': code, 'logo': None } item.update(program_description) item.pop('datetimeutc', None) title = program_description['title'] if 'title' in program_description else 'N/A' subtitle = program_description['subtitle'] if 'subtitle' in program_description else 'N/A' item.update({ 'slug': 'globo', 'name': 'Globo ' + re.sub(r'\d+','',code) + '[I] - ' + title + '[/I]', 'title': subtitle, #'Globo ' + re.sub(r'\d+','',code) + '[I] - ' + program_description['title'] + '[/I]', 'tvshowtitle': title, 'sorttitle': 'Globo ' + re.sub(r'\d+','',code), 'clearlogo': GLOBO_LOGO, # 'tagline': program_description['title'], 'studio': 'Rede Globo - ' + affiliate, # 'logo': GLOBO_LOGO, 'playable': 'true', 'id': liveglobo, 'channel_id': 196, 'live': True, 'fanart': GLOBO_FANART }) return item
def play_stream(self, id, meta, children_id=None): if id is None: return try: meta = json.loads(meta) except: meta = { "playcount": 0, "overlay": 6, "mediatype": "video", "aired": None } self.isLive = False if 'livefeed' in meta and meta['livefeed'] == 'true': control.log("PLAY LIVE!") self.isLive = True info = self.__getLiveVideoInfo( id, meta['affiliate'] if 'affiliate' in meta else None) if info is None: return item, self.url, stopEvent = self.__get_list_item(meta, info) else: info = resourceshelper.get_video_info(id, children_id) if info is None: return if 'resource_id' not in info: control.log("PLAY CHILDREN!") items = [] xbmc.PlayList(1).clear() first = True for i in info: hash, user, self.credentials = self.sign_resource( i['resource_id'], i['id'], i['player'], i['version']) i['hash'] = hash i['user'] = user item, url, stopEvent = self.__get_list_item(meta, i, False) if first: self.url = url first = False items.append(item) control.log("PLAYLIST ITEM URL: %s" % url) xbmc.PlayList(1).add(url, item) item = items[0] else: control.log("PLAY SINGLE RESOURCE!") hash, user, self.credentials = self.sign_resource( info['resource_id'], info["id"], info['player'], info['version'], meta['anonymous'] if 'anonymous' in meta else False) info['hash'] = hash info['user'] = user item, self.url, stopEvent = self.__get_list_item(meta, info) self.offset = float(meta['milliseconds_watched'] ) / 1000.0 if 'milliseconds_watched' in meta else 0 self.isLive = 'live' in meta and meta['live'] syshandle = int(sys.argv[1]) control.resolve(syshandle, True, item) self.stopPlayingEvent = threading.Event() self.stopPlayingEvent.clear() self.program_id = info['program_id'] if 'program_id' in info else None self.video_id = id 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: total_time = self.getTotalTime() current_time = self.getTime() if current_time - last_time > 5 or (last_time == 0 and current_time > 1): last_time = current_time percentage_watched = current_time / total_time if total_time > 0 else 1.0 / 1000000.0 self.save_video_progress( self.credentials, self.program_id, self.video_id, current_time * 1000, fully_watched=0.9 < percentage_watched <= 1) control.sleep(500) if stopEvent: control.log("Setting stop event for proxy player") stopEvent.set() control.log("Done playing. Quitting...")
def authenticate(self, username, password, service_id): if not self.is_authenticated(username, password, service_id) and ( username and password and service_id): control.log('username/password set. trying to authenticate') self.credentials = self._authenticate(username, password, service_id) success = self.credentials.get('success') if success is False: error_message = self.credentials.get('error_message') control.log('authentication error: %s' % error_message) control.infoDialog(error_message, icon='ERROR') return {}, {} is_authenticated, self.user_data = self.check_service( bypass_cache=True) if is_authenticated and self.is_authenticated( username, password, service_id): control.log('successfully authenticated') self._save_credentials() else: control.log('wrong username or password') message = '[%s] %s' % (self.__class__.__name__, control.lang(32003)) control.infoDialog(message, icon='ERROR') return {}, {} elif self.is_authenticated(username, password, service_id): control.log('[GLOBO AUTH] - already authenticated') else: control.log('no username set to authenticate', control.LOGWARNING) message = 'Missing user credentials' control.infoDialog(message, icon='ERROR') control.openSettings() return {}, {} control.log(repr(self.credentials)) returned_credentials = dict(self.credentials) del returned_credentials['brplay_id'] del returned_credentials['success'] del returned_credentials['error_message'] return returned_credentials, self.user_data
def onPlayBackStopped(self): control.log("PLAYBACK STOPPED") if self.stopPlayingEvent: self.stopPlayingEvent.set()
def request(url, close=True, redirect=True, error=False, proxy=None, post=None, headers=None, mobile=False, XHR=False, limit=None, referer=None, cookie=None, output='', timeout='30'): try: handlers = [] if not proxy is None: control.log("proxy: %s" % proxy) handlers += [urllib2.ProxyHandler(proxy), urllib2.HTTPHandler] opener = urllib2.build_opener(*handlers) opener = urllib2.install_opener(opener) if output == 'cookie' or output == 'extended' or not close == True: cookies = cookielib.LWPCookieJar() handlers += [ urllib2.HTTPHandler(), urllib2.HTTPSHandler(), urllib2.HTTPCookieProcessor(cookies) ] opener = urllib2.build_opener(*handlers) opener = urllib2.install_opener(opener) try: if sys.version_info < (2, 7, 9): raise Exception() import ssl ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE handlers += [urllib2.HTTPSHandler(context=ssl_context)] opener = urllib2.build_opener(*handlers) opener = urllib2.install_opener(opener) except: pass try: headers.update(headers) except: headers = {} if 'User-Agent' in headers: pass elif not mobile == True: headers['User-Agent'] = cache.get(randomagent, 1) else: headers['User-Agent'] = 'Apple-iPhone/701.341' if 'Referer' in headers: pass elif referer is None: headers['Referer'] = '%s://%s/' % (urlparse.urlparse(url).scheme, urlparse.urlparse(url).netloc) else: headers['Referer'] = referer if not 'Accept-Language' in headers: headers['Accept-Language'] = 'en-US' if 'X-Requested-With' in headers: pass elif XHR is True: headers['X-Requested-With'] = 'XMLHttpRequest' if 'Cookie' in headers: pass elif not cookie is None: headers['Cookie'] = printCookieDict(cookie) if isinstance( cookie, dict) else cookie if redirect is False: class NoRedirection(urllib2.HTTPErrorProcessor): def http_response(self, request, response): return response opener = urllib2.build_opener(NoRedirection) opener = urllib2.install_opener(opener) try: del headers['Referer'] except: pass request = urllib2.Request(url, data=post, headers=headers) rid = uuid.uuid4().hex control.log("Url request (%s): %s" % (rid, url)) try: response = urllib2.urlopen(request, timeout=int(timeout)) except urllib2.HTTPError as response: if response.code == 503: cf_result = response.read(5242880) try: encoding = response.info().getheader('Content-Encoding') except: encoding = None if encoding == 'gzip': cf_result = gzip.GzipFile( fileobj=StringIO.StringIO(cf_result)).read() if 'cf-browser-verification' in cf_result: netloc = '%s://%s' % (urlparse.urlparse(url).scheme, urlparse.urlparse(url).netloc) ua = headers['User-Agent'] cf = cache.get(cfcookie().get, 168, netloc, ua, timeout) headers['Cookie'] = cf request = urllib2.Request(url, data=post, headers=headers) response = urllib2.urlopen(request, timeout=int(timeout)) elif error is False: control.log("Response error code (%s): %s" % (rid, response.code)) return elif response.code == 403: control.log("Response error code (%s): %s" % (rid, response.code)) raise Exception("Permission Denied") elif error is False: control.log("Response error code (%s): %s" % (rid, response.code)) return control.log("Response code (%s): %s" % (rid, response.code)) if response.code == 403: raise Exception("Permission Denied") elif response.code >= 400: raise Exception("Request Error: %s" % response.code) if output == 'cookie': try: result = '; '.join( ['%s=%s' % (i.name, i.value) for i in cookies]) except: pass try: result = cf except: pass if close is True: response.close() return result elif output == 'geturl': result = response.geturl() if close is True: response.close() return result elif output == 'headers': result = response.headers if close is True: response.close() return result elif output == 'chunk': try: content = int(response.headers['Content-Length']) except: content = (2049 * 1024) if content < (2048 * 1024): return result = response.read(16 * 1024) if close is True: response.close() return result if limit == '0': result = response.read(224 * 1024) elif not limit is None: result = response.read(int(limit) * 1024) else: result = response.read(5242880) try: encoding = response.info().getheader('Content-Encoding') except: encoding = None if encoding == 'gzip': result = gzip.GzipFile(fileobj=StringIO.StringIO(result)).read() if 'sucuri_cloudproxy_js' in result: su = sucuri().get(result) headers['Cookie'] = su request = urllib2.Request(url, data=post, headers=headers) response = urllib2.urlopen(request, timeout=int(timeout)) if limit == '0': result = response.read(224 * 1024) elif not limit is None: result = response.read(int(limit) * 1024) else: result = response.read(5242880) try: encoding = response.info().getheader('Content-Encoding') except: encoding = None if encoding == 'gzip': result = gzip.GzipFile( fileobj=StringIO.StringIO(result)).read() control.log("response (%s): %s" % (rid, result)) if response.headers and response.headers.get('content-type') and ( 'application/json' in response.headers.get('content-type') or 'text/javascript' in response.headers.get('content-type')): return json.loads(result) if output == 'extended': response_headers = response.headers response_code = str(response.code) try: cookie = '; '.join( ['%s=%s' % (i.name, i.value) for i in cookies]) except: pass try: cookie = cf except: pass if close is True: response.close() return result, response_code, response_headers, headers, cookie else: if close is True: response.close() return result except Exception, e: traceback.print_exc() control.log("Request ERROR: %s" % str(e)) return
def onPlayBackStarted(self): control.log("PLAYBACK STARTED")
def log_error(self, msg): if is_standalone: print msg else: control.log(msg)
def update(self, query=None, info='true'): if not query == None: control.idle() try: items = [] season, episode = [], [] show = [os.path.join(self.library_folder, i) for i in control.listDir(self.library_folder)[0]] for s in show: try: season += [os.path.join(s, i) for i in control.listDir(s)[0]] except: pass for s in season: try: episode.append([os.path.join(s, i) for i in control.listDir(s)[1] if i.endswith('.strm')][-1]) except: pass for file in episode: try: file = control.openFile(file) read = file.read() read = read.encode('utf-8') file.close() if not read.startswith(sys.argv[0]): raise Exception() params = dict(urlparse.parse_qsl(read.replace('?',''))) try: tvshowtitle = params['tvshowtitle'] except: tvshowtitle = None try: tvshowtitle = params['show'] except: pass if tvshowtitle == None or tvshowtitle == '': raise Exception() year, imdb, tvdb = params['year'], params['imdb'], params['tvdb'] imdb = 'tt' + re.sub('[^0-9]', '', str(imdb)) try: tmdb = params['tmdb'] except: tmdb = '0' try: tvrage = params['tvrage'] except: tvrage = '0' items.append({'tvshowtitle': tvshowtitle, 'year': year, 'imdb': imdb, 'tmdb': tmdb, 'tvdb': tvdb, 'tvrage': tvrage}) except: pass items = [i for x, i in enumerate(items) if i not in items[x + 1:]] if len(items) == 0: raise Exception() except: return try: lib = control.jsonrpc('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties" : ["imdbnumber", "title", "year"]}, "id": 1}') lib = unicode(lib, 'utf-8', errors='ignore') lib = json.loads(lib)['result']['tvshows'] except: return if info == 'true' and not control.condVisibility('Window.IsVisible(infodialog)') and not control.condVisibility('Player.HasVideo'): control.infoDialog(control.lang(30422).encode('utf-8'), time=10000000) self.infoDialog = True try: control.makeFile(control.dataPath) dbcon = database.connect(control.libcacheFile) dbcur = dbcon.cursor() dbcur.execute("CREATE TABLE IF NOT EXISTS tvshows (""id TEXT, ""items TEXT, ""UNIQUE(id)"");") except: return try: from resources.lib.indexers import episodes except: return for item in items: it = None if xbmc.abortRequested == True: return sys.exit() try: dbcur.execute("SELECT * FROM tvshows WHERE id = '%s'" % item['tvdb']) fetch = dbcur.fetchone() it = eval(fetch[1].encode('utf-8')) except: pass try: if not it == None: raise Exception() it = episodes.episodes().get(item['tvshowtitle'], item['year'], item['imdb'], item['tmdb'], item['tvdb'], item['tvrage'], idx=False) status = it[0]['status'].lower() it = [{'name': i['name'], 'title': i['title'], 'year': i['year'], 'imdb': i['imdb'], 'tmdb': i['tmdb'], 'tvdb': i['tvdb'], 'tvrage': i['tvrage'], 'season': i['season'], 'episode': i['episode'], 'tvshowtitle': i['tvshowtitle'], 'alter': i['alter'], 'date': i['premiered']} for i in it] if status == 'continuing': raise Exception() dbcur.execute("INSERT INTO tvshows Values (?, ?)", (item['tvdb'], repr(it))) dbcon.commit() except: pass try: id = [item['imdb'], item['tvdb']] if not item['tmdb'] == '0': id += [item['tmdb']] ep = [x['title'].encode('utf-8') for x in lib if str(x['imdbnumber']) in id or (x['title'].encode('utf-8') == item['tvshowtitle'] and str(x['year']) == item['year'])][0] ep = control.jsonrpc('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"filter":{"and": [{"field": "tvshow", "operator": "is", "value": "%s"}]}, "properties": ["season", "episode"]}, "id": 1}' % ep) ep = unicode(ep, 'utf-8', errors='ignore') ep = json.loads(ep)['result']['episodes'][-1] num = [x for x,y in enumerate(it) if str(y['season']) == str(ep['season']) and str(y['episode']) == str(ep['episode'])][-1] it = [y for x,y in enumerate(it) if x > num] if len(it) == 0: continue except: continue for i in it: try: if xbmc.abortRequested == True: return sys.exit() if int(self.date) <= int(re.sub('[^0-9]', '', str(i['date']))): from resources.lib.sources import sources src = sources().checkSources(i['name'], i['title'], i['year'], i['imdb'], i['tmdb'], i['tvdb'], i['tvrage'], i['season'], i['episode'], i['tvshowtitle'], i['alter'], i['date']) control.log('### SOURCES SRC 10 %s | %s' % (src,i['name'])) if src == False: raise Exception() libtvshows().strmFile(i) except: pass if self.infoDialog == True: control.infoDialog(control.lang(30423).encode('utf-8'), time=1) if self.library_setting == 'true' and not control.condVisibility('Library.IsScanningVideo'): control.execute('UpdateLibrary(video)')
def _select_resource(video_id, resources, metadata, title_override=None, cdn=None): resource = None encrypted = False player = 'android' drm_scheme = None enable_4k = control.is_4k_enabled enable_hdr = control.setting('enable_hdr') == 'true' prefer_dash = control.setting('prefer_dash') == 'true' prefer_smoothstreaming = control.setting('prefer_smoothstreaming') == 'true' prefer_playready = control.setting('prefer_playready') == 'true' if prefer_smoothstreaming: for node in resources: if 'players' in node and 'encrypted' in node and node['encrypted'] and any('smoothstreaming' in s for s in node['players']) and any('playready' in s for s in node['content_protection']): encrypted = True resource = node player = 'android_native' drm_scheme = 'com.microsoft.playready' server_url = resource['content_protection']['playready']['server'] break if prefer_playready and not resource: try_player = 'androidtv_hdr' if enable_hdr else 'androidtv_sdr' if enable_4k else 'androidtv' for node in resources: if 'players' in node and 'encrypted' in node and node['encrypted'] and any(try_player in s for s in node['players']) and any('playready' in s for s in node['content_protection']): encrypted = True resource = node player = try_player drm_scheme = 'com.microsoft.playready' server_url = resource['content_protection']['playready']['server'] break if not resource: for node in resources: if 'players' in node and 'encrypted' in node and node['encrypted'] and any('android_native' in s for s in node['players']) and any('playready' in s for s in node['content_protection']): encrypted = True resource = node player = 'android_native' drm_scheme = 'com.microsoft.playready' server_url = resource['content_protection']['playready']['server'] break if not resource: for node in resources: if 'players' in node and 'encrypted' in node and node['encrypted'] and any('android_native' in s for s in node['players']) and any('widevine' in s for s in node['content_protection']): encrypted = True resource = node player = 'android_native' drm_scheme = 'com.widevine.alpha' server_url = resource['content_protection']['widevine']['server'] break if not resource and enable_4k and prefer_dash: for node in resources: if 'players' in node and any('tv_4k_dash' in s for s in node['players']): resource = node player = 'tv_4k_dash' break if not resource and prefer_dash: for node in resources: if 'players' in node and any('tv_dash' in s for s in node['players']): resource = node player = 'tv_dash' break if not resource and enable_4k and (not prefer_dash or not control.is_inputstream_available()): for node in resources: if 'players' in node and any('tvos_4k' in s for s in node['players']) and '2160' in node['_id'] and not node.get('encrypted', False): resource = node player = 'tvos_4k' break if not resource and enable_4k and enable_hdr: for node in resources: # if 'players' in node and 'height' in node and node['height'] == 2160 and any('androidtv_hdr' in s for s in node['players']): if 'players' in node and any('androidtv_hdr' in s for s in node['players']): resource = node player = 'androidtv_hdr' break if not resource and enable_4k: for node in resources: # if 'players' in node and 'height' in node and node['height'] == 2160 and any('androidtv_sdr' in s for s in node['players']): if 'players' in node and any('androidtv_sdr' in s for s in node['players']): resource = node player = 'androidtv_sdr' break #Prefer MP4 when available if not resource: for node in resources: if 'players' in node and 'height' in node and node['height'] == 720 and any('desktop' in s for s in node['players']): resource = node player = 'android' break if not resource: for node in resources: if 'players' in node and any('androidtv' in s for s in node['players']): resource = node player = 'androidtv' break if not resource: for node in resources: if 'players' in node and any('android' in s for s in node['players']): resource = node player = 'android' break if (resource or None) is None: control.infoDialog(message=control.lang(34102).encode('utf-8'), sound=True, icon='ERROR') return None control.log('Selected resource for video %s: %s' % (video_id, resource['_id'])) subtitles = [] for subtitle in resources: if 'type' in subtitle and subtitle['type'] == 'subtitle': control.log('Found Subtitle: %s' % subtitle['url']) subtitles.append({ 'language': subtitle['language'], 'url': subtitle['url'] }) cdn_data = resource['cdns'][cdn] if cdn in resource['cdns'] else None if cdn_data: domain = cdn_data['domain'] query_string_template = cdn_data['query_string_template'] path = resource['paths']['max'] url = domain + path else: query_string_template = resource["query_string_template"] url = resource["url"] cdn = 'globo' result = { "resource_id": resource['_id'], "id": video_id, "title": title_override or metadata["title"], "program": metadata["program"], "program_id": metadata["program_id"], "provider_id": metadata["provider_id"], "channel": metadata["channel"], "channel_id": metadata["channel_id"], "category": metadata["category"], "subscriber_only": metadata["subscriber_only"], "exhibited_at": metadata["exhibited_at"], "player": player, "version": PLAYER_VERSION, "url": url, "cdn": cdn, "query_string_template": query_string_template, "thumbUri": resource["thumbUri"] if 'thumbUri' in resource else None, "encrypted": encrypted, "drm_scheme": drm_scheme, "protection_url": server_url.replace(DEVICE_ID_KEY, DEVICE_ID) if encrypted else None, 'subtitles': subtitles } control.log(result) return result
def __get_video_info(self, id): playlistUrl = 'http://api.globovideos.com/videos/%s/playlist' playlistJson = client.request(playlistUrl % id, headers={"Accept-Encoding": "gzip"}) if not 'videos' in playlistJson or len(playlistJson['videos']) == 0: control.infoDialog(message=control.lang(34101).encode('utf-8'), sound=True, icon='ERROR') return None playlistJson = playlistJson['videos'][0] for node in playlistJson['resources']: if any("ios" in s for s in node['players']): resource = node break if resource == None: control.infoDialog(message=control.lang(34102).encode('utf-8'), sound=True, icon='ERROR') return None resource_id = resource['_id'] provider = control.setting('globosat_provider').lower().replace( ' ', '_') username = control.setting('globosat_username') password = control.setting('globosat_password') # authenticate authenticator = getattr(auth, provider)() credentials = authenticator.authenticate(playlistJson["provider_id"], username, password, False) hashUrl = 'https://security.video.globo.com/videos/%s/hash?resource_id=%s&version=1.1.23&player=ios' % ( id, resource_id) control.log("HASH URL: %s" % hashUrl) hashJson = client.request(hashUrl, cookie=credentials, mobile=True, headers={"Accept-Encoding": "gzip"}) control.log("HASH JSON: %s" % repr(hashJson)) if 'http_status_code' in hashJson and hashJson[ 'http_status_code'] == 403: control.infoDialog(message=str( '%s: %s' % (control.lang(34105).encode('utf-8'), hashJson['message'])), sound=True, icon='ERROR') return None return { "id": playlistJson["id"], "title": playlistJson["title"], "program": playlistJson["program"], "program_id": playlistJson["program_id"], "provider_id": playlistJson["provider_id"], "channel": playlistJson["channel"], "channel_id": playlistJson["channel_id"], "category": playlistJson["category"], "subscriber_only": playlistJson["subscriber_only"], "exhibited_at": playlistJson["exhibited_at"], "player": "ios", "url": resource["url"], "query_string_template": resource["query_string_template"], "thumbUri": None, # resource["thumbUri"], "hash": hashJson["hash"] }
def get_geofence_video_info(video_id, latitude, longitude, credentials, cdn=None): if credentials is None: return None proxy = control.proxy_url proxy = None if proxy is None or proxy == '' else { 'http': proxy, 'https': proxy, } version = PLAYER_VERSION # enable_4k = control.is_4k_enabled # enable_hdr = control.setting('enable_hdr') == 'true' players_preference = [] # if enable_4k: # if enable_hdr: # players_preference.extend([ # 'androidtv_hdr', # ]) # else: # players_preference.extend([ # 'androidtv_sdr' # ]) players_preference.extend([ # 'androidtv', 'android', # 'android_native', ]) selected_player = players_preference[0] post_data = { 'player': selected_player, 'version': version, 'lat': latitude, 'long': longitude, 'cdn': cdn or 'globo' } # tz: 00:00 # player: ios_native # cdn: globo # ts: 1613693205 # udid: bbec61e5f3a06ca54624e84accc232b5d49971a6 # version: 10.25.0 # lat: 51.49502563476562 # long: -0.03278398965019131 hash_url = 'http://security.video.globo.com/videos/%s/hash' % video_id control.log('POST %s' % hash_url) control.log(post_data) control.log(credentials) response = requests.post(hash_url, cookies=credentials, headers={ "Accept-Encoding": "gzip", "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Canais Globo (Globosat Play)/444 (iPhone)" }, data=post_data, proxies=proxy) response.raise_for_status() hash_json = response.json() control.log(hash_json) return { "id": video_id, "title": hash_json.get("name"), "category": 'Live', "subscriber_only": True, "channel": None, "player": selected_player, "url": hash_json.get("url"), "query_string_template": hash_json.get('query_string_template') or "h={{hash}}&k={{key}}&a={{openClosed}}&u={{user}}", "thumbUri": hash_json.get("thumbUri"), "hash_token": util.get_signed_hashes(hash_json.get('hash'))[0] if 'hash' in hash_json else hash_json.get('token'), "user": hash_json.get("user"), "credentials": credentials, "encrypted": hash_json.get('encrypted', False) }
def get_page(path, absolute=False): control.log('get_page: %s' % path) if not path: return if path == '/account/profiles/mylist': path = '/account/profile/user-tracks' if path.startswith('/account/') or absolute: url = path else: url = '/pages?id=' + path use_pagination = control.setting('telecine_use_pagination') == 'true' while url: response = get_cached(BASE_URL + url) template = response.get('template') control.log('template: %s' % template) if not template or template == 'Cinelist': entry = next(iter(response.get('entries', [])), response) list_obj = entry.get('list', response) # image_size = 'poster' if 'poster' in entry.get('template', 'poster').lower() else 'thumb' for item in list_obj.get('items', []): category = item.get('category', '').split('/') has_category = category and len(category) == 3 genre = category[0] if has_category else None subgenre = category[1] if has_category else None year = category[2] if has_category else None yield { 'handler': HANDLER, 'method': 'get_film' if item.get('path').startswith('/filme/') else 'get_page', 'id': item.get('id'), 'path': item.get('path'), 'label': item.get('name'), 'plot': item.get('mouseOverDescription', response.get('description')), 'genre': [genre, subgenre], 'year': year, 'overlay': 5 if item.get('percentWatched', 0) > 0.9 else 4, 'mediatype': 'movie' if item.get('originalImageUrl') else None, 'art': { 'poster': item.get('originalImageUrl', FANART), 'thumb': FANART if not item.get('originalImageUrl') else None, 'fanart': FANART }, 'properties': { 'playcount': 1 if item.get('percentWatched', 0) > 0.9 else 0 } } url = list_obj.get('paging', {}).get('next') if url and use_pagination: yield { 'handler': HANDLER, 'method': 'get_page', 'absolute': True, 'path': list_obj.get('paging', {}).get('next'), 'label': control.lang(34136).encode('utf-8'), 'art': { 'poster': control.addonNext(), 'fanart': FANART }, 'properties': { 'SpecialSort': 'bottom' } } url = None else: fanart = FANART for index, item in enumerate(response.get('entries', [])): list_type = item.get('type') if list_type in ['TextEntry', 'ImageEntry']: fanart = item.get('originalImageUrl', FANART) continue image_size = 'poster' if 'poster' in item.get( 'template', 'poster') else 'thumb' if list_type == 'UserEntry': path = item.get('list', {}).get('paging', {}).get('next') else: path = item.get('list', {}).get('path') yield { 'handler': HANDLER, 'method': 'get_page', 'path': path, 'label': item.get('title', item.get('text', '')) or control.lang(34132).encode('utf-8'), 'plot': response.get('description'), 'sorttitle': "%04d" % (index, ), 'sort': [ control.SORT_METHOD_VIDEO_SORT_TITLE, control.SORT_METHOD_LABEL ], 'art': { image_size: item.get('originalImageUrl', FANART), 'fanart': item.get('originalImageUrl', fanart) } } url = None
def get_video_router(video_id, is_live=False, cdn=None): proxy = control.proxy_url proxy = None if proxy is None or proxy == '' else { 'http': proxy, 'https': proxy, } cdn = cdn or 'globo' version = PLAYER_VERSION enable_4k = control.is_4k_enabled enable_hdr = control.setting('enable_hdr') == 'true' prefer_dash = control.setting('prefer_dash') == 'true' players_preference = [] if enable_4k: if enable_hdr: players_preference.extend([ 'tvos_4k', 'androidtv_hdr', 'roku_4k_hdr', 'webos_4k_hdr' ]) else: players_preference.extend([ 'androidtv_sdr' ]) players_preference.extend([ 'androidtv', 'android', 'android_native', ]) container = '.mpd' if prefer_dash else None # '.m3u8' selected_player = None response = None for player in players_preference: playlist_url = 'https://router.video.globo.com/cdn?video_id={video_id}&player_type={player}&video_type={video_type}&content_protection=widevine&quality=max&cdn={cdn}' final_url = playlist_url.format(video_id=video_id, player=player, video_type='Live' if is_live else 'Video', cdn=cdn) control.log('[Globoplay Player] - GET %s' % final_url) response = requests.get(final_url, headers={"Accept-Encoding": "gzip"}, proxies=proxy).json() control.log(response) if response and 'resource' in response: if container is None or any(container in source["url"] for source in response['resource']['sources']): selected_player = player break if not response: raise Exception("Couldn't find resource") resource = response['resource'] encrypted = resource['drm_protection_enabled'] if encrypted and resource['content_protection']['type'] != 'widevine': control.infoDialog(message='DRM not supported: %s' % resource['content_protection']['type'], sound=True, icon='ERROR') return None drm_scheme = 'com.widevine.alpha' if encrypted else None server_url = resource['content_protection']['server'] if encrypted else None source = resource['sources'][0] subtitles = [] if 'subtitles' in source and source['subtitles']: for language in source['subtitles']: subtitle = source['subtitles'][language] subtitles.append({ 'language': subtitle['language'], 'url': subtitle['url'] }) result = { "resource_id": resource['_id'], "id": video_id, "title": None, "program": None, "program_id": None, "provider_id": None, "channel": None, "channel_id": None, "category": None, "subscriber_only": True, "exhibited_at": None, "player": selected_player, "version": version, "url": source["url"], "query_string_template": source['auth_param_templates']["query_string"], "thumbUri": None, "encrypted": encrypted, "drm_scheme": drm_scheme, "protection_url": server_url.replace(DEVICE_ID_KEY, DEVICE_ID) if encrypted else None, 'cdn': source['cdn'], 'subtitles': subtitles } control.log(result) return result
def do_GET(self): print "XBMCLocalProxy: Serving GET request..." global g_stopEvent global g_downloader try: # Pull apart request path request_path = self.path[1:] path_and_query = request_path path_and_query_list = path_and_query.split('?') querystring = path_and_query_list[1] if len( path_and_query_list) > 1 else '' request_path = re.sub(r"\?.*", "", request_path) init_done = False log("GET REQUEST: %s" % self.path) if request_path.lower() == "brplay": (url, proxy, maxbitrate) = self.decode_url(querystring) if not g_downloader.init(self.wfile, url, proxy, g_stopEvent, maxbitrate): print 'cannot init' raise Exception( 'HLS.url failed to play\nServer down? check Url.') log("GET REQUEST Content-Type: %s" % g_downloader.MAIN_MIME_TYPE) self.send_response(200) self.send_header("Content-Type", g_downloader.MAIN_MIME_TYPE) self.end_headers() init_done = True g_downloader.keep_sending_video(self.wfile) else: is_playlist = request_path.endswith( '.m3u8') and not request_path.endswith('.srt.m3u8') is_media = request_path.endswith('.ts') self.send_response(200) mime_type = PLAYLIST_MIME_TYPE if is_playlist else VIDEO_MIME_TYPE if is_media else 'application/octet-stream' log("GET REQUEST Content-Type: %s" % mime_type) self.send_header("Content-Type", mime_type) self.end_headers() init_done = True if is_playlist: log("GET REQUEST MEDIA PLAYLIST") base_uri = 'http://%s:%s' % (HOST_NAME, PORT_NUMBER) g_downloader.download_segment_playlist( path_and_query, base_uri, self.wfile) elif is_media: log("GET REQUEST MEDIA DATA") g_downloader.download_segment_media( path_and_query, self.wfile) else: log("GET REQUEST BINARY DATA") g_downloader.download_binary(path_and_query, self.wfile) except Exception as inst: # Print out a stack trace traceback.print_exc() if not init_done: xbmc.executebuiltin( "XBMC.Notification(BRPlayProxy,%s,4000,'')" % inst.message) self.send_error(404) print 'closed' finally: log("REQUEST COMPLETED") try: self.finish() log("REQUEST FINISHED CALLED SUCCESSFULLY") except Exception, e: control.log("PROXYHANDLER ERROR: %s " % e.message)
def onPlayBackStarted(self): # Will be called when xbmc starts playing a file control.log("Playback has started!") if self.offset > 0: self.seekTime(float(self.offset))
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') 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...")
def playlive(self, id, meta): if id is None: return info = self.__get_video_info(id) if not info or 'channel' not in info: return if 'encrypted' in info and info['encrypted'] == 'true': control.infoDialog(message=control.lang(34103).encode('utf-8'), icon='Wr') return title = info['channel'] signed_hashes = util.get_signed_hashes(info['hash']) query_string = re.sub(r'{{(\w*)}}', r'%(\1)s', info['query_string_template']) query_string = query_string % { 'hash': signed_hashes[0], 'key': 'app', 'openClosed': 'F' if info['subscriber_only'] else 'A', 'user': info['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' self.url, mime_type, stopEvent = hlshelper.pick_bandwidth(url) 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)) 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) if mime_type: item.setMimeType(mime_type) item.setContentLookup(False) item.setProperty('inputstream.adaptive.manifest_type', 'hls') item.setProperty('inputstreamaddon', 'inputstream.adaptive') 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 last_time = 0.0 while not self.stopPlayingEvent.isSet(): if control.monitor.abortRequested(): control.log("Abort requested") break if self.isPlaying() and 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...")
def onPlayBackEnded(self): # Will be called when xbmc stops playing a file control.log("setting event in onPlayBackEnded ")
def update(self, query=None, info="true"): if not query == None: control.idle() try: items = [] season, episode = [], [] show = [os.path.join(self.library_folder, i) for i in control.listDir(self.library_folder)[0]] for s in show: try: season += [os.path.join(s, i) for i in control.listDir(s)[0]] except: pass for s in season: try: episode.append([os.path.join(s, i) for i in control.listDir(s)[1] if i.endswith(".strm")][-1]) except: pass for file in episode: try: file = control.openFile(file) read = file.read() read = read.encode("utf-8") file.close() if not read.startswith(sys.argv[0]): raise Exception() params = dict(urlparse.parse_qsl(read.replace("?", ""))) try: tvshowtitle = params["tvshowtitle"] except: tvshowtitle = None try: tvshowtitle = params["show"] except: pass if tvshowtitle == None or tvshowtitle == "": raise Exception() year, imdb, tvdb = params["year"], params["imdb"], params["tvdb"] imdb = "tt" + re.sub("[^0-9]", "", str(imdb)) try: tmdb = params["tmdb"] except: tmdb = "0" try: tvrage = params["tvrage"] except: tvrage = "0" items.append( { "tvshowtitle": tvshowtitle, "year": year, "imdb": imdb, "tmdb": tmdb, "tvdb": tvdb, "tvrage": tvrage, } ) except: pass items = [i for x, i in enumerate(items) if i not in items[x + 1 :]] if len(items) == 0: raise Exception() except: return try: lib = control.jsonrpc( '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": {"properties" : ["imdbnumber", "title", "year"]}, "id": 1}' ) lib = unicode(lib, "utf-8", errors="ignore") lib = json.loads(lib)["result"]["tvshows"] except: return if ( info == "true" and not control.condVisibility("Window.IsVisible(infodialog)") and not control.condVisibility("Player.HasVideo") ): control.infoDialog(control.lang(30422).encode("utf-8"), time=10000000) self.infoDialog = True try: control.makeFile(control.dataPath) dbcon = database.connect(control.libcacheFile) dbcur = dbcon.cursor() dbcur.execute("CREATE TABLE IF NOT EXISTS tvshows (" "id TEXT, " "items TEXT, " "UNIQUE(id)" ");") except: return try: from resources.lib.indexers import episodes except: return for item in items: it = None if xbmc.abortRequested == True: return sys.exit() try: dbcur.execute("SELECT * FROM tvshows WHERE id = '%s'" % item["tvdb"]) fetch = dbcur.fetchone() it = eval(fetch[1].encode("utf-8")) except: pass try: if not it == None: raise Exception() it = episodes.episodes().get( item["tvshowtitle"], item["year"], item["imdb"], item["tmdb"], item["tvdb"], item["tvrage"], idx=False, ) status = it[0]["status"].lower() it = [ { "name": i["name"], "title": i["title"], "year": i["year"], "imdb": i["imdb"], "tmdb": i["tmdb"], "tvdb": i["tvdb"], "tvrage": i["tvrage"], "season": i["season"], "episode": i["episode"], "tvshowtitle": i["tvshowtitle"], "alter": i["alter"], "date": i["premiered"], } for i in it ] if status == "continuing": raise Exception() dbcur.execute("INSERT INTO tvshows Values (?, ?)", (item["tvdb"], repr(it))) dbcon.commit() except: pass try: id = [item["imdb"], item["tvdb"]] if not item["tmdb"] == "0": id += [item["tmdb"]] ep = [ x["title"].encode("utf-8") for x in lib if str(x["imdbnumber"]) in id or (x["title"].encode("utf-8") == item["tvshowtitle"] and str(x["year"]) == item["year"]) ][0] ep = control.jsonrpc( '{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"filter":{"and": [{"field": "tvshow", "operator": "is", "value": "%s"}]}, "properties": ["season", "episode"]}, "id": 1}' % ep ) ep = unicode(ep, "utf-8", errors="ignore") ep = json.loads(ep)["result"]["episodes"][-1] num = [ x for x, y in enumerate(it) if str(y["season"]) == str(ep["season"]) and str(y["episode"]) == str(ep["episode"]) ][-1] it = [y for x, y in enumerate(it) if x > num] if len(it) == 0: continue except: continue for i in it: try: if xbmc.abortRequested == True: return sys.exit() if int(self.date) <= int(re.sub("[^0-9]", "", str(i["date"]))): from resources.lib.sources import sources src = sources().checkSources( i["name"], i["title"], i["year"], i["imdb"], i["tmdb"], i["tvdb"], i["tvrage"], i["season"], i["episode"], i["tvshowtitle"], i["alter"], i["date"], ) control.log("### SOURCES SRC 10 %s | %s" % (src, i["name"])) if src == False: raise Exception() libtvshows().strmFile(i) except: pass if self.infoDialog == True: control.infoDialog(control.lang(30423).encode("utf-8"), time=1) if self.library_setting == "true" and not control.condVisibility("Library.IsScanningVideo"): control.execute("UpdateLibrary(video)")