Skip to content

Commit

Permalink
Merge pull request #75 from dimkroon/version-1.2.0
Browse files Browse the repository at this point in the history
Version 1.2.0
  • Loading branch information
dimkroon authored Dec 6, 2023
2 parents 77181d7 + 8143312 commit c4217bb
Show file tree
Hide file tree
Showing 56 changed files with 31,614 additions and 4,211 deletions.
27 changes: 18 additions & 9 deletions plugin.video.viwx/addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.viwx" name="viwX" version="1.1.1" provider-name="Dimitri Kroon">
<addon id="plugin.video.viwx" name="viwX" version="1.2.0" provider-name="Dimitri Kroon">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="inputstream.adaptive" version="19.0.5"/>
Expand Down Expand Up @@ -30,15 +30,24 @@
<fanart>resources/fanart.png</fanart>
</assets>
<news>
[B]v1.1.1[/B]
- fix: playing VOD on kodi Omega failed with error.
[B]v1.2.0[/B]
[B]Fixes:[/B]
* All categories failed to open due to various changes at ITVX.
* Error on opening some series named 'Other Episodes', due to changes at ITVX.
* Some sub-collections failed with error 'Not Found', due to error in ITVX data'
* Added support for hero and collections items of type 'page'. Fixes some collections being empty, or hero item not shown.

[B]v1.1.0[/B]
- Updated user-agent string to Firefox 118.
- Added support for Live TV items in collections. Fixes: collection 'ITVX Live Channels' is empty.
- Added support for shortFromSlider in collection, like the folder with short news-like items in the collection 'Rugby World Cup'.
- Added support for shorForm collections. Fixes: absence of the collection 'Rugby World Cup 2023'.
- Adapt to a change at itvx causing an empty 'Kids Collection'.
[B]New features:[/B]
* Added a 'My itvX' entry in the main menu with:
- My List - ITVX's My List.
- Continue Watching: supports continue watching on different devices and different platforms.
- Because You Watched: recommendations by ITV based on a recently watched programme.
- Recommended: general recommendations by ITV.
* All programmes and series now have a context menu item to add/remove the programme to/from My List.

[B]Changes:[/B]
* When not signed in, a user is now always offered to sign in via viwX's settings when an item was opened that required authentication.
* Search now respects setting 'Hide premium content'.
</news>
<reuselanguageinvoker>true</reuselanguageinvoker>
</extension>
Expand Down
20 changes: 20 additions & 0 deletions plugin.video.viwx/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
v1.2.0
Fixes:
- All categories failed to open due to various changes at ITVX.
- Error on opening some series named 'Other Episodes', due to changes at ITVX.
- Some sub-collections failed with error 'Not Found', due to error in ITVX data.
- Added support for hero and collections items of type 'page'. Fixes some collections being empty, or hero item not shown.

New features:
- Added a 'My itvX' entry in the main menu with:
- My List - ITVX's My List.
- Continue Watching: supports continue watching on different devices and different platforms.
- Because You Watched: recommendations by ITV based on a recently watched programme.
- Recommended: general recommendations by ITV.
- All programmes and series now have a context menu item to add/remove the programme to/from My List.

Changes:
- When not signed in, a user is now always offered to sign in via viwX's settings when an item was opened that required authentication.
- Search now respects setting 'Hide premium content'.
- Brushed up README thanks to JohnVeness.

v 1.1.1
- fix: playing VOD on kodi Omega failed with error.

Expand Down
3 changes: 3 additions & 0 deletions plugin.video.viwx/resources/lib/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
__cache = {}


my_list_programmes = None


def get_item(key):
"""Return the cached data if present in the cache and not expired.
Return None otherwise.
Expand Down
27 changes: 21 additions & 6 deletions plugin.video.viwx/resources/lib/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

WEB_TIMEOUT = (3.5, 7)
USER_AGENT = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0'
USER_AGENT_VERSION = '118.0'


logger = logging.getLogger('.'.join((logger_id, __name__.split('.', 2)[-1])))
Expand Down Expand Up @@ -132,14 +133,14 @@ def set_default_cookies(cookiejar: RequestsCookieJar = None):
Return the cookiejar
"""
s = requests.Session()
if isinstance(cookiejar, RequestsCookieJar):
s.cookies = cookiejar
elif cookiejar is not None:
raise ValueError("Parameter cookiejar must be an instance of RequestCookiejar")

# noinspection PyBroadException
try:
s = requests.Session()
if isinstance(cookiejar, RequestsCookieJar):
s.cookies = cookiejar
elif cookiejar is not None:
raise ValueError("Parameter cookiejar must be an instance of RequestCookiejar")

