format with black
This commit is contained in:
parent
1c8df48822
commit
0fb28e0741
@ -155,7 +155,9 @@ for key in providers:
|
|||||||
proxies[elem] = []
|
proxies[elem] = []
|
||||||
new_providers[elem] = providers[key]
|
new_providers[elem] = providers[key]
|
||||||
|
|
||||||
for proxy_link, region_name, country in zip(proxy_current, region_current, proxy_countries):
|
for proxy_link, region_name, country in zip(
|
||||||
|
proxy_current, region_current, proxy_countries
|
||||||
|
):
|
||||||
new_key = key
|
new_key = key
|
||||||
if country is not None:
|
if country is not None:
|
||||||
new_key = f"{key}_{country}"
|
new_key = f"{key}_{country}"
|
||||||
@ -177,8 +179,12 @@ for proxy_provider in proxies.values():
|
|||||||
if isinstance(proxy_elem, ProxyElem) and isinstance(proxy_elem.proxy, str):
|
if isinstance(proxy_elem, ProxyElem) and isinstance(proxy_elem.proxy, str):
|
||||||
proxy_keys.append(proxy_elem.proxy)
|
proxy_keys.append(proxy_elem.proxy)
|
||||||
streamlink_sessions[proxy_elem.proxy] = streamlink.Streamlink()
|
streamlink_sessions[proxy_elem.proxy] = streamlink.Streamlink()
|
||||||
streamlink_sessions[proxy_elem.proxy].set_option("http-proxy", "socks5://" + proxy_elem.proxy)
|
streamlink_sessions[proxy_elem.proxy].set_option(
|
||||||
streamlink_sessions[proxy_elem.proxy].set_option("https-proxy", "socks5://" + proxy_elem.proxy)
|
"http-proxy", "socks5://" + proxy_elem.proxy
|
||||||
|
)
|
||||||
|
streamlink_sessions[proxy_elem.proxy].set_option(
|
||||||
|
"https-proxy", "socks5://" + proxy_elem.proxy
|
||||||
|
)
|
||||||
|
|
||||||
if icecast_server is not None and stream_server is not None:
|
if icecast_server is not None and stream_server is not None:
|
||||||
try:
|
try:
|
||||||
|
@ -6,7 +6,9 @@ import json
|
|||||||
playlist = None
|
playlist = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
resp = requests.get("https://git.purser.it/roypur/icecast-relay/raw/branch/master/icecast.xml")
|
resp = requests.get(
|
||||||
|
"https://git.purser.it/roypur/icecast-relay/raw/branch/master/icecast.xml"
|
||||||
|
)
|
||||||
dom = xml.dom.minidom.parseString(resp.text)
|
dom = xml.dom.minidom.parseString(resp.text)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
@ -39,7 +41,9 @@ except Exception as e:
|
|||||||
print(e)
|
print(e)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
resp = requests.get(f'https://cdn.jsdelivr.net/npm/@silvermine/videojs-chromecast@{chromecast_version}/dist/silvermine-videojs-chromecast.min.css')
|
resp = requests.get(
|
||||||
|
f"https://cdn.jsdelivr.net/npm/@silvermine/videojs-chromecast@{chromecast_version}/dist/silvermine-videojs-chromecast.min.css"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
else:
|
else:
|
||||||
@ -48,17 +52,19 @@ else:
|
|||||||
with open("/app/version/chromecast.txt", "w") as f:
|
with open("/app/version/chromecast.txt", "w") as f:
|
||||||
f.write(chromecast_version)
|
f.write(chromecast_version)
|
||||||
|
|
||||||
|
|
||||||
def store_cdnjs(name):
|
def store_cdnjs(name):
|
||||||
version = None
|
version = None
|
||||||
try:
|
try:
|
||||||
resp = requests.get(f'https://api.cdnjs.com/libraries/{name}?fields=version')
|
resp = requests.get(f"https://api.cdnjs.com/libraries/{name}?fields=version")
|
||||||
data = json.loads(resp.text)
|
data = json.loads(resp.text)
|
||||||
version = data["version"]
|
version = data["version"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
else:
|
else:
|
||||||
with open(f'/app/version/{name}.txt', "w") as f:
|
with open(f"/app/version/{name}.txt", "w") as f:
|
||||||
f.write(version)
|
f.write(version)
|
||||||
|
|
||||||
|
|
||||||
store_cdnjs("video.js")
|
store_cdnjs("video.js")
|
||||||
store_cdnjs("font-awesome")
|
store_cdnjs("font-awesome")
|
||||||
|
@ -10,11 +10,15 @@ import config
|
|||||||
import stream_providers
|
import stream_providers
|
||||||
from typing import Optional, cast, Any
|
from typing import Optional, cast, Any
|
||||||
|
|
||||||
logging.basicConfig(format='[%(filename)s:%(lineno)d] %(message)s', stream=sys.stdout, level=logging.INFO)
|
logging.basicConfig(
|
||||||
|
format="[%(filename)s:%(lineno)d] %(message)s",
|
||||||
|
stream=sys.stdout,
|
||||||
|
level=logging.INFO,
|
||||||
|
)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UpstreamHandler():
|
class UpstreamHandler:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.provider: Optional[str] = None
|
self.provider: Optional[str] = None
|
||||||
self.raw: bool = False
|
self.raw: bool = False
|
||||||
@ -45,18 +49,18 @@ class UpstreamHandler():
|
|||||||
raw_str = handler.get_query_argument("raw", None)
|
raw_str = handler.get_query_argument("raw", None)
|
||||||
direct_str = handler.get_query_argument("direct", None)
|
direct_str = handler.get_query_argument("direct", None)
|
||||||
|
|
||||||
true_values = ['y', 'yes', 't', 'true', 'on', '1']
|
true_values = ["y", "yes", "t", "true", "on", "1"]
|
||||||
if isinstance(direct_str, str):
|
if isinstance(direct_str, str):
|
||||||
try:
|
try:
|
||||||
self.direct = (direct_str.lower() in true_values)
|
self.direct = direct_str.lower() in true_values
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.info(e)
|
logger.info(e)
|
||||||
if isinstance(raw_str, str):
|
if isinstance(raw_str, str):
|
||||||
try:
|
try:
|
||||||
self.raw = (raw_str.lower() in true_values)
|
self.raw = raw_str.lower() in true_values
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.info(e)
|
logger.info(e)
|
||||||
if self.provider in config.providers.keys():
|
if self.provider in config.providers:
|
||||||
self.valid = True
|
self.valid = True
|
||||||
path = handler.request.path
|
path = handler.request.path
|
||||||
if self.provider.startswith("nextcloud"):
|
if self.provider.startswith("nextcloud"):
|
||||||
@ -82,7 +86,7 @@ class UpstreamHandler():
|
|||||||
|
|
||||||
|
|
||||||
class MainHandler(tornado.web.RequestHandler):
|
class MainHandler(tornado.web.RequestHandler):
|
||||||
async def handle_any(self, redir):
|
async def handle_any(self):
|
||||||
handler = UpstreamHandler()
|
handler = UpstreamHandler()
|
||||||
await handler.setup(self)
|
await handler.setup(self)
|
||||||
if handler.valid:
|
if handler.valid:
|
||||||
@ -102,18 +106,29 @@ class MainHandler(tornado.web.RequestHandler):
|
|||||||
if config.template_script is not None and config.template_html is not None:
|
if config.template_script is not None and config.template_html is not None:
|
||||||
provider_data = None
|
provider_data = None
|
||||||
if handler.provider.startswith("nextcloud"):
|
if handler.provider.startswith("nextcloud"):
|
||||||
provider_data = await stream_providers.get_nextcloud(handler.upstream, handler.proxy, logger)
|
provider_data = await stream_providers.get_nextcloud(
|
||||||
|
handler.upstream, handler.proxy, logger
|
||||||
|
)
|
||||||
elif handler.provider.startswith("seafile"):
|
elif handler.provider.startswith("seafile"):
|
||||||
provider_data = await stream_providers.get_seafile(handler.upstream, handler.proxy, logger)
|
provider_data = await stream_providers.get_seafile(
|
||||||
|
handler.upstream, handler.proxy, logger
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
provider_data = await stream_providers.get_any(handler.upstream, handler.proxy, logger)
|
provider_data = await stream_providers.get_any(
|
||||||
|
handler.upstream, handler.proxy, logger
|
||||||
|
)
|
||||||
|
|
||||||
video_info = {}
|
video_info = {}
|
||||||
if handler.direct:
|
if handler.direct:
|
||||||
video_info["upstream"] = provider_data.upstream()
|
video_info["upstream"] = provider_data.upstream()
|
||||||
video_info["poster"] = provider_data.thumbnail()
|
video_info["poster"] = provider_data.thumbnail()
|
||||||
else:
|
else:
|
||||||
proxied = await handler.proxy.proxy_url([(provider_data.upstream(), provider_data.proxy_ctype()), provider_data.thumbnail()])
|
proxied = await handler.proxy.proxy_url(
|
||||||
|
[
|
||||||
|
(provider_data.upstream(), provider_data.proxy_ctype()),
|
||||||
|
provider_data.thumbnail(),
|
||||||
|
]
|
||||||
|
)
|
||||||
video_info["upstream"] = proxied[0]
|
video_info["upstream"] = proxied[0]
|
||||||
video_info["poster"] = proxied[1]
|
video_info["poster"] = proxied[1]
|
||||||
|
|
||||||
@ -136,22 +151,24 @@ class MainHandler(tornado.web.RequestHandler):
|
|||||||
script = config.template_script.generate(info=json.dumps(video_info))
|
script = config.template_script.generate(info=json.dumps(video_info))
|
||||||
b64 = str(base64.b64encode(script), "ascii")
|
b64 = str(base64.b64encode(script), "ascii")
|
||||||
data = {}
|
data = {}
|
||||||
script_file = f'data:text/javascript;charset=utf-8;base64,{b64}'
|
script_file = f"data:text/javascript;charset=utf-8;base64,{b64}"
|
||||||
data["script"] = script_file
|
data["script"] = script_file
|
||||||
data["videojs_version"] = config.videojs_version
|
data["videojs_version"] = config.videojs_version
|
||||||
data["chromecast_version"] = config.chromecast_version
|
data["chromecast_version"] = config.chromecast_version
|
||||||
data["font_awesome_version"] = config.font_awesome_version
|
data["font_awesome_version"] = config.font_awesome_version
|
||||||
rendered_html = config.template_html.generate(data=data, meta=meta, title=title)
|
rendered_html = config.template_html.generate(
|
||||||
|
data=data, meta=meta, title=title
|
||||||
|
)
|
||||||
self.write(rendered_html)
|
self.write(rendered_html)
|
||||||
else:
|
else:
|
||||||
self.set_status(404)
|
self.set_status(404)
|
||||||
self.write("HTML template missing.")
|
self.write("HTML template missing.")
|
||||||
|
|
||||||
async def get(self):
|
async def get(self):
|
||||||
await self.handle_any(True)
|
await self.handle_any()
|
||||||
|
|
||||||
async def head(self):
|
async def head(self):
|
||||||
await self.handle_any(False)
|
await self.handle_any()
|
||||||
|
|
||||||
def data_received(self, _):
|
def data_received(self, _):
|
||||||
pass
|
pass
|
||||||
@ -186,13 +203,32 @@ class StyleHandler(tornado.web.RequestHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
handlers: list[tuple[tornado.routing.Matcher, tornado.web.RequestHandler]] = []
|
handlers: list[tuple[tornado.routing.Matcher, tornado.web.RequestHandler]] = []
|
||||||
handlers.append((cast(tornado.routing.Matcher, tornado.routing.PathMatches("/sources.m3u8")), cast(tornado.web.RequestHandler, PlaylistHandler)))
|
handlers.append(
|
||||||
handlers.append((cast(tornado.routing.Matcher, tornado.routing.PathMatches("/favicon.ico")), cast(tornado.web.RequestHandler, IconHandler)))
|
(
|
||||||
handlers.append((cast(tornado.routing.Matcher, tornado.routing.PathMatches("/style.css")), cast(tornado.web.RequestHandler, StyleHandler)))
|
cast(tornado.routing.Matcher, tornado.routing.PathMatches("/sources.m3u8")),
|
||||||
handlers.append((cast(tornado.routing.Matcher, tornado.routing.AnyMatches()), cast(tornado.web.RequestHandler, MainHandler)))
|
cast(tornado.web.RequestHandler, PlaylistHandler),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
handlers.append(
|
||||||
|
(
|
||||||
|
cast(tornado.routing.Matcher, tornado.routing.PathMatches("/favicon.ico")),
|
||||||
|
cast(tornado.web.RequestHandler, IconHandler),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
handlers.append(
|
||||||
|
(
|
||||||
|
cast(tornado.routing.Matcher, tornado.routing.PathMatches("/style.css")),
|
||||||
|
cast(tornado.web.RequestHandler, StyleHandler),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
handlers.append(
|
||||||
|
(
|
||||||
|
cast(tornado.routing.Matcher, tornado.routing.AnyMatches()),
|
||||||
|
cast(tornado.web.RequestHandler, MainHandler),
|
||||||
|
)
|
||||||
|
)
|
||||||
app_web = tornado.web.Application(cast(Any, handlers))
|
app_web = tornado.web.Application(cast(Any, handlers))
|
||||||
app_web.listen(8080)
|
app_web.listen(8080)
|
||||||
tornado.ioloop.IOLoop.current().start()
|
tornado.ioloop.IOLoop.current().start()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
@ -11,21 +11,26 @@ import json
|
|||||||
import re
|
import re
|
||||||
import config
|
import config
|
||||||
|
|
||||||
class DummyLogger():
|
|
||||||
|
class DummyLogger:
|
||||||
def debug(self, msg):
|
def debug(self, msg):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def warning(self, msg):
|
def warning(self, msg):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def error(self, msg):
|
def error(self, msg):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MetaParser(html.parser.HTMLParser):
|
class MetaParser(html.parser.HTMLParser):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.meta_data = {}
|
self.meta_data = {}
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def handle_starttag_meta(self, attrs):
|
def handle_starttag_meta(self, attrs):
|
||||||
name = None
|
name = None
|
||||||
for attr in (attrs + attrs):
|
for attr in attrs + attrs:
|
||||||
if len(attr) == 2:
|
if len(attr) == 2:
|
||||||
if isinstance(name, str):
|
if isinstance(name, str):
|
||||||
if attr[0] == "content":
|
if attr[0] == "content":
|
||||||
@ -33,9 +38,10 @@ class MetaParser(html.parser.HTMLParser):
|
|||||||
return
|
return
|
||||||
elif attr[0] == "property":
|
elif attr[0] == "property":
|
||||||
name = attr[1]
|
name = attr[1]
|
||||||
|
|
||||||
def handle_starttag_input(self, attrs):
|
def handle_starttag_input(self, attrs):
|
||||||
name = None
|
name = None
|
||||||
for attr in (attrs + attrs):
|
for attr in attrs + attrs:
|
||||||
if len(attr) == 2:
|
if len(attr) == 2:
|
||||||
if isinstance(name, str):
|
if isinstance(name, str):
|
||||||
if attr[0] == "value":
|
if attr[0] == "value":
|
||||||
@ -43,14 +49,18 @@ class MetaParser(html.parser.HTMLParser):
|
|||||||
return
|
return
|
||||||
elif attr[0] == "name":
|
elif attr[0] == "name":
|
||||||
name = attr[1]
|
name = attr[1]
|
||||||
|
|
||||||
def handle_starttag(self, tag, attrs):
|
def handle_starttag(self, tag, attrs):
|
||||||
if tag == "meta":
|
if tag == "meta":
|
||||||
return self.handle_starttag_meta(attrs)
|
return self.handle_starttag_meta(attrs)
|
||||||
elif tag == "input":
|
elif tag == "input":
|
||||||
return self.handle_starttag_input(attrs)
|
return self.handle_starttag_input(attrs)
|
||||||
|
|
||||||
class StreamData():
|
|
||||||
def __init__(self, upstream, ctype, proxy_ctype, thumbnail, title, description, override):
|
class StreamData:
|
||||||
|
def __init__(
|
||||||
|
self, upstream, ctype, proxy_ctype, thumbnail, title, description, override
|
||||||
|
):
|
||||||
self.values = {}
|
self.values = {}
|
||||||
self.values["upstream"] = upstream
|
self.values["upstream"] = upstream
|
||||||
self.values["ctype"] = ctype
|
self.values["ctype"] = ctype
|
||||||
@ -59,13 +69,16 @@ class StreamData():
|
|||||||
self.values["title"] = title
|
self.values["title"] = title
|
||||||
self.values["description"] = description
|
self.values["description"] = description
|
||||||
self.override = override
|
self.override = override
|
||||||
|
|
||||||
def update(self, key, value, override):
|
def update(self, key, value, override):
|
||||||
missing = not isinstance(self.values.get(key), str)
|
missing = not isinstance(self.values.get(key), str)
|
||||||
override = override and isinstance(value, str)
|
override = override and isinstance(value, str)
|
||||||
if missing or override:
|
if missing or override:
|
||||||
self.values[key] = value
|
self.values[key] = value
|
||||||
|
|
||||||
def upstream(self):
|
def upstream(self):
|
||||||
return self.values.get("upstream")
|
return self.values.get("upstream")
|
||||||
|
|
||||||
def ctype(self):
|
def ctype(self):
|
||||||
ctype = self.values.get("ctype")
|
ctype = self.values.get("ctype")
|
||||||
proxy_ctype = self.values.get("proxy_ctype")
|
proxy_ctype = self.values.get("proxy_ctype")
|
||||||
@ -73,21 +86,28 @@ class StreamData():
|
|||||||
if not ctype.startswith("audio/") and not ctype.startswith("video/"):
|
if not ctype.startswith("audio/") and not ctype.startswith("video/"):
|
||||||
return proxy_ctype
|
return proxy_ctype
|
||||||
return ctype
|
return ctype
|
||||||
|
|
||||||
def proxy_ctype(self):
|
def proxy_ctype(self):
|
||||||
return self.values.get("proxy_ctype")
|
return self.values.get("proxy_ctype")
|
||||||
|
|
||||||
def thumbnail(self):
|
def thumbnail(self):
|
||||||
return self.values.get("thumbnail")
|
return self.values.get("thumbnail")
|
||||||
|
|
||||||
def title(self):
|
def title(self):
|
||||||
return self.values.get("title")
|
return self.values.get("title")
|
||||||
|
|
||||||
def description(self):
|
def description(self):
|
||||||
return self.values.get("description")
|
return self.values.get("description")
|
||||||
|
|
||||||
def complete(self):
|
def complete(self):
|
||||||
return None not in self.values.values()
|
return None not in self.values.values()
|
||||||
|
|
||||||
def has_data(self):
|
def has_data(self):
|
||||||
for elem in self.values.values():
|
for elem in self.values.values():
|
||||||
if isinstance(elem, str):
|
if isinstance(elem, str):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def meta(self):
|
def meta(self):
|
||||||
data = []
|
data = []
|
||||||
if isinstance(self.values.get("thumbnail"), str):
|
if isinstance(self.values.get("thumbnail"), str):
|
||||||
@ -98,7 +118,8 @@ class StreamData():
|
|||||||
data.append(("og:description", self.values.get("description")))
|
data.append(("og:description", self.values.get("description")))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
class StreamProvider():
|
|
||||||
|
class StreamProvider:
|
||||||
def __init__(self, upstream, proxy, logger):
|
def __init__(self, upstream, proxy, logger):
|
||||||
self.name = self.__class__.__name__
|
self.name = self.__class__.__name__
|
||||||
self.upstream = upstream
|
self.upstream = upstream
|
||||||
@ -106,6 +127,7 @@ class StreamProvider():
|
|||||||
self.logger = logger
|
self.logger = logger
|
||||||
if isinstance(proxy, config.ProxyElem):
|
if isinstance(proxy, config.ProxyElem):
|
||||||
self.proxy = proxy
|
self.proxy = proxy
|
||||||
|
|
||||||
def extract_mime(self, upstream):
|
def extract_mime(self, upstream):
|
||||||
try:
|
try:
|
||||||
url = urllib.parse.urlparse(upstream)
|
url = urllib.parse.urlparse(upstream)
|
||||||
@ -121,6 +143,7 @@ class StreamProvider():
|
|||||||
return "application/vnd.apple.mpegurl"
|
return "application/vnd.apple.mpegurl"
|
||||||
return mime
|
return mime
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def init_stream(self):
|
def init_stream(self):
|
||||||
stream = {}
|
stream = {}
|
||||||
stream["upstream"] = None
|
stream["upstream"] = None
|
||||||
@ -131,6 +154,7 @@ class StreamProvider():
|
|||||||
stream["description"] = None
|
stream["description"] = None
|
||||||
stream["override"] = False
|
stream["override"] = False
|
||||||
return stream
|
return stream
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
data = self.stream()
|
data = self.stream()
|
||||||
proxy_ctype = data.proxy_ctype()
|
proxy_ctype = data.proxy_ctype()
|
||||||
@ -144,7 +168,9 @@ class StreamProvider():
|
|||||||
ctype = None
|
ctype = None
|
||||||
upstream = data.upstream()
|
upstream = data.upstream()
|
||||||
try:
|
try:
|
||||||
resp = requests.head(data.upstream(), proxies=proxies, timeout=5, allow_redirects=True)
|
resp = requests.head(
|
||||||
|
data.upstream(), proxies=proxies, timeout=5, allow_redirects=True
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.info("%s <%s>", e, self.upstream)
|
self.logger.info("%s <%s>", e, self.upstream)
|
||||||
else:
|
else:
|
||||||
@ -155,7 +181,16 @@ class StreamProvider():
|
|||||||
ctype = None
|
ctype = None
|
||||||
elif "mpegurl" in ctype:
|
elif "mpegurl" in ctype:
|
||||||
ctype = "application/vnd.apple.mpegurl"
|
ctype = "application/vnd.apple.mpegurl"
|
||||||
return StreamData(data.upstream(), ctype, proxy_ctype, data.thumbnail(), data.title(), data.description(), data.override)
|
return StreamData(
|
||||||
|
data.upstream(),
|
||||||
|
ctype,
|
||||||
|
proxy_ctype,
|
||||||
|
data.thumbnail(),
|
||||||
|
data.title(),
|
||||||
|
data.description(),
|
||||||
|
data.override,
|
||||||
|
)
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
data = None
|
data = None
|
||||||
try:
|
try:
|
||||||
@ -165,6 +200,7 @@ class StreamProvider():
|
|||||||
self.logger.info("%s <%s>", e, self.upstream)
|
self.logger.info("%s <%s>", e, self.upstream)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
class StreamlinkRunner(StreamProvider):
|
class StreamlinkRunner(StreamProvider):
|
||||||
def stream(self):
|
def stream(self):
|
||||||
try:
|
try:
|
||||||
@ -184,11 +220,20 @@ class StreamlinkRunner(StreamProvider):
|
|||||||
for key in reversed(streams):
|
for key in reversed(streams):
|
||||||
stream = streams.get(key)
|
stream = streams.get(key)
|
||||||
if hasattr(stream, "url"):
|
if hasattr(stream, "url"):
|
||||||
return StreamData(stream.url, self.extract_mime(stream.url), None, None, None, None, False)
|
return StreamData(
|
||||||
|
stream.url,
|
||||||
|
self.extract_mime(stream.url),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
False,
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.info("%s <%s>", e, self.upstream)
|
self.logger.info("%s <%s>", e, self.upstream)
|
||||||
return StreamData(None, None, None, None, None, None, False)
|
return StreamData(None, None, None, None, None, None, False)
|
||||||
|
|
||||||
|
|
||||||
class YoutubeRunner(StreamProvider):
|
class YoutubeRunner(StreamProvider):
|
||||||
def stream(self):
|
def stream(self):
|
||||||
best_stream = self.init_stream()
|
best_stream = self.init_stream()
|
||||||
@ -216,15 +261,17 @@ class YoutubeRunner(StreamProvider):
|
|||||||
best_width = best_format.get("width")
|
best_width = best_format.get("width")
|
||||||
best_height = best_format.get("height")
|
best_height = best_format.get("height")
|
||||||
new_url = vformat.get("url")
|
new_url = vformat.get("url")
|
||||||
if (isinstance(best_width, int) and
|
if (
|
||||||
isinstance(best_height, int) and
|
isinstance(best_width, int)
|
||||||
isinstance(current_width, int) and
|
and isinstance(best_height, int)
|
||||||
isinstance(current_height, int) and
|
and isinstance(current_width, int)
|
||||||
isinstance(new_url, str) and
|
and isinstance(current_height, int)
|
||||||
current_width > best_width and
|
and isinstance(new_url, str)
|
||||||
current_height > best_height and
|
and current_width > best_width
|
||||||
acodec != "none" and
|
and current_height > best_height
|
||||||
vcodec != "none"):
|
and acodec != "none"
|
||||||
|
and vcodec != "none"
|
||||||
|
):
|
||||||
best_format = vformat
|
best_format = vformat
|
||||||
best_stream["override"] = True
|
best_stream["override"] = True
|
||||||
best_stream["upstream"] = new_url
|
best_stream["upstream"] = new_url
|
||||||
@ -233,11 +280,14 @@ class YoutubeRunner(StreamProvider):
|
|||||||
self.logger.info("%s <%s>", e, self.upstream)
|
self.logger.info("%s <%s>", e, self.upstream)
|
||||||
return StreamData(**best_stream)
|
return StreamData(**best_stream)
|
||||||
|
|
||||||
|
|
||||||
class SeafileRunner(StreamProvider):
|
class SeafileRunner(StreamProvider):
|
||||||
def stream(self):
|
def stream(self):
|
||||||
stream_data = self.init_stream()
|
stream_data = self.init_stream()
|
||||||
json_data = None
|
json_data = None
|
||||||
proc = subprocess.run(["/app/seafile.js", self.upstream], capture_output=True, encoding="utf-8")
|
proc = subprocess.run(
|
||||||
|
["/app/seafile.js", self.upstream], capture_output=True, encoding="utf-8"
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
json_data = json.loads(proc.stdout)
|
json_data = json.loads(proc.stdout)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -249,6 +299,7 @@ class SeafileRunner(StreamProvider):
|
|||||||
stream_data["proxy_ctype"] = "video/mp4"
|
stream_data["proxy_ctype"] = "video/mp4"
|
||||||
return StreamData(**stream_data)
|
return StreamData(**stream_data)
|
||||||
|
|
||||||
|
|
||||||
class MetaProvider(StreamProvider):
|
class MetaProvider(StreamProvider):
|
||||||
def parse_web(self):
|
def parse_web(self):
|
||||||
stream_data = self.init_stream()
|
stream_data = self.init_stream()
|
||||||
@ -268,6 +319,7 @@ class MetaProvider(StreamProvider):
|
|||||||
stream_data["description"] = data.get("og:description")
|
stream_data["description"] = data.get("og:description")
|
||||||
return stream_data
|
return stream_data
|
||||||
|
|
||||||
|
|
||||||
class MetaRunner(MetaProvider):
|
class MetaRunner(MetaProvider):
|
||||||
def stream(self):
|
def stream(self):
|
||||||
stream_data = self.parse_web()
|
stream_data = self.parse_web()
|
||||||
@ -275,14 +327,17 @@ class MetaRunner(MetaProvider):
|
|||||||
stream_data["ctype"] = None
|
stream_data["ctype"] = None
|
||||||
return StreamData(**stream_data)
|
return StreamData(**stream_data)
|
||||||
|
|
||||||
|
|
||||||
class NextcloudRunner(MetaProvider):
|
class NextcloudRunner(MetaProvider):
|
||||||
def stream(self):
|
def stream(self):
|
||||||
stream_data = self.parse_web()
|
stream_data = self.parse_web()
|
||||||
stream_data["thumbnail"] = None
|
stream_data["thumbnail"] = None
|
||||||
return StreamData(**stream_data)
|
return StreamData(**stream_data)
|
||||||
|
|
||||||
|
|
||||||
upstream_cache = expiringdict.ExpiringDict(max_len=512, max_age_seconds=18000)
|
upstream_cache = expiringdict.ExpiringDict(max_len=512, max_age_seconds=18000)
|
||||||
|
|
||||||
|
|
||||||
async def get_from_runner(cache_key, runner, logger):
|
async def get_from_runner(cache_key, runner, logger):
|
||||||
result = None
|
result = None
|
||||||
cached = upstream_cache.get(cache_key)
|
cached = upstream_cache.get(cache_key)
|
||||||
@ -298,20 +353,36 @@ async def get_from_runner(cache_key, runner, logger):
|
|||||||
result = result_temp
|
result = result_temp
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def get_streamlink(upstream, proxy, logger):
|
async def get_streamlink(upstream, proxy, logger):
|
||||||
return await get_from_runner((0, upstream), StreamlinkRunner(upstream, proxy, logger), logger)
|
return await get_from_runner(
|
||||||
|
(0, upstream), StreamlinkRunner(upstream, proxy, logger), logger
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_ytdl(upstream, proxy, logger):
|
async def get_ytdl(upstream, proxy, logger):
|
||||||
return await get_from_runner((1, upstream), YoutubeRunner(upstream, proxy, logger), logger)
|
return await get_from_runner(
|
||||||
|
(1, upstream), YoutubeRunner(upstream, proxy, logger), logger
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_meta(upstream, proxy, logger):
|
async def get_meta(upstream, proxy, logger):
|
||||||
return await get_from_runner((2, upstream), MetaRunner(upstream, proxy, logger), logger)
|
return await get_from_runner(
|
||||||
|
(2, upstream), MetaRunner(upstream, proxy, logger), logger
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_nextcloud(upstream, proxy, logger):
|
async def get_nextcloud(upstream, proxy, logger):
|
||||||
return await get_from_runner((3, upstream), NextcloudRunner(upstream, proxy, logger), logger)
|
return await get_from_runner(
|
||||||
|
(3, upstream), NextcloudRunner(upstream, proxy, logger), logger
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_seafile(upstream, proxy, logger):
|
async def get_seafile(upstream, proxy, logger):
|
||||||
return await get_from_runner((3, upstream), SeafileRunner(upstream, proxy, logger), logger)
|
return await get_from_runner(
|
||||||
|
(3, upstream), SeafileRunner(upstream, proxy, logger), logger
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get_any(upstream, proxy, logger):
|
async def get_any(upstream, proxy, logger):
|
||||||
cache_key = (4, upstream)
|
cache_key = (4, upstream)
|
||||||
@ -331,7 +402,9 @@ async def get_any(upstream, proxy, logger):
|
|||||||
result.update("ctype", temp_result.ctype(), temp_result.override)
|
result.update("ctype", temp_result.ctype(), temp_result.override)
|
||||||
result.update("thumbnail", temp_result.thumbnail(), temp_result.override)
|
result.update("thumbnail", temp_result.thumbnail(), temp_result.override)
|
||||||
result.update("title", temp_result.title(), temp_result.override)
|
result.update("title", temp_result.title(), temp_result.override)
|
||||||
result.update("description", temp_result.description(), temp_result.override)
|
result.update(
|
||||||
|
"description", temp_result.description(), temp_result.override
|
||||||
|
)
|
||||||
if result.complete():
|
if result.complete():
|
||||||
upstream_cache[cache_key] = result
|
upstream_cache[cache_key] = result
|
||||||
break
|
break
|
||||||
|
Loading…
Reference in New Issue
Block a user