瀏覽代碼

Update endpoint versions, switch tweet endpoint

Zed 1 年之前
父節點
當前提交
81764ea0f8
共有 3 個文件被更改,包括 48 次插入29 次删除
  1. 1 1
      src/auth.nim
  2. 30 16
      src/consts.nim
  3. 17 12
      src/parser.nim

+ 1 - 1
src/auth.nim

@@ -9,7 +9,7 @@ const
   dayInSeconds = 24 * 60 * 60
   apiMaxReqs: Table[Api, int] = {
     Api.search: 50,
-    Api.tweetDetail: 150,
+    Api.tweetDetail: 500,
     Api.userTweets: 500,
     Api.userTweetsAndReplies: 500,
     Api.userMedia: 500,

+ 30 - 16
src/consts.nim

@@ -5,22 +5,20 @@ const
   consumerKey* = "3nVuSoBZnx6U4vzUxf5w"
   consumerSecret* = "Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys"
 
-  api = parseUri("https://api.twitter.com")
-  activate* = $(api / "1.1/guest/activate.json")
+  gql = parseUri("https://api.x.com") / "graphql"
 
-  graphql = api / "graphql"
-  graphUser* = graphql / "u7wQyGi6oExe8_TRWGMq4Q/UserResultByScreenNameQuery"
-  graphUserById* = graphql / "oPppcargziU1uDQHAUmH-A/UserResultByIdQuery"
-  graphUserTweets* = graphql / "3JNH4e9dq1BifLxAa3UMWg/UserWithProfileTweetsQueryV2"
-  graphUserTweetsAndReplies* = graphql / "8IS8MaO-2EN6GZZZb8jF0g/UserWithProfileTweetsAndRepliesQueryV2"
-  graphUserMedia* = graphql / "PDfFf8hGeJvUCiTyWtw4wQ/MediaTimelineV2"
-  graphTweet* = graphql / "q94uRCEn65LZThakYcPT6g/TweetDetail"
-  graphTweetResult* = graphql / "sITyJdhRPpvpEjg4waUmTA/TweetResultByIdQuery"
-  graphSearchTimeline* = graphql / "gkjsKepM6gl_HmFWoWKfgg/SearchTimeline"
-  graphListById* = graphql / "iTpgCtbdxrsJfyx0cFjHqg/ListByRestId"
-  graphListBySlug* = graphql / "-kmqNvm5Y-cVrfvBy6docg/ListBySlug"
-  graphListMembers* = graphql / "P4NpVZDqUD_7MEM84L-8nw/ListMembers"
-  graphListTweets* = graphql / "BbGLL1ZfMibdFNWlk7a0Pw/ListTimeline"
+  graphUser* = gql / "u7wQyGi6oExe8_TRWGMq4Q/UserResultByScreenNameQuery"
+  graphUserById* = gql / "oPppcargziU1uDQHAUmH-A/UserResultByIdQuery"
+  graphUserTweets* = gql / "JLApJKFY0MxGTzCoK6ps8Q/UserWithProfileTweetsQueryV2"
+  graphUserTweetsAndReplies* = gql / "Y86LQY7KMvxn5tu3hFTyPg/UserWithProfileTweetsAndRepliesQueryV2"
+  graphUserMedia* = gql / "PDfFf8hGeJvUCiTyWtw4wQ/MediaTimelineV2"
+  graphTweet* = gql / "Vorskcd2tZ-tc4Gx3zbk4Q/ConversationTimelineV2"
+  graphTweetResult* = gql / "sITyJdhRPpvpEjg4waUmTA/TweetResultByIdQuery"
+  graphSearchTimeline* = gql / "KI9jCXUx3Ymt-hDKLOZb9Q/SearchTimeline"
+  graphListById* = gql / "oygmAig8kjn0pKsx_bUadQ/ListByRestId"
+  graphListBySlug* = gql / "88GTz-IPPWLn1EiU8XoNVg/ListBySlug"
+  graphListMembers* = gql / "kSmxeqEeelqdHSR7jMnb_w/ListMembers"
+  graphListTweets* = gql / "BbGLL1ZfMibdFNWlk7a0Pw/ListTimeline"
 
   gqlFeatures* = """{
   "android_graphql_skip_api_media_color_palette": false,
@@ -62,7 +60,23 @@ 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,
+  "communities_web_enable_tweet_community_results_fetch": false,
+  "responsive_web_jetfuel_frame": false,
+  "responsive_web_grok_analyze_button_fetch_trends_enabled": false,
+  "responsive_web_grok_image_annotation_enabled": false,
+  "rweb_tipjar_consumption_enabled": false,
+  "profile_label_improvements_pcf_label_in_post_enabled": false,
+  "creator_subscriptions_quote_tweet_preview_enabled": false,
+  "c9s_tweet_anatomy_moderator_badge_enabled": false,
+  "responsive_web_grok_analyze_post_followups_enabled": false,
+  "rweb_video_timestamps_enabled": false,
+  "responsive_web_grok_share_attachment_enabled": false,
+  "articles_preview_enabled": false,
+  "immersive_video_status_linkable_timestamps": false,
+  "articles_api_enabled": false,
+  "responsive_web_grok_analysis_button_from_backend": false
 }""".replace(" ", "").replace("\n", "")
 
   tweetVariables* = """{

+ 17 - 12
src/parser.nim

@@ -352,18 +352,23 @@ proc parseGraphTweetResult*(js: JsonNode): Tweet =
   with tweet, js{"data", "tweet_result", "result"}:
     result = parseGraphTweet(tweet, false)
 
-proc parseGraphConversation*(js: JsonNode; tweetId: string): Conversation =
+proc parseGraphConversation*(js: JsonNode; tweetId: string; v2=true): Conversation =
   result = Conversation(replies: Result[Chain](beginning: true))
 
-  let instructions = ? js{"data", "threaded_conversation_with_injections_v2", "instructions"}
+  let
+    rootKey = if v2: "timeline_response" else: "threaded_conversation_with_injections_v2"
+    contentKey = if v2: "content" else: "itemContent"
+    resultKey = if v2: "tweetResult" else: "tweet_results"
+
+  let instructions = ? js{"data", rootKey, "instructions"}
   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)
+      with tweetResult, e{"content", contentKey, resultKey, "result"}:
+        let tweet = parseGraphTweet(tweetResult, not v2)
 
         if not tweet.available:
           tweet.id = parseBiggestInt(entryId.getId())
@@ -372,26 +377,26 @@ proc parseGraphConversation*(js: JsonNode; tweetId: string): Conversation =
           result.tweet = tweet
         else:
           result.before.content.add tweet
+    elif entryId.startsWith("conversationthread"):
+      let (thread, self) = parseGraphThread(e)
+      if self:
+        result.after = thread
+      else:
+        result.replies.content.add thread
     elif entryId.startsWith("tombstone"):
       let id = entryId.getId()
       let tweet = Tweet(
         id: parseBiggestInt(id),
         available: false,
-        text: e{"content", "itemContent", "tombstoneInfo", "richText"}.getTombstone
+        text: e{"content", contentKey, "tombstoneInfo", "richText"}.getTombstone
       )
 
       if id == tweetId:
         result.tweet = tweet
       else:
         result.before.content.add tweet
-    elif entryId.startsWith("conversationthread"):
-      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
+      result.replies.bottom = e{"content", contentKey, "value"}.getStr
 
 proc parseGraphTimeline*(js: JsonNode; root: string; after=""): Profile =
   result = Profile(tweets: Timeline(beginning: after.len == 0))