KodiMov+ 1.0.0+kodimov.1: fork of Movistar+ 1.0.0
- New id plugin.video.kodimovplus, name KodiMov+, proxy port 57031 - Takes over the login of plugin.video.movistarplus on first run - Password-less login from the Movistar home network (autologin token traded for a classic token via the new servers' initData) - Hides the channels that can't play (LALIGA, Liga de Campeones) - Adds TVG2 and TeleVigo to the TV guide list - Re-exports the TV guide channel list every 6 hours Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ccc17b4e5c
commit
066a203e9e
35 files changed
+412
-30
No files matched your search
@@ -22,6 +22,7 @@ from .network import Network
|
||||
from .cache import Cache
|
||||
from .timeconv import *
|
||||
from .useragent import useragent
|
||||
from . import kodimov
|
||||
|
||||
class Movistar(object):
|
||||
account = {'username': '', 'password': '',
|
||||
@@ -37,6 +38,8 @@ class Movistar(object):
|
||||
'demarcation': 0}
|
||||
|
||||
add_extra_info = True
|
||||
hide_unplayable = True
|
||||
add_extra_channels = True
|
||||
#dplayer = 'webplayer'
|
||||
#device_code = 'WP_OTT'
|
||||
#manufacturer = 'Firefox'
|
||||
@@ -45,9 +48,14 @@ class Movistar(object):
|
||||
manufacturer = 'LG'
|
||||
account_dir = 'account_1'
|
||||
|
||||
def __init__(self, config_directory, reuse_devices=False):
|
||||
def __init__(self, config_directory, reuse_devices=False, network_login=False, account_number=''):
|
||||
self.logged = False
|
||||
self.expired_access_token = False
|
||||
self.network_login_result = None
|
||||
try:
|
||||
kodimov.migrate_from_original(config_directory)
|
||||
except Exception as e:
|
||||
LOG('migrate_from_original failed: {}'.format(e))
|
||||
|
||||
# Network
|
||||
headers = {
|
||||
@@ -111,6 +119,9 @@ class Movistar(object):
|
||||
#LOG('access_token: {}'.format(self.account['access_token']))
|
||||
LOG('expired_access_token: {}'.format(self.expired_access_token))
|
||||
|
||||
if not self.account['access_token'] and network_login:
|
||||
self.try_network_login(account_number)
|
||||
|
||||
if not self.account['access_token']: return
|
||||
|
||||
# Account
|
||||
@@ -209,6 +220,21 @@ class Movistar(object):
|
||||
data = self.cache.load_file('searchs.json')
|
||||
self.search_list = json.loads(data) if data else []
|
||||
|
||||
def try_network_login(self, account_number='', force=False):
|
||||
# At most one attempt every 10 minutes, unless asked from the menu.
|
||||
stamp = self.cache.config_directory + 'network_login.stamp'
|
||||
if not force and os.path.exists(stamp) and time.time() - os.path.getmtime(stamp) < 600:
|
||||
return False
|
||||
self.cache.save_file('network_login.stamp', str(int(time.time())))
|
||||
success, reason = kodimov.network_login(self, kodimov.find_account_number(self, account_number))
|
||||
LOG('network login: {} {}'.format(success, reason))
|
||||
self.network_login_result = (success, reason)
|
||||
if success:
|
||||
self.account['access_token'] = self.cache.load_file('access_token.conf')
|
||||
self.expired_access_token = False
|
||||
self.cache.remove_file('tokens.json')
|
||||
return success
|
||||
|
||||
def get_token(self):
|
||||
data = {"accountNumber": self.account['id'],
|
||||
"userProfile": self.account['profile_id'],
|
||||
@@ -666,6 +692,7 @@ class Movistar(object):
|
||||
t['subscribed'] = self.is_subscribed_channel(c.get('tvProducts', []))
|
||||
t['info']['playcount'] = 1 # Set as watched
|
||||
t['uid'] = c.get('Uid')
|
||||
t['watermark'] = bool(c.get('QMWatermark'))
|
||||
if False and 'links' in c:
|
||||
for l in c['links']:
|
||||
if l['rel'] == 'watermarks':
|
||||
@@ -684,6 +711,8 @@ class Movistar(object):
|
||||
|
||||
res.append(t)
|
||||
|
||||
if self.hide_unplayable:
|
||||
res = [t for t in res if kodimov.is_playable(t)]
|
||||
return res
|
||||
|
||||
def get_channels_with_epg(self):
|
||||
@@ -1375,7 +1404,7 @@ class Movistar(object):
|
||||
t['logo'] = c['art']['icon']
|
||||
t['preset'] = c['dial']
|
||||
args = urlencode({'action': 'play', 'stype': 'tv', 'id': c['id'], 'url': c['url'], 'session_request': c['session_request']})
|
||||
t['stream'] = 'plugin://plugin.video.movistarplus/?' + args
|
||||
t['stream'] = 'plugin://plugin.video.kodimovplus/?' + args
|
||||
if 'cas_id' in c: t['cas_id'] = c['cas_id']
|
||||
res.append(t)
|
||||
return res
|
||||
@@ -1390,9 +1419,10 @@ class Movistar(object):
|
||||
item = '#EXTINF:-1 tvg-name="{name}" tvg-id="{id}" tvg-logo="{logo}" tvg-chno="{preset}" {catchup} group-title="Movistar+",{name}\n{stream}\n\n'.format(
|
||||
name=t['name'], id=t['id'], logo=t['logo'], preset=t['preset'], stream=url, catchup='catchup="default" catchup-source="{catchup-id}" catchup-days="7"')
|
||||
items.append(item)
|
||||
res = '#EXTM3U\n## Movistar+\n{}'.format(''.join(items))
|
||||
with io.open(filename, 'w', encoding='utf-8', newline='') as handle:
|
||||
handle.write(res)
|
||||
if self.add_extra_channels:
|
||||
items.append(kodimov.extra_channels_m3u8())
|
||||
res = '#EXTM3U\n## KodiMov+\n{}'.format(''.join(items))
|
||||
return kodimov.write_if_changed(filename, res)
|
||||
|
||||
def export_epg(self, date=None, duration=2):
|
||||
if sys.version_info[0] >= 3:
|
||||
@@ -1419,7 +1449,7 @@ class Movistar(object):
|
||||
url = 'https://grmovistar.imagenio.telefonica.net/asfe/rest/tvMediaURLs?tvProgram.id='+ program_id +'&svc=startover'
|
||||
session_request = '{"contentID":' + program_id +',"streamType":"CUTV"}'
|
||||
args = urlencode({'action': 'play', 'stype': 'u7d', 'id': program_id, 'url': url, 'session_request': session_request})
|
||||
t['stream'] = 'plugin://plugin.video.movistarplus/?' + args
|
||||
t['stream'] = 'plugin://plugin.video.kodimovplus/?' + args
|
||||
|
||||
if False and self.add_extra_info and id in ['HOLLYW', 'TCM', 'AMC', 'MV3', 'MV2', 'CPSER', 'FOXGE', 'TNT']:
|
||||
i = {'id': e['id'], 'show_id': e['show_id']}
|
||||
|
||||
Reference in new issue
Block a user