- These 25 channels are missing from the amazon.tv channel list and their streams answer 403 to the CDN token of the classic servers. They are now taken from the web player's channel list and guide and opened with a CDN token from Movistar's new servers (live and catch-up). Stream session and licence stay on the classic servers. The other channels are untouched. - The new servers need a device registered as a web player and the Movistar home network: a box registered otherwise gets one extra registration; away from the home network the channels are not listed. - The CDN token is used for its 12 hours and renewed in the background: the server that gives it out at times refuses everything for minutes. - New setting, off by default: always play at the best quality, up to 1080p (InputStream Adaptive stays at 576p on these streams when left on automatic). - Error 4027 is shown only when the retry after registering the device again fails too; the first licence request for these channels always gets it. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
998 lines
39 KiB
Python
998 lines
39 KiB
Python
# encoding: utf-8
|
|
#
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
from __future__ import unicode_literals, absolute_import, division
|
|
|
|
import sys
|
|
import json
|
|
import io
|
|
import os.path
|
|
from datetime import datetime, timedelta
|
|
from .timeconv import isodate2date
|
|
|
|
import xbmc
|
|
import xbmcgui
|
|
import xbmcplugin
|
|
import xbmcaddon
|
|
|
|
if sys.version_info[0] >= 3:
|
|
import urllib.request as urllib2
|
|
from urllib.parse import urlencode, parse_qsl, quote_plus
|
|
unicode = str
|
|
else:
|
|
import urllib2
|
|
from urllib import urlencode, quote_plus
|
|
from urlparse import parse_qsl
|
|
|
|
from .log import LOG
|
|
from .movistar import *
|
|
from .addon import *
|
|
from .gui import *
|
|
from .useragent import useragent
|
|
|
|
kodi_version= int(xbmc.getInfoLabel('System.BuildVersion')[:2])
|
|
|
|
# Get the plugin url in plugin:// notation.
|
|
_url = sys.argv[0]
|
|
# Get the plugin handle as an integer number.
|
|
_handle = int(sys.argv[1])
|
|
|
|
def get_url(**kwargs):
|
|
for key, value in kwargs.items():
|
|
if isinstance(value, unicode):
|
|
kwargs[key] = value.encode('utf-8')
|
|
return '{0}?{1}'.format(_url, urlencode(kwargs))
|
|
|
|
def play(params):
|
|
LOG('play - params: {}'.format(params))
|
|
|
|
if not 'url' in params:
|
|
show_notification(addon.getLocalizedString(30204))
|
|
return
|
|
|
|
url = params['url']
|
|
channel_id = params['id']
|
|
stype = params['stype']
|
|
|
|
token = m.account['ssp_token']
|
|
|
|
import inputstreamhelper
|
|
is_helper = inputstreamhelper.Helper('mpd', drm='com.widevine.alpha')
|
|
if not is_helper.check_inputstream():
|
|
show_notification(addon.getLocalizedString(30202))
|
|
return
|
|
|
|
"""
|
|
if addon.getSettingBool('reregister'):
|
|
m.unregister_device()
|
|
m.register_device()
|
|
"""
|
|
|
|
session_opened = False
|
|
if addon.getSettingBool('open_session') or stype == 'vod':
|
|
d = m.open_session(params['session_request'])
|
|
session_opened = True
|
|
LOG('Open session: d: {}'.format(d))
|
|
if d['resultCode'] != 0:
|
|
show_notification(d['resultText'])
|
|
return
|
|
if 'resultData' in d and 'cToken' in d['resultData']:
|
|
token = d['resultData']['cToken']
|
|
|
|
if stype == 'vod':
|
|
d = m.delete_session()
|
|
session_opened = False
|
|
LOG('Delete session: d: {}'.format(d))
|
|
|
|
LOG("token: {}".format(token))
|
|
|
|
if stype in ['u7d', 'rec']:
|
|
d = m.get_u7d_url(url)
|
|
if 'resultText' in d:
|
|
show_notification(d['resultText'])
|
|
return
|
|
else:
|
|
url = d['url']
|
|
#if True:
|
|
# url = url.replace('DASH_WPC_WIDEVINE', 'DASH_TV_WIDEVINE')
|
|
|
|
# U7D from start and end times
|
|
#if stype == 'tv' and all(param in params for param in ['cas_id', 'start_time', 'end_time']):
|
|
# start = datetime.utcfromtimestamp(int(params['start_time']))
|
|
# end = datetime.utcfromtimestamp(int(params['end_time']))
|
|
# catchup_url = 'https://stover-wp0.cdn.telefonica.com/{cas_id}/vxfmt=dp/Manifest.mpd?device_profile=DASH_TV_WIDEVINE&start_time={start_time}&end_time={end_time}'
|
|
# url = catchup_url.format(cas_id=params['cas_id'], start_time=start.strftime('%Y-%m-%dT%H:%M:%SZ'), end_time=end.strftime('%Y-%m-%dT%H:%M:%SZ'))
|
|
# LOG('url from capchup: {}'.format(url))
|
|
|
|
|
|
# Read the proxy address
|
|
proxy = addon.getSetting('proxy_address')
|
|
LOG('proxy address: {}'.format(proxy))
|
|
|
|
if addon.getSettingBool('manifest_modification') and proxy:
|
|
url = '{}/?manifest={}'.format(proxy, url)
|
|
|
|
LOG("url: {}".format(url))
|
|
|
|
headers = 'Content-Type=application/octet-stream'
|
|
headers += '&User-Agent=' + useragent
|
|
headers += '&Accept=*/*&Accept-Language=es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3'
|
|
headers += '&Referer=https://ver.movistarplus.es/'
|
|
headers += '&Origin=https://ver.movistarplus.es'
|
|
#headers += '&Host=wv-ottlic-f3.imagenio.telefonica.net'
|
|
manifest_headers = 'User-Agent=' + useragent
|
|
|
|
if params.get('new_api') == '1':
|
|
# LALIGA, DAZN LALIGA, Liga de Campeones: their streams only open with a
|
|
# CDN token from the new servers. The player keeps the token it starts
|
|
# with, so it must have hours left.
|
|
from . import kodimov
|
|
try:
|
|
cdn_token = kodimov.new_api_cdn_token(m, min_life=3 * 3600)
|
|
except Exception as e:
|
|
LOG('new_api_cdn_token failed: {}'.format(e))
|
|
show_notification(addon.getLocalizedString(30510).format(e))
|
|
return
|
|
manifest_headers += '&x-tcdn-token=' + cdn_token
|
|
elif True: #stype in ['tv', 'u7d', 'rec']:
|
|
cdn_token = m.cache.load('cdn.conf', 60)
|
|
if not cdn_token:
|
|
cdn_token = m.get_cdntoken()
|
|
if not cdn_token:
|
|
time.sleep(2)
|
|
cdn_token = m.get_cdntoken()
|
|
if cdn_token:
|
|
m.cache.save_file('cdn.conf', cdn_token)
|
|
else:
|
|
show_notification('Ha pasado algo')
|
|
return
|
|
#LOG('cdn_token: {}'.format(cdn_token))
|
|
manifest_headers += '&x-tcdn-token=' + cdn_token
|
|
|
|
license_url = 'https://wv-ottlic-f3.imagenio.telefonica.net/TFAESP/wvls/contentlicenseservice/v1/licenses'
|
|
certificate = (
|
|
'CsECCAMSEBcFuRfMEgSGiwYzOi93KowYgrSCkgUijgIwggEKAoIBAQCZ7Vs7Mn2rXiTvw7YqlbWY'
|
|
'UgrVvMs3UD4GRbgU2Ha430BRBEGtjOOtsRu4jE5yWl5KngeVKR1YWEAjp+GvDjipEnk5MAhhC28V'
|
|
'jIeMfiG/+/7qd+EBnh5XgeikX0YmPRTmDoBYqGB63OBPrIRXsTeo1nzN6zNwXZg6IftO7L1KEMpH'
|
|
'SQykfqpdQ4IY3brxyt4zkvE9b/tkQv0x4b9AsMYE0cS6TJUgpL+X7r1gkpr87vVbuvVk4tDnbNfF'
|
|
'XHOggrmWEguDWe3OJHBwgmgNb2fG2CxKxfMTRJCnTuw3r0svAQxZ6ChD4lgvC2ufXbD8Xm7fZPvT'
|
|
'CLRxG88SUAGcn1oJAgMBAAE6FGxpY2Vuc2Uud2lkZXZpbmUuY29tEoADrjRzFLWoNSl/JxOI+3u4'
|
|
'y1J30kmCPN3R2jC5MzlRHrPMveoEuUS5J8EhNG79verJ1BORfm7BdqEEOEYKUDvBlSubpOTOD8S/'
|
|
'wgqYCKqvS/zRnB3PzfV0zKwo0bQQQWz53ogEMBy9szTK/NDUCXhCOmQuVGE98K/PlspKkknYVeQr'
|
|
'OnA+8XZ/apvTbWv4K+drvwy6T95Z0qvMdv62Qke4XEMfvKUiZrYZ/DaXlUP8qcu9u/r6DhpV51Wj'
|
|
'x7zmVflkb1gquc9wqgi5efhn9joLK3/bNixbxOzVVdhbyqnFk8ODyFfUnaq3fkC3hR3f0kmYgI41'
|
|
'sljnXXjqwMoW9wRzBMINk+3k6P8cbxfmJD4/Paj8FwmHDsRfuoI6Jj8M76H3CTsZCZKDJjM3BQQ6'
|
|
'Kb2m+bQ0LMjfVDyxoRgvfF//M/EEkPrKWyU2C3YBXpxaBquO4C8A0ujVmGEEqsxN1HX9lu6c5OMm'
|
|
'8huDxwWFd7OHMs3avGpr7RP7DUnTikXrh6X0')
|
|
|
|
play_item = xbmcgui.ListItem(path= url)
|
|
license_type = 'com.widevine.alpha'
|
|
license_key = ''
|
|
|
|
if format(addon.getSetting('drm_type')) == 'Playready':
|
|
license_type = 'com.microsoft.playready'
|
|
|
|
if addon.getSettingBool('use_proxy_for_license') and proxy:
|
|
request_id = str(int(time.time()*1000))
|
|
license_key = '{}/license?token={}&stype={}&session_request={}&request_id={}'.format(proxy, quote_plus(token), stype, quote_plus(params['session_request']), request_id)
|
|
LOG('license_key: {}'.format(license_key))
|
|
else:
|
|
license_key = license_url
|
|
headers += '&nv-authorizations={}'.format(token)
|
|
|
|
if kodi_version > 20:
|
|
play_item.setProperty('inputstream.adaptive.drm_legacy', '{}|{}|{}'.format(license_type, license_key, headers))
|
|
else:
|
|
play_item.setProperty('inputstream.adaptive.license_type', license_type)
|
|
play_item.setProperty('inputstream.adaptive.license_key', '{}|{}|R{{SSM}}|'.format(license_key, headers))
|
|
play_item.setProperty('inputstream.adaptive.manifest_type', 'mpd')
|
|
#play_item.setProperty('inputstream.adaptive.manifest_type', 'hls')
|
|
|
|
if addon.getSettingBool('best_quality'):
|
|
# Left to itself, InputStream Adaptive starts these streams at 576p and
|
|
# never gets to the 720p/1080p versions (they use a different key)
|
|
best = '4K' if addon.getSettingBool('uhd') else '1080p'
|
|
play_item.setProperty('inputstream.adaptive.stream_selection_type', 'fixed-res')
|
|
play_item.setProperty('inputstream.adaptive.chooser_resolution_max', best)
|
|
play_item.setProperty('inputstream.adaptive.chooser_resolution_secure_max', best)
|
|
|
|
play_item.setProperty('inputstream.adaptive.stream_headers', manifest_headers)
|
|
play_item.setProperty('inputstream.adaptive.manifest_headers', manifest_headers)
|
|
|
|
play_item.setProperty('inputstream.adaptive.server_certificate', certificate)
|
|
#play_item.setProperty('inputstream.adaptive.license_flags', 'persistent_storage')
|
|
#play_item.setProperty('inputstream.adaptive.license_flags', 'force_secure_decoder')
|
|
|
|
if stype == 'u7d':
|
|
play_item.setProperty('inputstream.adaptive.play_timeshift_buffer', 'true')
|
|
|
|
if kodi_version < 19:
|
|
play_item.setProperty('inputstreamaddon', 'inputstream.adaptive')
|
|
else:
|
|
play_item.setProperty('inputstream', 'inputstream.adaptive')
|
|
|
|
play_item.setMimeType('application/dash+xml')
|
|
play_item.setContentLookup(False)
|
|
|
|
# Add info
|
|
if addon.getSettingBool('add_extra_info') and stype in ['vod', 'u7d', 'rec']:
|
|
t = {'id': params['id']}
|
|
if 'show_id' in params: t['show_id'] = params['show_id']
|
|
m.add_video_extra_info(t)
|
|
play_item.setInfo('video', t['info'])
|
|
play_item.setArt(t['art'])
|
|
|
|
# Subtitles
|
|
if stype == 'vod' and addon.getSettingBool('use_ttml2ssa'):
|
|
# Convert subtitles
|
|
from ttml2ssa import Ttml2SsaAddon
|
|
ttml = Ttml2SsaAddon()
|
|
#ttml.use_language_filter = False
|
|
subtype = ttml.subtitle_type()
|
|
|
|
subfolder = os.path.join(profile_dir, 'subtitles')
|
|
if not os.path.exists(subfolder):
|
|
os.makedirs(subfolder)
|
|
|
|
sublist = m.get_subtitles(params['url'])
|
|
LOG('sublist: {}'.format(sublist))
|
|
subpaths = []
|
|
for sub in sublist:
|
|
filename = os.path.join(subfolder, sub['lang'])
|
|
LOG('Converting {}'.format(sub['filename']))
|
|
subheaders = m.net.headers.copy()
|
|
subheaders['x-tcdn-token'] = cdn_token
|
|
response = m.net.session.get(sub['url'], allow_redirects=True, headers=subheaders)
|
|
content = response.content
|
|
with io.open(filename + '.ttml', 'w', encoding='utf-8', newline='') as handle:
|
|
handle.write(content.decode('utf-8'))
|
|
ttml.parse_ttml_from_string(content)
|
|
if subtype != 'srt':
|
|
filename_ssa = filename + '.ssa'
|
|
ttml.write2file(filename_ssa)
|
|
subpaths.append(filename_ssa)
|
|
if subtype != 'ssa':
|
|
filename_srt = filename
|
|
if (subtype == 'both'): filename_srt += '.SRT'
|
|
filename_srt += '.srt'
|
|
ttml.write2file(filename_srt)
|
|
subpaths.append(filename_srt)
|
|
play_item.setSubtitles(subpaths)
|
|
|
|
#if True:
|
|
# m.unregister_device()
|
|
# m.register_device()
|
|
|
|
xbmcplugin.setResolvedUrl(_handle, True, listitem=play_item)
|
|
|
|
LOG('**** session_opened: {}'.format(session_opened))
|
|
watermarks = []
|
|
if stype == 'tv' and 'uid' in params:
|
|
watermarks = m.get_watermarks(params['uid'])
|
|
LOG('watermarks: {}'.format(watermarks))
|
|
|
|
if session_opened or watermarks:
|
|
window = xbmcgui.Window(12005)
|
|
label = xbmcgui.ControlLabel(0, 0, 400, 20, m.account['id'], textColor='0xFFFFFFFF', alignment=6)
|
|
from .player import MyPlayer
|
|
player = MyPlayer()
|
|
monitor = xbmc.Monitor()
|
|
while not monitor.abortRequested() and player.running:
|
|
monitor.waitForAbort(10)
|
|
#LOG('**** waiting')
|
|
if player.isPlaying() and watermarks:
|
|
now = isodate2date(datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'))
|
|
for wm in list(watermarks):
|
|
start = isodate2date(wm['start'])
|
|
stop = isodate2date(wm['stop'])
|
|
if now >= start:
|
|
watermarks.remove(wm)
|
|
if now < stop:
|
|
duration = (stop - start).total_seconds()
|
|
#show_notification(m.account['id'], xbmcgui.NOTIFICATION_INFO)
|
|
w = window.getWidth()
|
|
h = window.getHeight()
|
|
#LOG('window h: {} w: {}'.format(h, w))
|
|
pos_x = w-label.getWidth()-60
|
|
pos_y = h-200
|
|
label.setPosition(pos_x, pos_y)
|
|
window.addControl(label)
|
|
time.sleep(duration)
|
|
window.removeControl(label)
|
|
if session_opened:
|
|
d = m.delete_session()
|
|
LOG('Delete session: d: {}'.format(d))
|
|
LOG('Playback finished')
|
|
|
|
|
|
def add_videos(category, ctype, videos, ref=None, url_next=None, url_prev=None, from_wishlist=False):
|
|
#LOG("category: {} ctype: {}".format(category, ctype))
|
|
xbmcplugin.setPluginCategory(_handle, category)
|
|
xbmcplugin.setContent(_handle, ctype)
|
|
|
|
if ctype == 'movies' or ctype == 'seasons':
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_UNSORTED)
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LABEL)
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_TITLE)
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_VIDEO_YEAR)
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_GENRE)
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_LASTPLAYED)
|
|
if ctype == 'episodes':
|
|
xbmcplugin.addSortMethod(_handle, xbmcplugin.SORT_METHOD_EPISODE)
|
|
|
|
"""
|
|
if url_prev:
|
|
list_item = xbmcgui.ListItem(label = addon.getLocalizedString(30110)) # Previous page
|
|
xbmcplugin.addDirectoryItem(_handle, get_url(action=ref, url=url_prev, name=category), list_item, True)
|
|
"""
|
|
|
|
for t in videos:
|
|
#LOG("t: {}".format(t))
|
|
if 'subscribed' in t:
|
|
if addon.getSettingBool('only_subscribed') and t['subscribed'] == False: continue
|
|
t['info']['title'] = m.colorize_title(t)
|
|
|
|
if 'availability' in t:
|
|
ends = int(t['availability'].get('end', '0'))
|
|
if ends > 0:
|
|
now = int(time.time()*1000)
|
|
n_hours = int((ends - now) / (1000 * 60 * 60))
|
|
n_days = int(n_hours / 24)
|
|
if (n_days <= addon.getSettingInt('expdays')):
|
|
if n_days < 1:
|
|
t['info']['title'] += ' [COLOR red](' + addon.getLocalizedString(30401).format(n_hours) + ')[/COLOR]'
|
|
else:
|
|
t['info']['title'] += ' [COLOR red](' + addon.getLocalizedString(30400).format(n_days) + ')[/COLOR]'
|
|
|
|
title_name = t['info']['title']
|
|
if not 'type' in t: continue
|
|
|
|
wishlist_action = None
|
|
if t['type'] in ['movie', 'series', 'season']:
|
|
id = t['id']
|
|
stype = 'vod'
|
|
possible_to_add = False
|
|
|
|
if from_wishlist:
|
|
# Remove from wishlist
|
|
if 'favorite_data' in t:
|
|
if 'favorites2' in t['favorite_data']:
|
|
id = t['favorite_data']['favorites2']['id']
|
|
stype = t['favorite_data']['favorites2']['family']
|
|
possible_to_add = True
|
|
elif t['type'] == 'season' and 'favorites2.season' in t['favorite_data']:
|
|
id = t['favorite_data']['favorites2.season']['id']
|
|
stype = t['favorite_data']['favorites2.season']['family']
|
|
possible_to_add = True
|
|
else:
|
|
# Add to wishlist
|
|
if t['type'] in ['series', 'season']:
|
|
possible_to_add = t.get('seguible', False)
|
|
|
|
if t['type'] == 'movie':
|
|
if t.get('stream_type') == 'vod':
|
|
possible_to_add = t['url'] != ''
|
|
if 'show_id' in t:
|
|
possible_to_add = t['url'] != ''
|
|
stype = 'tv'
|
|
id = t['show_id']
|
|
|
|
if possible_to_add:
|
|
if not from_wishlist:
|
|
op = 'add'
|
|
message = 30175
|
|
else:
|
|
op = 'delete'
|
|
message = 30176
|
|
wishlist_action = (addon.getLocalizedString(message), "RunPlugin(" + get_url(action='to_wishlist', id=id, op=op, stype=stype) + ")")
|
|
|
|
if t['type'] == 'movie':
|
|
list_item = xbmcgui.ListItem(label = title_name)
|
|
#if t['url'] == '':
|
|
# t['info']['title'] = '[COLOR gray]' + t['info']['title'] +'[/COLOR]'
|
|
list_item.setProperty('IsPlayable', 'true')
|
|
list_item.setInfo('video', t['info'])
|
|
list_item.setArt(t['art'])
|
|
|
|
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'])
|
|
actions.append((addon.getLocalizedString(30173), "RunPlugin(" + action + ")"))
|
|
|
|
if 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 t.get('new_api'): url += '&new_api=1'
|
|
if 'show_id' in t: url += '&show_id={}'.format(t['show_id'])
|
|
if 'uid' in t: url += '&uid={}'.format(t['uid'])
|
|
xbmcplugin.addDirectoryItem(_handle, url, list_item, False)
|
|
elif t['type'] == 'series':
|
|
list_item = xbmcgui.ListItem(label = title_name)
|
|
list_item.setInfo('video', t['info'])
|
|
list_item.setArt(t['art'])
|
|
if wishlist_action:
|
|
list_item.addContextMenuItems([wishlist_action])
|
|
xbmcplugin.addDirectoryItem(_handle, get_url(action='series', id=t['id'], name=title_name), list_item, True)
|
|
elif t['type'] == 'season':
|
|
list_item = xbmcgui.ListItem(label = title_name)
|
|
list_item.setInfo('video', t['info'])
|
|
list_item.setArt(t['art'])
|
|
if wishlist_action:
|
|
list_item.addContextMenuItems([wishlist_action])
|
|
xbmcplugin.addDirectoryItem(_handle, get_url(action='season', id=t['id'], name=title_name), list_item, True)
|
|
elif t['type'] == 'category':
|
|
list_item = xbmcgui.ListItem(label = title_name)
|
|
#list_item.setInfo('video', t['info'])
|
|
#list_item.setArt(t['art'])
|
|
xbmcplugin.addDirectoryItem(_handle, get_url(action='category', id=t['id'], name=title_name), list_item, True)
|
|
|
|
if url_next:
|
|
list_item = xbmcgui.ListItem(label = addon.getLocalizedString(30109)) # Next page
|
|
xbmcplugin.addDirectoryItem(_handle, get_url(action=ref, url=url_next, from_wishlist=from_wishlist, name=category), list_item, True)
|
|
|
|
xbmcplugin.endOfDirectory(_handle)
|
|
|
|
def list_devices(params):
|
|
LOG('list_devices: params: {}'.format(params))
|
|
|
|
devices = m.get_devices()
|
|
|
|
if 'id' in params:
|
|
if params['name'] == 'select':
|
|
LOG('Selecting device {}'.format(params['id']))
|
|
m.change_device(params['id'])
|
|
elif params['name'] == 'close':
|
|
LOG('Closing session {}'.format(params['id']))
|
|
m.delete_session(params['id'])
|
|
elif params['name'] == 'delete':
|
|
LOG('Removing device {}'.format(params['id']))
|
|
m.delete_device(params['id'])
|
|
if params['id'] == m.account['device_id']:
|
|
LOG('Registering device')
|
|
m.register_device()
|
|
|
|
xbmc.executebuiltin("Container.Refresh")
|
|
return
|
|
|
|
open_folder(addon.getLocalizedString(30108)) # Devices
|
|
|
|
for d in devices:
|
|
name = d['name'] +' - '+ d['type'] + ' (' + d['reg_date'] + ')'
|
|
if d['playing']: name += ' [' + d['playing'] + ']'
|
|
name += ' ['+ d['id'][:5] +']'
|
|
if d['id'] == m.account['device_id']:
|
|
name = '[B][COLOR blue]' + name + '[/COLOR][/B]'
|
|
|
|
select_action = get_url(action='devices', id=d['id'], name='select')
|
|
close_action = get_url(action='devices', id=d['id'], name='close')
|
|
remove_action = get_url(action='devices', id=d['id'], name='delete')
|
|
cm = [(addon.getLocalizedString(30150), "RunPlugin(" + close_action + ")"),
|
|
(addon.getLocalizedString(30151), "RunPlugin(" + remove_action + ")")]
|
|
if d['type_code'] == 'WP':
|
|
cm.insert(0, (addon.getLocalizedString(30152), "RunPlugin(" + select_action + ")"))
|
|
default_action = select_action
|
|
else:
|
|
default_action = close_action
|
|
add_menu_option(name, default_action, cm)
|
|
|
|
close_folder(cacheToDisc=False)
|
|
|
|
def list_profiles(params):
|
|
LOG('list_profiles: params: {}'.format(params))
|
|
|
|
profiles = m.get_profiles()
|
|
|
|
if 'id' in params:
|
|
if params['name'] == 'select':
|
|
LOG('Selecting profile {}'.format(params['id']))
|
|
m.change_profile(params['id'])
|
|
xbmc.executebuiltin("Container.Refresh")
|
|
return
|
|
|
|
open_folder(addon.getLocalizedString(30180)) # Profiles
|
|
for p in profiles:
|
|
name = p['name']
|
|
if p['id'] == m.account['profile_id']:
|
|
name = '[B][COLOR blue]' + name + '[/COLOR][/B]'
|
|
img_url = m.get_profile_image_url(p['image_id'])
|
|
art = {'icon': img_url} if img_url else None
|
|
select_action = get_url(action='profiles', id=p['id'], name='select')
|
|
add_menu_option(name, select_action, art=art)
|
|
close_folder(cacheToDisc=False)
|
|
|
|
def list_epg(params):
|
|
LOG('list_epg: {}'.format(params))
|
|
from .timeconv import my_strftime
|
|
if 'id' in params:
|
|
if not 'date' in params:
|
|
today = datetime.today()
|
|
for i in range(6, 0, -1):
|
|
past_date = today - timedelta(days=i)
|
|
date = past_date.strftime('%Y-%m-%dT00:00:00')
|
|
display_str = my_strftime(past_date, '%a %d')
|
|
add_menu_option(display_str, get_url(action='epg', id=params['id'], name=params['name'], date=date))
|
|
add_videos(params['name'], 'movies', m.epg_to_movies(params['id'], params.get('date'), duration=1))
|
|
else:
|
|
channels = m.get_channels()
|
|
open_folder(addon.getLocalizedString(30107)) # EPG
|
|
for t in channels:
|
|
name = t['info']['title']
|
|
add_menu_option(name, get_url(action='epg', id=t['id'], name=name.encode('utf-8')), art=t['art'])
|
|
close_folder()
|
|
|
|
def listing(name, url):
|
|
data = m.download_list(url, use_hz=False)
|
|
l = []
|
|
url_next = None
|
|
url_prev = None
|
|
if 'Contenidos' in data:
|
|
l = m.get_list(data['Contenidos'])
|
|
url_next = data['next']['href'] if isinstance(data['next'], dict) and 'href' 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')
|
|
|
|
def listing_hz(name, url, from_wishlist=False):
|
|
data = m.download_list(url, use_hz=True)
|
|
l = []
|
|
url_next = None
|
|
url_prev = None
|
|
if 'Contenidos' in data:
|
|
l = m.get_list(data['Contenidos'])
|
|
url_next = data['next']['href'] if isinstance(data['next'], dict) and 'href' 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)
|
|
|
|
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
|
|
|
|
name = addon.getLocalizedString(30106).encode('utf-8')
|
|
add_menu_option(name, get_url(action='listing', name=name, url=m.get_vod_list_url(cat='tvshows'))) # TV Shows
|
|
|
|
name = addon.getLocalizedString(30120).encode('utf-8')
|
|
add_menu_option(name, get_url(action='listing', name=name, url=m.get_vod_list_url(cat='documentaries'))) # Documentaries
|
|
|
|
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):
|
|
search_term = params.get('search_term', None)
|
|
if search_term:
|
|
if sys.version_info[0] < 3:
|
|
search_term = search_term.decode('utf-8')
|
|
if params.get('name', None) == 'delete':
|
|
m.delete_search(search_term)
|
|
xbmc.executebuiltin("Container.Refresh")
|
|
else:
|
|
url = m.get_search_url(search_term)
|
|
listing_hz(addon.getLocalizedString(30117), url)
|
|
return
|
|
|
|
if params.get('name', None) == 'new':
|
|
search_term = input_window(addon.getLocalizedString(30116)) # Search term
|
|
if search_term:
|
|
if sys.version_info[0] < 3:
|
|
search_term = search_term.decode('utf-8')
|
|
m.add_search(search_term)
|
|
xbmc.executebuiltin("Container.Refresh")
|
|
return
|
|
|
|
open_folder(addon.getLocalizedString(30113)) # Search
|
|
add_menu_option(addon.getLocalizedString(30113), get_url(action='search', name='new')) # New search
|
|
|
|
for i in reversed(m.search_list):
|
|
remove_action = get_url(action='search', search_term=i, name='delete')
|
|
cm = [(addon.getLocalizedString(30114), "RunPlugin(" + remove_action + ")")]
|
|
add_menu_option(i.encode('utf-8'), get_url(action='search', search_term=i), cm)
|
|
|
|
close_folder(cacheToDisc=False)
|
|
|
|
def order_recording(program_id):
|
|
data = m.order_recording(program_id)
|
|
if data and 'resultText' in data:
|
|
show_notification(data['resultText'])
|
|
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')
|
|
res = xbmcgui.Dialog().yesno(addon.getLocalizedString(30173), addon.getLocalizedString(30174).format(name))
|
|
if res == True:
|
|
m.delete_recording(id)
|
|
xbmc.executebuiltin("Container.Refresh")
|
|
|
|
def clear_session():
|
|
m.delete_session_files()
|
|
|
|
def logout():
|
|
clear_session()
|
|
m.cache.remove_file('auth.key')
|
|
|
|
def login():
|
|
def ask_credentials(username='', password=''):
|
|
username = input_window(addon.getLocalizedString(30163), username) # Username
|
|
if username:
|
|
password = input_window(addon.getLocalizedString(30164), password, hidden=True) # Password
|
|
if password:
|
|
return username, password
|
|
return None, None
|
|
|
|
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()
|
|
else:
|
|
show_notification(addon.getLocalizedString(30166)) # Failed
|
|
|
|
def network_login():
|
|
# The account number and the device are found/registered automatically.
|
|
account_number = addon.getSetting('account_number')
|
|
# Keeps device_id.conf: clearing the session would register a new device.
|
|
if m.try_network_login(account_number, force=True):
|
|
show_notification(addon.getLocalizedString(30503), xbmcgui.NOTIFICATION_INFO) # Logged in
|
|
xbmc.executebuiltin('Container.Refresh')
|
|
else:
|
|
reason = (m.network_login_result or (False, ''))[1]
|
|
show_notification(addon.getLocalizedString(30504).format(reason)) # Failed
|
|
|
|
def login_with_key():
|
|
filename = xbmcgui.Dialog().browseSingle(1, addon.getLocalizedString(30182), '', '.key')
|
|
if filename:
|
|
m.install_key_file(filename)
|
|
clear_session()
|
|
|
|
def export_key():
|
|
directory = xbmcgui.Dialog().browseSingle(0, addon.getLocalizedString(30185), '')
|
|
if directory:
|
|
m.export_key_file(directory + 'movistarplus.key')
|
|
|
|
def import_credentials():
|
|
filename = xbmcgui.Dialog().browseSingle(1, addon.getLocalizedString(30193), '', '.json')
|
|
if filename:
|
|
m.import_credentials(filename)
|
|
|
|
def export_credentials():
|
|
directory = xbmcgui.Dialog().browseSingle(0, addon.getLocalizedString(30194), '')
|
|
if directory:
|
|
m.export_credentials(os.path.join(directory, 'credenciales.json'))
|
|
|
|
def select_account(id, name):
|
|
m.switch_account(id)
|
|
open_folder(name)
|
|
add_menu_option(addon.getLocalizedString(30501), get_url(action='network_login')) # Login from home network
|
|
add_menu_option(addon.getLocalizedString(30183), get_url(action='login')) # Login with username
|
|
if addon.getSettingBool('enable_key_login'):
|
|
add_menu_option(addon.getLocalizedString(30181), get_url(action='login_with_key')) # Login with key
|
|
if os.path.exists(os.path.join(m.cache.config_directory, 'auth.key')):
|
|
add_menu_option(addon.getLocalizedString(30184), get_url(action='export_key')) # Export key
|
|
add_menu_option(addon.getLocalizedString(30150), get_url(action='logout')) # Close session
|
|
add_menu_option(addon.getLocalizedString(30196), get_url(action='import_credentials'))
|
|
if os.path.exists(os.path.join(m.cache.config_directory, 'credentials.json')):
|
|
add_menu_option(addon.getLocalizedString(30195), get_url(action='export_credentials'))
|
|
close_folder(cacheToDisc=False)
|
|
|
|
def list_accounts(params):
|
|
LOG('list_accounts: {}'.format(params))
|
|
|
|
if params.get('name') == 'new_account':
|
|
m.create_new_account()
|
|
|
|
accounts = m.get_accounts()
|
|
open_folder(addon.getLocalizedString(30160)) # Accounts
|
|
for account in accounts:
|
|
name = account['name']
|
|
login = account.get('login')
|
|
if login:
|
|
name += ' ({})'.format(login)
|
|
if account['id'] == m.account_dir:
|
|
display_name = '[B][COLOR blue]' + name + '[/COLOR][/B]'
|
|
else:
|
|
display_name = name
|
|
add_menu_option(display_name, get_url(action='select_account', id=account['id'], name=name))
|
|
add_menu_option(addon.getLocalizedString(30161), get_url(action='accounts', name='new_account')) # Add new
|
|
close_folder(cacheToDisc=False)
|
|
|
|
if params.get('name') == 'new_account':
|
|
xbmc.executebuiltin('Container.Update({},replace)'.format(xbmc.getInfoLabel('Container.FolderPath')))
|
|
|
|
def iptv(params):
|
|
LOG('iptv: params: {}'.format(params))
|
|
if m.logged:
|
|
#try:
|
|
if True:
|
|
from .iptvmanager import IPTVManager
|
|
port = int(params['port'])
|
|
if params['action'] == 'iptv-channels':
|
|
IPTVManager(port).send_channels(m)
|
|
elif params['action'] == 'iptv-epg':
|
|
IPTVManager(port).send_epg(m)
|
|
#except:
|
|
# pass
|
|
|
|
def create_iptv_settings():
|
|
from .iptv import save_iptv_settings
|
|
from . import kodimov
|
|
show_notification(addon.getLocalizedString(30319), xbmcgui.NOTIFICATION_INFO)
|
|
output_file = 'instance-settings-91.xml' if kodi_version > 19 else 'settings.xml'
|
|
epg_url = None
|
|
if False: #addon.getSettingBool('use_external_epg'):
|
|
epg_url = addon.getSetting('epg_url')
|
|
try:
|
|
pvr_addon = xbmcaddon.Addon('pvr.iptvsimple')
|
|
pvr_dir = translatePath(pvr_addon.getAddonInfo('profile'))
|
|
LOG('pvr_dir: {}'.format(pvr_dir))
|
|
filename = os.path.join(pvr_dir, output_file)
|
|
if os.path.exists(filename):
|
|
res = xbmcgui.Dialog().yesno(addon.getLocalizedString(30322), addon.getLocalizedString(30323))
|
|
if res == False: return
|
|
# Write the channel list and the programme guide first: if IPTV Simple
|
|
# starts before epg.xml exists, Kodi stores an empty guide for every
|
|
# channel and doesn't ask again for hours.
|
|
export_epg_now()
|
|
if not os.path.exists(os.path.join(profile_dir, 'epg.xml')):
|
|
show_notification(addon.getLocalizedString(30509)) # Log in first
|
|
return
|
|
save_iptv_settings(filename, 'KodiMov+', 'kodimovplus', epg_url)
|
|
# IPTV Simple now reads epg.xml, so the service must keep it up to date.
|
|
addon.setSettingBool('auto_export_epg', True)
|
|
# Show Movistar's own channel numbers instead of 1, 2, 3...
|
|
xbmc.executeJSONRPC(json.dumps({'jsonrpc': '2.0', 'id': 1, 'method': 'Settings.SetSettingValue',
|
|
'params': {'setting': 'pvrmanager.usebackendchannelnumbers', 'value': True}}))
|
|
# Restart IPTV Simple so it loads the new instance and channel list.
|
|
kodimov.restart_iptv_simple()
|
|
except:
|
|
show_notification(addon.getLocalizedString(30324))
|
|
|
|
def export_channels_now():
|
|
if not m.logged: return
|
|
channels_filename = os.path.join(profile_dir, 'channels.m3u8')
|
|
if m.export_channels_to_m3u8(channels_filename, addon.getSettingBool('only_subscribed')):
|
|
LOG('export_channels_now: channel list changed')
|
|
|
|
def export_epg_now(quiet=False, reload_guide=False):
|
|
# quiet: background refresh from the service, no pop-ups while watching TV
|
|
def notify(message):
|
|
if not quiet: show_notification(message, xbmcgui.NOTIFICATION_INFO)
|
|
def report_progress(message):
|
|
notify(addon.getLocalizedString(30314).format(message))
|
|
|
|
if not m.logged: return
|
|
|
|
only_subscribed = addon.getSettingBool('only_subscribed')
|
|
channels_filename = os.path.join(profile_dir, 'channels.m3u8')
|
|
epg_filename = os.path.join(profile_dir, 'epg.xml')
|
|
notify(addon.getLocalizedString(30310))
|
|
m.export_channels_to_m3u8(channels_filename, only_subscribed)
|
|
|
|
if True: #not addon.getSettingBool('use_external_epg'):
|
|
notify(addon.getLocalizedString(30311))
|
|
changed = m.export_epg_to_xml(epg_filename, addon.getSettingInt('export_days'), report_progress, only_subscribed)
|
|
if changed and reload_guide:
|
|
from . import kodimov
|
|
try:
|
|
pvr_dir = translatePath(xbmcaddon.Addon('pvr.iptvsimple').getAddonInfo('profile'))
|
|
except RuntimeError: # IPTV Simple not installed or disabled
|
|
pvr_dir = None
|
|
if pvr_dir: kodimov.reload_iptv_guide(pvr_dir, 'kodimovplus')
|
|
|
|
notify(addon.getLocalizedString(30313))
|
|
|
|
|
|
def to_wishlist(params):
|
|
stype = params['stype']
|
|
if params['op'] == 'add':
|
|
retcode, message = m.add_to_wishlist(params['id'], stype)
|
|
else:
|
|
retcode, message = m.delete_from_wishlist(params['id'], stype)
|
|
if retcode in [201, 204]:
|
|
message = 30177 if params['op'] == 'add' else 30178
|
|
show_notification(addon.getLocalizedString(message), xbmcgui.NOTIFICATION_INFO)
|
|
if params['op'] == 'delete':
|
|
xbmc.executebuiltin("Container.Refresh")
|
|
else:
|
|
show_notification(str(retcode) +': '+ message)
|
|
|
|
|
|
def router(paramstring):
|
|
"""
|
|
Router function that calls other functions
|
|
depending on the provided paramstring
|
|
:param paramstring: URL encoded plugin paramstring
|
|
:type paramstring: str
|
|
"""
|
|
|
|
params = dict(parse_qsl(paramstring))
|
|
LOG('params: {}'.format(params))
|
|
if params:
|
|
if params['action'] == 'play':
|
|
play(params)
|
|
elif params['action'] == 'tv':
|
|
if addon.getSettingBool('channels_with_epg'):
|
|
channels = m.get_channels_with_epg()
|
|
else:
|
|
channels = m.get_channels()
|
|
add_videos(addon.getLocalizedString(30104), 'movies', channels)
|
|
elif params['action'] == 'devices':
|
|
list_devices(params)
|
|
elif params['action'] == 'profiles':
|
|
list_profiles(params)
|
|
elif params['action'] == 'login_with_key':
|
|
login_with_key()
|
|
elif params['action'] == 'login':
|
|
login()
|
|
elif params['action'] == 'network_login':
|
|
network_login()
|
|
elif params['action'] == 'export_channels_now':
|
|
export_channels_now()
|
|
elif params['action'] == 'new_api_keep_warm':
|
|
if m.logged:
|
|
from . import kodimov
|
|
kodimov.new_api_keep_warm(m)
|
|
elif params['action'] == 'export_key':
|
|
export_key()
|
|
elif params['action'] == 'export_credentials':
|
|
export_credentials()
|
|
elif params['action'] == 'import_credentials':
|
|
import_credentials()
|
|
elif params['action'] == 'select_account':
|
|
select_account(params['id'], params['name'])
|
|
elif params['action'] == 'accounts':
|
|
list_accounts(params)
|
|
elif params['action'] == 'logout':
|
|
logout()
|
|
elif params['action'] == 'epg':
|
|
list_epg(params)
|
|
elif params['action'] == 'add_recording':
|
|
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)
|
|
elif params['action'] == 'continue-watching':
|
|
listing_hz(addon.getLocalizedString(30102), m.get_viewings_url())
|
|
elif params['action'] == 'recordings':
|
|
# Recordings
|
|
listing_hz(addon.getLocalizedString(30103), m.get_recordings_url())
|
|
elif params['action'] == 'listing':
|
|
listing(params['name'], params['url'])
|
|
elif params['action'] == 'listing_hz':
|
|
listing_hz(params['name'], params['url'], params.get('from_wishlist'))
|
|
elif params['action'] == 'series':
|
|
add_videos(params['name'], 'seasons', m.get_seasons(params['id']))
|
|
elif params['action'] == 'season':
|
|
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'] == 'create_iptv_settings':
|
|
create_iptv_settings()
|
|
elif params['action'] == 'export_epg_now':
|
|
export_epg_now(quiet=params.get('quiet') == '1', reload_guide=params.get('reload_guide') == '1')
|
|
elif params['action'] == 'to_wishlist':
|
|
to_wishlist(params)
|
|
elif 'iptv' in params['action']:
|
|
iptv(params)
|
|
else:
|
|
# Main
|
|
open_folder(addon.getLocalizedString(30101)) # Menu
|
|
|
|
if m.logged:
|
|
add_menu_option(addon.getLocalizedString(30104), get_url(action='tv'), icon='tv.png') # TV
|
|
add_menu_option(addon.getLocalizedString(30107), get_url(action='epg'), icon='epg.png') # EGP
|
|
add_menu_option(addon.getLocalizedString(30102), get_url(action='wishlist'), icon='mylist.png') # My list
|
|
add_menu_option(addon.getLocalizedString(30103), get_url(action='recordings'), icon='recording.png') # Recordings
|
|
add_menu_option(addon.getLocalizedString(30122), get_url(action='continue-watching'), icon='continue.png') # Continue
|
|
add_menu_option(addon.getLocalizedString(30111), get_url(action='vod'), icon='vod.png') # VOD
|
|
add_menu_option(addon.getLocalizedString(30112), get_url(action='search'), icon='search.png') # Search
|
|
add_menu_option(addon.getLocalizedString(30180), get_url(action='profiles'), icon='profiles.png') # Profiles
|
|
add_menu_option(addon.getLocalizedString(30108), get_url(action='devices'), icon='devices.png') # Devices
|
|
else:
|
|
if m.expired_access_token:
|
|
show_notification(addon.getLocalizedString(30208))
|
|
add_menu_option(addon.getLocalizedString(30501), get_url(action='network_login'), icon='account.png') # Login from home network
|
|
|
|
add_menu_option(addon.getLocalizedString(30160), get_url(action='accounts'), icon='account.png') # Accounts
|
|
add_menu_option(addon.getLocalizedString(30450), get_url(action='show_donation_dialog'), icon='qr.png') # Donation
|
|
close_folder(cacheToDisc=False)
|
|
|
|
|
|
def run():
|
|
# Call the router function and pass the plugin call parameters to it.
|
|
# We use string slicing to trim the leading '?' from the plugin call paramstring
|
|
params = sys.argv[2][1:]
|
|
|
|
if 'show_donation_dialog' in params:
|
|
from .customdialog import show_donation_dialog
|
|
show_donation_dialog()
|
|
return
|
|
|
|
global m
|
|
reuse_devices = addon.getSettingBool('reuse_devices')
|
|
LOG('profile_dir: {}'.format(profile_dir))
|
|
LOG('reuse_devices: {}'.format(reuse_devices))
|
|
m = Movistar(profile_dir, reuse_devices=reuse_devices,
|
|
network_login=addon.getSettingBool('network_login'),
|
|
account_number=addon.getSetting('account_number'))
|
|
m.add_extra_info = addon.getSettingBool('add_extra_info')
|
|
m.hide_unplayable = addon.getSettingBool('hide_unplayable')
|
|
m.add_extra_channels = addon.getSettingBool('extra_channels')
|
|
if addon.getSettingBool('uhd'):
|
|
m.quality = 'UHD'
|
|
|
|
profile_id = addon.getSetting('profile_id').upper()
|
|
LOG('profile_id: {}'.format(profile_id))
|
|
if profile_id not in ['', 'AUTO']:
|
|
m.account['platform'] = profile_id
|
|
|
|
# Clear cache
|
|
LOG('Cleaning cache. {} files removed.'.format(m.cache.clear_cache()))
|
|
|
|
if '/iptv/channels' in sys.argv[0]: params += '&action=iptv-channels'
|
|
elif '/iptv/epg' in sys.argv[0]: params += '&action=iptv-epg'
|
|
router(params)
|