Skip to content

Commit 5faf4c9

Browse files
committed
1.5.1
1 parent 72dfa3d commit 5faf4c9

11 files changed

Lines changed: 733 additions & 71 deletions

File tree

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ EPG lze pak stáhnout z http://<adresa nebo jméno serveru>:<port (defaultně 80
3737
Na http://<adresa nebo jméno serveru>:<port (defaultně 8082)>, např. http://127.0.0.1:8082 je možné stiskem tlačítka vynutit načtení kanálů nebo vytvotvoření nové sessiony.
3838

3939
<b><u>Změny</u></b>
40+
v1.5.1 (18.4.2026)
41+
- zpětné přehrávání v build-in přehrávači (od sedin2)
42+
- basic autentizace (od sedin2)
43+
- oprava spouštění streamu některých kanálů
44+
- přetáčení u live streamů
45+
4046
v1.5.0 (11.4.2026)
4147
- nová webová stránka (od sedlin2)
4248

@@ -48,6 +54,3 @@ v1.4.4 (7.4.2026)
4854

4955
v1.4.3 (1.4.2026)
5056
- oprava generování EPG
51-
52-
v1.4.2 (1.4.2026)
53-
- změna verze API

addon.xml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<addon id="script.oneplay.server" name="Oneplay Server" provider-name="waladir" version="1.5.0">
1+
<addon id="script.oneplay.server" name="Oneplay Server" provider-name="waladir" version="1.5.1">
22
<requires>
33
<import addon="xbmc.python" version="3.0.0"/>
44
<import addon="script.module.bottle"/>
@@ -15,6 +15,12 @@ Playlist: http://&lt;server&gt;:&lt;port&gt;/playlist
1515
<platform>all</platform>
1616
<source>https://github.com/waladir/script.oneplay.server</source>
1717
<news>
18+
v1.5.1 (18.4.2026)
19+
- zpětné přehrávání v build-in přehrávači (od sedin2)
20+
- basic autentizace (od sedin2)
21+
- oprava spouštění streamu některých kanálů
22+
- přetáčení u live streamů
23+
1824
v1.5.0 (11.4.2026)
1925
- nová webová stránka (od sedin2)
2026

@@ -26,9 +32,6 @@ v1.4.4 (7.4.2026)
2632

2733
v1.4.3 (1.4.2026)
2834
- oprava generování EPG
29-
30-
v1.4.2 (1.4.2026)
31-
- změna verze API
3235
</news>
3336
<assets>
3437
<icon>icon.png</icon>

changelog.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
v1.5.1 (18.4.2026)
2+
- zpětné přehrávání v build-in přehrávači (od sedin2)
3+
- basic autentizace (od sedin2)
4+
- oprava spouštění streamu některých kanálů
5+
- přetáčení u live streamů
6+
17
v1.5.0 (11.4.2026)
28
- nová webová stránka (od sedin2)
39

@@ -9,7 +15,3 @@ v1.4.4 (7.4.2026)
915

1016
v1.4.3 (1.4.2026)
1117
- oprava generování EPG
12-
13-
v1.4.2 (1.4.2026)
14-
- změna verze API
15-

config.txt.sample

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@
1414
"pin":"4321",
1515
"profile_pin":"4321",
1616
"debug":0,
17-
"cesta_ffmpeg":"/usr/bin/ffmpeg"
17+
"cesta_ffmpeg":"/usr/bin/ffmpeg",
18+
"auth_user":"",
19+
"auth_pass":""
1820
}

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,7 @@ services:
1919
PROFILE_PIN: 4321
2020
DEBUG: 0
2121
CESTA_FFMPEG: /usr/bin/ffmpeg
22+
AUTH_USER:
23+
AUTH_PASS:
24+
2225

resources/lib/epg.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,34 @@ def get_day_epg(from_ts, to_ts):
9393
epg.update({channel['channelId'] + str(startts) : epg_item})
9494
return epg
9595

