@the-convocation/twitter-scraper 0.20.4 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.commitlintrc ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "@commitlint/config-conventional"
4
+ ]
5
+ }
package/.eslintrc.js ADDED
@@ -0,0 +1,24 @@
1
+ module.exports = {
2
+ parser: '@typescript-eslint/parser',
3
+ parserOptions: {
4
+ tsconfigRootDir: __dirname,
5
+ sourceType: 'module',
6
+ },
7
+ plugins: ['@typescript-eslint/eslint-plugin'],
8
+ extends: [
9
+ 'plugin:@typescript-eslint/recommended',
10
+ 'plugin:prettier/recommended',
11
+ ],
12
+ root: true,
13
+ env: {
14
+ node: true,
15
+ jest: true,
16
+ },
17
+ ignorePatterns: ['**/*.js'],
18
+ rules: {
19
+ '@typescript-eslint/interface-name-prefix': 'off',
20
+ '@typescript-eslint/explicit-function-return-type': 'off',
21
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
22
+ '@typescript-eslint/no-explicit-any': 'off',
23
+ },
24
+ };
package/.gitattributes ADDED
@@ -0,0 +1,78 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ #
5
+ # The above will handle all files NOT found below
6
+ #
7
+
8
+ # Code
9
+ *.js text eol=lf
10
+ *.ts text eol=lf
11
+
12
+ # Documents
13
+ *.bibtex text diff=bibtex
14
+ *.doc diff=astextplain
15
+ *.DOC diff=astextplain
16
+ *.docx diff=astextplain
17
+ *.DOCX diff=astextplain
18
+ *.dot diff=astextplain
19
+ *.DOT diff=astextplain
20
+ *.pdf diff=astextplain
21
+ *.PDF diff=astextplain
22
+ *.rtf diff=astextplain
23
+ *.RTF diff=astextplain
24
+ *.md text diff=markdown
25
+ *.mdx text diff=markdown
26
+ *.tex text diff=tex
27
+ *.adoc text
28
+ *.textile text
29
+ *.mustache text
30
+ *.csv text
31
+ *.tab text
32
+ *.tsv text
33
+ *.txt text
34
+ *.sql text
35
+
36
+ # Graphics
37
+ *.png binary
38
+ *.jpg binary
39
+ *.jpeg binary
40
+ *.gif binary
41
+ *.tif binary
42
+ *.tiff binary
43
+ *.ico binary
44
+ *.svg text
45
+ *.eps binary
46
+
47
+ # Scripts
48
+ *.bash text eol=lf
49
+ *.fish text eol=lf
50
+ *.sh text eol=lf
51
+ *.zsh text eol=lf
52
+ *.bat text eol=crlf
53
+ *.cmd text eol=crlf
54
+ *.ps1 text eol=crlf
55
+
56
+ # Serialisation
57
+ *.json text
58
+ *.toml text
59
+ *.xml text
60
+ *.yaml text
61
+ *.yml text
62
+
63
+ # Archives
64
+ *.7z binary
65
+ *.gz binary
66
+ *.tar binary
67
+ *.tgz binary
68
+ *.zip binary
69
+
70
+ # Text files where line endings should be preserved
71
+ *.patch -text
72
+
73
+ #
74
+ # Exclude files from exporting
75
+ #
76
+
77
+ .gitattributes export-ignore
78
+ .gitignore export-ignore
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ dist/
3
+ *.json
package/.prettierrc ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "singleQuote": true,
3
+ "trailingComma": "all",
4
+ "semi": true
5
+ }
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  [![Documentation badge](https://img.shields.io/badge/docs-here-informational)](https://the-convocation.github.io/twitter-scraper/)
4
4
 
5
- A port of [n0madic/twitter-scraper](https://github.com/n0madic/twitter-scraper)
6
- to Node.js.
5
+ A port of the now-archived [n0madic/twitter-scraper](https://github.com/n0madic/twitter-scraper) to Node.js.
7
6
 
8
7
  > Twitter's API is annoying to work with, and has lots of limitations — luckily
9
8
  > their frontend (JavaScript) has it's own API, which I reverse-engineered. No
@@ -11,12 +10,20 @@ to Node.js.
11
10
  >
12
11
  > You can use this library to get the text of any user's Tweets trivially.
13
12
 
14
- Known limitations:
13
+ Many things have changed since X (the company formerly known as Twitter) was acquired in 2022:
15
14
 
16
- - Search operations require logging in with a real user account via
17
- `scraper.login()`.
15
+ - Several operations require logging in with a real user account via
16
+ `scraper.login()`. **While we are not aware of confirmed cases caused
17
+ by this library, any account you log into with this library is subject
18
+ to being banned at any time. You have been warned.**
18
19
  - Twitter's frontend API does in fact have rate limits
19
- ([#11](https://github.com/the-convocation/twitter-scraper/issues/11))
20
+ ([#11](https://github.com/the-convocation/twitter-scraper/issues/11)).
21
+ The rate limits are dynamic and sometimes change, so we don't know
22
+ exactly what they are at all times. Refer to [rate limiting](#rate-limiting)
23
+ for more information.
24
+ - Twitter's authentication requirements and frontend API endpoints
25
+ change frequently, breaking this library. Fixes for these issues
26
+ typically take at least a few days to go out.
20
27
 
21
28
  ## Installation
22
29
 
@@ -62,15 +69,15 @@ const scraper = new Scraper({
62
69
  // The arguments here are the same as the parameters to fetch(), and
63
70
  // are kept as-is for flexibility of both the library and applications.
64
71
  if (input instanceof URL) {
65
- const proxy = "https://corsproxy.io/?" +
66
- encodeURIComponent(input.toString());
72
+ const proxy =
73
+ 'https://corsproxy.io/?' + encodeURIComponent(input.toString());
67
74
  return [proxy, init];
68
- } else if (typeof input === "string") {
69
- const proxy = "https://corsproxy.io/?" + encodeURIComponent(input);
75
+ } else if (typeof input === 'string') {
76
+ const proxy = 'https://corsproxy.io/?' + encodeURIComponent(input);
70
77
  return [proxy, init];
71
78
  } else {
72
79
  // Omitting handling for example
73
- throw new Error("Unexpected request input type");
80
+ throw new Error('Unexpected request input type');
74
81
  }
75
82
  },
76
83
  },
@@ -87,10 +94,10 @@ front page).
87
94
  #### Next.js 13.x example:
88
95
 
89
96
  ```tsx
90
- "use client";
97
+ 'use client';
91
98
 
92
- import { Scraper, Tweet } from "@the-convocation/twitter-scraper";
93
- import { useEffect, useMemo, useState } from "react";
99
+ import { Scraper, Tweet } from '@the-convocation/twitter-scraper';
100
+ import { useEffect, useMemo, useState } from 'react';
94
101
 
95
102
  export default function Home() {
96
103
  const scraper = useMemo(
@@ -99,15 +106,15 @@ export default function Home() {
99
106
  transform: {
100
107
  request(input: RequestInfo | URL, init?: RequestInit) {
101
108
  if (input instanceof URL) {
102
- const proxy = "https://corsproxy.io/?" +
103
- encodeURIComponent(input.toString());
109
+ const proxy =
110
+ 'https://corsproxy.io/?' + encodeURIComponent(input.toString());
104
111
  return [proxy, init];
105
- } else if (typeof input === "string") {
106
- const proxy = "https://corsproxy.io/?" +
107
- encodeURIComponent(input);
112
+ } else if (typeof input === 'string') {
113
+ const proxy =
114
+ 'https://corsproxy.io/?' + encodeURIComponent(input);
108
115
  return [proxy, init];
109
116
  } else {
110
- throw new Error("Unexpected request input type");
117
+ throw new Error('Unexpected request input type');
111
118
  }
112
119
  },
113
120
  },
@@ -118,7 +125,7 @@ export default function Home() {
118
125
 
119
126
  useEffect(() => {
120
127
  async function getTweet() {
121
- const latestTweet = await scraper.getLatestTweet("twitter");
128
+ const latestTweet = await scraper.getLatestTweet('twitter');
122
129
  if (latestTweet) {
123
130
  setTweet(latestTweet);
124
131
  }
@@ -159,11 +166,10 @@ supported directly by interceptors):
159
166
  const scraper = new Scraper({
160
167
  fetch: (input, init) => {
161
168
  // Transform input and init into your function's expected types...
162
- return fetch(input, init)
163
- .then((res) => {
164
- // Transform res into a web-compliant response...
165
- return res;
166
- });
169
+ return fetch(input, init).then((res) => {
170
+ // Transform res into a web-compliant response...
171
+ return res;
172
+ });
167
173
  },
168
174
  });
169
175
  ```
@@ -186,7 +192,10 @@ yarn add cycletls
186
192
 
187
193
  ```ts
188
194
  import { Scraper } from '@the-convocation/twitter-scraper';
189
- import { cycleTLSFetch, cycleTLSExit } from '@the-convocation/twitter-scraper/cycletls';
195
+ import {
196
+ cycleTLSFetch,
197
+ cycleTLSExit,
198
+ } from '@the-convocation/twitter-scraper/cycletls';
190
199
 
191
200
  const scraper = new Scraper({
192
201
  fetch: cycleTLSFetch,
@@ -204,6 +213,7 @@ cycleTLSExit();
204
213
  See the [cycletls example](./examples/cycletls/) for a complete working example.
205
214
 
206
215
  ### Rate limiting
216
+
207
217
  The Twitter API heavily rate-limits clients, requiring that the scraper has its own
208
218
  rate-limit handling to behave predictably when rate-limiting occurs. By default, the
209
219
  scraper uses a rate-limiting strategy that waits for the current rate-limiting period
@@ -216,7 +226,7 @@ scrapers logged-in to different accounts (refer to [#116](https://github.com/the
216
226
  implementation to the `rateLimitStrategy` option in the scraper constructor:
217
227
 
218
228
  ```ts
219
- import { Scraper, RateLimitStrategy } from "@the-convocation/twitter-scraper";
229
+ import { Scraper, RateLimitStrategy } from '@the-convocation/twitter-scraper';
220
230
 
221
231
  class CustomRateLimitStrategy implements RateLimitStrategy {
222
232
  async onRateLimit(event: RateLimitEvent): Promise<void> {
@@ -231,6 +241,7 @@ const scraper = new Scraper({
231
241
 
232
242
  More information on this interface can be found on the [`RateLimitStrategy`](https://the-convocation.github.io/twitter-scraper/interfaces/RateLimitStrategy.html)
233
243
  page in the documentation. The library provides two pre-written implementations to choose from:
244
+
234
245
  - `WaitingRateLimitStrategy`: The default, which waits for the limit to expire.
235
246
  - `ErrorRateLimitStrategy`: A strategy that throws if any rate-limit event occurs.
236
247
 
@@ -715,15 +715,8 @@ class TwitterUserAuth extends TwitterGuestAuth {
715
715
  );
716
716
  }
717
717
  async isLoggedIn() {
718
- const res = await requestApi(
719
- "https://api.x.com/1.1/account/verify_credentials.json",
720
- this
721
- );
722
- if (!res.success) {
723
- return false;
724
- }
725
- const { value: verify } = res;
726
- return verify && !verify.errors?.length;
718
+ const cookie = await this.getCookieString();
719
+ return cookie.includes("ct0=");
727
720
  }
728
721
  async login(username, password, email, twoFactorSecret) {
729
722
  await this.updateGuestToken();
@@ -983,11 +976,12 @@ class TwitterUserAuth extends TwitterGuestAuth {
983
976
  ]
984
977
  });
985
978
  }
986
- async handleSuccessSubtask(_subtaskId, _prev, _credentials, api) {
987
- return await this.executeFlowTask({
988
- flow_token: api.getFlowToken(),
989
- subtask_inputs: []
990
- });
979
+ async handleSuccessSubtask() {
980
+ log("Successfully logged in with user credentials.");
981
+ return {
982
+ status: "success",
983
+ response: {}
984
+ };
991
985
  }
992
986
  async executeFlowTask(data) {
993
987
  let onboardingTaskUrl = "https://api.x.com/1.1/onboarding/task.json";
@@ -1095,14 +1089,16 @@ class TwitterUserAuth extends TwitterGuestAuth {
1095
1089
  }
1096
1090
 
1097
1091
  const endpoints = {
1098
- // TODO: Migrate other endpoint URLs here
1099
1092
  UserTweets: "https://x.com/i/api/graphql/oRJs8SLCRNRbQzuZG93_oA/UserTweets?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withQuickPromoteEligibilityTweetFields%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D",
1100
1093
  UserTweetsAndReplies: "https://x.com/i/api/graphql/Hk4KlJ-ONjlJsucqR55P7g/UserTweetsAndReplies?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D",
1101
1094
  UserLikedTweets: "https://x.com/i/api/graphql/XHTMjDbiTGLQ9cP1em-aqQ/Likes?variables=%7B%22userId%22%3A%222244196397%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withClientEventToken%22%3Afalse%2C%22withBirdwatchNotes%22%3Afalse%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticlePlainText%22%3Afalse%7D",
1102
1095
  UserByScreenName: "https://api.x.com/graphql/-oaLodhGbbnzJBACb1kk2Q/UserByScreenName?variables=%7B%22screen_name%22%3A%22geminiapp%22%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22hidden_profile_subscriptions_enabled%22%3Atrue%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22subscriptions_verification_info_is_identity_verified_enabled%22%3Atrue%2C%22subscriptions_verification_info_verified_since_enabled%22%3Atrue%2C%22highlights_tweets_tab_ui_enabled%22%3Atrue%2C%22responsive_web_twitter_article_notes_tab_enabled%22%3Atrue%2C%22subscriptions_feature_can_gift_premium%22%3Atrue%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%7D&fieldToggles=%7B%22withPayments%22%3Afalse%2C%22withAuxiliaryUserLabels%22%3Atrue%7D",
1103
1096
  TweetDetail: "https://x.com/i/api/graphql/YVyS4SfwYW7Uw5qwy0mQCA/TweetDetail?variables=%7B%22focalTweetId%22%3A%221985465713096794294%22%2C%22referrer%22%3A%22profile%22%2C%22with_rux_injections%22%3Afalse%2C%22rankingMode%22%3A%22Relevance%22%2C%22includePromotedContent%22%3Atrue%2C%22withCommunity%22%3Atrue%2C%22withQuickPromoteEligibilityTweetFields%22%3Atrue%2C%22withBirdwatchNotes%22%3Atrue%2C%22withVoice%22%3Atrue%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticleRichContentState%22%3Atrue%2C%22withArticlePlainText%22%3Afalse%2C%22withGrokAnalyze%22%3Afalse%2C%22withDisallowedReplyControls%22%3Afalse%7D",
1104
1097
  TweetResultByRestId: "https://api.x.com/graphql/tCVRZ3WCvoj0BVO7BKnL-Q/TweetResultByRestId?variables=%7B%22tweetId%22%3A%221985465713096794294%22%2C%22withCommunity%22%3Afalse%2C%22includePromotedContent%22%3Afalse%2C%22withVoice%22%3Afalse%7D&features=%7B%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Afalse%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22payments_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D&fieldToggles=%7B%22withArticleRichContentState%22%3Atrue%2C%22withArticlePlainText%22%3Afalse%2C%22withGrokAnalyze%22%3Afalse%2C%22withDisallowedReplyControls%22%3Afalse%7D",
1105
- ListTweets: "https://x.com/i/api/graphql/S1Sm3_mNJwa-fnY9htcaAQ/ListLatestTweetsTimeline?variables=%7B%22listId%22%3A%221736495155002106192%22%2C%22count%22%3A20%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D"
1098
+ ListTweets: "https://x.com/i/api/graphql/S1Sm3_mNJwa-fnY9htcaAQ/ListLatestTweetsTimeline?variables=%7B%22listId%22%3A%221736495155002106192%22%2C%22count%22%3A20%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Afalse%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Afalse%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D",
1099
+ SearchTimeline: "https://x.com/i/api/graphql/nK1dw4oV3k4w5TdtcAdSww/SearchTimeline?variables=%7B%22rawQuery%22%3A%22twitter%22%2C%22count%22%3A20%2C%22querySource%22%3A%22typed_query%22%2C%22product%22%3A%22Top%22%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%2C%22responsive_web_graphql_exclude_directive_enabled%22%3Atrue%2C%22tweetypie_unmention_optimization_enabled%22%3Atrue%2C%22responsive_web_media_download_video_enabled%22%3Afalse%2C%22rweb_lists_timeline_redesign_enabled%22%3Atrue%7D",
1100
+ Followers: "https://x.com/i/api/graphql/SCu9fVIlCUm-BM8-tL5pkQ/Followers?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D",
1101
+ Following: "https://x.com/i/api/graphql/S5xUN9s2v4xk50KWGGvyvQ/Following?variables=%7B%22userId%22%3A%221806359170830172162%22%2C%22count%22%3A20%2C%22includePromotedContent%22%3Afalse%2C%22withGrokTranslatedBio%22%3Afalse%7D&features=%7B%22rweb_video_screen_enabled%22%3Afalse%2C%22profile_label_improvements_pcf_label_in_post_enabled%22%3Atrue%2C%22responsive_web_profile_redirect_enabled%22%3Afalse%2C%22rweb_tipjar_consumption_enabled%22%3Atrue%2C%22verified_phone_label_enabled%22%3Afalse%2C%22creator_subscriptions_tweet_preview_api_enabled%22%3Atrue%2C%22responsive_web_graphql_timeline_navigation_enabled%22%3Atrue%2C%22responsive_web_graphql_skip_user_profile_image_extensions_enabled%22%3Afalse%2C%22premium_content_api_read_enabled%22%3Afalse%2C%22communities_web_enable_tweet_community_results_fetch%22%3Atrue%2C%22c9s_tweet_anatomy_moderator_badge_enabled%22%3Atrue%2C%22responsive_web_grok_analyze_button_fetch_trends_enabled%22%3Afalse%2C%22responsive_web_grok_analyze_post_followups_enabled%22%3Atrue%2C%22responsive_web_jetfuel_frame%22%3Atrue%2C%22responsive_web_grok_share_attachment_enabled%22%3Atrue%2C%22articles_preview_enabled%22%3Atrue%2C%22responsive_web_edit_tweet_api_enabled%22%3Atrue%2C%22graphql_is_translatable_rweb_tweet_is_translatable_enabled%22%3Atrue%2C%22view_counts_everywhere_api_enabled%22%3Atrue%2C%22longform_notetweets_consumption_enabled%22%3Atrue%2C%22responsive_web_twitter_article_tweet_consumption_enabled%22%3Atrue%2C%22tweet_awards_web_tipping_enabled%22%3Afalse%2C%22responsive_web_grok_show_grok_translated_post%22%3Atrue%2C%22responsive_web_grok_analysis_button_from_backend%22%3Atrue%2C%22creator_subscriptions_quote_tweet_preview_enabled%22%3Afalse%2C%22freedom_of_speech_not_reach_fetch_enabled%22%3Atrue%2C%22standardized_nudges_misinfo%22%3Atrue%2C%22tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled%22%3Atrue%2C%22longform_notetweets_rich_text_read_enabled%22%3Atrue%2C%22longform_notetweets_inline_media_enabled%22%3Atrue%2C%22responsive_web_grok_image_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_imagine_annotation_enabled%22%3Atrue%2C%22responsive_web_grok_community_note_auto_translation_is_enabled%22%3Afalse%2C%22responsive_web_enhance_cards_enabled%22%3Afalse%7D"
1106
1102
  };
1107
1103
  class ApiRequest {
1108
1104
  constructor(info) {
@@ -1837,52 +1833,35 @@ async function getSearchTimeline(query, maxItems, searchMode, auth, cursor) {
1837
1833
  if (maxItems > 50) {
1838
1834
  maxItems = 50;
1839
1835
  }
1840
- const variables = {
1841
- rawQuery: query,
1842
- count: maxItems,
1843
- querySource: "typed_query",
1844
- product: "Top"
1845
- };
1846
- const features = addApiFeatures({
1847
- longform_notetweets_inline_media_enabled: true,
1848
- responsive_web_enhance_cards_enabled: false,
1849
- responsive_web_media_download_video_enabled: false,
1850
- responsive_web_twitter_article_tweet_consumption_enabled: false,
1851
- tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
1852
- interactive_text_enabled: false,
1853
- responsive_web_text_conversations_enabled: false,
1854
- vibe_api_enabled: false
1855
- });
1856
- const fieldToggles = {
1857
- withArticleRichContentState: false
1858
- };
1836
+ const searchTimelineRequest = apiRequestFactory.createSearchTimelineRequest();
1837
+ searchTimelineRequest.variables.rawQuery = query;
1838
+ searchTimelineRequest.variables.count = maxItems;
1839
+ searchTimelineRequest.variables.querySource = "typed_query";
1840
+ searchTimelineRequest.variables.product = "Top";
1859
1841
  if (cursor != null && cursor != "") {
1860
- variables["cursor"] = cursor;
1842
+ searchTimelineRequest.variables["cursor"] = cursor;
1861
1843
  }
1862
1844
  switch (searchMode) {
1863
1845
  case 1 /* Latest */:
1864
- variables.product = "Latest";
1846
+ searchTimelineRequest.variables.product = "Latest";
1865
1847
  break;
1866
1848
  case 2 /* Photos */:
1867
- variables.product = "Photos";
1849
+ searchTimelineRequest.variables.product = "Photos";
1868
1850
  break;
1869
1851
  case 3 /* Videos */:
1870
- variables.product = "Videos";
1852
+ searchTimelineRequest.variables.product = "Videos";
1871
1853
  break;
1872
1854
  case 4 /* Users */:
1873
- variables.product = "People";
1855
+ searchTimelineRequest.variables.product = "People";
1874
1856
  break;
1875
1857
  }
1876
- const params = new URLSearchParams();
1877
- const featuresStr = stringify(features);
1878
- const fieldTogglesStr = stringify(fieldToggles);
1879
- const variablesStr = stringify(variables);
1880
- if (featuresStr) params.set("features", featuresStr);
1881
- if (fieldTogglesStr) params.set("fieldToggles", fieldTogglesStr);
1882
- if (variablesStr) params.set("variables", variablesStr);
1883
1858
  const res = await requestApi(
1884
- `https://api.x.com/graphql/gkjsKepM6gl_HmFWoWKfgg/SearchTimeline?${params.toString()}`,
1885
- auth
1859
+ searchTimelineRequest.toRequestUrl(),
1860
+ auth,
1861
+ "GET",
1862
+ void 0,
1863
+ void 0,
1864
+ bearerToken2
1886
1865
  );
1887
1866
  if (!res.success) {
1888
1867
  throw res.err;
@@ -1978,28 +1957,20 @@ async function getFollowingTimeline(userId, maxItems, auth, cursor) {
1978
1957
  if (maxItems > 50) {
1979
1958
  maxItems = 50;
1980
1959
  }
1981
- const variables = {
1982
- userId,
1983
- count: maxItems,
1984
- includePromotedContent: false
1985
- };
1986
- const features = addApiFeatures({
1987
- responsive_web_twitter_article_tweet_consumption_enabled: false,
1988
- tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
1989
- longform_notetweets_inline_media_enabled: true,
1990
- responsive_web_media_download_video_enabled: false
1991
- });
1960
+ const followingRequest = apiRequestFactory.createFollowingRequest();
1961
+ followingRequest.variables.userId = userId;
1962
+ followingRequest.variables.count = maxItems;
1963
+ followingRequest.variables.includePromotedContent = false;
1992
1964
  if (cursor != null && cursor != "") {
1993
- variables["cursor"] = cursor;
1965
+ followingRequest.variables.cursor = cursor;
1994
1966
  }
1995
- const params = new URLSearchParams();
1996
- const featuresStr = stringify(features);
1997
- const variablesStr = stringify(variables);
1998
- if (featuresStr) params.set("features", featuresStr);
1999
- if (variablesStr) params.set("variables", variablesStr);
2000
1967
  const res = await requestApi(
2001
- `https://x.com/i/api/graphql/iSicc7LrzWGBgDPL0tM_TQ/Following?${params.toString()}`,
2002
- auth
1968
+ followingRequest.toRequestUrl(),
1969
+ auth,
1970
+ "GET",
1971
+ void 0,
1972
+ void 0,
1973
+ bearerToken2
2003
1974
  );
2004
1975
  if (!res.success) {
2005
1976
  throw res.err;
@@ -2015,28 +1986,20 @@ async function getFollowersTimeline(userId, maxItems, auth, cursor) {
2015
1986
  if (maxItems > 50) {
2016
1987
  maxItems = 50;
2017
1988
  }
2018
- const variables = {
2019
- userId,
2020
- count: maxItems,
2021
- includePromotedContent: false
2022
- };
2023
- const features = addApiFeatures({
2024
- responsive_web_twitter_article_tweet_consumption_enabled: false,
2025
- tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
2026
- longform_notetweets_inline_media_enabled: true,
2027
- responsive_web_media_download_video_enabled: false
2028
- });
1989
+ const followersRequest = apiRequestFactory.createFollowersRequest();
1990
+ followersRequest.variables.userId = userId;
1991
+ followersRequest.variables.count = maxItems;
1992
+ followersRequest.variables.includePromotedContent = false;
2029
1993
  if (cursor != null && cursor != "") {
2030
- variables["cursor"] = cursor;
1994
+ followersRequest.variables.cursor = cursor;
2031
1995
  }
2032
- const params = new URLSearchParams();
2033
- const featuresStr = stringify(features);
2034
- const variablesStr = stringify(variables);
2035
- if (featuresStr) params.set("features", featuresStr);
2036
- if (variablesStr) params.set("variables", variablesStr);
2037
1996
  const res = await requestApi(
2038
- `https://x.com/i/api/graphql/rRXFSG5vR6drKr5M37YOTw/Followers?${params.toString()}`,
2039
- auth
1997
+ followersRequest.toRequestUrl(),
1998
+ auth,
1999
+ "GET",
2000
+ void 0,
2001
+ void 0,
2002
+ bearerToken2
2040
2003
  );
2041
2004
  if (!res.success) {
2042
2005
  throw res.err;
@@ -2164,7 +2127,11 @@ async function fetchTweetsAndReplies(userId, maxTweets, cursor, auth) {
2164
2127
  }
2165
2128
  const res = await requestApi(
2166
2129
  userTweetsRequest.toRequestUrl(),
2167
- auth
2130
+ auth,
2131
+ "GET",
2132
+ void 0,
2133
+ void 0,
2134
+ bearerToken2
2168
2135
  );
2169
2136
  if (!res.success) {
2170
2137
  throw res.err;
@@ -2183,7 +2150,11 @@ async function fetchListTweets(listId, maxTweets, cursor, auth) {
2183
2150
  }
2184
2151
  const res = await requestApi(
2185
2152
  listTweetsRequest.toRequestUrl(),
2186
- auth
2153
+ auth,
2154
+ "GET",
2155
+ void 0,
2156
+ void 0,
2157
+ bearerToken2
2187
2158
  );
2188
2159
  if (!res.success) {
2189
2160
  throw res.err;
@@ -2238,7 +2209,11 @@ async function fetchLikedTweets(userId, maxTweets, cursor, auth) {
2238
2209
  }
2239
2210
  const res = await requestApi(
2240
2211
  userTweetsRequest.toRequestUrl(),
2241
- auth
2212
+ auth,
2213
+ "GET",
2214
+ void 0,
2215
+ void 0,
2216
+ bearerToken2
2242
2217
  );
2243
2218
  if (!res.success) {
2244
2219
  throw res.err;