Add Invidious/Nitter link replacement preferences

This commit is contained in:
Zed 2019-08-15 15:51:20 +02:00
parent 93da24be85
commit 7dfbc16f4c
6 changed files with 41 additions and 16 deletions

View file

@ -11,6 +11,8 @@ const
usernameRegex = re"(^|[^A-z0-9_?])@([A-z0-9_]+)" usernameRegex = re"(^|[^A-z0-9_?])@([A-z0-9_]+)"
picRegex = re"pic.twitter.com/[^ ]+" picRegex = re"pic.twitter.com/[^ ]+"
ellipsisRegex = re" ?…" ellipsisRegex = re" ?…"
ytRegex = re"youtu(be.com|.be)"
twRegex = re"twitter.com"
nbsp = $Rune(0x000A0) nbsp = $Rune(0x000A0)
proc stripText*(text: string): string = proc stripText*(text: string): string =
@ -46,7 +48,7 @@ proc reUsernameToLink*(m: RegexMatch; s: string): string =
pretext & toLink("/" & username, "@" & username) pretext & toLink("/" & username, "@" & username)
proc linkifyText*(text: string): string = proc linkifyText*(text: string; prefs: Prefs): string =
result = xmltree.escape(stripText(text)) result = xmltree.escape(stripText(text))
result = result.replace(ellipsisRegex, "") result = result.replace(ellipsisRegex, "")
result = result.replace(emailRegex, reEmailToLink) result = result.replace(emailRegex, reEmailToLink)
@ -55,6 +57,16 @@ proc linkifyText*(text: string): string =
result = result.replace(re"([^\s\(\n%])<a", "$1 <a") result = result.replace(re"([^\s\(\n%])<a", "$1 <a")
result = result.replace(re"</a>\s+([;.,!\)'%]|&apos;)", "</a>$1") result = result.replace(re"</a>\s+([;.,!\)'%]|&apos;)", "</a>$1")
result = result.replace(re"^\. <a", ".<a") result = result.replace(re"^\. <a", ".<a")
if prefs.replaceYouTube.len > 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 = proc stripTwitterUrls*(text: string): string =
result = text result = text

View file

@ -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 from net import Port
import jester, regex import jester, regex

View file

