Files
DemonEditor/app/eparser/iptv.py

130 lines
4.9 KiB
Python
Raw Normal View History

2018-03-12 22:47:43 +03:00
""" Module for IPTV and streams support """
2019-04-18 21:43:35 +03:00
import re
2018-03-12 22:47:43 +03:00
from enum import Enum
2020-06-13 01:01:20 +03:00
from urllib.parse import unquote, quote
2018-03-12 22:47:43 +03:00
2021-01-31 16:27:35 +03:00
from app.commons import log
from app.eparser.ecommons import BqServiceType, Service
2019-12-22 20:42:29 +03:00
from app.settings import SettingsType
from app.ui.uicommons import IPTV_ICON
2017-12-08 18:32:28 +03:00
2018-02-12 13:34:00 +03:00
# url, description, urlkey, account, usrname, psw, s_type, iconsrc, iconsrc_b, group
NEUTRINO_FAV_ID_FORMAT = "{}::{}::{}::{}::{}::{}::{}::{}::{}::{}"
2018-04-10 16:03:36 +03:00
ENIGMA2_FAV_ID_FORMAT = " {}:0:{}:{:X}:{:X}:{:X}:{:X}:0:0:0:{}:{}\n#DESCRIPTION: {}\n"
2018-11-16 23:08:40 +03:00
MARKER_FORMAT = " 1:64:{}:0:0:0:0:0:0:0::{}\n#DESCRIPTION {}\n"
2018-03-12 22:47:43 +03:00
class StreamType(Enum):
DVB_TS = "1"
NONE_TS = "4097"
2019-04-14 00:03:52 +03:00
NONE_REC_1 = "5001"
NONE_REC_2 = "5002"
2020-06-09 18:38:18 +03:00
E_SERVICE_URI = "8193"
2021-01-11 12:30:44 +03:00
E_SERVICE_HLS = "8739"
2017-12-08 18:32:28 +03:00
2018-02-12 13:34:00 +03:00
2021-01-31 16:27:35 +03:00
def parse_m3u(path, s_type, detect_encoding=True, params=None):
with open(path, "rb") as file:
data = file.read()
encoding = "utf-8"
if detect_encoding:
try:
import chardet
except ModuleNotFoundError:
pass
else:
enc = chardet.detect(data)
encoding = enc.get("encoding", "utf-8")
2018-01-31 00:13:42 +03:00
aggr = [None] * 10
2021-01-31 16:27:35 +03:00
s_aggr = aggr[: -3]
2018-11-16 23:08:40 +03:00
services = []
groups = set()
2021-01-31 16:27:35 +03:00
marker_counter = 1
sid_counter = 1
2017-12-08 18:32:28 +03:00
name = None
2021-01-31 16:27:35 +03:00
picon = None
p_id = "1_0_1_0_0_0_0_0_0_0.png"
st = BqServiceType.IPTV.name
params = params or [0, 0, 0, 0]
2019-12-22 20:42:29 +03:00
for line in str(data, encoding=encoding, errors="ignore").splitlines():
2017-12-08 18:32:28 +03:00
if line.startswith("#EXTINF"):
2021-01-31 16:27:35 +03:00
inf, sep, line = line.partition(" ")
if not line:
line = inf
line, sep, name = line.rpartition(",")
data = re.split('"', line)
size = len(data)
if size < 3:
continue
d = {data[i].lower().strip(" ="): data[i + 1] for i in range(0, len(data) - 1, 2)}
picon = d.get("tvg-logo", None)
grp_name = d.get("group-title", None)
if grp_name not in groups:
groups.add(grp_name)
fav_id = MARKER_FORMAT.format(marker_counter, grp_name, grp_name)
marker_counter += 1
mr = Service(None, None, None, grp_name, *aggr[0:3], BqServiceType.MARKER.name, *aggr, fav_id, None)
services.append(mr)
2019-12-22 20:42:29 +03:00
elif line.startswith("#EXTGRP") and s_type is SettingsType.ENIGMA_2:
2018-11-16 23:08:40 +03:00
grp_name = line.strip("#EXTGRP:").strip()
if grp_name not in groups:
groups.add(grp_name)
2021-01-31 16:27:35 +03:00
fav_id = MARKER_FORMAT.format(marker_counter, grp_name, grp_name)
marker_counter += 1
2018-11-16 23:08:40 +03:00
mr = Service(None, None, None, grp_name, *aggr[0:3], BqServiceType.MARKER.name, *aggr, fav_id, None)
services.append(mr)
2018-11-16 22:35:47 +03:00
elif not line.startswith("#"):
2019-01-27 23:59:06 +03:00
url = line.strip()
2021-01-31 16:27:35 +03:00
params[0] = sid_counter
sid_counter += 1
fav_id = get_fav_id(url, name, s_type, params)
if all((name, url, fav_id)):
srv = Service(None, None, IPTV_ICON, name, *aggr[0:3], st, picon, p_id, *s_aggr, url, fav_id, None)
2019-01-27 23:59:06 +03:00
services.append(srv)
2021-01-31 16:27:35 +03:00
else:
log("*.m3u* parse error ['{}']: name[{}], url[{}], fav id[{}]".format(path, name, url, fav_id))
2017-12-08 18:32:28 +03:00
2018-11-16 23:08:40 +03:00
return services
2017-12-08 18:32:28 +03:00
2019-12-22 20:42:29 +03:00
def export_to_m3u(path, bouquet, s_type):
pattern = re.compile(".*:(http.*):.*") if s_type is SettingsType.ENIGMA_2 else re.compile("(http.*?)::::.*")
2019-04-18 21:43:35 +03:00
lines = ["#EXTM3U\n"]
2019-05-01 17:21:51 +03:00
current_grp = None
2019-04-18 21:43:35 +03:00
for s in bouquet.services:
2019-05-01 17:21:51 +03:00
s_type = s.type
if s_type is BqServiceType.IPTV:
2019-04-18 21:43:35 +03:00
res = re.match(pattern, s.data)
if not res:
continue
data = res.group(1)
2019-05-01 17:21:51 +03:00
lines.append("#EXTINF:-1,{}\n".format(s.name))
if current_grp:
lines.append(current_grp)
2020-06-09 18:38:18 +03:00
lines.append("{}\n".format(unquote(data.strip())))
2019-05-01 17:21:51 +03:00
elif s_type is BqServiceType.MARKER:
current_grp = "#EXTGRP:{}\n".format(s.name)
2019-04-18 21:43:35 +03:00
with open(path + "{}.m3u".format(bouquet.name), "w", encoding="utf-8") as file:
file.writelines(lines)
2021-01-31 16:27:35 +03:00
def get_fav_id(url, service_name, settings_type, params=None, stream_type=None, s_type=1):
2019-06-23 23:25:03 +03:00
""" Returns fav id depending on the profile. """
2021-01-31 16:27:35 +03:00
if settings_type is SettingsType.ENIGMA_2:
stream_type = stream_type or StreamType.NONE_TS.value
params = params or (0, 0, 0, 0)
return ENIGMA2_FAV_ID_FORMAT.format(stream_type, s_type, *params, quote(url), service_name, service_name, None)
elif settings_type is SettingsType.NEUTRINO_MP:
2019-06-23 23:25:03 +03:00
return NEUTRINO_FAV_ID_FORMAT.format(url, "", 0, None, None, None, None, "", "", 1)
2017-12-08 18:32:28 +03:00
if __name__ == "__main__":
pass