diff --git a/src/api.nim b/src/api.nim index 61d33bb..779b3e4 100644 --- a/src/api.nim +++ b/src/api.nim @@ -9,13 +9,13 @@ proc getGraphProfile*(username: string): Future[Profile] {.async.} = js = await fetch(graphUser ? {"variables": $variables}) result = parseGraphProfile(js, username) -proc getGraphList*(name, list: string): Future[List] {.async.} = +proc getGraphListBySlug*(name, list: string): Future[List] {.async.} = let variables = %*{"screenName": name, "listSlug": list, "withHighlightedLabel": false} js = await fetch(graphList ? {"variables": $variables}) result = parseGraphList(js) -proc getGraphListById*(id: string): Future[List] {.async.} = +proc getGraphList*(id: string): Future[List] {.async.} = let variables = %*{"listId": id, "withHighlightedLabel": false} js = await fetch(graphListId ? {"variables": $variables}) diff --git a/src/parser.nim b/src/parser.nim index 054e6ca..292a87c 100644 --- a/src/parser.nim +++ b/src/parser.nim @@ -73,7 +73,7 @@ proc parseGraphList*(js: JsonNode): List = result = List( id: list{"id_str"}.getStr, - name: list{"name"}.getStr.replace(' ', '-'), + name: list{"name"}.getStr, username: list{"user", "legacy", "screen_name"}.getStr, userId: list{"user", "legacy", "id_str"}.getStr, description: list{"description"}.getStr, diff --git a/src/redis_cache.nim b/src/redis_cache.nim index ef6f9d3..b09c575 100644 --- a/src/redis_cache.nim +++ b/src/redis_cache.nim @@ -56,7 +56,7 @@ proc initRedisPool*(cfg: Config) {.async.} = template pidKey(name: string): string = "pid:" & $(hash(name) div 1_000_000) 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.} = pool.withAcquire(r): @@ -129,17 +129,17 @@ proc getCachedPhotoRail*(name: string): Future[PhotoRail] {.async.} = result = await getPhotoRail(name) await cache(result, name) -proc getCachedList*(username=""; name=""; id=""): Future[List] {.async.} = - let list = if id.len > 0: redisNil - else: await get(toLower("l:" & username & '/' & name)) +proc getCachedList*(username=""; slug=""; id=""): Future[List] {.async.} = + let list = if id.len == 0: redisNil + else: await get("l:" & id) if list != redisNil: result = fromFlatty(uncompress(list), List) else: if id.len > 0: - result = await getGraphListById(id) + result = await getGraphList(id) else: - result = await getGraphList(username, name) + result = await getGraphListBySlug(username, slug) await cache(result) proc getCachedRss*(key: string): Future[Rss] {.async.} = diff --git a/src/routes/list.nim b/src/routes/list.nim index e8191e2..0d9bae8 100644 --- a/src/routes/list.nim +++ b/src/routes/list.nim @@ -1,5 +1,5 @@ # SPDX-License-Identifier: AGPL-3.0-only -import strutils +import strutils, uri import jester @@ -8,41 +8,44 @@ import ".."/[types, redis_cache, api] import ../views/[general, timeline, list] export getListTimeline, getGraphList -template respList*(list, timeline, vnode: typed) = +template respList*(list, timeline, title, vnode: typed) = if list.id.len == 0: - resp Http404, showError("List \"" & @"list" & "\" not found", cfg) + resp Http404, showError("List \"" & @"id" & "\" not found", cfg) let 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) = router list: - get "/@name/lists/@list/?": + get "/@name/lists/@slug/?": cond '.' notin @"name" cond @"name" != "i" + cond @"slug" != "memberships" let - prefs = cookiePrefs() - list = await getCachedList(@"name", @"list") - timeline = await getListTimeline(list.id, getCursor()) - vnode = renderTimelineTweets(timeline, prefs, request.path) - respList(list, timeline, vnode) - - 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)) + slug = decodeUrl(@"slug") + list = await getCachedList(@"name", slug) + if list.id.len == 0: + resp Http404, showError("List \"" & @"slug" & "\" not found", cfg) + redirect("/i/lists/" & list.id) get "/i/lists/@id/?": cond '.' notin @"id" - let list = await getCachedList(id=(@"id")) - if list.id.len == 0: - resp Http404 - await cache(list) - redirect("/" & list.username & "/lists/" & list.name) + let + prefs = cookiePrefs() + list = await getCachedList(id=(@"id")) + title = "@" & list.username & "/" & 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)) diff --git a/src/routes/rss.nim b/src/routes/rss.nim index 2fd2901..997bfde 100644 --- a/src/routes/rss.nim +++ b/src/routes/rss.nim @@ -119,19 +119,18 @@ proc createRssRouter*(cfg: Config) = await cacheRss(key, rss) respRss(rss) - get "/@name/lists/@list/rss": + get "/i/lists/@id/rss": cond cfg.enableRss - cond '.' notin @"name" let cursor = getCursor() - key = @"name" & "/" & @"list" & cursor + key = @"id" & cursor var rss = await getCachedRss(key) if rss.cursor.len > 0: respRss(rss) let - list = await getCachedList(@"name", @"list") + list = await getCachedList(id=(@"id")) timeline = await getListTimeline(list.id, cursor) rss.cursor = timeline.bottom rss.feed = compress renderListRss(timeline.content, list, cfg) diff --git a/src/views/list.nim b/src/views/list.nim index b94d170..e5639d1 100644 --- a/src/views/list.nim +++ b/src/views/list.nim @@ -25,5 +25,5 @@ proc renderList*(body: VNode; query: Query; list: List): VNode = tdiv(class="timeline-description"): text list.description - renderListTabs(query, &"/{list.username}/lists/{list.name}") + renderListTabs(query, &"/i/lists/{list.id}") body diff --git a/src/views/rss.nimf b/src/views/rss.nimf index d000060..889578a 100644 --- a/src/views/rss.nimf +++ b/src/views/rss.nimf @@ -109,7 +109,7 @@ ${renderRssTweets(timeline.content, cfg)} #end proc # #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 = ""