@glagan/rettiwt-api 7.0.0

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.
Files changed (165) hide show
  1. package/.eslintrc.js +166 -0
  2. package/.gitattributes +3 -0
  3. package/.github/FUNDING.yml +4 -0
  4. package/.github/ISSUE_TEMPLATE/bug-report.yml +57 -0
  5. package/.github/ISSUE_TEMPLATE/feature-request.yml +20 -0
  6. package/.github/ISSUE_TEMPLATE/question.yml +15 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +32 -0
  8. package/.github/workflows/ci.yml +32 -0
  9. package/.github/workflows/publish.yml +23 -0
  10. package/.nvmrc +1 -0
  11. package/.prettierignore +3 -0
  12. package/.prettierrc +13 -0
  13. package/LICENSE +21 -0
  14. package/README.md +566 -0
  15. package/dist/cli.js +43 -0
  16. package/eslint.config.mjs +17 -0
  17. package/package.json +50 -0
  18. package/src/Rettiwt.ts +97 -0
  19. package/src/cli.ts +48 -0
  20. package/src/collections/Extractors.ts +155 -0
  21. package/src/collections/Groups.ts +81 -0
  22. package/src/collections/Requests.ts +89 -0
  23. package/src/collections/Tweet.ts +17 -0
  24. package/src/commands/DirectMessage.ts +62 -0
  25. package/src/commands/List.ts +90 -0
  26. package/src/commands/Tweet.ts +437 -0
  27. package/src/commands/User.ts +367 -0
  28. package/src/enums/Api.ts +10 -0
  29. package/src/enums/Authentication.ts +10 -0
  30. package/src/enums/Data.ts +13 -0
  31. package/src/enums/Logging.ts +14 -0
  32. package/src/enums/Media.ts +10 -0
  33. package/src/enums/Notification.ts +12 -0
  34. package/src/enums/Resource.ts +69 -0
  35. package/src/enums/Tweet.ts +8 -0
  36. package/src/enums/raw/Analytics.ts +32 -0
  37. package/src/enums/raw/Media.ts +10 -0
  38. package/src/enums/raw/Notification.ts +11 -0
  39. package/src/enums/raw/Tweet.ts +20 -0
  40. package/src/helper/CliUtils.ts +17 -0
  41. package/src/helper/JsonUtils.ts +70 -0
  42. package/src/index.ts +128 -0
  43. package/src/models/RettiwtConfig.ts +101 -0
  44. package/src/models/args/FetchArgs.ts +169 -0
  45. package/src/models/args/PostArgs.ts +93 -0
  46. package/src/models/args/ProfileArgs.ts +68 -0
  47. package/src/models/auth/AuthCookie.ts +58 -0
  48. package/src/models/auth/AuthCredential.ts +83 -0
  49. package/src/models/data/Analytics.ts +97 -0
  50. package/src/models/data/BookmarkFolder.ts +73 -0
  51. package/src/models/data/Conversation.ts +344 -0
  52. package/src/models/data/CursoredData.ts +64 -0
  53. package/src/models/data/DirectMessage.ts +335 -0
  54. package/src/models/data/Inbox.ts +124 -0
  55. package/src/models/data/List.ts +113 -0
  56. package/src/models/data/Notification.ts +84 -0
  57. package/src/models/data/Tweet.ts +388 -0
  58. package/src/models/data/User.ts +187 -0
  59. package/src/models/errors/TwitterError.ts +65 -0
  60. package/src/models/params/Variables.ts +62 -0
  61. package/src/requests/DirectMessage.ts +229 -0
  62. package/src/requests/List.ts +203 -0
  63. package/src/requests/Media.ts +67 -0
  64. package/src/requests/Tweet.ts +607 -0
  65. package/src/requests/User.ts +1191 -0
  66. package/src/services/internal/AuthService.ts +115 -0
  67. package/src/services/internal/ErrorService.ts +41 -0
  68. package/src/services/internal/LogService.ts +34 -0
  69. package/src/services/public/DirectMessageService.ts +159 -0
  70. package/src/services/public/FetcherService.ts +366 -0
  71. package/src/services/public/ListService.ts +241 -0
  72. package/src/services/public/TweetService.ts +886 -0
  73. package/src/services/public/UserService.ts +1154 -0
  74. package/src/types/ErrorHandler.ts +13 -0
  75. package/src/types/Fetch.ts +3 -0
  76. package/src/types/RettiwtConfig.ts +48 -0
  77. package/src/types/args/FetchArgs.ts +233 -0
  78. package/src/types/args/PostArgs.ts +142 -0
  79. package/src/types/args/ProfileArgs.ts +33 -0
  80. package/src/types/auth/AuthCookie.ts +22 -0
  81. package/src/types/auth/AuthCredential.ts +28 -0
  82. package/src/types/auth/TransactionHeader.ts +8 -0
  83. package/src/types/data/Analytics.ts +58 -0
  84. package/src/types/data/BookmarkFolder.ts +12 -0
  85. package/src/types/data/Conversation.ts +44 -0
  86. package/src/types/data/CursoredData.ts +24 -0
  87. package/src/types/data/DirectMessage.ts +33 -0
  88. package/src/types/data/Inbox.ts +23 -0
  89. package/src/types/data/List.ts +33 -0
  90. package/src/types/data/Notification.ts +26 -0
  91. package/src/types/data/Tweet.ts +99 -0
  92. package/src/types/data/User.ts +54 -0
  93. package/src/types/errors/TwitterError.ts +37 -0
  94. package/src/types/params/Variables.ts +41 -0
  95. package/src/types/raw/base/Analytic.ts +32 -0
  96. package/src/types/raw/base/BookmarkFolder.ts +12 -0
  97. package/src/types/raw/base/Cursor.ts +13 -0
  98. package/src/types/raw/base/Error.ts +38 -0
  99. package/src/types/raw/base/LimitedVisibilityTweet.ts +40 -0
  100. package/src/types/raw/base/List.ts +50 -0
  101. package/src/types/raw/base/Media.ts +53 -0
  102. package/src/types/raw/base/Message.ts +22 -0
  103. package/src/types/raw/base/Notification.ts +66 -0
  104. package/src/types/raw/base/Space.ts +35 -0
  105. package/src/types/raw/base/Tweet.ts +139 -0
  106. package/src/types/raw/base/User.ts +182 -0
  107. package/src/types/raw/composite/DataResult.ts +8 -0
  108. package/src/types/raw/composite/TimelineList.ts +10 -0
  109. package/src/types/raw/composite/TimelineTweet.ts +14 -0
  110. package/src/types/raw/composite/TimelineUser.ts +13 -0
  111. package/src/types/raw/dm/Conversation.ts +59 -0
  112. package/src/types/raw/dm/InboxInitial.ts +155 -0
  113. package/src/types/raw/dm/InboxTimeline.ts +301 -0
  114. package/src/types/raw/dm/UserUpdates.ts +46 -0
  115. package/src/types/raw/generic/Response.ts +10 -0
  116. package/src/types/raw/list/AddMember.ts +175 -0
  117. package/src/types/raw/list/Details.ts +176 -0
  118. package/src/types/raw/list/Members.ts +154 -0
  119. package/src/types/raw/list/RemoveMember.ts +174 -0
  120. package/src/types/raw/list/Tweets.ts +2296 -0
  121. package/src/types/raw/media/FinalizeUpload.ts +20 -0
  122. package/src/types/raw/media/InitalizeUpload.ts +12 -0
  123. package/src/types/raw/media/LiveVideoStream.ts +21 -0
  124. package/src/types/raw/space/Details.ts +359 -0
  125. package/src/types/raw/tweet/Bookmark.ts +14 -0
  126. package/src/types/raw/tweet/Details.ts +210 -0
  127. package/src/types/raw/tweet/DetailsBulk.ts +338 -0
  128. package/src/types/raw/tweet/Like.ts +14 -0
  129. package/src/types/raw/tweet/Likers.ts +200 -0
  130. package/src/types/raw/tweet/Post.ts +150 -0
  131. package/src/types/raw/tweet/Replies.ts +539 -0
  132. package/src/types/raw/tweet/Retweet.ts +31 -0
  133. package/src/types/raw/tweet/Retweeters.ts +208 -0
  134. package/src/types/raw/tweet/Schedule.ts +18 -0
  135. package/src/types/raw/tweet/Search.ts +597 -0
  136. package/src/types/raw/tweet/Unbookmark.ts +14 -0
  137. package/src/types/raw/tweet/Unlike.ts +14 -0
  138. package/src/types/raw/tweet/Unpost.ts +20 -0
  139. package/src/types/raw/tweet/Unretweet.ts +31 -0
  140. package/src/types/raw/tweet/Unschedule.ts +14 -0
  141. package/src/types/raw/user/Affiliates.ts +179 -0
  142. package/src/types/raw/user/Analytics.ts +23 -0
  143. package/src/types/raw/user/BookmarkFolderTweets.ts +53 -0
  144. package/src/types/raw/user/BookmarkFolders.ts +41 -0
  145. package/src/types/raw/user/Bookmarks.ts +637 -0
  146. package/src/types/raw/user/Details.ts +185 -0
  147. package/src/types/raw/user/DetailsBulk.ts +104 -0
  148. package/src/types/raw/user/Follow.ts +280 -0
  149. package/src/types/raw/user/Followed.ts +1942 -0
  150. package/src/types/raw/user/Followers.ts +215 -0
  151. package/src/types/raw/user/Following.ts +215 -0
  152. package/src/types/raw/user/Highlights.ts +1287 -0
  153. package/src/types/raw/user/Likes.ts +1254 -0
  154. package/src/types/raw/user/Lists.ts +378 -0
  155. package/src/types/raw/user/Media.ts +1738 -0
  156. package/src/types/raw/user/Notifications.ts +499 -0
  157. package/src/types/raw/user/ProfileUpdate.ts +80 -0
  158. package/src/types/raw/user/Recommended.ts +2319 -0
  159. package/src/types/raw/user/Scheduled.ts +37 -0
  160. package/src/types/raw/user/Search.ts +230 -0
  161. package/src/types/raw/user/Subscriptions.ts +176 -0
  162. package/src/types/raw/user/Tweets.ts +1254 -0
  163. package/src/types/raw/user/TweetsAndReplies.ts +1254 -0
  164. package/src/types/raw/user/Unfollow.ts +280 -0
  165. package/tsconfig.json +97 -0
@@ -0,0 +1,607 @@
1
+ import { RawTweetRepliesSortType, RawTweetSearchResultType } from '../enums/raw/Tweet';
2
+ import { TweetFilter } from '../models/args/FetchArgs';
3
+ import { NewTweet } from '../models/args/PostArgs';
4
+ import { MediaVariable, ReplyVariable } from '../models/params/Variables';
5
+ import { ITweetFilter } from '../types/args/FetchArgs';
6
+ import { INewTweet } from '../types/args/PostArgs';
7
+ import { FetchConfig } from '../types/Fetch';
8
+
9
+ /**
10
+ * Collection of requests related to tweets.
11
+ *
12
+ * @public
13
+ */
14
+ export class TweetRequests {
15
+ /**
16
+ * @param id - The ID of the tweet to bookmark
17
+ */
18
+ public static bookmark(id: string): FetchConfig {
19
+ return {
20
+ method: 'post',
21
+ url: 'https://x.com/i/api/graphql/aoDbu3RHznuiSkQ9aNM67Q/CreateBookmark',
22
+ body: {
23
+ /* eslint-disable @typescript-eslint/naming-convention */
24
+ variables: JSON.stringify({ tweet_id: id }),
25
+ /* eslint-enable @typescript-eslint/naming-convention */
26
+ },
27
+ };
28
+ }
29
+
30
+ /**
31
+ * @param ids - The IDs of the tweets whose details are to be fetched.
32
+ */
33
+ public static bulkDetails(ids: string[]): FetchConfig {
34
+ return {
35
+ method: 'get',
36
+ url: 'https://x.com/i/api/graphql/-R17e8UqwApFGdMxa3jASA/TweetResultsByRestIds',
37
+ params: {
38
+ /* eslint-disable @typescript-eslint/naming-convention */
39
+ variables: JSON.stringify({
40
+ tweetIds: ids,
41
+ referrer: 'home',
42
+ with_rux_injections: false,
43
+ includePromotedContent: false,
44
+ withCommunity: false,
45
+ withQuickPromoteEligibilityTweetFields: false,
46
+ withBirdwatchNotes: false,
47
+ withVoice: false,
48
+ withV2Timeline: false,
49
+ }),
50
+ features: JSON.stringify({
51
+ rweb_lists_timeline_redesign_enabled: true,
52
+ responsive_web_graphql_exclude_directive_enabled: true,
53
+ verified_phone_label_enabled: true,
54
+ creator_subscriptions_tweet_preview_api_enabled: true,
55
+ responsive_web_graphql_timeline_navigation_enabled: true,
56
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
57
+ tweetypie_unmention_optimization_enabled: true,
58
+ responsive_web_edit_tweet_api_enabled: true,
59
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
60
+ view_counts_everywhere_api_enabled: true,
61
+ longform_notetweets_consumption_enabled: true,
62
+ responsive_web_twitter_article_tweet_consumption_enabled: false,
63
+ tweet_awards_web_tipping_enabled: false,
64
+ freedom_of_speech_not_reach_fetch_enabled: true,
65
+ standardized_nudges_misinfo: true,
66
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
67
+ longform_notetweets_rich_text_read_enabled: true,
68
+ longform_notetweets_inline_media_enabled: true,
69
+ responsive_web_media_download_video_enabled: false,
70
+ responsive_web_enhance_cards_enabled: false,
71
+ responsive_web_grok_show_grok_translated_post: false,
72
+ responsive_web_grok_analyze_post_followups_enabled: false,
73
+ responsive_web_jetfuel_frame: false,
74
+ responsive_web_grok_image_annotation_enabled: false,
75
+ communities_web_enable_tweet_community_results_fetch: false,
76
+ c9s_tweet_anatomy_moderator_badge_enabled: false,
77
+ premium_content_api_read_enabled: false,
78
+ responsive_web_grok_analysis_button_from_backend: false,
79
+ profile_label_improvements_pcf_label_in_post_enabled: false,
80
+ rweb_tipjar_consumption_enabled: false,
81
+ creator_subscriptions_quote_tweet_preview_enabled: false,
82
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
83
+ articles_preview_enabled: false,
84
+ responsive_web_grok_share_attachment_enabled: false,
85
+ responsive_web_grok_imagine_annotation_enabled: false,
86
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
87
+ responsive_web_profile_redirect_enabled: false,
88
+ }),
89
+ /* eslint-enable @typescript-eslint/naming-convention */
90
+ },
91
+ };
92
+ }
93
+
94
+ /**
95
+ * @param id - The id of the tweet whose details are to be fetched.
96
+ */
97
+ public static details(id: string): FetchConfig {
98
+ return {
99
+ method: 'get',
100
+ url: 'https://x.com/i/api/graphql/aFvUsJm2c-oDkJV75blV6g/TweetResultByRestId',
101
+ params: {
102
+ /* eslint-disable @typescript-eslint/naming-convention */
103
+ variables: JSON.stringify({
104
+ tweetId: id,
105
+ referrer: 'home',
106
+ with_rux_injections: false,
107
+ includePromotedContent: false,
108
+ withCommunity: false,
109
+ withQuickPromoteEligibilityTweetFields: false,
110
+ withBirdwatchNotes: false,
111
+ withVoice: false,
112
+ withV2Timeline: false,
113
+ }),
114
+ features: JSON.stringify({
115
+ creator_subscriptions_tweet_preview_api_enabled: true,
116
+ premium_content_api_read_enabled: false,
117
+ communities_web_enable_tweet_community_results_fetch: true,
118
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
119
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
120
+ responsive_web_grok_analyze_post_followups_enabled: false,
121
+ responsive_web_jetfuel_frame: false,
122
+ responsive_web_grok_share_attachment_enabled: true,
123
+ articles_preview_enabled: true,
124
+ responsive_web_edit_tweet_api_enabled: true,
125
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
126
+ view_counts_everywhere_api_enabled: true,
127
+ longform_notetweets_consumption_enabled: true,
128
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
129
+ tweet_awards_web_tipping_enabled: false,
130
+ responsive_web_grok_show_grok_translated_post: false,
131
+ responsive_web_grok_analysis_button_from_backend: false,
132
+ creator_subscriptions_quote_tweet_preview_enabled: false,
133
+ freedom_of_speech_not_reach_fetch_enabled: true,
134
+ standardized_nudges_misinfo: true,
135
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
136
+ longform_notetweets_rich_text_read_enabled: true,
137
+ longform_notetweets_inline_media_enabled: true,
138
+ profile_label_improvements_pcf_label_in_post_enabled: true,
139
+ rweb_tipjar_consumption_enabled: true,
140
+ verified_phone_label_enabled: true,
141
+ responsive_web_grok_image_annotation_enabled: true,
142
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
143
+ responsive_web_graphql_timeline_navigation_enabled: true,
144
+ responsive_web_enhance_cards_enabled: false,
145
+ }),
146
+ /* eslint-enable @typescript-eslint/naming-convention */
147
+ },
148
+ };
149
+ }
150
+
151
+ /**
152
+ * @param id - The id of the tweet to be liked.
153
+ */
154
+ public static like(id: string): FetchConfig {
155
+ return {
156
+ method: 'post',
157
+ url: 'https://x.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet',
158
+ body: {
159
+ /* eslint-disable @typescript-eslint/naming-convention */
160
+ variables: {
161
+ tweet_id: id,
162
+ },
163
+ /* eslint-enable @typescript-eslint/naming-convention */
164
+ },
165
+ };
166
+ }
167
+
168
+ /**
169
+ * @param id - The id of the tweet whose likers are to be fetched.
170
+ * @param count - The number of likers to fetch. Only works as a lower limit when used with a cursor.
171
+ * @param cursor - The cursor to the batch of likers to fetch.
172
+ */
173
+ public static likers(id: string, count?: number, cursor?: string): FetchConfig {
174
+ return {
175
+ method: 'get',
176
+ url: 'https://x.com/i/api/graphql/b3OrdeHDQfb9zRMC0fV3bw/Favoriters',
177
+ params: {
178
+ /* eslint-disable @typescript-eslint/naming-convention */
179
+ variables: JSON.stringify({
180
+ tweetId: id,
181
+ count: count,
182
+ cursor: cursor,
183
+ enableRanking: false,
184
+ includePromotedContent: false,
185
+ }),
186
+ features: JSON.stringify({
187
+ rweb_video_screen_enabled: false,
188
+ profile_label_improvements_pcf_label_in_post_enabled: true,
189
+ responsive_web_profile_redirect_enabled: false,
190
+ rweb_tipjar_consumption_enabled: true,
191
+ verified_phone_label_enabled: true,
192
+ creator_subscriptions_tweet_preview_api_enabled: true,
193
+ responsive_web_graphql_timeline_navigation_enabled: true,
194
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
195
+ premium_content_api_read_enabled: false,
196
+ communities_web_enable_tweet_community_results_fetch: true,
197
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
198
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
199
+ responsive_web_grok_analyze_post_followups_enabled: true,
200
+ responsive_web_jetfuel_frame: true,
201
+ responsive_web_grok_share_attachment_enabled: true,
202
+ articles_preview_enabled: true,
203
+ responsive_web_edit_tweet_api_enabled: true,
204
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
205
+ view_counts_everywhere_api_enabled: true,
206
+ longform_notetweets_consumption_enabled: true,
207
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
208
+ tweet_awards_web_tipping_enabled: false,
209
+ responsive_web_grok_show_grok_translated_post: false,
210
+ responsive_web_grok_analysis_button_from_backend: true,
211
+ creator_subscriptions_quote_tweet_preview_enabled: false,
212
+ freedom_of_speech_not_reach_fetch_enabled: true,
213
+ standardized_nudges_misinfo: true,
214
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
215
+ longform_notetweets_rich_text_read_enabled: true,
216
+ longform_notetweets_inline_media_enabled: true,
217
+ responsive_web_grok_image_annotation_enabled: true,
218
+ responsive_web_grok_imagine_annotation_enabled: true,
219
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
220
+ responsive_web_enhance_cards_enabled: false,
221
+ }),
222
+ /* eslint-enable @typescript-eslint/naming-convention */
223
+ },
224
+ };
225
+ }
226
+
227
+ /**
228
+ * @param args - The configuration object for the tweet to be posted.
229
+ */
230
+ public static post(args: INewTweet): FetchConfig {
231
+ // Parsing the args
232
+ const parsedArgs = new NewTweet(args);
233
+
234
+ return {
235
+ method: 'post',
236
+ url: 'https://x.com/i/api/graphql/Uf3io9zVp1DsYxrmL5FJ7g/CreateTweet',
237
+ body: {
238
+ /* eslint-disable @typescript-eslint/naming-convention */
239
+ variables: {
240
+ tweet_text: parsedArgs.text,
241
+ dark_request: false,
242
+ attachment_url: parsedArgs.quote ? `https://x.com/i/status/${parsedArgs.quote}` : undefined,
243
+ media: parsedArgs.media ? new MediaVariable(parsedArgs.media) : undefined,
244
+ reply: parsedArgs.replyTo ? new ReplyVariable(parsedArgs.replyTo) : undefined,
245
+ semantic_annotation_ids: [],
246
+ },
247
+ features: {
248
+ premium_content_api_read_enabled: false,
249
+ communities_web_enable_tweet_community_results_fetch: true,
250
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
251
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
252
+ responsive_web_grok_analyze_post_followups_enabled: true,
253
+ responsive_web_jetfuel_frame: false,
254
+ responsive_web_grok_share_attachment_enabled: true,
255
+ responsive_web_edit_tweet_api_enabled: true,
256
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
257
+ view_counts_everywhere_api_enabled: true,
258
+ longform_notetweets_consumption_enabled: true,
259
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
260
+ tweet_awards_web_tipping_enabled: false,
261
+ responsive_web_grok_show_grok_translated_post: false,
262
+ responsive_web_grok_analysis_button_from_backend: true,
263
+ creator_subscriptions_quote_tweet_preview_enabled: false,
264
+ longform_notetweets_rich_text_read_enabled: true,
265
+ longform_notetweets_inline_media_enabled: true,
266
+ profile_label_improvements_pcf_label_in_post_enabled: true,
267
+ rweb_tipjar_consumption_enabled: true,
268
+ verified_phone_label_enabled: true,
269
+ articles_preview_enabled: true,
270
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
271
+ freedom_of_speech_not_reach_fetch_enabled: true,
272
+ standardized_nudges_misinfo: true,
273
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
274
+ responsive_web_grok_image_annotation_enabled: true,
275
+ responsive_web_graphql_timeline_navigation_enabled: true,
276
+ responsive_web_enhance_cards_enabled: false,
277
+ responsive_web_grok_imagine_annotation_enabled: false,
278
+ responsive_web_profile_redirect_enabled: false,
279
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
280
+ },
281
+ /* eslint-enable @typescript-eslint/naming-convention */
282
+ },
283
+ };
284
+ }
285
+
286
+ /**
287
+ * @param id - The id of the tweet whose replies are to be fetched.
288
+ * @param cursor - The cursor to the batch of replies to fetch.
289
+ */
290
+ public static replies(id: string, cursor?: string, sortBy?: RawTweetRepliesSortType): FetchConfig {
291
+ return {
292
+ method: 'get',
293
+ url: 'https://x.com/i/api/graphql/97JF30KziU00483E_8elBA/TweetDetail',
294
+ params: {
295
+ /* eslint-disable @typescript-eslint/naming-convention */
296
+ variables: JSON.stringify({
297
+ focalTweetId: id,
298
+ cursor: cursor,
299
+ referrer: 'tweet',
300
+ with_rux_injections: false,
301
+ rankingMode: sortBy ?? RawTweetRepliesSortType.RELEVACE,
302
+ includePromotedContent: true,
303
+ withCommunity: true,
304
+ withQuickPromoteEligibilityTweetFields: true,
305
+ withBirdwatchNotes: true,
306
+ withVoice: true,
307
+ }),
308
+ features: JSON.stringify({
309
+ rweb_video_screen_enabled: false,
310
+ profile_label_improvements_pcf_label_in_post_enabled: true,
311
+ responsive_web_profile_redirect_enabled: false,
312
+ rweb_tipjar_consumption_enabled: true,
313
+ verified_phone_label_enabled: true,
314
+ creator_subscriptions_tweet_preview_api_enabled: true,
315
+ responsive_web_graphql_timeline_navigation_enabled: true,
316
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
317
+ premium_content_api_read_enabled: false,
318
+ communities_web_enable_tweet_community_results_fetch: true,
319
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
320
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
321
+ responsive_web_grok_analyze_post_followups_enabled: true,
322
+ responsive_web_jetfuel_frame: true,
323
+ responsive_web_grok_share_attachment_enabled: true,
324
+ articles_preview_enabled: true,
325
+ responsive_web_edit_tweet_api_enabled: true,
326
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
327
+ view_counts_everywhere_api_enabled: true,
328
+ longform_notetweets_consumption_enabled: true,
329
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
330
+ tweet_awards_web_tipping_enabled: false,
331
+ responsive_web_grok_show_grok_translated_post: false,
332
+ responsive_web_grok_analysis_button_from_backend: true,
333
+ creator_subscriptions_quote_tweet_preview_enabled: false,
334
+ freedom_of_speech_not_reach_fetch_enabled: true,
335
+ standardized_nudges_misinfo: true,
336
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
337
+ longform_notetweets_rich_text_read_enabled: true,
338
+ longform_notetweets_inline_media_enabled: true,
339
+ responsive_web_grok_image_annotation_enabled: true,
340
+ responsive_web_grok_imagine_annotation_enabled: true,
341
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
342
+ responsive_web_enhance_cards_enabled: false,
343
+ }),
344
+ fieldToggles: JSON.stringify({
345
+ withArticleRichContentState: true,
346
+ withArticlePlainText: false,
347
+ withGrokAnalyze: false,
348
+ withDisallowedReplyControls: false,
349
+ }),
350
+ /* eslint-enable @typescript-eslint/naming-convention */
351
+ },
352
+ };
353
+ }
354
+
355
+ /**
356
+ * @param id - The id of the tweet which is to be retweeted.
357
+ */
358
+ public static retweet(id: string): FetchConfig {
359
+ return {
360
+ method: 'post',
361
+ url: 'https://x.com/i/api/graphql/LFho5rIi4xcKO90p9jwG7A/CreateRetweet',
362
+ body: {
363
+ variables: {
364
+ /* eslint-disable @typescript-eslint/naming-convention */
365
+ tweet_id: id,
366
+ dark_request: false,
367
+ /* eslint-enable @typescript-eslint/naming-convention */
368
+ },
369
+ },
370
+ };
371
+ }
372
+
373
+ /**
374
+ * @param id - The id of the tweet whose retweeters are to be fetched.
375
+ * @param count - The number of retweeters to fetch. Only works as a lower limit when used with a cursor.
376
+ * @param cursor - The cursor to the batch of retweeters to fetch.
377
+ */
378
+ public static retweeters(id: string, count?: number, cursor?: string): FetchConfig {
379
+ return {
380
+ method: 'get',
381
+ url: 'https://x.com/i/api/graphql/wfglZEC0MRgBdxMa_1a5YQ/Retweeters',
382
+ params: {
383
+ /* eslint-disable @typescript-eslint/naming-convention */
384
+ variables: JSON.stringify({
385
+ tweetId: id,
386
+ count: count,
387
+ cursor: cursor,
388
+ includePromotedContent: false,
389
+ }),
390
+ features: JSON.stringify({
391
+ rweb_video_screen_enabled: false,
392
+ profile_label_improvements_pcf_label_in_post_enabled: true,
393
+ responsive_web_profile_redirect_enabled: false,
394
+ rweb_tipjar_consumption_enabled: true,
395
+ verified_phone_label_enabled: true,
396
+ creator_subscriptions_tweet_preview_api_enabled: true,
397
+ responsive_web_graphql_timeline_navigation_enabled: true,
398
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
399
+ premium_content_api_read_enabled: false,
400
+ communities_web_enable_tweet_community_results_fetch: true,
401
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
402
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
403
+ responsive_web_grok_analyze_post_followups_enabled: true,
404
+ responsive_web_jetfuel_frame: true,
405
+ responsive_web_grok_share_attachment_enabled: true,
406
+ articles_preview_enabled: true,
407
+ responsive_web_edit_tweet_api_enabled: true,
408
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
409
+ view_counts_everywhere_api_enabled: true,
410
+ longform_notetweets_consumption_enabled: true,
411
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
412
+ tweet_awards_web_tipping_enabled: false,
413
+ responsive_web_grok_show_grok_translated_post: false,
414
+ responsive_web_grok_analysis_button_from_backend: true,
415
+ creator_subscriptions_quote_tweet_preview_enabled: false,
416
+ freedom_of_speech_not_reach_fetch_enabled: true,
417
+ standardized_nudges_misinfo: true,
418
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
419
+ longform_notetweets_rich_text_read_enabled: true,
420
+ longform_notetweets_inline_media_enabled: true,
421
+ responsive_web_grok_image_annotation_enabled: true,
422
+ responsive_web_grok_imagine_annotation_enabled: true,
423
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
424
+ responsive_web_enhance_cards_enabled: false,
425
+ }),
426
+ /* eslint-enable @typescript-eslint/naming-convention */
427
+ },
428
+ };
429
+ }
430
+
431
+ /**
432
+ * @param args - The configuration object for the tweet to be posted.
433
+ *
434
+ * @remarks - Only `text` and `media.id` parameters are supported.
435
+ */
436
+ public static schedule(args: INewTweet): FetchConfig {
437
+ // Parsing the args
438
+ const parsedArgs = new NewTweet(args);
439
+
440
+ return {
441
+ method: 'post',
442
+ url: 'https://x.com/i/api/graphql/LCVzRQGxOaGnOnYH01NQXg/CreateScheduledTweet',
443
+ body: {
444
+ /* eslint-disable @typescript-eslint/naming-convention */
445
+ variables: {
446
+ post_tweet_request: {
447
+ auto_populate_reply_metadata: false,
448
+ status: parsedArgs.text,
449
+ exclude_reply_user_ids: [],
450
+ media_ids: parsedArgs.media?.map((item) => item.id) ?? [],
451
+ },
452
+ execute_at: Math.floor((parsedArgs.scheduleFor ?? new Date()).getTime() / 1000),
453
+ },
454
+ /* eslint-enable @typescript-eslint/naming-convention */
455
+ },
456
+ };
457
+ }
458
+
459
+ /**
460
+ * @param filter - The filter to use for searching tweets.
461
+ * @param count - The number of tweets to fetch. Only works as a lower limit when used with a cursor.
462
+ * @param cursor - The cursor to the batch of tweets to fetch.
463
+ */
464
+ public static search(filter: ITweetFilter, count?: number, cursor?: string): FetchConfig {
465
+ // Parsing the filter
466
+ const parsedFilter = new TweetFilter(filter);
467
+
468
+ return {
469
+ method: 'get',
470
+ url: 'https://x.com/i/api/graphql/M1jEez78PEfVfbQLvlWMvQ/SearchTimeline',
471
+ params: {
472
+ /* eslint-disable @typescript-eslint/naming-convention */
473
+ variables: JSON.stringify({
474
+ rawQuery: new TweetFilter(parsedFilter).toString(),
475
+ count: count,
476
+ cursor: cursor,
477
+ querySource: 'typed_query',
478
+ product: parsedFilter.top ? RawTweetSearchResultType.TOP : RawTweetSearchResultType.LATEST,
479
+ withGrokTranslatedBio: false,
480
+ }),
481
+ features: JSON.stringify({
482
+ rweb_video_screen_enabled: false,
483
+ profile_label_improvements_pcf_label_in_post_enabled: true,
484
+ responsive_web_profile_redirect_enabled: false,
485
+ rweb_tipjar_consumption_enabled: true,
486
+ verified_phone_label_enabled: true,
487
+ creator_subscriptions_tweet_preview_api_enabled: true,
488
+ responsive_web_graphql_timeline_navigation_enabled: true,
489
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
490
+ premium_content_api_read_enabled: false,
491
+ communities_web_enable_tweet_community_results_fetch: true,
492
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
493
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
494
+ responsive_web_grok_analyze_post_followups_enabled: true,
495
+ responsive_web_jetfuel_frame: true,
496
+ responsive_web_grok_share_attachment_enabled: true,
497
+ articles_preview_enabled: true,
498
+ responsive_web_edit_tweet_api_enabled: true,
499
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
500
+ view_counts_everywhere_api_enabled: true,
501
+ longform_notetweets_consumption_enabled: true,
502
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
503
+ tweet_awards_web_tipping_enabled: false,
504
+ responsive_web_grok_show_grok_translated_post: false,
505
+ responsive_web_grok_analysis_button_from_backend: true,
506
+ creator_subscriptions_quote_tweet_preview_enabled: false,
507
+ freedom_of_speech_not_reach_fetch_enabled: true,
508
+ standardized_nudges_misinfo: true,
509
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
510
+ longform_notetweets_rich_text_read_enabled: true,
511
+ longform_notetweets_inline_media_enabled: true,
512
+ responsive_web_grok_image_annotation_enabled: true,
513
+ responsive_web_grok_imagine_annotation_enabled: true,
514
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
515
+ responsive_web_enhance_cards_enabled: false,
516
+ }),
517
+ /* eslint-enable @typescript-eslint/naming-convention */
518
+ },
519
+ };
520
+ }
521
+
522
+ /**
523
+ * @param id - The id of the tweet to be unbookmarked.
524
+ */
525
+ public static unbookmark(id: string): FetchConfig {
526
+ return {
527
+ method: 'post',
528
+ url: 'https://x.com/i/api/graphql/Wlmlj2-xzyS1GN3a6cj-mQ/DeleteBookmark',
529
+ body: {
530
+ /* eslint-disable @typescript-eslint/naming-convention */
531
+ variables: {
532
+ tweet_id: id,
533
+ },
534
+ /* eslint-enable @typescript-eslint/naming-convention */
535
+ },
536
+ };
537
+ }
538
+
539
+ /**
540
+ * @param id - The id of the tweet to be unliked.
541
+ */
542
+ public static unlike(id: string): FetchConfig {
543
+ return {
544
+ method: 'post',
545
+ url: 'https://x.com/i/api/graphql/ZYKSe-w7KEslx3JhSIk5LA/UnfavoriteTweet',
546
+ body: {
547
+ /* eslint-disable @typescript-eslint/naming-convention */
548
+ variables: {
549
+ tweet_id: id,
550
+ },
551
+ /* eslint-enable @typescript-eslint/naming-convention */
552
+ },
553
+ };
554
+ }
555
+
556
+ /**
557
+ * @param id - The id of the tweet to be unposted.
558
+ */
559
+ public static unpost(id: string): FetchConfig {
560
+ return {
561
+ method: 'post',
562
+ url: 'https://x.com/i/api/graphql/VaenaVgh5q5ih7kvyVjgtg/DeleteTweet',
563
+ body: {
564
+ /* eslint-disable @typescript-eslint/naming-convention */
565
+ variables: {
566
+ tweet_id: id,
567
+ },
568
+ /* eslint-enable @typescript-eslint/naming-convention */
569
+ },
570
+ };
571
+ }
572
+
573
+ /**
574
+ * @param id - The id of the source tweet (which was retweeted), to be unretweeted.
575
+ */
576
+ public static unretweet(id: string): FetchConfig {
577
+ return {
578
+ method: 'post',
579
+ url: 'https://x.com/i/api/graphql/iQtK4dl5hBmXewYZuEOKVw/DeleteRetweet',
580
+ body: {
581
+ /* eslint-disable @typescript-eslint/naming-convention */
582
+ variables: {
583
+ source_tweet_id: id,
584
+ },
585
+ /* eslint-enable @typescript-eslint/naming-convention */
586
+ },
587
+ };
588
+ }
589
+
590
+ /**
591
+ * @param id - The id of the scheduled tweet to be unscheduled.
592
+ */
593
+ public static unschedule(id: string): FetchConfig {
594
+ return {
595
+ method: 'post',
596
+ url: 'https://x.com/i/api/graphql/CTOVqej0JBXAZSwkp1US0g/DeleteScheduledTweet',
597
+ body: {
598
+ /* eslint-disable @typescript-eslint/naming-convention */
599
+ variables: {
600
+ scheduled_tweet_id: id,
601
+ },
602
+ queryId: 'CTOVqej0JBXAZSwkp1US0g',
603
+ /* eslint-enable @typescript-eslint/naming-convention */
604
+ },
605
+ };
606
+ }
607
+ }