Browse Source

Add Invidious/Nitter link replacement preferences

Zed 7 years ago
parent
commit
7dfbc16f4c
6 changed files with 41 additions and 16 deletions
  1. 13 1
      src/formatters.nim
  2. 2 1
      src/nitter.nim
  3. 12 2
      src/prefs.nim
  4. 5 3
      src/types.nim
  5. 3 3
      src/views/profile.nim
  6. 6 6
      src/views/tweet.nim

+ 13 - 1
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%])<a", "$1 <a")
   result = result.replace(re"</a>\s+([;.,!\)'%]|&apos;)", "</a>$1")
   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 =
   result = text

+ 2 - 1
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

+ 12 - 2
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

+ 5 - 3
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

+ 3 - 3
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)
 

+ 6 - 6
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)