script.module.iptvlib/lib/iptvlib/__init__.py

285 lines
9.0 KiB
Python

# coding=utf-8
#
# Copyright (C) 2018 Dmitry Vinogradov
# https://github.com/kodi-iptv-addons
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
#
import builtins
import calendar
import datetime
import math
import os
import platform
import sys
import threading
import time
from functools import wraps
import xbmc
import xbmcaddon
import importlib
if hasattr(builtins, 'addon_id') is False:
setattr(builtins, 'addon_id', os.path.basename(os.path.abspath(os.path.dirname(__file__))))
addon = xbmcaddon.Addon(id=getattr(builtins, 'addon_id'))
utc_local_offset = math.ceil(calendar.timegm(time.localtime()) - time.time())
importlib.reload(sys)
# noinspection PyUnresolvedReferences
sys.setdefaultencoding('utf-8')
TENSECS = 10 # type: int
MIN = 60 # type: int
HALFHOUR = 1800 # type: int
HOUR = 3600 # type: int
DAY = 86400 # type: int
TWODAYS = 172800 # type: int
TREEDAYS = 259200 # type: int
WEEK = 604800 # type: int
TWOWEEKS = 1209600 # type: int
TEXT_SUBSCRIPTION_REQUIRED_ID = 30101 # type: int
TEXT_SET_CREDENTIALS_ID = 30102 # type: int
TEXT_AUTHENTICATION_FAILED_ID = 30103 # type: int
TEXT_CHECK_SETTINGS_ID = 30104 # type: int
TEXT_NOT_PLAYABLE_ID = 30105 # type: int
TEXT_SERVICE_ERROR_OCCURRED_ID = 30106 # type: int
TEXT_SURE_TO_EXIT_ID = 30107 # type: int
TEXT_ARCHIVE_NOT_AVAILABLE_YET_ID = 30108 # type: int
TEXT_JUMP_TO_ARCHIVE_ID = 30109 # type: int
TEXT_CHANNEL_HAS_NO_ARCHIVE_ID = 30110 # type: int
TEXT_LIVE_NO_FORWARD_SKIP_ID = 30111 # type: int
TEXT_IDLE_DIALOG_ID = 30112 # type: int
TEXT_IDLE_DIALOG_COUNTDOWN_ID = 30113 # type: int
TEXT_HTTP_REQUEST_ERROR_ID = 30114 # type: int
TEXT_PLEASE_RESTART_KODI_ID = 30115 # type: int
TEXT_INSTALL_EXTRA_RESOURCES_ID = 30116 # type: int
TEXT_PLEASE_CHECK_INTERNET_CONNECTION_ID = 30117 # type: int
TEXT_UNEXPECTED_RESPONSE_FROM_SERVICE_PROVIDER_ID = 30118 # type: int
TEXT_UNEXPECTED_ERROR_OCCURRED_ID = 30119 # type: int
TEXT_NO_INFO_AVAILABLE_ID = 30201 # type: int
TEXT_ABBR_MINUTES_ID = 30202 # type: int
TEXT_ABBR_SECONDS_ID = 30203 # type: int
TEXT_WEEKDAY_FULL_ID_PREFIX = 3030 # type: int
TEXT_WEEKDAY_ABBR_ID_PREFIX = 3031 # type: int
TEXT_MONTH_FULL_ID_PREFIX = 304 # type: int
TEXT_MONTH_ABBR_ID_PREFIX = 305 # type: int
# noinspection PyUnresolvedReferences
class WindowMixin(object):
is_closing = False # type: bool
def __init__(self, **kwargs):
self.is_closing = False
super(WindowMixin, self).__init__()
def close(self):
self.is_closing = True
super(WindowMixin, self).close()
def show_control(self, *control_ids):
for control_id in control_ids:
control = self.getControl(control_id)
if control:
control.setVisible(True)
def hide_control(self, *control_ids):
for control_id in control_ids:
control = self.getControl(control_id)
if control:
control.setVisible(False)
def set_control_image(self, control_id, image):
control = self.getControl(control_id)
if control:
control.setImage(image)
def setcontrol_label(self, control_id, label):
control = self.getControl(control_id)
if control and label:
control.setLabel(label)
def set_control_text(self, control_id, text):
control = self.getControl(control_id)
if control:
control.setText(text)
def get_string(id_):
return xbmcaddon.Addon(os.path.basename(os.path.abspath(os.path.dirname(__file__) + "/../../"))).getLocalizedString(id_)
def show_small_popup(title='', msg='', delay=5000, image=''):
xbmc.executebuiltin('XBMC.Notification("%s","%s",%d,"%s")' % (title, msg, delay, image))
def build_user_agent():
# type: () -> str
return 'KODI/%s (%s; %s %s; python %s) %s/%s ' % (
xbmc.getInfoLabel('System.BuildVersion').split(" ")[0],
xbmc.getInfoLabel('System.BuildVersion'),
platform.system(),
platform.release(),
platform.python_version(),
addon.getAddonInfo('id').replace('-DEV', ''),
addon.getAddonInfo('version')
)
def unique(s, t):
# type: (str, str) -> str
t = (t * ((len(s) // len(t)) + 1))[:len(s)]
if isinstance(s, str):
return "".join(chr(ord(a) ^ ord(b)) for a, b in zip(s, t))
else:
return str([a ^ b for a, b in zip(s, t)])
def secs_to_percent(length, played):
# type: (int, float) -> float
return (100 * played) / length
def percent_to_secs(length, percent):
# type: (int, float) -> int
return int((length * percent) / 100)
def format_secs(secs, id="time"):
# type: (int, str) -> str
if id == "time":
return "{:0>8}".format(datetime.timedelta(seconds=secs))
if id == "skip":
prefix = "+"
if secs < 0:
prefix = "-"
secs *= -1
elif secs == 0:
prefix = ""
if secs > 60:
return "%s%s %s" % (prefix, secs / 60, get_string(TEXT_ABBR_MINUTES_ID))
return "%s%s %s" % (prefix, secs, get_string(TEXT_ABBR_SECONDS_ID))
def format_date(timestamp, id="dateshort", custom_format=None):
# type: (float, str, str) -> str
ids = {
"%A": (TEXT_WEEKDAY_FULL_ID_PREFIX, "%w"),
"%a": (TEXT_WEEKDAY_ABBR_ID_PREFIX, "%w"),
"%B": (TEXT_MONTH_FULL_ID_PREFIX, "%m"),
"%b": (TEXT_MONTH_ABBR_ID_PREFIX, "%m")
}
if timestamp:
if custom_format is not None:
dt = datetime.datetime.fromtimestamp(timestamp)
for k in ids.keys():
if k in custom_format:
v = get_string(int("%s%s" % (ids[k][0], dt.strftime(ids[k][1]))))
custom_format = custom_format.replace(k, v)
return dt.strftime(custom_format)
return datetime.datetime.fromtimestamp(timestamp).strftime(xbmc.getRegion(id))
return ''
def time_now():
# type: () -> float
return time.time()
def timestamp_to_midnight(timestamp):
# type: (float) -> int
# noinspection PyTypeChecker
return int(time.mktime(
datetime.datetime.combine(
datetime.datetime.fromtimestamp(timestamp),
datetime.datetime.min.time()
).timetuple()
))
def str_to_datetime(str_date, fmt):
# type: (str, str) -> datetime.datetime
try:
d = datetime.datetime.strptime(str_date, fmt)
except TypeError:
from time import strptime
d = datetime.datetime(*(strptime(str_date, fmt)[0:6]))
return d
def str_to_timestamp(str_date, fmt):
# type: (str, str) -> int
try:
return int(time.mktime(str_to_datetime(str_date, fmt).timetuple()))
except:
return 0
def run_async(func):
"""
Decorator to run a function in a separate thread
"""
@wraps(func)
def async_func(*args, **kwargs):
thread = threading.Thread(target=func, args=args, kwargs=kwargs)
thread.start()
return thread
return async_func
def log(msg, level=xbmc.LOGINFO):
if level == xbmc.LOGDEBUG:
import inspect
mod = inspect.getmodule(inspect.stack()[1][0])
calframe = inspect.getouterframes(inspect.currentframe(), 2)
msg = "------- [%s.%s] : %s" % (mod.__name__, calframe[1][3], msg)
xbmc.log('%s: %s' % (addon.getAddonInfo('name'), msg), level)
def normalize(text):
# type: (str) -> str
if type(text) is not str:
text = str(text)
symbols = ("абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ",
"abvgdeejzijklmnoprstufhzcss_y_euaABVGDEEJZIJKLMNOPRSTUFHZCSS_Y_EUA")
tr = dict([(ord(a), ord(b)) for (a, b) in zip(*symbols)])
import re
regs = [
'\s+\+[0-9]+', # time shift suffix, e.g. "RTL +7"
'\s+\[[a-zA-Z]+\]', # land code suffix, e.g. "RTL [de]"
'\s+(HQ)', # High quality suffix, e.g. "RTL (HQ)"
]
for reg in regs:
text = re.sub(reg, '', text)
return re.sub('[^0-9a-zA-Z+-]+', '', text.translate(tr)).upper()
x = lambda s: s.decode("hex")
z = lambda s: str.encode(s, "hex")
h1 = '3d37612b5542244c4e3952775a3f6b5a24367732426e583750'
h2 = '5543155b26780b63394e25593d50043d48535a532c0f344e24' \
'54541205362d49632d563e1b3f5c1f65505f130f172f750e66' \
'0b03541f65710978684f6f467c4b563f52531946640b3b0a2b' \
'4011044a6839596a2b556f0c27190e2c194d0a1421073c0a2b' \
'40113e162e3f'