Add Invidious/Nitter link replacement preferences
This commit is contained in:
		
							parent
							
								
									93da24be85
								
							
						
					
					
						commit
						7dfbc16f4c
					
				| 
						 | 
				
			
			@ -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+([;.,!\)'%]|')", "</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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue