2019-10-26 13:34:30 +00:00
|
|
|
import asyncdispatch, strutils, sequtils, uri, options
|
2019-09-06 00:42:35 +00:00
|
|
|
import jester
|
|
|
|
|
|
|
|
import router_utils
|
2019-09-20 23:08:30 +00:00
|
|
|
import ".."/[api, types, cache, formatters, agents, query]
|
2019-09-13 20:24:58 +00:00
|
|
|
import ../views/[general, profile, timeline, status, search]
|
2019-09-06 00:42:35 +00:00
|
|
|
|
|
|
|
export uri, sequtils
|
|
|
|
export router_utils
|
2019-09-13 20:24:58 +00:00
|
|
|
export api, cache, formatters, query, agents
|
2019-09-06 00:42:35 +00:00
|
|
|
export profile, timeline, status
|
|
|
|
|
2019-10-21 21:12:40 +00:00
|
|
|
proc fetchSingleTimeline*(name, after, agent: string; query: Query;
|
2019-10-23 06:34:03 +00:00
|
|
|
media=true): Future[(Profile, Timeline)] {.async.} =
|
2019-09-06 00:42:35 +00:00
|
|
|
var timeline: Timeline
|
|
|
|
var profile: Profile
|
|
|
|
var cachedProfile = hasCachedProfile(name)
|
|
|
|
|
|
|
|
if cachedProfile.isSome:
|
|
|
|
profile = get(cachedProfile)
|
|
|
|
|
2019-09-19 00:23:22 +00:00
|
|
|
if query.kind == posts:
|
2019-09-06 00:42:35 +00:00
|
|
|
if cachedProfile.isSome:
|
2019-10-21 21:12:40 +00:00
|
|
|
timeline = await getTimeline(name, after, agent, media)
|
2019-09-06 00:42:35 +00:00
|
|
|
else:
|
2019-10-23 07:03:15 +00:00
|
|
|
(profile, timeline) = await getProfileAndTimeline(name, after, agent, media)
|
2019-09-06 00:42:35 +00:00
|
|
|
cache(profile)
|
|
|
|
else:
|
2019-10-23 06:34:03 +00:00
|
|
|
var timelineFut =
|
|
|
|
if query.kind == QueryKind.media:
|
|
|
|
getMediaTimeline(name, after, agent, media)
|
|
|
|
else:
|
|
|
|
getSearch[Tweet](query, after, agent, media)
|
2019-09-06 00:42:35 +00:00
|
|
|
if cachedProfile.isNone:
|
|
|
|
profile = await getCachedProfile(name, agent)
|
|
|
|
timeline = await timelineFut
|
|
|
|
|
2019-09-15 10:10:43 +00:00
|
|
|
if profile.username.len == 0: return
|
2019-10-23 06:34:03 +00:00
|
|
|
return (profile, timeline)
|
2019-09-06 00:42:35 +00:00
|
|
|
|
2019-12-04 04:58:18 +00:00
|
|
|
proc fetchMultiTimeline*(names: seq[string]; after, agent: string; query: Query;
|
|
|
|
media=true): Future[Timeline] {.async.} =
|
2019-09-06 00:42:35 +00:00
|
|
|
var q = query
|
2019-09-19 00:23:22 +00:00
|
|
|
q.fromUser = names
|
|
|
|
if q.kind == posts and "replies" notin q.excludes:
|
|
|
|
q.excludes.add "replies"
|
2019-12-04 04:58:18 +00:00
|
|
|
return await getSearch[Tweet](q, after, agent, media)
|
2019-09-06 00:42:35 +00:00
|
|
|
|
2019-09-20 20:56:27 +00:00
|
|
|
proc get*(req: Request; key: string): string =
|
2019-12-06 07:21:37 +00:00
|
|
|
params(req).getOrDefault(key)
|
2019-09-20 20:56:27 +00:00
|
|
|
|
2019-10-21 03:19:00 +00:00
|
|
|
proc showTimeline*(request: Request; query: Query; cfg: Config; rss: string): Future[string] {.async.} =
|
2019-09-20 20:56:27 +00:00
|
|
|
let
|
|
|
|
agent = getAgent()
|
|
|
|
prefs = cookiePrefs()
|
|
|
|
name = request.get("name")
|
2019-10-08 13:15:47 +00:00
|
|
|
after = request.get("max_position")
|
2019-12-04 04:58:18 +00:00
|
|
|
names = getNames(name)
|
2019-09-06 00:42:35 +00:00
|
|
|
|
2019-10-23 07:03:15 +00:00
|
|
|
if names.len != 1:
|
2019-09-15 10:10:43 +00:00
|
|
|
let
|
|
|
|
timeline = await fetchMultiTimeline(names, after, agent, query)
|
2019-09-20 20:56:27 +00:00
|
|
|
html = renderTweetSearch(timeline, prefs, getPath())
|
2019-12-04 04:58:18 +00:00
|
|
|
return renderMain(html, request, cfg, "Multi", rss=rss)
|
2019-09-06 00:42:35 +00:00
|
|
|
|
2019-10-23 07:03:15 +00:00
|
|
|
let
|
|
|
|
rail = getPhotoRail(names[0], agent, skip=(query.kind == media))
|
|
|
|
(p, t) = await fetchSingleTimeline(names[0], after, agent, query)
|
|
|
|
r = await rail
|
|
|
|
if p.username.len == 0: return
|
|
|
|
let pHtml = renderProfile(p, t, r, prefs, getPath())
|
|
|
|
return renderMain(pHtml, request, cfg, pageTitle(p), pageDesc(p),
|
|
|
|
rss=rss, images = @[p.getUserpic("_200x200")])
|
|
|
|
|
2019-09-06 00:42:35 +00:00
|
|
|
template respTimeline*(timeline: typed) =
|
|
|
|
if timeline.len == 0:
|
2019-10-21 05:59:22 +00:00
|
|
|
resp Http404, showError("User \"" & @"name" & "\" not found", cfg)
|
2019-09-06 00:42:35 +00:00
|
|
|
resp timeline
|
|
|
|
|
|
|
|
proc createTimelineRouter*(cfg: Config) =
|
|
|
|
setProfileCacheTime(cfg.profileCacheTime)
|
|
|
|
|
|
|
|
router timeline:
|
|
|
|
get "/@name/?":
|
|
|
|
cond '.' notin @"name"
|
2019-09-15 10:10:43 +00:00
|
|
|
let rss = "/$1/rss" % @"name"
|
2019-10-21 03:19:00 +00:00
|
|
|
respTimeline(await showTimeline(request, Query(), cfg, rss))
|
2019-09-06 00:42:35 +00:00
|
|
|
|
2019-10-07 15:46:16 +00:00
|
|
|
get "/@name/with_replies":
|
2019-09-06 00:42:35 +00:00
|
|
|
cond '.' notin @"name"
|
2019-10-07 15:46:16 +00:00
|
|
|
let rss = "/$1/with_replies/rss" % @"name"
|
2019-10-21 03:19:00 +00:00
|
|
|
respTimeline(await showTimeline(request, getReplyQuery(@"name"), cfg, rss))
|
2019-09-06 00:42:35 +00:00
|
|
|
|
|
|
|
get "/@name/media":
|
|
|
|
cond '.' notin @"name"
|
2019-09-15 10:10:43 +00:00
|
|
|
let rss = "/$1/media/rss" % @"name"
|
2019-10-21 03:19:00 +00:00
|
|
|
respTimeline(await showTimeline(request, getMediaQuery(@"name"), cfg, rss))
|
2019-09-15 07:57:45 +00:00
|
|
|
|
2019-09-20 01:35:27 +00:00
|
|
|
get "/@name/search":
|
|
|
|
cond '.' notin @"name"
|
|
|
|
let query = initQuery(params(request), name=(@"name"))
|
2019-09-20 20:56:27 +00:00
|
|
|
let rss = "/$1/search/rss?$2" % [@"name", genQueryUrl(query)]
|
2019-10-21 03:19:00 +00:00
|
|
|
respTimeline(await showTimeline(request, query, cfg, rss))
|