96+
def get_live_epg():
97+
channels = load_channels()
98+
current_ts = int(time.time())
99+
epg = get_day_epg(current_ts-2*60*60, current_ts + 60*60)
100+
channel_epg = {}
101+
for channel_id in channels.keys():
102+
channel_epg.update({channel_id : {'now' : None, 'next' : None}})
103+
for epg_item in sorted(epg.values(), key = lambda item: item['startts']):
104+
channel_id = epg_item['channel_id']
105+
if channel_id not in channel_epg:
106+
continue
107+
if epg_item['startts'] <= current_ts and epg_item['endts'] > current_ts:
108+
if channel_epg[channel_id]['now'] is None:
109+
channel_epg[channel_id]['now'] = {
110+
'title' : epg_item['title'],
111+
'time' : datetime.fromtimestamp(epg_item['startts']).strftime('%H:%M') + ' - ' + datetime.fromtimestamp(epg_item['endts']).strftime('%H:%M'),
112+
'startts' : epg_item['startts'],
113+
'endts' : epg_item['endts'],
114+
'description' : epg_item.get('description', ''),
115+
'cover' : epg_item.get('cover', '')
116+
}
117+
elif epg_item['startts'] > current_ts and channel_epg[channel_id]['next'] is None:
118+
channel_epg[channel_id]['next'] = {
119+
'title' : epg_item['title'],
120+
'time' : datetime.fromtimestamp(epg_item['startts']).strftime('%H:%M') + ' - ' + datetime.fromtimestamp(epg_item['endts']).strftime('%H:%M')
121+
}
122+
return channel_epg
123+
96124
def get_epg():
97125
tz_offset = int(datetime.now(timezone.utc).astimezone().utcoffset().total_seconds() / 3600)
98126
channels = load_channels()

