Misc. fixes and refactorings
This commit is contained in:
		
							parent
							
								
									c736a98614
								
							
						
					
					
						commit
						5eec0bde3d
					
				| 
						 | 
					@ -169,13 +169,13 @@ proc getIntentStats*(profile: var Profile; node: XmlNode) =
 | 
				
			||||||
    of "following": profile.following = text
 | 
					    of "following": profile.following = text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseTweetStats*(node: XmlNode): TweetStats =
 | 
					proc parseTweetStats*(node: XmlNode): TweetStats =
 | 
				
			||||||
  result = TweetStats(replies: "0", retweets: "0", likes: "0")
 | 
					  result = TweetStats()
 | 
				
			||||||
  for action in node.selectAll(".ProfileTweet-actionCountForAria"):
 | 
					  for action in node.selectAll(".ProfileTweet-actionCountForAria"):
 | 
				
			||||||
    let text = action.innerText.split()
 | 
					    let text = action.innerText.split()
 | 
				
			||||||
    case text[1][0 .. 2]
 | 
					    case text[1][0 .. 2]
 | 
				
			||||||
    of "ret": result.retweets = text[0]
 | 
					    of "ret": result.retweets = text[0].parseInt
 | 
				
			||||||
    of "rep": result.replies = text[0]
 | 
					    of "rep": result.replies = text[0].parseInt
 | 
				
			||||||
    of "lik": result.likes = text[0]
 | 
					    of "lik": result.likes = text[0].parseInt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc parseTweetReply*(node: XmlNode): seq[string] =
 | 
					proc parseTweetReply*(node: XmlNode): seq[string] =
 | 
				
			||||||
  let reply = node.select(".ReplyingToContextBelowAuthor")
 | 
					  let reply = node.select(".ReplyingToContextBelowAuthor")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import jester
 | 
				
			||||||
import router_utils
 | 
					import router_utils
 | 
				
			||||||
import ".."/[api, types, agents]
 | 
					import ".."/[api, types, agents]
 | 
				
			||||||
import ../views/[embed]
 | 
					import ../views/[embed]
 | 
				
			||||||
 | 
					export getVideo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export embed
 | 
					export embed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import jester
 | 
				
			||||||
import router_utils
 | 
					import router_utils
 | 
				
			||||||
import ".."/[query, types, api, agents]
 | 
					import ".."/[query, types, api, agents]
 | 
				
			||||||
import ../views/[general, timeline, list]
 | 
					import ../views/[general, timeline, list]
 | 
				
			||||||
 | 
					export getListTimeline, getListMembers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template respList*(list, timeline: typed) =
 | 
					template respList*(list, timeline: typed) =
 | 
				
			||||||
  if list.minId.len == 0:
 | 
					  if list.minId.len == 0:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,9 @@ const m3u8Regex* = re"""url="(.+.m3u8)""""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc createMediaRouter*(cfg: Config) =
 | 
					proc createMediaRouter*(cfg: Config) =
 | 
				
			||||||
  router media:
 | 
					  router media:
 | 
				
			||||||
 | 
					    get "/pic/?":
 | 
				
			||||||
 | 
					      resp Http404
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get "/pic/@url":
 | 
					    get "/pic/@url":
 | 
				
			||||||
      cond "http" in @"url"
 | 
					      cond "http" in @"url"
 | 
				
			||||||
      cond "twimg" in @"url"
 | 
					      cond "twimg" in @"url"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import jester
 | 
				
			||||||
import router_utils
 | 
					import router_utils
 | 
				
			||||||
import ".."/[query, types, api, agents]
 | 
					import ".."/[query, types, api, agents]
 | 
				
			||||||
