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"?>
<addon id="plugin.video.movistarplus"
name="Movistar+"
version="0.7.16"
version="0.8.0"
provider-name="Paco8">
<requires>
<!--- <import addon="xbmc.python" version="2.25.0"/> -->
+110 -4
View File
@@ -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 '', ''
+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.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':
+1
View File
@@ -1,5 +1,6 @@
<settings>
<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="30020" type="bool" id="channels_with_epg" default="false"/>
<setting label="30021" type="bool" id="add_extra_info" default="false"/>