@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,229 @@
1
+ import qs from 'querystring';
2
+ import { FetchConfig } from '../types/Fetch';
3
+
4
+ /**
5
+ * Common parameter sets for DM requests
6
+ */
7
+ const BaseDMParams = {
8
+ /* eslint-disable @typescript-eslint/naming-convention */
9
+
10
+ nsfw_filtering_enabled: false,
11
+ filter_low_quality: true,
12
+ include_quality: 'all',
13
+ dm_secret_conversations_enabled: false,
14
+ krs_registration_enabled: false,
15
+ cards_platform: 'Web-12',
16
+ include_cards: 1,
17
+ include_ext_alt_text: true,
18
+ include_ext_limited_action_results: true,
19
+ include_quote_count: true,
20
+ include_reply_count: 1,
21
+ tweet_mode: 'extended',
22
+ include_ext_views: true,
23
+ include_groups: true,
24
+ include_inbox_timelines: true,
25
+ include_ext_media_color: true,
26
+ supports_reactions: true,
27
+ supports_edit: true,
28
+ include_ext_edit_control: true,
29
+ include_ext_business_affiliations_label: true,
30
+ ext: 'mediaColor%2CaltText%2CbusinessAffiliationsLabel%2CmediaStats%2ChighlightedLabel%2CparodyCommentaryFanLabel%2CvoiceInfo%2CbirdwatchPivot%2CsuperFollowMetadata%2CunmentionInfo%2CeditControl%2Carticle',
31
+
32
+ /* eslint-enable @typescript-eslint/naming-convention */
33
+ };
34
+
35
+ const DMUserIncludeParams = {
36
+ /* eslint-disable @typescript-eslint/naming-convention */
37
+
38
+ include_profile_interstitial_type: 1,
39
+ include_blocking: 1,
40
+ include_blocked_by: 1,
41
+ include_followed_by: 1,
42
+ include_want_retweets: 1,
43
+ include_mute_edge: 1,
44
+ include_can_dm: 1,
45
+ include_can_media_tag: 1,
46
+ include_ext_is_blue_verified: 1,
47
+ include_ext_verified_type: 1,
48
+ include_ext_profile_image_shape: 1,
49
+ skip_status: 1,
50
+
51
+ /* eslint-enable @typescript-eslint/naming-convention */
52
+ };
53
+
54
+ /**
55
+ * Collection of requests related to direct messages.
56
+ *
57
+ * @public
58
+ */
59
+ export class DMRequests {
60
+ /**
61
+ * Get a specific DM conversation
62
+ * @param conversationId - The conversation ID (e.g., "394028042-1712730991884689408")
63
+ * @param maxId - Maximum ID for pagination (optional)
64
+ */
65
+ public static conversation(conversationId: string, maxId?: string): FetchConfig {
66
+ const context = maxId ? 'FETCH_DM_CONVERSATION_HISTORY' : 'FETCH_DM_CONVERSATION';
67
+
68
+ return {
69
+ method: 'get',
70
+ url: `https://x.com/i/api/1.1/dm/conversation/${conversationId}.json`,
71
+ params: {
72
+ ...BaseDMParams,
73
+ ...DMUserIncludeParams,
74
+ /* eslint-disable @typescript-eslint/naming-convention */
75
+ max_id: maxId,
76
+ context: context,
77
+ dm_users: false,
78
+ include_conversation_info: true,
79
+ /* eslint-enable @typescript-eslint/naming-convention */
80
+ },
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Delete a DM conversation
86
+ * @param conversationId - The ID of the conversation to delete
87
+ */
88
+ public static deleteConversation(conversationId: string): FetchConfig {
89
+ return {
90
+ method: 'post',
91
+ url: `https://x.com/i/api/1.1/dm/${conversationId}/delete.json`,
92
+ body: qs.stringify({
93
+ /* eslint-disable @typescript-eslint/naming-convention */
94
+ dm_secret_conversations_enabled: false,
95
+ krs_registration_enabled: false,
96
+ cards_platform: 'Web-12',
97
+ include_cards: 1,
98
+ include_ext_alt_text: true,
99
+ include_ext_limited_action_results: true,
100
+ include_quote_count: true,
101
+ include_reply_count: 1,
102
+ tweet_mode: 'extended',
103
+ include_ext_views: true,
104
+ dm_users: false,
105
+ include_groups: true,
106
+ include_inbox_timelines: true,
107
+ include_ext_media_color: true,
108
+ supports_reactions: true,
109
+ supports_edit: true,
110
+ include_conversation_info: true,
111
+ }),
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Get the initial state of the DM inbox
117
+ */
118
+ public static inboxInitial(): FetchConfig {
119
+ return {
120
+ method: 'get',
121
+ url: 'https://x.com/i/api/1.1/dm/inbox_initial_state.json',
122
+ params: {
123
+ ...BaseDMParams,
124
+ ...DMUserIncludeParams,
125
+ /* eslint-disable @typescript-eslint/naming-convention */
126
+ dm_users: true,
127
+ include_ext_parody_commentary_fan_label: true,
128
+ ext: 'mediaColor%2CaltText%2CmediaStats%2ChighlightedLabel%2CparodyCommentaryFanLabel%2CvoiceInfo%2CbirdwatchPivot%2CsuperFollowMetadata%2CunmentionInfo%2CeditControl%2Carticle',
129
+ },
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Get inbox timeline (pagination of conversations)
135
+ * @param maxId - Maximum ID for pagination
136
+ */
137
+ public static inboxTimeline(maxId?: string): FetchConfig {
138
+ return {
139
+ method: 'get',
140
+ url: 'https://x.com/i/api/1.1/dm/inbox_timeline/trusted.json',
141
+ params: {
142
+ ...BaseDMParams,
143
+ ...DMUserIncludeParams,
144
+ /* eslint-disable @typescript-eslint/naming-convention */
145
+ max_id: maxId,
146
+ dm_users: false,
147
+ },
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Create a new DM or get DM creation interface
153
+ */
154
+ // public static new(): FetchConfig {
155
+ // return {
156
+ // method: 'get',
157
+ // url: 'https://x.com/i/api/1.1/dm/new2.json',
158
+ // params: {
159
+ // /* eslint-disable @typescript-eslint/naming-convention */
160
+ // ext: 'mediaColor%2CaltText%2CmediaStats%2ChighlightedLabel%2CparodyCommentaryFanLabel%2CvoiceInfo%2CbirdwatchPivot%2CsuperFollowMetadata%2CunmentionInfo%2CeditControl%2Carticle',
161
+ // include_ext_alt_text: true,
162
+ // include_ext_limited_action_results: true,
163
+ // include_reply_count: 1,
164
+ // tweet_mode: 'extended',
165
+ // include_ext_views: true,
166
+ // include_groups: true,
167
+ // include_inbox_timelines: true,
168
+ // include_ext_media_color: true,
169
+ // supports_reactions: true,
170
+ // supports_edit: true,
171
+ // },
172
+ // paramsSerializer: { encode: encodeURIComponent },
173
+ // };
174
+ // }
175
+
176
+ /**
177
+ * Check DM permissions for specific recipients
178
+ * @param recipientIds - Array of recipient user IDs
179
+ */
180
+ // public static permissions(recipientIds: string[]): FetchConfig {
181
+ // return {
182
+ // method: 'get',
183
+ // url: 'https://x.com/i/api/1.1/dm/permissions.json',
184
+ // params: {
185
+ // /* eslint-disable @typescript-eslint/naming-convention */
186
+ // recipient_ids: recipientIds.join(','),
187
+ // dm_users: true,
188
+ // },
189
+ // paramsSerializer: { encode: encodeURIComponent },
190
+ // };
191
+ // }
192
+
193
+ /**
194
+ * Update the last seen event ID for a conversation
195
+ * @param lastSeenEventId - The ID of the last seen event
196
+ * @param trustedLastSeenEventId - The trusted last seen event ID (usually same as lastSeenEventId)
197
+ */
198
+ // public static updateLastSeenEventId(lastSeenEventId: string, trustedLastSeenEventId?: string): FetchConfig {
199
+ // return {
200
+ // method: 'post',
201
+ // url: 'https://x.com/i/api/1.1/dm/update_last_seen_event_id.json',
202
+ // data: qs.stringify({
203
+ // /* eslint-disable @typescript-eslint/naming-convention */
204
+ // last_seen_event_id: lastSeenEventId,
205
+ // trusted_last_seen_event_id: trustedLastSeenEventId ?? lastSeenEventId,
206
+ // }),
207
+ // };
208
+ // }
209
+
210
+ /**
211
+ * Get user updates for DMs (polling for new messages)
212
+ * @param cursor - Cursor for pagination
213
+ * @param activeConversationId - ID of the currently active conversation
214
+ */
215
+ // public static userUpdates(cursor?: string, activeConversationId?: string): FetchConfig {
216
+ // return {
217
+ // method: 'get',
218
+ // url: 'https://x.com/i/api/1.1/dm/user_updates.json',
219
+ // params: {
220
+ // ...DM_BASE_PARAMS,
221
+ // /* eslint-disable @typescript-eslint/naming-convention */
222
+ // cursor: cursor,
223
+ // active_conversation_id: activeConversationId,
224
+ // dm_users: false,
225
+ // },
226
+ // paramsSerializer: { encode: encodeURIComponent },
227
+ // };
228
+ // }
229
+ }
@@ -0,0 +1,203 @@
1
+ import { FetchConfig } from '../types/Fetch';
2
+
3
+ /**
4
+ * Collection of requests related to lists.
5
+ *
6
+ * @public
7
+ */
8
+ export class ListRequests {
9
+ /**
10
+ * @param listId - The ID of the target list.
11
+ * @param userId - The ID of the user to be added as a member.
12
+ */
13
+ public static addMember(listId: string, userId: string): FetchConfig {
14
+ return {
15
+ method: 'post',
16
+ url: 'https://x.com/i/api/graphql/EadD8ivrhZhYQr2pDmCpjA/ListAddMember',
17
+ body: {
18
+ /* eslint-disable @typescript-eslint/naming-convention */
19
+
20
+ variables: {
21
+ listId: listId,
22
+ userId: userId,
23
+ },
24
+ features: {
25
+ profile_label_improvements_pcf_label_in_post_enabled: true,
26
+ responsive_web_profile_redirect_enabled: false,
27
+ rweb_tipjar_consumption_enabled: true,
28
+ verified_phone_label_enabled: true,
29
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
30
+ responsive_web_graphql_timeline_navigation_enabled: true,
31
+ },
32
+
33
+ /* eslint-enable @typescript-eslint/naming-convention */
34
+ },
35
+ };
36
+ }
37
+
38
+ /**
39
+ * @param id - The id of the list whose details are to be fetched.
40
+ */
41
+ public static details(id: string): FetchConfig {
42
+ return {
43
+ method: 'get',
44
+ url: 'https://x.com/i/api/graphql/Tzkkg-NaBi_y1aAUUb6_eQ/ListByRestId',
45
+ params: {
46
+ /* eslint-disable @typescript-eslint/naming-convention */
47
+ variables: JSON.stringify({ listId: id }),
48
+ features: JSON.stringify({
49
+ profile_label_improvements_pcf_label_in_post_enabled: true,
50
+ responsive_web_profile_redirect_enabled: false,
51
+ rweb_tipjar_consumption_enabled: true,
52
+ verified_phone_label_enabled: true,
53
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
54
+ responsive_web_graphql_timeline_navigation_enabled: true,
55
+ }),
56
+ /* eslint-enable @typescript-eslint/naming-convention */
57
+ },
58
+ };
59
+ }
60
+
61
+ /**
62
+ * @param id - The id of the list whose members are to be fetched.
63
+ * @param count - The number of members to fetch. Must be \<= 100.
64
+ * @param cursor - The cursor to the batch of members to fetch.
65
+ */
66
+ public static members(id: string, count?: number, cursor?: string): FetchConfig {
67
+ return {
68
+ method: 'get',
69
+ url: 'https://x.com/i/api/graphql/Bnhcen0kdsMAU1tW7U79qQ/ListMembers',
70
+ params: {
71
+ /* eslint-disable @typescript-eslint/naming-convention */
72
+ variables: JSON.stringify({
73
+ listId: id,
74
+ count: count,
75
+ cursor: cursor,
76
+ }),
77
+ features: JSON.stringify({
78
+ rweb_video_screen_enabled: false,
79
+ profile_label_improvements_pcf_label_in_post_enabled: true,
80
+ responsive_web_profile_redirect_enabled: false,
81
+ rweb_tipjar_consumption_enabled: true,
82
+ verified_phone_label_enabled: true,
83
+ creator_subscriptions_tweet_preview_api_enabled: true,
84
+ responsive_web_graphql_timeline_navigation_enabled: true,
85
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
86
+ premium_content_api_read_enabled: false,
87
+ communities_web_enable_tweet_community_results_fetch: true,
88
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
89
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
90
+ responsive_web_grok_analyze_post_followups_enabled: true,
91
+ responsive_web_jetfuel_frame: true,
92
+ responsive_web_grok_share_attachment_enabled: true,
93
+ articles_preview_enabled: true,
94
+ responsive_web_edit_tweet_api_enabled: true,
95
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
96
+ view_counts_everywhere_api_enabled: true,
97
+ longform_notetweets_consumption_enabled: true,
98
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
99
+ tweet_awards_web_tipping_enabled: false,
100
+ responsive_web_grok_show_grok_translated_post: false,
101
+ responsive_web_grok_analysis_button_from_backend: true,
102
+ creator_subscriptions_quote_tweet_preview_enabled: false,
103
+ freedom_of_speech_not_reach_fetch_enabled: true,
104
+ standardized_nudges_misinfo: true,
105
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
106
+ longform_notetweets_rich_text_read_enabled: true,
107
+ longform_notetweets_inline_media_enabled: true,
108
+ responsive_web_grok_image_annotation_enabled: true,
109
+ responsive_web_grok_imagine_annotation_enabled: true,
110
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
111
+ responsive_web_enhance_cards_enabled: false,
112
+ }),
113
+ /* eslint-enable @typescript-eslint/naming-convention */
114
+ },
115
+ };
116
+ }
117
+
118
+ /**
119
+ * @param listId - The ID of the target list.
120
+ * @param userId - The ID of the user to remove as a member.
121
+ */
122
+ public static removeMember(listId: string, userId: string): FetchConfig {
123
+ return {
124
+ method: 'post',
125
+ url: 'https://x.com/i/api/graphql/B5tMzrMYuFHJex_4EXFTSw/ListRemoveMember',
126
+ body: {
127
+ /* eslint-disable @typescript-eslint/naming-convention */
128
+
129
+ variables: {
130
+ listId: listId,
131
+ userId: userId,
132
+ },
133
+ features: {
134
+ profile_label_improvements_pcf_label_in_post_enabled: true,
135
+ responsive_web_profile_redirect_enabled: false,
136
+ rweb_tipjar_consumption_enabled: true,
137
+ verified_phone_label_enabled: true,
138
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
139
+ responsive_web_graphql_timeline_navigation_enabled: true,
140
+ },
141
+
142
+ /* eslint-enable @typescript-eslint/naming-convention */
143
+ },
144
+ };
145
+ }
146
+
147
+ /**
148
+ * @param id - The id of the list whose tweets are to be fetched.
149
+ * @param count - The number of tweets to fetch. Must be \<= 100.
150
+ * @param cursor - The cursor to the batch of tweets to fetch.
151
+ */
152
+ public static tweets(id: string, count?: number, cursor?: string): FetchConfig {
153
+ return {
154
+ method: 'get',
155
+ url: 'https://x.com/i/api/graphql/fqNUs_6rqLf89u_2waWuqg/ListLatestTweetsTimeline',
156
+ params: {
157
+ /* eslint-disable @typescript-eslint/naming-convention */
158
+ variables: JSON.stringify({
159
+ listId: id,
160
+ count: count,
161
+ cursor: cursor,
162
+ }),
163
+ features: JSON.stringify({
164
+ rweb_video_screen_enabled: false,
165
+ profile_label_improvements_pcf_label_in_post_enabled: true,
166
+ responsive_web_profile_redirect_enabled: false,
167
+ rweb_tipjar_consumption_enabled: true,
168
+ verified_phone_label_enabled: true,
169
+ creator_subscriptions_tweet_preview_api_enabled: true,
170
+ responsive_web_graphql_timeline_navigation_enabled: true,
171
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
172
+ premium_content_api_read_enabled: false,
173
+ communities_web_enable_tweet_community_results_fetch: true,
174
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
175
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
176
+ responsive_web_grok_analyze_post_followups_enabled: true,
177
+ responsive_web_jetfuel_frame: true,
178
+ responsive_web_grok_share_attachment_enabled: true,
179
+ articles_preview_enabled: true,
180
+ responsive_web_edit_tweet_api_enabled: true,
181
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
182
+ view_counts_everywhere_api_enabled: true,
183
+ longform_notetweets_consumption_enabled: true,
184
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
185
+ tweet_awards_web_tipping_enabled: false,
186
+ responsive_web_grok_show_grok_translated_post: false,
187
+ responsive_web_grok_analysis_button_from_backend: true,
188
+ creator_subscriptions_quote_tweet_preview_enabled: false,
189
+ freedom_of_speech_not_reach_fetch_enabled: true,
190
+ standardized_nudges_misinfo: true,
191
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
192
+ longform_notetweets_rich_text_read_enabled: true,
193
+ longform_notetweets_inline_media_enabled: true,
194
+ responsive_web_grok_image_annotation_enabled: true,
195
+ responsive_web_grok_imagine_annotation_enabled: true,
196
+ responsive_web_grok_community_note_auto_translation_is_enabled: false,
197
+ responsive_web_enhance_cards_enabled: false,
198
+ }),
199
+ /* eslint-enable @typescript-eslint/naming-convention */
200
+ },
201
+ };
202
+ }
203
+ }
@@ -0,0 +1,67 @@
1
+ import fs from 'fs';
2
+
3
+ import FormData from 'form-data';
4
+ import { FetchConfig } from '../types/Fetch';
5
+
6
+ /**
7
+ * Collection of requests related to media.
8
+ *
9
+ * @public
10
+ */
11
+ export class MediaRequests {
12
+ /**
13
+ * @param id - The allocated id of the media item to be uploaded.
14
+ * @param media - The media item to upload.
15
+ */
16
+ public static appendUpload(id: string, media: string | ArrayBuffer): FetchConfig {
17
+ const data = new FormData();
18
+ data.append('media', typeof media == 'string' ? fs.createReadStream(media) : Buffer.from(media));
19
+ return {
20
+ method: 'post',
21
+ headers: { referer: 'https://x.com' },
22
+ url: 'https://upload.x.com/i/media/upload.json',
23
+ params: {
24
+ /* eslint-disable @typescript-eslint/naming-convention */
25
+ command: 'APPEND',
26
+ media_id: id,
27
+ segment_index: 0,
28
+ /* eslint-enable @typescript-eslint/naming-convention */
29
+ },
30
+ body: data,
31
+ };
32
+ }
33
+
34
+ /**
35
+ * @param id - The allocated id of the media item.
36
+ */
37
+ public static finalizeUpload(id: string): FetchConfig {
38
+ return {
39
+ method: 'post',
40
+ headers: { referer: 'https://x.com' },
41
+ url: 'https://upload.x.com/i/media/upload.json',
42
+ params: {
43
+ /* eslint-disable @typescript-eslint/naming-convention */
44
+ command: 'FINALIZE',
45
+ media_id: id,
46
+ /* eslint-enable @typescript-eslint/naming-convention */
47
+ },
48
+ };
49
+ }
50
+
51
+ /**
52
+ * @param size - The size (in bytes) of the media item to be uploaded.
53
+ */
54
+ public static initializeUpload(size: number): FetchConfig {
55
+ return {
56
+ method: 'post',
57
+ headers: { referer: 'https://x.com' },
58
+ url: 'https://upload.x.com/i/media/upload.json',
59
+ params: {
60
+ /* eslint-disable @typescript-eslint/naming-convention */
61
+ command: 'INIT',
62
+ total_bytes: size,
63
+ /* eslint-enable @typescript-eslint/naming-convention */
64
+ },
65
+ };
66
+ }
67
+ }