import ../views/general
 | 
					import ../views/general
 | 
				
			||||||
 | 
					export resolve
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template respResolved*(url, kind: string): untyped =
 | 
					template respResolved*(url, kind: string): untyped =
 | 
				
			||||||
  let u = url
 | 
					  let u = url
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,8 +87,9 @@ proc createTimelineRouter*(cfg: Config) =
 | 
				
			||||||
  setProfileCacheTime(cfg.profileCacheTime)
 | 
					  setProfileCacheTime(cfg.profileCacheTime)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  router timeline:
 | 
					  router timeline:
 | 
				
			||||||
    get "/@name/?@tab?":
 | 
					    get "/@name/?@tab?/?":
 | 
				
			||||||
      cond '.' notin @"name"
 | 
					      cond '.' notin @"name"
 | 
				
			||||||
 | 
					      cond @"name" notin ["pic", "gif", "video"]
 | 
				
			||||||
      cond @"tab" in ["with_replies", "media", "search", ""]
 | 
					      cond @"tab" in ["with_replies", "media", "search", ""]
 | 
				
			||||||
      let
 | 
					      let
 | 
				
			||||||
        prefs = cookiePrefs()
 | 
					        prefs = cookiePrefs()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,8 @@ type
 | 
				
			||||||
    tweetId*: string
 | 
					    tweetId*: string
 | 
				
			||||||
    color*: string
 | 
					    color*: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PhotoRail* = seq[GalleryPhoto]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Poll* = object
 | 
					  Poll* = object
 | 
				
			||||||
    options*: seq[string]
 | 
					    options*: seq[string]
 | 
				
			||||||
    values*: seq[int]
 | 
					    values*: seq[int]
 | 
				
			||||||
| 
						 | 
					@ -131,9 +133,9 @@ type
 | 
				
			||||||
    id*: int64
 | 
					    id*: int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TweetStats* = object
 | 
					  TweetStats* = object
 | 
				
			||||||
    replies*: string
 | 
					    replies*: int
 | 
				
			||||||
    retweets*: string
 | 
					    retweets*: int
 | 
				
			||||||
    likes*: string
 | 
					    likes*: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Tweet* = ref object
 | 
					  Tweet* = ref object
 | 
				
			||||||
    id*: int64
 | 
					    id*: int64
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ proc renderStat(num, class: string; text=""): VNode =
 | 
				
			||||||
  buildHtml(li(class=class)):
 | 
					  buildHtml(li(class=class)):
 | 
				
			||||||
    span(class="profile-stat-header"): text capitalizeAscii(t)
 | 
					    span(class="profile-stat-header"): text capitalizeAscii(t)
 | 
				
			||||||
    span(class="profile-stat-num"):
 | 
					    span(class="profile-stat-num"):
 | 
				
			||||||
      text if num.len == 0: "?" else: num
 | 
					      text if num.len == 0: "?" else: insertSep(num, ',')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode =
 | 
					proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="profile-card")):
 | 
					  buildHtml(tdiv(class="profile-card")):
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode =
 | 
				
			||||||
          renderStat(profile.followers, "followers")
 | 
					          renderStat(profile.followers, "followers")
 | 
				
			||||||
          renderStat(profile.likes, "likes")
 | 
					          renderStat(profile.likes, "likes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderPhotoRail(profile: Profile; photoRail: seq[GalleryPhoto]): VNode =
 | 
					proc renderPhotoRail(profile: Profile; photoRail: PhotoRail): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="photo-rail-card")):
 | 
					  buildHtml(tdiv(class="photo-rail-card")):
 | 
				
			||||||
    tdiv(class="photo-rail-header"):
 | 
					    tdiv(class="photo-rail-header"):
 | 
				
			||||||
      a(href=(&"/{profile.username}/media")):
 | 
					      a(href=(&"/{profile.username}/media")):
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ proc renderProtected(username: string): VNode =
 | 
				
			||||||
      p: text &"Only confirmed followers have access to @{username}'s tweets."
 | 
					      p: text &"Only confirmed followers have access to @{username}'s tweets."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderProfile*(profile: Profile; timeline: Timeline;
 | 
					proc renderProfile*(profile: Profile; timeline: Timeline;
 | 
				
			||||||
                    photoRail: seq[GalleryPhoto]; prefs: Prefs; path: string): VNode =
 | 
					                    photoRail: PhotoRail; prefs: Prefs; path: string): VNode =
 | 
				
			||||||
  timeline.query.fromUser = @[profile.username]
 | 
					  timeline.query.fromUser = @[profile.username]
 | 
				
			||||||
  buildHtml(tdiv(class="profile-tabs")):
 | 
					  buildHtml(tdiv(class="profile-tabs")):
 | 
				
			||||||
    if not prefs.hideBanner:
 | 
					    if not prefs.hideBanner:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ proc renderVideo*(video: Video; prefs: Prefs; path: string): VNode =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderGif(gif: Gif; prefs: Prefs): VNode =
 | 
					proc renderGif(gif: Gif; prefs: Prefs): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="attachments media-gif")):
 | 
					  buildHtml(tdiv(class="attachments media-gif")):
 | 
				
			||||||
    tdiv(class="gallery-gif", style=style(maxHeight, "unset")):
 | 
					    tdiv(class="gallery-gif", style={maxHeight: "unset"}):
 | 
				
			||||||
      tdiv(class="attachment"):
 | 
					      tdiv(class="attachment"):
 | 
				
			||||||
        let thumb = getPicUrl(gif.thumb)
 | 
					        let thumb = getPicUrl(gif.thumb)
 | 
				
			||||||
        let url = getGifUrl(gif.url)
 | 
					        let url = getGifUrl(gif.url)
 | 
				
			||||||
