mirror of https://github.com/zedeus/nitter
Replace old pinned tweet endpoint with GraphQL
This commit is contained in:
parent
bed060f052
commit
5676ecc1f2
12
src/api.nim
12
src/api.nim
|
@ -69,6 +69,14 @@ proc getGraphListMembers*(list: List; after=""): Future[Result[User]] {.async.}
|
|||
let url = graphListMembers ? {"variables": $variables, "features": gqlFeatures}
|
||||
result = parseGraphListMembers(await fetchRaw(url, Api.listMembers), after)
|
||||
|
||||
proc getGraphTweetResult*(id: string): Future[Tweet] {.async.} =
|
||||
if id.len == 0: return
|
||||
let
|
||||
variables = tweetResultVariables % id
|
||||
params = {"variables": variables, "features": gqlFeatures}
|
||||
js = await fetch(graphTweetResult ? params, Api.tweetResult)
|
||||
result = parseGraphTweetResult(js)
|
||||
|
||||
proc getGraphTweet(id: string; after=""): Future[Conversation] {.async.} =
|
||||
if id.len == 0: return
|
||||
let
|
||||
|
@ -87,10 +95,6 @@ proc getTweet*(id: string; after=""): Future[Conversation] {.async.} =
|
|||
if after.len > 0:
|
||||
result.replies = await getReplies(id, after)
|
||||
|
||||
proc getStatus*(id: string): Future[Tweet] {.async.} =
|
||||
let url = status / (id & ".json") ? genParams()
|
||||
result = parseStatus(await fetch(url, Api.status))
|
||||
|
||||
proc getPhotoRail*(name: string): Future[PhotoRail] {.async.} =
|
||||
if name.len == 0: return
|
||||
let
|
||||
|
|
|
@ -12,12 +12,13 @@ const
|
|||
search* = api / "2/search/adaptive.json"
|
||||
|
||||
graphql = api / "graphql"
|
||||
graphUser* = graphql / "8mPfHBetXOg-EHAyeVxUoA/UserByScreenName"
|
||||
graphUserById* = graphql / "nI8WydSd-X-lQIVo6bdktQ/UserByRestId"
|
||||
graphUserTweets* = graphql / "9rys0A7w1EyqVd2ME0QCJg/UserTweets"
|
||||
graphUserTweetsAndReplies* = graphql / "ehMCHF3Mkgjsfz_aImqOsg/UserTweetsAndReplies"
|
||||
graphUserMedia* = graphql / "MA_EP2a21zpzNWKRkaPBMg/UserMedia"
|
||||
graphTweet* = graphql / "6I7Hm635Q6ftv69L8VrSeQ/TweetDetail"
|
||||
graphUser* = graphql / "8mPfHBetXOg-EHAyeVxUoA/UserByScreenName"
|
||||
graphUserById* = graphql / "nI8WydSd-X-lQIVo6bdktQ/UserByRestId"
|
||||
graphTweetResult* = graphql / "rt-rHeSJ-2H9O9gxWQcPcg/TweetResultByRestId"
|
||||
graphListById* = graphql / "iTpgCtbdxrsJfyx0cFjHqg/ListByRestId"
|
||||
graphListBySlug* = graphql / "-kmqNvm5Y-cVrfvBy6docg/ListBySlug"
|
||||
graphListMembers* = graphql / "P4NpVZDqUD_7MEM84L-8nw/ListMembers"
|
||||
|
@ -91,6 +92,16 @@ const
|
|||
"withVoice": false
|
||||
}"""
|
||||
|
||||
tweetResultVariables* = """{
|
||||
"tweetId": "$1",
|
||||
"includePromotedContent": false,
|
||||
"withDownvotePerspective": false,
|
||||
"withReactionsMetadata": false,
|
||||
"withReactionsPerspective": false,
|
||||
"withVoice": false,
|
||||
"withCommunity": false
|
||||
}"""
|
||||
|
||||
userTweetsVariables* = """{
|
||||
"userId": "$1", $2
|
||||
"count": 20,
|
||||
|
|
|
@ -317,19 +317,6 @@ proc parseGlobalObjects(js: JsonNode): GlobalObjects =
|
|||
tweet.user = result.users[tweet.user.id]
|
||||
result.tweets[k] = tweet
|
||||
|
||||
proc parseStatus*(js: JsonNode): Tweet =
|
||||
with e, js{"errors"}:
|
||||
if e.getError in {tweetNotFound, tweetUnavailable, tweetCensored, doesntExist,
|
||||
tweetNotAuthorized, suspended}:
|
||||
return
|
||||
|
||||
result = parseTweet(js, js{"card"})
|
||||
if not result.isNil:
|
||||
result.user = parseUser(js{"user"})
|
||||
|
||||
with quote, js{"quoted_status"}:
|
||||
result.quote = some parseStatus(js{"quoted_status"})
|
||||
|
||||
proc parseInstructions[T](res: var Result[T]; global: GlobalObjects; js: JsonNode) =
|
||||
if js.kind != JArray or js.len == 0:
|
||||
return
|
||||
|
@ -425,6 +412,10 @@ proc parseGraphThread(js: JsonNode): tuple[thread: Chain; self: bool] =
|
|||
if t{"item", "itemContent", "tweetDisplayType"}.getStr == "SelfThread":
|
||||
result.self = true
|
||||
|
||||
proc parseGraphTweetResult*(js: JsonNode): Tweet =
|
||||
with tweet, js{"data", "tweetResult", "result"}:
|
||||
result = parseGraphTweet(tweet)
|
||||
|
||||
proc parseGraphConversation*(js: JsonNode; tweetId: string): Conversation =
|
||||
result = Conversation(replies: Result[Chain](beginning: true))
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ proc getCachedTweet*(id: int64): Future[Tweet] {.async.} =
|
|||
if tweet != redisNil:
|
||||
tweet.deserialize(Tweet)
|
||||
else:
|
||||
result = await getStatus($id)
|
||||
result = await getGraphTweetResult($id)
|
||||
if not result.isNil:
|
||||
await cache(result)
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ proc getPoolJson*(): JsonNode =
|
|||
let
|
||||
maxReqs =
|
||||
case api
|
||||
of Api.status: 180
|
||||
of Api.search: 250
|
||||
of Api.timeline: 187
|
||||
of Api.listMembers, Api.listBySlug, Api.list, Api.listTweets,
|
||||
Api.userTweets, Api.userTweetsAndReplies, Api.userMedia,
|
||||
Api.userRestId, Api.userScreenName, Api.tweetDetail: 500
|
||||
Api.userRestId, Api.userScreenName,
|
||||
Api.tweetDetail, Api.tweetResult: 500
|
||||
reqs = maxReqs - token.apis[api].remaining
|
||||
|
||||
reqsPerApi[$api] = reqsPerApi.getOrDefault($api, 0) + reqs
|
||||
|
|
|
@ -15,6 +15,7 @@ type
|
|||
|
||||
Api* {.pure.} = enum
|
||||
tweetDetail
|
||||
tweetResult
|
||||
timeline
|
||||
search
|
||||
list
|
||||
|
@ -26,7 +27,6 @@ type
|
|||
userTweets
|
||||
userTweetsAndReplies
|
||||
userMedia
|
||||
status
|
||||
|
||||
RateLimit* = object
|
||||
remaining*: int
|
||||
|
|
Loading…
Reference in New Issue