Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelarnauts committed Jan 24, 2021
1 parent d79bb85 commit 358d9e2
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 49 deletions.
2 changes: 1 addition & 1 deletion resources/lib/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def disable_source(addon_id):
def install():
""" Setup IPTV Simple """
from resources.lib.modules.menu import Menu
Menu().install()
Menu().show_install()


@routing.route('/play')
Expand Down
8 changes: 4 additions & 4 deletions resources/lib/modules/contextmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@


class ContextMenu:
"""Helper class for PVR Context Menu handling"""
""" Helper class for PVR Context Menu handling (used in Kodi 18) """

def __init__(self):
"""Initialise the Context Menu Module"""
""" Initialise object """

def play(self):
""" Play from Context Menu (used in Kodi 18) """
""" Play from Context Menu """
stream = self.get_direct_uri()
if stream is None:
kodiutils.ok_dialog(message=kodiutils.localize(30706))
Expand All @@ -30,7 +30,7 @@ def play(self):

@staticmethod
def get_direct_uri():
"""Retrieve a direct URI from the selected ListItem."""
""" Retrieve a direct URI from the selected ListItem. """
# We use a clever way / ugly hack (pick your choice) to hide the direct stream in Kodi 18.
# Title [COLOR green]•[/COLOR][COLOR vod="plugin://plugin.video.example/play/whatever"][/COLOR]
label = sys.listitem.getLabel() # pylint: disable=no-member
Expand Down
56 changes: 39 additions & 17 deletions resources/lib/modules/iptvsimple.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,42 @@ class IptvSimple:
restart_required = False

def __init__(self):
"""Init"""
"""Initialise object"""

@classmethod
def _get_settings(cls):
"""Return a dictionary with the required settings."""
output_dir = kodiutils.addon_profile()
return {
'm3uPathType': '0', # Local path
'm3uPath': os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST),
'epgPathType': '0', # Local path
'epgPath': os.path.join(output_dir, IPTV_SIMPLE_EPG),
'epgCache': 'true',
'epgTimeShift': '0',
'logoPathType': '0', # Local path
'logoPath': '/',
'catchupEnabled': 'true', # Allow playback from the guide in Matrix
'allChannelsCatchupMode': '1', # Allow to specify the vod mode per channel
'catchupOnlyOnFinishedProgrammes': 'false', # Allow vod also on future programs
}

@classmethod
def check(cls):
"""Check if IPTV Simple is configured correctly."""
try:
addon = kodiutils.get_addon(IPTV_SIMPLE_ID)
except Exception as exc: # pylint: disable=broad-except
_LOGGER.warning('Could not find IPTV Simple: %s', str(exc))
return False

# Validate IPTV Simple configuration
settings = cls._get_settings()
for key, value in settings.items():
if value != addon.getSetting(key):
return False

return True

@classmethod
def setup(cls):
Expand All @@ -45,22 +80,9 @@ def setup(cls):
cls._deactivate()

# Configure IPTV Simple
output_dir = kodiutils.addon_profile()

addon.setSetting('m3uPathType', '0') # Local path
addon.setSetting('m3uPath', os.path.join(output_dir, IPTV_SIMPLE_PLAYLIST))

addon.setSetting('epgPathType', '0') # Local path
addon.setSetting('epgPath', os.path.join(output_dir, IPTV_SIMPLE_EPG))
addon.setSetting('epgCache', 'true')
addon.setSetting('epgTimeShift', '0')

addon.setSetting('logoPathType', '0') # Local path
addon.setSetting('logoPath', '/')

addon.setSetting('catchupEnabled', 'true')
addon.setSetting('allChannelsCatchupMode', '1')
addon.setSetting('catchupOnlyOnFinishedProgrammes', 'false')
settings = cls._get_settings()
for key, value in settings.items():
addon.setSetting(key, value)

# Activate IPTV Simple
cls._activate()
Expand Down
44 changes: 25 additions & 19 deletions resources/lib/modules/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ def show_mainmenu():
""" Show the main menu. """
listing = []

if not IptvSimple.check():
listing.append(TitleItem(
title=kodiutils.localize(30822),
path=kodiutils.url_for('install'),
art_dict=dict(
icon='DefaultAddonService.png',
),
))

listing.append(TitleItem(
title=kodiutils.localize(30803),
path=kodiutils.url_for('refresh'),
Expand All @@ -33,37 +42,32 @@ def show_mainmenu():
),
))

listing.append(TitleItem(
title='IPTV Manager Settings…',
path=kodiutils.url_for('show_settings'),
art_dict=dict(
icon='DefaultAddonService.png',
),
info_dict=dict(
plot='IPTV Manager Settings…',
),
))
# listing.append(TitleItem(
# title='IPTV Manager Settings…', # TODO: translate
# path=kodiutils.url_for('show_settings'),
# art_dict=dict(
# icon='DefaultAddonService.png',
# ),
# info_dict=dict(
# plot='IPTV Manager Settings…', # TODO: translate
# ),
# ))

listing.append(TitleItem(
title='Manage Sources…',
title='Manage Sources…', # TODO: translate
path=kodiutils.url_for('show_sources'),
art_dict=dict(
icon='DefaultPlaylist.png',
),
info_dict=dict(
plot='Manage Sources…',
plot='Manage Sources…', # TODO: translate
),
))

