diff --git a/addon.xml b/addon.xml index 1dd002e..b3310eb 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ @@ -21,7 +21,8 @@ Movistar+ para Kodi, con inicio de sesión automático desde la red de Movistar Fork of Paco8's Movistar+ add-on (plugin.video.movistarplus). Logs in by itself from the Movistar home network, keeps the channel list and numbers up to date, hides the channels that need stronger DRM than Kodi has, adds free Galician channels (TVG2, TeleVigo) and writes a programme guide for every channel. Requires a Movistar+ subscription. Fork del addon Movistar+ de Paco8 (plugin.video.movistarplus). Inicia sesión solo desde la red de Movistar, mantiene la lista y los números de los canales al día, oculta los canales que necesitan una protección que Kodi no tiene añade canales gallegos gratuitos (TVG2, TeleVigo) y genera la guía de programación de todos los canales. Se necesita estar abonado a Movistar+. - 1.0.0+kodimov.6: the programme guide refreshes on its own again on boxes first set up with kodimov.1, where the automatic guide export had stayed off (the guide ran out after 2 days). + 1.0.0+kodimov.7: the programme guide has the synopsis, picture, genre, year and age rating of each programme. IPTV Simple now reloads the guide every hour instead of once a day, so a new guide shows up in Kodi by itself (existing TV guide setups are switched over once). +1.0.0+kodimov.6: the programme guide refreshes on its own again on boxes first set up with kodimov.1, where the automatic guide export had stayed off (the guide ran out after 2 days). 1.0.0+kodimov.5: TV guide setup writes the programme guide before creating the IPTV Simple settings, so the guide isn't empty on a new box. 1.0.0+kodimov.4: first login on a new box needs no password from the Movistar home network: the account is found and the box registered automatically. 1.0.0+kodimov.3: one-tap TV setup: "Create settings for IPTV Simple" also turns on Movistar channel numbers, daily list reload, and restarts IPTV Simple; fixes invalid XML in that file. diff --git a/resources/lib/iptv.py b/resources/lib/iptv.py index 0323c88..b73e06e 100644 --- a/resources/lib/iptv.py +++ b/resources/lib/iptv.py @@ -15,8 +15,8 @@ def save_iptv_settings(filename, name, addon_id, epg_url=None): true 1 false - 2 - 60 + 1 + 60 4 10 20 diff --git a/resources/lib/kodimov.py b/resources/lib/kodimov.py index 8b722d2..d1931c0 100644 --- a/resources/lib/kodimov.py +++ b/resources/lib/kodimov.py @@ -210,6 +210,37 @@ def write_if_changed(filename, content): return True +def use_hourly_iptv_refresh(pvr_dir, addon_id): + """TV guide setups before kodimov.7 made IPTV Simple reload the channel list + and programme guide only once a day, at 4:00, so a new epg.xml didn't reach + Kodi for up to a day. Switch them to a reload every hour, which also makes + Kodi fetch the guide again. Returns True if IPTV Simple must be restarted.""" + import glob + import re + changed = False + for filename in glob.glob(os.path.join(pvr_dir, 'instance-settings-*.xml')): + with io.open(filename, 'r', encoding='utf-8') as f: + content = f.read() + if 'plugin.video.{}/channels.m3u8'.format(addon_id) not in content: continue + new = content + for setting, value in (('m3uRefreshMode', '1'), ('m3uRefreshIntervalMins', '60')): + new = re.sub(r']*?(/>|>[^<]*)'.format(setting), + '{}'.format(setting, value), new) + if write_if_changed(filename, new): + LOG('use_hourly_iptv_refresh: updated {}'.format(filename)) + changed = True + return changed + + +def restart_iptv_simple(): + """Restarts IPTV Simple so it loads its instance settings again.""" + import xbmc + for enabled in (False, True): + xbmc.executeJSONRPC(json.dumps({'jsonrpc': '2.0', 'id': 1, 'method': 'Addons.SetAddonEnabled', + 'params': {'addonid': 'pvr.iptvsimple', 'enabled': enabled}})) + xbmc.sleep(3000) + + def extra_channels_xmltv(session): """Returns the and elements for the extra channels, taken from a public XMLTV guide and renamed to their tvg-id.""" diff --git a/resources/lib/movistar.py b/resources/lib/movistar.py index 595c5ee..b6e8505 100644 --- a/resources/lib/movistar.py +++ b/resources/lib/movistar.py @@ -564,6 +564,13 @@ class Movistar(object): if 'TituloHorLinea2' in p: pr['desc2'] = p['TituloHorLinea2'] pr['show_id'] = p['ShowId'] + # Synopsis, genre, year, age rating and picture come with the guide + pr['plot'] = p.get('Resena') or '' + pr['genre'] = p.get('GeneroComAntena') or '' + pr['year'] = p.get('Anno') or '' + pr['age_rating'] = (p.get('NivelMoral') or {}).get('Id') or '' + images = {i.get('id'): i.get('uri') for i in (p.get('Imagenes') or [])} + pr['image'] = images.get('horizontal') or images.get('default') or '' if 'SerialId' in p: pr['serie_id'] = p['SerialId'] pr['id'] = p['Id'] @@ -1454,6 +1461,9 @@ class Movistar(object): t['subtitle'] = e['desc2'] t['start'] = datetime.utcfromtimestamp(e['start']/1000).strftime('%Y-%m-%dT%H:%M:%SZ') t['stop'] = datetime.utcfromtimestamp(e['end']/1000).strftime('%Y-%m-%dT%H:%M:%SZ') + for key, field in (('description', 'plot'), ('image', 'image'), ('genre', 'genre'), + ('year', 'year'), ('age_rating', 'age_rating')): + if e.get(field): t[key] = e[field] if True: program_id = str(e['show_id']) @@ -1533,8 +1543,6 @@ class Movistar(object): '>\n' + ' {}\n'.format(html_escape(e['title'])) + ' {}\n'.format(html_escape(e['subtitle']))) - if 'image' in e: - res.append(' \n'.format(e['image'])) if 'description' in e: res.append(' {}\n'.format(html_escape(e['description']))) if 'credits' in e and len(e['credits']) > 0: @@ -1545,6 +1553,14 @@ class Movistar(object): elif c['type'] == 'actor': res.append(' {}\n'.format(c['name'])) res.append(' \n'); + if 'year' in e: + res.append(' {}\n'.format(html_escape(e['year']))) + if 'genre' in e: + res.append(' {}\n'.format(html_escape(e['genre']))) + if 'image' in e: + res.append(' \n'.format(html_escape(e['image']))) + if 'age_rating' in e: + res.append(' {}\n'.format(html_escape(e['age_rating']))) res.append('\n') if self.add_extra_channels: res.extend(kodimov.extra_channels_xmltv(self.net.session)) diff --git a/resources/lib/plugin.py b/resources/lib/plugin.py index a22f0cf..5573241 100644 --- a/resources/lib/plugin.py +++ b/resources/lib/plugin.py @@ -749,6 +749,7 @@ def iptv(params): 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 @@ -776,10 +777,7 @@ def create_iptv_settings(): 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. - for enabled in (False, True): - xbmc.executeJSONRPC(json.dumps({'jsonrpc': '2.0', 'id': 1, 'method': 'Addons.SetAddonEnabled', - 'params': {'addonid': 'pvr.iptvsimple', 'enabled': enabled}})) - xbmc.sleep(3000) + kodimov.restart_iptv_simple() except: show_notification(addon.getLocalizedString(30324)) diff --git a/service.py b/service.py index 2ce0e98..80c51ef 100644 --- a/service.py +++ b/service.py @@ -10,6 +10,7 @@ import xbmcgui from resources.lib.proxy import Proxy from resources.lib.addon import * from resources.lib.log import LOG +from resources.lib import kodimov def export_epg(): from datetime import datetime, timedelta @@ -41,10 +42,19 @@ if __name__ == '__main__': # Refreshes the TV guide channel list (new channels, new numbers) and the # programme guide a minute after Kodi starts and then every 6 hours. Opening the add-on also renews the 10-day Movistar login. next_export = time.time() + 60 + try: + pvr_dir = translatePath(xbmcaddon.Addon('pvr.iptvsimple').getAddonInfo('profile')) + restart_iptv = kodimov.use_hourly_iptv_refresh(pvr_dir, 'kodimovplus') + except RuntimeError: # IPTV Simple not installed or disabled + restart_iptv = False + player = xbmc.Player() monitor = xbmc.Monitor() while not monitor.abortRequested(): if monitor.waitForAbort(1): break + if restart_iptv and not player.isPlaying(): # restarting stops live TV + restart_iptv = False + kodimov.restart_iptv_simple() if time.time() >= next_export: next_export = time.time() + 6 * 3600 if addon.getSettingBool('auto_export_epg'): # channels + programme guide