diff --git a/channels/discoveryplus.py b/channels/discoveryplus.py index 9f735cd9..abe3ffd1 100644 --- a/channels/discoveryplus.py +++ b/channels/discoveryplus.py @@ -35,7 +35,9 @@ def mainlist(item): def liveDict(): livedict = {} - for key in session.get(api + '/cms/routes/home?decorators=viewingHistory&include=default', headers=headers).json()['included']: + + for key in session.get(api + '/cms/routes/canali?decorators=viewingHistory&include=default', headers=headers).json()['included']: + if key['type'] == 'channel' and key.get('attributes',{}).get('hasLiveStream', '') and 'Free' in key.get('attributes',{}).get('packages', []): title = key['attributes']['name'] livedict[title] = {} diff --git a/channels/mediasetplay.json b/channels/mediasetplay.json index 660a0a7b..c482bf94 100644 --- a/channels/mediasetplay.json +++ b/channels/mediasetplay.json @@ -8,6 +8,14 @@ "categories": ["movie", "tvshow", "documentary", "live"], "not_active": ["include_in_newest"], "default_off": ["include_in_global_search"], - "settings": [], - "cloudflare": true + "settings": [ + { + "id": "mpd", + "type": "bool", + "label": "Preferisci mpd", + "default": true, + "enabled": true, + "visible": true + } + ] } diff --git a/channels/mediasetplay.py b/channels/mediasetplay.py index 1ee3c480..abac9da5 100644 --- a/channels/mediasetplay.py +++ b/channels/mediasetplay.py @@ -2,359 +2,325 @@ # ------------------------------------------------------------ # Canale per Mediaset Play # ------------------------------------------------------------ -from platformcode import logger -import uuid +from time import time +from platformcode import logger, config +import uuid, datetime, xbmc import requests, sys -from core import support -if sys.version_info[0] >= 3: from urllib.parse import urlencode, quote -else: from urllib import urlencode, quote -if sys.version_info[0] >= 3: from concurrent import futures -else: from concurrent_py2 import futures +from core import support, jsontools, tmdb +if sys.version_info[0] >= 3: + from urllib.parse import urlencode, quote + from concurrent import futures +else: + from urllib import urlencode, quote + from concurrent_py2 import futures from collections import OrderedDict -PAGINATION = 4 +host = 'https://www.mediasetplay.mediaset.it' +loginUrl = 'https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v2.0' -host = '' -post_url = '?assetTypes=HD,browser,widevine,geoIT|geoNo:HD,browser,geoIT|geoNo:HD,geoIT|geoNo:SD,browser,widevine,geoIT|geoNo:SD,browser,geoIT|geoNo:SD,geoIT|geoNo&auto=true&balance=true&format=smil&formats=MPEG-DASH,MPEG4,M3U&tracking=true' -deviceid = '61d27df7-5cbf-4419-ba06-cfd27ecd4588' -loginUrl = 'https://api-ott-prod-fe.mediaset.net/PROD/play/idm/anonymous/login/v1.0' -loginData = {"cid": deviceid, "platform": "pc", "appName": "web/mediasetplay-web/d667681"} -lic_url = 'https://widevine.entitlement.theplatform.eu/wv/web/ModularDrm/getRawWidevineLicense?releasePid=%s&account=http://access.auth.theplatform.com/data/Account/2702976343&schema=1.0&token={token}|Accept=*/*&Content-Type=&User-Agent=' + support.httptools.get_user_agent() + '|R{{SSM}}|' -entry = 'https://api.one.accedo.tv/content/entry/{id}?locale=it' -entries = 'https://api.one.accedo.tv/content/entries?id={id}&locale=it' +clientid = 'f66e2a01-c619-4e53-8e7c-4761449dd8ee' + + +loginData = {"client_id": clientid, "platform": "pc", "appName": "web//mediasetplay-web/5.1.493-plus-da8885b"} sessionUrl = "https://api.one.accedo.tv/session?appKey=59ad346f1de1c4000dfd09c5&uuid={uuid}&gid=default" -current_session = requests.Session() -current_session.headers.update({'Content-Type': 'application/json', 'User-Agent': support.httptools.get_user_agent(), 'Referer': support.config.get_channel_url()}) +session = requests.Session() +session.headers.update({'Content-Type': 'application/json', 'User-Agent': support.httptools.get_user_agent(), 'Referer': host}) + +entry = 'https://api.one.accedo.tv/content/entry/{id}?locale=it' +entries = 'https://api.one.accedo.tv/content/entries?id={id}&locale=it' # login anonimo -res = current_session.post(loginUrl, json=loginData, verify=False) -Token = res.headers['t-cts'] -current_session.headers.update({'t-apigw': res.headers['t-apigw'], 't-cts': Token}) -lic_url = lic_url.format(token=Token) -tracecid = res.json()['response']['traceCid'] -cwid = res.json()['response']['cwId'] +# support.dbg() +res = session.post(loginUrl, json=loginData, verify=False) +Token = res.json()['response']['beToken'] +sid = res.json()['response']['sid'] +session.headers.update({'authorization': 'Bearer ' + Token}) # sessione -res = current_session.get(sessionUrl.format(uuid=str(uuid.uuid4())), verify=False) -current_session.headers.update({'x-session': res.json()['sessionKey']}) - -cdict = {'CWFILMTOPVIEWED':'filmPiuVisti24H', - 'CWFILMCOMEDY':'filmCommedia', - 'CWFILMACTION':'filmAzioneThrillerAvventura', - 'CWFILMDRAMATIC':'filmDrammatico', - 'CWFILMSENTIMENTAL':'filmSentimentale', - 'CWFILMCLASSIC':'filmClassici', - 'personToContentFilm':'personToContentFilm', - 'CWHOMEFICTIONNOWELITE':'stagioniFictionSerieTvSezione', - 'CWFICTIONSOAP':'mostRecentSoapOpera', - 'CWFICTIONDRAMATIC':'stagioniFictionDrammatico', - 'CWFICTIONPOLICE':'stagioniFictionPoliziesco', - 'CWFICTIONCOMEDY':'stagioniFictionCommedia', - 'CWFICTIONSITCOM':'stagioniFictionSitCom', - 'CWFICTIONSENTIMENTAL':'stagioniFictionSentimentale', - 'CWFICTIONBIOGRAPHICAL':'stagioniFictionBiografico', - 'CWPROGTVPRIME':'stagioniPrimaSerata', - 'CWPROGTVDAY':'stagioniDaytime', - 'CWPROGTVTOPVIEWED':'programmiTvClip24H', - 'CWPROGTVTALENT':'stagioniReality', - 'CWPROGTVVARIETY':'stagioniVarieta', - 'CWPROGTVTALK':'stagioniTalk', - 'CWPROGTVTG':'mostRecentTg', - 'CWPROGTVSPORT':'mostRecentSport', - 'CWPROGTVMAGAZINE':'stagioniCucinaLifestyle', - 'CWDOCUMOSTRECENT':'mostRecentDocumentariFep', - 'CWDOCUTOPVIEWED':'stagioniDocumentari', - 'CWDOCUSPAZIO':'documentariSpazio', - 'CWDOCUNATURANIMALI':'documentariNatura', - 'CWDOCUSCIENZATECH':'documentariScienza', - 'CWDOCUBIOSTORIE':'documentariBioStoria', - 'CWDOCUINCHIESTE':'documentariInchiesta', - 'CWFILMDOCU':'filmDocumentario', - 'CWKIDSBOINGFORYOU':'kidsBoing', - 'CWKIDSCARTOONITO':'kidsCartoonito', - 'CWKIDSMEDIASETBRAND':'kidsMediaset', - 'CWENABLERKIDS':'stagioniKids'} +sessionKey = session.get(sessionUrl.format(uuid=str(uuid.uuid4())), verify=False).json()['sessionKey'] +session.headers.update({'x-session': sessionKey}) @support.menu def mainlist(item): - top = [('Dirette {bold}', ['https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-stations?sort=ShortTitle', 'live'])] + top = [('Dirette {bold}', ['', 'live'])] - menu = [('Film {bullet bold}', ['5acfcbc423eec6000d64a6bb', 'menu', ['Tutti','all','searchMovie']]), - ('Fiction / Serie TV {bullet bold}', ['5acfcb3c23eec6000d64a6a4', 'menu', ['Tutte','all','searchStagioni'], 'tvshow']), - ('Programmi TV{ bullet bold}', ['5acfc8011de1c4000b6ec953', 'menu', ['Tutti','all','searchStagioni'], 'tvshow']), - ('Documentari {bullet bold}', ['5bfd17c423eec6001aec49f9', 'menu', ['Tutti','all',''], 'undefined']), - ('Kids {bullet bold}', ['5acfcb8323eec6000d64a6b3', 'menu',['Tutti','all',''], 'undefined']), - ('Family {bullet bold}', ['5e662d01a0e845001d56875b', 'menu',['Tutti','all',''], 'undefined']), - ] + menu = [('Fiction / Serie TV {bullet bold}', ['/fiction', 'menu', '5acfcb3c23eec6000d64a6a4', 'tvshow']), + ('Programmi TV{ bullet bold}', ['/programmitv', 'menu', '5acfc8011de1c4000b6ec953', 'tvshow']), + ('Documentari {bullet bold}', ['/documentari', 'menu', '5bfd17c423eec6001aec49f9', 'undefined']), + ('Kids {bullet bold}', ['/kids', 'menu', '5acfcb8323eec6000d64a6b3', 'undefined'])] search = '' return locals() +def menu(item): + logger.debug() + itemlist = [] + res = get_from_id(item) + for it in res: + logger.debug(jsontools.dump(it)) + if 'uxReference' in it: + itemlist.append(item.clone(title=support.typo(it['title'], 'bullet bold'), + url= it['landingUrl'], + feed = it.get('feedurlV2',''), + ref=it.get('uxReferenceV2', ''), + params=it.get('uxReferenceV2Params', ''), + args='', + action='peliculas')) + return itemlist + + +def live(item): + itemlist = [] + + res = session.get('https://static3.mediasetplay.mediaset.it/apigw/nownext/nownext.json').json()['response'] + allguide = res['listings'] + stations = res['stations'] + + for it in stations.values(): + plot = '' + title = it['title'] + url = 'https:' + it['mediasetstation$pageUrl'] + if 'plus' in title.lower() or 'premium' in title.lower(): continue + if it['callSign'] in allguide: + urls = [] + guide = allguide[it['callSign']] + plot = '[B]{}[/B]\n{}\n\nA Seguire:\n[B]{}[/B]\n{}'.format(guide['currentListing']['mediasetlisting$epgTitle'], + guide['currentListing']['description'], + guide['nextListing']['mediasetlisting$epgTitle'], + guide['nextListing']['description'],) + + itemlist.append(item.clone(title=support.typo(title, 'bold'), fulltitle=title, urls=guide['tuningInstruction']['urn:theplatform:tv:location:any'], plot=plot, url=url, action='play', forcethumb=True)) + + itemlist.sort(key=lambda it: support.channels_order.get(it.fulltitle, 999)) + support.thumb(itemlist, live=True) + return itemlist + def search(item, text): - itemlist = [] - logger.debug(text) - item.search = text + item.ref = 'main' + item.query = text + item.params = 'channel≈' try: - itemlist = peliculas(item) + return peliculas(item) + # Continua la ricerca in caso di errore except: import sys for line in sys.exc_info(): support.logger.error("%s" % line) - - return itemlist - - -def menu(item): - logger.debug() - itemlist = [] - if item.url: - json = get_from_id(item) - for it in json: - if 'uxReference' in it: itemlist.append( - item.clone(title=support.typo(it['title'], 'bullet bold'), url= it['landingUrl'], ref=it['uxReference'], args='', action='peliculas')) - return itemlist - - -def liveDict(): - livedict = OrderedDict({}) - json = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-stations?sort=ShortTitle').json()['entries'] - for it in json: - urls = [] - if it.get('tuningInstruction') and not it.get('mediasetstation$digitalOnly'): - guide=current_session.get('https://static3.mediasetplay.mediaset.it/apigw/nownext/' + it['callSign'] + '.json').json()['response'] - for key in it['tuningInstruction']['urn:theplatform:tv:location:any']: - urls += key['publicUrls'] - title = it['title'] - livedict[title] = {} - livedict[title]['urls'] = urls - livedict[title]['plot'] = support.typo(guide['currentListing']['mediasetlisting$epgTitle'],'bold') + '\n' + guide['currentListing']['mediasetlisting$shortDescription'] + '\n' + guide['currentListing']['description'] + '\n\n' + support.typo('A Seguire:' + guide['nextListing']['mediasetlisting$epgTitle'], 'bold') - return livedict - - -def live(item): - logger.debug() - itemlist = [] - for key, value in liveDict().items(): - itemlist.append(item.clone(title=support.typo(key, 'bold'), - fulltitle=key, - show=key, - contentTitle=key, - forcethumb=True, - urls=value['urls'], - plot=value['plot'], - action='play', - no_return=True)) - return support.thumb(itemlist, live=True) + return [] def peliculas(item): - logger.debug() itemlist = [] - titlelist = [] - contentType = '' - if item.text: - json = [] - itlist = [] - with futures.ThreadPoolExecutor() as executor: - for arg in ['searchMovie', 'searchStagioni', 'searchClip']: - item.args = ['', 'search', arg] - itlist += [executor.submit(get_programs, item)] - for res in futures.as_completed(itlist): - json += res.result() - else: - json = get_programs(item) - for it in json: - if item.search.lower() in it['title'].lower() and it['title'] not in titlelist: - titlelist.append(it['title']) - if 'media' in it: - action = 'findvideos' - contentType = 'movie' - urls = [] - for key in it['media']: - urls.append(key['publicUrl']) + res = get_programs(item) + video_id= '' + for it in res['items']: + thumb = '' + fanart = '' + contentSerieName = '' + url = 'https:'+ it.get('mediasettvseason$pageUrl', it.get('mediasetprogram$videoPageUrl', it.get('mediasetprogram$pageUrl'))) + title = it.get('mediasetprogram$brandTitle', it.get('title')) + title2 = it['title'] + if title != title2: + title = '{} - {}'.format(title, title2) + plot = it.get('longDescription', it.get('description', it.get('mediasettvseason$brandDescription', ''))) + + if it.get('seriesTitle'): + contentSerieName = it['seriesTitle'] + contentType = 'tvshow' + action = 'epmenu' + else: + contentType = 'movie' + video_id = it['guid'] + action = 'play' + for k, v in it['thumbnails'].items(): + if 'image_vertical' in k and not thumb: + thumb = v['url'].replace('.jpg', '@3.jpg') + if 'image_header_poster' in k and not fanart: + fanart = v['url'].replace('.jpg', '@3.jpg') + if thumb and fanart: + break + + itemlist.append(item.clone(title=support.typo(title, 'bold'), + fulltitle=title, + contentTitle=title, + contentSerieName=contentSerieName, + action=action, + contentType=contentType, + thumbnail=thumb, + fanart=fanart, + plot=plot, + url=url, + video_id=video_id, + seriesid = it.get('id',''), + forcethumb=True)) + if res['next']: + item.page = res['next'] + support.nextPage(itemlist, item) - else: - action = 'epmenu' - contentType = 'tvshow' - urls = it['mediasetprogram$brandId'] - if urls: - title = it['mediasetprogram$brandTitle'] + ' - ' if 'mediasetprogram$brandTitle' in it and it['mediasetprogram$brandTitle'] != it['title'] else '' - itemlist.append( - item.clone(channel=item.channel, - action=action, - title=support.typo(title + it['title'], 'bold'), - fulltitle=it['title'], - show=it['title'], - contentType=contentType if contentType else item.contentType, - contentTitle=it['title'] if 'movie' in [contentType, item.contentType] else '', - contentSerieName=it['title'] if 'tvshow' in [contentType, item.contentType] else '', - thumbnail=it['thumbnails']['image_vertical-264x396']['url'] if 'image_vertical-264x396' in it['thumbnails'] else '', - fanart=it['thumbnails']['image_keyframe_poster-1280x720']['url'] if 'image_keyframe_poster-1280x720' in it['thumbnails'] else '', - plot=it['longDescription'] if 'longDescription' in it else it['description'] if 'description' in it else '', - urls=urls, - seriesid = it.get('seriesId',''), - url=it['mediasetprogram$pageUrl'], - forcethumb=True, - no_return=True)) return itemlist - def epmenu(item): logger.debug() itemlist = [] if item.seriesid: - seasons = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-tv-seasons?bySeriesId=' + item.seriesid).json()['entries'] - for season in seasons: - if 'mediasettvseason$brandId' in season and 'mediasettvseason$displaySeason' in season: - itemlist.append( - item.clone(seriesid = '', - title=support.typo(season['mediasettvseason$displaySeason'], 'bold'), - urls=season['mediasettvseason$brandId'])) + res = requests.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-subbrands-v2?byTvSeasonId={}&sort=mediasetprogram$order'.format(item.seriesid)).json()['entries'] + for it in res: + itemlist.append( + item.clone(seriesid = '', + title=support.typo(it['description'], 'bold'), + subbrand=it['mediasetprogram$subBrandId'], + action='episodios')) itemlist = sorted(itemlist, key=lambda it: it.title, reverse=True) - if len(itemlist) == 1: return epmenu(itemlist[0]) - if not itemlist: - entries = current_session.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-brands?byCustomValue={brandId}{' + item.urls + '}').json()['entries'] - for entry in entries: - if 'mediasetprogram$subBrandId' in entry: - itemlist.append( - item.clone(action='episodios', - title=support.typo(entry['description'], 'bold'), - url=entry['mediasetprogram$subBrandId'], - order=entry.get('mediasetprogram$order',0))) if len(itemlist) == 1: return episodios(itemlist[0]) - itemlist = sorted(itemlist, key=lambda it: it.order) - return itemlist + return itemlist def episodios(item): - logger.debug() itemlist = [] - if not item.nextIndex: item.nextIndex = 1 + res = requests.get('https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-programs-v2?byCustomValue={subBrandId}{' + item.subbrand +'}&sort=:publishInfo_lastPublished|asc,tvSeasonEpisodeNumber').json()['entries'] - url = 'https://feed.entertainment.tv.theplatform.eu/f/PR1GhC/mediaset-prod-all-programs?byCustomValue={subBrandId}{'+ item.url + '}&range=' + str(item.nextIndex) + '-' + str(item.nextIndex + PAGINATION) - json = current_session.get(url).json()['entries'] + for it in res: + thumb = '' + title = '' + season = it.get('tvSeasonNumber','') + episode = it.get('tvSeasonEpisodeNumber','') - for it in json: - urls = [] - if 'media' in it: - for key in it['media']: - urls.append(key['publicUrl']) - if urls: - title = it['title'] - itemlist.append( - item.clone(action='findvideos', - title=support.typo(title, 'bold'), - contentType='episode', - thumbnail=it['thumbnails']['image_vertical-264x396']['url'] if 'image_vertical-264x396' in it['thumbnails'] else '', - fanart=it['thumbnails']['image_keyframe_poster-1280x720']['url'] if 'image_keyframe_poster-1280x720' in it['thumbnails'] else '', - plot=it['longDescription'] if 'longDescription' in it else it['description'], - urls=urls, - url=it['mediasetprogram$pageUrl'], - year=it.get('year',''), - ep= it.get('tvSeasonEpisodeNumber', 0) if it.get('tvSeasonEpisodeNumber', 0) else 0, - forcethumb=True, - no_return=True)) + ep_title = it['title'] + if season and episode: + title = '{}x{:02d} - {}'.format(season, episode, ep_title) + elif episode: + title = '{:02d} - {}'.format(episode, ep_title) + else: + title = ep_title + for k, v in it['thumbnails'].items(): + if 'image_keyframe' in k and not thumb: + thumb = v['url'].replace('.jpg', '@3.jpg') + break + if not thumb: thumb = item.thumbnail - if len(itemlist) == 1: return findvideos(itemlist[0]) + itemlist.append(item.clone(title=title, + contentSeason = season, + contentEpisodeNumber = episode, + thumbnail=thumb, + forcethumb=True, + contentType='episode', + action='play', + video_id=it['guid'])) - if (len(json) >= PAGINATION): - item.nextIndex += PAGINATION + 1 - support.nextPage(itemlist, item) + itemlist.sort(key=lambda it: (it.contentSeson, it.contentEpisodeNumber)) return itemlist -def findvideos(item): - logger.debug() - itemlist = [item.clone(server='directo', title='Mediaset Play', urls=item.urls, action='play')] - return support.server(item, itemlist=itemlist, Download=False) - - def play(item): logger.debug() - for url in item.urls: - sec_data = support.match(url + post_url).data + item.no_return=True + mpd = config.get_setting('mpd', item.channel) + post = {format} + + lic_url = 'https://widevine.entitlement.theplatform.eu/wv/web/ModularDrm/getRawWidevineLicense?releasePid={pid}&account=http://access.auth.theplatform.com/data/Account/2702976343&schema=1.0&token={token}|Accept=*/*&Content-Type=&User-Agent={ua}|R{{SSM}}|' + url = '' + + if item.video_id: + payload = '{"contentId":"' + item.video_id + ' ","streamType":"VOD","delivery":"Streaming","createDevice":true}' + res = session.post('https://api-ott-prod-fe.mediaset.net/PROD/play/playback/check/v2.0?sid=' + sid, data=payload).json()['response']['mediaSelector'] + url = res['url'] + Formats = res['formats'] + Format = res['format'] + mpd = True if 'dash' in Formats else False + else: + for it in item.urls: + if (mpd and it['format'] == 'application/dash+xml') or (not mpd and it['format'] == 'application/x-mpegURL'): + try: + url = it['publicUrls'][0] + break + except: + logger.debug('No url find for', 'mpd' if mpd else 'hls') + pass + + if url: + post = {} + post['format'] = Format + post['assetTypes'] = 'HD,browser,widevine,geoIT|geoNo:HD,browser,geoIT|geoNo:HD,geoIT|geoNo:SD,browser,widevine,geoIT|geoNo:SD,browser,geoIT|geoNo:SD,geoIT|geoNo' + if Format == 'SMIL': + post['auth'] = Token + post['formats'] = Formats + + sec_data = support.match(url + '?' + urlencode(post)).data item.url = support.match(sec_data, patron=r'