diff --git a/src/parser.nim b/src/parser.nim index 10d2866..ed40d09 100644 --- a/src/parser.nim +++ b/src/parser.nim @@ -208,6 +208,7 @@ proc parseTweet(js: JsonNode; jsCard: JsonNode = newJNull()): Tweet = id: js{"id_str"}.getId, threadId: js{"conversation_id_str"}.getId, replyId: js{"in_reply_to_status_id_str"}.getId, + replyHandle: js{"in_reply_to_screen_name"}.getStr, text: js{"full_text"}.getStr, time: js{"created_at"}.getTime, hasThread: js{"self_thread"}.notNull, diff --git a/src/routes/status.nim b/src/routes/status.nim index 66bddb4..b780132 100644 --- a/src/routes/status.nim +++ b/src/routes/status.nim @@ -1,5 +1,5 @@ # SPDX-License-Identifier: AGPL-3.0-only -import asyncdispatch, strutils, sequtils, uri, options, sugar +import asyncdispatch, strutils, sequtils, uri, options, sugar, strformat import jester, karax/vdom @@ -64,30 +64,43 @@ proc createStatusRouter*(cfg: Config) = resp Http404, showError(error, cfg) let - title = pageTitle(conv.tweet) - ogTitle = pageTitle(conv.tweet.user) - desc = conv.tweet.text - avatar = conv.tweet.user.userPic - time = some(conv.tweet.time) + tweet = conv.tweet + title = pageTitle(tweet) + ogTitle = pageTitle(tweet.user) + desc = tweet.text + avatar = tweet.user.userPic + time = some(tweet.time) var - images = conv.tweet.photos + images = tweet.photos video = "" + context = "" + contextUrl = "" - if conv.tweet.video.isSome(): - let videoObj = get(conv.tweet.video) + if tweet.quote.isSome(): + let + quote = tweet.quote.get() + quoteUser = quote.user + context = &"↘ Quoting: {quoteUser.fullname} (@{quoteUser.username})" + contextUrl = &"{getUrlPrefix(cfg)}/i/status/{quote.id}" + elif tweet.replyId != 0: + context = &"↩ Replying to: @{tweet.replyHandle}" + contextUrl = &"{getUrlPrefix(cfg)}/i/status/{tweet.replyId}" + + if tweet.video.isSome(): + let videoObj = get(tweet.video) images = @[videoObj.thumb] let vars = videoObj.variants.filterIt(it.contentType == mp4) # idk why this wont sort when it sorts everywhere else #video = vars.sortedByIt(it.bitrate)[^1].url video = vars[^1].url - elif conv.tweet.gif.isSome(): - let gif = get(conv.tweet.gif) + elif tweet.gif.isSome(): + let gif = get(tweet.gif) images = @[gif.thumb] video = getPicUrl(gif.url) - #elif conv.tweet.card.isSome(): - # let card = conv.tweet.card.get() + #elif tweet.card.isSome(): + # let card = tweet.card.get() # if card.image.len > 0: # images = @[card.image] # elif card.video.isSome(): @@ -95,7 +108,8 @@ proc createStatusRouter*(cfg: Config) = let html = renderConversation(conv, prefs, getPath() & "#m") resp renderMain(html, request, cfg, prefs, title, desc, ogTitle, - images=images, video=video, avatar=avatar, time=time) + images=images, video=video, avatar=avatar, time=time, + context=context, contextUrl=contextUrl) get "/@name/@s/@id/@m/?@i?": cond @"s" in ["status", "statuses"] diff --git a/src/types.nim b/src/types.nim index 4fdef5a..feb06e6 100644 --- a/src/types.nim +++ b/src/types.nim @@ -211,6 +211,7 @@ type text*: string time*: DateTime reply*: seq[string] + replyHandle*: string pinned*: bool hasThread*: bool available*: bool diff --git a/src/views/general.nim b/src/views/general.nim index c919d8c..f788d9b 100644 --- a/src/views/general.nim +++ b/src/views/general.nim @@ -38,7 +38,7 @@ proc renderNavbar(cfg: Config; req: Request; rss, canonical: string): VNode = proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; video=""; images: seq[string] = @[]; banner=""; ogTitle=""; - rss=""; canonical=""; avatar=""; + rss=""; canonical=""; avatar=""; context=""; contextUrl=""; time: Option[DateTime] = none(DateTime)): VNode = var theme = prefs.theme.toTheme if "theme" in req.params: @@ -140,16 +140,28 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; meta(property="og:video:url", content=video) meta(property="og:video:secure_url", content=video) meta(property="og:video:type", content="video/mp4") - var title = encodeUrl(finalizedDesc) - var author = encodeUrl(finalizedTitleText) + + var + title = encodeUrl(finalizedDesc) + author = encodeUrl(finalizedTitleText) + url = req.path + if len(finalizedDesc) > 67: title = author author = encodeUrl(finalizedDesc) - verbatim &"" - #link(rel="alternate", - # href=&"{getUrlPrefix(cfg)}/oembed.json?type=video&title={encodeUrl(stripHtml(desc))}&user={encodeUrl(finalizedTitleText)}&url={encodeUrl(req.path)}", - # `type`="application/json+oembed") + if context != "": + author = encodeUrl(context & "\n") & author + + if contextUrl != "": + url = contextUrl + + verbatim &"" + elif context != "" and contextUrl != "": + var + title = encodeUrl(finalizedTitleText) + author = encodeUrl(context) + verbatim &"" # this is last so images are also preloaded # if this is done earlier, Chrome only preloads one image for some reason @@ -158,14 +170,15 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs; titleText=""; desc=""; ogTitle=""; rss=""; video=""; - images: seq[string] = @[]; banner=""; avatar=""; - time: Option[DateTime] = none(DateTime)): string = + images: seq[string] = @[]; banner=""; avatar=""; context=""; + contextUrl = ""; time: Option[DateTime] = none(DateTime) + ): string = let canonical = getTwitterLink(req.path, req.params) let node = buildHtml(html(lang="en")): renderHead(prefs, cfg, req, titleText, desc, video, images, banner, ogTitle, - rss, canonical, avatar, time) + rss, canonical, avatar, context, contextUrl, time) body: renderNavbar(cfg, req, rss, canonical)