rettiwt-api 7.0.2 → 7.1.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 (86) hide show
  1. package/README.md +38 -10
  2. package/dist/collections/Extractors.d.ts +14 -0
  3. package/dist/collections/Extractors.js +7 -0
  4. package/dist/collections/Extractors.js.map +1 -1
  5. package/dist/collections/Groups.js +7 -0
  6. package/dist/collections/Groups.js.map +1 -1
  7. package/dist/collections/Requests.js +7 -0
  8. package/dist/collections/Requests.js.map +1 -1
  9. package/dist/commands/List.js +87 -0
  10. package/dist/commands/List.js.map +1 -1
  11. package/dist/commands/Tweet.js +14 -0
  12. package/dist/commands/Tweet.js.map +1 -1
  13. package/dist/commands/User.js +13 -0
  14. package/dist/commands/User.js.map +1 -1
  15. package/dist/enums/Resource.d.ts +7 -0
  16. package/dist/enums/Resource.js +7 -0
  17. package/dist/enums/Resource.js.map +1 -1
  18. package/dist/index.d.ts +7 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/models/args/PostArgs.d.ts +31 -1
  21. package/dist/models/args/PostArgs.js +43 -1
  22. package/dist/models/args/PostArgs.js.map +1 -1
  23. package/dist/requests/List.d.ts +22 -0
  24. package/dist/requests/List.js +106 -0
  25. package/dist/requests/List.js.map +1 -1
  26. package/dist/requests/Tweet.d.ts +4 -0
  27. package/dist/requests/Tweet.js +59 -0
  28. package/dist/requests/Tweet.js.map +1 -1
  29. package/dist/requests/User.d.ts +4 -0
  30. package/dist/requests/User.js +56 -34
  31. package/dist/requests/User.js.map +1 -1
  32. package/dist/services/public/ListService.d.ts +136 -0
  33. package/dist/services/public/ListService.js +175 -0
  34. package/dist/services/public/ListService.js.map +1 -1
  35. package/dist/services/public/TweetService.d.ts +26 -0
  36. package/dist/services/public/TweetService.js +33 -0
  37. package/dist/services/public/TweetService.js.map +1 -1
  38. package/dist/services/public/UserService.d.ts +28 -0
  39. package/dist/services/public/UserService.js +35 -0
  40. package/dist/services/public/UserService.js.map +1 -1
  41. package/dist/types/args/PostArgs.d.ts +50 -0
  42. package/dist/types/raw/list/Create.d.ts +14 -0
  43. package/dist/types/raw/list/Create.js +4 -0
  44. package/dist/types/raw/list/Create.js.map +1 -0
  45. package/dist/types/raw/list/Delete.d.ts +10 -0
  46. package/dist/types/raw/list/Delete.js +4 -0
  47. package/dist/types/raw/list/Delete.js.map +1 -0
  48. package/dist/types/raw/list/Mute.d.ts +10 -0
  49. package/dist/types/raw/list/Mute.js +3 -0
  50. package/dist/types/raw/list/Mute.js.map +1 -0
  51. package/dist/types/raw/list/Unmute.d.ts +10 -0
  52. package/dist/types/raw/list/Unmute.js +3 -0
  53. package/dist/types/raw/list/Unmute.js.map +1 -0
  54. package/dist/types/raw/list/Update.d.ts +11 -0
  55. package/dist/types/raw/list/Update.js +3 -0
  56. package/dist/types/raw/list/Update.js.map +1 -0
  57. package/dist/types/raw/tweet/History.d.ts +48 -0
  58. package/dist/types/raw/tweet/History.js +4 -0
  59. package/dist/types/raw/tweet/History.js.map +1 -0
  60. package/dist/types/raw/user/RemoveFollower.d.ts +13 -0
  61. package/dist/types/raw/user/RemoveFollower.js +4 -0
  62. package/dist/types/raw/user/RemoveFollower.js.map +1 -0
  63. package/package.json +1 -1
  64. package/src/collections/Extractors.ts +16 -0
  65. package/src/collections/Groups.ts +7 -0
  66. package/src/collections/Requests.ts +7 -0
  67. package/src/commands/List.ts +100 -0
  68. package/src/commands/Tweet.ts +14 -0
  69. package/src/commands/User.ts +13 -0
  70. package/src/enums/Resource.ts +7 -0
  71. package/src/index.ts +7 -1
  72. package/src/models/args/PostArgs.ts +53 -1
  73. package/src/requests/List.ts +117 -0
  74. package/src/requests/Tweet.ts +60 -0
  75. package/src/requests/User.ts +61 -34
  76. package/src/services/public/ListService.ts +201 -0
  77. package/src/services/public/TweetService.ts +38 -0
  78. package/src/services/public/UserService.ts +40 -0
  79. package/src/types/args/PostArgs.ts +58 -0
  80. package/src/types/raw/list/Create.ts +16 -0
  81. package/src/types/raw/list/Delete.ts +12 -0
  82. package/src/types/raw/list/Mute.ts +10 -0
  83. package/src/types/raw/list/Unmute.ts +10 -0
  84. package/src/types/raw/list/Update.ts +12 -0
  85. package/src/types/raw/tweet/History.ts +57 -0
  86. package/src/types/raw/user/RemoveFollower.ts +15 -0
