opkg update opkg install wget ca-certificates mc python3 lighttpd-mod-cgi
mkdir -p /opt/etc/ttv wget --no-check-certificate -O /opt/etc/ttv/ttv.py https://raw.githubusercontent.com/Kyrie1965/ttv/master/ttv.py wget --no-check-certificate -O /opt/share/www/playlist.cgi https://raw.githubusercontent.com/Kyrie1965/ttv/master/playlist.cgi chmod +x /opt/share/www/playlist.cgi
PLAYLIST_LOAD_URL = "http://91.92.66.82/trash/ttv-list/ttv.all.tag.player.m3u" TEMPLATE_SAVE_PATH = "/opt/etc/ttv/template.txt" FAVORITES_LOAD_PATH = "/opt/etc/ttv/favorites.txt" PLAYLIST_SAVE_PATH = "/opt/etc/ttv/playlist.m3u" LOGOS_URL = "https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/{}" #LOGOS_URL = "{}" STREAM_URL = "http://127.0.0.1:6878/ace/getstream?id={}&.mp4" #STREAM_URL = "acestream://{}" EPG_LINKS = "https://teleguide.info/download/new3/xmltv.xml.gz" #EPG_LINKS = "https://teleguide.info/download/new3/xmltv.xml.gz,http://programtv.ru/xmltv.xml.gz,http://api.torrent-tv.ru/ttv.xmltv.xml.gz" import re import urllib.request import os from operator import itemgetter as i from functools import cmp_to_key from urllib.parse import urlencode def cmp(a, b): return (a > b) - (a < b) def multikeysort(items, columns): comparers = [ ((i(col[1:].strip()), -1) if col.startswith('-') else (i(col.strip()), 1)) for col in columns ] def comparer(left, right): comparer_iter = ( cmp(fn(left), fn(right)) * mult for fn, mult in comparers ) return next((result for result in comparer_iter if result), 0) return sorted(items, key=cmp_to_key(comparer)) def loadChannels(content): lines = content.splitlines() returnChannels = {} pattern = re.compile("group-title=\"(.*?)\"") channelName = "" channelGroup = "" channelStreamID = "" waitURI = False for line in lines: if line.startswith("acestream"): if waitURI: channelStreamID = line[12:] HD = False if "HD" in channelName: HD = True tmpDict = {"name": channelName, "group": channelGroup, "stream": channelStreamID, "hd": HD} returnChannels[channelName] = tmpDict waitURI = False elif line.startswith("#EXTINF"): x = line.split("\",") if (len(x) != 2): continue channelName = x[1] match = pattern.search(x[0]) if match: channelGroup = match.group(1) else: channelGroup = "Общие" waitURI = True return returnChannels def saveTemplate(content, channels, path): lines = content.splitlines() pattern = re.compile("group-title=\"(.*?)\"") waitURI = False channelName = "" channelReplace = "" channelNewName = "" channelEPG = "" channelGroup = "" channelStreamID = "" groupDict = {} currentGroup = 1 template="" for line in lines: if line.startswith("acestream"): if waitURI: channelStreamID = line[12:] template += channelName template += "/" template += channelReplace template += "/" template += channelNewName template += "/" template += channelEPG template += "/" template += channelName + ".png" template += "/" template += channelGroup template += "\n" waitURI = False elif line.startswith("#EXTINF"): x = line.split("\",") if (len(x) != 2): continue channelName = x[1] channelNewName = x[1] channelEPG = x[1] if (channels.get(channelName + " HD") != None): channelReplace = channelName + " HD" else: channelReplace = "-" match = pattern.search(x[0]) if match: channelGroup = match.group(1) if (groupDict.get(channelGroup)): channelGroup = groupDict.get(channelGroup) else: newGroupName = "{:02d}_{}".format(currentGroup, channelGroup) currentGroup += 1 groupDict[channelGroup] = newGroupName channelGroup = newGroupName else: channelGroup = "00_Unsigned" waitURI = True file = open(path,'w', encoding='utf-8') file.write(template) file.close() return def loadFavorites(content): returnChannels = {} lines = content.splitlines() for line in lines: parts = line.split('/') if len(parts) == 6: tmpDict = {"name": parts[0], "replace": parts[1], "newName": parts[2], "EPG": parts[3], "logo": parts[4], "group": parts[5]} returnChannels[parts[0]] = tmpDict elif len(parts) == 5: #совместимость с предыдущим вариантом tmpDict = {"name": parts[0], "replace": parts[1], "newName": parts[2], "EPG": parts[3], "group": parts[4], "logo": parts[0] + ".png"} returnChannels[parts[0]] = tmpDict return returnChannels def savePlaylist(channels, favorites, path): returnChannels = [] currentChannels = set() for key, chDict in favorites.items(): if chDict["replace"] != "-": if favorites.get(chDict["replace"]) != None and channels.get(chDict["replace"]) != None: currentChannels.add(chDict["replace"]) elif channels.get(chDict["name"]) != None: currentChannels.add(chDict["name"]) elif channels.get(chDict["name"]) != None: currentChannels.add(chDict["name"]) for ch in currentChannels: chFromFavorites = favorites.get(ch) chFromChannels = channels.get(ch) tmpDict = {"name": chFromFavorites.get("newName"), "oldName": chFromFavorites.get("name"), "EPG": chFromFavorites.get("EPG"), "group": chFromFavorites.get("group"), "logo": chFromFavorites.get("logo"), "stream": chFromChannels.get("stream"), "hd": chFromChannels.get("hd")} returnChannels.append(tmpDict) result = multikeysort(returnChannels, ['group', '-hd', 'name']) template="" template += "#EXTM3U url-tvg=" template += "\"" template += EPG_LINKS template += "\"" template += "\n" for n in result: group = n.get("group") if group.find("_", 2, 3) != -1: group = group[3:] template += "#EXTINF:-1 tvg-name=\"{}\" tvg-logo=\"{}\" group-title=\"{}\" ,{}".format(n.get("EPG"), LOGOS_URL.format(urllib.parse.quote(n.get("logo"))), group, n.get("name")) template += "\n" template += STREAM_URL.format(n.get("stream")) template += "\n" file = open(path,'w', encoding='utf-8') file.write(template) file.close() return result response = urllib.request.urlopen(PLAYLIST_LOAD_URL) content = response.read().decode("utf-8") channels = loadChannels(content) if channels == None or (len(channels.keys()) == 0): exit() saveTemplate(content, channels, TEMPLATE_SAVE_PATH) exists = os.path.isfile(FAVORITES_LOAD_PATH) if exists: file = open(FAVORITES_LOAD_PATH,'r', encoding='utf-8') content = file.read() favorites = loadFavorites(content) savePlaylist(channels, favorites, PLAYLIST_SAVE_PATH)
#!/bin/sh PATH=/opt/sbin:/opt/bin:/opt/usr/sbin:/opt/usr/bin:/usr/sbin:/usr/bin:/sbin:/bin python3 /opt/etc/ttv/ttv.py echo "Content-Type: text/plain; charset=UTF-8" echo "" echo "$(cat /opt/etc/ttv/playlist.m3u)"
mcedit /opt/etc/lighttpd/lighttpd.conf
server.port = 81
mcedit /opt/etc/lighttpd/conf.d/30-cgi.conf
".cgi" => "/bin/sh"
/opt/etc/init.d/S80lighttpd start
python3 /opt/etc/ttv/ttv.py
Amedia Premium/Amedia Premium HD/Amedia Premium/Amedia Premium/Amedia Premium.png/11_Фильмы и сериалы Amedia Premium HD/-/Amedia Premium HD/Amedia Premium HD/Amedia Premium HD.png/11_Фильмы и сериалы Дождь/Дождь HD/Дождь/Дождь/Дождь.png/12_Общие Дождь HD/-/Дождь HD/Дождь HD/Дождь HD.png/12_Общие Viasat History/-/Viasat History/Viasat History/Viasat History.png/01_Познавательные Discovery Channel/Discovery Channel HD/Discovery Channel/Discovery Channel/Discovery Channel.png/01_Познавательные Discovery Channel HD/-/Discovery Channel HD/Discovery Channel HD/Discovery Channel HD.png/01_Познавательные Discovery Science/Discovery Science HD/Discovery Science/Discovery Science/Discovery Science.png/01_Познавательные Discovery Science HD/-/Discovery Science HD/Discovery Science HD/Discovery Science HD.png/01_Познавательные Amedia Hit/Amedia Hit HD/Amedia Hit/Amedia Hit/Amedia Hit.png/11_Фильмы и сериалы Amedia Hit HD/-/Amedia Hit HD/Amedia Hit HD/Amedia Hit HD.png/11_Фильмы и сериалы Матч ТВ/Матч ТВ HD/Матч!/Матч!/Матч ТВ.png/03_Спортивные Матч ТВ HD/-/Матч! HD/Матч!/Матч ТВ HD.png/03_Спортивные Eurosport 1/Eurosport 1 HD/Eurosport 1/Eurosport 1/Eurosport 1.png/03_Спортивные Eurosport 1 HD/-/Eurosport 1 HD/Eurosport 1 HD/Eurosport 1 HD.png/03_Спортивные Paramount Comedy HD (Россия)/-/Paramount Comedy HD/Paramount Comedy HD (Россия)/Paramount Comedy HD (Россия).png/11_Фильмы и сериалы Матч! Футбол 1/Матч! Футбол 1 HD/Матч! Футбол 1/Матч! Футбол 1/Матч! Футбол 1.png/03_Спортивные Матч! Футбол 1 HD/-/Матч! Футбол 1 HD/Матч! Футбол 1 HD/Матч! Футбол 1 HD.png/03_Спортивные Россия 1/Россия HD/Россия 1/Россия 1/Россия 1.png/13_Зомби-пропаганда Россия HD/-/Россия HD/Россия HD/Россия HD.png/13_Зомби-пропаганда
#EXTM3U url-tvg="https://teleguide.info/download/new3/xmltv.xml.gz"
#EXTINF:-1 tvg-name="Discovery Channel HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Discovery%20Channel%20HD.png" group-title="Познавательные" ,Discovery Channel HD
http://127.0.0.1:6878/ace/getstream?id=da1232435c2d54cebdd114fb8e9632b4d8a2977e&.mp4
#EXTINF:-1 tvg-name="Discovery Science HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Discovery%20Science%20HD.png" group-title="Познавательные" ,Discovery Science HD
http://127.0.0.1:6878/ace/getstream?id=03fb28986da9168dd56ec6891253bcc496c13eb5&.mp4
#EXTINF:-1 tvg-name="Viasat History" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Viasat%20History.png" group-title="Познавательные" ,Viasat History
http://127.0.0.1:6878/ace/getstream?id=fca01ece6298f5ada1e26b0ab0236fa213312bea&.mp4
#EXTINF:-1 tvg-name="Eurosport 1 HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Eurosport%201%20HD.png" group-title="Спортивные" ,Eurosport 1 HD
http://127.0.0.1:6878/ace/getstream?id=001be3c7f3a83322c57627d2ce12c563f37c7ab9&.mp4
#EXTINF:-1 tvg-name="Матч!" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/%D0%9C%D0%B0%D1%82%D1%87%20%D0%A2%D0%92%20HD.png" group-title="Спортивные" ,Матч! HD
http://127.0.0.1:6878/ace/getstream?id=8f33256291e7136bfdb1b0ab5a84717dff8e9a31&.mp4
#EXTINF:-1 tvg-name="Матч! Футбол 1 HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/%D0%9C%D0%B0%D1%82%D1%87%21%20%D0%A4%D1%83%D1%82%D0%B1%D0%BE%D0%BB%201%20HD.png" group-title="Спортивные" ,Матч! Футбол 1 HD
http://127.0.0.1:6878/ace/getstream?id=63dea7ffffdfeadca5a7cb50fd66bd1433de8d19&.mp4
#EXTINF:-1 tvg-name="Amedia Hit HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Amedia%20Hit%20HD.png" group-title="Фильмы и сериалы" ,Amedia Hit HD
http://127.0.0.1:6878/ace/getstream?id=3f6a960f2051914b07b9ffc931b2e0b1b1d6a968&.mp4
#EXTINF:-1 tvg-name="Amedia Premium HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Amedia%20Premium%20HD.png" group-title="Фильмы и сериалы" ,Amedia Premium HD
http://127.0.0.1:6878/ace/getstream?id=f78faf23a6339f4a13412178b4675c931d5fba08&.mp4
#EXTINF:-1 tvg-name="Paramount Comedy HD (Россия)" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/Paramount%20Comedy%20HD%20%28%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F%29.png" group-title="Фильмы и сериалы" ,Paramount Comedy HD
http://127.0.0.1:6878/ace/getstream?id=a9023adab9228b8aa7f1b508b553140b69cecd80&.mp4
#EXTINF:-1 tvg-name="Дождь" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/%D0%94%D0%BE%D0%B6%D0%B4%D1%8C.png" group-title="Общие" ,Дождь
http://127.0.0.1:6878/ace/getstream?id=1bd74f323ca46413efa97ad77d1579e00eb0b79f&.mp4
#EXTINF:-1 tvg-name="Россия HD" tvg-logo="https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D1%8F%20HD.png" group-title="Зомби-пропаганда" ,Россия HD
http://127.0.0.1:6878/ace/getstream?id=7d5f9b63186bc7bbb9475f6a48fb8b2152f247c8&.mp4
Познавательные: Discovery Channel HD Discovery Science HD Viasat History Спортивные: Eurosport 1 HD Матч! HD Матч! Футбол 1 HD Фильмы и сериалы: Amedia Hit HD Amedia Premium HD Paramount Comedy HD Общие: Дождь Зомби-пропаганда: Россия HD
mcedit /opt/etc/ttv/ttv.py
PLAYLIST_LOAD_URL = "http://91.92.66.82/trash/ttv-list/ttv.all.tag.player.m3u"
TEMPLATE_SAVE_PATH = "/opt/etc/ttv/template.txt"
FAVORITES_LOAD_PATH = "/opt/etc/ttv/favorites.txt"
PLAYLIST_SAVE_PATH = "/opt/etc/ttv/playlist.m3u"
LOGOS_URL = "https://raw.githubusercontent.com/Kyrie1965/ttv/master/logos/{}"
#LOGOS_URL = "{}"
STREAM_URL = "http://127.0.0.1:6878/ace/getstream?id={}&.mp4"
#STREAM_URL = "acestream://{}"
EPG_LINKS = "https://teleguide.info/download/new3/xmltv.xml.gz"
#EPG_LINKS = "https://teleguide.info/download/new3/xmltv.xml.gz,http://programtv.ru/xmltv.xml.gz,http://api.torrent-tv.ru/ttv.xmltv.xml.gz"
Source: https://habr.com/ru/post/438842/