resources/lib/stream.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,13 @@ def get_live(id):
4343
pin = get_config_value('pin')
4444
else:
4545
pin = '1234'
46-
post = {"authorization":[{"schema":"PinRequestAuthorization","pin":pin,"type":"parental"}],"payload":{"criteria":{"schema":"ContentCriteria","contentId":"channel." + id},"startMode":"live"},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
46+
post = {"authorization":[{"schema":"PinRequestAuthorization","pin":pin,"type":"parental"}],"payload":{"criteria":{"schema":"ContentCriteria","contentId":"channel." + id},"startMode":"start"},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
4747
else:
48-
post = {"payload":{"criteria":{"schema":"ContentCriteria","contentId":"channel." + id},"startMode":"live"},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
48+
post = {"payload":{"criteria":{"schema":"ContentCriteria","contentId":"channel." + id},"startMode":"start"},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
4949
data = call_api(url = 'https://http.cms.jyxo.cz/api/' + api_version + '/content.play', data = post, token = token)
50+
if 'err' in data:
51+
post['payload']['startMode'] = 'live'
52+
data = call_api(url = 'https://http.cms.jyxo.cz/api/' + api_version + '/content.play', data = post, token = token)
5053
if md == True and 'liveControl' in data['playerControl'] and 'mosaic' in data['playerControl']['liveControl']:
5154
stream_number = 1
5255
for md_item in data['playerControl']['liveControl']['mosaic']['items']:
@@ -57,7 +60,7 @@ def get_live(id):
5760
elif 'contentId' in md_item['play']['params']['payload']:
5861
md_id = md_item['play']['params']['payload']['contentId']
5962
if md_id is not None:
60-
post = {"payload":{"criteria":{"schema":"MDPlaybackCriteria","contentId":md_id,"position":0},"startMode":"live"},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
63+
post = {"payload":{"criteria":{"schema":"MDPlaybackCriteria","contentId":md_id,"position":0},"startMode":"start"},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
6164
data = call_api(url = 'https://http.cms.jyxo.cz/api/' + api_version + '/content.play', data = post, token = token)
6265
if 'err' in data or 'media' not in data:
6366
url = 'http://sledovanietv.sk/download/noAccess-cs.m3u8'
@@ -103,7 +106,15 @@ def get_archive(channel_name, start_ts, end_ts):
103106
if md == True:
104107
post = {"payload":{"criteria":{"schema":"MDPlaybackCriteria","contentId":epg[start_ts]['id'],"position":0}},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
105108
else:
106-
post = {"payload":{'criteria': {'schema': 'ChannelPlaybackCriteria', 'channel': epg[start_ts]['payload']['deeplink']['channel'], 'time': epg[start_ts]['payload']['deeplink']['time']}},"playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
109+
payload = None
110+
data = call_api(url = 'https://http.cms.jyxo.cz/api/' + api_version + '/page.content.display', data = {'payload': epg[start_ts]['payload']}, token = token)
111+
for block in data.get('layout', {}).get('blocks', []):
112+
schema = block.get('schema')
113+
if not payload and schema == 'ContentHeaderBlock':
114+
action = block.get('mainAction', {}).get('action', {})
115+
if action.get('call') == 'content.play':
116+
payload = action.get('params', {}).get('payload')
117+
post = {"payload":payload, "playbackCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","subtitle":{"formats":["vtt"],"locations":["InstreamTrackLocation","ExternalTrackLocation"]},"liveSpecificCapabilities":{"protocols":["dash","hls"],"drm":["widevine","fairplay"],"altTransfer":"Unicast","multipleAudio":False}}}
107118
data = call_api(url = 'https://http.cms.jyxo.cz/api/' + api_version + '/content.play', data = post, token = token)
108119
url = 'http://sledovanietv.sk/download/noAccess-cs.m3u8'
109120
for asset in data['media']['stream']['assets']:
@@ -116,6 +127,3 @@ def get_archive(channel_name, start_ts, end_ts):
116127
return url
117128
else:
118129
return get_live(channel_name)
119-
120-
121-

resources/lib/utils.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def get_config_value(setting):
4242
addon = xbmcaddon.Addon()
4343
return addon.getSetting(setting)
4444
elif is_docker() == True and not os.path.exists(os.path.join(get_script_path(), 'config.txt')):
45-
defaults = {'WEBSERVER_IP' : '0.0.0.0', 'WEBSERVER_PORT' : 8082, 'EPG_DNU_ZPETNE' : 1, 'EPG_DNU_DOPREDU' : 1, 'INTERVAL_STAHOVANI_EPG' : 0, 'ODSTRANIT_HD' : 0, 'POUZIVAT_CISLA_KANALU' : 0, 'PORADI_SLUZBY' : -1, 'PIN' : '4321', 'PROFILE_PIN' : '4321', 'DEBUG' : 0, 'CESTA_FFMPEG' : '/usr/bin/ffmpeg'}
45+
defaults = {'WEBSERVER_IP' : '0.0.0.0', 'WEBSERVER_PORT' : 8082, 'EPG_DNU_ZPETNE' : 1, 'EPG_DNU_DOPREDU' : 1, 'INTERVAL_STAHOVANI_EPG' : 0, 'ODSTRANIT_HD' : 0, 'POUZIVAT_CISLA_KANALU' : 0, 'PORADI_SLUZBY' : -1, 'PIN' : '4321', 'PROFILE_PIN' : '4321', 'DEBUG' : 0, 'CESTA_FFMPEG' : '/usr/bin/ffmpeg', 'AUTH_USER' : '', 'AUTH_PASS' : ''}
4646
value = os.getenv(setting.upper())
4747
if value is None and setting.upper() in defaults:
4848
value = defaults[setting.upper()]
@@ -118,7 +118,17 @@ def get_version():
118118
xml = minidom.parse(filename)
119119
addon = xml.getElementsByTagName('addon')
120120
for element in addon:
121-
version = ' (v.' + element.attributes['version'].value + ')'
121+
version = ' (v' + element.attributes['version'].value + ')'
122122
except IOError as error:
123123
return version
124124
return version
125+
126+
def check_client_network(ip):
127+
try:
128+
server_ip = get_ip_address()
129+
client_ip = ip
130+
server_parts = server_ip.split('.')
131+
client_parts = client_ip.split('.')
132+
return server_parts[:2] == client_parts[:2] or client_ip == '127.0.0.1'
133+
except Exception:
134+
return False

0 commit comments

Comments
 (0)