Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions plugin.video.vrt.nu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ leave a message at [our Facebook page](https://facebook.com/kodivrtnu/).
</table>

## Releases
### v2.5.43 (2025-09-15)
- Fix TV guide menu listings (@mediaminister)

### v2.5.42 (2025-08-29)
- Fix api calls (@mediaminister)

Expand Down
5 changes: 4 additions & 1 deletion plugin.video.vrt.nu/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.vrt.nu" name="VRT MAX" version="2.5.42+matrix.1" provider-name="Martijn Moreel, dagwieers, mediaminister">
<addon id="plugin.video.vrt.nu" name="VRT MAX" version="2.5.43+matrix.1" provider-name="Martijn Moreel, dagwieers, mediaminister">
<requires>
<import addon="resource.images.studios.white" version="0.0.22"/>
<import addon="script.module.beautifulsoup4" version="4.6.2"/>
Expand Down Expand Up @@ -42,6 +42,9 @@
<website>https://github.com/add-ons/plugin.video.vrt.nu/wiki</website>
<source>https://github.com/add-ons/plugin.video.vrt.nu</source>
<news>
v2.5.43 (2025-09-15)
- Fix TV guide menu listings

v2.5.42 (2025-08-29)
- Fix api calls

Expand Down
9 changes: 2 additions & 7 deletions plugin.video.vrt.nu/resources/lib/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""This is the actual VRT MAX video plugin entry point"""

from __future__ import absolute_import, division, unicode_literals
from routing import Plugin

try: # Python 3
from urllib.parse import unquote_plus
except ImportError: # Python 2
from urllib import unquote_plus
from urllib.parse import unquote_plus

from routing import Plugin
from kodiutils import container_refresh, end_of_directory, execute_builtin, get_global_setting, localize, log_access, notification, ok_dialog, refresh_caches

plugin = Plugin() # pylint: disable=invalid-name
Expand Down
1 change: 0 additions & 1 deletion plugin.video.vrt.nu/resources/lib/addon_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""This is the actual VRT MAX video plugin entry point"""

from __future__ import absolute_import, division, unicode_literals
import xbmcaddon
import kodiutils

Expand Down
13 changes: 4 additions & 9 deletions plugin.video.vrt.nu/resources/lib/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,13 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Implements VRT MAX GraphQL API functionality"""

from __future__ import absolute_import, division, unicode_literals

try: # Python 3
from urllib.parse import quote_plus, unquote
except ImportError: # Python 2
from urllib import quote_plus, unquote
from urllib.parse import quote_plus, unquote

from data import CHANNELS
from helperobjects import TitleItem
from kodiutils import (colour, delete_cached_thumbnail, get_cache, get_setting_bool, get_setting_int, get_url_json, has_addon, has_credentials,
localize, localize_from_data, log, update_cache, url_for)
from utils import find_entry, from_unicode, reformat_image_url, shorten_link, to_unicode, url_to_program, youtube_to_plugin_url
from utils import find_entry, reformat_image_url, shorten_link, url_to_program, youtube_to_plugin_url
from graphql_data import EPISODE_TILE

SCREENSHOT_URL = 'https://www.vrt.be/vrtnu-static/screenshots'
Expand Down Expand Up @@ -47,7 +42,7 @@ def get_context_menu(program_name, program_id, program_title, program_type, favo

# Follow/unfollow
follow_suffix = localize(30410) if program_type != 'oneoff' else '' # program
encoded_program_title = to_unicode(quote_plus(from_unicode(program_title))) # We need to ensure forward slashes are quoted
encoded_program_title = quote_plus(program_title) # We need to ensure forward slashes are quoted
if favorited:
context_menu.append((
localize(30412, title=follow_suffix), # Unfollow
Expand Down Expand Up @@ -465,7 +460,7 @@ def get_latest_episode_data(program_name):
highest_ep_no = 0
highest_ep = {}
for edge in edges:
ep_no = int(edge.get('node').get('episode').get('episodeNumberRaw'))
ep_no = int(edge.get('node').get('episode').get('episodeNumberRaw') or 0)
if ep_no > highest_ep_no:
highest_ep_no = ep_no
highest_ep = edge.get('node').get('episode')
Expand Down
12 changes: 3 additions & 9 deletions plugin.video.vrt.nu/resources/lib/apihelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,15 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Implements an ApiHelper class with common VRT MAX API functionality"""

from __future__ import absolute_import, division, unicode_literals

try: # Python 3
from urllib.parse import quote_plus, unquote
except ImportError: # Python 2
from urllib import quote_plus
from urllib2 import unquote
from urllib.parse import quote_plus, unquote

from data import CHANNELS
from helperobjects import TitleItem
from kodiutils import (delete_cached_thumbnail, get_cache, get_cached_url_json, get_global_setting,
get_setting_bool, get_setting_int, get_url_json, has_addon, localize,
localize_from_data, log, ttl, update_cache, url_for)
from metadata import Metadata
from utils import (add_https_proto, html_to_kodi, find_entry, from_unicode, play_url_to_id,
from utils import (add_https_proto, html_to_kodi, find_entry, play_url_to_id,
realpage, youtube_to_plugin_url)


Expand Down Expand Up @@ -594,7 +588,7 @@ def get_episodes(self, program=None, season=None, episodes=None, category=None,
if keywords:
if not season:
season = 'allseasons'
params['q'] = quote_plus(from_unicode(keywords))
params['q'] = quote_plus(keywords)
params['highlight'] = 'true'

if whatson_id:
Expand Down
2 changes: 0 additions & 2 deletions plugin.video.vrt.nu/resources/lib/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""A list of static data"""

from __future__ import absolute_import, division, unicode_literals

# The margin at start/end to consider a video as watched
# This value is used by resumepoints and upnext
SECONDS_MARGIN = 30
Expand Down
10 changes: 2 additions & 8 deletions plugin.video.vrt.nu/resources/lib/favorites.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Implementation of Favorites class"""

from __future__ import absolute_import, division, unicode_literals

try: # Python 3
from urllib.parse import unquote
except ImportError: # Python 2
from urllib2 import unquote
from urllib.parse import unquote

from kodiutils import (container_refresh, get_cache, get_setting_bool, get_url_json,
has_credentials, input_down, invalidate_caches, localize,
Expand Down Expand Up @@ -84,7 +79,7 @@ def get_favorites(self):
'Authorization': 'Bearer ' + access_token,
'Content-Type': 'application/json',
'x-vrt-client-name': 'WEB',
'x-vrt-client-version': '1.5.0',
'x-vrt-client-version': '1.5.12',
}
graphql = """
query Favs(
Expand Down Expand Up @@ -119,7 +114,6 @@ def get_favorites(self):
__typename
... on LinkAction {
link
linkType
__typename
}
}
Expand Down
3 changes: 0 additions & 3 deletions plugin.video.vrt.nu/resources/lib/graphql_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Implements VRT MAX GraphQL API functionality"""

from __future__ import absolute_import, division, unicode_literals


EPISODE_TILE = """
fragment episodeTile on EpisodeTile {
__typename
Expand Down
2 changes: 0 additions & 2 deletions plugin.video.vrt.nu/resources/lib/helperobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Various helper classes used throughout the VRT MAX add-on"""

from __future__ import absolute_import, division, unicode_literals


class ApiData:
"""This helper object holds all media information"""
Expand Down
1 change: 0 additions & 1 deletion plugin.video.vrt.nu/resources/lib/iptvmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""Implementation of IPTVManager class"""

from __future__ import absolute_import, division, unicode_literals
from kodiutils import log, url_for


Expand Down
59 changes: 20 additions & 39 deletions plugin.video.vrt.nu/resources/lib/kodiutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
"""All functionality that requires Kodi imports"""

from __future__ import absolute_import, division, unicode_literals
from contextlib import contextmanager
from sys import version_info
from socket import timeout
from ssl import SSLError

from urllib.parse import quote, urlencode
from urllib.request import HTTPErrorProcessor

import xbmc
import xbmcplugin

Expand All @@ -17,14 +19,6 @@
from xbmc import translatePath # pylint: disable=ungrouped-imports

from xbmcaddon import Addon
from utils import from_unicode, to_unicode

try: # Python 3
from urllib.parse import quote, urlencode
from urllib.request import HTTPErrorProcessor
except ImportError: # Python 2
from urllib import urlencode
from urllib2 import quote, HTTPErrorProcessor

ADDON = Addon()
DEFAULT_CACHE_DIR = 'cache'
Expand Down Expand Up @@ -138,7 +132,7 @@ def addon_path():

def translate_path(path):
"""Converts a Kodi special:// path to the corresponding OS-specific path"""
return to_unicode(translatePath(from_unicode(path)))
return translatePath(path)


def addon_profile():
Expand All @@ -158,7 +152,7 @@ def show_listing(list_items, category=None, sort='unsorted', ascending=True, con
from addon import plugin

set_property('container.url', 'plugin://' + addon_id() + plugin.path)
xbmcplugin.setPluginFanart(handle=plugin.handle, image=from_unicode(addon_fanart()))
xbmcplugin.setPluginFanart(handle=plugin.handle, image=addon_fanart())

usemenucaching = get_setting_bool('usemenucaching', default=True)
if cache is None:
Expand Down Expand Up @@ -276,10 +270,7 @@ def show_listing(list_items, category=None, sort='unsorted', ascending=True, con

def play(stream, video=None):
"""Create a virtual directory listing to play its only item"""
try: # Python 3
from urllib.parse import unquote
except ImportError: # Python 2
from urllib2 import unquote
from urllib.parse import unquote

from xbmcgui import ListItem
from addon import plugin
Expand Down Expand Up @@ -353,7 +344,7 @@ def get_search_string(search_string=None):
keyboard = xbmc.Keyboard(search_string, localize(30134))
keyboard.doModal()
if keyboard.isConfirmed():
search_string = to_unicode(keyboard.getText())
search_string = keyboard.getText()
return search_string


Expand Down Expand Up @@ -464,10 +455,6 @@ def localize_date(date, strftime):
elif '%b' in strftime:
strftime = strftime.replace('%b', MONTH_SHORT[date.strftime('%m')])

# %e isn't supported on Python 2.7 on Windows
if '%e' in strftime:
strftime = strftime.replace('%e', date.strftime('%d').lstrip('0'))

return date.strftime(strftime)


Expand All @@ -487,7 +474,7 @@ def localize_from_data(name, data):
def get_setting(key, default=None):
"""Get an add-on setting as string"""
try:
value = to_unicode(ADDON.getSetting(key))
value = ADDON.getSetting(key)
except RuntimeError: # Occurs when the add-on is disabled
return default
if value == '' and default is not None:
Expand Down Expand Up @@ -535,7 +522,7 @@ def get_setting_float(key, default=None):

def set_setting(key, value):
"""Set an add-on setting"""
return ADDON.setSetting(key, from_unicode(str(value)))
return ADDON.setSetting(key, str(value))


def set_setting_bool(key, value):
Expand Down Expand Up @@ -608,7 +595,7 @@ def get_advanced_setting_int(key, default=0):
def get_property(key, default=None, window_id=10000):
"""Get a Window property"""
from xbmcgui import Window
value = to_unicode(Window(window_id).getProperty(key))
value = Window(window_id).getProperty(key)
if value == '' and default is not None:
return default
return value
Expand All @@ -617,7 +604,7 @@ def get_property(key, default=None, window_id=10000):
def set_property(key, value, window_id=10000):
"""Set a Window property"""
from xbmcgui import Window
return Window(window_id).setProperty(key, from_unicode(value))
return Window(window_id).setProperty(key, value)


def clear_property(key, window_id=10000):
Expand Down Expand Up @@ -813,7 +800,7 @@ def get_cache_dir(cache_dir=DEFAULT_CACHE_DIR):

def get_addon_info(key):
"""Return addon information"""
return to_unicode(ADDON.getAddonInfo(key))
return ADDON.getAddonInfo(key)


def listdir(path):
Expand Down Expand Up @@ -975,7 +962,7 @@ def log(level=1, message='', **kwargs):
from string import Formatter
message = Formatter().vformat(message, (), SafeDict(**kwargs))
message = '[{addon}] {message}'.format(addon=addon_id(), message=message)
xbmc.log(from_unicode(message), level % 3 if debug_logging else 2)
xbmc.log(message, level % 3 if debug_logging else 2)


def log_access(argv):
Expand All @@ -989,7 +976,7 @@ def log_error(message, **kwargs):
from string import Formatter
message = Formatter().vformat(message, (), SafeDict(**kwargs))
message = '[{addon}] {message}'.format(addon=addon_id(), message=message)
xbmc.log(from_unicode(message), 4)
xbmc.log(message, 4)


def jsonrpc(*args, **kwargs):
Expand Down Expand Up @@ -1127,12 +1114,9 @@ def ttl(kind='direct'):

def open_url(url, data=None, headers=None, method=None, cookiejar=None, follow_redirects=True, raise_errors=None):
"""Return a urllib http response"""
try: # Python 3
from urllib.error import HTTPError, URLError
from urllib.parse import unquote
from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler, Request
except ImportError: # Python 2
from urllib2 import build_opener, HTTPError, HTTPCookieProcessor, ProxyHandler, Request, URLError, unquote
from urllib.error import HTTPError, URLError
from urllib.parse import unquote
from urllib.request import build_opener, HTTPCookieProcessor, ProxyHandler, Request

opener_args = []
if not follow_redirects:
Expand All @@ -1152,7 +1136,7 @@ def open_url(url, data=None, headers=None, method=None, cookiejar=None, follow_r
log(2, 'URL post: {url}', url=unquote(url))
# Make sure we don't log the password
debug_data = data
if 'password' in to_unicode(debug_data):
if 'password' in debug_data.decode('utf-8'):
debug_data = '**redacted**'
log(2, 'URL post data: {data}', data=debug_data)
else:
Expand All @@ -1168,10 +1152,7 @@ def open_url(url, data=None, headers=None, method=None, cookiejar=None, follow_r
except HTTPError as exc:
if isinstance(raise_errors, list) and 401 in raise_errors or raise_errors == 'all':
raise
if hasattr(req, 'selector'): # Python 3.4+
url_length = len(req.selector)
else: # Python 2.7
url_length = len(req.get_selector())
url_length = len(req.selector)
if exc.code == 400 and 7600 <= url_length <= 8192:
ok_dialog(heading='HTTP Error 400', message=localize(30967))
log_error('HTTP Error 400: Probably exceeded maximum url length: '
Expand Down Expand Up @@ -1221,7 +1202,7 @@ def get_json_data(response, fail=None):
from json import load, loads
try:
if (3, 0, 0) <= version_info < (3, 6, 0): # the JSON object must be str, not 'bytes'
return loads(to_unicode(response.read()))
return loads(response.read().decode('utf-8'))
return load(response)
except TypeError as exc: # 'NoneType' object is not callable
log_error('JSON TypeError: {exc}', exc=exc)
Expand Down
Loading