| 
						 | 
					@ -124,14 +124,16 @@ proc renderGif(gif: Gif; prefs: Prefs): VNode =
 | 
				
			||||||
proc renderPoll(poll: Poll): VNode =
 | 
					proc renderPoll(poll: Poll): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="poll")):
 | 
					  buildHtml(tdiv(class="poll")):
 | 
				
			||||||
    for i in 0 ..< poll.options.len:
 | 
					    for i in 0 ..< poll.options.len:
 | 
				
			||||||
      let leader = if poll.leader == i: " leader" else: ""
 | 
					      let
 | 
				
			||||||
      let perc = $poll.values[i] & "%"
 | 
					        leader = if poll.leader == i: " leader" else: ""
 | 
				
			||||||
 | 
					        perc = poll.values[i] / poll.votes * 100
 | 
				
			||||||
 | 
					        percStr = (&"{perc:>3.0f}").strip(chars={'.'}) & '%'
 | 
				
			||||||
      tdiv(class=("poll-meter" & leader)):
 | 
					      tdiv(class=("poll-meter" & leader)):
 | 
				
			||||||
        span(class="poll-choice-bar", style=style(width, perc))
 | 
					        span(class="poll-choice-bar", style={width: percStr})
 | 
				
			||||||
        span(class="poll-choice-value"): text perc
 | 
					        span(class="poll-choice-value"): text percStr
 | 
				
			||||||
        span(class="poll-choice-option"): text poll.options[i]
 | 
					        span(class="poll-choice-option"): text poll.options[i]
 | 
				
			||||||
    span(class="poll-info"):
 | 
					    span(class="poll-info"):
 | 
				
			||||||
      text $poll.votes & " votes • " & poll.status
 | 
					      text insertSep($poll.votes, ',') & " votes • " & poll.status
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderCardImage(card: Card): VNode =
 | 
					proc renderCardImage(card: Card): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="card-image-container")):
 | 
					  buildHtml(tdiv(class="card-image-container")):
 | 
				
			||||||