@@ -151,6 +151,66 @@ export class TweetRequests {
151
151
  };
152
152
  }
153
153
 
154
+ /**
155
+ * @param id - The id of the tweet whose edit history is to be fetched.
156
+ */
157
+ public static history(id: string): AxiosRequestConfig {
158
+ return {
159
+ method: 'get',
160
+ url: 'https://x.com/i/api/graphql/MGElmrYILE8wUfI8GorUYA/TweetEditHistory',
161
+ params: {
162
+ /* eslint-disable @typescript-eslint/naming-convention */
163
+ variables: JSON.stringify({
164
+ tweetId: id,
165
+ withQuickPromoteEligibilityTweetFields: true,
166
+ }),
167
+ features: JSON.stringify({
168
+ premium_content_api_read_enabled: false,
169
+ communities_web_enable_tweet_community_results_fetch: true,
170
+ c9s_tweet_anatomy_moderator_badge_enabled: true,
171
+ responsive_web_grok_analyze_button_fetch_trends_enabled: false,
172
+ responsive_web_grok_analyze_post_followups_enabled: true,
173
+ rweb_cashtags_composer_attachment_enabled: true,
174
+ responsive_web_jetfuel_frame: true,
175
+ responsive_web_grok_share_attachment_enabled: true,
176
+ responsive_web_grok_annotations_enabled: true,
177
+ freedom_of_speech_not_reach_fetch_enabled: true,
178
+ standardized_nudges_misinfo: true,
179
+ tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
180
+ rweb_video_screen_enabled: false,
181
+ responsive_web_edit_tweet_api_enabled: true,
182
+ rweb_conversational_replies_downvote_enabled: false,
183
+ graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
184
+ view_counts_everywhere_api_enabled: true,
185
+ longform_notetweets_consumption_enabled: true,
186
+ responsive_web_twitter_article_tweet_consumption_enabled: true,
187
+ content_disclosure_indicator_enabled: true,
188
+ content_disclosure_ai_generated_indicator_enabled: true,
189
+ responsive_web_grok_show_grok_translated_post: true,
190
+ responsive_web_grok_analysis_button_from_backend: true,
191
+ post_ctas_fetch_enabled: true,
192
+ profile_label_improvements_pcf_label_in_post_enabled: true,
193
+ responsive_web_profile_redirect_enabled: false,
194
+ rweb_tipjar_consumption_enabled: false,
195
+ verified_phone_label_enabled: false,
196
+ rweb_cashtags_enabled: true,
197
+ longform_notetweets_rich_text_read_enabled: true,
198
+ longform_notetweets_inline_media_enabled: false,
199
+ articles_preview_enabled: true,
200
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
201
+ responsive_web_grok_community_note_auto_translation_is_enabled: true,
202
+ responsive_web_grok_image_annotation_enabled: true,
203
+ responsive_web_grok_imagine_annotation_enabled: true,
204
+ responsive_web_graphql_timeline_navigation_enabled: true,
205
+ creator_subscriptions_tweet_preview_api_enabled: true,
206
+ responsive_web_enhance_cards_enabled: false,
207
+ }),
208
+ /* eslint-enable @typescript-eslint/naming-convention */
209
+ },
210
+ paramsSerializer: { encode: encodeURIComponent },
211
+ };
212
+ }
213
+
154
214
  /**
155
215
  * @param id - The id of the tweet to be liked.
156
216
  */
