nitter/src/routes/media.nim

114 lines
2.8 KiB
Nim
Raw Normal View History

import uri, strutils, httpclient, os, hashes
import asynchttpserver, asyncstreams, asyncfile, asyncnet
2019-09-06 02:42:35 +02:00
import jester, regex
import router_utils
import ".."/[types, formatters, agents]
2019-09-06 02:42:35 +02:00
import ../views/general
export asynchttpserver, asyncstreams, asyncfile, asyncnet
export httpclient, os, strutils, asyncstreams, regex
const
m3u8Regex* = re"""url="(.+.m3u8)""""
m3u8Mime* = "application/vnd.apple.mpegurl"
maxAge* = "max-age=604800"
2019-09-06 02:42:35 +02:00
let mediaAgent* = getAgent()
2020-01-22 13:04:35 +01:00
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()
client = newAsyncHttpClient(userAgent=mediaAgent)
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
let headers = newHttpHeaders({
"Content-Type": res.headers["content-type", 0],
"Content-Length": res.headers["content-length", 0],
"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
except HttpRequestError, OSError:
result = Http404
finally:
client.safeClose()
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 "/pic/@url":
2019-09-06 02:42:35 +02:00
cond "http" in @"url"
cond "twimg" in @"url"
let uri = parseUri(decodeUrl(@"url"))
cond isTwitterUrl($uri) == true
enableRawMode()
let code = await proxyMedia(request, $uri)
if code == Http200:
enableRawMode()
break route
else:
resp code
2019-09-06 02:42:35 +02:00
get "/video/@sig/@url":
cond "http" in @"url"
var url = decodeUrl(@"url")
let prefs = cookiePrefs()
if getHmac(url) != @"sig":
resp showError("Failed to verify signature", cfg)
2019-09-06 02:42:35 +02:00
if ".mp4" in url or ".ts" in url:
let code = await proxyMedia(request, url)
if code == Http200:
enableRawMode()
break route
else:
resp code
2019-09-06 02:42:35 +02:00
var content: string
2019-09-06 02:42:35 +02:00
if ".vmap" in url:
var m: RegexMatch
content = await safeFetch(url, mediaAgent)
if content.find(m3u8Regex, m):
url = decodeUrl(content[m.group(0)[0]])
content = await safeFetch(url, mediaAgent)
else:
resp Http404
2019-09-06 02:42:35 +02:00
if ".m3u8" in url:
let vid = await safeFetch(url, mediaAgent)
content = proxifyVideo(vid, prefs.proxyVideos)
2019-09-06 02:42:35 +02:00
resp content, m3u8Mime