kodiutils.show_listing(listing, sort=['unsorted'])

@staticmethod
def show_settings():
""" Show the sources menu. """
kodiutils.open_settings()

@staticmethod
def install():
def show_install():
""" Setup IPTV Simple """
reply = kodiutils.yesno_dialog(message=kodiutils.localize(30700)) # Are you sure...
if reply:
Expand All @@ -72,7 +76,9 @@ def install():
else:
kodiutils.ok_dialog(message=kodiutils.localize(30702)) # The configuration of IPTV Simple has failed!

# Open settings again
@staticmethod
def show_settings():
""" Show the sources menu. """
kodiutils.open_settings()

@staticmethod
Expand Down
9 changes: 7 additions & 2 deletions resources/lib/modules/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,15 @@ def delete(self):
with open(os.path.join(kodiutils.addon_profile(), Sources.SOURCES_FILE), 'w') as fdesc:
json.dump(sources, fdesc)

def get_channels(self):
@staticmethod
def get_channels():
"""Get channel data from this source"""

# TODO
return []

def get_epg(self):
@staticmethod
def get_epg():
"""Get epg data from this source"""
# TODO
return []
11 changes: 6 additions & 5 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from __future__ import absolute_import, division, print_function, unicode_literals

import os
import sys
import time
import unittest
from xml.etree import ElementTree as etree
Expand All @@ -15,14 +16,15 @@
from xbmcgui import ListItem

from resources.lib import kodiutils
from resources.lib.modules.contextmenu import ContextMenu
from resources.lib.modules.sources import Sources


class IntegrationTest(unittest.TestCase):
"""Integration Tests"""

def test_refresh(self):
"""Test the refreshing of data"""
"""Test the refreshing of data."""
m3u_path = 'tests/home/userdata/addon_data/service.iptv.manager/playlist.m3u8'
epg_path = 'tests/home/userdata/addon_data/service.iptv.manager/epg.xml'

Expand Down Expand Up @@ -52,14 +54,13 @@ def test_refresh(self):
self.assertIsNotNone(xml.find('./channel[@id="channel1.com"]'))
self.assertIsNotNone(xml.find('./channel[@id="één.be"]'))

# Now, try playing something from the Guide
import sys
def test_play_from_guide(self):
"""Play something from the guide."""
sys.listitem = ListItem(label='Example Show [COLOR green]•[/COLOR][COLOR vod="plugin://plugin.video.example/play/something"][/COLOR]',
path='pvr://guide/0006/2020-05-23 11:35:00.epg')

# Try to play it
from resources.lib.functions import play_from_contextmenu
play_from_contextmenu()
ContextMenu().play()

# Check that something is playing
player = xbmc.Player()
Expand Down
4 changes: 3 additions & 1 deletion tests/test_iptvsimple.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ class IptvSimpleTest(unittest.TestCase):

def test_setup(self):
"""Test the setup of IPTV Simple (this will be mocked)"""
self.assertTrue(IptvSimple.setup())
self.assertFalse(IptvSimple.check()) # Configuration will be incorrect
self.assertTrue(IptvSimple.setup()) # Setup configuration
self.assertTrue(IptvSimple.check()) # Configuration will be correct

def test_restart(self):
"""Test the restart of IPTV Simple (this will be mocked)"""
Expand Down
60 changes: 60 additions & 0 deletions tests/test_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,29 @@
import unittest
from uuid import uuid4

from mock import patch

from resources.lib import kodiutils
from resources.lib.modules.sources import CustomSource, Sources

TEST_PLAYLIST = """
#EXTM3U
#EXTINF:-1 tvg-name="Test 1" tvg-id="test1.com" tvg-logo="https://example.com/test1.png" tvg-chno="1" group-title="Test IPTV Addon" catchup="vod",Test 1
plugin://plugin.video.test/play/live
"""

TEST_EPG = """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">
<tv>
<channel id="test1.com"></channel>
<programme start="20210123114255 +0100" stop="20210123121255 +0100" channel="test1.com" catchup-id="plugin://plugin.video.test/play/vod/1">
<title>Test 1</title>
<desc>Test 1 description</desc>
</programme>
</tv>
"""


class SourcesTest(unittest.TestCase):

Expand Down Expand Up @@ -42,6 +62,46 @@ def test_create(self):
self.assertIn(key, sources.keys())
self.assertEqual(sources.get(key).enabled, True)

def test_fetch(self):

def mocked_requests_get(*args, **kwargs):
class MockResponse:
def __init__(self, json_data, status_code):
self.json_data = json_data
self.status_code = status_code

def json(self):
return self.json_data

if args[0].endsWith('m3u'):
return MockResponse(TEST_PLAYLIST, 200)
elif args[0].endsWith('xml'):
return MockResponse(TEST_EPG, 200)

return MockResponse(None, 404)

with patch('requests.get', side_effect=mocked_requests_get):
source = CustomSource(uuid=str(uuid4()),
name='Test Source',
enabled=False,
playlist_uri='https://example.com/playlist.m3u',
playlist_type=CustomSource.TYPE_URL,
epg_uri='https://example.com/playlist.m3u',
epg_type=CustomSource.TYPE_URL,
)

channels = source.get_channels()

print(channels)


epg = source.get_epg()

print(epg)

exit()



if __name__ == '__main__':
unittest.main()

0 comments on commit 358d9e2

Please sign in to comment.