| 
						 | 
					@ -169,11 +171,11 @@ proc renderCard(card: Card; prefs: Prefs; path: string): VNode =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderStats(stats: TweetStats; views: string): VNode =
 | 
					proc renderStats(stats: TweetStats; views: string): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="tweet-stats")):
 | 
					  buildHtml(tdiv(class="tweet-stats")):
 | 
				
			||||||
    span(class="tweet-stat"): icon "comment", $stats.replies
 | 
					    span(class="tweet-stat"): icon "comment", insertSep($stats.replies, ',')
 | 
				
			||||||
    span(class="tweet-stat"): icon "retweet", $stats.retweets
 | 
					    span(class="tweet-stat"): icon "retweet", insertSep($stats.retweets, ',')
 | 
				
			||||||
    span(class="tweet-stat"): icon "heart", $stats.likes
 | 
					    span(class="tweet-stat"): icon "heart", insertSep($stats.likes, ',')
 | 
				
			||||||
    if views.len > 0:
 | 
					    if views.len > 0:
 | 
				
			||||||
      span(class="tweet-stat"): icon "play", views
 | 
					      span(class="tweet-stat"): icon "play", insertSep(views, ',')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
proc renderReply(tweet: Tweet): VNode =
 | 
					proc renderReply(tweet: Tweet): VNode =
 | 
				
			||||||
  buildHtml(tdiv(class="replying-to")):
 | 
					  buildHtml(tdiv(class="replying-to")):
 | 
				
			||||||
| 
						 | 
					@ -279,7 +281,8 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
 | 
				
			||||||
      var views = ""
 | 
					      var views = ""
 | 
				
			||||||
      renderHeader(tweet)
 | 
					      renderHeader(tweet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if index == 0 and tweet.reply.len > 0:
 | 
					      if index == 0 and tweet.reply.len > 0 and
 | 
				
			||||||
 | 
					         (tweet.reply.len > 1 or tweet.reply[0] != tweet.profile.username):
 | 
				
			||||||
        renderReply(tweet)
 | 
					        renderReply(tweet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      tdiv(class="tweet-content media-body", dir="auto"):
 | 
					      tdiv(class="tweet-content media-body", dir="auto"):
 | 
				
			||||||
| 
						 | 
					@ -288,9 +291,6 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
 | 
				
			||||||
      if tweet.attribution.isSome:
 | 
					      if tweet.attribution.isSome:
 | 
				
			||||||
        renderAttribution(tweet.attribution.get())
 | 
					        renderAttribution(tweet.attribution.get())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if tweet.quote.isSome:
 | 
					 | 
				
			||||||
        renderQuote(tweet.quote.get(), prefs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if tweet.card.isSome:
 | 
					      if tweet.card.isSome:
 | 
				
			||||||
        renderCard(tweet.card.get(), prefs, path)
 | 
					        renderCard(tweet.card.get(), prefs, path)
 | 
				
			||||||
      elif tweet.photos.len > 0:
 | 
					      elif tweet.photos.len > 0:
 | 
				
			||||||
| 
						 | 
					@ -304,6 +304,9 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
 | 
				
			||||||
      elif tweet.poll.isSome:
 | 
					      elif tweet.poll.isSome:
 | 
				
			||||||
        renderPoll(tweet.poll.get())
 | 
					        renderPoll(tweet.poll.get())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if tweet.quote.isSome:
 | 
				
			||||||
 | 
					        renderQuote(tweet.quote.get(), prefs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if mainTweet:
 | 
					      if mainTweet:
 | 
				
			||||||
        p(class="tweet-published"): text getTweetTime(tweet)
 | 
					        p(class="tweet-published"): text getTweetTime(tweet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ class ProfileTest(BaseTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_suspended(self):
 | 
					    def test_suspended(self):
 | 
				
			||||||
        self.open_nitter('test')
 | 
					        self.open_nitter('test')
 | 
				
			||||||
        self.assert_text(f'User "test" has been suspended')
 | 
					        self.assert_text('User "test" has been suspended')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @parameterized.expand(banner_color)
 | 
					    @parameterized.expand(banner_color)
 | 
				
			||||||
    def test_banner_color(self, username, color):
 | 
					    def test_banner_color(self, username, color):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue