Fix tweets not loading

This commit is contained in:
Cynthia Foxwell 2025-03-20 11:42:34 -06:00
parent 6e86e086c3
commit c7d6b4291c
Signed by: Cynosphere
SSH key fingerprint: SHA256:H3SM8ufP/uxqLwKSH7xY89TDnbR9uOHzjLoBr0tlajk
4 changed files with 59 additions and 50 deletions

View file

@ -100,7 +100,7 @@ proc getGraphTweet(id: string; after=""): Future[Conversation] {.async.} =
let
cursor = if after.len > 0: "\"cursor\":\"$1\"," % after else: ""
variables = tweetVariables % [id, cursor]
params = {"variables": variables, "features": gqlFeatures}
params = {"variables": variables, "features": gqlFeatures, "fieldToggles": tweetFieldToggles}
js = await fetch(graphTweet ? params, Api.tweetDetail)
result = parseGraphConversation(js, id)

View file

@ -116,7 +116,8 @@ template fetchImpl(result, additional_headers, fetchBody) {.dirty.} =
#release(token, used=true)
if resp.status == $Http400:
raise newException(InternalError, $url)
let errText = "body: '" & result & "' url: " & $url
raise newException(InternalError, errText)
except InternalError as e:
raise e
except BadClientError as e:

View file

@ -20,7 +20,7 @@ const
graphUserTweets* = graphql / "3JNH4e9dq1BifLxAa3UMWg/UserWithProfileTweetsQueryV2"
graphUserTweetsAndReplies* = graphql / "8IS8MaO-2EN6GZZZb8jF0g/UserWithProfileTweetsAndRepliesQueryV2"
graphUserMedia* = graphql / "dexO_2tohK86JDudXXG3Yw/UserMedia"
graphTweet* = graphql / "q94uRCEn65LZThakYcPT6g/TweetDetail"
graphTweet* = graphql / "y90SwUGBZ3yz0yNUmCHgTw/TweetDetail"
graphTweetResult* = graphql / "sITyJdhRPpvpEjg4waUmTA/TweetResultByIdQuery"
graphSearchTimeline* = graphql / "gkjsKepM6gl_HmFWoWKfgg/SearchTimeline"
graphListById* = graphql / "iTpgCtbdxrsJfyx0cFjHqg/ListByRestId"
@ -95,30 +95,36 @@ const
"unified_cards_ad_metadata_container_dynamic_card_content_query_enabled": false,
"verified_phone_label_enabled": false,
"vibe_api_enabled": false,
"view_counts_everywhere_api_enabled": false
"view_counts_everywhere_api_enabled": false,
"premium_content_api_read_enabled": false,
"responsive_web_grok_analyze_button_fetch_trends_enabled": false,
"responsive_web_grok_analysis_button_from_backend": false,
"responsive_web_grok_analyze_post_followups_enabled": false,
"responsive_web_jetfuel_frame": false,
"profile_label_improvements_pcf_label_in_post_enabled": true,
"responsive_web_grok_image_annotation_enabled": false,
"responsive_web_grok_share_attachment_enabled": false,
"rweb_video_screen_enabled": false
}""".replace(" ", "").replace("\n", "")
tweetVariables* = """{
"focalTweetId": "$1",
$2
"includeHasBirdwatchNotes": false,
"with_rux_injections": false,
"rankingMode": "Relevance",
"includePromotedContent": false,
"withBirdwatchNotes": false,
"withVoice": false,
"withV2Timeline": true
"withCommunity": true,
"withQuickPromoteEligibilityTweetFields": false,
"withBirdwatchNotes": true,
"withVoice": true
}""".replace(" ", "").replace("\n", "")
# oldUserTweetsVariables* = """{
# "userId": "$1", $2
# "count": 20,
# "includePromotedContent": false,
# "withDownvotePerspective": false,
# "withReactionsMetadata": false,
# "withReactionsPerspective": false,
# "withVoice": false,
# "withV2Timeline": true
# }
# """.replace(" ", "").replace("\n", "")
tweetFieldToggles* = """{
"withArticleRichContentState": false,
"withArticlePlainText": true,
"withGrokAnalyze": false,
"withDisallowedReplyControls": false
}""".replace(" ", "").replace("\n", "")
userTweetsVariables* = """{
"rest_id": "$1",
@ -151,4 +157,4 @@ const
$2
"count": 20,
"includePromotedContent": false
}""".replace(" ", "").replace("\n", "")
}""".replace(" ", "").replace("\n", "")

View file

@ -505,39 +505,41 @@ proc parseGraphConversation*(js: JsonNode; tweetId: string): Conversation =
if instructions.len == 0:
return
for e in instructions[0]{"entries"}:
let entryId = e{"entryId"}.getStr
if entryId.startsWith("tweet"):
with tweetResult, e{"content", "itemContent", "tweet_results", "result"}:
let tweet = parseGraphTweet(tweetResult, true)
for i in instructions:
if i{"type"}.getStr == "TimelineAddEntries":
for e in i{"entries"}:
let entryId = e{"entryId"}.getStr
if entryId.startsWith("tweet"):
with tweetResult, e{"content", "itemContent", "tweet_results", "result"}:
let tweet = parseGraphTweet(tweetResult, true)
if not tweet.available:
tweet.id = parseBiggestInt(entryId.getId())
if not tweet.available:
tweet.id = parseBiggestInt(entryId.getId())
if $tweet.id == tweetId:
result.tweet = tweet
else:
result.before.content.add tweet
elif entryId.startsWith("tombstone"):
let id = entryId.getId()
let tweet = Tweet(
id: parseBiggestInt(id),
available: false,
text: e{"content", "itemContent", "tombstoneInfo", "richText"}.getTombstone
)
if $tweet.id == tweetId:
result.tweet = tweet
else:
result.before.content.add tweet
elif entryId.startsWith("tombstone"):
let id = entryId.getId()
let tweet = Tweet(
id: parseBiggestInt(id),
available: false,
text: e{"content", "itemContent", "tombstoneInfo", "richText"}.getTombstone
)
if id == tweetId:
result.tweet = tweet
else:
result.before.content.add tweet
elif entryId.startsWith("conversationthread") or entryId.startswith("reply-mixer-conversation"):
let (thread, self) = parseGraphThread(e)
if self:
result.after = thread
else:
result.replies.content.add thread
elif entryId.startsWith("cursor-bottom"):
result.replies.bottom = e{"content", "itemContent", "value"}.getStr
if id == tweetId:
result.tweet = tweet
else:
result.before.content.add tweet
elif entryId.startsWith("conversationthread") or entryId.startswith("reply-mixer-conversation"):
let (thread, self) = parseGraphThread(e)
if self:
result.after = thread
else:
result.replies.content.add thread
elif entryId.startsWith("cursor-bottom"):
result.replies.bottom = e{"content", "value"}.getStr
proc parseGraphTimeline*(js: JsonNode; root: string; after=""): Profile =
result = Profile(tweets: Timeline(beginning: after.len == 0))