1.0.0+kodimov.9: get a new guide into Kodi right after start or update

Kodi keeps its own copy of the programme guide and fetches it again only
when IPTV Simple reloads its files, on its refresh timer; restarting IPTV
Simple is not enough. After the first refresh following a Kodi start or
add-on update, if the guide changed and nothing is playing, restart IPTV
Simple with a 1-minute timer, wait for the reload, then restart it with
the hourly timer again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
XoséandClaude Opus 5.5 committed 2026-11-10 08:51:51 +01:00
1 parent 5df60a1fb8
commit e16dd66f63
5 files changed
+50 -16

No files matched your search

+32 -8
View File
@@ -212,11 +212,12 @@ 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."""
def set_iptv_refresh(pvr_dir, addon_id, minutes=60):
"""Makes the IPTV Simple instances that read this add-on's files reload the
channel list and programme guide every few minutes. Each reload also makes
Kodi fetch the guide again. TV guide setups before kodimov.7 reloaded only
once a day, at 4:00. Returns True if a file changed (IPTV Simple must be
restarted to use it)."""
import glob
import re
changed = False
@@ -225,15 +226,38 @@ def use_hourly_iptv_refresh(pvr_dir, addon_id):
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')):
for setting, value in (('m3uRefreshMode', '1'), ('m3uRefreshIntervalMins', str(minutes))):
new = re.sub(r'<setting id="{}"[^>]*?(/>|>[^<]*</setting>)'.format(setting),
'<setting id="{}">{}</setting>'.format(setting, value), new)
if write_if_changed(filename, new):
LOG('use_hourly_iptv_refresh: updated {}'.format(filename))
if new != content:
write_if_changed(filename, new)
LOG('set_iptv_refresh: {} minutes in {}'.format(minutes, filename))
changed = True
return changed
def reload_iptv_guide(pvr_dir, addon_id):
"""Gets a new programme guide into Kodi now instead of at the next hourly
reload. Restarting IPTV Simple isn't enough: Kodi keeps its own copy of the
guide and fetches it again only when IPTV Simple reloads, which happens on
its timer. So restart it with a 1-minute timer, wait for that reload, then
restart it with the hourly timer. Restarting stops live TV, so this does
nothing if something is playing."""
import xbmc
monitor, player = xbmc.Monitor(), xbmc.Player()
if player.isPlaying(): return
if not set_iptv_refresh(pvr_dir, addon_id, 1): return
try:
restart_iptv_simple()
monitor.waitForAbort(90)
finally:
set_iptv_refresh(pvr_dir, addon_id, 60)
while player.isPlaying(): # until then it keeps reloading every minute
if monitor.waitForAbort(10): return
if not monitor.abortRequested():
restart_iptv_simple()
def restart_iptv_simple():
"""Restarts IPTV Simple so it loads its instance settings again."""
import xbmc
+1 -1
View File
@@ -1566,7 +1566,7 @@ class Movistar(object):
if self.add_extra_channels:
res.extend(kodimov.extra_channels_xmltv(self.net.session))
res.append('</tv>\n')
kodimov.write_if_changed(filename, ''.join(res))
return kodimov.write_if_changed(filename, ''.join(res))
def save_credentials(self, username, password):
from .b64 import encode_base64
+10 -3
View File
@@ -787,7 +787,7 @@ def export_channels_now():
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):
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)
@@ -804,7 +804,14 @@ def export_epg_now(quiet=False):
if True: #not addon.getSettingBool('use_external_epg'):
notify(addon.getLocalizedString(30311))
m.export_epg_to_xml(epg_filename, addon.getSettingInt('export_days'), report_progress, only_subscribed)
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))
@@ -900,7 +907,7 @@ def router(paramstring):
elif params['action'] == 'create_iptv_settings':
create_iptv_settings()
elif params['action'] == 'export_epg_now':
export_epg_now(quiet=params.get('quiet') == '1')
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']: