Преглед изворни кода

Misc. fixes and refactorings

Zed пре 6 година
родитељ
комит
5eec0bde3d

+ 4 - 4
src/parserutils.nim

@@ -169,13 +169,13 @@ proc getIntentStats*(profile: var Profile; node: XmlNode) =
     of "following": profile.following = text
 
 proc parseTweetStats*(node: XmlNode): TweetStats =
-  result = TweetStats(replies: "0", retweets: "0", likes: "0")
+  result = TweetStats()
   for action in node.selectAll(".ProfileTweet-actionCountForAria"):
     let text = action.innerText.split()
     case text[1][0 .. 2]
-    of "ret": result.retweets = text[0]
-    of "rep": result.replies = text[0]
-    of "lik": result.likes = text[0]
+    of "ret": result.retweets = text[0].parseInt
+    of "rep": result.replies = text[0].parseInt
+    of "lik": result.likes = text[0].parseInt
 
 proc parseTweetReply*(node: XmlNode): seq[string] =
   let reply = node.select(".ReplyingToContextBelowAuthor")

+ 1 - 0
src/routes/embed.nim

@@ -5,6 +5,7 @@ import jester
 import router_utils
 import ".."/[api, types, agents]
 import ../views/[embed]
+export getVideo
 
 export embed
 

+ 1 - 0
src/routes/list.nim

@@ -5,6 +5,7 @@ import jester
 import router_utils
 import ".."/[query, types, api, agents]
 import ../views/[general, timeline, list]
+export getListTimeline, getListMembers
 
 template respList*(list, timeline: typed) =
   if list.minId.len == 0:

+ 3 - 0
src/routes/media.nim

@@ -13,6 +13,9 @@ const m3u8Regex* = re"""url="(.+.m3u8)""""
 
 proc createMediaRouter*(cfg: Config) =
   router media:
+    get "/pic/?":
+      resp Http404
+
     get "/pic/@url":
       cond "http" in @"url"
       cond "twimg" in @"url"

+ 1 - 0
src/routes/resolver.nim

@@ -5,6 +5,7 @@ import jester
 import router_utils
 import ".."/[query, types, api, agents]
 import ../views/general
+export resolve
 
 template respResolved*(url, kind: string): untyped =
   let u = url

+ 2 - 1
src/routes/timeline.nim

@@ -87,8 +87,9 @@ proc createTimelineRouter*(cfg: Config) =
   setProfileCacheTime(cfg.profileCacheTime)
 
   router timeline:
-    get "/@name/?@tab?":
+    get "/@name/?@tab?/?":
       cond '.' notin @"name"
+      cond @"name" notin ["pic", "gif", "video"]
       cond @"tab" in ["with_replies", "media", "search", ""]
       let
         prefs = cookiePrefs()

+ 5 - 3
src/types.nim

@@ -87,6 +87,8 @@ type
     tweetId*: string
     color*: string
 
+  PhotoRail* = seq[GalleryPhoto]
+
   Poll* = object
     options*: seq[string]
     values*: seq[int]
@@ -131,9 +133,9 @@ type
     id*: int64
 
   TweetStats* = object
-    replies*: string
-    retweets*: string
-    likes*: string
+    replies*: int
+    retweets*: int
+    likes*: int
 
   Tweet* = ref object
     id*: int64

+ 3 - 3
src/views/profile.nim

@@ -9,7 +9,7 @@ proc renderStat(num, class: string; text=""): VNode =
   buildHtml(li(class=class)):
     span(class="profile-stat-header"): text capitalizeAscii(t)
     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 =
   buildHtml(tdiv(class="profile-card")):
@@ -57,7 +57,7 @@ proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode =
           renderStat(profile.followers, "followers")
           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")):
     tdiv(class="photo-rail-header"):
       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."
 
 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]
   buildHtml(tdiv(class="profile-tabs")):
     if not prefs.hideBanner:

+ 17 - 14
src/views/tweet.nim

@@ -110,7 +110,7 @@ proc renderVideo*(video: Video; prefs: Prefs; path: string): VNode =
 
 proc renderGif(gif: Gif; prefs: Prefs): VNode =
   buildHtml(tdiv(class="attachments media-gif")):
-    tdiv(class="gallery-gif", style=style(maxHeight, "unset")):
+    tdiv(class="gallery-gif", style={maxHeight: "unset"}):
       tdiv(class="attachment"):
         let thumb = getPicUrl(gif.thumb)
         let url = getGifUrl(gif.url)
@@ -124,14 +124,16 @@ proc renderGif(gif: Gif; prefs: Prefs): VNode =
 proc renderPoll(poll: Poll): VNode =
   buildHtml(tdiv(class="poll")):
     for i in 0 ..< poll.options.len:
-      let leader = if poll.leader == i: " leader" else: ""
-      let perc = $poll.values[i] & "%"
+      let
+        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)):
-        span(class="poll-choice-bar", style=style(width, perc))
-        span(class="poll-choice-value"): text perc
+        span(class="poll-choice-bar", style={width: percStr})
+        span(class="poll-choice-value"): text percStr
         span(class="poll-choice-option"): text poll.options[i]
     span(class="poll-info"):
-      text $poll.votes & " votes • " & poll.status
+      text insertSep($poll.votes, ',') & " votes • " & poll.status
 
 proc renderCardImage(card: Card): VNode =
   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 =
   buildHtml(tdiv(class="tweet-stats")):
-    span(class="tweet-stat"): icon "comment", $stats.replies
-    span(class="tweet-stat"): icon "retweet", $stats.retweets
-    span(class="tweet-stat"): icon "heart", $stats.likes
+    span(class="tweet-stat"): icon "comment", insertSep($stats.replies, ',')
+    span(class="tweet-stat"): icon "retweet", insertSep($stats.retweets, ',')
+    span(class="tweet-stat"): icon "heart", insertSep($stats.likes, ',')
     if views.len > 0:
-      span(class="tweet-stat"): icon "play", views
+      span(class="tweet-stat"): icon "play", insertSep(views, ',')
 
 proc renderReply(tweet: Tweet): VNode =
   buildHtml(tdiv(class="replying-to")):
@@ -279,7 +281,8 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
       var views = ""
       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)
 
       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:
         renderAttribution(tweet.attribution.get())
 
-      if tweet.quote.isSome:
-        renderQuote(tweet.quote.get(), prefs)
-
       if tweet.card.isSome:
         renderCard(tweet.card.get(), prefs, path)
       elif tweet.photos.len > 0:
@@ -304,6 +304,9 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
       elif tweet.poll.isSome:
         renderPoll(tweet.poll.get())
 
+      if tweet.quote.isSome:
+        renderQuote(tweet.quote.get(), prefs)
+
       if mainTweet:
         p(class="tweet-published"): text getTweetTime(tweet)
 

+ 1 - 1
tests/test_profile.py

@@ -72,7 +72,7 @@ class ProfileTest(BaseTestCase):
 
     def test_suspended(self):
         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)
     def test_banner_color(self, username, color):