diff --git a/src/formatters.nim b/src/formatters.nim index 9e27fe5..4a268c0 100644 --- a/src/formatters.nim +++ b/src/formatters.nim @@ -11,6 +11,8 @@ const usernameRegex = re"(^|[^A-z0-9_?])@([A-z0-9_]+)" picRegex = re"pic.twitter.com/[^ ]+" ellipsisRegex = re" ?…" + ytRegex = re"youtu(be.com|.be)" + twRegex = re"twitter.com" nbsp = $Rune(0x000A0) proc stripText*(text: string): string = @@ -46,7 +48,7 @@ proc reUsernameToLink*(m: RegexMatch; s: string): string = pretext & toLink("/" & username, "@" & username) -proc linkifyText*(text: string): string = +proc linkifyText*(text: string; prefs: Prefs): string = result = xmltree.escape(stripText(text)) result = result.replace(ellipsisRegex, "") result = result.replace(emailRegex, reEmailToLink) @@ -55,6 +57,16 @@ proc linkifyText*(text: string): string = result = result.replace(re"([^\s\(\n%])\s+([;.,!\)'%]|')", "$1") result = result.replace(re"^\. 0: + result = result.replace(ytRegex, prefs.replaceYouTube) + if prefs.replaceTwitter.len > 0: + result = result.replace(twRegex, prefs.replaceTwitter) + +proc replaceUrl*(url: string; prefs: Prefs): string = + if prefs.replaceYouTube.len > 0: + return url.replace(ytRegex, prefs.replaceYouTube) + if prefs.replaceTwitter.len > 0: + return url.replace(twRegex, prefs.replaceTwitter) proc stripTwitterUrls*(text: string): string = result = text diff --git a/src/nitter.nim b/src/nitter.nim index 8b29c7d..45198bf 100644 --- a/src/nitter.nim +++ b/src/nitter.nim @@ -1,4 +1,5 @@ -import asyncdispatch, asyncfile, httpclient, sequtils, strutils, strformat, uri, os +import asyncdispatch, asyncfile, httpclient, uri, os +import sequtils, strformat, strutils from net import Port import jester, regex diff --git a/src/prefs.nim b/src/prefs.nim index 93549b8..4fb9ef7 100644 --- a/src/prefs.nim +++ b/src/prefs.nim @@ -1,4 +1,4 @@ -import asyncdispatch, times, macros, tables +import asyncdispatch, times, macros, tables, xmltree import types withCustomDb("prefs.db", "", "", ""): @@ -25,6 +25,16 @@ type placeholder*: string const prefList*: Table[string, seq[Pref]] = { + "Privacy": @[ + Pref(kind: input, name: "replaceTwitter", + label: "Replace Twitter links with Nitter (blank to disable)", + defaultInput: "nitter.net", placeholder: "Nitter hostname"), + + Pref(kind: input, name: "replaceYouTube", + label: "Replace YouTube links with Invidious (blank to disable)", + defaultInput: "invidio.us", placeholder: "Invidious hostname") + ], + "Media": @[ Pref(kind: checkbox, name: "videoPlayback", label: "Enable hls.js video playback (requires JavaScript)", @@ -94,7 +104,7 @@ macro genUpdatePrefs*(): untyped = of checkbox: result.add quote do: prefs.`ident` = `value` == "on" of input: - result.add quote do: prefs.`ident` = `value` + result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`)) of select: let options = pref.options let default = pref.defaultOption diff --git a/src/types.nim b/src/types.nim index 8787fc0..38ef3b5 100644 --- a/src/types.nim +++ b/src/types.nim @@ -43,9 +43,9 @@ db("cache.db", "", "", ""): thumb*: string views*: string playbackType* {. - dbType: "STRING", - parseIt: parseEnum[VideoType](it.s), - formatIt: $it, + dbType: "STRING" + parseIt: parseEnum[VideoType](it.s) + formatIt: $it .}: VideoType available* {.dbType: "STRING", parseIt: parseBool(it.s) formatIt: $it.}: bool @@ -55,6 +55,8 @@ db("cache.db", "", "", ""): hideTweetStats* {.dbType: "STRING", parseIt: parseBool(it.s), formatIt: $it.}: bool hideBanner* {.dbType: "STRING", parseIt: parseBool(it.s), formatIt: $it.}: bool stickyProfile* {.dbType: "STRING", parseIt: parseBool(it.s), formatIt: $it.}: bool + replaceYouTube*: string + replaceTwitter*: string type QueryKind* = enum diff --git a/src/views/profile.nim b/src/views/profile.nim index 513b0d9..e6b8318 100644 --- a/src/views/profile.nim +++ b/src/views/profile.nim @@ -11,7 +11,7 @@ proc renderStat(num, class: string; text=""): VNode = span(class="profile-stat-num"): text if num.len == 0: "?" else: num -proc renderProfileCard*(profile: Profile): VNode = +proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode = buildHtml(tdiv(class="profile-card")): a(class="profile-card-avatar", href=profile.getUserPic().getSigUrl("pic")): genImg(profile.getUserpic("_200x200")) @@ -23,7 +23,7 @@ proc renderProfileCard*(profile: Profile): VNode = tdiv(class="profile-card-extra"): if profile.bio.len > 0: tdiv(class="profile-bio"): - p: verbatim linkifyText(profile.bio) + p: verbatim linkifyText(profile.bio, prefs) if profile.location.len > 0: tdiv(class="profile-location"): @@ -76,7 +76,7 @@ proc renderProfile*(profile: Profile; timeline: Timeline; let sticky = if prefs.stickyProfile: "sticky" else: "unset" tdiv(class="profile-tab", style={position: sticky}): - renderProfileCard(profile) + renderProfileCard(profile, prefs) if photoRail.len > 0: renderPhotoRail(profile, photoRail) diff --git a/src/views/tweet.nim b/src/views/tweet.nim index 407dd4e..d36ac84 100644 --- a/src/views/tweet.nim +++ b/src/views/tweet.nim @@ -92,7 +92,7 @@ proc renderPoll(poll: Poll): VNode = proc renderCardImage(card: Card): VNode = buildHtml(tdiv(class="card-image-container")): tdiv(class="card-image"): - img(src=get(card.image).getSigUrl("pic")) + img(src=getSigUrl(get(card.image), "pic")) if card.kind == player: tdiv(class="card-overlay"): tdiv(class="card-overlay-circle"): @@ -103,7 +103,7 @@ proc renderCard(card: Card; prefs: Prefs): VNode = let large = if card.kind in largeCards: " large" else: "" buildHtml(tdiv(class=("card" & large))): - a(class="card-container", href=card.url): + a(class="card-container", href=replaceUrl(card.url, prefs)): if card.image.isSome: renderCardImage(card) elif card.video.isSome: @@ -147,7 +147,7 @@ proc renderQuoteMedia(quote: Quote): VNode = tdiv(class="quote-sensitive"): icon "attention", class="quote-sensitive-icon" -proc renderQuote(quote: Quote): VNode = +proc renderQuote(quote: Quote; prefs: Prefs): VNode = if not quote.available: return buildHtml(tdiv(class="quote unavailable")): tdiv(class="unavailable-quote"): @@ -167,7 +167,7 @@ proc renderQuote(quote: Quote): VNode = renderReply(quote) tdiv(class="quote-text"): - verbatim linkifyText(quote.text) + verbatim linkifyText(quote.text, prefs) if quote.hasThread: a(class="show-thread", href=getLink(quote)): @@ -194,10 +194,10 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; class=""; renderReply(tweet) tdiv(class="status-content media-body"): - verbatim linkifyText(tweet.text) + verbatim linkifyText(tweet.text, prefs) if tweet.quote.isSome: - renderQuote(tweet.quote.get()) + renderQuote(tweet.quote.get(), prefs) if tweet.card.isSome: renderCard(tweet.card.get(), prefs)