From 8898e8500cebb4759a4664309c9cd70b75a0038e Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 13:15:30 +0200 Subject: [PATCH 01/19] Prepare python3 and fix encoding issue. --- context.py | 2 + contextEPG.py | 2 + default.py | 14 +- language.py | 3 +- main.py | 358 +++++++++++++++++++++++++------------------------- server.py | 2 + 6 files changed, 197 insertions(+), 184 deletions(-) diff --git a/context.py b/context.py index ec28ded..ea7ce8e 100644 --- a/context.py +++ b/context.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import urllib import xbmc diff --git a/contextEPG.py b/contextEPG.py index 646a3d1..71354f6 100644 --- a/contextEPG.py +++ b/contextEPG.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import locale import time from datetime import datetime diff --git a/default.py b/default.py index 7916d35..9b921a9 100644 --- a/default.py +++ b/default.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals import xbmc,xbmcgui,xbmcaddon,xbmcvfs,xbmcplugin import sys import time,datetime @@ -5,7 +6,11 @@ import pytz import tzlocal import re -import urllib + +try: + from urllib.parse import quote_plus +except ImportError: + from urllib import quote_plus def log(x): xbmc.log(repr(x),xbmc.LOGERROR) @@ -24,7 +29,6 @@ def remove_formatting(label): channel = sys.argv[1] channel = channel.decode("utf8") #channel = channel.encode("utf8") -#channel = urllib.quote_plus(channel) title = sys.argv[2] date = sys.argv[3] @@ -56,9 +60,9 @@ def remove_formatting(label): program_id = cursor.execute('SELECT uid FROM programmes WHERE channelid=? AND start=?',(channel_id,start_time)).fetchone()[0] #log((channel_id, program_id, start_time)) if program_id: - channel = channel.encode("utf8") - channel = urllib.quote_plus(channel) - xbmc.executebuiltin("ActivateWindow(videos,plugin://plugin.video.iptv.recorder/broadcast/%s/%s,return)" % (program_id,channel)) + channel_encoded = channel.encode("utf8") + channel_encoded = quote_plus(channel_encoded) + xbmc.executebuiltin("ActivateWindow(videos,plugin://plugin.video.iptv.recorder/broadcast/%s/%s,return)" % (program_id,channel_encoded)) except Exception as e: #log(e) diff --git a/language.py b/language.py index e53858d..195df0a 100644 --- a/language.py +++ b/language.py @@ -1,4 +1,5 @@ #! /usr/bin/python +from __future__ import unicode_literals __strings = {} @@ -17,7 +18,7 @@ ids_range = range(30000, 31000) ids_reserved = [int(m.msgctxt[1:]) for m in po] ids_available = [x for x in ids_range if x not in ids_reserved] - print "warning: missing translation for", missing + print("warning: missing translation for %s" % missing) for text in missing: id = ids_available.pop(0) entry = polib.POEntry( diff --git a/main.py b/main.py index 2e1f2be..fbb082f 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +from __future__ import unicode_literals + from xbmcswift2 import Plugin, ListItem from HTMLParser import HTMLParser from collections import namedtuple @@ -25,7 +27,11 @@ import sys import threading import time -import urllib +try: + from urllib.parse import quote, quote_plus, unquote_plus +except ImportError: + from urllib import quote, quote_plus, unquote_plus + import uuid import xbmc, xbmcaddon, xbmcvfs, xbmcgui, xbmcplugin @@ -43,7 +49,7 @@ def log(v): big_list_view = True -if plugin.get_setting("multiline") == "true": +if plugin.get_setting('multiline', unicode) == "true": CR = "[CR]" else: CR = "" @@ -115,7 +121,6 @@ def find(path): @plugin.route('/play_channel/') def play_channel(channelname): channelname = channelname.decode("utf8") - #channelname = urllib.quote_plus(channelname.encode("utf8")) conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile'))) c = conn.cursor() @@ -132,7 +137,6 @@ def play_channel(channelname): @plugin.route('/play_channel_external/') def play_channel_external(channelname): channelname = channelname.decode("utf8") - #channelname = urllib.quote_plus(channelname.encode("utf8")) conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile'))) c = conn.cursor() @@ -143,9 +147,9 @@ def play_channel_external(channelname): uid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel if url: - cmd = [plugin.get_setting('external.player')] + cmd = [plugin.get_setting('external.player', unicode)] - args = plugin.get_setting('external.player.args') + args = plugin.get_setting('external.player.args', unicode) if args: cmd.append(args) @@ -157,9 +161,9 @@ def play_channel_external(channelname): @plugin.route('/play_external/') def play_external(path): - cmd = [plugin.get_setting('external.player')] + cmd = [plugin.get_setting('external.player', unicode)] - args = plugin.get_setting('external.player.args') + args = plugin.get_setting('external.player.args', unicode) if args: cmd.append(args) @@ -220,7 +224,7 @@ def jobs(): if url: context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=echannelname)))) - if plugin.get_setting('external.player'): + if plugin.get_setting('external.player', unicode): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=echannelname)))) @@ -259,7 +263,7 @@ def rules(): if url: context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=echannelname)))) - if plugin.get_setting('external.player'): + if plugin.get_setting('external.player', unicode): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=echannelname)))) if type.startswith("WATCH"): @@ -356,7 +360,7 @@ def delete_job(job, kill=True, ask=True): if ask and not (xbmcgui.Dialog().yesno("IPTV Recorder", _("Cancel Record?"))): return - if windows() and plugin.get_setting('task.scheduler') == 'true': + if windows() and plugin.get_setting('task.scheduler', unicode) == 'true': cmd = ["schtasks", "/delete", "/f", "/tn", job] subprocess.Popen(cmd, shell=True) else: @@ -405,14 +409,14 @@ def delete_ffmpeg(): def ffmpeg_location(): - ffmpeg_src = xbmc.translatePath(plugin.get_setting('ffmpeg')) + ffmpeg_src = xbmc.translatePath(plugin.get_setting('ffmpeg', unicode)) if xbmc.getCondVisibility('system.platform.android'): ffmpeg_dst = '/data/data/%s/ffmpeg' % android_get_current_appid() - if (plugin.get_setting('ffmpeg') != plugin.get_setting('ffmpeg.last')) or (not xbmcvfs.exists(ffmpeg_dst) and ffmpeg_src != ffmpeg_dst): + if (plugin.get_setting('ffmpeg', unicode) != plugin.get_setting('ffmpeg.last', unicode)) or (not xbmcvfs.exists(ffmpeg_dst) and ffmpeg_src != ffmpeg_dst): xbmcvfs.copy(ffmpeg_src, ffmpeg_dst) - plugin.set_setting('ffmpeg.last',plugin.get_setting('ffmpeg')) + plugin.set_setting('ffmpeg.last',plugin.get_setting('ffmpeg', unicode)) ffmpeg = ffmpeg_dst else: @@ -565,10 +569,11 @@ def get_utc_from_string(date_string): return utcnow.replace(day=int(day), month=int(month), year=int(year), hour=int(hour), minute=int(minute), second=0, microsecond=0) - timedelta(seconds=utc_offset) +def write_in_file(file, string): + file.write(string.encode('utf8')) def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, channelid=None, channelname=None, start=None,stop=None, play=False, title=None): #TODO check for ffmpeg process already recording if job is re-added - #channelname = urllib.unquote_plus(channelname) conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() @@ -615,7 +620,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, if aheaders: for h in aheaders: k, v = h.split('=', 1) - headers[k] = urllib.unquote_plus(v) + headers[k] = unquote_plus(v) local_starttime = utc2local(start) local_endtime = utc2local(stop) @@ -669,8 +674,8 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, if job: return - before = int(plugin.get_setting('minutes.before') or "0") - after = int(plugin.get_setting('minutes.after') or "0") + before = int(plugin.get_setting('minutes.before', unicode) or "0") + after = int(plugin.get_setting('minutes.after', unicode) or "0") local_starttime = local_starttime - timedelta(minutes=before) local_endtime = local_endtime + timedelta(minutes=after) @@ -684,8 +689,8 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, length = local_endtime - local_starttime seconds = total_seconds(length) - kodi_recordings = xbmc.translatePath(plugin.get_setting('recordings')) - ffmpeg_recordings = plugin.get_setting('ffmpeg.recordings') or kodi_recordings + kodi_recordings = xbmc.translatePath(plugin.get_setting('recordings', unicode)) + ffmpeg_recordings = plugin.get_setting('ffmpeg.recordings', unicode) or kodi_recordings if series: dir = os.path.join(kodi_recordings, "TV", folder) ffmpeg_dir = os.path.join(ffmpeg_recordings, "TV", folder) @@ -698,15 +703,15 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, xbmcvfs.mkdirs(dir) path = os.path.join(dir, filename) json_path = path + '.json' - path = path + '.' + plugin.get_setting("ffmpeg.ext") + path = path + '.' + plugin.get_setting('ffmpeg.ext', unicode) ffmpeg = ffmpeg_location() if not ffmpeg: return - if plugin.get_setting('json',bool): + if plugin.get_setting('json', bool): json_nfo = json.dumps(nfo) f = xbmcvfs.File(json_path,'w') - f.write(json_nfo) + write_in_file(f, json_nfo) f.close() cmd = [ffmpeg] @@ -718,23 +723,23 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, probe_cmd = cmd - ffmpeg_recording_path = os.path.join(ffmpeg_dir, filename + '.' + plugin.get_setting("ffmpeg.ext")) + ffmpeg_recording_path = os.path.join(ffmpeg_dir, filename + '.' + plugin.get_setting('ffmpeg.ext', unicode)) cmd = probe_cmd + ["-y", "-t", str(seconds), "-fflags","+genpts","-vcodec","copy","-acodec","copy"] - ffmpeg_reconnect = plugin.get_setting('ffmpeg.reconnect',bool) + ffmpeg_reconnect = plugin.get_setting('ffmpeg.reconnect', bool) if ffmpeg_reconnect: cmd = cmd + ["-reconnect_at_eof", "1", "-reconnect_streamed", "1", "-reconnect_delay_max", "300"] - ffmpeg_args = plugin.get_setting('ffmpeg.args') + ffmpeg_args = plugin.get_setting('ffmpeg.args', unicode) if ffmpeg_args: cmd = cmd + ffmpeg_args.split(' ') - if (plugin.get_setting('ffmpeg.pipe') == 'true') and not (windows() and (plugin.get_setting('task.scheduler') == 'true')): + if (plugin.get_setting('ffmpeg.pipe', unicode) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): cmd = cmd + ['-f', 'mpegts','-'] else: - cmd.append(ffmpeg_recording_path.encode('utf8')) + cmd.append(ffmpeg_recording_path) - post_command = plugin.get_setting('post.command') + post_command = plugin.get_setting('post.command', unicode) post_cmd = post_command.split(' ') - post_cmd = [s.replace("$p",ffmpeg_recording_path.encode('utf8')).replace("$d",ffmpeg_dir.encode('utf8')).replace("$f",filename.encode('utf8') + '.' + plugin.get_setting("ffmpeg.ext")) for s in post_cmd] + post_cmd = [s.replace("$p",ffmpeg_recording_path).replace("$d",ffmpeg_dir).replace("$f",filename + '.' + plugin.get_setting('ffmpeg.ext', unicode)) for s in post_cmd] directory = "special://profile/addon_data/plugin.video.iptv.recorder/jobs/" xbmcvfs.mkdirs(directory) @@ -742,95 +747,95 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, pyjob = directory + job + ".py" f = xbmcvfs.File(pyjob, 'wb') - f.write("# -*- coding: utf-8 -*-\n") - f.write("import os, subprocess, time\n") + write_in_file(f, "# -*- coding: utf-8 -*-\n") + write_in_file(f, "import os, subprocess, time\n") - debug = plugin.get_setting('debug.ffmpeg') == 'true' + debug = plugin.get_setting('debug.ffmpeg', unicode) == 'true' if watch == False and remind == False: - if not (windows() and (plugin.get_setting('task.scheduler') == 'true')): - f.write("import xbmc,xbmcvfs,xbmcgui\n") - notification = 'xbmcgui.Dialog().notification("Recording: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent')=="false") - f.write(notification.encode("utf8")) - f.write("cmd = %s\n" % repr(cmd)) + if not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + write_in_file(f, "import xbmc,xbmcvfs,xbmcgui\n") + notification = 'xbmcgui.Dialog().notification("Recording: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', unicode) == "false") + write_in_file(f, notification) + write_in_file(f, "cmd = %s\n" % repr(cmd)) if url.startswith('plugin://'): - f.write("player = xbmc.Player()\n") - f.write("player.play('%s')\n" % url.encode("utf8")) - f.write("new_url = ''\n") - f.write("for _ in range(60):\n") - f.write(" time.sleep(1)\n") - f.write(" if player.isPlaying():\n") - f.write(" new_url = player.getPlayingFile()\n") - f.write(" break\n") - f.write("time.sleep(1)\n") - f.write("player.stop()\n") - f.write("time.sleep(1)\n") - f.write("if new_url:\n") - f.write(" cmd[2] = new_url\n") + write_in_file(f, "player = xbmc.Player()\n") + write_in_file(f, "player.play('%s')\n" % url) + write_in_file(f, "new_url = ''\n") + write_in_file(f, "for _ in range(60):\n") + write_in_file(f, " time.sleep(1)\n") + write_in_file(f, " if player.isPlaying():\n") + write_in_file(f, " new_url = player.getPlayingFile()\n") + write_in_file(f, " break\n") + write_in_file(f, "time.sleep(1)\n") + write_in_file(f, "player.stop()\n") + write_in_file(f, "time.sleep(1)\n") + write_in_file(f, "if new_url:\n") + write_in_file(f, " cmd[2] = new_url\n") else: - f.write("cmd = %s\n" % repr(cmd)) + write_in_file(f, "cmd = %s\n" % repr(cmd)) if debug: - f.write("stdout = open(r'%s','w+')\n" % xbmc.translatePath(pyjob+'.stdout.txt')) - f.write("stderr = open(r'%s','w+')\n" % xbmc.translatePath(pyjob+'.stderr.txt')) - f.write("p = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, shell=%s)\n" % windows()) + write_in_file(f, "stdout = open(r'%s','w+')\n" % xbmc.translatePath(pyjob+'.stdout.txt')) + write_in_file(f, "stderr = open(r'%s','w+')\n" % xbmc.translatePath(pyjob+'.stderr.txt')) + write_in_file(f, "p = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, shell=%s)\n" % windows()) else: - if (plugin.get_setting('ffmpeg.pipe') == 'true') and not (windows() and (plugin.get_setting('task.scheduler') == 'true')): - f.write("p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=%s)\n" % windows()) + if (plugin.get_setting('ffmpeg.pipe', unicode) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + write_in_file(f, "p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=%s)\n" % windows()) else: - f.write("p = subprocess.Popen(cmd, shell=%s)\n" % windows()) - f.write("f = open(r'%s', 'w+')\n" % xbmc.translatePath(pyjob+'.pid')) - f.write("f.write(repr(p.pid))\n") - f.write("f.close()\n") - if (plugin.get_setting('ffmpeg.pipe') == 'true') and not (windows() and (plugin.get_setting('task.scheduler') == 'true')): - f.write('video = xbmcvfs.File(r"%s","wb")\n' % path.encode('utf8')) - f.write('playing = False\n') - f.write("while True:\n") - f.write(" data = p.stdout.read(1000000)\n") - f.write(" if data:\n") - f.write(" video.write(data)\n") - f.write(" else:\n") - f.write(" break\n") + write_in_file(f, "p = subprocess.Popen(cmd, shell=%s)\n" % windows()) + write_in_file(f, "f = open(r'%s', 'w+')\n" % xbmc.translatePath(pyjob+'.pid')) + write_in_file(f, "f.write(repr(p.pid).encode('utf-8'))\n") + write_in_file(f, "f.close()\n") + if (plugin.get_setting('ffmpeg.pipe', unicode) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + write_in_file(f, 'video = xbmcvfs.File(r"%s","wb")\n' % path) + write_in_file(f, 'playing = False\n') + write_in_file(f, "while True:\n") + write_in_file(f, " data = p.stdout.read(1000000)\n") + write_in_file(f, " if data:\n") + write_in_file(f, " video.write(data)\n") + write_in_file(f, " else:\n") + write_in_file(f, " break\n") if play: - f.write(" if not playing:\n") - f.write(" xbmc.Player().play(r'%s')\n" % path.encode('utf8')) - f.write(" playing = True\n") - f.write("video.close()\n") + write_in_file(f, " if not playing:\n") + write_in_file(f, " xbmc.Player().play(r'%s')\n" % path) + write_in_file(f, " playing = True\n") + write_in_file(f, "video.close()\n") else: - f.write("p.wait()\n") + write_in_file(f, "p.wait()\n") if debug: - f.write("stderr.close()\n") - f.write("stdout.close()\n") - if not (windows() and (plugin.get_setting('task.scheduler') == 'true')): - notification = 'xbmcgui.Dialog().notification("Recording finished: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent')=="false") - f.write(notification.encode("utf8")) + write_in_file(f, "stderr.close()\n") + write_in_file(f, "stdout.close()\n") + if not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + notification = 'xbmcgui.Dialog().notification("Recording finished: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', unicode)=="false") + write_in_file(f, notification) if post_command: - f.write("post_cmd = %s\n" % repr(post_cmd)) - f.write("p = subprocess.Popen(post_cmd, shell=%s)\n" % windows()) + write_in_file(f, "post_cmd = %s\n" % repr(post_cmd)) + write_in_file(f, "p = subprocess.Popen(post_cmd, shell=%s)\n" % windows()) #TODO copy file somewhere else elif remind == True: - cmd = 'xbmcgui.Dialog().notification("%s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent')=="false") - f.write("import xbmc, xbmcgui\n") - f.write("%s\n" % cmd.encode("utf8")) + cmd = 'xbmcgui.Dialog().notification("%s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', unicode)=="false") + write_in_file(f, "import xbmc, xbmcgui\n") + write_in_file(f, "%s\n" % cmd) else: - if (plugin.get_setting('external.player.watch') == 'true') or (windows() and (plugin.get_setting('task.scheduler') == 'true')): - cmd = [plugin.get_setting('external.player'), plugin.get_setting('external.player.args'), url] - f.write("cmd = %s\n" % repr(cmd)) - f.write("p = subprocess.Popen(cmd, shell=%s)\n" % windows()) + if (plugin.get_setting('external.player.watch', unicode) == 'true') or (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + cmd = [plugin.get_setting('external.player', unicode), plugin.get_setting('external.player.args', unicode), url] + write_in_file(f, "cmd = %s\n" % repr(cmd)) + write_in_file(f, "p = subprocess.Popen(cmd, shell=%s)\n" % windows()) else: cmd = 'xbmc.Player().play("%s")\n' % url - f.write("import xbmc\n") - f.write("%s\n" % cmd.encode("utf8")) + write_in_file(f, "import xbmc\n") + write_in_file(f, "%s\n" % cmd) f.close() - if windows() and (plugin.get_setting('task.scheduler') == 'true') and remind == False: + if windows() and (plugin.get_setting('task.scheduler', unicode) == 'true') and remind == False: if immediate: cmd = 'RunScript(%s)' % (pyjob) xbmc.executebuiltin(cmd) else: st = "%02d:%02d" % (local_starttime.hour, local_starttime.minute) sd = "%02d/%02d/%04d" % (local_starttime.day, local_starttime.month, local_starttime.year) - cmd = ["schtasks", "/create", "/f", "/tn", job, "/sc", "once", "/st", st, "/sd", sd, "/tr", "%s %s" % (xbmc.translatePath(plugin.get_setting('python')), xbmc.translatePath(pyjob))] + cmd = ["schtasks", "/create", "/f", "/tn", job, "/sc", "once", "/st", st, "/sd", sd, "/tr", "%s %s" % (xbmc.translatePath(plugin.get_setting('python', unicode)), xbmc.translatePath(pyjob))] subprocess.Popen(cmd, shell=True) else: now = datetime.now() @@ -904,8 +909,8 @@ def renew_jobs(): local_starttime = utc2local(start) local_endtime = utc2local(stop) - before = int(plugin.get_setting('minutes.before') or "0") - after = int(plugin.get_setting('minutes.after') or "0") + before = int(plugin.get_setting('minutes.before', unicode) or "0") + after = int(plugin.get_setting('minutes.after', unicode) or "0") local_starttime = local_starttime - timedelta(minutes=before) local_endtime = local_endtime + timedelta(minutes=after) @@ -927,7 +932,7 @@ def renew_jobs(): #TODO reduce time of job if already started - if windows() and (plugin.get_setting('task.scheduler') == 'true'): + if windows() and (plugin.get_setting('task.scheduler', unicode) == 'true'): if immediate: cmd = 'RunScript(%s)' % (pyjob) xbmc.executebuiltin(cmd) @@ -954,21 +959,21 @@ def renew_jobs(): def sane_name(name): if not name: return - if windows() or (plugin.get_setting('filename.urlencode') == 'true'): - name = urllib.quote(name.encode("utf8")) + if windows() or (plugin.get_setting('filename.urlencode', unicode) == 'true'): + name = quote(name.encode('utf-8')) name = name.replace("%20",' ') name = name.replace('/',"%2F") else: - quote = {'"': '%22', '|': '%7C', '*': '%2A', '/': '%2F', '<': '%3C', ':': '%3A', '\\': '%5C', '?': '%3F', '>': '%3E'} - for char in quote: - name = name.replace(char, quote[char]) + _quote = {'"': '%22', '|': '%7C', '*': '%2A', '/': '%2F', '<': '%3C', ':': '%3A', '\\': '%5C', '?': '%3F', '>': '%3E'} + for char in _quote: + name = name.replace(char, _quote[char]) return name def refresh(): containerAddonName = xbmc.getInfoLabel('Container.PluginName') AddonName = xbmcaddon.Addon().getAddonInfo('id') - if (containerAddonName == AddonName) and (plugin.get_setting('refresh') == 'true') : + if (containerAddonName == AddonName) and (plugin.get_setting('refresh', unicode) == 'true') : xbmc.executebuiltin('Container.Refresh') @@ -1433,7 +1438,6 @@ def remind_always_search_plot(channelid, channelname): @plugin.route('/broadcast//') def broadcast(programmeid, channelname): channelname = channelname.decode("utf8") - #channelname = urllib.unquote_plus(channelname) #log(channelname) conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) @@ -1542,7 +1546,7 @@ def broadcast(programmeid, channelname): 'is_playable': True, }) - if plugin.get_setting('external.player'): + if plugin.get_setting('external.player', unicode): items.append({ 'label': _("Play Channel External") + " - %s" % (channelname), 'path': plugin.url_for(play_channel_external, channelname=echannelname), @@ -1552,9 +1556,9 @@ def broadcast(programmeid, channelname): 'is_playable': True, }) - if xbmc.getCondVisibility('System.HasAddon(%s)' % plugin.get_setting('meta')) == 1: - icon = xbmcaddon.Addon(plugin.get_setting('meta')).getAddonInfo('icon') - name = xbmcaddon.Addon(plugin.get_setting('meta')).getAddonInfo('name') + if xbmc.getCondVisibility('System.HasAddon(%s)' % plugin.get_setting('meta', unicode)) == 1: + icon = xbmcaddon.Addon(plugin.get_setting('meta', unicode)).getAddonInfo('icon') + name = xbmcaddon.Addon(plugin.get_setting('meta', unicode)).getAddonInfo('name') if episode: #log((channelname,channelid,title,episode)) tvdb_url = "http://thetvdb.com/api/GetSeries.php?seriesname=%s&language=en" % title @@ -1570,27 +1574,27 @@ def broadcast(programmeid, channelname): found = True season = match.group(1) ep = match.group(2) - meta_url = "plugin://%s/tv/play/%s/%d/%d/library" % (plugin.get_setting('meta').lower(),tvdb_id,int(season),int(ep)) + meta_url = "plugin://%s/tv/play/%s/%d/%d/library" % (plugin.get_setting('meta', unicode).lower(),tvdb_id,int(season),int(ep)) items.append({ 'label': "%s - %s %s" % (name,title,episode), 'path': meta_url, 'thumbnail': icon, }) if not found: - meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta').lower(),urllib.quote_plus(title.encode("utf8"))) + meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta', unicode).lower(),quote_plus(title.encode("utf8"))) items.append({ 'label': "%s - %s" % (name,title), 'path': meta_url, 'thumbnail': icon, }) else: - meta_url = "plugin://%s/movies/search_term/%s/1" % (plugin.get_setting('meta').lower(),urllib.quote_plus(title.encode("utf8"))) + meta_url = "plugin://%s/movies/search_term/%s/1" % (plugin.get_setting('meta', unicode).lower(),quote_plus(title.encode("utf8"))) items.append({ 'label': "%s - Movie - %s" % (name,title), 'path': meta_url, 'thumbnail': icon, }) - meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta').lower(),urllib.quote_plus(title.encode("utf8"))) + meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta', unicode).lower(),quote_plus(title.encode("utf8"))) items.append({ 'label': "%s - TV Show - %s" % (name,title), 'path': meta_url, @@ -1684,7 +1688,7 @@ def search_title_input(title): def search_title(title): title = title.decode("utf8") - if plugin.get_setting('add.context.searches') == 'true': + if plugin.get_setting('add.context.searches', unicode) == 'true': searches = plugin.get_storage('search_title') searches[title] = '' @@ -1834,7 +1838,7 @@ def search_categories_input(categories): def search_categories(categories): categories = categories.decode("utf8") - if plugin.get_setting('add.context.searches') == 'true': + if plugin.get_setting('add.context.searches', unicode) == 'true': searches = plugin.get_storage('search_categories') searches[categories] = '' @@ -1879,7 +1883,7 @@ def channel(channelid,channelname): conn.commit() conn.close() - if plugin.get_setting('add.favourite.channel') == 'true': + if plugin.get_setting('add.favourite.channel', unicode) == 'true': add_favourite_channel(channelname.encode("utf8"), channelid.encode("utf8"), thumbnail) return listing(programmes, scroll=True, channelname=echannelname) @@ -1955,7 +1959,7 @@ def movie(title, date): def listing(programmes, scroll=False, channelname=None): if channelname: - channelname = urllib.unquote_plus(channelname.decode("utf8")) + channelname = unquote_plus(channelname.decode("utf8")) conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() @@ -2011,14 +2015,14 @@ def listing(programmes, scroll=False, channelname=None): starttime = utc2local(start) endtime = utc2local(stop) - if plugin.get_setting('show.categories') == 'true': + if plugin.get_setting('show.categories', unicode) == 'true': categories_label = "[COLOR grey]%s[/COLOR]" % categories else: categories_label = "" if endtime < now: color = "orange" - if plugin.get_setting('show.finished') == 'false': + if plugin.get_setting('show.finished', unicode) == 'false': continue else: if current == None: @@ -2036,10 +2040,10 @@ def listing(programmes, scroll=False, channelname=None): else: stitle = "[COLOR %s]%s[/COLOR][COLOR grey]%s[/COLOR]" % (color, title, episode) - if (plugin.get_setting('hide.channel.name') == "true") and thumbnail: + if (plugin.get_setting('hide.channel.name', unicode) == "true") and thumbnail: channelname_label = "" else: - channelname_label = urllib.unquote_plus(pchannelname) + channelname_label = unquote_plus(pchannelname) label = "%02d:%02d [COLOR grey]%s[/COLOR] %s %s %s%s %s" % (starttime.hour, starttime.minute, day(starttime), channelname_label, categories_label, CR, stitle, recording) @@ -2070,7 +2074,7 @@ def listing(programmes, scroll=False, channelname=None): if url: context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=echannelname)))) - if plugin.get_setting('external.player'): + if plugin.get_setting('external.player', unicode): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=echannelname)))) context_items.append((echannelname, 'ActivateWindow(%s,%s,return)' % (xbmcgui.getCurrentWindowId(), plugin.url_for('channel', channelid=echannelid, channelname=echannelname)))) @@ -2099,7 +2103,7 @@ def listing(programmes, scroll=False, channelname=None): conn.commit() conn.close() - if scroll and plugin.get_setting('scroll.now') == 'true': + if scroll and plugin.get_setting('scroll.now', unicode) == 'true': threading.Thread(target=focus,args=[current]).start() return items @@ -2108,7 +2112,7 @@ def listing(programmes, scroll=False, channelname=None): def focus(i): #TODO find way to check this has worked (clist.getSelectedPosition returns -1) - xbmc.sleep(int(plugin.get_setting('scroll.ms') or "0")) + xbmc.sleep(int(plugin.get_setting('scroll.ms', unicode) or "0")) #TODO deal with hidden .. win = xbmcgui.Window(xbmcgui.getCurrentWindowId()) cid = win.getFocusId() @@ -2188,7 +2192,7 @@ def group(channelgroup=None,section=None): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() - if plugin.get_setting('sort.channels') == 'true': + if plugin.get_setting('sort.channels', unicode) == 'true': order = " ORDER by name" else: order = "" @@ -2202,22 +2206,22 @@ def group(channelgroup=None,section=None): logos = dict((x[0],x[1]) for x in streams) collection = channels - show_now_next = plugin.get_setting('show.now.next.all') == "true" + show_now_next = plugin.get_setting('show.now.next.all', unicode) == "true" elif section == "FAVOURITES": favourite_channels = cursor.execute("SELECT * FROM favourites ORDER BY channelname").fetchall() streams = cursor.execute("SELECT * FROM streams" + order).fetchall() collection = favourite_channels - show_now_next = plugin.get_setting('show.now.next.favourites') == "true" + show_now_next = plugin.get_setting('show.now.next.favourites', unicode) == "true" else: channels = cursor.execute("SELECT * FROM channels" + order).fetchall() #channel_logos = {x[1]:x[3] for x in channels} channel_logos = dict((x[1],x[3]) for x in channels) if channelgroup == "All Channels": streams = cursor.execute("SELECT * FROM streams" + order).fetchall() - show_now_next = plugin.get_setting('show.now.next.all') == "true" + show_now_next = plugin.get_setting('show.now.next.all', unicode) == "true" else: streams = cursor.execute("SELECT * FROM streams WHERE groups=?" + order, (channelgroup, )).fetchall() - show_now_next = plugin.get_setting('show.now.next.lists') == "true" + show_now_next = plugin.get_setting('show.now.next.lists', unicode) == "true" collection = streams favourites = cursor.execute("SELECT channelname FROM favourites").fetchall() @@ -2266,7 +2270,6 @@ def group(channelgroup=None,section=None): logo = tvg_logo #channelname = channelname.encode("ascii") - #channelname = urllib.unquote_plus(channelname) #channelname = channelname.decode("utf8") description = "" @@ -2278,7 +2281,7 @@ def group(channelgroup=None,section=None): title = now_titles[channelid][0] local_start = utc2local(now_titles[channelid][1]) description = now_titles[channelid][2] - if plugin.get_setting('show.categories') == 'true': + if plugin.get_setting('show.categories', unicode) == 'true': categories = "[COLOR grey]%s[/COLOR]" % now_titles[channelid][3] else: categories = "" @@ -2289,7 +2292,7 @@ def group(channelgroup=None,section=None): if channelid in next_titles: title = next_titles[channelid][0] local_start = utc2local(next_titles[channelid][1]) - if plugin.get_setting('show.categories') == 'true': + if plugin.get_setting('show.categories', unicode) == 'true': next_categories = "[COLOR grey]%s[/COLOR]" % next_titles[channelid][2] else: next_categories = "" @@ -2297,10 +2300,10 @@ def group(channelgroup=None,section=None): else: next_title = "" - if plugin.get_setting('show.now.next.hide.empty') == "true" and not now_title and not next_title: + if plugin.get_setting('show.now.next.hide.empty', unicode) == "true" and not now_title and not next_title: continue - if (plugin.get_setting('hide.channel.name') == "true") and logo: + if (plugin.get_setting('hide.channel.name', unicode) == "true") and logo: label = "%s %s%s" % (now_title, CR, next_title) else: label = u"%s %s %s%s" % (channelname, now_title, CR, next_title) @@ -2311,29 +2314,29 @@ def group(channelgroup=None,section=None): context_items = [] - channelname = channelname.encode("utf8") + channelname_encoded = channelname.encode("utf8") if channelid: - channelid =channelid.encode("utf8") + channelid_encoded = channelid.encode("utf8") if url: - context_items.append((_("Add One Time Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_one_time, channelname=channelname)))) - context_items.append((_("Add Daily Time Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_daily_time, channelname=channelname)))) - context_items.append((_("Add Weekly Time Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_weekly_time, channelname=channelname)))) - context_items.append((_("Record and Play"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_and_play, channelname=channelname)))) + context_items.append((_("Add One Time Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_one_time, channelname=channelname_encoded)))) + context_items.append((_("Add Daily Time Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_daily_time, channelname=channelname_encoded)))) + context_items.append((_("Add Weekly Time Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_weekly_time, channelname=channelname_encoded)))) + context_items.append((_("Record and Play"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_and_play, channelname=channelname_encoded)))) if channelid: - context_items.append((_("Add Title Search Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_always_search, channelid=channelid, channelname=channelname)))) - context_items.append((_("Add Plot Search Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_always_search_plot, channelid=channelid, channelname=channelname)))) - context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=channelname)))) - if plugin.get_setting('external.player'): - context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=channelname)))) + context_items.append((_("Add Title Search Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_always_search, channelid=channelid_encoded, channelname=channelname_encoded)))) + context_items.append((_("Add Plot Search Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_always_search_plot, channelid=channelid_encoded, channelname=channelname_encoded)))) + context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=channelname_encoded)))) + if plugin.get_setting('external.player', unicode): + context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=channelname_encoded)))) if channelname not in favourites and channelid: - context_items.append((_("Add Favourite Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(add_favourite_channel, channelname=channelname, channelid=channelid, thumbnail=thumbnail)))) + context_items.append((_("Add Favourite Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(add_favourite_channel, channelname=channelname_encoded, channelid=channelid_encoded, thumbnail=thumbnail)))) else: - context_items.append((_("Remove Favourite Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(remove_favourite_channel, channelname=channelname)))) + context_items.append((_("Remove Favourite Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(remove_favourite_channel, channelname=channelname_encoded)))) if url and channelid: - path = plugin.url_for(channel, channelid=channelid, channelname=channelname) + path = plugin.url_for(channel, channelid=channelid_encoded, channelname=channelname_encoded) else: path = sys.argv[0] @@ -2621,7 +2624,7 @@ def delete_recording(label, path): if not (xbmcgui.Dialog().yesno("IPTV Recorder", "[COLOR red]" + _("Delete Recording?") + "[/COLOR]", label)): return xbmcvfs.delete(path) - length = int(len('.' + plugin.get_setting("ffmpeg.ext"))) + length = int(len('.' + plugin.get_setting('ffmpeg.ext', unicode))) xbmcvfs.delete(path[:-length]+'.json') refresh() @@ -2632,13 +2635,13 @@ def delete_all_recordings(): if not result: return - dir = plugin.get_setting('recordings') + dir = plugin.get_setting('recordings', unicode) dirs, files = find(dir) for file in sorted(files): - if file.endswith('.' + plugin.get_setting("ffmpeg.ext")): + if file.endswith('.' + plugin.get_setting('ffmpeg.ext', unicode)): success = xbmcvfs.delete(file) if success: - length = int(len('.' + plugin.get_setting("ffmpeg.ext"))) + length = int(len('.' + plugin.get_setting('ffmpeg.ext', unicode))) json_file = file[:-length]+'.json' xbmcvfs.delete(json_file) @@ -2654,7 +2657,7 @@ def find_files(root): found_files = found_files + find_files(path) file_list = [] for file in files: - if file.endswith('.' + plugin.get_setting("ffmpeg.ext")): + if file.endswith('.' + plugin.get_setting('ffmpeg.ext', unicode)): file = os.path.join(xbmc.translatePath(root), file) file_list.append(file) return found_files + file_list @@ -2662,7 +2665,7 @@ def find_files(root): @plugin.route('/recordings') def recordings(): - dir = plugin.get_setting('recordings') + dir = plugin.get_setting('recordings', unicode) found_files = find_files(dir) items = [] @@ -2693,14 +2696,14 @@ def recordings(): label = os.path.splitext(os.path.basename(path))[0] description = "" starts.append("0") - label = urllib.unquote_plus(label) + label = unquote_plus(label) label = label.decode("utf8") context_items = [] context_items.append((_("Delete Recording"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(delete_recording, label=label.encode("utf8"), path=path)))) context_items.append((_("Delete All Recordings"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(delete_all_recordings)))) - if plugin.get_setting('external.player'): + if plugin.get_setting('external.player', unicode): context_items.append((_("External Player"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_external, path=path)))) #context_items.append((_("Convert to mp4"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(convert, path=path)))) @@ -2782,7 +2785,7 @@ def xmltv(): for x in ["1","2"]: dialog.update(0, message=_("Finding streams")) - mode = plugin.get_setting('external.m3u.'+x) + mode = plugin.get_setting('external.m3u.'+x, unicode) if mode == "0": if x == "1": try: @@ -2797,9 +2800,9 @@ def xmltv(): else: path = "" elif mode == "1": - path = plugin.get_setting('external.m3u.file.'+x) + path = plugin.get_setting('external.m3u.file.'+x, unicode) else: - path = plugin.get_setting('external.m3u.url.'+x) + path = plugin.get_setting('external.m3u.url.'+x, unicode) if path: @@ -2816,7 +2819,7 @@ def xmltv(): log(encoding) data = data.decode(encoding['encoding']) - settings_shift = float(plugin.get_setting('external.m3u.shift.'+x)) + settings_shift = float(plugin.get_setting('external.m3u.shift.'+x, unicode)) global_shift = settings_shift header = re.search('#EXTM3U(.*)', data) @@ -2836,7 +2839,6 @@ def xmltv(): if ',' in re.sub('tvg-[a-z]+"[^"]*"','',channel[0], flags=re.I): name = channel[0].rsplit(',', 1)[-1].strip() #name = name.encode("utf8") - #name = urllib.quote_plus(name) tvg_name = re.search('tvg-name="(.*?)"', channel[0], flags=re.I) if tvg_name: @@ -2860,8 +2862,8 @@ def xmltv(): shifts[tvg_id] = float(tvg_shift) + settings_shift url = channel[1] - search = plugin.get_setting('m3u.regex.search') - replace = plugin.get_setting('m3u.regex.replace') + search = plugin.get_setting('m3u.regex.search', unicode) + replace = plugin.get_setting('m3u.regex.replace', unicode) if search: url = re.sub(search, replace, url) @@ -2878,7 +2880,7 @@ def xmltv(): for x in ["1","2"]: - mode = plugin.get_setting('external.xmltv.'+x) + mode = plugin.get_setting('external.xmltv.'+x, unicode) if mode == "0": if x == "1": try: @@ -2892,9 +2894,9 @@ def xmltv(): else: path = "" elif mode == "1": - path = plugin.get_setting('external.xmltv.file.'+x) + path = plugin.get_setting('external.xmltv.file.'+x, unicode) else: - path = plugin.get_setting('external.xmltv.url.'+x) + path = plugin.get_setting('external.xmltv.url.'+x, unicode) if path: @@ -2915,7 +2917,7 @@ def xmltv(): decompressedFile = gzip.GzipFile(fileobj=compressedFile, mode='rb') data = decompressedFile.read() f = xbmcvfs.File(xml, "wb") - f.write(data) + write_in_file(f, data) f.close() else: xbmcvfs.copy(tmp, xml) @@ -2987,7 +2989,7 @@ def xmltv(): for x in ["1","2"]: - mode = plugin.get_setting('external.xmltv.'+x) + mode = plugin.get_setting('external.xmltv.'+x, unicode) if mode == "0": if x == "1": try: @@ -3001,9 +3003,9 @@ def xmltv(): else: path = "" elif mode == "1": - path = plugin.get_setting('external.xmltv.file.'+x) + path = plugin.get_setting('external.xmltv.file.'+x, unicode) else: - path = plugin.get_setting('external.xmltv.url.'+x) + path = plugin.get_setting('external.xmltv.url.'+x, unicode) if path: @@ -3059,8 +3061,8 @@ def xmltv(): title = re.search('(.*?) ''') with open(filename,'w') as f: - f.write(text) + write_in_file(f, text) xbmc.executebuiltin("UpdateLocalAddons") time.sleep(1) @@ -3390,7 +3392,7 @@ def index(): - if plugin.get_setting('show.skin',bool): + if plugin.get_setting('show.skin', bool): items.append( { 'label': "[COLOR yellow]NEW! Create Estuary (IPTV Recorder) Skin[/COLOR]", @@ -3430,7 +3432,7 @@ def index(): items.append( { 'label': _("Recordings Folder"), - 'path': plugin.get_setting('recordings'), + 'path': plugin.get_setting('recordings', unicode), 'thumbnail':get_icon_path('recordings'), 'context_menu': context_items, }) @@ -3467,7 +3469,7 @@ def index(): 'context_menu': context_items, }) - free = get_free_space_mb(xbmc.translatePath(plugin.get_setting('recordings'))) + free = get_free_space_mb(xbmc.translatePath(plugin.get_setting('recordings', unicode))) if free: items.append( { @@ -3490,7 +3492,7 @@ def index(): if big_list_view == True: - view_mode = int(plugin.get_setting('view.mode') or "0") + view_mode = int(plugin.get_setting('view.mode', unicode) or "0") if view_mode: plugin.set_view_mode(view_mode) diff --git a/server.py b/server.py index ae96b98..a43ce5e 100644 --- a/server.py +++ b/server.py @@ -1,3 +1,5 @@ +from __future__ import unicode_literals + import xbmcaddon import xbmc, xbmcgui, xbmcvfs import requests From 74e50804108cc624affde95cf3a28ea6b290679c Mon Sep 17 00:00:00 2001 From: dob! Date: Sun, 10 May 2020 15:10:25 +0200 Subject: [PATCH 02/19] Prepare python3 and fix encoding issue. --- main.py | 180 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/main.py b/main.py index fbb082f..21a8b93 100644 --- a/main.py +++ b/main.py @@ -49,7 +49,7 @@ def log(v): big_list_view = True -if plugin.get_setting('multiline', unicode) == "true": +if plugin.get_setting('multiline', str) == "true": CR = "[CR]" else: CR = "" @@ -147,9 +147,9 @@ def play_channel_external(channelname): uid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel if url: - cmd = [plugin.get_setting('external.player', unicode)] + cmd = [plugin.get_setting('external.player', str)] - args = plugin.get_setting('external.player.args', unicode) + args = plugin.get_setting('external.player.args', str) if args: cmd.append(args) @@ -161,9 +161,9 @@ def play_channel_external(channelname): @plugin.route('/play_external/') def play_external(path): - cmd = [plugin.get_setting('external.player', unicode)] + cmd = [plugin.get_setting('external.player', str)] - args = plugin.get_setting('external.player.args', unicode) + args = plugin.get_setting('external.player.args', str) if args: cmd.append(args) @@ -224,7 +224,7 @@ def jobs(): if url: context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=echannelname)))) - if plugin.get_setting('external.player', unicode): + if plugin.get_setting('external.player', str): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=echannelname)))) @@ -263,7 +263,7 @@ def rules(): if url: context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=echannelname)))) - if plugin.get_setting('external.player', unicode): + if plugin.get_setting('external.player', str): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=echannelname)))) if type.startswith("WATCH"): @@ -360,7 +360,7 @@ def delete_job(job, kill=True, ask=True): if ask and not (xbmcgui.Dialog().yesno("IPTV Recorder", _("Cancel Record?"))): return - if windows() and plugin.get_setting('task.scheduler', unicode) == 'true': + if windows() and plugin.get_setting('task.scheduler', str) == 'true': cmd = ["schtasks", "/delete", "/f", "/tn", job] subprocess.Popen(cmd, shell=True) else: @@ -409,14 +409,14 @@ def delete_ffmpeg(): def ffmpeg_location(): - ffmpeg_src = xbmc.translatePath(plugin.get_setting('ffmpeg', unicode)) + ffmpeg_src = xbmc.translatePath(plugin.get_setting('ffmpeg', str)) if xbmc.getCondVisibility('system.platform.android'): ffmpeg_dst = '/data/data/%s/ffmpeg' % android_get_current_appid() - if (plugin.get_setting('ffmpeg', unicode) != plugin.get_setting('ffmpeg.last', unicode)) or (not xbmcvfs.exists(ffmpeg_dst) and ffmpeg_src != ffmpeg_dst): + if (plugin.get_setting('ffmpeg', str) != plugin.get_setting('ffmpeg.last', str)) or (not xbmcvfs.exists(ffmpeg_dst) and ffmpeg_src != ffmpeg_dst): xbmcvfs.copy(ffmpeg_src, ffmpeg_dst) - plugin.set_setting('ffmpeg.last',plugin.get_setting('ffmpeg', unicode)) + plugin.set_setting('ffmpeg.last',plugin.get_setting('ffmpeg', str)) ffmpeg = ffmpeg_dst else: @@ -674,8 +674,8 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, if job: return - before = int(plugin.get_setting('minutes.before', unicode) or "0") - after = int(plugin.get_setting('minutes.after', unicode) or "0") + before = int(plugin.get_setting('minutes.before', str) or "0") + after = int(plugin.get_setting('minutes.after', str) or "0") local_starttime = local_starttime - timedelta(minutes=before) local_endtime = local_endtime + timedelta(minutes=after) @@ -689,8 +689,8 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, length = local_endtime - local_starttime seconds = total_seconds(length) - kodi_recordings = xbmc.translatePath(plugin.get_setting('recordings', unicode)) - ffmpeg_recordings = plugin.get_setting('ffmpeg.recordings', unicode) or kodi_recordings + kodi_recordings = xbmc.translatePath(plugin.get_setting('recordings', str)) + ffmpeg_recordings = plugin.get_setting('ffmpeg.recordings', str) or kodi_recordings if series: dir = os.path.join(kodi_recordings, "TV", folder) ffmpeg_dir = os.path.join(ffmpeg_recordings, "TV", folder) @@ -703,7 +703,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, xbmcvfs.mkdirs(dir) path = os.path.join(dir, filename) json_path = path + '.json' - path = path + '.' + plugin.get_setting('ffmpeg.ext', unicode) + path = path + '.' + plugin.get_setting('ffmpeg.ext', str) ffmpeg = ffmpeg_location() if not ffmpeg: return @@ -723,23 +723,23 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, probe_cmd = cmd - ffmpeg_recording_path = os.path.join(ffmpeg_dir, filename + '.' + plugin.get_setting('ffmpeg.ext', unicode)) + ffmpeg_recording_path = os.path.join(ffmpeg_dir, filename + '.' + plugin.get_setting('ffmpeg.ext', str)) cmd = probe_cmd + ["-y", "-t", str(seconds), "-fflags","+genpts","-vcodec","copy","-acodec","copy"] ffmpeg_reconnect = plugin.get_setting('ffmpeg.reconnect', bool) if ffmpeg_reconnect: cmd = cmd + ["-reconnect_at_eof", "1", "-reconnect_streamed", "1", "-reconnect_delay_max", "300"] - ffmpeg_args = plugin.get_setting('ffmpeg.args', unicode) + ffmpeg_args = plugin.get_setting('ffmpeg.args', str) if ffmpeg_args: cmd = cmd + ffmpeg_args.split(' ') - if (plugin.get_setting('ffmpeg.pipe', unicode) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + if (plugin.get_setting('ffmpeg.pipe', str) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): cmd = cmd + ['-f', 'mpegts','-'] else: cmd.append(ffmpeg_recording_path) - post_command = plugin.get_setting('post.command', unicode) + post_command = plugin.get_setting('post.command', str) post_cmd = post_command.split(' ') - post_cmd = [s.replace("$p",ffmpeg_recording_path).replace("$d",ffmpeg_dir).replace("$f",filename + '.' + plugin.get_setting('ffmpeg.ext', unicode)) for s in post_cmd] + post_cmd = [s.replace("$p",ffmpeg_recording_path).replace("$d",ffmpeg_dir).replace("$f",filename + '.' + plugin.get_setting('ffmpeg.ext', str)) for s in post_cmd] directory = "special://profile/addon_data/plugin.video.iptv.recorder/jobs/" xbmcvfs.mkdirs(directory) @@ -751,11 +751,11 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, write_in_file(f, "import os, subprocess, time\n") - debug = plugin.get_setting('debug.ffmpeg', unicode) == 'true' + debug = plugin.get_setting('debug.ffmpeg', str) == 'true' if watch == False and remind == False: - if not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + if not (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): write_in_file(f, "import xbmc,xbmcvfs,xbmcgui\n") - notification = 'xbmcgui.Dialog().notification("Recording: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', unicode) == "false") + notification = 'xbmcgui.Dialog().notification("Recording: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', str) == "false") write_in_file(f, notification) write_in_file(f, "cmd = %s\n" % repr(cmd)) @@ -780,14 +780,14 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, write_in_file(f, "stderr = open(r'%s','w+')\n" % xbmc.translatePath(pyjob+'.stderr.txt')) write_in_file(f, "p = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, shell=%s)\n" % windows()) else: - if (plugin.get_setting('ffmpeg.pipe', unicode) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + if (plugin.get_setting('ffmpeg.pipe', str) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): write_in_file(f, "p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=%s)\n" % windows()) else: write_in_file(f, "p = subprocess.Popen(cmd, shell=%s)\n" % windows()) write_in_file(f, "f = open(r'%s', 'w+')\n" % xbmc.translatePath(pyjob+'.pid')) write_in_file(f, "f.write(repr(p.pid).encode('utf-8'))\n") write_in_file(f, "f.close()\n") - if (plugin.get_setting('ffmpeg.pipe', unicode) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): + if (plugin.get_setting('ffmpeg.pipe', str) == 'true') and not (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): write_in_file(f, 'video = xbmcvfs.File(r"%s","wb")\n' % path) write_in_file(f, 'playing = False\n') write_in_file(f, "while True:\n") @@ -806,20 +806,20 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, if debug: write_in_file(f, "stderr.close()\n") write_in_file(f, "stdout.close()\n") - if not (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): - notification = 'xbmcgui.Dialog().notification("Recording finished: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', unicode)=="false") + if not (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): + notification = 'xbmcgui.Dialog().notification("Recording finished: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', str)=="false") write_in_file(f, notification) if post_command: write_in_file(f, "post_cmd = %s\n" % repr(post_cmd)) write_in_file(f, "p = subprocess.Popen(post_cmd, shell=%s)\n" % windows()) #TODO copy file somewhere else elif remind == True: - cmd = 'xbmcgui.Dialog().notification("%s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', unicode)=="false") + cmd = 'xbmcgui.Dialog().notification("%s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', str)=="false") write_in_file(f, "import xbmc, xbmcgui\n") write_in_file(f, "%s\n" % cmd) else: - if (plugin.get_setting('external.player.watch', unicode) == 'true') or (windows() and (plugin.get_setting('task.scheduler', unicode) == 'true')): - cmd = [plugin.get_setting('external.player', unicode), plugin.get_setting('external.player.args', unicode), url] + if (plugin.get_setting('external.player.watch', str) == 'true') or (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): + cmd = [plugin.get_setting('external.player', str), plugin.get_setting('external.player.args', str), url] write_in_file(f, "cmd = %s\n" % repr(cmd)) write_in_file(f, "p = subprocess.Popen(cmd, shell=%s)\n" % windows()) else: @@ -828,14 +828,14 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, write_in_file(f, "%s\n" % cmd) f.close() - if windows() and (plugin.get_setting('task.scheduler', unicode) == 'true') and remind == False: + if windows() and (plugin.get_setting('task.scheduler', str) == 'true') and remind == False: if immediate: cmd = 'RunScript(%s)' % (pyjob) xbmc.executebuiltin(cmd) else: st = "%02d:%02d" % (local_starttime.hour, local_starttime.minute) sd = "%02d/%02d/%04d" % (local_starttime.day, local_starttime.month, local_starttime.year) - cmd = ["schtasks", "/create", "/f", "/tn", job, "/sc", "once", "/st", st, "/sd", sd, "/tr", "%s %s" % (xbmc.translatePath(plugin.get_setting('python', unicode)), xbmc.translatePath(pyjob))] + cmd = ["schtasks", "/create", "/f", "/tn", job, "/sc", "once", "/st", st, "/sd", sd, "/tr", "%s %s" % (xbmc.translatePath(plugin.get_setting('python', str)), xbmc.translatePath(pyjob))] subprocess.Popen(cmd, shell=True) else: now = datetime.now() @@ -909,8 +909,8 @@ def renew_jobs(): local_starttime = utc2local(start) local_endtime = utc2local(stop) - before = int(plugin.get_setting('minutes.before', unicode) or "0") - after = int(plugin.get_setting('minutes.after', unicode) or "0") + before = int(plugin.get_setting('minutes.before', str) or "0") + after = int(plugin.get_setting('minutes.after', str) or "0") local_starttime = local_starttime - timedelta(minutes=before) local_endtime = local_endtime + timedelta(minutes=after) @@ -932,7 +932,7 @@ def renew_jobs(): #TODO reduce time of job if already started - if windows() and (plugin.get_setting('task.scheduler', unicode) == 'true'): + if windows() and (plugin.get_setting('task.scheduler', str) == 'true'): if immediate: cmd = 'RunScript(%s)' % (pyjob) xbmc.executebuiltin(cmd) @@ -959,7 +959,7 @@ def renew_jobs(): def sane_name(name): if not name: return - if windows() or (plugin.get_setting('filename.urlencode', unicode) == 'true'): + if windows() or (plugin.get_setting('filename.urlencode', str) == 'true'): name = quote(name.encode('utf-8')) name = name.replace("%20",' ') name = name.replace('/',"%2F") @@ -973,7 +973,7 @@ def sane_name(name): def refresh(): containerAddonName = xbmc.getInfoLabel('Container.PluginName') AddonName = xbmcaddon.Addon().getAddonInfo('id') - if (containerAddonName == AddonName) and (plugin.get_setting('refresh', unicode) == 'true') : + if (containerAddonName == AddonName) and (plugin.get_setting('refresh', str) == 'true') : xbmc.executebuiltin('Container.Refresh') @@ -1546,7 +1546,7 @@ def broadcast(programmeid, channelname): 'is_playable': True, }) - if plugin.get_setting('external.player', unicode): + if plugin.get_setting('external.player', str): items.append({ 'label': _("Play Channel External") + " - %s" % (channelname), 'path': plugin.url_for(play_channel_external, channelname=echannelname), @@ -1556,9 +1556,9 @@ def broadcast(programmeid, channelname): 'is_playable': True, }) - if xbmc.getCondVisibility('System.HasAddon(%s)' % plugin.get_setting('meta', unicode)) == 1: - icon = xbmcaddon.Addon(plugin.get_setting('meta', unicode)).getAddonInfo('icon') - name = xbmcaddon.Addon(plugin.get_setting('meta', unicode)).getAddonInfo('name') + if xbmc.getCondVisibility('System.HasAddon(%s)' % plugin.get_setting('meta', str)) == 1: + icon = xbmcaddon.Addon(plugin.get_setting('meta', str)).getAddonInfo('icon') + name = xbmcaddon.Addon(plugin.get_setting('meta', str)).getAddonInfo('name') if episode: #log((channelname,channelid,title,episode)) tvdb_url = "http://thetvdb.com/api/GetSeries.php?seriesname=%s&language=en" % title @@ -1574,27 +1574,27 @@ def broadcast(programmeid, channelname): found = True season = match.group(1) ep = match.group(2) - meta_url = "plugin://%s/tv/play/%s/%d/%d/library" % (plugin.get_setting('meta', unicode).lower(),tvdb_id,int(season),int(ep)) + meta_url = "plugin://%s/tv/play/%s/%d/%d/library" % (plugin.get_setting('meta', str).lower(),tvdb_id,int(season),int(ep)) items.append({ 'label': "%s - %s %s" % (name,title,episode), 'path': meta_url, 'thumbnail': icon, }) if not found: - meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta', unicode).lower(),quote_plus(title.encode("utf8"))) + meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta', str).lower(),quote_plus(title.encode("utf8"))) items.append({ 'label': "%s - %s" % (name,title), 'path': meta_url, 'thumbnail': icon, }) else: - meta_url = "plugin://%s/movies/search_term/%s/1" % (plugin.get_setting('meta', unicode).lower(),quote_plus(title.encode("utf8"))) + meta_url = "plugin://%s/movies/search_term/%s/1" % (plugin.get_setting('meta', str).lower(),quote_plus(title.encode("utf8"))) items.append({ 'label': "%s - Movie - %s" % (name,title), 'path': meta_url, 'thumbnail': icon, }) - meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta', unicode).lower(),quote_plus(title.encode("utf8"))) + meta_url = "plugin://%s/tv/search_term/%s/1" % (plugin.get_setting('meta', str).lower(),quote_plus(title.encode("utf8"))) items.append({ 'label': "%s - TV Show - %s" % (name,title), 'path': meta_url, @@ -1688,7 +1688,7 @@ def search_title_input(title): def search_title(title): title = title.decode("utf8") - if plugin.get_setting('add.context.searches', unicode) == 'true': + if plugin.get_setting('add.context.searches', str) == 'true': searches = plugin.get_storage('search_title') searches[title] = '' @@ -1838,7 +1838,7 @@ def search_categories_input(categories): def search_categories(categories): categories = categories.decode("utf8") - if plugin.get_setting('add.context.searches', unicode) == 'true': + if plugin.get_setting('add.context.searches', str) == 'true': searches = plugin.get_storage('search_categories') searches[categories] = '' @@ -1883,7 +1883,7 @@ def channel(channelid,channelname): conn.commit() conn.close() - if plugin.get_setting('add.favourite.channel', unicode) == 'true': + if plugin.get_setting('add.favourite.channel', str) == 'true': add_favourite_channel(channelname.encode("utf8"), channelid.encode("utf8"), thumbnail) return listing(programmes, scroll=True, channelname=echannelname) @@ -2015,14 +2015,14 @@ def listing(programmes, scroll=False, channelname=None): starttime = utc2local(start) endtime = utc2local(stop) - if plugin.get_setting('show.categories', unicode) == 'true': + if plugin.get_setting('show.categories', str) == 'true': categories_label = "[COLOR grey]%s[/COLOR]" % categories else: categories_label = "" if endtime < now: color = "orange" - if plugin.get_setting('show.finished', unicode) == 'false': + if plugin.get_setting('show.finished', str) == 'false': continue else: if current == None: @@ -2040,7 +2040,7 @@ def listing(programmes, scroll=False, channelname=None): else: stitle = "[COLOR %s]%s[/COLOR][COLOR grey]%s[/COLOR]" % (color, title, episode) - if (plugin.get_setting('hide.channel.name', unicode) == "true") and thumbnail: + if (plugin.get_setting('hide.channel.name', str) == "true") and thumbnail: channelname_label = "" else: channelname_label = unquote_plus(pchannelname) @@ -2074,7 +2074,7 @@ def listing(programmes, scroll=False, channelname=None): if url: context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=echannelname)))) - if plugin.get_setting('external.player', unicode): + if plugin.get_setting('external.player', str): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=echannelname)))) context_items.append((echannelname, 'ActivateWindow(%s,%s,return)' % (xbmcgui.getCurrentWindowId(), plugin.url_for('channel', channelid=echannelid, channelname=echannelname)))) @@ -2103,7 +2103,7 @@ def listing(programmes, scroll=False, channelname=None): conn.commit() conn.close() - if scroll and plugin.get_setting('scroll.now', unicode) == 'true': + if scroll and plugin.get_setting('scroll.now', str) == 'true': threading.Thread(target=focus,args=[current]).start() return items @@ -2112,7 +2112,7 @@ def listing(programmes, scroll=False, channelname=None): def focus(i): #TODO find way to check this has worked (clist.getSelectedPosition returns -1) - xbmc.sleep(int(plugin.get_setting('scroll.ms', unicode) or "0")) + xbmc.sleep(int(plugin.get_setting('scroll.ms', str) or "0")) #TODO deal with hidden .. win = xbmcgui.Window(xbmcgui.getCurrentWindowId()) cid = win.getFocusId() @@ -2192,7 +2192,7 @@ def group(channelgroup=None,section=None): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() - if plugin.get_setting('sort.channels', unicode) == 'true': + if plugin.get_setting('sort.channels', str) == 'true': order = " ORDER by name" else: order = "" @@ -2206,22 +2206,22 @@ def group(channelgroup=None,section=None): logos = dict((x[0],x[1]) for x in streams) collection = channels - show_now_next = plugin.get_setting('show.now.next.all', unicode) == "true" + show_now_next = plugin.get_setting('show.now.next.all', str) == "true" elif section == "FAVOURITES": favourite_channels = cursor.execute("SELECT * FROM favourites ORDER BY channelname").fetchall() streams = cursor.execute("SELECT * FROM streams" + order).fetchall() collection = favourite_channels - show_now_next = plugin.get_setting('show.now.next.favourites', unicode) == "true" + show_now_next = plugin.get_setting('show.now.next.favourites', str) == "true" else: channels = cursor.execute("SELECT * FROM channels" + order).fetchall() #channel_logos = {x[1]:x[3] for x in channels} channel_logos = dict((x[1],x[3]) for x in channels) if channelgroup == "All Channels": streams = cursor.execute("SELECT * FROM streams" + order).fetchall() - show_now_next = plugin.get_setting('show.now.next.all', unicode) == "true" + show_now_next = plugin.get_setting('show.now.next.all', str) == "true" else: streams = cursor.execute("SELECT * FROM streams WHERE groups=?" + order, (channelgroup, )).fetchall() - show_now_next = plugin.get_setting('show.now.next.lists', unicode) == "true" + show_now_next = plugin.get_setting('show.now.next.lists', str) == "true" collection = streams favourites = cursor.execute("SELECT channelname FROM favourites").fetchall() @@ -2281,7 +2281,7 @@ def group(channelgroup=None,section=None): title = now_titles[channelid][0] local_start = utc2local(now_titles[channelid][1]) description = now_titles[channelid][2] - if plugin.get_setting('show.categories', unicode) == 'true': + if plugin.get_setting('show.categories', str) == 'true': categories = "[COLOR grey]%s[/COLOR]" % now_titles[channelid][3] else: categories = "" @@ -2292,7 +2292,7 @@ def group(channelgroup=None,section=None): if channelid in next_titles: title = next_titles[channelid][0] local_start = utc2local(next_titles[channelid][1]) - if plugin.get_setting('show.categories', unicode) == 'true': + if plugin.get_setting('show.categories', str) == 'true': next_categories = "[COLOR grey]%s[/COLOR]" % next_titles[channelid][2] else: next_categories = "" @@ -2300,10 +2300,10 @@ def group(channelgroup=None,section=None): else: next_title = "" - if plugin.get_setting('show.now.next.hide.empty', unicode) == "true" and not now_title and not next_title: + if plugin.get_setting('show.now.next.hide.empty', str) == "true" and not now_title and not next_title: continue - if (plugin.get_setting('hide.channel.name', unicode) == "true") and logo: + if (plugin.get_setting('hide.channel.name', str) == "true") and logo: label = "%s %s%s" % (now_title, CR, next_title) else: label = u"%s %s %s%s" % (channelname, now_title, CR, next_title) @@ -2327,7 +2327,7 @@ def group(channelgroup=None,section=None): context_items.append((_("Add Title Search Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_always_search, channelid=channelid_encoded, channelname=channelname_encoded)))) context_items.append((_("Add Plot Search Rule"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(record_always_search_plot, channelid=channelid_encoded, channelname=channelname_encoded)))) context_items.append((_("Play Channel"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel, channelname=channelname_encoded)))) - if plugin.get_setting('external.player', unicode): + if plugin.get_setting('external.player', str): context_items.append((_("Play Channel External"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_channel_external, channelname=channelname_encoded)))) if channelname not in favourites and channelid: @@ -2624,7 +2624,7 @@ def delete_recording(label, path): if not (xbmcgui.Dialog().yesno("IPTV Recorder", "[COLOR red]" + _("Delete Recording?") + "[/COLOR]", label)): return xbmcvfs.delete(path) - length = int(len('.' + plugin.get_setting('ffmpeg.ext', unicode))) + length = int(len('.' + plugin.get_setting('ffmpeg.ext', str))) xbmcvfs.delete(path[:-length]+'.json') refresh() @@ -2635,13 +2635,13 @@ def delete_all_recordings(): if not result: return - dir = plugin.get_setting('recordings', unicode) + dir = plugin.get_setting('recordings', str) dirs, files = find(dir) for file in sorted(files): - if file.endswith('.' + plugin.get_setting('ffmpeg.ext', unicode)): + if file.endswith('.' + plugin.get_setting('ffmpeg.ext', str)): success = xbmcvfs.delete(file) if success: - length = int(len('.' + plugin.get_setting('ffmpeg.ext', unicode))) + length = int(len('.' + plugin.get_setting('ffmpeg.ext', str))) json_file = file[:-length]+'.json' xbmcvfs.delete(json_file) @@ -2657,7 +2657,7 @@ def find_files(root): found_files = found_files + find_files(path) file_list = [] for file in files: - if file.endswith('.' + plugin.get_setting('ffmpeg.ext', unicode)): + if file.endswith('.' + plugin.get_setting('ffmpeg.ext', str)): file = os.path.join(xbmc.translatePath(root), file) file_list.append(file) return found_files + file_list @@ -2665,7 +2665,7 @@ def find_files(root): @plugin.route('/recordings') def recordings(): - dir = plugin.get_setting('recordings', unicode) + dir = plugin.get_setting('recordings', str) found_files = find_files(dir) items = [] @@ -2703,7 +2703,7 @@ def recordings(): context_items.append((_("Delete Recording"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(delete_recording, label=label.encode("utf8"), path=path)))) context_items.append((_("Delete All Recordings"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(delete_all_recordings)))) - if plugin.get_setting('external.player', unicode): + if plugin.get_setting('external.player', str): context_items.append((_("External Player"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(play_external, path=path)))) #context_items.append((_("Convert to mp4"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(convert, path=path)))) @@ -2785,7 +2785,7 @@ def xmltv(): for x in ["1","2"]: dialog.update(0, message=_("Finding streams")) - mode = plugin.get_setting('external.m3u.'+x, unicode) + mode = plugin.get_setting('external.m3u.'+x, str) if mode == "0": if x == "1": try: @@ -2800,9 +2800,9 @@ def xmltv(): else: path = "" elif mode == "1": - path = plugin.get_setting('external.m3u.file.'+x, unicode) + path = plugin.get_setting('external.m3u.file.'+x, str) else: - path = plugin.get_setting('external.m3u.url.'+x, unicode) + path = plugin.get_setting('external.m3u.url.'+x, str) if path: @@ -2819,7 +2819,7 @@ def xmltv(): log(encoding) data = data.decode(encoding['encoding']) - settings_shift = float(plugin.get_setting('external.m3u.shift.'+x, unicode)) + settings_shift = float(plugin.get_setting('external.m3u.shift.'+x, str)) global_shift = settings_shift header = re.search('#EXTM3U(.*)', data) @@ -2862,8 +2862,8 @@ def xmltv(): shifts[tvg_id] = float(tvg_shift) + settings_shift url = channel[1] - search = plugin.get_setting('m3u.regex.search', unicode) - replace = plugin.get_setting('m3u.regex.replace', unicode) + search = plugin.get_setting('m3u.regex.search', str) + replace = plugin.get_setting('m3u.regex.replace', str) if search: url = re.sub(search, replace, url) @@ -2880,7 +2880,7 @@ def xmltv(): for x in ["1","2"]: - mode = plugin.get_setting('external.xmltv.'+x, unicode) + mode = plugin.get_setting('external.xmltv.'+x, str) if mode == "0": if x == "1": try: @@ -2894,9 +2894,9 @@ def xmltv(): else: path = "" elif mode == "1": - path = plugin.get_setting('external.xmltv.file.'+x, unicode) + path = plugin.get_setting('external.xmltv.file.'+x, str) else: - path = plugin.get_setting('external.xmltv.url.'+x, unicode) + path = plugin.get_setting('external.xmltv.url.'+x, str) if path: @@ -2989,7 +2989,7 @@ def xmltv(): for x in ["1","2"]: - mode = plugin.get_setting('external.xmltv.'+x, unicode) + mode = plugin.get_setting('external.xmltv.'+x, str) if mode == "0": if x == "1": try: @@ -3003,9 +3003,9 @@ def xmltv(): else: path = "" elif mode == "1": - path = plugin.get_setting('external.xmltv.file.'+x, unicode) + path = plugin.get_setting('external.xmltv.file.'+x, str) else: - path = plugin.get_setting('external.xmltv.url.'+x, unicode) + path = plugin.get_setting('external.xmltv.url.'+x, str) if path: @@ -3061,8 +3061,8 @@ def xmltv(): title = re.search('(.*?) Date: Sat, 9 May 2020 13:15:55 +0200 Subject: [PATCH 03/19] Fix wrong error reporting. --- server.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server.py b/server.py index a43ce5e..93aa4f2 100644 --- a/server.py +++ b/server.py @@ -37,7 +37,7 @@ def Service(): if ADDON.getSetting('service') == 'true': monitor = xbmc.Monitor() - xbmc.log("[plugin.video.iptv.recorder] service started...", xbmc.LOGERROR) + xbmc.log("[plugin.video.iptv.recorder] service started...") if ADDON.getSetting('service.startup') == 'true': time.sleep(int(ADDON.getSetting('service.delay.seconds'))) @@ -55,7 +55,7 @@ def Service(): nextTime = lastTime + datetime.timedelta(seconds=waitTime) td = nextTime - now timeLeft = td.seconds + (td.days * 24 * 3600) - xbmc.log("[plugin.video.iptv.recorder] Service waiting for interval %s" % waitTime, xbmc.LOGERROR) + xbmc.log("[plugin.video.iptv.recorder] Service waiting for interval %s" % waitTime) elif ADDON.getSetting('service.type') == '2': next_time = ADDON.getSetting('service.time') @@ -73,11 +73,11 @@ def Service(): if timeLeft <= 0: timeLeft = 1 - xbmc.log("[plugin.video.iptv.recorder] Service waiting for %d seconds" % timeLeft, xbmc.LOGERROR) + xbmc.log("[plugin.video.iptv.recorder] Service waiting for %d seconds" % timeLeft) if timeLeft and monitor.waitForAbort(timeLeft): break - xbmc.log("[plugin.video.iptv.recorder] Service now triggered...", xbmc.LOGERROR) + xbmc.log("[plugin.video.iptv.recorder] Service now triggered...") Service() now = time.time() ADDON.setSetting('last.update', str(now)) From 458295908075e0d6e179609ff37ef65564190e89 Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 13:22:34 +0200 Subject: [PATCH 04/19] Fix french translations. --- resources/language/French/strings.po | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/language/French/strings.po b/resources/language/French/strings.po index d338437..ddd60b6 100644 --- a/resources/language/French/strings.po +++ b/resources/language/French/strings.po @@ -4,7 +4,7 @@ msgstr "" msgctxt "#30000" msgid "Delete All Recordings?" -msgstr "Supprimer tous les enregistrements?" +msgstr "Supprimer tous les enregistrements ?" msgctxt "#30001" msgid "Play Channel" @@ -32,7 +32,7 @@ msgstr "Lecteur externe" msgctxt "#30007" msgid "Title Search (% is wildcard)?" -msgstr "Rechercher par titre (% est joker)?" +msgstr "Rechercher par titre (% est joker) ?" msgctxt "#30008" msgid "Delete All Jobs" @@ -80,11 +80,11 @@ msgstr "Supprimer la recherche" msgctxt "#30019" msgid "Cancel Record?" -msgstr "Annuler l'enregistrement?" +msgstr "Annuler l'enregistrement ?" msgctxt "#30020" msgid "Delete Recording?" -msgstr "Supprimer l'enregistrement?" +msgstr "Supprimer l'enregistrement ?" msgctxt "#30021" msgid "New" @@ -112,7 +112,7 @@ msgstr "Ajouter une règle de recherche par description" msgctxt "#30027" msgid "Delete All Rules?" -msgstr "Supprimer toutes les règles?" +msgstr "Supprimer toutes les règles ?" msgctxt "#30028" msgid "Recordings Folder" @@ -120,7 +120,7 @@ msgstr "Dossier d'enregistrement" msgctxt "#30029" msgid "ffmpeg exe not found!" -msgstr "ffmpeg exe non trouvé!" +msgstr "ffmpeg exe non trouvé !" msgctxt "#30030" msgid "Tomorrow" @@ -160,7 +160,7 @@ msgstr "Hier" msgctxt "#30039" msgid "Delete All Jobs?" -msgstr "Supprimer toutes les programmations?" +msgstr "Supprimer toutes les programmations ?" msgctxt "#30040" msgid "Recordings" @@ -212,7 +212,7 @@ msgstr "Mettre en veille tous les jours" msgctxt "#30052" msgid "Delete Everything and Start Again?" -msgstr "Tout supprimer et recharger?" +msgstr "Tout supprimer et recharger ?" msgctxt "#30053" msgid "Watch Once" From d98ed555e5b302d81deda77908a44e4c46ac1bc6 Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 14:58:28 +0200 Subject: [PATCH 05/19] Fix translation tool. --- language.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/language.py b/language.py index 195df0a..2fd4479 100644 --- a/language.py +++ b/language.py @@ -5,20 +5,32 @@ if __name__ == "__main__": import polib + import traceback po = polib.pofile('resources/language/English/strings.po') try: + import os import re import subprocess - r = subprocess.check_output(["grep", "-hnr", "_([\'\"]", "."]) - strings = re.compile("_\([\"'](.*?)[\"']\)", re.IGNORECASE).findall(r) + + strings = [] + regex_to_found = re.compile("_\([\"'](.*?)[\"']\)", re.IGNORECASE) + for root, dirs, files in os.walk("."): + for file in files: + if file.endswith(".py"): + with open(os.path.join(root, file), "r", encoding="utf-8") as file_content: + for line in file_content: + strings_found = regex_to_found.findall(line) + if strings_found: + strings.extend(strings_found) + translated = [m.msgid.lower().replace("'", "\\'") for m in po] missing = set([s for s in strings if s.lower() not in translated]) if missing: ids_range = range(30000, 31000) ids_reserved = [int(m.msgctxt[1:]) for m in po] ids_available = [x for x in ids_range if x not in ids_reserved] - print("warning: missing translation for %s" % missing) + print("New text to translate found : %s" % missing) for text in missing: id = ids_available.pop(0) entry = polib.POEntry( @@ -29,6 +41,7 @@ po.append(entry) po.save('resources/language/English/strings.po') except: + traceback.print_exc() pass content = [] From c8dd0d279bda1fa208c1a1c419adf0ccc9a5997d Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 15:08:26 +0200 Subject: [PATCH 06/19] Add some missing translations. --- language.py | 1 + resources/language/English/strings.po | 4 ++ resources/language/French/strings.po | 76 +++++++++++++++++++++++++++ resources/language/German/strings.po | 4 ++ 4 files changed, 85 insertions(+) diff --git a/language.py b/language.py index 2fd4479..59b8b5d 100644 --- a/language.py +++ b/language.py @@ -157,3 +157,4 @@ def get_string(t): __strings['add one time rule'] = 30087 __strings['categories'] = 30088 __strings['remind weekly'] = 30089 +__strings['convert to mp4'] = 30090 diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index 695494e..62dc4a4 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -361,3 +361,7 @@ msgstr "" msgctxt "#30089" msgid "Remind Weekly" msgstr "" + +msgctxt "#30090" +msgid "Convert to mp4" +msgstr "" diff --git a/resources/language/French/strings.po b/resources/language/French/strings.po index ddd60b6..a8b52b6 100644 --- a/resources/language/French/strings.po +++ b/resources/language/French/strings.po @@ -289,3 +289,79 @@ msgstr "Annuler le rappel" msgctxt "#30071" msgid "% is Wildcard" msgstr "% est joker" + +msgctxt "#30072" +msgid "Search" +msgstr "Rechercher" + +msgctxt "#30073" +msgid "TV Shows" +msgstr "Programmes" + +msgctxt "#30074" +msgid "Movies" +msgstr "Films" + +msgctxt "#30075" +msgid "Do Not Load Group" +msgstr "Ne pas charger le groupe de chaînes" + +msgctxt "#30076" +msgid "Delete ffmpeg" +msgstr "Supprimer ffmpeg" + +msgctxt "#30077" +msgid "Add Daily Time Rule" +msgstr "Ajouter une règle quotidienne" + +msgctxt "#30078" +msgid "Add Weekly Time Rule" +msgstr "Ajouter une règle hebdomadaire" + +msgctxt "#30079" +msgid "Record and Play" +msgstr "Enregistrer et regarder" + +msgctxt "#30080" +msgid "Watch Weekly" +msgstr "Regarder chaque semaine" + +msgctxt "#30081" +msgid "Other" +msgstr "Autres" + +msgctxt "#30082" +msgid "Select Groups To Load" +msgstr "Sélectionner les groupes de chaînes à charger" + +msgctxt "#30083" +msgid "Record Weekly" +msgstr "Enregistrer chaque semaine" + +msgctxt "#30084" +msgid "Maintenance" +msgstr "Maintenance" + +msgctxt "#30085" +msgid "Load Group" +msgstr "Charger le groupe de chaîne" + +msgctxt "#30086" +msgid "Browse" +msgstr "Parcourir" + +msgctxt "#30087" +msgid "Add One Time Rule" +msgstr "Ajouter une règle unique" + +msgctxt "#30088" +msgid "Categories" +msgstr "Categories" + +msgctxt "#30089" +msgid "Remind Weekly" +msgstr "Me le rappeler chaque semaine" + +msgctxt "#30090" +msgid "Convert to mp4" +msgstr "Convertir en mp4" diff --git a/resources/language/German/strings.po b/resources/language/German/strings.po index af65caa..cb28f08 100644 --- a/resources/language/German/strings.po +++ b/resources/language/German/strings.po @@ -361,3 +361,7 @@ msgstr "Kategorien" msgctxt "#30089" msgid "Remind Weekly" msgstr "Wöchentlich erinnern" + +msgctxt "#30090" +msgid "Convert to mp4" +msgstr "Convert to mp4" From aadaac75258610fb3c7c0d5223ebb7b995908283 Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 15:18:06 +0200 Subject: [PATCH 07/19] Improve one french translation. --- resources/language/French/strings.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/language/French/strings.po b/resources/language/French/strings.po index a8b52b6..ed175d5 100644 --- a/resources/language/French/strings.po +++ b/resources/language/French/strings.po @@ -64,7 +64,7 @@ msgstr "Supprimer tous les enregistrements" msgctxt "#30015" msgid "Full EPG" -msgstr "EPG Complet" +msgstr "Programme télé complet" msgctxt "#30016" msgid "Search Title" From e8a93bdd3cb668c24f5b8a60f8ab67e502731c88 Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 15:18:36 +0200 Subject: [PATCH 08/19] Add translation for "All Channels". --- language.py | 1 + main.py | 9 ++++++--- resources/language/English/strings.po | 4 ++++ resources/language/French/strings.po | 4 ++++ resources/language/German/strings.po | 4 ++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/language.py b/language.py index 59b8b5d..b87d50c 100644 --- a/language.py +++ b/language.py @@ -158,3 +158,4 @@ def get_string(t): __strings['categories'] = 30088 __strings['remind weekly'] = 30089 __strings['convert to mp4'] = 30090 +__strings['all channels'] = 30091 diff --git a/main.py b/main.py index 21a8b93..3792534 100644 --- a/main.py +++ b/main.py @@ -2216,7 +2216,7 @@ def group(channelgroup=None,section=None): channels = cursor.execute("SELECT * FROM channels" + order).fetchall() #channel_logos = {x[1]:x[3] for x in channels} channel_logos = dict((x[1],x[3]) for x in channels) - if channelgroup == "All Channels": + if channelgroup == "All_Channels": streams = cursor.execute("SELECT * FROM streams" + order).fetchall() show_now_next = plugin.get_setting('show.now.next.all', str) == "true" else: @@ -2361,7 +2361,7 @@ def groups(): channelgroups = cursor.execute("SELECT DISTINCT groups FROM streams ORDER BY groups").fetchall() - for channelgroup in [("All Channels", )] + channelgroups: + for channelgroup in [("All_Channels", )] + channelgroups: channelgroup = channelgroup[0] if not channelgroup: @@ -2373,8 +2373,11 @@ def groups(): else: context_items.append((_("Do Not Load Group"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(remove_load_group, channelgroup=channelgroup.encode("utf8"))))) + channel_name = channelgroup + if channel_name == "All_Channels": + channel_name = _("All Channels") items.append({ - 'label': channelgroup, + 'label': channel_name, 'path': plugin.url_for(group, channelgroup=channelgroup.encode("utf8")), 'thumbnail': get_icon_path('folder'), 'context_menu': context_items, diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index 62dc4a4..892ccc7 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -365,3 +365,7 @@ msgstr "" msgctxt "#30090" msgid "Convert to mp4" msgstr "" + +msgctxt "#30091" +msgid "All Channels" +msgstr "" diff --git a/resources/language/French/strings.po b/resources/language/French/strings.po index ed175d5..dc66596 100644 --- a/resources/language/French/strings.po +++ b/resources/language/French/strings.po @@ -365,3 +365,7 @@ msgstr "Me le rappeler chaque semaine" msgctxt "#30090" msgid "Convert to mp4" msgstr "Convertir en mp4" + +msgctxt "#30091" +msgid "All Channels" +msgstr "Toutes les chaînes" diff --git a/resources/language/German/strings.po b/resources/language/German/strings.po index cb28f08..cdc88b6 100644 --- a/resources/language/German/strings.po +++ b/resources/language/German/strings.po @@ -365,3 +365,7 @@ msgstr "Wöchentlich erinnern" msgctxt "#30090" msgid "Convert to mp4" msgstr "Convert to mp4" + +msgctxt "#30091" +msgid "All Channels" +msgstr "All Channels" From a493b42b9566ddd8b5147a634a9c1f053d3db3e8 Mon Sep 17 00:00:00 2001 From: dob! Date: Sun, 10 May 2020 15:11:19 +0200 Subject: [PATCH 09/19] Upgrading "Sort Channels by" settings. --- main.py | 78 +++++++++++++++++++++--------------------- resources/settings.xml | 2 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/main.py b/main.py index 3792534..31715bc 100644 --- a/main.py +++ b/main.py @@ -125,11 +125,11 @@ def play_channel(channelname): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile'))) c = conn.cursor() - channel = c.execute("SELECT * FROM streams WHERE name=?", (channelname, )).fetchone() + channel = c.execute("SELECT url FROM streams WHERE name=?", (channelname, )).fetchone() if not channel: return - uid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel + url = channel[0] #plugin.set_resolved_url(url) xbmc.Player().play(url) @@ -141,10 +141,10 @@ def play_channel_external(channelname): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile'))) c = conn.cursor() - channel = c.execute("SELECT * FROM streams WHERE name=?", (channelname, )).fetchone() + channel = c.execute("SELECT url FROM streams WHERE name=?", (channelname, )).fetchone() if not channel: return - uid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel + url = channel[0] if url: cmd = [plugin.get_setting('external.player', str)] @@ -212,9 +212,9 @@ def jobs(): continue url = "" - channel = cursor.execute("SELECT * FROM streams WHERE tvg_id=?", (channelid, )).fetchone() + channel = cursor.execute("SELECT name, url FROM streams WHERE tvg_id=?", (channelid, )).fetchone() if channel: - uid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel + name, url = channel echannelname=name.encode("utf8") context_items = [] @@ -252,7 +252,7 @@ def rules(): for uid, channelid, channelname, title, start, stop, description, type, rulename in rules: url = "" - channel = cursor.execute("SELECT * FROM streams WHERE tvg_id=?", (channelid, )).fetchone() + channel = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE tvg_id=?", (channelid, )).fetchone() if channel: cuid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel echannelname=name.encode("utf8") @@ -589,13 +589,13 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, #log((channelid,channelname)) if channelid: - channel = cursor.execute("SELECT * FROM streams WHERE tvg_id=? AND tvg_name=?", (channelid, channelname)).fetchone() + channel = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE tvg_id=? AND tvg_name=?", (channelid, channelname)).fetchone() if not channel: - channel = cursor.execute("SELECT * FROM streams WHERE tvg_id=? AND name=?", (channelid, channelname)).fetchone() + channel = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE tvg_id=? AND name=?", (channelid, channelname)).fetchone() else: - channel = cursor.execute("SELECT * FROM streams WHERE name=?", (channelname,)).fetchone() + channel = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE name=?", (channelname,)).fetchone() if not channel: - channel = cursor.execute("SELECT * FROM streams WHERE tvg_name=?", (channelname,)).fetchone() + channel = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE tvg_name=?", (channelname,)).fetchone() if not channel: xbmc.log("No channel %s" % channelname, xbmc.LOGERROR) @@ -1446,8 +1446,7 @@ def broadcast(programmeid, channelname): programme = cursor.execute('SELECT channelid, title, start AS "start [TIMESTAMP]", stop AS "stop [TIMESTAMP]", episode FROM programmes WHERE uid=? LIMIT 1', (programmeid, )).fetchone() channelid, title, start, stop, episode = programme - #channel = cursor.execute("SELECT * FROM streams WHERE tvg_id=? AND tvg_name=?", (channelid, channelname)).fetchone() - channel = cursor.execute("SELECT * FROM streams WHERE name=?", (channelname,)).fetchone() + channel = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE name=?", (channelname,)).fetchone() if not channel: channel = cursor.execute("SELECT * FROM channels WHERE tvg_name=?", (channelname, )).fetchone() uid, tvg_id, name, tvg_logo = channel @@ -1865,17 +1864,13 @@ def channel(channelid,channelname): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() - channel = cursor.execute("SELECT * FROM streams WHERE tvg_id=?", (channelid, )).fetchone() - if not channel: - channel = cursor.execute("SELECT * FROM channels WHERE id=?", (channelid, )).fetchone() - uid, tvg_id, name, tvg_logo = channel - url = "" + thumbnail = cursor.execute("SELECT tvg_logo FROM streams WHERE tvg_id=?", (channelid, )).fetchone() + if not thumbnail: + thumbnail = cursor.execute("SELECT icon FROM channels WHERE id=?", (channelid, )).fetchone() + if thumbnail: + thumbnail = thumbnail[0] else: - uid, name, tvg_name, tvg_id, tvg_logo, groups, url = channel - - thumbnail = tvg_logo - #channelname = name - + thumbnail = '' programmes = cursor.execute( 'SELECT uid, channelid , title , sub_title , start AS "start [TIMESTAMP]", stop AS "stop [TIMESTAMP]", date , description , episode, categories FROM programmes WHERE channelid=?', (channelid, )).fetchall() @@ -1964,7 +1959,7 @@ def listing(programmes, scroll=False, channelname=None): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() - streams = cursor.execute("SELECT * FROM streams").fetchall() + streams = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams").fetchall() #streams = {x[3]:x for x in streams} streams = dict((x[3],x) for x in streams) @@ -1986,7 +1981,7 @@ def listing(programmes, scroll=False, channelname=None): if channelname: pchannelname = channelname - stream = streams.get(channelid) #cursor.execute("SELECT * FROM streams WHERE tvg_id=?", (channelid, )).fetchone() + stream = streams.get(channelid) channel = channels.get(channelid) if stream: cuid, schannelname, tvg_name, tvg_id, tvg_logo, groups, url = stream @@ -2192,15 +2187,20 @@ def group(channelgroup=None,section=None): conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) cursor = conn.cursor() - if plugin.get_setting('sort.channels', str) == 'true': - order = " ORDER by name" + order_settings = plugin.get_setting('sort.channels.v2', str) + if order_settings == '1': + order_channels = " ORDER by name" + order_favourites = " ORDER by channelname" + order_stream = " ORDER by name" else: - order = "" + order_channels = " INNER JOIN streams ON streams.tvg_id = channels.id ORDER BY tv_number"; + order_favourites = " INNER JOIN streams ON streams.tvg_id = favourites.channelid ORDER BY tv_number"; + order_stream = " ORDER by tv_number" logos = {} channel_logos = {} if section == "EPG": - channels = cursor.execute("SELECT * FROM channels" + order).fetchall() + channels = cursor.execute("SELECT channels.id, channels.name, channels.icon FROM channels" + order_channels).fetchall() streams = cursor.execute("SELECT tvg_id, tvg_logo FROM streams").fetchall() #logos = {x[0]:x[1] for x in streams} logos = dict((x[0],x[1]) for x in streams) @@ -2208,26 +2208,26 @@ def group(channelgroup=None,section=None): collection = channels show_now_next = plugin.get_setting('show.now.next.all', str) == "true" elif section == "FAVOURITES": - favourite_channels = cursor.execute("SELECT * FROM favourites ORDER BY channelname").fetchall() - streams = cursor.execute("SELECT * FROM streams" + order).fetchall() + favourite_channels = cursor.execute("SELECT channelname, channelid, logo FROM favourites" + order_favourites).fetchall() + streams = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams" + order_stream).fetchall() collection = favourite_channels show_now_next = plugin.get_setting('show.now.next.favourites', str) == "true" else: - channels = cursor.execute("SELECT * FROM channels" + order).fetchall() + channels = cursor.execute("SELECT * FROM channels" + order_channels).fetchall() #channel_logos = {x[1]:x[3] for x in channels} channel_logos = dict((x[1],x[3]) for x in channels) if channelgroup == "All_Channels": - streams = cursor.execute("SELECT * FROM streams" + order).fetchall() + streams = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams" + order_stream).fetchall() show_now_next = plugin.get_setting('show.now.next.all', str) == "true" else: - streams = cursor.execute("SELECT * FROM streams WHERE groups=?" + order, (channelgroup, )).fetchall() + streams = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams WHERE groups=?" + order_stream, (channelgroup, )).fetchall() show_now_next = plugin.get_setting('show.now.next.lists', str) == "true" collection = streams favourites = cursor.execute("SELECT channelname FROM favourites").fetchall() favourites = [x[0] for x in favourites] - all_streams = cursor.execute("SELECT * FROM streams" + order).fetchall() + all_streams = cursor.execute("SELECT uid, name, tvg_name, tvg_id, tvg_logo, groups, url FROM streams" + order_stream).fetchall() #stream_urls = {x[3]:x[6] for x in all_streams if x} stream_urls = dict((x[3],x[6]) for x in all_streams if x) @@ -2249,7 +2249,7 @@ def group(channelgroup=None,section=None): url = "" if section == "EPG": - uid, id, name, icon = stream_channel + id, name, icon = stream_channel channelname = name channelid = id url = stream_urls.get(channelid) @@ -2779,7 +2779,7 @@ def xmltv(): try: conn.execute('ALTER TABLE rules ADD COLUMN name TEXT') except: pass #TODO check primary key - conn.execute('CREATE TABLE IF NOT EXISTS streams(uid INTEGER PRIMARY KEY ASC, name TEXT, tvg_name TEXT, tvg_id TEXT, tvg_logo TEXT, groups TEXT, url TEXT)') + conn.execute('CREATE TABLE IF NOT EXISTS streams(uid INTEGER PRIMARY KEY ASC, name TEXT, tvg_name TEXT, tvg_id TEXT, tvg_logo TEXT, groups TEXT, url TEXT, tv_number INTEGER)') conn.execute('CREATE TABLE IF NOT EXISTS favourites(channelname TEXT, channelid TEXT, logo TEXT, PRIMARY KEY(channelname))') conn.execute('CREATE TABLE IF NOT EXISTS jobs(uid INTEGER PRIMARY KEY ASC, uuid TEXT, channelid TEXT, channelname TEXT, title TEXT, start TIMESTAMP, stop TIMESTAMP, type TEXT)') @@ -2874,8 +2874,8 @@ def xmltv(): if groups: groups = groups.group(1) or None - conn.execute("INSERT OR IGNORE INTO streams(name, tvg_name, tvg_id, tvg_logo, groups, url) VALUES (?, ?, ?, ?, ?, ?)", - [name, tvg_name, tvg_id, tvg_logo, groups, url.strip()]) + conn.execute("INSERT OR IGNORE INTO streams(name, tvg_name, tvg_id, tvg_logo, groups, url, tv_number) VALUES (?, ?, ?, ?, ?, ?, ?)", + [name, tvg_name, tvg_id, tvg_logo, groups, url.strip(), i]) i += 1 percent = 0 + int(100.0 * i / total) diff --git a/resources/settings.xml b/resources/settings.xml index aa5c8bc..6d28483 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -5,7 +5,7 @@ - + From 8443f8fa0c5e80cac98b1d0def8a1f0fe3ced533 Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 18:06:46 +0200 Subject: [PATCH 10/19] Fix date not found in records. --- main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.py b/main.py index 31715bc..0ad8521 100644 --- a/main.py +++ b/main.py @@ -3082,6 +3082,8 @@ def xmltv(): date = re.search('(.*?)(.*?)', m, flags=(re.I|re.DOTALL)) if cats: From 2fdf77261ace9466a55fbf1e22bf51a7e28866cb Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 18:10:36 +0200 Subject: [PATCH 11/19] Add date of records in record list. --- main.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 0ad8521..c00277b 100644 --- a/main.py +++ b/main.py @@ -2683,16 +2683,20 @@ def recordings(): title = programme['title'] sub_title = programme['sub_title'] or '' episode = programme['episode'] - date = "(%s)" % programme['date'] or '' + date = programme.get('date', '') + if date is None: + date = '' + else: + date = "(%s) " % programme.get('date', '') start = programme['start'] starts.append(start) if episode and episode != "MOVIE": - label = "%s [COLOR grey]%s[/COLOR] %s" % (title, episode, sub_title) + label = "%s%s [COLOR grey]%s[/COLOR] %s" % (date, title, episode, sub_title) elif episode == "MOVIE": - label = "%s %s" % (title,date) + label = "%s%s" % (date, title) else: - label = "%s %s" % (title, sub_title) + label = "%s%s %s" % (date, title, sub_title) description = programme['description'] except: From be05912d76c7b692ba2f86b4ea37022bdb2a74f2 Mon Sep 17 00:00:00 2001 From: dob! Date: Sat, 9 May 2020 18:10:58 +0200 Subject: [PATCH 12/19] Add channel icon in the record list. --- main.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/main.py b/main.py index c00277b..8f90ec7 100644 --- a/main.py +++ b/main.py @@ -2674,12 +2674,17 @@ def recordings(): items = [] starts = [] + conn = sqlite3.connect(xbmc.translatePath('%sxmltv.db' % plugin.addon.getAddonInfo('profile')), detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) + cursor = conn.cursor() + for path in found_files: + thumbnail = None try: json_file = path[:-3]+'.json' info = json.loads(xbmcvfs.File(json_file).read()) programme = info["programme"] + channelid = programme.get('channelid', None) title = programme['title'] sub_title = programme['sub_title'] or '' episode = programme['episode'] @@ -2688,9 +2693,14 @@ def recordings(): date = '' else: date = "(%s) " % programme.get('date', '') + start = programme['start'] starts.append(start) + stream_found = cursor.execute("SELECT tvg_logo FROM streams WHERE tvg_id=?", (channelid, )).fetchone() + if stream_found: + thumbnail = stream_found[0] + if episode and episode != "MOVIE": label = "%s%s [COLOR grey]%s[/COLOR] %s" % (date, title, episode, sub_title) elif episode == "MOVIE": @@ -2715,6 +2725,7 @@ def recordings(): #context_items.append((_("Convert to mp4"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(convert, path=path)))) items.append({ + 'thumbnail': thumbnail, 'label': label, 'path': path, 'is_playable': True, From 1a99e5b1207f72a72f63d9856b775f33154c6f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20B=C3=A9tous?= Date: Tue, 28 Apr 2020 13:50:45 +0200 Subject: [PATCH 13/19] Improve encoding detection of the XML TV file The encoding of the XML TV file can be found either: 1. with a regular expression on the encoding tag in the XML file 2. or using the chardet.detect() function on the content of the XML file Option 1 is improved by updating the regex: an encoding tag using single quotes will also be detected now. Option 2 could last more than several minutes for huge files. So if the file has more than 50,000 characters, the detection is done only on the first 50,000 characters (which should be enough to detect the encoding). --- main.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 8f90ec7..79749e6 100644 --- a/main.py +++ b/main.py @@ -2944,11 +2944,16 @@ def xmltv(): data = f.read() f.close() - match = re.search('<\?xml.*?encoding="(.*?)"',data,flags=(re.I|re.DOTALL)) + match = re.search(r'<\?xml.*?encoding=["\'](.*?)["\']',data,flags=(re.I|re.DOTALL)) if match: encoding = match.group(1) else: - chardet_encoding = chardet.detect(data) + # Improve performance by limiting the detection of the encoding + # to the first 50k characters if the XML file is bigger + if len(data) > 50000: + chardet_encoding = chardet.detect(data[:50000]) + else: + chardet_encoding = chardet.detect(data) encoding = chardet_encoding['encoding'] data = data.decode(encoding) @@ -3033,11 +3038,16 @@ def xmltv(): data = f.read() f.close() - match = re.search('<\?xml.*?encoding="(.*?)"',data,flags=(re.I|re.DOTALL)) + match = re.search(r'<\?xml.*?encoding=["\'](.*?)["\']',data,flags=(re.I|re.DOTALL)) if match: encoding = match.group(1) else: - chardet_encoding = chardet.detect(data) + # Improve performance by limiting the detection of the encoding + # to the first 50k characters if the XML file is bigger + if len(data) > 50000: + chardet_encoding = chardet.detect(data[:50000]) + else: + chardet_encoding = chardet.detect(data) encoding = chardet_encoding['encoding'] data = data.decode(encoding) From b11fed35f25b7a77102d85f017b2277c7cb5ad4a Mon Sep 17 00:00:00 2001 From: dob! Date: Sun, 10 May 2020 15:12:21 +0200 Subject: [PATCH 14/19] Using kodi_six python module to fix error for python3. --- addon.xml | 1 + context.py | 3 +-- contextEPG.py | 3 +-- default.py | 2 +- language.py | 2 +- main.py | 55 ++++++++++++++++++++++++++++++--------------------- server.py | 4 ++-- 7 files changed, 40 insertions(+), 30 deletions(-) diff --git a/addon.xml b/addon.xml index bafcbb8..0852d19 100644 --- a/addon.xml +++ b/addon.xml @@ -9,6 +9,7 @@ provider-name="primaeval, Chychy"> + video diff --git a/context.py b/context.py index ea7ce8e..920abbf 100644 --- a/context.py +++ b/context.py @@ -2,8 +2,7 @@ import urllib -import xbmc -import xbmcgui +from kodi_six import xbmc, xbmcgui def log(x): diff --git a/contextEPG.py b/contextEPG.py index 71354f6..44b8472 100644 --- a/contextEPG.py +++ b/contextEPG.py @@ -5,8 +5,7 @@ from datetime import datetime import urllib -import xbmc -import xbmcgui +from kodi_six import xbmc, xbmcgui DATE_FORMAT = "%Y-%m-%d %H:%M:00" diff --git a/default.py b/default.py index 9b921a9..9799463 100644 --- a/default.py +++ b/default.py @@ -1,5 +1,5 @@ from __future__ import unicode_literals -import xbmc,xbmcgui,xbmcaddon,xbmcvfs,xbmcplugin +from kodi_six import xbmc,xbmcgui,xbmcaddon,xbmcvfs,xbmcplugin import sys import time,datetime import sqlite3 diff --git a/language.py b/language.py index b87d50c..a3e7b04 100644 --- a/language.py +++ b/language.py @@ -55,7 +55,7 @@ line = "__strings['{0}'] = {1}\n".format(m.msgid.lower().replace("'", "\\'"), m.msgctxt.replace('#', '').strip()) f.write(line) else: - import xbmc, xbmcaddon + from kodi_six import xbmc, xbmcaddon __language__ = xbmcaddon.Addon().getLocalizedString def get_string(t): diff --git a/main.py b/main.py index 79749e6..d09253c 100644 --- a/main.py +++ b/main.py @@ -33,8 +33,7 @@ from urllib import quote, quote_plus, unquote_plus import uuid -import xbmc, xbmcaddon, xbmcvfs, xbmcgui, xbmcplugin - +from kodi_six import xbmc, xbmcaddon, xbmcvfs, xbmcgui, xbmcplugin def addon_id(): return xbmcaddon.Addon().getAddonInfo('id') @@ -570,7 +569,7 @@ def get_utc_from_string(date_string): second=0, microsecond=0) - timedelta(seconds=utc_offset) def write_in_file(file, string): - file.write(string.encode('utf8')) + file.write(bytearray(string.encode('utf8'))) def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, channelid=None, channelname=None, start=None,stop=None, play=False, title=None): #TODO check for ffmpeg process already recording if job is re-added @@ -754,7 +753,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, debug = plugin.get_setting('debug.ffmpeg', str) == 'true' if watch == False and remind == False: if not (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): - write_in_file(f, "import xbmc,xbmcvfs,xbmcgui\n") + write_in_file(f, "from kodi_six import xbmc,xbmcvfs,xbmcgui\n") notification = 'xbmcgui.Dialog().notification("Recording: %s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', str) == "false") write_in_file(f, notification) write_in_file(f, "cmd = %s\n" % repr(cmd)) @@ -793,7 +792,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, write_in_file(f, "while True:\n") write_in_file(f, " data = p.stdout.read(1000000)\n") write_in_file(f, " if data:\n") - write_in_file(f, " video.write(data)\n") + write_in_file(f, " video.write(bytearray(data.encode('utf-8')))\n") write_in_file(f, " else:\n") write_in_file(f, " break\n") if play: @@ -815,7 +814,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, #TODO copy file somewhere else elif remind == True: cmd = 'xbmcgui.Dialog().notification("%s", "%s", sound=%s)\n' % (channelname, title, plugin.get_setting('silent', str)=="false") - write_in_file(f, "import xbmc, xbmcgui\n") + write_in_file(f, "from kodi_six import xbmc, xbmcgui\n") write_in_file(f, "%s\n" % cmd) else: if (plugin.get_setting('external.player.watch', str) == 'true') or (windows() and (plugin.get_setting('task.scheduler', str) == 'true')): @@ -824,7 +823,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, write_in_file(f, "p = subprocess.Popen(cmd, shell=%s)\n" % windows()) else: cmd = 'xbmc.Player().play("%s")\n' % url - write_in_file(f, "import xbmc\n") + write_in_file(f, "from kodi_six import xbmc\n") write_in_file(f, "%s\n" % cmd) f.close() @@ -874,11 +873,11 @@ def convert(path): t.start() while True: - data = input.read(100000) - log(("read",len(data))) - if not data: + data_bytes = bytes(input.readBytes(100000)) + log(("read", len(data_bytes))) + if not data_bytes: break - p.stdin.write(data) + p.stdin.write(bytearray(data_bytes)) p.stdin.close() error.close() @@ -2924,27 +2923,33 @@ def xmltv(): xbmcvfs.copy(path, tmp) f = xbmcvfs.File(tmp, "rb") - data = f.read() + data_bytes = bytes(f.readBytes()) f.close() - magic = data[:3] + magic = data_bytes[:3] if magic == "\x1f\x8b\x08": dialog.update(0, message=_("Unzipping xmltv file")) compressedFile = StringIO.StringIO() - compressedFile.write(data) + compressedFile.write(data_bytes) compressedFile.seek(0) decompressedFile = gzip.GzipFile(fileobj=compressedFile, mode='rb') - data = decompressedFile.read() + data_bytes = decompressedFile.read() f = xbmcvfs.File(xml, "wb") - write_in_file(f, data) + f.write(bytearray(data_bytes)) f.close() else: xbmcvfs.copy(tmp, xml) f = xbmcvfs.File(xml, 'rb') - data = f.read() + data_bytes = bytes(f.readBytes()) f.close() - match = re.search(r'<\?xml.*?encoding=["\'](.*?)["\']',data,flags=(re.I|re.DOTALL)) + data_test_decoding = data_bytes.decode('utf-8', errors='ignore') + index_end_first_line = data_test_decoding.find('\n') + match = None + if index_end_first_line != -1: + first_line = data_test_decoding[:index_end_first_line] + match = re.search('<\?xml.*?encoding=["\'](.*?)["\']', first_line, flags=(re.I|re.DOTALL)) + if match: encoding = match.group(1) else: @@ -2955,7 +2960,7 @@ def xmltv(): else: chardet_encoding = chardet.detect(data) encoding = chardet_encoding['encoding'] - data = data.decode(encoding) + data = data_bytes.decode(encoding) htmlparser = HTMLParser() @@ -3035,10 +3040,16 @@ def xmltv(): xml = os.path.join(profilePath, 'xmltv'+x+'.xml') f = xbmcvfs.File(xml, 'rb') - data = f.read() + data_bytes = bytes(f.readBytes()) f.close() - match = re.search(r'<\?xml.*?encoding=["\'](.*?)["\']',data,flags=(re.I|re.DOTALL)) + data_test_decoding = data_bytes.decode('utf-8', errors='ignore') + index_end_first_line = data_test_decoding.find('\n') + match = None + if index_end_first_line != -1: + first_line = data_test_decoding[:index_end_first_line] + match = re.search('<\?xml.*?encoding=["\'](.*?)["\']', first_line, flags=(re.I|re.DOTALL)) + if match: encoding = match.group(1) else: @@ -3049,7 +3060,7 @@ def xmltv(): else: chardet_encoding = chardet.detect(data) encoding = chardet_encoding['encoding'] - data = data.decode(encoding) + data = data_bytes.decode(encoding) htmlparser = HTMLParser() diff --git a/server.py b/server.py index 93aa4f2..51493be 100644 --- a/server.py +++ b/server.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals -import xbmcaddon -import xbmc, xbmcgui, xbmcvfs +from kodi_six import xbmc, xbmcgui, xbmcaddon, xbmcvfs + import requests import base64 import time, datetime From 19e182d6e20636c219860545c0fa55033f5c1bad Mon Sep 17 00:00:00 2001 From: dob! Date: Sun, 10 May 2020 00:02:20 +0200 Subject: [PATCH 15/19] Fix search input not supporting non ascii character. --- main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index d09253c..73c1e9d 100644 --- a/main.py +++ b/main.py @@ -1661,7 +1661,7 @@ def search_title_dialog(): context_items.append((_("Delete Search"), 'XBMC.RunPlugin(%s)' % (plugin.url_for(delete_search_title, title=search.encode("utf8"))))) items.append({ "label": search, - "path": plugin.url_for('search_title', title=search.encode("utf8")), + "path": plugin.url_for('search_title', title=search.encode("utf-8")), "thumbnail": get_icon_path('search'), 'context_menu': context_items, }) @@ -1674,12 +1674,12 @@ def search_title_input(title): if title == "title": title = "" d = xbmcgui.Dialog() - what = d.input(_("Search Title"), title).decode("utf8") + what = d.input(_("Search Title"), title) #log(what) if not what: return searches[what] = '' - return search_title(what.encode("utf8")) + return search_title(what.encode("utf-8")) @plugin.route('/search_title/') From 51c640d3248323f7ab740bd6960ca61e7407a14d Mon Sep 17 00:00:00 2001 From: dob! <dobidev@gmail.com> Date: Sun, 10 May 2020 13:37:36 +0200 Subject: [PATCH 16/19] Factorize detection of xml files encoding. --- main.py | 56 ++++++++++++++++++++++---------------------------------- 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/main.py b/main.py index 73c1e9d..6b32498 100644 --- a/main.py +++ b/main.py @@ -2766,6 +2766,26 @@ def xml2utc(xml): return dt return '' +def find_xml_bytes_encoding(data_bytes): + data_test_decoding = data_bytes.decode('utf-8', errors='ignore') + index_end_first_line = data_test_decoding.find('\n') + match = None + if index_end_first_line != -1: + first_line = data_test_decoding[:index_end_first_line] + match = re.search('<\?xml.*?encoding=["\'](.*?)["\']', first_line, flags=(re.I|re.DOTALL)) + + if match: + encoding = match.group(1) + else: + # Improve performance by limiting the detection of the encoding + # to the first 50k characters if the XML file is bigger + if len(data_bytes) > 50000: + chardet_encoding = chardet.detect(data_bytes[:50000]) + else: + chardet_encoding = chardet.detect(data_bytes) + encoding = chardet_encoding['encoding'] + + return encoding @plugin.route('/xmltv') def xmltv(): @@ -2943,23 +2963,7 @@ def xmltv(): data_bytes = bytes(f.readBytes()) f.close() - data_test_decoding = data_bytes.decode('utf-8', errors='ignore') - index_end_first_line = data_test_decoding.find('\n') - match = None - if index_end_first_line != -1: - first_line = data_test_decoding[:index_end_first_line] - match = re.search('<\?xml.*?encoding=["\'](.*?)["\']', first_line, flags=(re.I|re.DOTALL)) - - if match: - encoding = match.group(1) - else: - # Improve performance by limiting the detection of the encoding - # to the first 50k characters if the XML file is bigger - if len(data) > 50000: - chardet_encoding = chardet.detect(data[:50000]) - else: - chardet_encoding = chardet.detect(data) - encoding = chardet_encoding['encoding'] + encoding = find_xml_bytes_encoding(data_bytes) data = data_bytes.decode(encoding) htmlparser = HTMLParser() @@ -3043,23 +3047,7 @@ def xmltv(): data_bytes = bytes(f.readBytes()) f.close() - data_test_decoding = data_bytes.decode('utf-8', errors='ignore') - index_end_first_line = data_test_decoding.find('\n') - match = None - if index_end_first_line != -1: - first_line = data_test_decoding[:index_end_first_line] - match = re.search('<\?xml.*?encoding=["\'](.*?)["\']', first_line, flags=(re.I|re.DOTALL)) - - if match: - encoding = match.group(1) - else: - # Improve performance by limiting the detection of the encoding - # to the first 50k characters if the XML file is bigger - if len(data) > 50000: - chardet_encoding = chardet.detect(data[:50000]) - else: - chardet_encoding = chardet.detect(data) - encoding = chardet_encoding['encoding'] + encoding = find_xml_bytes_encoding(data_bytes) data = data_bytes.decode(encoding) htmlparser = HTMLParser() From 886600a3f6fd9bcba893b017d93c84acbb16317c Mon Sep 17 00:00:00 2001 From: dob! <dobidev@gmail.com> Date: Sun, 10 May 2020 15:14:55 +0200 Subject: [PATCH 17/19] Fix some import for python3 --- main.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 6b32498..7eeb3fd 100644 --- a/main.py +++ b/main.py @@ -2,7 +2,6 @@ from __future__ import unicode_literals from xbmcswift2 import Plugin, ListItem -from HTMLParser import HTMLParser from collections import namedtuple from datetime import datetime, timedelta, tzinfo from language import get_string as _ @@ -13,7 +12,6 @@ import ctypes import glob import gzip -import StringIO import json import os, os.path import platform @@ -29,8 +27,12 @@ import time try: from urllib.parse import quote, quote_plus, unquote_plus + from html.parser import HTMLParser + from io import StringIO except ImportError: from urllib import quote, quote_plus, unquote_plus + from HTMLParser import HTMLParser + from StringIO import StringIO import uuid from kodi_six import xbmc, xbmcaddon, xbmcvfs, xbmcgui, xbmcplugin @@ -2948,7 +2950,7 @@ def xmltv(): magic = data_bytes[:3] if magic == "\x1f\x8b\x08": dialog.update(0, message=_("Unzipping xmltv file")) - compressedFile = StringIO.StringIO() + compressedFile = StringIO() compressedFile.write(data_bytes) compressedFile.seek(0) decompressedFile = gzip.GzipFile(fileobj=compressedFile, mode='rb') From 841b3f86b614269509f19acb25b2ba2054d65487 Mon Sep 17 00:00:00 2001 From: dob! <dobidev@gmail.com> Date: Sun, 10 May 2020 19:01:29 +0200 Subject: [PATCH 18/19] Fix loading skin estuary. --- main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 7eeb3fd..2af9a95 100644 --- a/main.py +++ b/main.py @@ -3344,7 +3344,7 @@ def estuary(): filename = xbmc.translatePath('special://home/addons/skin.estuary.iptv.recorder/addon.xml') with open(filename,'r') as f: - text = f.read() + text = f.read().decode('utf-8') text = text.replace('skin.estuary','skin.estuary.iptv.recorder').replace('Estuary','Estuary (IPTV Recorder)') with open(filename,'w') as f: write_in_file(f, text) @@ -3352,14 +3352,14 @@ def estuary(): files = glob.glob(os.path.join(to_path,'language','*','*.po')) for filename in files: with open(filename,'r') as f: - text = f.read() + text = f.read().decode('utf-8') text = text.replace('skin.estuary','skin.estuary.iptv.recorder') with open(filename,'w') as f: write_in_file(f, text) filename = xbmc.translatePath('special://home/addons/skin.estuary.iptv.recorder/xml/DialogPVRInfo.xml') with open(filename,'r') as f: - text = f.read() + text = f.read().decode('utf-8') text = text.replace('<control type="grouplist" id="9000">', '''<control type="grouplist" id="9000"> <include content="InfoDialogButton"> From 029d795b2914841d8f2b50d448200edfb31a8b82 Mon Sep 17 00:00:00 2001 From: dob! <dobidev@gmail.com> Date: Sun, 10 May 2020 19:26:11 +0200 Subject: [PATCH 19/19] Fix encoding issue in the "Record and play" feature. --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 2af9a95..f9f5a01 100644 --- a/main.py +++ b/main.py @@ -794,7 +794,7 @@ def record_once_thread(programmeid, do_refresh=True, watch=False, remind=False, write_in_file(f, "while True:\n") write_in_file(f, " data = p.stdout.read(1000000)\n") write_in_file(f, " if data:\n") - write_in_file(f, " video.write(bytearray(data.encode('utf-8')))\n") + write_in_file(f, " video.write(data)\n") write_in_file(f, " else:\n") write_in_file(f, " break\n") if play: