nitter/src/routes/media.nim

142 lines
3.5 KiB
Nim
Raw Permalink Normal View History

2021-12-27 02:37:38 +01:00
# SPDX-License-Identifier: AGPL-3.0-only
2020-06-09 15:04:38 +02:00
import uri, strutils, httpclient, os, hashes, base64, re
import asynchttpserver, asyncstreams, asyncfile, asyncnet
2019-09-06 02:42:35 +02:00
2020-06-09 15:04:38 +02:00
import jester
2019-09-06 02:42:35 +02:00
import router_utils
2022-01-17 04:13:27 +01:00
import ".."/[types, formatters, utils]
2019-09-06 02:42:35 +02:00
export asynchttpserver, asyncstreams, asyncfile, asyncnet
2020-06-09 15:04:38 +02:00
export httpclient, os, strutils, asyncstreams, base64, re
const
m3u8Mime* = "application/vnd.apple.mpegurl"
maxAge* = "max-age=604800"
2019-09-06 02:42:35 +02:00
2022-01-17 04:13:27 +01:00
proc safeFetch*(url: string): Future[string] {.async.} =
let client = newAsyncHttpClient()
2020-06-09 16:45:21 +02:00
try: result = await client.getContent(url)
except: discard
finally: client.close()
template respond*(req: asynchttpserver.Request; headers) =
var msg = "HTTP/1.1 200 OK\c\L"
for k, v in headers:
msg.add(k & ": " & v & "\c\L")
msg.add "\c\L"
yield req.client.send(msg)
proc proxyMedia*(req: jester.Request; url: string): Future[HttpCode] {.async.} =
result = Http200
let
request = req.getNativeReq()
2022-01-17 04:13:27 +01:00
client = newAsyncHttpClient()
try:
let res = await client.get(url)
if res.status != "200 OK":
return Http404
let hashed = $hash(url)
if request.headers.getOrDefault("If-None-Match") == hashed:
return Http304
2020-11-07 23:02:27 +01:00
let contentLength =
if res.headers.hasKey("content-length"):
res.headers["content-length", 0]
else:
""
let headers = newHttpHeaders({
"Content-Type": res.headers["content-type", 0],
2020-11-07 23:02:27 +01:00
"Content-Length": contentLength,
"Cache-Control": maxAge,
"ETag": hashed
})
respond(request, headers)
var (hasValue, data) = (true, "")
while hasValue:
(hasValue, data) = await res.bodyStream.read()
if hasValue:
await request.client.send(data)
data.setLen 0
2020-06-07 08:23:05 +02:00
except HttpRequestError, ProtocolError, OSError:
result = Http404
finally:
2020-06-09 16:45:21 +02:00
client.close()
2020-06-09 15:04:38 +02:00
template check*(code): untyped =
if code != Http200:
resp code
else:
enableRawMode()
break route
proc decoded*(req: jester.Request; index: int): string =
let
based = req.matches[0].len > 1
encoded = req.matches[index]
if based: decode(encoded)
else: decodeUrl(encoded)
2019-09-06 02:42:35 +02:00
proc createMediaRouter*(cfg: Config) =
router media:
2020-05-26 14:24:41 +02:00
get "/pic/?":
resp Http404
get re"^\/pic\/orig\/(enc)?\/?(.+)":
var url = decoded(request, 1)
if "twimg.com" notin url:
url.insert(twimg)
if not url.startsWith(https):
url.insert(https)
url.add("?name=orig")
let uri = parseUri(url)
cond isTwitterUrl(uri) == true
let code = await proxyMedia(request, url)
check code
2020-06-09 15:04:38 +02:00
get re"^\/pic\/(enc)?\/?(.+)":
var url = decoded(request, 1)
if "twimg.com" notin url:
url.insert(twimg)
if not url.startsWith(https):
url.insert(https)
let uri = parseUri(url)
cond isTwitterUrl(uri) == true
2020-06-09 15:04:38 +02:00
let code = await proxyMedia(request, url)
check code
2020-06-09 15:04:38 +02:00
get re"^\/video\/(enc)?\/?(.+)\/(.+)$":
let url = decoded(request, 2)
cond "http" in url
2019-09-06 02:42:35 +02:00
2020-06-09 15:04:38 +02:00
if getHmac(url) != request.matches[1]:
resp showError("Failed to verify signature", cfg)
2019-09-06 02:42:35 +02:00
if ".mp4" in url or ".ts" in url or ".m4s" in url:
let code = await proxyMedia(request, url)
2020-06-09 15:04:38 +02:00
check code
2019-09-06 02:42:35 +02:00
var content: string
2019-09-06 02:42:35 +02:00
if ".vmap" in url:
2022-01-17 04:13:27 +01:00
let m3u8 = getM3u8Url(await safeFetch(url))
2020-06-09 15:04:38 +02:00
if m3u8.len > 0:
2022-01-17 04:13:27 +01:00
content = await safeFetch(url)
else:
resp Http404
2019-09-06 02:42:35 +02:00
if ".m3u8" in url:
2022-01-17 04:13:27 +01:00
let vid = await safeFetch(url)
2020-06-09 16:45:21 +02:00
content = proxifyVideo(vid, cookiePref(proxyVideos))
2019-09-06 02:42:35 +02:00
resp content, m3u8Mime