diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..0a04128
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/README.md b/README.md
index 9830773..e08bf92 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,45 @@
-# script.video.iptv.itv
+# ITV Addon for KODI
+[![logo](https://raw.githubusercontent.com/kodi-iptv-addons/kodi-iptv-addons/master/script.video.iptv.itv/resources/icon.png)](https://goo.gl/LZQKVL)
+
+
+
+## Installation guide
+
+* Download repository zip file: [https://goo.gl/NQ4CEY](https://goo.gl/NQ4CEY) (which is a shortcut to [repository.iptv.zip](https://raw.githubusercontent.com/dmitry-vinogradov/kodi-iptv-addons/master/repository.iptv.zip))
+* In KODI's _Add-ons / Add-on browser_ select **Install from zip file**
+* Navigate and choose the downloaded repository zip file **_repository.iptv.zip_**
+* After installation:
+ * go to **Install from repository**
+ * select **IPTV Add-ons repository**
+ * open **Video Addons**
+ * Select and install **ITV** addon.
+
+## Установка
+
+* Скачиваем ZIP файл репозитория: [https://goo.gl/NQ4CEY](https://goo.gl/NQ4CEY) (это сокращенный URL для [repository.iptv.zip](https://raw.githubusercontent.com/dmitry-vinogradov/kodi-iptv-addons/master/repository.iptv.zip))
+* В разделе _Дополнения_ выбираем **Установить из файла ZIP**
+* Выбираем скаченный ZIP файл **_repository.iptv.zip_**
+* После установки репозитория:
+ * Выбираем пункт **Установка из репозитория**
+ * Выбираем репозиторий **IPTV Add-ons repository**
+ * Открываем **Видеодополнения**
+ * Выбираем и устанавливаем **ITV** дополнение.
+
+### Screenshots:
+
+
+
+[![screenshot](https://raw.githubusercontent.com/kodi-iptv-addons/kodi-iptv-addons/master/screenshot_01.png)](#)
+
+
+
+[![screenshot](https://raw.githubusercontent.com/kodi-iptv-addons/kodi-iptv-addons/master/screenshot_02.png)](#)
+
+
+
+[![screenshot](https://raw.githubusercontent.com/kodi-iptv-addons/kodi-iptv-addons/master/screenshot_03.png)](#)
+
+
+
+[![screenshot](https://raw.githubusercontent.com/kodi-iptv-addons/kodi-iptv-addons/master/screenshot_04.png)](#)
\ No newline at end of file
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..9e7cc30
--- /dev/null
+++ b/__init__.py
@@ -0,0 +1,20 @@
+# 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.
+#
diff --git a/addon.xml b/addon.xml
new file mode 100644
index 0000000..c5bb8d4
--- /dev/null
+++ b/addon.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+ video
+
+
+
+ resources/icon.png
+
+
+
+ all
+ IPTV player for ITV (itv.live)
+ IPTV player for ITV (itv.live)
+ GNU LESSER GENERAL PUBLIC LICENSE Version 3, June 2007
+
+
+v1.1.3 (2020-04-15)
+- Minor bug fixes
+v1.1.2 (2020-03-30)
+- Fixed stream URL resolving
+v1.1.1 (2019-01-31)
+- Implemented usage of alternative EPG with program images
+- Added stop on idle addon settings
+v1.0.4 (2018-11-02)
+- Improved error handling
+v1.0.3 (2018-10-20)
+- Handle authentication failures properly
+v1.0.2 (2018-10-20)
+- Set default value for hostname in settings to api.itv.live
+v1.0.1 (2018-10-19)
+- Bug fixes
+v1.0.0 (2018-10-19)
+- Initial release
+
+
+
diff --git a/changelog.txt b/changelog.txt
new file mode 100644
index 0000000..b4916cf
--- /dev/null
+++ b/changelog.txt
@@ -0,0 +1,17 @@
+v1.1.3 (2020-04-15)
+- Minor bug fixes
+v1.1.2 (2020-03-30)
+- Fixed stream URL resolving
+v1.1.1 (2019-01-31)
+- Implemented usage of alternative EPG with program images
+- Added stop on idle addon settings
+v1.0.4 (2018-11-02)
+- Improved error handling
+v1.0.3 (2018-10-20)
+- Handle authentication failures properly
+v1.0.2 (2018-10-20)
+- Set default value for hostname in settings to api.itv.live
+v1.0.1 (2018-10-19)
+- Bug fixes
+v1.0.0 (2018-10-19)
+- Initial release
diff --git a/default.py b/default.py
new file mode 100644
index 0000000..4037c23
--- /dev/null
+++ b/default.py
@@ -0,0 +1,82 @@
+# 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 os
+
+setattr(builtins, 'addon_id', os.path.basename(os.path.abspath(os.path.dirname(__file__))))
+
+import xbmcgui
+from .itv import Itv
+from iptvlib.api import ApiException
+from iptvlib import *
+from iptvlib.mainwindow import MainWindow
+
+
+class Main(object):
+ def __init__(self):
+ self.main_window = MainWindow.create(self.check_settings)
+ self.main_window.doModal()
+ del self.main_window
+
+ def check_settings(self):
+ # type: () -> bool
+ hostname = addon.getSetting("hostname")
+ key = addon.getSetting("key")
+ if hostname == "" or key == "":
+
+ dialog = xbmcgui.Dialog()
+ yesno = bool(
+ dialog.yesno(
+ addon.getAddonInfo("name"), " ",
+ get_string(TEXT_SUBSCRIPTION_REQUIRED_ID),
+ get_string(TEXT_SET_CREDENTIALS_ID)
+ )
+ )
+ del dialog
+ if yesno is True:
+ addon.openSettings()
+ return self.check_settings()
+ else:
+ return False
+
+ adult = addon.getSetting("adult") == 'true' or \
+ addon.getSetting("adult") == True
+ sort_channels = addon.getSetting("sort_channels") == 'true' or \
+ addon.getSetting("sort_channels") == True
+
+ try:
+ self.main_window.api = Itv(hostname, key, adult, sort_channels=sort_channels)
+ except ApiException as ex:
+ if ex.code == Itv.E_HTTP_REQUEST_FAILED:
+ dialog = xbmcgui.Dialog()
+ dialog.ok(
+ addon.getAddonInfo("name"),
+ get_string(TEXT_HTTP_REQUEST_ERROR_ID) + '\n' +
+ ex.message + '\n' +
+ ex.origin_error
+ )
+ return False
+
+ return True
+
+
+if __name__ == "__main__":
+ Main()
diff --git a/itv.py b/itv.py
new file mode 100644
index 0000000..89c412f
--- /dev/null
+++ b/itv.py
@@ -0,0 +1,162 @@
+# 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 json
+from urllib.parse import quote
+
+from iptvlib.api import Api, ApiException
+from iptvlib.models import *
+
+
+class Itv(Api):
+ PROTECTED_GROUP = "Взрослый"
+ TEXT_ERROR_WRONG_KEY_ID = 30005 # type: int
+
+ key = None # type: str
+ adult = None # type: bool
+ sort_channels = None # type: bool
+ hostname = None # type: str
+ _player_info = None # type: list
+
+ def __init__(self, hostname, key, adult, **kwargs):
+ super(Itv, self).__init__(**kwargs)
+ self.hostname = hostname
+ self.key = self.username = key
+ self.adult = adult
+ self.auth_status = self.AUTH_STATUS_NONE
+ Model.API = self
+
+ @property
+ def base_api_url(self):
+ return "http://%s/%%s" % self.hostname
+
+ @property
+ def base_icon_url(self):
+ return "http://%s/icon/%%s" % self.hostname
+
+ @property
+ def host(self):
+ return self.hostname
+
+ @property
+ def diff_live_archive(self):
+ return TENSECS
+
+ @property
+ def archive_ttl(self):
+ return TREEDAYS
+
+ def get_cookie(self):
+ return ""
+
+ def is_login_request(self, uri, payload=None, method=None, headers=None):
+ return uri == "" and payload.get("action") == "playerInfo"
+
+ def login(self):
+ self._player_info = []
+ response = self.make_request("", {"action": "playerInfo", "ukey": self.key})
+ if isinstance(response, list) and len(response) and response[0].get("response") == "No Token":
+ raise ApiException(
+ addon.getLocalizedString(self.TEXT_ERROR_WRONG_KEY_ID),
+ Api.E_API_ERROR
+ )
+ else:
+ is_error, error = Api.is_error_response(response)
+ if is_error:
+ raise ApiException(error.get("message"), error.get("code"))
+
+ self._player_info = response
+ self.auth_status = self.AUTH_STATUS_OK
+ return response
+
+ def get_groups(self):
+ if self._player_info is None:
+ self.login()
+ number = 1
+ groups = OrderedDict()
+ channels = OrderedDict()
+ for channel_data in self._player_info:
+ if (channel_data["cat_id"] in groups) is False:
+ gid = str(channel_data["cat_id"])
+ groups[gid] = Group(
+ gid=gid,
+ name=channel_data["cat_name"],
+ channels=OrderedDict(),
+ number=number
+ )
+ number += 1
+ group = groups[channel_data["cat_id"]]
+
+ if self.adult is False and group.name == self.PROTECTED_GROUP:
+ continue
+
+ cid = str(channel_data["ch_id"])
+ channel = Channel(
+ cid=cid,
+ gid=group.gid,
+ name=channel_data["channel_name"],
+ icon=self.base_icon_url % channel_data["logo"],
+ epg=True,
+ archive=bool(channel_data.get("rec", 0)),
+ protected=group.name == self.PROTECTED_GROUP
+ )
+ channel.data.update({"server": channel_data["server_cdn"], "token": channel_data["token"], "port": channel_data["port_cdn"]})
+ group.channels[cid] = channels[cid] = channel
+ return groups
+
+ def get_stream_url(self, cid, ut_start=None):
+ channel = self.channels[cid]
+ url = "http://%s:%s/%s/" % \
+ (channel.data["server"], channel.data["port"] if channel.data["port"] != "" else "80", cid)
+ if ut_start is None:
+ url = "%smono.m3u8?token=%s" % (url, channel.data["token"])
+ else:
+ url = "%sindex-%s-%s.m3u8?token=%s" % (url, int(ut_start), int(time_now() - ut_start), channel.data["token"])
+ return self.resolve_url(url)
+
+ def get_epg(self, cid):
+ # type: (str) -> OrderedDict[int, Program]
+ programs = self.get_epg_gh(self.channels[cid])
+ if len(programs):
+ return programs
+
+ obj = quote(json.dumps({"action": "epg", "chid": cid}))
+ response = self.make_request("epg.php?obj=%s" % obj) # type: dict[str, list[dict]]
+ is_error, error = Api.is_error_response(response)
+ if is_error:
+ raise ApiException(error.get("message"), error.get("code"))
+
+ programs = OrderedDict()
+ prev = None
+ for v in response["res"]:
+ program = Program(
+ cid,
+ self.channels[cid].gid,
+ int(v["startTime"]),
+ int(v["stopTime"]),
+ v["title"],
+ v["desc"],
+ self.channels[cid].archive
+ )
+ if prev is not None:
+ program.prev_program = prev
+ prev.next_program = program
+ programs[program.ut_start] = prev = program
+ return programs
diff --git a/resources/icon.png b/resources/icon.png
new file mode 100644
index 0000000..585fffe
Binary files /dev/null and b/resources/icon.png differ
diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po
new file mode 100644
index 0000000..e114061
--- /dev/null
+++ b/resources/language/English/strings.po
@@ -0,0 +1,35 @@
+# XBMC Media Center language file
+# Addon Name: IPTV player for ITV (itv.live)
+# Addon id: script.video.iptv.itv
+# Addon Provider: Dmitry Vinogradov
+msgid ""
+msgstr ""
+
+# Settings
+msgctxt "#30001"
+msgid "ITV Account"
+msgstr "ITV Account"
+
+msgctxt "#30002"
+msgid "Api Hostname"
+msgstr "Api Hostname"
+
+msgctxt "#30003"
+msgid "Key"
+msgstr "Key"
+
+msgctxt "#30004"
+msgid "Show adult channels"
+msgstr "Show adult channels"
+
+msgctxt "#30005"
+msgid "Wrong key"
+msgstr "Wrong key"
+
+msgctxt "#30006"
+msgid "Sort channels"
+msgstr "Sort channels"
+
+msgctxt "#30007"
+msgid "Stop playback when idle"
+msgstr "Stop playback when idle"
diff --git a/resources/language/German/strings.po b/resources/language/German/strings.po
new file mode 100644
index 0000000..c646986
--- /dev/null
+++ b/resources/language/German/strings.po
@@ -0,0 +1,35 @@
+# XBMC Media Center language file
+# Addon Name: IPTV player for ITV (itv.live)
+# Addon id: script.video.iptv.itv
+# Addon Provider: Dmitry Vinogradov
+msgid ""
+msgstr ""
+
+# Settings
+msgctxt "#30001"
+msgid "Account"
+msgstr "Zugangsdaten"
+
+msgctxt "#30002"
+msgid "Api Hostname"
+msgstr "Api Hostname"
+
+msgctxt "#30003"
+msgid "Key"
+msgstr "Key"
+
+msgctxt "#30004"
+msgid "Show adult channels"
+msgstr "Zeige Kanäle für Erwachsene"
+
+msgctxt "#30005"
+msgid "Wrong key"
+msgstr "Falscher Key"
+
+msgctxt "#30006"
+msgid "Sort channels"
+msgstr "Sortiere Kanäle"
+
+msgctxt "#30007"
+msgid "Stop playback when idle"
+msgstr "Wiedergabestop bei Inaktivität"
diff --git a/resources/language/Russian/strings.po b/resources/language/Russian/strings.po
new file mode 100644
index 0000000..965117f
--- /dev/null
+++ b/resources/language/Russian/strings.po
@@ -0,0 +1,35 @@
+# XBMC Media Center language file
+# Addon Name: IPTV player for ITV (itv.live)
+# Addon id: script.video.iptv.itv
+# Addon Provider: Dmitry Vinogradov
+msgid ""
+msgstr ""
+
+# Settings
+msgctxt "#30001"
+msgid "Account"
+msgstr "Аккаунт"
+
+msgctxt "#30002"
+msgid "Api Hostname"
+msgstr "Имя API хоста"
+
+msgctxt "#30003"
+msgid "Key"
+msgstr "Ключ"
+
+msgctxt "#30004"
+msgid "Show adult channels"
+msgstr "Показывать каналы для взрослых"
+
+msgctxt "#30005"
+msgid "Wrong key"
+msgstr "Неправильный ключ"
+
+msgctxt "#30006"
+msgid "Sort channels"
+msgstr "Сортировать каналы"
+
+msgctxt "#30007"
+msgid "Stop playback when idle"
+msgstr "Прекращать воспроизведение при неактивности"
diff --git a/resources/settings.xml b/resources/settings.xml
new file mode 100644
index 0000000..dc0822a
--- /dev/null
+++ b/resources/settings.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+