Refactor routing code

This commit is contained in:
Zed
2019-09-06 02:42:35 +02:00
parent 7bdf5b0f76
commit 014f01bf88
7 changed files with 253 additions and 203 deletions

64
src/routes/media.nim Normal file
View File

@@ -0,0 +1,64 @@
import asyncfile, uri, strutils, httpclient, os
import jester, regex
import router_utils
import ".."/[types, formatters, utils, prefs]
import ../views/general
export asyncfile, httpclient, os, strutils
export regex
export utils
proc createMediaRouter*(cfg: Config) =
router media:
get "/pic/@sig/@url":
cond "http" in @"url"
cond "twimg" in @"url"
let
uri = parseUri(decodeUrl(@"url"))
path = uri.path.split("/")[2 .. ^1].join("/")
filename = cfg.cacheDir / cleanFilename(path & uri.query)
if getHmac($uri) != @"sig":
resp showError("Failed to verify signature", cfg.title)
if not existsDir(cfg.cacheDir):
createDir(cfg.cacheDir)
if not existsFile(filename):
let client = newAsyncHttpClient()
await client.downloadFile($uri, filename)
client.close()
if not existsFile(filename):
resp Http404
let file = openAsync(filename)
let buf = await readAll(file)
file.close()
resp buf, mimetype(filename)
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.title)
let client = newAsyncHttpClient()
var content = await client.getContent(url)
if ".vmap" in url:
var m: RegexMatch
discard content.find(re"""url="(.+.m3u8)"""", m)
url = decodeUrl(content[m.group(0)[0]])
content = await client.getContent(url)
if ".m3u8" in url:
content = proxifyVideo(content, prefs.proxyVideos)
client.close()
resp content, mimetype(url)

View File

@@ -0,0 +1,38 @@
import strutils, uri
import jester
import router_utils
import ".."/[prefs, types, utils]
import ../views/[general, preferences]
export preferences
proc createPrefRouter*(cfg: Config) =
router preferences:
template savePrefs(): untyped =
setCookie("preferences", $prefs.id, daysForward(360), httpOnly=true, secure=cfg.useHttps)
get "/settings":
let prefs = cookiePrefs()
let path = refPath()
resp renderMain(renderPreferences(prefs, path), prefs, cfg.title, "Preferences", path)
post "/saveprefs":
var prefs = cookiePrefs()
genUpdatePrefs()
savePrefs()
redirect(refPath())
post "/resetprefs":
var prefs = cookiePrefs()
resetPrefs(prefs)
savePrefs()
redirect($(parseUri("/settings") ? filterParams(request.params)))
post "/enablehls":
var prefs = cookiePrefs()
prefs.hlsPlayback = true
cache(prefs)
savePrefs()
redirect(refPath())

View File

@@ -0,0 +1,11 @@
import ../utils
template cookiePrefs*(): untyped {.dirty.} =
getPrefs(request.cookies.getOrDefault("preferences"))
template getPath*(): untyped {.dirty.} =
$(parseUri(request.path) ? filterParams(request.params))
template refPath*(): untyped {.dirty.} =
if @"referer".len > 0: @"referer" else: "/"

127
src/routes/timeline.nim Normal file
View File

@@ -0,0 +1,127 @@
import asyncdispatch, strutils, sequtils, uri
import jester
import router_utils
import ".."/[api, prefs, types, utils, cache, formatters, agents, search]
import ../views/[general, profile, timeline, status]
export uri, sequtils
export router_utils
export api, cache, formatters, search, agents
export profile, timeline, status
proc showSingleTimeline(name, after, agent: string; query: Option[Query];
prefs: Prefs; path, title: string): Future[string] {.async.} =
let railFut = getPhotoRail(name, agent)
var timeline: Timeline
var profile: Profile
var cachedProfile = hasCachedProfile(name)
if cachedProfile.isSome:
profile = get(cachedProfile)
if query.isNone:
if cachedProfile.isSome:
timeline = await getTimeline(name, after, agent)
else:
(profile, timeline) = await getProfileAndTimeline(name, agent, after)
cache(profile)
else:
var timelineFut = getTimelineSearch(get(query), after, agent)
if cachedProfile.isNone:
profile = await getCachedProfile(name, agent)
timeline = await timelineFut
if profile.username.len == 0:
return ""
let profileHtml = renderProfile(profile, timeline, await railFut, prefs, path)
return renderMain(profileHtml, prefs, title, pageTitle(profile),
pageDesc(profile), path)
proc showMultiTimeline(names: seq[string]; after, agent: string; query: Option[Query];
prefs: Prefs; path, title: string): Future[string] {.async.} =
var q = query
if q.isSome:
get(q).fromUser = names
else:
q = some(Query(kind: multi, fromUser: names, excludes: @["replies"]))
var timeline = renderMulti(await getTimelineSearch(get(q), after, agent),
names.join(","), prefs, path)
return renderMain(timeline, prefs, title, "Multi")
proc showTimeline*(name, after: string; query: Option[Query];
prefs: Prefs; path, title: string): Future[string] {.async.} =
let agent = getAgent()
let names = name.strip(chars={'/'}).split(",").filterIt(it.len > 0)
if names.len == 1:
return await showSingleTimeline(names[0], after, agent, query, prefs, path, title)
else:
return await showMultiTimeline(names, after, agent, query, prefs, path, title)
template respTimeline*(timeline: typed) =
if timeline.len == 0:
resp Http404, showError("User \"" & @"name" & "\" not found", cfg.title)
resp timeline
proc createTimelineRouter*(cfg: Config) =
setProfileCacheTime(cfg.profileCacheTime)
router timeline:
get "/@name/?":
cond '.' notin @"name"
respTimeline(await showTimeline(@"name", @"after", none(Query),
cookiePrefs(), getPath(), cfg.title))
get "/@name/search":
cond '.' notin @"name"
let prefs = cookiePrefs()
let query = initQuery(@"filter", @"include", @"not", @"sep", @"name")
respTimeline(await showTimeline(@"name", @"after", some(query),
cookiePrefs(), getPath(), cfg.title))
get "/@name/replies":
cond '.' notin @"name"
let prefs = cookiePrefs()
respTimeline(await showTimeline(@"name", @"after", some(getReplyQuery(@"name")),
cookiePrefs(), getPath(), cfg.title))
get "/@name/media":
cond '.' notin @"name"
let prefs = cookiePrefs()
respTimeline(await showTimeline(@"name", @"after", some(getMediaQuery(@"name")),
cookiePrefs(), getPath(), cfg.title))
get "/@name/status/@id":
cond '.' notin @"name"
let prefs = cookiePrefs()
let conversation = await getTweet(@"name", @"id", getAgent())
if conversation == nil or conversation.tweet.id.len == 0:
resp Http404, showError("Tweet not found", cfg.title)
let path = getPath()
let title = pageTitle(conversation.tweet.profile)
let desc = conversation.tweet.text
let html = renderConversation(conversation, prefs, path)
if conversation.tweet.video.isSome():
let thumb = get(conversation.tweet.video).thumb
let vidUrl = getVideoEmbed(conversation.tweet.id)
resp renderMain(html, prefs, cfg.title, title, desc, path, images = @[thumb],
`type`="video", video=vidUrl)
elif conversation.tweet.gif.isSome():
let thumb = get(conversation.tweet.gif).thumb
let vidUrl = getVideoEmbed(conversation.tweet.id)
resp renderMain(html, prefs, cfg.title, title, desc, path, images = @[thumb],
`type`="video", video=vidUrl)
else:
resp renderMain(html, prefs, cfg.title, title, desc, path, images=conversation.tweet.photos)
get "/i/web/status/@id":
redirect("/i/status/" & @"id")