Version 0.8.0

This commit is contained in:
Paco8 committed 2023-11-29 14:59:08 +01:00
1 parent 2ece393522
commit 983c80965a
4 files changed
+175 -14

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.movistarplus" <addon id="plugin.video.movistarplus"
name="Movistar+" name="Movistar+"
version="0.7.16" version="0.8.0"
provider-name="Paco8"> provider-name="Paco8">
<requires> <requires>
<!--- <import addon="xbmc.python" version="2.25.0"/> --> <!--- <import addon="xbmc.python" version="2.25.0"/> -->
+110 -4
View File
@@ -454,6 +454,8 @@ class Movistar(object):
if 'TituloHorLinea2' in p: if 'TituloHorLinea2' in p:
pr['desc2'] = p['TituloHorLinea2'] pr['desc2'] = p['TituloHorLinea2']
pr['show_id'] = p['ShowId'] pr['show_id'] = p['ShowId']
if 'SerialId' in p:
pr['serie_id'] = p['SerialId']
pr['id'] = p['Id'] pr['id'] = p['Id']
#if 'links' in p: pr['links'] = p['links'] #if 'links' in p: pr['links'] = p['links']
epg[id].append(pr) epg[id].append(pr)
@@ -566,12 +568,12 @@ class Movistar(object):
t['stream_type'] = 'tv' t['stream_type'] = 'tv'
t['info']['mediatype'] = 'movie' t['info']['mediatype'] = 'movie'
t['channel_name'] = c['Nombre'].strip() 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'] t['id'] = c['CodCadenaTv']
#if add_epg_info: #if add_epg_info:
# t['desc1'] = c['Nombre'] # t['desc1'] = c['Nombre']
# t['desc2'] = '' # t['desc2'] = ''
t['dial'] = c['Dial'] t['dial'] = c.get('Dial', '0')
t['url'] = c['PuntoReproduccion'] t['url'] = c['PuntoReproduccion']
if 'Logo' in c: if 'Logo' in c:
t['art']['icon'] = t['art']['thumb'] = t['art']['poster'] = c['Logo'] 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'], 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']) ACCOUNTNUMBER=self.account['id'], idsOnly='false', start=1, end=30, mdrm='true', demarcation=self.account['demarcation'])
#url += '&filter=AD-SINX&topic=CN' #url += '&filter=AD-SINX&topic=CN'
if self.quality == 'UHD': url += '&filterQuality=UHD'
url += '&_='+ str(int(time.time()*1000)) url += '&_='+ str(int(time.time()*1000))
return url return url
@@ -942,6 +945,20 @@ class Movistar(object):
except: except:
return None 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): def delete_recording(self, program_id):
headers = self.net.headers.copy() headers = self.net.headers.copy()
headers['Content-Type'] = 'application/json' headers['Content-Type'] = 'application/json'
@@ -974,6 +991,8 @@ class Movistar(object):
t['url'] = '' t['url'] = ''
t['id'] = p['id'] t['id'] = p['id']
t['show_id'] = p['show_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['session_request'] = '{"contentID":' + str(t['id']) +',"streamType":"CUTV"}'
t['info']['playcount'] = 1 # Set as watched t['info']['playcount'] = 1 # Set as watched
t['start'] = p['start'] t['start'] = p['start']
@@ -1024,8 +1043,9 @@ class Movistar(object):
return res return res
def get_vod_list_url(self, cat='movies'): def get_vod_list_url(self, cat='movies'):
#sort = 'FD' #sort = 'FE'
sort = 'MA' 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']) 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,' + self.entitlements['suscripcion']
#filter = '&filter=AC-OM,AC-MA,MA-GBLCICLO59,TD-CUP,RG-SINCAT,AC-PREPUB' #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)) #LOG('vod url: {}'.format(url))
return 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): def install_key_file(self, filename):
import shutil import shutil
if sys.version_info[0] > 2: 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)) self.cache.save_file('auth.key', json.dumps(data, ensure_ascii=False))
def delete_session_files(self): 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) self.cache.remove_file(f)
def get_profile_image_url(self, img_id): 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: with io.open(filename, 'w', encoding='utf-8', newline='') as handle:
handle.write(''.join(res)) 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 '', ''
+63 -9
View File
@@ -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.setInfo('video', t['info'])
list_item.setArt(t['art']) list_item.setArt(t['art'])
if t.get('stream_type') == 'u7d' and 'show_id' in t and not t.get('aired', False): actions = []
record_program_action = (addon.getLocalizedString(30171), "RunPlugin(" + get_url(action='add_recording', id=t['show_id']) + ")") if t.get('stream_type') == 'u7d':
list_item.addContextMenuItems([record_program_action]) 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: if 'rec' in t:
action = get_url(action='delete_recording', id=t['rec']['id'], name=t['rec']['name']) 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: 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']) 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']) 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 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) 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 open_folder(addon.getLocalizedString(30111)) # VOD
name = addon.getLocalizedString(30105).encode('utf-8') 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 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') 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 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() close_folder()
def search(params): def search(params):
@@ -494,6 +529,13 @@ def order_recording(program_id):
else: else:
show_notification(addon.getLocalizedString(30172), xbmcgui.NOTIFICATION_INFO) 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): def delete_recording(id, name):
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
name = name.decode('utf-8') name = name.decode('utf-8')
@@ -510,16 +552,24 @@ def logout():
m.cache.remove_file('auth.key') m.cache.remove_file('auth.key')
def login(): def login():
def ask_credentials(username=''): def ask_credentials(username='', password=''):
username = input_window(addon.getLocalizedString(30163), username) # Username username = input_window(addon.getLocalizedString(30163), username) # Username
if username: if username:
password = input_window(addon.getLocalizedString(30164), hidden=True) # Password password = input_window(addon.getLocalizedString(30164), password, hidden=True) # Password
if password: if password:
return username, password return username, password
return None, None 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 username:
if store_credentials:
m.save_credentials(username, password)
success, _ = m.login(username, password) success, _ = m.login(username, password)
if success: if success:
clear_session() clear_session()
@@ -627,6 +677,8 @@ def router(paramstring):
order_recording(params['id']) order_recording(params['id'])
elif params['action'] == 'delete_recording': elif params['action'] == 'delete_recording':
delete_recording(params['id'], params['name']) delete_recording(params['id'], params['name'])
elif params['action'] == 'add_recording_season':
order_recording_season(params['id'])
elif params['action'] == 'wishlist': elif params['action'] == 'wishlist':
# Wishlist # Wishlist
listing_hz(addon.getLocalizedString(30102), m.get_wishlist_url(), from_wishlist=True) 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'])) add_videos(params['name'], 'episodes', m.get_episodes(params['id']))
elif params['action'] == 'vod': elif params['action'] == 'vod':
list_vod() list_vod()
elif params['action'] == 'list_section':
list_section(params['key'])
elif params['action'] == 'search': elif params['action'] == 'search':
search(params) search(params)
elif params['action'] == 'export_epg_now': elif params['action'] == 'export_epg_now':
+1
View File
@@ -1,5 +1,6 @@
<settings> <settings>
<category label="30001"> <category label="30001">
<setting id="store_credentials" type="bool" label="30050" default="false"/>
<setting label="30017" type="bool" id="only_subscribed" default="true"/> <setting label="30017" type="bool" id="only_subscribed" default="true"/>
<setting label="30020" type="bool" id="channels_with_epg" default="false"/> <setting label="30020" type="bool" id="channels_with_epg" default="false"/>
<setting label="30021" type="bool" id="add_extra_info" default="false"/> <setting label="30021" type="bool" id="add_extra_info" default="false"/>