diff --git a/.gitignore b/.gitignore index 55031d6..e140769 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ nitter.conf guest_accounts.json* dump.rdb proxy/node_modules +*.dll +*.exe +*.pem +Caddyfile diff --git a/src/routes/embed.nim b/src/routes/embed.nim index 7f58ef9..967718b 100644 --- a/src/routes/embed.nim +++ b/src/routes/embed.nim @@ -36,4 +36,4 @@ proc createEmbedRouter*(cfg: Config) = resp Http404 get "/oembed.json": - respJson generateOembed(cfg, @"type", @"title", @"user", @"url") + respJson generateOembed(cfg, @"type", @"title", @"user", @"url", @"provider") diff --git a/src/routes/status.nim b/src/routes/status.nim index 17be5ba..232b55e 100644 --- a/src/routes/status.nim +++ b/src/routes/status.nim @@ -67,6 +67,8 @@ proc createStatusRouter*(cfg: Config) = title = pageTitle(conv.tweet) ogTitle = pageTitle(conv.tweet.user) desc = conv.tweet.text + avatar = conv.tweet.user.userPic + time = some(conv.tweet.time) var images = conv.tweet.photos @@ -93,7 +95,7 @@ proc createStatusRouter*(cfg: Config) = let html = renderConversation(conv, prefs, getPath() & "#m") resp renderMain(html, request, cfg, prefs, title, desc, ogTitle, - images=images, video=video) + images=images, video=video, avatar=avatar, time=time) get "/@name/@s/@id/@m/?@i?": cond @"s" in ["status", "statuses"] diff --git a/src/views/embed.nim b/src/views/embed.nim index 981e28f..e82ca63 100644 --- a/src/views/embed.nim +++ b/src/views/embed.nim @@ -23,13 +23,13 @@ proc renderVideoEmbed*(tweet: Tweet; cfg: Config; req: Request): string = result = doctype & $node -proc generateOembed*(cfg: Config; typ, title, user, url: string): JsonNode = +proc generateOembed*(cfg: Config; typ, title, user, url, provider: string): JsonNode = %*{ "type": typ, "version": "1.0", - "provider_name": "Nitter", + "provider_name": provider, "provider_url": getUrlPrefix(cfg), "title": title, "author_name": user, "author_url": url - } \ No newline at end of file + } diff --git a/src/views/general.nim b/src/views/general.nim index abcf45c..c919d8c 100644 --- a/src/views/general.nim +++ b/src/views/general.nim @@ -1,5 +1,5 @@ # SPDX-License-Identifier: AGPL-3.0-only -import uri, strutils, strformat +import uri, strutils, strformat, times, options import karax/[karaxdsl, vdom] import renderutils @@ -38,7 +38,8 @@ 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=""): VNode = + rss=""; canonical=""; avatar=""; + time: Option[DateTime] = none(DateTime)): VNode = var theme = prefs.theme.toTheme if "theme" in req.params: theme = req.params["theme"].toTheme @@ -99,26 +100,41 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; else: meta(property="og:title", content=finalizedTitleText) meta(property="og:description", content=finalizedDesc) - meta(property="og:site_name", content="Nitter") meta(property="og:locale", content="en_US") + var siteName = "Nitter" + + if time.isSome: + let timeObj = time.get + let timeStr = $timeObj + meta(property="og:article:published_time", content=timeStr) + + let formattedTime = timeObj.format("yyyy/MM/dd HH:mm:ss") + siteName = &"Nitter • {formattedTime}" + + meta(property="og:site_name", content=siteName) + if banner.len > 0 and not banner.startsWith('#'): let bannerUrl = getPicUrl(banner) link(rel="preload", type="image/png", href=bannerUrl, `as`="image") - for url in images: - let preloadUrl = if "400x400" in url: getPicUrl(url) - else: getSmallPic(url) - link(rel="preload", type="image/png", href=preloadUrl, `as`="image") + if images.len > 0: + for url in images: + let preloadUrl = if "400x400" in url: getPicUrl(url) + else: getSmallPic(url) + link(rel="preload", type="image/png", href=preloadUrl, `as`="image") - let image = getUrlPrefix(cfg) & getPicUrl(url) - meta(property="og:image", content=image) - if video.len == 0: - meta(property="twitter:image:src", content=image) - if rss.len > 0: - meta(property="twitter:card", content="summary") - elif video.len == 0: - meta(property="twitter:card", content="summary_large_image") + let image = getUrlPrefix(cfg) & getPicUrl(url) + meta(property="og:image", content=image) + if video.len == 0: + meta(property="twitter:image:src", content=image) + if rss.len > 0: + meta(property="twitter:card", content="summary") + elif video.len == 0: + meta(property="twitter:card", content="summary_large_image") + elif avatar.len > 0: + let avatarUrl = getUrlPrefix(cfg) & getPicUrl(avatar) + meta(property="og:image", content=avatarUrl) if video.len > 0: meta(property="og:video:url", content=video) @@ -130,7 +146,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; title = author author = encodeUrl(finalizedDesc) - verbatim &"" + 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") @@ -142,13 +158,14 @@ 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=""): string = + images: seq[string] = @[]; banner=""; avatar=""; + 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) + rss, canonical, avatar, time) body: renderNavbar(cfg, req, rss, canonical)