1
0
mirror of https://git.sr.ht/~cadence/NewLeaf synced 2024-11-14 12:07:30 +00:00
NewLeaf/index.py

114 lines
3.2 KiB
Python
Raw Normal View History

import cherrypy
import json
2020-08-07 14:51:32 +00:00
import requests
import youtube_dlc
2020-08-13 14:20:11 +00:00
from extractors.video import extract_video
from extractors.channel import extract_channel, extract_channel_videos, extract_channel_latest
from extractors.manifest import extract_manifest
from extractors.search import extract_search
from extractors.suggestions import extract_search_suggestions
2020-10-02 10:40:39 +00:00
@cherrypy.tools.register("before_finalize", priority=60)
def custom_headers():
cherrypy.response.headers["Access-Control-Allow-Origin"] = "*"
2020-08-09 08:38:40 +00:00
2020-10-02 10:40:39 +00:00
class Second(object):
def _cp_dispatch(self, vpath):
2020-08-09 08:38:40 +00:00
if vpath[:4] == ["api", "manifest", "dash", "id"]:
vpath[:4] = ["manifest"]
return self
2020-08-07 14:51:01 +00:00
if vpath[:2] == ["api", "v1"]:
endpoints = [
["channels", 1, 2],
["videos", 1, 1],
2020-08-10 07:25:15 +00:00
["search", 0, 1]
2020-08-07 14:51:01 +00:00
]
for e in endpoints:
2020-08-07 14:51:01 +00:00
if vpath[2] == e[0] and len(vpath) >= e[1]+3 and len(vpath) <= e[2]+3:
vpath[:3] = [e[0]]
return self
return vpath
@cherrypy.expose
@cherrypy.tools.json_out()
2020-08-09 11:42:15 +00:00
def videos(self, id, **kwargs):
2020-08-13 14:20:11 +00:00
return extract_video(id)
2020-08-09 08:38:40 +00:00
@cherrypy.expose
@cherrypy.tools.encode()
2020-08-09 11:42:15 +00:00
def manifest(self, id, **kwargs):
2020-08-13 14:20:11 +00:00
result = extract_manifest(id)
if type(result) is dict:
cherrypy.response.headers["content-type"] = "application/json"
return bytes(json.dumps(result), "utf8")
elif type(result) is requests.models.Response:
cherrypy.response.headers["content-type"] = result.headers["content-type"]
return result
else:
cherrypy.response.headers["content-type"] = "application/dash+xml"
return result
2020-08-09 08:38:40 +00:00
@cherrypy.expose
@cherrypy.tools.json_out()
2020-08-09 11:42:15 +00:00
def channels(self, *suffix, **kwargs):
ucid = ""
part = ""
2020-08-13 14:20:11 +00:00
possible_parts = ("videos", "latest", "playlists")
if len(suffix) == 1:
ucid = suffix[0]
else: # len(suffix) >= 2
2020-08-13 14:20:11 +00:00
if suffix[0] in possible_parts:
[part, ucid] = suffix
2020-08-13 14:20:11 +00:00
elif suffix[1] in possible_parts:
[ucid, part] = suffix
2020-08-13 14:20:11 +00:00
else:
return {
error: "Two components specified in URL, but neither component was recognised as a part keyword.",
identifier: "PART_KEYWORD_NOT_RECOGNISED"
}
2020-08-13 08:25:10 +00:00
if part == "playlists":
return []
2020-08-13 14:20:11 +00:00
elif part == "latest":
return extract_channel_latest(ucid)
elif part == "videos":
return extract_channel_videos(ucid)
else: # part == "", so extract whole channel
return extract_channel(ucid)
2020-08-07 14:51:01 +00:00
@cherrypy.expose
@cherrypy.tools.json_out()
2020-08-10 07:25:15 +00:00
def search(self, *suffix, q, **kwargs):
if suffix == ("suggestions",):
return self.suggestions(q=q)
2020-08-13 14:20:11 +00:00
return extract_search(q)
2020-08-07 14:51:01 +00:00
2020-08-10 07:25:15 +00:00
@cherrypy.expose
@cherrypy.tools.json_out()
def suggestions(self, *, q, **kwargs):
return extract_search_suggestions(q)
2020-08-10 07:25:15 +00:00
2020-08-07 14:51:32 +00:00
@cherrypy.expose
def vi(self, id, file):
with requests.get("https://i.ytimg.com/vi/{}/{}".format(id, file)) as r:
r.raise_for_status()
cherrypy.response.headers["content-type"] = r.headers["content-type"]
return r # no idea if this is a good way to do it, but it definitely works! :D
@cherrypy.expose
def ggpht(self, *path):
with requests.get("https://yt3.ggpht.com/{}".format("/".join(path))) as r:
cherrypy.response.headers["content-type"] = r.headers["content-type"]
r.raise_for_status()
return r
2020-08-11 13:28:16 +00:00
cherrypy.config.update({"server.socket_port": 3000, "server.socket_host": "0.0.0.0"})
2020-10-02 10:40:39 +00:00
cherrypy.quickstart(Second(), "/", {
"/": {
"tools.custom_headers.on": True
}
})