Merge remote-tracking branch 'upstream/master'
I really hope nothing breaks! :3
This commit is contained in:
@@ -6,7 +6,7 @@ import types, utils, query
|
|||||||
const
|
const
|
||||||
cards = "cards.twitter.com/cards"
|
cards = "cards.twitter.com/cards"
|
||||||
tco = "https://t.co"
|
tco = "https://t.co"
|
||||||
twitter = parseUri("https://twitter.com")
|
twitter = parseUri("https://x.com")
|
||||||
|
|
||||||
let
|
let
|
||||||
twRegex = re"(?<=(?<!\S)https:\/\/|(?<=\s))(www\.|mobile\.)?twitter\.com"
|
twRegex = re"(?<=(?<!\S)https:\/\/|(?<=\s))(www\.|mobile\.)?twitter\.com"
|
||||||
@@ -64,18 +64,20 @@ proc replaceUrls*(body: string; prefs: Prefs; absolute=""): string =
|
|||||||
result = body
|
result = body
|
||||||
|
|
||||||
if prefs.replaceYouTube.len > 0 and "youtu" in result:
|
if prefs.replaceYouTube.len > 0 and "youtu" in result:
|
||||||
result = result.replace(ytRegex, prefs.replaceYouTube)
|
let youtubeHost = strip(prefs.replaceYouTube, chars={'/'})
|
||||||
|
result = result.replace(ytRegex, youtubeHost)
|
||||||
|
|
||||||
if prefs.replaceTwitter.len > 0:
|
if prefs.replaceTwitter.len > 0:
|
||||||
|
let twitterHost = strip(prefs.replaceTwitter, chars={'/'})
|
||||||
if tco in result:
|
if tco in result:
|
||||||
result = result.replace(tco, https & prefs.replaceTwitter & "/t.co")
|
result = result.replace(tco, https & twitterHost & "/t.co")
|
||||||
if "x.com" in result:
|
if "x.com" in result:
|
||||||
result = result.replace(xRegex, prefs.replaceTwitter)
|
result = result.replace(xRegex, twitterHost)
|
||||||
result = result.replacef(xLinkRegex, a(
|
result = result.replacef(xLinkRegex, a(
|
||||||
prefs.replaceTwitter & "$2", href = https & prefs.replaceTwitter & "$1"))
|
twitterHost & "$2", href = https & twitterHost & "$1"))
|
||||||
if "twitter.com" in result:
|
if "twitter.com" in result:
|
||||||
result = result.replace(cards, prefs.replaceTwitter & "/cards")
|
result = result.replace(cards, twitterHost & "/cards")
|
||||||
result = result.replace(twRegex, prefs.replaceTwitter)
|
result = result.replace(twRegex, twitterHost)
|
||||||
result = result.replacef(twLinkRegex, a(
|
result = result.replacef(twLinkRegex, a(
|
||||||
prefs.replaceTwitter & "$2", href = https & prefs.replaceTwitter & "$1"))
|
prefs.replaceTwitter & "$2", href = https & prefs.replaceTwitter & "$1"))
|
||||||
if "imgur.com" in result:
|
if "imgur.com" in result:
|
||||||
@@ -96,9 +98,10 @@ proc replaceUrls*(body: string; prefs: Prefs; absolute=""): string =
|
|||||||
prefs.replaceSoundCloud & "$4", href = https & prefs.replaceSoundCloud & "$2"))
|
prefs.replaceSoundCloud & "$4", href = https & prefs.replaceSoundCloud & "$2"))
|
||||||
|
|
||||||
if prefs.replaceReddit.len > 0 and ("reddit.com" in result or "redd.it" in result):
|
if prefs.replaceReddit.len > 0 and ("reddit.com" in result or "redd.it" in result):
|
||||||
result = result.replace(rdShortRegex, prefs.replaceReddit & "/comments/")
|
let redditHost = strip(prefs.replaceReddit, chars={'/'})
|
||||||
result = result.replace(rdRegex, prefs.replaceReddit)
|
result = result.replace(rdShortRegex, redditHost & "/comments/")
|
||||||
if prefs.replaceReddit in result and "/gallery/" in result:
|
result = result.replace(rdRegex, redditHost)
|
||||||
|
if redditHost in result and "/gallery/" in result:
|
||||||
result = result.replace("/gallery/", "/comments/")
|
result = result.replace("/gallery/", "/comments/")
|
||||||
|
|
||||||
if absolute.len > 0 and "href" in result:
|
if absolute.len > 0 and "href" in result:
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ proc parseGraphConversation*(js: JsonNode; tweetId: string): Conversation =
|
|||||||
result.before.content.add tweet
|
result.before.content.add tweet
|
||||||
elif entryId.startsWith("cursor-bottom"):
|
elif entryId.startsWith("cursor-bottom"):
|
||||||
var cursorValue = select(
|
var cursorValue = select(
|
||||||
|
e{"content", "value"},
|
||||||
e{"content", "content", "value"},
|
e{"content", "content", "value"},
|
||||||
e{"content", "itemContent", "value"}
|
e{"content", "itemContent", "value"}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,10 +6,9 @@ import types
|
|||||||
const
|
const
|
||||||
validFilters* = @[
|
validFilters* = @[
|
||||||
"media", "images", "twimg", "videos",
|
"media", "images", "twimg", "videos",
|
||||||
"native_video", "consumer_video", "pro_video",
|
"native_video", "consumer_video", "spaces",
|
||||||
"links", "news", "quote", "mentions",
|
"links", "news", "quote", "mentions",
|
||||||
"replies", "retweets", "nativeretweets",
|
"replies", "retweets", "nativeretweets"
|
||||||
"verified", "safe"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
emptyQuery* = "include:nativeretweets"
|
emptyQuery* = "include:nativeretweets"
|
||||||
@@ -18,6 +17,11 @@ template `@`(param: string): untyped =
|
|||||||
if param in pms: pms[param]
|
if param in pms: pms[param]
|
||||||
else: ""
|
else: ""
|
||||||
|
|
||||||
|
proc validateNumber(value: string): string =
|
||||||
|
if value.anyIt(not it.isDigit):
|
||||||
|
return ""
|
||||||
|
return value
|
||||||
|
|
||||||
proc initQuery*(pms: Table[string, string]; name=""): Query =
|
proc initQuery*(pms: Table[string, string]; name=""): Query =
|
||||||
result = Query(
|
result = Query(
|
||||||
kind: parseEnum[QueryKind](@"f", tweets),
|
kind: parseEnum[QueryKind](@"f", tweets),
|
||||||
@@ -26,7 +30,7 @@ proc initQuery*(pms: Table[string, string]; name=""): Query =
|
|||||||
excludes: validFilters.filterIt("e-" & it in pms),
|
excludes: validFilters.filterIt("e-" & it in pms),
|
||||||
since: @"since",
|
since: @"since",
|
||||||
until: @"until",
|
until: @"until",
|
||||||
near: @"near"
|
minLikes: validateNumber(@"min_faves")
|
||||||
)
|
)
|
||||||
|
|
||||||
if name.len > 0:
|
if name.len > 0:
|
||||||
@@ -81,8 +85,8 @@ proc genQueryParam*(query: Query): string =
|
|||||||
result &= " since:" & query.since
|
result &= " since:" & query.since
|
||||||
if query.until.len > 0:
|
if query.until.len > 0:
|
||||||
result &= " until:" & query.until
|
result &= " until:" & query.until
|
||||||
if query.near.len > 0:
|
if query.minLikes.len > 0:
|
||||||
result &= &" near:\"{query.near}\" within:15mi"
|
result &= " min_faves:" & query.minLikes
|
||||||
if query.text.len > 0:
|
if query.text.len > 0:
|
||||||
if result.len > 0:
|
if result.len > 0:
|
||||||
result &= " " & query.text
|
result &= " " & query.text
|
||||||
@@ -106,8 +110,8 @@ proc genQueryUrl*(query: Query): string =
|
|||||||
params.add "since=" & query.since
|
params.add "since=" & query.since
|
||||||
if query.until.len > 0:
|
if query.until.len > 0:
|
||||||
params.add "until=" & query.until
|
params.add "until=" & query.until
|
||||||
if query.near.len > 0:
|
if query.minLikes.len > 0:
|
||||||
params.add "near=" & query.near
|
params.add "min_faves=" & query.minLikes
|
||||||
|
|
||||||
if params.len > 0:
|
if params.len > 0:
|
||||||
result &= params.join("&")
|
result &= params.join("&")
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ proc createStatusRouter*(cfg: Config) =
|
|||||||
resp $renderReplies(replies, prefs, getPath())
|
resp $renderReplies(replies, prefs, getPath())
|
||||||
|
|
||||||
let conv = await getTweet(id, getCursor())
|
let conv = await getTweet(id, getCursor())
|
||||||
if conv == nil:
|
|
||||||
warn "nil conv"
|
|
||||||
|
|
||||||
if conv == nil or conv.tweet == nil or conv.tweet.id == 0:
|
if conv == nil or conv.tweet == nil or conv.tweet.id == 0:
|
||||||
var error = "Tweet not found"
|
var error = "Tweet not found"
|
||||||
@@ -68,7 +66,7 @@ proc createStatusRouter*(cfg: Config) =
|
|||||||
|
|
||||||
get "/@name/@s/@id/@m/?@i?":
|
get "/@name/@s/@id/@m/?@i?":
|
||||||
cond @"s" in ["status", "statuses"]
|
cond @"s" in ["status", "statuses"]
|
||||||
cond @"m" in ["video", "photo"]
|
cond @"m" in ["video", "photo", "history"]
|
||||||
redirect("/$1/status/$2" % [@"name", @"id"])
|
redirect("/$1/status/$2" % [@"name", @"id"])
|
||||||
|
|
||||||
get "/@name/statuses/@id/?":
|
get "/@name/statuses/@id/?":
|
||||||
@@ -76,6 +74,6 @@ proc createStatusRouter*(cfg: Config) =
|
|||||||
|
|
||||||
get "/i/web/status/@id":
|
get "/i/web/status/@id":
|
||||||
redirect("/i/status/" & @"id")
|
redirect("/i/status/" & @"id")
|
||||||
|
|
||||||
get "/@name/thread/@id/?":
|
get "/@name/thread/@id/?":
|
||||||
redirect("/$1/status/$2" % [@"name", @"id"])
|
redirect("/$1/status/$2" % [@"name", @"id"])
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ proc createTimelineRouter*(cfg: Config) =
|
|||||||
get "/intent/user":
|
get "/intent/user":
|
||||||
respUserId()
|
respUserId()
|
||||||
|
|
||||||
|
get "/intent/follow/?":
|
||||||
|
let username = request.params.getOrDefault("screen_name")
|
||||||
|
if username.len == 0:
|
||||||
|
resp Http400, showError("Missing screen_name parameter", cfg)
|
||||||
|
redirect("/" & username)
|
||||||
|
|
||||||
get "/@name/?@tab?/?":
|
get "/@name/?@tab?/?":
|
||||||
cond '.' notin @"name"
|
cond '.' notin @"name"
|
||||||
cond @"name" notin ["pic", "gif", "video", "search", "settings", "login", "intent", "i"]
|
cond @"name" notin ["pic", "gif", "video", "search", "settings", "login", "intent", "i"]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ proc createUnsupportedRouter*(cfg: Config) =
|
|||||||
get "/@name/lists/?": feature()
|
get "/@name/lists/?": feature()
|
||||||
|
|
||||||
get "/intent/?@i?":
|
get "/intent/?@i?":
|
||||||
cond @"i" notin ["user"]
|
cond @"i" notin ["user", "follow"]
|
||||||
feature()
|
feature()
|
||||||
|
|
||||||
get "/i/@i?/?@j?":
|
get "/i/@i?/?@j?":
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ body {
|
|||||||
background-color: var(--bg_color);
|
background-color: var(--bg_color);
|
||||||
color: var(--fg_color);
|
color: var(--fg_color);
|
||||||
font-family: $font_stack;
|
font-family: $font_stack;
|
||||||
font-size: 14px;
|
font-size: 15px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ button {
|
|||||||
|
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="date"],
|
input[type="date"],
|
||||||
|
input[type="number"],
|
||||||
select {
|
select {
|
||||||
@include input-colors;
|
@include input-colors;
|
||||||
background-color: var(--bg_elements);
|
background-color: var(--bg_elements);
|
||||||
@@ -24,7 +25,12 @@ select {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"] {
|
||||||
height: 16px;
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +44,17 @@ input[type="date"]::-webkit-inner-spin-button {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
-moz-appearance: textfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"]::-webkit-inner-spin-button,
|
||||||
|
input[type="number"]::-webkit-outer-spin-button {
|
||||||
|
display: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="date"]::-webkit-clear-button {
|
input[type="date"]::-webkit-clear-button {
|
||||||
margin-left: 17px;
|
margin-left: 17px;
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
@@ -176,7 +193,8 @@ input::-webkit-datetime-edit-year-field:focus {
|
|||||||
color: var(--fg_color);
|
color: var(--fg_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type="text"],
|
||||||
|
input[type="number"] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
max-width: 140px;
|
max-width: 140px;
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type="text"],
|
||||||
|
input[type="number"] {
|
||||||
height: calc(100% - 4px);
|
height: calc(100% - 4px);
|
||||||
width: calc(100% - 8px);
|
width: calc(100% - 8px);
|
||||||
}
|
}
|
||||||
@@ -155,15 +156,14 @@
|
|||||||
|
|
||||||
.profile-tabs {
|
.profile-tabs {
|
||||||
@include search-resize(820px, 5);
|
@include search-resize(820px, 5);
|
||||||
@include search-resize(725px, 4);
|
@include search-resize(715px, 4);
|
||||||
@include search-resize(600px, 6);
|
@include search-resize(700px, 5);
|
||||||
@include search-resize(560px, 5);
|
@include search-resize(485px, 4);
|
||||||
@include search-resize(480px, 4);
|
|
||||||
@include search-resize(410px, 3);
|
@include search-resize(410px, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@include search-resize(560px, 5);
|
@include search-resize(700px, 5);
|
||||||
@include search-resize(480px, 4);
|
@include search-resize(485px, 4);
|
||||||
@include search-resize(410px, 3);
|
@include search-resize(410px, 3);
|
||||||
|
|
||||||
@media(max-width: 600px) {
|
@media(max-width: 600px) {
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ type
|
|||||||
fromUser*: seq[string]
|
fromUser*: seq[string]
|
||||||
since*: string
|
since*: string
|
||||||
until*: string
|
until*: string
|
||||||
near*: string
|
minLikes*: string
|
||||||
sep*: string
|
sep*: string
|
||||||
|
|
||||||
Gif* = object
|
Gif* = object
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ proc renderNavbar(cfg: Config; req: Request; rss, canonical: string): VNode =
|
|||||||
tdiv(class="nav-item right"):
|
tdiv(class="nav-item right"):
|
||||||
if cfg.enableRss and rss.len > 0:
|
if cfg.enableRss and rss.len > 0:
|
||||||
icon "rss", title="RSS Feed", href=rss
|
icon "rss", title="RSS Feed", href=rss
|
||||||
icon "bird", title="Open in Twitter", href=canonical
|
icon "bird", title="Open in X", href=canonical
|
||||||
a(href="https://buymeacoffee.com/kuu7o"): verbatim lp
|
a(href="https://buymeacoffee.com/kuu7o"): verbatim lp
|
||||||
icon "info", title="About", href="/about"
|
icon "info", title="About", href="/about"
|
||||||
icon "cog", title="Preferences", href=("/settings?referer=" & encodeUrl(path))
|
icon "cog", title="Preferences", href=("/settings?referer=" & encodeUrl(path))
|
||||||
|
|
||||||
proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
||||||
video=""; images: seq[string] = @[]; banner=""; ogTitle="";
|
video=""; images: seq[string] = @[]; banner=""; ogTitle="";
|
||||||
rss=""; canonical=""): VNode =
|
rss=""; alternate=""): VNode =
|
||||||
var theme = prefs.theme.toTheme
|
var theme = prefs.theme.toTheme
|
||||||
if "theme" in req.params:
|
if "theme" in req.params:
|
||||||
theme = req.params["theme"].toTheme
|
theme = req.params["theme"].toTheme
|
||||||
@@ -54,7 +54,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
|||||||
let opensearchUrl = getUrlPrefix(cfg) & "/opensearch"
|
let opensearchUrl = getUrlPrefix(cfg) & "/opensearch"
|
||||||
|
|
||||||
buildHtml(head):
|
buildHtml(head):
|
||||||
link(rel="stylesheet", type="text/css", href="/css/style.css?v=20")
|
link(rel="stylesheet", type="text/css", href="/css/style.css?v=21")
|
||||||
link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=3")
|
link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=3")
|
||||||
|
|
||||||
if theme.len > 0:
|
if theme.len > 0:
|
||||||
@@ -68,8 +68,8 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
|||||||
link(rel="search", type="application/opensearchdescription+xml", title=cfg.title,
|
link(rel="search", type="application/opensearchdescription+xml", title=cfg.title,
|
||||||
href=opensearchUrl)
|
href=opensearchUrl)
|
||||||
|
|
||||||
if canonical.len > 0:
|
if alternate.len > 0:
|
||||||
link(rel="canonical", href=canonical)
|
link(rel="alternate", href=alternate, title="View on X")
|
||||||
|
|
||||||
if cfg.enableRss and rss.len > 0:
|
if cfg.enableRss and rss.len > 0:
|
||||||
link(rel="alternate", type="application/rss+xml", href=rss, title="RSS feed")
|
link(rel="alternate", type="application/rss+xml", href=rss, title="RSS feed")
|
||||||
@@ -131,16 +131,16 @@ proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs;
|
|||||||
titleText=""; desc=""; ogTitle=""; rss=""; video="";
|
titleText=""; desc=""; ogTitle=""; rss=""; video="";
|
||||||
images: seq[string] = @[]; banner=""): string =
|
images: seq[string] = @[]; banner=""): string =
|
||||||
|
|
||||||
let canonical = getTwitterLink(req.path, req.params)
|
let twitterLink = getTwitterLink(req.path, req.params)
|
||||||
|
|
||||||
let node = buildHtml(html(lang="en")):
|
let node = buildHtml(html(lang="en")):
|
||||||
renderHead(prefs, cfg, req, titleText, desc, video, images, banner, ogTitle,
|
renderHead(prefs, cfg, req, titleText, desc, video, images, banner, ogTitle,
|
||||||
rss, canonical)
|
rss, twitterLink)
|
||||||
|
|
||||||
body(class=if prefs.verifiedBadge == "Hide all": "hide-verified-all"
|
body(class=if prefs.verifiedBadge == "Hide all": "hide-verified-all"
|
||||||
elif prefs.verifiedBadge == "Show official only": "hide-verified-blue"
|
elif prefs.verifiedBadge == "Show official only": "hide-verified-blue"
|
||||||
else: ""):
|
else: ""):
|
||||||
renderNavbar(cfg, req, rss, canonical)
|
renderNavbar(cfg, req, rss, twitterLink)
|
||||||
|
|
||||||
tdiv(class="container"):
|
tdiv(class="container"):
|
||||||
body
|
body
|
||||||
|
|||||||
@@ -89,6 +89,13 @@ proc genDate*(pref, state: string): VNode =
|
|||||||
input(name=pref, `type`="date", value=state)
|
input(name=pref, `type`="date", value=state)
|
||||||
icon "calendar"
|
icon "calendar"
|
||||||
|
|
||||||
|
proc genNumberInput*(pref, label, state, placeholder: string; class=""; autofocus=true; min="0"): VNode =
|
||||||
|
let p = placeholder
|
||||||
|
buildHtml(tdiv(class=("pref-group pref-input " & class))):
|
||||||
|
if label.len > 0:
|
||||||
|
label(`for`=pref): text label
|
||||||
|
input(name=pref, `type`="number", placeholder=p, value=state, autofocus=(autofocus and state.len == 0), min=min, step="1")
|
||||||
|
|
||||||
proc genImg*(url: string; class=""): VNode =
|
proc genImg*(url: string; class=""): VNode =
|
||||||
buildHtml():
|
buildHtml():
|
||||||
img(src=getPicUrl(url), class=class, alt="", loading="lazy")
|
img(src=getPicUrl(url), class=class, alt="", loading="lazy")
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ proc renderThread(thread: Tweets; prefs: Prefs; path: string): VNode =
|
|||||||
|
|
||||||
proc renderUser*(user: User; prefs: Prefs; path: string): VNode =
|
proc renderUser*(user: User; prefs: Prefs; path: string): VNode =
|
||||||
let class = if user.sensitive: "timeline-item nsfw" else: "timeline-item"
|
let class = if user.sensitive: "timeline-item nsfw" else: "timeline-item"
|
||||||
buildHtml(tdiv(class=class)):
|
buildHtml(tdiv(class=class, data-username=user.username)):
|
||||||
a(class="tweet-link", href=("/" & user.username))
|
a(class="tweet-link", href=("/" & user.username))
|
||||||
tdiv(class="tweet-body profile-result"):
|
tdiv(class="tweet-body profile-result"):
|
||||||
tdiv(class="tweet-header"):
|
tdiv(class="tweet-header"):
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class=""; index=0;
|
|||||||
divClass.add " nsfw"
|
divClass.add " nsfw"
|
||||||
|
|
||||||
if not tweet.available:
|
if not tweet.available:
|
||||||
return buildHtml(tdiv(class=divClass & "unavailable timeline-item")):
|
return buildHtml(tdiv(class=divClass & "unavailable timeline-item", data-username=tweet.user.username)):
|
||||||
tdiv(class="unavailable-box"):
|
tdiv(class="unavailable-box"):
|
||||||
if tweet.tombstone.len > 0:
|
if tweet.tombstone.len > 0:
|
||||||
text tweet.tombstone
|
text tweet.tombstone
|
||||||
@@ -297,7 +297,7 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class=""; index=0;
|
|||||||
tweet = tweet.retweet.get
|
tweet = tweet.retweet.get
|
||||||
retweet = fullTweet.user.fullname
|
retweet = fullTweet.user.fullname
|
||||||
|
|
||||||
buildHtml(tdiv(class=("timeline-item " & divClass))):
|
buildHtml(tdiv(class=("timeline-item " & divClass), data-username=tweet.user.username)):
|
||||||
if not mainTweet:
|
if not mainTweet:
|
||||||
a(class="tweet-link", href=getLink(tweet))
|
a(class="tweet-link", href=getLink(tweet))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user