diff --git a/addon.xml b/addon.xml index caee771..b37f66f 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ diff --git a/resources/lib/movistar.py b/resources/lib/movistar.py index 96546c8..c509aad 100644 --- a/resources/lib/movistar.py +++ b/resources/lib/movistar.py @@ -454,6 +454,8 @@ class Movistar(object): if 'TituloHorLinea2' in p: pr['desc2'] = p['TituloHorLinea2'] pr['show_id'] = p['ShowId'] + if 'SerialId' in p: + pr['serie_id'] = p['SerialId'] pr['id'] = p['Id'] #if 'links' in p: pr['links'] = p['links'] epg[id].append(pr) @@ -566,12 +568,12 @@ class Movistar(object): t['stream_type'] = 'tv' t['info']['mediatype'] = 'movie' t['channel_name'] = c['Nombre'].strip() - t['info']['title'] = str(c['Dial']) +'. ' + t['channel_name'] + t['info']['title'] = str(c.get('Dial', '0')) +'. ' + t['channel_name'] t['id'] = c['CodCadenaTv'] #if add_epg_info: # t['desc1'] = c['Nombre'] # t['desc2'] = '' - t['dial'] = c['Dial'] + t['dial'] = c.get('Dial', '0') t['url'] = c['PuntoReproduccion'] if 'Logo' in c: t['art']['icon'] = t['art']['thumb'] = t['art']['poster'] = c['Logo'] @@ -648,6 +650,7 @@ class Movistar(object): deviceType='webplayer', DIGITALPLUSUSERIDC=self.account['encoded_user'], PROFILE=self.account['platform'], ACCOUNTNUMBER=self.account['id'], idsOnly='false', start=1, end=30, mdrm='true', demarcation=self.account['demarcation']) #url += '&filter=AD-SINX&topic=CN' + if self.quality == 'UHD': url += '&filterQuality=UHD' url += '&_='+ str(int(time.time()*1000)) return url @@ -942,6 +945,20 @@ class Movistar(object): except: return None + def order_recording_season(self, season_id): + headers = self.net.headers.copy() + headers['Content-Type'] = 'application/json' + headers['X-Hzid'] = self.account['session_token'] + url = self.endpoints['grabartemporada'] + data = '{"tvSeasonID":"' + str(season_id) +'"}' + response = self.net.session.post(url, data=data, headers=headers) + content = response.content.decode('utf-8') + try: + data = json.loads(content) + return data + except: + return None + def delete_recording(self, program_id): headers = self.net.headers.copy() headers['Content-Type'] = 'application/json' @@ -974,6 +991,8 @@ class Movistar(object): t['url'] = '' t['id'] = p['id'] t['show_id'] = p['show_id'] + if 'serie_id' in p: + t['serie_id'] = p['serie_id'] t['session_request'] = '{"contentID":' + str(t['id']) +',"streamType":"CUTV"}' t['info']['playcount'] = 1 # Set as watched t['start'] = p['start'] @@ -1024,8 +1043,9 @@ class Movistar(object): return res def get_vod_list_url(self, cat='movies'): - #sort = 'FD' + #sort = 'FE' sort = 'MA' + #sort = 'AZ' url = self.endpoints['consultar'].format(deviceType='webplayer', profile=self.account['platform'], sort=sort, start=1, end=50, mdrm='true', demarcation=self.account['demarcation']) filter = '&filter=AC-OM,AC-MA,MA-GBLCICLO59,TD-CUP,RG-SINCAT,AC-PREPUB,' + self.entitlements['suscripcion'] #filter = '&filter=AC-OM,AC-MA,MA-GBLCICLO59,TD-CUP,RG-SINCAT,AC-PREPUB' @@ -1042,6 +1062,79 @@ class Movistar(object): #LOG('vod url: {}'.format(url)) return url + def get_vod_sections(self): + from collections import OrderedDict + + profile = self.account['platform'] + #profile = 'OTT' + #profile = 'LITE' + + content = self.cache.load('vod_sections.json') + if content: + data = json.loads(content) + else: + url = 'https://apps.dof6.com/feed/conf.php?id=justconfig&id_perfil={}&dispositivo=cell'.format(profile) + data = self.net.load_data(url) + self.cache.save_file('vod_sections.json', json.dumps(data, ensure_ascii=False)) + + submenu = data.get('YOMVIANDROID', {}).get('Menu', {}).get('Submenu', []) + res = OrderedDict() + for o in submenu: + #print_json(o) + menu = {} + menu['visible'] = (o.get('@visible') != 'false') + menu['id'] = o.get('@id') + + if 'Modulo' in o: + section_name = o['@nombre'] if '@nombre' in o else o['@P'] + modulo = o['Modulo'] + + section = [] + + if isinstance(modulo, dict): + modulo = [modulo] + + if isinstance(modulo, list): + for m in modulo: + if 'consulta' in m and m['consulta'].get('@endpoint_ref', '') == 'consultar': + if not '@nombre' in m: continue + #print (menu['id'], m['@nombre']) + c = {} + c['name'] = m['@nombre'] + pars = '' + sort = '' + + parametros = m['consulta']['parametro'] + if isinstance(parametros, dict): + parametros = [parametros] + + for par in parametros: + #print_json(par) + if par.get('@incluir', '') == 'true': + pars += '&{}={}'.format(par['@id'], par['@value']) + if par['@id'] == 'sort': + sort = par['@value'] + + pars = pars.replace('{suscripcion}', self.entitlements['suscripcion']) + c['url'] = self.endpoints['consultar'].format(deviceType='webplayer', profile=profile, sort=sort, start=1, end=50, mdrm='true', demarcation=self.account['demarcation']) + c['url'] += pars + if self.quality == 'UHD': c['url'] += '&filterQuality=UHD' + section.append(c) + if len(section) > 0: + menu['name'] = section_name + menu['data'] = section + res[menu['id']] = menu + + if 'portada_cine_destacados' in res: + res['portada_cine_destacados']['visible'] = True + res['portada_cine_destacados']['name'] = 'Cine - Géneros' + + if 'portada_series_destacados' in res: + res['portada_series_destacados']['visible'] = True + res['portada_series_destacados']['name'] = 'Series - Géneros' + + return res + def install_key_file(self, filename): import shutil if sys.version_info[0] > 2: @@ -1069,7 +1162,7 @@ class Movistar(object): self.cache.save_file('auth.key', json.dumps(data, ensure_ascii=False)) def delete_session_files(self): - for f in ['access_token.conf', 'account.json', 'device_id.conf', 'devices.json', 'profile_id.conf', 'tokens.json', 'channels2.json', 'epg2.json']: + for f in ['access_token.conf', 'account.json', 'device_id.conf', 'devices.json', 'profile_id.conf', 'tokens.json', 'channels2.json', 'channels_UHD.json', 'channels_HD.json', 'epg2.json', 'epg_UHD.json', 'epg_HD.json']: self.cache.remove_file(f) def get_profile_image_url(self, img_id): @@ -1215,3 +1308,16 @@ class Movistar(object): with io.open(filename, 'w', encoding='utf-8', newline='') as handle: handle.write(''.join(res)) + def save_credentials(self, username, password): + from .b64 import encode_base64 + data = {'username': username, 'password': encode_base64(password)} + self.cache.save_file('credentials.json', json.dumps(data, ensure_ascii=False)) + + def load_credentials(self): + from .b64 import decode_base64 + content = self.cache.load_file('credentials.json') + if content: + data = json.loads(content) + return data['username'], decode_base64(data['password']) + else: + return '', '' diff --git a/resources/lib/plugin.py b/resources/lib/plugin.py index b58f327..587a8a4 100644 --- a/resources/lib/plugin.py +++ b/resources/lib/plugin.py @@ -298,16 +298,26 @@ def add_videos(category, ctype, videos, ref=None, url_next=None, url_prev=None, list_item.setInfo('video', t['info']) list_item.setArt(t['art']) - if t.get('stream_type') == 'u7d' and 'show_id' in t and not t.get('aired', False): - record_program_action = (addon.getLocalizedString(30171), "RunPlugin(" + get_url(action='add_recording', id=t['show_id']) + ")") - list_item.addContextMenuItems([record_program_action]) + actions = [] + if t.get('stream_type') == 'u7d': + LOG(t) + if 'show_id' in t and not t.get('aired', False): + record_program_action = (addon.getLocalizedString(30171), "RunPlugin(" + get_url(action='add_recording', id=t['show_id']) + ")") + actions.append(record_program_action) + if 'serie_id' in t: + record_season_action = (addon.getLocalizedString(30169), "RunPlugin(" + get_url(action='add_recording_season', id=t['serie_id']) + ")") + actions.append(record_season_action) if 'rec' in t: action = get_url(action='delete_recording', id=t['rec']['id'], name=t['rec']['name']) - list_item.addContextMenuItems([(addon.getLocalizedString(30173), "RunPlugin(" + action + ")")]) + actions.append((addon.getLocalizedString(30173), "RunPlugin(" + action + ")")) if wishlist_action: - list_item.addContextMenuItems([wishlist_action]) + actions.append(wishlist_action) + + if len(actions) > 0: + LOG(actions) + list_item.addContextMenuItems(actions) url = get_url(action='play', id=t['id'], url=t['url'], session_request=t['session_request'], stype=t['stream_type']) if 'show_id' in t: url += '&show_id={}'.format(t['show_id']) @@ -440,7 +450,7 @@ def listing_hz(name, url, from_wishlist=False): url_prev = data['prev']['href'] if isinstance(data['next'], dict) and 'prev' in data['next'] else None add_videos(name, 'movies', l, url_next=url_next, url_prev=url_prev, ref='listing_hz', from_wishlist=from_wishlist) -def list_vod(): +def list_vod0(): open_folder(addon.getLocalizedString(30111)) # VOD name = addon.getLocalizedString(30105).encode('utf-8') add_menu_option(name, get_url(action='listing', name=name, url=m.get_vod_list_url(cat='movies'))) # Movies @@ -453,6 +463,31 @@ def list_vod(): name = addon.getLocalizedString(30121).encode('utf-8') add_menu_option(name, get_url(action='listing', name=name, url=m.get_vod_list_url(cat='kids'))) # Kids + + sections = m.get_vod_sections() + + close_folder() + +def list_vod(): + open_folder(addon.getLocalizedString(30111)) # VOD + + sections = m.get_vod_sections() + for key, s in sections.items(): + if not s['visible']: continue + name = s['name'].encode('utf-8') + add_menu_option(name, get_url(action='list_section', name=name, key=key)) + + close_folder() + +def list_section(key): + open_folder(addon.getLocalizedString(30111)) # VOD + + sections = m.get_vod_sections() + items = sections[key]['data'] + for item in items: + name = item['name'].encode('utf-8') + add_menu_option(name, get_url(action='listing', name=name, url=item['url'])) + close_folder() def search(params): @@ -494,6 +529,13 @@ def order_recording(program_id): else: show_notification(addon.getLocalizedString(30172), xbmcgui.NOTIFICATION_INFO) +def order_recording_season(season_id): + data = m.order_recording_season(season_id) + if data and 'resultText' in data: + show_notification(data['resultText']) + else: + show_notification(addon.getLocalizedString(30172), xbmcgui.NOTIFICATION_INFO) + def delete_recording(id, name): if sys.version_info[0] < 3: name = name.decode('utf-8') @@ -510,16 +552,24 @@ def logout(): m.cache.remove_file('auth.key') def login(): - def ask_credentials(username=''): + def ask_credentials(username='', password=''): username = input_window(addon.getLocalizedString(30163), username) # Username if username: - password = input_window(addon.getLocalizedString(30164), hidden=True) # Password + password = input_window(addon.getLocalizedString(30164), password, hidden=True) # Password if password: return username, password return None, None - username, password = ask_credentials() + store_credentials = addon.getSettingBool('store_credentials') + if store_credentials: + username, password = m.load_credentials() + else: + username, password = ('', '') + + username, password = ask_credentials(username, password) if username: + if store_credentials: + m.save_credentials(username, password) success, _ = m.login(username, password) if success: clear_session() @@ -627,6 +677,8 @@ def router(paramstring): order_recording(params['id']) elif params['action'] == 'delete_recording': delete_recording(params['id'], params['name']) + elif params['action'] == 'add_recording_season': + order_recording_season(params['id']) elif params['action'] == 'wishlist': # Wishlist listing_hz(addon.getLocalizedString(30102), m.get_wishlist_url(), from_wishlist=True) @@ -643,6 +695,8 @@ def router(paramstring): add_videos(params['name'], 'episodes', m.get_episodes(params['id'])) elif params['action'] == 'vod': list_vod() + elif params['action'] == 'list_section': + list_section(params['key']) elif params['action'] == 'search': search(params) elif params['action'] == 'export_epg_now': diff --git a/resources/settings.xml b/resources/settings.xml index 070f18c..8187c9a 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -1,5 +1,6 @@ +