@@ -440,22 +440,25 @@ export class UserRequests {
440
440
  */
441
441
  public static followed(count?: number, cursor?: string): AxiosRequestConfig {
442
442
  return {
443
- method: 'get',
444
- url: 'https://x.com/i/api/graphql/_qO7FJzShSKYWi9gtboE6A/HomeLatestTimeline',
445
- params: {
446
- /* eslint-disable @typescript-eslint/naming-convention */
447
- variables: JSON.stringify({
443
+ method: 'post',
444
+ url: 'https://x.com/i/api/graphql/iCyHMXVutL66dZyvMtyChA/HomeLatestTimeline',
445
+ data: {
446
+ variables: {
448
447
  count: count,
449
448
  cursor: cursor,
449
+ enableRanking: false,
450
450
  includePromotedContent: false,
451
- latestControlAvailable: true,
452
- withCommunity: false,
453
- }),
454
- features: JSON.stringify({
451
+ requestContext: 'launch',
452
+ seenTweetIds: [],
453
+ },
454
+ features: {
455
+ /* eslint-disable @typescript-eslint/naming-convention */
456
+
455
457
  rweb_video_screen_enabled: false,
458
+ rweb_cashtags_enabled: true,
456
459
  profile_label_improvements_pcf_label_in_post_enabled: true,
457
460
  responsive_web_profile_redirect_enabled: false,
458
- rweb_tipjar_consumption_enabled: true,
461
+ rweb_tipjar_consumption_enabled: false,
459
462
  verified_phone_label_enabled: true,
460
463
  creator_subscriptions_tweet_preview_api_enabled: true,
461
464
  responsive_web_graphql_timeline_navigation_enabled: true,
@@ -467,29 +470,32 @@ export class UserRequests {
467
470
  responsive_web_grok_analyze_post_followups_enabled: true,
468
471
  responsive_web_jetfuel_frame: true,
469
472
  responsive_web_grok_share_attachment_enabled: true,
473
+ responsive_web_grok_annotations_enabled: true,
470
474
  articles_preview_enabled: true,
471
475
  responsive_web_edit_tweet_api_enabled: true,
472
476
  graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
473
477
  view_counts_everywhere_api_enabled: true,
474
478
  longform_notetweets_consumption_enabled: true,
475
479
  responsive_web_twitter_article_tweet_consumption_enabled: true,
476
- tweet_awards_web_tipping_enabled: false,
477
- responsive_web_grok_show_grok_translated_post: false,
480
+ content_disclosure_indicator_enabled: true,
481
+ content_disclosure_ai_generated_indicator_enabled: true,
482
+ responsive_web_grok_show_grok_translated_post: true,
478
483
  responsive_web_grok_analysis_button_from_backend: true,
479
- creator_subscriptions_quote_tweet_preview_enabled: false,
484
+ post_ctas_fetch_enabled: true,
480
485
  freedom_of_speech_not_reach_fetch_enabled: true,
481
486
  standardized_nudges_misinfo: true,
482
487
  tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
483
488
  longform_notetweets_rich_text_read_enabled: true,
484
- longform_notetweets_inline_media_enabled: true,
489
+ longform_notetweets_inline_media_enabled: false,
485
490
  responsive_web_grok_image_annotation_enabled: true,
486
491
  responsive_web_grok_imagine_annotation_enabled: true,
487
- responsive_web_grok_community_note_auto_translation_is_enabled: false,
492
+ responsive_web_grok_community_note_auto_translation_is_enabled: true,
488
493
  responsive_web_enhance_cards_enabled: false,
489
- }),
490
- /* eslint-enable @typescript-eslint/naming-convention */
494
+
495
+ /* eslint-enable @typescript-eslint/naming-convention */
496
+ },
497
+ queryId: 'iCyHMXVutL66dZyvMtyChA',
491
498
  },
492
- paramsSerializer: { encode: encodeURIComponent },
493
499
  };
494
500
  }
495
501
 
@@ -915,23 +921,25 @@ export class UserRequests {
915
921
  */
916
922
  public static recommended(count?: number, cursor?: string): AxiosRequestConfig {
917
923
  return {
918
- method: 'get',
919
- url: 'https://x.com/i/api/graphql/V7xdnRnvW6a8vIsMr9xK7A/HomeTimeline',
920
- params: {
921
- /* eslint-disable @typescript-eslint/naming-convention */
922
- variables: JSON.stringify({
924
+ method: 'post',
925
+ url: 'https://x.com/i/api/graphql/jYMvLJJjGjO3aKWY3bP5HA/HomeTimeline',
926
+ data: {
927
+ variables: {
923
928
  count: count,
924
929
  cursor: cursor,
925
930
  includePromotedContent: false,
926
- latestControlAvailable: true,
931
+ requestContext: 'launch',
927
932
  withCommunity: false,
928
933
  seenTweetIds: [],
929
- }),
930
- features: JSON.stringify({
934
+ },
935
+ features: {
936
+ /* eslint-disable @typescript-eslint/naming-convention */
937
+
931
938
  rweb_video_screen_enabled: false,
939
+ rweb_cashtags_enabled: true,
932
940
  profile_label_improvements_pcf_label_in_post_enabled: true,
933
941
  responsive_web_profile_redirect_enabled: false,
934
- rweb_tipjar_consumption_enabled: true,
942
+ rweb_tipjar_consumption_enabled: false,
935
943
  verified_phone_label_enabled: true,
936
944
  creator_subscriptions_tweet_preview_api_enabled: true,
937
945
  responsive_web_graphql_timeline_navigation_enabled: true,
@@ -943,29 +951,48 @@ export class UserRequests {
943
951
  responsive_web_grok_analyze_post_followups_enabled: true,
944
952
  responsive_web_jetfuel_frame: true,
945
953
  responsive_web_grok_share_attachment_enabled: true,
954
+ responsive_web_grok_annotations_enabled: true,
946
955
  articles_preview_enabled: true,
947
956
  responsive_web_edit_tweet_api_enabled: true,
948
957
  graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
949
958
  view_counts_everywhere_api_enabled: true,
950
959
  longform_notetweets_consumption_enabled: true,
951
960
  responsive_web_twitter_article_tweet_consumption_enabled: true,
952
- tweet_awards_web_tipping_enabled: false,
953
- responsive_web_grok_show_grok_translated_post: false,
961
+ content_disclosure_indicator_enabled: true,
962
+ content_disclosure_ai_generated_indicator_enabled: true,
963
+ responsive_web_grok_show_grok_translated_post: true,
954
964
  responsive_web_grok_analysis_button_from_backend: true,
955
- creator_subscriptions_quote_tweet_preview_enabled: false,
965
+ post_ctas_fetch_enabled: true,
956
966
  freedom_of_speech_not_reach_fetch_enabled: true,
957
967
  standardized_nudges_misinfo: true,
958
968
  tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
959
969
  longform_notetweets_rich_text_read_enabled: true,
960
- longform_notetweets_inline_media_enabled: true,
970
+ longform_notetweets_inline_media_enabled: false,
961
971
  responsive_web_grok_image_annotation_enabled: true,
962
972
  responsive_web_grok_imagine_annotation_enabled: true,
963
- responsive_web_grok_community_note_auto_translation_is_enabled: false,
973
+ responsive_web_grok_community_note_auto_translation_is_enabled: true,
964
974
  responsive_web_enhance_cards_enabled: false,
965
- }),
975
+
976
+ /* eslint-enable @typescript-eslint/naming-convention */
977
+ },
978
+ queryId: 'jYMvLJJjGjO3aKWY3bP5HA',
979
+ },
980
+ };
981
+ }
982
+
983
+ /**
984
+ * @param id - The id of the user to remove from the authenticated user's followers.
985
+ */
986
+ public static removeFollower(id: string): AxiosRequestConfig {
987
+ return {
988
+ method: 'post',
989
+ url: 'https://x.com/i/api/graphql/QpNfg0kpPRfjROQ_9eOLXA/RemoveFollower',
990
+ data: {
991
+ /* eslint-disable @typescript-eslint/naming-convention */
992
+ variables: { target_user_id: id },
993
+ queryId: 'QpNfg0kpPRfjROQ_9eOLXA',
966
994
  /* eslint-enable @typescript-eslint/naming-convention */
967
995
  },
968
- paramsSerializer: { encode: encodeURIComponent },
969
996
  };
970
997
  }
971
998
 
@@ -5,11 +5,17 @@ import { List } from '../../models/data/List';
5
5
  import { Tweet } from '../../models/data/Tweet';
6
6
  import { User } from '../../models/data/User';
7
7
  import { RettiwtConfig } from '../../models/RettiwtConfig';
8
+ import { IListUpdates, INewList } from '../../types/args/PostArgs';
8
9
  import { IListMemberAddResponse } from '../../types/raw/list/AddMember';
10
+ import { IListCreateResponse } from '../../types/raw/list/Create';
11
+ import { IListDeleteResponse } from '../../types/raw/list/Delete';
9
12
  import { IListDetailsResponse } from '../../types/raw/list/Details';
10
13
  import { IListMembersResponse } from '../../types/raw/list/Members';
14
+ import { IListMuteResponse } from '../../types/raw/list/Mute';
11
15
  import { IListMemberRemoveResponse } from '../../types/raw/list/RemoveMember';
12
16
  import { IListTweetsResponse } from '../../types/raw/list/Tweets';
17
+ import { IListUnmuteResponse } from '../../types/raw/list/Unmute';
18
+ import { IListUpdateResponse } from '../../types/raw/list/Update';
13
19
 
14
20
  import { FetcherService } from './FetcherService';
15
21
 
@@ -64,6 +70,82 @@ export class ListService extends FetcherService {
64
70
  return data;
65
71
  }
66
72
 
73
+ /**
74
+ * Create a list.
75
+ *
76
+ * @param list - The details of the list to create.
77
+ *
78
+ * @returns The ID of the created list. If creation was unsuccessful, return `undefined`.
79
+ *
80
+ * @example
81
+ *
82
+ * ```ts
83
+ * import { Rettiwt } from 'rettiwt-api';
84
+ *
85
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
86
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
87
+ *
88
+ * // Creating a public list
89
+ * rettiwt.list.create({ name: 'My list', description: 'List description', isPrivate: false })
90
+ * .then(res => {
91
+ * console.log(res);
92
+ * })
93
+ * .catch(err => {
94
+ * console.log(err);
95
+ * });
96
+ * ```
97
+ */
98
+ public async create(list: INewList): Promise<string | undefined> {
99
+ const resource: ResourceType = ResourceType.LIST_CREATE;
100
+
101
+ // Creating the list
102
+ const response = await this.request<IListCreateResponse>(resource, {
103
+ list: list,
104
+ });
105
+
106
+ // Deserializing response
107
+ const data = Extractors[resource](response.data);
108
+
109
+ return data;
110
+ }
111
+
112
+ /**
113
+ * Delete a list.
114
+ *
115
+ * @param id - The ID of the list to delete.
116
+ *
117
+ * @returns Whether deletion was successful.
118
+ *
119
+ * @example
120
+ *
121
+ * ```ts
122
+ * import { Rettiwt } from 'rettiwt-api';
123
+ *
124
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
125
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
126
+ *
127
+ * // Deleting the list with ID '1234567890'
128
+ * rettiwt.list.delete('1234567890')
129
+ * .then(res => {
130
+ * console.log(res);
131
+ * })
132
+ * .catch(err => {
133
+ * console.log(err);
134
+ * });
135
+ * ```
136
+ */
137
+ public async delete(id: string): Promise<boolean> {
138
+ const resource: ResourceType = ResourceType.LIST_DELETE;
139
+
140
+ // Deleting the list
141
+ const response = await this.request<IListDeleteResponse>(resource, { id: id });
142
+
143
+ // Deserializing response
144
+ const data = Extractors[resource](response.data);
145
+
146
+ return data;
147
+ }
148
+
67
149
  /**
68
150
  * Get the details of a list.
69
151
  *
@@ -150,6 +232,43 @@ export class ListService extends FetcherService {
150
232
  return data;
151
233
  }
152
234
 
235
+ /**
236
+ * Mute a list.
237
+ *
238
+ * @param id - The ID of the list to mute.
239
+ *
240
+ * @returns Whether muting was successful.
241
+ *
242
+ * @example
243
+ *
244
+ * ```ts
245
+ * import { Rettiwt } from 'rettiwt-api';
246
+ *
247
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
248
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
249
+ *
250
+ * // Muting the list with ID '1234567890'
251
+ * rettiwt.list.mute('1234567890')
252
+ * .then(res => {
253
+ * console.log(res);
254
+ * })
255
+ * .catch(err => {
256
+ * console.log(err);
257
+ * });
258
+ * ```
259
+ */
260
+ public async mute(id: string): Promise<boolean> {
261
+ const resource: ResourceType = ResourceType.LIST_MUTE;
262
+
263
+ // Muting the list
264
+ const response = await this.request<IListMuteResponse>(resource, { id: id });
265
+
266
+ // Deserializing response
267
+ const data = Extractors[resource](response.data);
268
+
269
+ return data;
270
+ }
271
+
153
272
  /**
154
273
  * Remove a member from a list.
155
274
  *
@@ -238,4 +357,86 @@ export class ListService extends FetcherService {
238
357
 
239
358
  return data;
240
359
  }
360
+
361
+ /**
362
+ * Unmute a list.
363
+ *
364
+ * @param id - The ID of the list to unmute.
365
+ *
366
+ * @returns Whether unmuting was successful.
367
+ *
368
+ * @example
369
+ *
370
+ * ```ts
371
+ * import { Rettiwt } from 'rettiwt-api';
372
+ *
373
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
374
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
375
+ *
376
+ * // Unmuting the list with ID '1234567890'
377
+ * rettiwt.list.unmute('1234567890')
378
+ * .then(res => {
379
+ * console.log(res);
380
+ * })
381
+ * .catch(err => {
382
+ * console.log(err);
383
+ * });
384
+ * ```
385
+ */
386
+ public async unmute(id: string): Promise<boolean> {
387
+ const resource: ResourceType = ResourceType.LIST_UNMUTE;
388
+
389
+ // Unmuting the list
390
+ const response = await this.request<IListUnmuteResponse>(resource, { id: id });
391
+
392
+ // Deserializing response
393
+ const data = Extractors[resource](response.data);
394
+
395
+ return data;
396
+ }
397
+
398
+ /**
399
+ * Update a list.
400
+ *
401
+ * @param id - The ID of the list to update.
402
+ * @param updates - The updates to apply to the list.
403
+ *
404
+ * @returns The updated list. If update was unsuccessful, return `undefined`.
405
+ *
406
+ * @remarks
407
+ * Fields omitted from `updates` are left unchanged. Use an empty string for
408
+ * `description` to clear the existing description.
409
+ *
410
+ * @example
411
+ *
412
+ * ```ts
413
+ * import { Rettiwt } from 'rettiwt-api';
414
+ *
415
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
416
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
417
+ *
418
+ * // Updating the list with ID '1234567890'
419
+ * rettiwt.list.update('1234567890', { name: 'My list', description: 'List description', isPrivate: false })
420
+ * .then(res => {
421
+ * console.log(res);
422
+ * })
423
+ * .catch(err => {
424
+ * console.log(err);
425
+ * });
426
+ * ```
427
+ */
428
+ public async update(id: string, updates: IListUpdates): Promise<List | undefined> {
429
+ const resource: ResourceType = ResourceType.LIST_UPDATE;
430
+
431
+ // Updating the list
432
+ const response = await this.request<IListUpdateResponse>(resource, {
433
+ id: id,
434
+ listUpdates: updates,
435
+ });
436
+
437
+ // Deserializing response
438
+ const data = Extractors[resource](response.data);
439
+
440
+ return data;
441
+ }
241
442
  }
@@ -15,6 +15,7 @@ import { IMediaInitializeUploadResponse } from '../../types/raw/media/InitalizeU
15
15
  import { ITweetBookmarkResponse } from '../../types/raw/tweet/Bookmark';
16
16
  import { ITweetDetailsResponse } from '../../types/raw/tweet/Details';
17
17
  import { ITweetDetailsBulkResponse } from '../../types/raw/tweet/DetailsBulk';
18
+ import { ITweetHistoryResponse } from '../../types/raw/tweet/History';
18
19
  import { ITweetLikeResponse } from '../../types/raw/tweet/Like';
19
20
  import { ITweetLikersResponse } from '../../types/raw/tweet/Likers';
20
21
  import { ITweetPostNoteResponse, ITweetPostResponse } from '../../types/raw/tweet/Post';
@@ -176,6 +177,43 @@ export class TweetService extends FetcherService {
176
177
  }
177
178
  }
178
179
 
180
+ /**
181
+ * Get the edit history of a tweet.
182
+ *
183
+ * @param id - The ID of the target tweet.
184
+ *
185
+ * @returns The list of tweet versions, ordered by the returned timeline.
186
+ *
187
+ * @example
188
+ *
189
+ * ```ts
190
+ * import { Rettiwt } from 'rettiwt-api';
191
+ *
192
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
193
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
194
+ *
195
+ * // Fetching the edit history of the tweet with id '1234567890'
196
+ * rettiwt.tweet.history('1234567890')
197
+ * .then(res => {
198
+ * console.log(res);
199
+ * })
200
+ * .catch(err => {
201
+ * console.log(err);
202
+ * });
203
+ * ```
204
+ */
205
+ public async history(id: string): Promise<Tweet[]> {
206
+ const resource = ResourceType.TWEET_HISTORY;
207
+
208
+ // Fetching raw tweet history
209
+ const response = await this.request<ITweetHistoryResponse>(resource, { id: id });
210
+
211
+ // Deserializing response
212
+ const data = Extractors[resource](response.data);
213
+
214
+ return data;
215
+ }
216
+
179
217
  /**
180
218
  * Like a tweet.
181
219
  *
@@ -32,6 +32,7 @@ import { IUserMediaResponse } from '../../types/raw/user/Media';
32
32
  import { IUserNotificationsResponse } from '../../types/raw/user/Notifications';
33
33
  import { IUserProfileUpdateResponse } from '../../types/raw/user/ProfileUpdate';
34
34
  import { IUserRecommendedResponse } from '../../types/raw/user/Recommended';
35
+ import { IUserRemoveFollowerResponse } from '../../types/raw/user/RemoveFollower';
35
36
  import { IUserSearchResponse } from '../../types/raw/user/Search';
36
37
  import { IUserSettingsResponse } from '../../types/raw/user/Settings';
37
38
  import { IUserSubscriptionsResponse } from '../../types/raw/user/Subscriptions';
@@ -1041,6 +1042,45 @@ export class UserService extends FetcherService {
1041
1042
  return data;
1042
1043
  }
1043
1044
 
1045
+ /**
1046
+ * Remove a user from the authenticated user's followers (force-unfollow).
1047
+ *
1048
+ * @param id - The ID of the user to remove as a follower.
1049
+ *
1050
+ * @returns Whether the user was removed successfully.
1051
+ *
1052
+ * @throws Code 108 if given user id is invalid.
1053
+ *
1054
+ * @example
1055
+ *
1056
+ * ```ts
1057
+ * import { Rettiwt } from 'rettiwt-api';
1058
+ *
1059
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
1060
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
1061
+ *
1062
+ * // Removing the User with id '1234567890' from the authenticated user's followers
1063
+ * rettiwt.user.removeFollower('1234567890')
1064
+ * .then(res => {
1065
+ * console.log(res);
1066
+ * })
1067
+ * .catch(err => {
1068
+ * console.log(err);
1069
+ * });
1070
+ * ```
1071
+ */
1072
+ public async removeFollower(id: string): Promise<boolean> {
1073
+ const resource = ResourceType.USER_REMOVE_FOLLOWER;
1074
+
1075
+ // Removing the follower
1076
+ const response = await this.request<IUserRemoveFollowerResponse>(resource, { id: id });
1077
+
1078
+ // Deserializing the response
1079
+ const data = Extractors[resource](response.data) ?? false;
1080
+
1081
+ return data;
1082
+ }
1083
+
1044
1084
  /**
1045
1085
  * Get the reply timeline of a user.
1046
1086
  *
@@ -18,6 +18,10 @@ export interface IPostArgs {
18
18
  * - {@link ResourceType.TWEET_UNLIKE}
19
19
  * - {@link ResourceType.TWEET_UNPOST}
20
20
  * - {@link ResourceType.TWEET_UNRETWEET}
21
+ * - {@link ResourceType.LIST_DELETE}
22
+ * - {@link ResourceType.LIST_MUTE}
23
+ * - {@link ResourceType.LIST_UNMUTE}
24
+ * - {@link ResourceType.LIST_UPDATE}
21
25
  * - {@link ResourceType.USER_FOLLOW}
22
26
  * - {@link ResourceType.USER_UNFOLLOW}
23
27
  *
@@ -26,6 +30,23 @@ export interface IPostArgs {
26
30
  */
27
31
  id?: string;
28
32
 
33
+ /**
34
+ * The list that is to be created.
35
+ *
36
+ * @remarks
37
+ * Required only when creating a list using the following resources:
38
+ * - {@link ResourceType.LIST_CREATE}
39
+ */
40
+ list?: INewList;
41
+
42
+ /**
43
+ * The updates to apply to an existing list.
44
+ *
45
+ * @remarks
46
+ * Required only when updating a list using {@link ResourceType.LIST_UPDATE}.
47
+ */
48
+ listUpdates?: IListUpdates;
49
+
29
50
  /**
30
51
  * The new username to set.
31
52
  *
@@ -104,6 +125,43 @@ export interface IPostArgs {
104
125
  changePassword?: IChangePasswordArgs;
105
126
  }
106
127
 
128
+ /**
129
+ * Configuration for the list to be created.
130
+ *
131
+ * @public
132
+ */
133
+ export interface INewList {
134
+ /** The list name. */
135
+ name: string;
136
+
137
+ /** The list description. */
138
+ description?: string;
139
+
140
+ /** Whether the list is private. */
141
+ isPrivate?: boolean;
142
+ }
143
+
144
+ /**
145
+ * Configuration for the updates to apply to an existing list.
146
+ *
147
+ * @public
148
+ */
149
+ export interface IListUpdates {
150
+ /** The updated list name. */
151
+ name?: string;
152
+
153
+ /**
154
+ * The updated list description.
155
+ *
156
+ * @remarks
157
+ * Use an empty string to clear the existing description.
158
+ */
159
+ description?: string;
160
+
161
+ /** Whether the list is private. */
162
+ isPrivate?: boolean;
163
+ }
164
+
107
165
  /**
108
166
  * Configuration for the new tweet to be posted.
109
167
  *
@@ -0,0 +1,16 @@
1
+ /* eslint-disable */
2
+
3
+ /**
4
+ * The raw data received when creating a tweet list.
5
+ *
6
+ * @public
7
+ */
8
+ export interface IListCreateResponse {
9
+ data?: {
10
+ list?: IListCreateList;
11
+ };
12
+ }
13
+
14
+ interface IListCreateList {
15
+ id_str?: string;
16
+ }
@@ -0,0 +1,12 @@
1
+ /* eslint-disable */
2
+
3
+ /**
4
+ * The raw data received when deleting a tweet list.
5
+ *
6
+ * @public
7
+ */
8
+ export interface IListDeleteResponse {
9
+ data?: {
10
+ list_delete?: string;
11
+ };
12
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The raw data received when muting a tweet list.
3
+ *
4
+ * @public
5
+ */
6
+ export interface IListMuteResponse {
7
+ data?: {
8
+ list?: string;
9
+ };
10
+ }