# Make a request to reject all cookies.
resp = s.get(
'https://identityservice.syrenis.com/Home/SaveConsent',
Expand Down Expand Up @@ -260,6 +261,20 @@ def put_json(url, data, headers=None, **kwargs):
return resp


def delete_json(url, data, headers=None, **kwargs):
"""DELETE JSON data and return the response object or None if no data has been returned."""
dflt_headers = {'Accept': 'application/json'}
if headers:
dflt_headers.update(headers)
resp = web_request('DELETE', url, dflt_headers, data, **kwargs)
if resp.status_code == 204: # No Content
return None
try:
return resp.json()
except json.JSONDecodeError:
raise FetchError(Script.localize(30920))


def get_document(url, headers=None, **kwargs):
"""GET any document. Expects the document to be UTF-8 encoded and returns
the contents as string.
Expand Down
71 changes: 27 additions & 44 deletions plugin.video.viwx/resources/lib/itv.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
from . import fetch
from . import kodi_utils

from .errors import AuthenticationError


logger = logging.getLogger(logger_id + '.itv')

Expand Down Expand Up @@ -89,48 +87,33 @@ def get_live_schedule(hours=4, local_tz=None):
}


def _request_stream_data(url, stream_type='live', retry_on_error=True):
from .itv_account import itv_session
def _request_stream_data(url, stream_type='live'):
from .itv_account import itv_session, fetch_authenticated
session = itv_session()

try:
stream_req_data['user']['token'] = session.access_token
stream_req_data['client']['supportsAdPods'] = stream_type != 'live'

if stream_type == 'live':
accept_type = 'application/vnd.itv.online.playlist.sim.v3+json'
# Live MUST have a featureset containing an item without outband-webvtt, or a bad request is returned.
min_features = ['mpeg-dash', 'widevine']
else:
accept_type = 'application/vnd.itv.vod.playlist.v2+json'
# ITV appears now to use the min feature for catchup streams, causing subtitles
# to go missing if not specified here. Min and max both specifying webvtt appears to
# be no problem for catchup streams that don't have subtitles.
min_features = ['mpeg-dash', 'widevine', 'outband-webvtt', 'hd', 'single-track']

stream_req_data['variantAvailability']['featureset']['min'] = min_features

stream_data = fetch.post_json(
url, stream_req_data,
headers={'Accept': accept_type},
cookies=session.cookie)

http_status = stream_data.get('StatusCode', 0)
if http_status == 401:
raise AuthenticationError

return stream_data
except AuthenticationError:
if retry_on_error:
if session.refresh():
return _request_stream_data(url, stream_type, retry_on_error=False)
else:
if kodi_utils.show_msg_not_logged_in():
from xbmc import executebuiltin
executebuiltin('Addon.OpenSettings({})'.format(utils.addon_info.id))
raise
else:
raise
stream_req_data['user']['token'] = session.access_token
stream_req_data['client']['supportsAdPods'] = stream_type != 'live'

if stream_type == 'live':
accept_type = 'application/vnd.itv.online.playlist.sim.v3+json'
# Live MUST have a featureset containing an item without outband-webvtt, or a bad request is returned.
min_features = ['mpeg-dash', 'widevine']
else:
accept_type = 'application/vnd.itv.vod.playlist.v2+json'
# ITV appears now to use the min feature for catchup streams, causing subtitles
# to go missing if not specified here. Min and max both specifying webvtt appears to
# be no problem for catchup streams that don't have subtitles.
min_features = ['mpeg-dash', 'widevine', 'outband-webvtt', 'hd', 'single-track']

stream_req_data['variantAvailability']['featureset']['min'] = min_features

stream_data = fetch_authenticated(
fetch.post_json, url,
data=stream_req_data,
headers={'Accept': accept_type},
cookies=session.cookie)

return stream_data


def get_live_urls(url=None, title=None, start_time=None, play_from_start=False):
Expand Down Expand Up @@ -178,12 +161,12 @@ def get_catchup_urls(episode_url):
subtitles = stream_data['Subtitles'][0]['Href']
except (TypeError, KeyError, IndexError):
subtitles = None
return dash_url, key_service, subtitles, playlist['VideoType']
return dash_url, key_service, subtitles, playlist['VideoType'], playlist['ProductionId']


def get_vtt_subtitles(subtitles_url):
"""Return a tuple with the file paths to rst subtitles files. The tuple usually
has only one single element, but could contain more.
has only a single element, but could contain more.
Return None if subtitles_url does not point to a valid Web-vvt subtitle file or
subtitles are not te be shown by user setting.
Expand Down
Loading

0 comments on commit c4217bb

Please sign in to comment.