Merge branch 'rework-list'

This commit is contained in:
Zed 2021-12-30 20:51:24 +01:00
commit 5501752fdb
7 changed files with 49 additions and 45 deletions

View File

@ -9,13 +9,13 @@ proc getGraphProfile*(username: string): Future[Profile] {.async.} =
js = await fetch(graphUser ? {"variables": $variables}) js = await fetch(graphUser ? {"variables": $variables})
result = parseGraphProfile(js, username) result = parseGraphProfile(js, username)
proc getGraphList*(name, list: string): Future[List] {.async.} = proc getGraphListBySlug*(name, list: string): Future[List] {.async.} =
let let
variables = %*{"screenName": name, "listSlug": list, "withHighlightedLabel": false} variables = %*{"screenName": name, "listSlug": list, "withHighlightedLabel": false}
js = await fetch(graphList ? {"variables": $variables}) js = await fetch(graphList ? {"variables": $variables})
result = parseGraphList(js) result = parseGraphList(js)
proc getGraphListById*(id: string): Future[List] {.async.} = proc getGraphList*(id: string): Future[List] {.async.} =
let let
variables = %*{"listId": id, "withHighlightedLabel": false} variables = %*{"listId": id, "withHighlightedLabel": false}
js = await fetch(graphListId ? {"variables": $variables}) js = await fetch(graphListId ? {"variables": $variables})

View File

