added feature to view who a user follows or is followed by (won't compile because of a compiler bug)

This commit is contained in:
PrivacyDev 2023-06-05 22:38:17 -04:00
parent 1150a59e38
commit 2ce3ee6d84
8 changed files with 72 additions and 34 deletions

View file

@ -3,7 +3,6 @@ import asyncdispatch, httpclient, uri, strutils, sequtils, sugar
import packedjson import packedjson
import types, query, formatters, consts, apiutils, parser import types, query, formatters, consts, apiutils, parser
import experimental/parser as newParser import experimental/parser as newParser
import config
proc getGraphUser*(username: string): Future[User] {.async.} = proc getGraphUser*(username: string): Future[User] {.async.} =
if username.len == 0: return if username.len == 0: return
@ -112,6 +111,24 @@ proc getGraphRetweeters*(id: string; after=""): Future[UsersTimeline] {.async.}
js = await fetch(graphRetweeters ? params, Api.retweeters) js = await fetch(graphRetweeters ? params, Api.retweeters)
result = parseGraphRetweetersTimeline(js, id) result = parseGraphRetweetersTimeline(js, id)
proc getGraphFollowing*(id: string; after=""): Future[UsersTimeline] {.async.} =
if id.len == 0: return
let
cursor = if after.len > 0: "\"cursor\":\"$1\"," % after else: ""
variables = followVariables % [id, cursor]
params = {"variables": variables, "features": gqlFeatures}
js = await fetch(graphFollowing ? params, Api.following)
result = parseGraphFollowTimeline(js, id)
proc getGraphFollowers*(id: string; after=""): Future[UsersTimeline] {.async.} =
if id.len == 0: return
let
cursor = if after.len > 0: "\"cursor\":\"$1\"," % after else: ""
variables = followVariables % [id, cursor]
params = {"variables": variables, "features": gqlFeatures}
js = await fetch(graphFollowers ? params, Api.followers)
result = parseGraphFollowTimeline(js, id)
proc getReplies*(id, after: string): Future[Result[Chain]] {.async.} = proc getReplies*(id, after: string): Future[Result[Chain]] {.async.} =
result = (await getGraphTweet(id, after)).replies result = (await getGraphTweet(id, after)).replies
result.beginning = after.len == 0 result.beginning = after.len == 0

View file

@ -28,6 +28,8 @@ const
graphListTweets* = graphql / "jZntL0oVJSdjhmPcdbw_eA/ListLatestTweetsTimeline" graphListTweets* = graphql / "jZntL0oVJSdjhmPcdbw_eA/ListLatestTweetsTimeline"
graphFavoriters* = graphql / "mDc_nU8xGv0cLRWtTaIEug/Favoriters" graphFavoriters* = graphql / "mDc_nU8xGv0cLRWtTaIEug/Favoriters"
graphRetweeters* = graphql / "RCR9gqwYD1NEgi9FWzA50A/Retweeters" graphRetweeters* = graphql / "RCR9gqwYD1NEgi9FWzA50A/Retweeters"
graphFollowers* = graphql / "EAqBhgcGr_qPOzhS4Q3scQ/Followers"
graphFollowing* = graphql / "JPZiqKjET7_M1r5Tlr8pyA/Following"
timelineParams* = { timelineParams* = {
"include_profile_interstitial_type": "0", "include_profile_interstitial_type": "0",
@ -129,3 +131,9 @@ const
"count" : 20, "count" : 20,
"includePromotedContent": false "includePromotedContent": false
}""" }"""
followVariables* = """{
"userId" : "$1", $2
"count" : 20,
"includePromotedContent": false
}"""

View file

@ -498,10 +498,10 @@ proc parseGraphTimeline*(js: JsonNode; root: string; after=""): Timeline =
elif entryId.startsWith("cursor-bottom"): elif entryId.startsWith("cursor-bottom"):
result.bottom = e{"content", "value"}.getStr result.bottom = e{"content", "value"}.getStr
proc parseGraphUsersTimeline(js: JsonNode; root: string; key: string; after=""): UsersTimeline = proc parseGraphUsersTimeline(timeline: JsonNode; after=""): UsersTimeline =
result = UsersTimeline(beginning: after.len == 0) result = UsersTimeline(beginning: after.len == 0)
let instructions = ? js{"data", key, "timeline", "instructions"} let instructions = ? timeline{"instructions"}
if instructions.len == 0: if instructions.len == 0:
return return
@ -520,10 +520,13 @@ proc parseGraphUsersTimeline(js: JsonNode; root: string; key: string; after=""):
result.top = e{"content", "value"}.getStr result.top = e{"content", "value"}.getStr
proc parseGraphFavoritersTimeline*(js: JsonNode; root: string; after=""): UsersTimeline = proc parseGraphFavoritersTimeline*(js: JsonNode; root: string; after=""): UsersTimeline =
return parseGraphUsersTimeline(js, root, "favoriters_timeline", after) return parseGraphUsersTimeline(js{"data", "favoriters_timeline", "timeline"}, after)
proc parseGraphRetweetersTimeline*(js: JsonNode; root: string; after=""): UsersTimeline = proc parseGraphRetweetersTimeline*(js: JsonNode; root: string; after=""): UsersTimeline =
return parseGraphUsersTimeline(js, root, "retweeters_timeline", after) return parseGraphUsersTimeline(js{"data", "retweeters_timeline", "timeline"}, after)
proc parseGraphFollowTimeline*(js: JsonNode; root: string; after=""): UsersTimeline =
return parseGraphUsersTimeline(js{"data", "user", "result", "timeline", "timeline"}, after)
proc parseGraphSearch*(js: JsonNode; after=""): Timeline = proc parseGraphSearch*(js: JsonNode; after=""): Timeline =
result = Timeline(beginning: after.len == 0) result = Timeline(beginning: after.len == 0)

View file

@ -5,7 +5,7 @@ import jester, karax/vdom
import router_utils import router_utils
import ".."/[types, formatters, api] import ".."/[types, formatters, api]
import ../views/[general, status, timeline, search] import ../views/[general, status, search]
export uri, sequtils, options, sugar export uri, sequtils, options, sugar
export router_utils export router_utils

View file

@ -127,12 +127,18 @@ proc createTimelineRouter*(cfg: Config) =
get "/@name/?@tab?/?": get "/@name/?@tab?/?":
cond '.' notin @"name" cond '.' notin @"name"
cond @"name" notin ["pic", "gif", "video", "search", "settings", "login", "intent", "i"] cond @"name" notin ["pic", "gif", "video", "search", "settings", "login", "intent", "i"]
cond @"tab" in ["with_replies", "media", "search", "favorites", ""] cond @"tab" in ["with_replies", "media", "search", "favorites", "following", "followers", ""]
let let
prefs = cookiePrefs() prefs = cookiePrefs()
after = getCursor() after = getCursor()
names = getNames(@"name") names = getNames(@"name")
case @"tab":
of "followers":
resp renderMain(renderUserList(await getGraphFollowers(await getUserId(@"name"), getCursor()), prefs), request, cfg, prefs)
of "following":
resp renderMain(renderUserList(await getGraphFollowing(await getUserId(@"name"), getCursor()), prefs), request, cfg, prefs)
else:
var query = request.getQuery(@"tab", @"name") var query = request.getQuery(@"tab", @"name")
if names.len != 1: if names.len != 1:
query.fromUser = names query.fromUser = names

View file

@ -32,6 +32,8 @@ type
userMedia userMedia
favoriters favoriters
retweeters retweeters
following
followers
RateLimit* = object RateLimit* = object
remaining*: int remaining*: int

View file

@ -59,7 +59,9 @@ proc renderUserCard*(user: User; prefs: Prefs): VNode =
tdiv(class="profile-card-extra-links"): tdiv(class="profile-card-extra-links"):
ul(class="profile-statlist"): ul(class="profile-statlist"):
renderStat(user.tweets, "posts", text="Tweets") renderStat(user.tweets, "posts", text="Tweets")
a(href="/" & user.username & "/following"):
renderStat(user.following, "following") renderStat(user.following, "following")
a(href="/" & user.username & "/followers"):
renderStat(user.followers, "followers") renderStat(user.followers, "followers")
renderStat(user.likes, "likes") renderStat(user.likes, "likes")