@ -1,4 +1,4 @@
import asyncdispatch, times, macros, tables import asyncdispatch, times, macros, tables, xmltree
import types import types
withCustomDb("prefs.db", "", "", ""): withCustomDb("prefs.db", "", "", ""):
@ -25,6 +25,16 @@ type
placeholder*: string placeholder*: string
const prefList*: Table[string, seq[Pref]] = { 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": @[ "Media": @[
Pref(kind: checkbox, name: "videoPlayback", Pref(kind: checkbox, name: "videoPlayback",
label: "Enable hls.js video playback (requires JavaScript)", label: "Enable hls.js video playback (requires JavaScript)",
@ -94,7 +104,7 @@ macro genUpdatePrefs*(): untyped =
of checkbox: of checkbox:
result.add quote do: prefs.`ident` = `value` == "on" result.add quote do: prefs.`ident` = `value` == "on"
of input: of input:
result.add quote do: prefs.`ident` = `value` result.add quote do: prefs.`ident` = xmltree.escape(strip(`value`))
of select: of select:
let options = pref.options let options = pref.options
let default = pref.defaultOption let default = pref.defaultOption

View file

@ -43,9 +43,9 @@ db("cache.db", "", "", ""):
thumb*: string thumb*: string
views*: string views*: string
playbackType* {. playbackType* {.
dbType: "STRING", dbType: "STRING"
parseIt: parseEnum[VideoType](it.s), parseIt: parseEnum[VideoType](it.s)
formatIt: $it, formatIt: $it
.}: VideoType .}: VideoType
available* {.dbType: "STRING", parseIt: parseBool(it.s) formatIt: $it.}: bool 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 hideTweetStats* {.dbType: "STRING", parseIt: parseBool(it.s), formatIt: $it.}: bool
hideBanner* {.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 stickyProfile* {.dbType: "STRING", parseIt: parseBool(it.s), formatIt: $it.}: bool
replaceYouTube*: string
replaceTwitter*: string
type type
QueryKind* = enum QueryKind* = enum

View file

@ -11,7 +11,7 @@ proc renderStat(num, class: string; text=""): VNode =
span(class="profile-stat-num"): span(class="profile-stat-num"):
text if num.len == 0: "?" else: 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")): buildHtml(tdiv(class="profile-card")):
a(class="profile-card-avatar", href=profile.getUserPic().getSigUrl("pic")): a(class="profile-card-avatar", href=profile.getUserPic().getSigUrl("pic")):
genImg(profile.getUserpic("_200x200")) genImg(profile.getUserpic("_200x200"))
@ -23,7 +23,7 @@ proc renderProfileCard*(profile: Profile): VNode =
tdiv(class="profile-card-extra"): tdiv(class="profile-card-extra"):
if profile.bio.len > 0: if profile.bio.len > 0:
tdiv(class="profile-bio"): tdiv(class="profile-bio"):
p: verbatim linkifyText(profile.bio) p: verbatim linkifyText(profile.bio, prefs)
if profile.location.len > 0: if profile.location.len > 0:
tdiv(class="profile-location"): tdiv(class="profile-location"):
@ -76,7 +76,7 @@ proc renderProfile*(profile: Profile; timeline: Timeline;
let sticky = if prefs.stickyProfile: "sticky" else: "unset" let sticky = if prefs.stickyProfile: "sticky" else: "unset"
tdiv(class="profile-tab", style={position: sticky}): tdiv(class="profile-tab", style={position: sticky}):
renderProfileCard(profile) renderProfileCard(profile, prefs)
if photoRail.len > 0: if photoRail.len > 0:
renderPhotoRail(profile, photoRail) renderPhotoRail(profile, photoRail)

View file

@ -92,7 +92,7 @@ proc renderPoll(poll: Poll): VNode =
proc renderCardImage(card: Card): VNode = proc renderCardImage(card: Card): VNode =
buildHtml(tdiv(class="card-image-container")): buildHtml(tdiv(class="card-image-container")):
tdiv(class="card-image"): tdiv(class="card-image"):
img(src=get(card.image).getSigUrl("pic")) img(src=getSigUrl(get(card.image), "pic"))
if card.kind == player: if card.kind == player:
tdiv(class="card-overlay"): tdiv(class="card-overlay"):
tdiv(class="card-overlay-circle"): 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: "" let large = if card.kind in largeCards: " large" else: ""
buildHtml(tdiv(class=("card" & large))): 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: if card.image.isSome:
renderCardImage(card) renderCardImage(card)
elif card.video.isSome: elif card.video.isSome:
@ -147,7 +147,7 @@ proc renderQuoteMedia(quote: Quote): VNode =
tdiv(class="quote-sensitive"): tdiv(class="quote-sensitive"):
icon "attention", class="quote-sensitive-icon" icon "attention", class="quote-sensitive-icon"
proc renderQuote(quote: Quote): VNode = proc renderQuote(quote: Quote; prefs: Prefs): VNode =
if not quote.available: if not quote.available:
return buildHtml(tdiv(class="quote unavailable")): return buildHtml(tdiv(class="quote unavailable")):
tdiv(class="unavailable-quote"): tdiv(class="unavailable-quote"):
@ -167,7 +167,7 @@ proc renderQuote(quote: Quote): VNode =
renderReply(quote) renderReply(quote)
tdiv(class="quote-text"): tdiv(class="quote-text"):
verbatim linkifyText(quote.text) verbatim linkifyText(quote.text, prefs)
if quote.hasThread: if quote.hasThread:
a(class="show-thread", href=getLink(quote)): a(class="show-thread", href=getLink(quote)):
@ -194,10 +194,10 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; class="";
renderReply(tweet) renderReply(tweet)
tdiv(class="status-content media-body"): tdiv(class="status-content media-body"):
verbatim linkifyText(tweet.text) verbatim linkifyText(tweet.text, prefs)
if tweet.quote.isSome: if tweet.quote.isSome:
renderQuote(tweet.quote.get()) renderQuote(tweet.quote.get(), prefs)
if tweet.card.isSome: if tweet.card.isSome:
renderCard(tweet.card.get(), prefs) renderCard(tweet.card.get(), prefs)