@ -73,9 +73,9 @@ proc parseGraphList*(js: JsonNode): List =
result = List( result = List(
id: list{"id_str"}.getStr, id: list{"id_str"}.getStr,
name: list{"name"}.getStr.replace(' ', '-'), name: list{"name"}.getStr,
username: list{"user", "legacy", "screen_name"}.getStr, username: list{"user", "legacy", "screen_name"}.getStr,
userId: list{"user", "legacy", "id_str"}.getStr, userId: list{"user", "rest_id"}.getStr,
description: list{"description"}.getStr, description: list{"description"}.getStr,
members: list{"member_count"}.getInt, members: list{"member_count"}.getInt,
banner: list{"custom_banner_media", "media_info", "url"}.getImageStr banner: list{"custom_banner_media", "media_info", "url"}.getImageStr

View File

@ -58,7 +58,7 @@ proc initRedisPool*(cfg: Config) {.async.} =
template pidKey(name: string): string = "pid:" & $(hash(name) div 1_000_000) template pidKey(name: string): string = "pid:" & $(hash(name) div 1_000_000)
template profileKey(name: string): string = "p:" & name template profileKey(name: string): string = "p:" & name
template listKey(l: List): string = toLower("l:" & l.username & '/' & l.name) template listKey(l: List): string = "l:" & l.id
proc get(query: string): Future[string] {.async.} = proc get(query: string): Future[string] {.async.} =
pool.withAcquire(r): pool.withAcquire(r):
@ -131,17 +131,17 @@ proc getCachedPhotoRail*(name: string): Future[PhotoRail] {.async.} =
result = await getPhotoRail(name) result = await getPhotoRail(name)
await cache(result, name) await cache(result, name)
proc getCachedList*(username=""; name=""; id=""): Future[List] {.async.} = proc getCachedList*(username=""; slug=""; id=""): Future[List] {.async.} =
let list = if id.len > 0: redisNil let list = if id.len == 0: redisNil
else: await get(toLower("l:" & username & '/' & name)) else: await get("l:" & id)
if list != redisNil: if list != redisNil:
result = fromFlatty(uncompress(list), List) result = fromFlatty(uncompress(list), List)
else: else:
if id.len > 0: if id.len > 0:
result = await getGraphListById(id) result = await getGraphList(id)
else: else:
result = await getGraphList(username, name) result = await getGraphListBySlug(username, slug)
await cache(result) await cache(result)
proc getCachedRss*(key: string): Future[Rss] {.async.} = proc getCachedRss*(key: string): Future[Rss] {.async.} =

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
import strutils import strutils, uri
import jester import jester
@ -8,41 +8,44 @@ import ".."/[types, redis_cache, api]
import ../views/[general, timeline, list] import ../views/[general, timeline, list]
export getListTimeline, getGraphList export getListTimeline, getGraphList
template respList*(list, timeline, vnode: typed) = template respList*(list, timeline, title, vnode: typed) =
if list.id.len == 0: if list.id.len == 0:
resp Http404, showError("List \"" & @"list" & "\" not found", cfg) resp Http404, showError("List \"" & @"id" & "\" not found", cfg)
let let
html = renderList(vnode, timeline.query, list) html = renderList(vnode, timeline.query, list)
rss = "/$1/lists/$2/rss" % [@"name", @"list"] rss = "/i/lists/$1/rss" % [@"id"]
resp renderMain(html, request, cfg, prefs, rss=rss, banner=list.banner) resp renderMain(html, request, cfg, prefs, titleText=title, rss=rss, banner=list.banner)
proc createListRouter*(cfg: Config) = proc createListRouter*(cfg: Config) =
router list: router list:
get "/@name/lists/@list/?": get "/@name/lists/@slug/?":
cond '.' notin @"name" cond '.' notin @"name"
cond @"name" != "i" cond @"name" != "i"
cond @"slug" != "memberships"
let let
prefs = cookiePrefs() slug = decodeUrl(@"slug")
list = await getCachedList(@"name", @"list") list = await getCachedList(@"name", slug)
timeline = await getListTimeline(list.id, getCursor()) if list.id.len == 0:
vnode = renderTimelineTweets(timeline, prefs, request.path) resp Http404, showError("List \"" & @"slug" & "\" not found", cfg)
respList(list, timeline, vnode) redirect("/i/lists/" & list.id)
get "/@name/lists/@list/members":
cond '.' notin @"name"
cond @"name" != "i"
let
prefs = cookiePrefs()
list = await getCachedList(@"name", @"list")
members = await getListMembers(list, getCursor())
respList(list, members, renderTimelineUsers(members, prefs, request.path))
get "/i/lists/@id/?": get "/i/lists/@id/?":
cond '.' notin @"id" cond '.' notin @"id"
let list = await getCachedList(id=(@"id")) let
if list.id.len == 0: prefs = cookiePrefs()
resp Http404 list = await getCachedList(id=(@"id"))
await cache(list) title = "@" & list.username & "/" & list.name
redirect("/" & list.username & "/lists/" & list.name) timeline = await getListTimeline(list.id, getCursor())
vnode = renderTimelineTweets(timeline, prefs, request.path)
respList(list, timeline, title, vnode)
get "/i/lists/@id/members":
cond '.' notin @"id"
let
prefs = cookiePrefs()
list = await getCachedList(id=(@"id"))
title = "@" & list.username & "/" & list.name
members = await getListMembers(list, getCursor())
respList(list, members, title, renderTimelineUsers(members, prefs, request.path))

View File

@ -62,7 +62,7 @@ proc createRssRouter*(cfg: Config) =
let let
cursor = getCursor() cursor = getCursor()
key = $hash(genQueryUrl(query)) & cursor key = "search:" & $hash(genQueryUrl(query)) & ":" & cursor
var rss = await getCachedRss(key) var rss = await getCachedRss(key)
if rss.cursor.len > 0: if rss.cursor.len > 0:
@ -82,7 +82,7 @@ proc createRssRouter*(cfg: Config) =
let let
cursor = getCursor() cursor = getCursor()
name = @"name" name = @"name"
key = name & cursor key = "twitter:" & name & ":" & cursor
var rss = await getCachedRss(key) var rss = await getCachedRss(key)
if rss.cursor.len > 0: if rss.cursor.len > 0:
@ -105,9 +105,9 @@ proc createRssRouter*(cfg: Config) =
of "search": initQuery(params(request), name=name) of "search": initQuery(params(request), name=name)
else: Query(fromUser: @[name]) else: Query(fromUser: @[name])
var key = @"name" & "/" & @"tab" var key = @"tab" & ":" & @"name" & ":"
if @"tab" == "search": if @"tab" == "search":
key &= $hash(genQueryUrl(query)) key &= $hash(genQueryUrl(query)) & "/"
key &= getCursor() key &= getCursor()
var rss = await getCachedRss(key) var rss = await getCachedRss(key)
@ -119,19 +119,20 @@ proc createRssRouter*(cfg: Config) =
await cacheRss(key, rss) await cacheRss(key, rss)
respRss(rss) respRss(rss)
get "/@name/lists/@list/rss": get "/i/lists/@id/rss":
cond cfg.enableRss cond cfg.enableRss
cond '.' notin @"name"
let let
cursor = getCursor() cursor = getCursor()
key = @"name" & "/" & @"list" & cursor key =
if cursor.len == 0: "lists:" & @"id"
else: "lists:" & @"id" & ":" & cursor
var rss = await getCachedRss(key) var rss = await getCachedRss(key)
if rss.cursor.len > 0: if rss.cursor.len > 0:
respRss(rss) respRss(rss)
let let
list = await getCachedList(@"name", @"list") list = await getCachedList(id=(@"id"))
timeline = await getListTimeline(list.id, cursor) timeline = await getListTimeline(list.id, cursor)
rss.cursor = timeline.bottom rss.cursor = timeline.bottom
rss.feed = compress renderListRss(timeline.content, list, cfg) rss.feed = compress renderListRss(timeline.content, list, cfg)

View File

@ -25,5 +25,5 @@ proc renderList*(body: VNode; query: Query; list: List): VNode =
tdiv(class="timeline-description"): tdiv(class="timeline-description"):
text list.description text list.description
renderListTabs(query, &"/{list.username}/lists/{list.name}") renderListTabs(query, &"/i/lists/{list.id}")
body body

View File

@ -109,7 +109,7 @@ ${renderRssTweets(timeline.content, cfg)}
#end proc #end proc
# #
#proc renderListRss*(tweets: seq[Tweet]; list: List; cfg: Config): string = #proc renderListRss*(tweets: seq[Tweet]; list: List; cfg: Config): string =
#let link = &"{getUrlPrefix(cfg)}/{list.username}/lists/{list.name}" #let link = &"{getUrlPrefix(cfg)}/i/lists/{list.id}"
#result = "" #result = ""
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"> <rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">