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
@@ -0,0 +1,48 @@
1
+ import { ITimelineTweet } from '../composite/TimelineTweet';
2
+ /**
3
+ * Represents the raw response received when fetching a tweet's edit history.
4
+ *
5
+ * @public
6
+ */
7
+ export interface ITweetHistoryResponse {
8
+ data?: {
9
+ tweet_result_by_rest_id?: {
10
+ result?: {
11
+ edit_history_timeline?: {
12
+ timeline?: ITweetHistoryTimeline;
13
+ };
14
+ };
15
+ };
16
+ };
17
+ }
18
+ export interface ITweetHistoryTimeline {
19
+ instructions?: ITweetHistoryInstruction[];
20
+ }
21
+ export interface ITweetHistoryInstruction {
22
+ direction?: string;
23
+ entries?: ITweetHistoryEntry[];
24
+ type: string;
25
+ }
26
+ export interface ITweetHistoryEntry {
27
+ content?: ITweetHistoryModule;
28
+ entryId: string;
29
+ sortIndex?: string;
30
+ }
31
+ export interface ITweetHistoryModule {
32
+ __typename: string;
33
+ displayType: string;
34
+ entryType: string;
35
+ header?: ITweetHistoryHeader;
36
+ items?: ITweetHistoryItem[];
37
+ }
38
+ export interface ITweetHistoryHeader {
39
+ displayType: string;
40
+ sticky: boolean;
41
+ text: string;
42
+ }
43
+ export interface ITweetHistoryItem {
44
+ entryId: string;
45
+ item: {
46
+ itemContent: ITimelineTweet;
47
+ };
48
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* eslint-disable */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=History.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"History.js","sourceRoot":"","sources":["../../../../src/types/raw/tweet/History.ts"],"names":[],"mappings":";AAAA,oBAAoB"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The raw data received when removing a given user from the authenticated user's followers.
3
+ *
4
+ * @public
5
+ */
6
+ export interface IUserRemoveFollowerResponse {
7
+ data?: {
8
+ remove_follower?: {
9
+ __typename?: string;
10
+ unfollow_success_reason?: string;
11
+ };
12
+ };
13
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* eslint-disable */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=RemoveFollower.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemoveFollower.js","sourceRoot":"","sources":["../../../../src/types/raw/user/RemoveFollower.ts"],"names":[],"mappings":";AAAA,oBAAoB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rettiwt-api",
3
- "version": "7.0.2",
3
+ "version": "7.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "description": "An API for fetching data from TwitterAPI, without any rate limits!",
@@ -14,15 +14,21 @@ import { IConversationTimelineResponse } from '../types/raw/dm/Conversation';
14
14
  import { IInboxInitialResponse } from '../types/raw/dm/InboxInitial';
15
15
  import { IInboxTimelineResponse } from '../types/raw/dm/InboxTimeline';
16
16
  import { IListMemberAddResponse } from '../types/raw/list/AddMember';
17
+ import { IListCreateResponse } from '../types/raw/list/Create';
18
+ import { IListDeleteResponse } from '../types/raw/list/Delete';
17
19
  import { IListDetailsResponse } from '../types/raw/list/Details';
18
20
  import { IListMembersResponse } from '../types/raw/list/Members';
21
+ import { IListMuteResponse } from '../types/raw/list/Mute';
19
22
  import { IListMemberRemoveResponse } from '../types/raw/list/RemoveMember';
20
23
  import { IListTweetsResponse } from '../types/raw/list/Tweets';
24
+ import { IListUnmuteResponse } from '../types/raw/list/Unmute';
25
+ import { IListUpdateResponse } from '../types/raw/list/Update';
21
26
  import { IMediaInitializeUploadResponse } from '../types/raw/media/InitalizeUpload';
22
27
  import { IAudioSpaceByIdResponse } from '../types/raw/space/AudioSpaceById';
23
28
  import { ITweetBookmarkResponse } from '../types/raw/tweet/Bookmark';
24
29
  import { ITweetDetailsResponse } from '../types/raw/tweet/Details';
25
30
  import { ITweetDetailsBulkResponse } from '../types/raw/tweet/DetailsBulk';
31
+ import { ITweetHistoryResponse } from '../types/raw/tweet/History';
26
32
  import { ITweetLikeResponse } from '../types/raw/tweet/Like';
27
33
  import { ITweetLikersResponse } from '../types/raw/tweet/Likers';
28
34
  import { ITweetPostNoteResponse, ITweetPostResponse } from '../types/raw/tweet/Post';
@@ -56,6 +62,7 @@ import { IUserMediaResponse } from '../types/raw/user/Media';
56
62
  import { IUserNotificationsResponse } from '../types/raw/user/Notifications';
57
63
  import { IUserProfileUpdateResponse } from '../types/raw/user/ProfileUpdate';
58
64
  import { IUserRecommendedResponse } from '../types/raw/user/Recommended';
65
+ import { IUserRemoveFollowerResponse } from '../types/raw/user/RemoveFollower';
59
66
  import { IUserSearchResponse } from '../types/raw/user/Search';
60
67
  import { IUserSettingsResponse } from '../types/raw/user/Settings';
61
68
  import { IUserSubscriptionsResponse } from '../types/raw/user/Subscriptions';
@@ -71,6 +78,8 @@ import { IUserUnfollowResponse } from '../types/raw/user/Unfollow';
71
78
  export const Extractors = {
72
79
  /* eslint-disable @typescript-eslint/naming-convention */
73
80
 
81
+ LIST_CREATE: (response: IListCreateResponse): string | undefined => response.data?.list?.id_str ?? undefined,
82
+ LIST_DELETE: (response: IListDeleteResponse): boolean => response.data?.list_delete === 'Done',
74
83
  LIST_DETAILS: (response: IListDetailsResponse, id: string): List | undefined => List.single(response, id),
75
84
  LIST_MEMBERS: (response: IListMembersResponse): CursoredData<User> =>
76
85
  new CursoredData<User>(response, BaseType.USER),
@@ -78,8 +87,12 @@ export const Extractors = {
78
87
  response.data?.list?.member_count ?? undefined,
79
88
  LIST_MEMBER_REMOVE: (response: IListMemberRemoveResponse): number | undefined =>
80
89
  response.data?.list?.member_count ?? undefined,
90
+ LIST_MUTE: (response: IListMuteResponse): boolean => response.data?.list === 'Done',
81
91
  LIST_TWEETS: (response: IListTweetsResponse): CursoredData<Tweet> =>
82
92
  new CursoredData<Tweet>(response, BaseType.TWEET),
93
+ LIST_UNMUTE: (response: IListUnmuteResponse): boolean => response.data?.list === 'Done',
94
+ LIST_UPDATE: (response: IListUpdateResponse): List | undefined =>
95
+ response.data?.list ? new List(response.data.list) : undefined,
83
96
 
84
97
  MEDIA_UPLOAD_APPEND: (): void => undefined,
85
98
  MEDIA_UPLOAD_FINALIZE: (): void => undefined,
@@ -97,6 +110,7 @@ export const Extractors = {
97
110
  TWEET_DETAILS: (response: ITweetDetailsResponse, id: string): Tweet | undefined => Tweet.single(response, id),
98
111
  TWEET_DETAILS_ALT: (response: ITweetRepliesResponse, id: string): Tweet | undefined => Tweet.single(response, id),
99
112
  TWEET_DETAILS_BULK: (response: ITweetDetailsBulkResponse, ids: string[]): Tweet[] => Tweet.multiple(response, ids),
113
+ TWEET_HISTORY: (response: ITweetHistoryResponse): Tweet[] => Tweet.timeline(response),
100
114
  TWEET_LIKE: (response: ITweetLikeResponse): boolean => (response?.data?.favorite_tweet ? true : false),
101
115
  TWEET_LIKERS: (response: ITweetLikersResponse): CursoredData<User> =>
102
116
  new CursoredData<User>(response, BaseType.USER),
@@ -154,6 +168,8 @@ export const Extractors = {
154
168
  new CursoredData<Tweet>(response, BaseType.TWEET),
155
169
  USER_NOTIFICATIONS: (response: IUserNotificationsResponse): CursoredData<Notification> =>
156
170
  new CursoredData<Notification>(response, BaseType.NOTIFICATION),
171
+ USER_REMOVE_FOLLOWER: (response: IUserRemoveFollowerResponse): boolean =>
172
+ response?.data?.remove_follower?.unfollow_success_reason ? true : false,
157
173
  USER_SEARCH: (response: IUserSearchResponse): CursoredData<User> => new CursoredData<User>(response, BaseType.USER),
158
174
  USER_SUBSCRIPTIONS: (response: IUserSubscriptionsResponse): CursoredData<User> =>
159
175
  new CursoredData<User>(response, BaseType.USER),
@@ -28,6 +28,7 @@ export const FetchResourcesGroup = [
28
28
  ResourceType.TWEET_DETAILS,
29
29
  ResourceType.TWEET_DETAILS_ALT,
30
30
  ResourceType.TWEET_DETAILS_BULK,
31
+ ResourceType.TWEET_HISTORY,
31
32
  ResourceType.TWEET_LIKERS,
32
33
  ResourceType.TWEET_REPLIES,
33
34
  ResourceType.TWEET_RETWEETERS,
@@ -62,8 +63,13 @@ export const FetchResourcesGroup = [
62
63
  * @internal
63
64
  */
64
65
  export const PostResourcesGroup = [
66
+ ResourceType.LIST_CREATE,
67
+ ResourceType.LIST_DELETE,
65
68
  ResourceType.LIST_MEMBER_ADD,
66
69
  ResourceType.LIST_MEMBER_REMOVE,
70
+ ResourceType.LIST_MUTE,
71
+ ResourceType.LIST_UNMUTE,
72
+ ResourceType.LIST_UPDATE,
67
73
  ResourceType.MEDIA_UPLOAD_APPEND,
68
74
  ResourceType.MEDIA_UPLOAD_FINALIZE,
69
75
  ResourceType.MEDIA_UPLOAD_INITIALIZE,
@@ -80,6 +86,7 @@ export const PostResourcesGroup = [
80
86
  ResourceType.TWEET_UNRETWEET,
81
87
  ResourceType.TWEET_UNSCHEDULE,
82
88
  ResourceType.USER_FOLLOW,
89
+ ResourceType.USER_REMOVE_FOLLOWER,
83
90
  ResourceType.USER_UNFOLLOW,
84
91
  ResourceType.USER_PROFILE_UPDATE,
85
92
  ResourceType.USER_PROFILE_IMAGE_UPDATE,
@@ -20,11 +20,16 @@ import { TweetRepliesSortTypeMap } from './Tweet';
20
20
  export const Requests: { [key in keyof typeof ResourceType]: (args: IFetchArgs | IPostArgs) => AxiosRequestConfig } = {
21
21
  /* eslint-disable @typescript-eslint/naming-convention */
22
22
 
23
+ LIST_CREATE: (args: IPostArgs) => ListRequests.create(args.list!),
24
+ LIST_DELETE: (args: IPostArgs) => ListRequests.delete(args.id!),
23
25
  LIST_DETAILS: (args: IFetchArgs) => ListRequests.details(args.id!),
24
26
  LIST_MEMBERS: (args: IFetchArgs) => ListRequests.members(args.id!, args.count, args.cursor),
25
27
  LIST_MEMBER_ADD: (args: IPostArgs) => ListRequests.addMember(args.id!, args.userId!),
26
28
  LIST_MEMBER_REMOVE: (args: IPostArgs) => ListRequests.removeMember(args.id!, args.userId!),
29
+ LIST_MUTE: (args: IPostArgs) => ListRequests.mute(args.id!),
27
30
  LIST_TWEETS: (args: IFetchArgs) => ListRequests.tweets(args.id!, args.count, args.cursor),
31
+ LIST_UNMUTE: (args: IPostArgs) => ListRequests.unmute(args.id!),
32
+ LIST_UPDATE: (args: IPostArgs) => ListRequests.update(args.id!, args.listUpdates!),
28
33
 
29
34
  MEDIA_UPLOAD_APPEND: (args: IPostArgs) => MediaRequests.appendUpload(args.upload!.id!, args.upload!.media!),
30
35
  MEDIA_UPLOAD_FINALIZE: (args: IPostArgs) => MediaRequests.finalizeUpload(args.upload!.id!),
@@ -42,6 +47,7 @@ export const Requests: { [key in keyof typeof ResourceType]: (args: IFetchArgs |
42
47
  TWEET_DETAILS: (args: IFetchArgs) => TweetRequests.details(args.id!),
43
48
  TWEET_DETAILS_ALT: (args: IFetchArgs) => TweetRequests.replies(args.id!),
44
49
  TWEET_DETAILS_BULK: (args: IFetchArgs) => TweetRequests.bulkDetails(args.ids!),
50
+ TWEET_HISTORY: (args: IFetchArgs) => TweetRequests.history(args.id!),
45
51
  TWEET_LIKE: (args: IPostArgs) => TweetRequests.like(args.id!),
46
52
  TWEET_LIKERS: (args: IFetchArgs) => TweetRequests.likers(args.id!, args.count, args.cursor),
47
53
  TWEET_POST: (args: IPostArgs) => TweetRequests.post(args.tweet!),
@@ -85,6 +91,7 @@ export const Requests: { [key in keyof typeof ResourceType]: (args: IFetchArgs |
85
91
  USER_LISTS: (args: IFetchArgs) => UserRequests.lists(args.id!, args.count, args.cursor),
86
92
  USER_MEDIA: (args: IFetchArgs) => UserRequests.media(args.id!, args.count, args.cursor),
87
93
  USER_NOTIFICATIONS: (args: IFetchArgs) => UserRequests.notifications(args.count, args.cursor),
94
+ USER_REMOVE_FOLLOWER: (args: IPostArgs) => UserRequests.removeFollower(args.id!),
88
95
  USER_SEARCH: (args: IFetchArgs) => UserRequests.search(args.id!, args.count, args.cursor),
89
96
  USER_SUBSCRIPTIONS: (args: IFetchArgs) => UserRequests.subscriptions(args.id!, args.count, args.cursor),
90
97
  USER_TIMELINE: (args: IFetchArgs) => UserRequests.tweets(args.id!, args.count, args.cursor),
@@ -2,6 +2,20 @@ import { Command, createCommand } from 'commander';
2
2
 
3
3
  import { output } from '../helper/CliUtils';
4
4
  import { Rettiwt } from '../Rettiwt';
5
+ import { IListUpdates } from '../types/args/PostArgs';
6
+
7
+ type ListCreateOptions = {
8
+ description?: boolean | string;
9
+ private?: boolean;
10
+ };
11
+
12
+ type ListUpdateOptions = ListCreateOptions & {
13
+ public?: boolean;
14
+ };
15
+
16
+ function getDescription(description?: boolean | string): string | undefined {
17
+ return typeof description === 'string' ? description : undefined;
18
+ }
5
19
 
6
20
  /**
7
21
  * Creates a new 'list' command which uses the given Rettiwt instance.
@@ -13,6 +27,92 @@ function createListCommand(rettiwt: Rettiwt): Command {
13
27
  // Creating the 'list' command
14
28
  const list = createCommand('list').description('Access resources related to lists');
15
29
 
30
+ // Create
31
+ list.command('create')
32
+ .description('Create a new list')
33
+ .argument('<name>', 'The name of the tweet list')
34
+ .option('-d, --description [string]', 'The description of the tweet list')
35
+ .option('--private', 'Create a private list')
36
+ .action(async (name: string, options?: ListCreateOptions) => {
37
+ try {
38
+ const id = await rettiwt.list.create({
39
+ name: name,
40
+ description: getDescription(options?.description),
41
+ isPrivate: options?.private,
42
+ });
43
+ output(id);
44
+ } catch (error) {
45
+ output(error);
46
+ }
47
+ });
48
+
49
+ // Update
50
+ list.command('update')
51
+ .description('Update a list')
52
+ .argument('<id>', 'The ID of the tweet list')
53
+ .argument('[name]', 'The updated name of the tweet list')
54
+ .option('-d, --description [string]', 'The updated description of the tweet list')
55
+ .option('--private', 'Update to a private list')
56
+ .option('--public', 'Update to a public list')
57
+ .action(async (id: string, name?: string, options?: ListUpdateOptions) => {
58
+ try {
59
+ if (options?.private && options?.public) {
60
+ throw new Error('List cannot be both private and public');
61
+ }
62
+
63
+ const updates: IListUpdates = {
64
+ ...(name !== undefined ? { name: name } : {}),
65
+ ...(typeof options?.description === 'string' ? { description: options.description } : {}),
66
+ ...(options?.private ? { isPrivate: true } : {}),
67
+ ...(options?.public ? { isPrivate: false } : {}),
68
+ };
69
+
70
+ const details = await rettiwt.list.update(id, updates);
71
+ output(details);
72
+ } catch (error) {
73
+ output(error);
74
+ }
75
+ });
76
+
77
+ // Delete
78
+ list.command('delete')
79
+ .description('Delete a list')
80
+ .argument('<id>', 'The ID of the tweet list')
81
+ .action(async (id: string) => {
82
+ try {
83
+ const deleted = await rettiwt.list.delete(id);
84
+ output(deleted);
85
+ } catch (error) {
86
+ output(error);
87
+ }
88
+ });
89
+
90
+ // Mute
91
+ list.command('mute')
92
+ .description('Mute a list')
93
+ .argument('<id>', 'The ID of the tweet list')
94
+ .action(async (id: string) => {
95
+ try {
96
+ const muted = await rettiwt.list.mute(id);
97
+ output(muted);
98
+ } catch (error) {
99
+ output(error);
100
+ }
101
+ });
102
+
103
+ // Unmute
104
+ list.command('unmute')
105
+ .description('Unmute a list')
106
+ .argument('<id>', 'The ID of the tweet list')
107
+ .action(async (id: string) => {
108
+ try {
109
+ const unmuted = await rettiwt.list.unmute(id);
110
+ output(unmuted);
111
+ } catch (error) {
112
+ output(error);
113
+ }
114
+ });
115
+
16
116
  // Add member
17
117
  list.command('add-member')
18
118
  .description('Add a new member to a list')
@@ -55,6 +55,20 @@ function createTweetCommand(rettiwt: Rettiwt): Command {
55
55
  }
56
56
  });
57
57
 
58
+ // History
59
+ tweet
60
+ .command('history')
61
+ .description('Fetch the edit history of a tweet')
62
+ .argument('<id>', 'The id of the tweet')
63
+ .action(async (id: string) => {
64
+ try {
65
+ const tweets = await rettiwt.tweet.history(id);
66
+ output(tweets);
67
+ } catch (error) {
68
+ output(error);
69
+ }
70
+ });
71
+
58
72
  // Like
59
73
  tweet
60
74
  .command('like')
@@ -278,6 +278,19 @@ function createUserCommand(rettiwt: Rettiwt): Command {
278
278
  }
279
279
  });
280
280
 
281
+ // Remove Follower
282
+ user.command('remove-follower')
283
+ .description("Remove a user from the authenticated user's followers")
284
+ .argument('<id>', 'The user to remove as a follower')
285
+ .action(async (id: string) => {
286
+ try {
287
+ const result = await rettiwt.user.removeFollower(id);
288
+ output(result);
289
+ } catch (error) {
290
+ output(error);
291
+ }
292
+ });
293
+
281
294
  // Replies
282
295
  user.command('replies')
283
296
  .description('Fetch the replies timeline the given user')
@@ -5,11 +5,16 @@
5
5
  */
6
6
  export enum ResourceType {
7
7
  // LIST
8
+ LIST_CREATE = 'LIST_CREATE',
9
+ LIST_DELETE = 'LIST_DELETE',
8
10
  LIST_DETAILS = 'LIST_DETAILS',
9
11
  LIST_MEMBER_ADD = 'LIST_MEMBER_ADD',
10
12
  LIST_MEMBER_REMOVE = 'LIST_MEMBER_REMOVE',
11
13
  LIST_MEMBERS = 'LIST_MEMBERS',
14
+ LIST_MUTE = 'LIST_MUTE',
12
15
  LIST_TWEETS = 'LIST_TWEETS',
16
+ LIST_UNMUTE = 'LIST_UNMUTE',
17
+ LIST_UPDATE = 'LIST_UPDATE',
13
18
 
14
19
  // MEDIA
15
20
  MEDIA_UPLOAD_APPEND = 'MEDIA_UPLOAD_APPEND',
@@ -30,6 +35,7 @@ export enum ResourceType {
30
35
  TWEET_DETAILS = 'TWEET_DETAILS',
31
36
  TWEET_DETAILS_ALT = 'TWEET_DETAILS_ALT',
32
37
  TWEET_DETAILS_BULK = 'TWEET_DETAILS_BULK',
38
+ TWEET_HISTORY = 'TWEET_HISTORY',
33
39
  TWEET_LIKE = 'TWEET_LIKE',
34
40
  TWEET_LIKERS = 'TWEET_LIKERS',
35
41
  TWEET_POST = 'TWEET_POST',
@@ -65,6 +71,7 @@ export enum ResourceType {
65
71
  USER_LISTS = 'USER_LISTS',
66
72
  USER_MEDIA = 'USER_MEDIA',
67
73
  USER_NOTIFICATIONS = 'USER_NOTIFICATIONS',
74
+ USER_REMOVE_FOLLOWER = 'USER_REMOVE_FOLLOWER',
68
75
  USER_SEARCH = 'USER_SEARCH',
69
76
  USER_SUBSCRIPTIONS = 'USER_SUBSCRIPTIONS',
70
77
  USER_TIMELINE = 'USER_TIMELINE',
package/src/index.ts CHANGED
@@ -82,16 +82,22 @@ export { ITimelineTweet as IRawTimelineTweet } from './types/raw/composite/Timel
82
82
  export { ITimelineUser as IRawTimelineUser } from './types/raw/composite/TimelineUser';
83
83
  export { IResponse as IRawResponse } from './types/raw/generic/Response';
84
84
  export { IListMemberAddResponse as IRawListMemberAddResponse } from './types/raw/list/AddMember';
85
- export { IListMemberRemoveResponse as IRawListMemberRemoveResponse } from './types/raw/list/RemoveMember';
85
+ export { IListCreateResponse as IRawListCreateResponse } from './types/raw/list/Create';
86
+ export { IListDeleteResponse as IRawListDeleteResponse } from './types/raw/list/Delete';
86
87
  export { IListDetailsResponse as IRawListDetailsResponse } from './types/raw/list/Details';
87
88
  export { IListMembersResponse as IRawListMembersResponse } from './types/raw/list/Members';
89
+ export { IListMuteResponse as IRawListMuteResponse } from './types/raw/list/Mute';
90
+ export { IListMemberRemoveResponse as IRawListMemberRemoveResponse } from './types/raw/list/RemoveMember';
88
91
  export { IListTweetsResponse as IRawListTweetsResponse } from './types/raw/list/Tweets';
92
+ export { IListUnmuteResponse as IRawListUnmuteResponse } from './types/raw/list/Unmute';
93
+ export { IListUpdateResponse as IRawListUpdateResponse } from './types/raw/list/Update';
89
94
  export { IMediaFinalizeUploadResponse as IRawMediaFinalizeUploadResponse } from './types/raw/media/FinalizeUpload';
90
95
  export { IMediaInitializeUploadResponse as IRawMediaInitializeUploadResponse } from './types/raw/media/InitalizeUpload';
91
96
  export { IMediaLiveVideoStreamResponse as IRawMediaLiveVideoStreamResponse } from './types/raw/media/LiveVideoStream';
92
97
  export { IAudioSpaceByIdResponse as IRawSpaceDetailsResponse } from './types/raw/space/AudioSpaceById';
93
98
  export { ITweetDetailsResponse as IRawTweetDetailsResponse } from './types/raw/tweet/Details';
94
99
  export { ITweetDetailsBulkResponse as IRawTweetDetailsBulkResponse } from './types/raw/tweet/DetailsBulk';
100
+ export { ITweetHistoryResponse as IRawTweetHistoryResponse } from './types/raw/tweet/History';
95
101
  export { ITweetLikeResponse as IRawTweetLikeResponse } from './types/raw/tweet/Like';
96
102
  export { ITweetLikersResponse as IRawTweetLikersResponse } from './types/raw/tweet/Likers';
97
103
  export { ITweetPostResponse as IRawTweetPostResponse } from './types/raw/tweet/Post';
@@ -1,4 +1,12 @@
1
- import { IChangePasswordArgs, INewTweet, INewTweetMedia, IPostArgs, IUploadArgs } from '../../types/args/PostArgs';
1
+ import {
2
+ IChangePasswordArgs,
3
+ IListUpdates,
4
+ INewList,
5
+ INewTweet,
6
+ INewTweetMedia,
7
+ IPostArgs,
8
+ IUploadArgs,
9
+ } from '../../types/args/PostArgs';
2
10
 
3
11
  import { ProfileUpdateOptions } from './ProfileArgs';
4
12
 
@@ -11,6 +19,8 @@ export class PostArgs implements IPostArgs {
11
19
  public changePassword?: ChangePasswordArgs;
12
20
  public conversationId?: string;
13
21
  public id?: string;
22
+ public list?: NewList;
23
+ public listUpdates?: ListUpdates;
14
24
  public profileBanner?: string;
15
25
  public profileImage?: string;
16
26
  public profileOptions?: ProfileUpdateOptions;
@@ -25,6 +35,7 @@ export class PostArgs implements IPostArgs {
25
35
  */
26
36
  public constructor(args: IPostArgs) {
27
37
  this.id = args.id;
38
+ this.list = args.list ? new NewList(args.list) : undefined;
28
39
  this.tweet = args.tweet ? new NewTweet(args.tweet) : undefined;
29
40
  this.upload = args.upload ? new UploadArgs(args.upload) : undefined;
30
41
  this.userId = args.userId;
@@ -34,6 +45,7 @@ export class PostArgs implements IPostArgs {
34
45
  this.profileImage = PostArgs._validateNonEmptyString(args.profileImage, 'Profile image');
35
46
  this.profileBanner = PostArgs._validateNonEmptyString(args.profileBanner, 'Profile banner');
36
47
  this.changePassword = args.changePassword ? new ChangePasswordArgs(args.changePassword) : undefined;
48
+ this.listUpdates = args.listUpdates ? new ListUpdates(args.listUpdates) : undefined;
37
49
  }
38
50
 
39
51
  /**
@@ -61,6 +73,46 @@ export class PostArgs implements IPostArgs {
61
73
  }
62
74
  }
63
75
 
76
+ /**
77
+ * Configuration for the list to be created.
78
+ *
79
+ * @public
80
+ */
81
+ export class NewList implements INewList {
82
+ public description?: string;
83
+ public isPrivate: boolean;
84
+ public name: string;
85
+
86
+ /**
87
+ * @param newList - The args specifying the list to be created.
88
+ */
89
+ public constructor(newList: INewList) {
90
+ this.name = newList.name;
91
+ this.description = newList.description;
92
+ this.isPrivate = newList.isPrivate ?? false;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Configuration for the updates to apply to an existing list.
98
+ *
99
+ * @public
100
+ */
101
+ export class ListUpdates implements IListUpdates {
102
+ public description?: string;
103
+ public isPrivate?: boolean;
104
+ public name?: string;
105
+
106
+ /**
107
+ * @param updates - The updates to apply to the target list.
108
+ */
109
+ public constructor(updates: IListUpdates) {
110
+ this.name = updates.name;
111
+ this.description = updates.description;
112
+ this.isPrivate = updates.isPrivate;
113
+ }
114
+ }
115
+
64
116
  /**
65
117
  * Configuration for the new tweet to be posted.
66
118
  *
@@ -1,5 +1,7 @@
1
1
  import { AxiosRequestConfig } from 'axios';
2
2
 
3
+ import { IListUpdates, INewList } from '../types/args/PostArgs';
4
+
3
5
  /**
4
6
  * Collection of requests related to lists.
5
7
  *
@@ -35,6 +37,54 @@ export class ListRequests {
35
37
  };
36
38
  }
37
39
 
40
+ /**
41
+ * @param list - The details of the list to create.
42
+ */
43
+ public static create(list: INewList): AxiosRequestConfig {
44
+ return {
45
+ method: 'post',
46
+ headers: { referer: 'https://x.com/i/lists/create' },
47
+ url: 'https://x.com/i/api/graphql/4lSOF4GqldI-NbiFET4ofQ/CreateList',
48
+ data: {
49
+ /* eslint-disable @typescript-eslint/naming-convention */
50
+
51
+ variables: {
52
+ isPrivate: list.isPrivate ?? false,
53
+ name: list.name,
54
+ ...(list.description !== undefined ? { description: list.description } : {}),
55
+ },
56
+ features: {
57
+ profile_label_improvements_pcf_label_in_post_enabled: true,
58
+ responsive_web_profile_redirect_enabled: false,
59
+ rweb_tipjar_consumption_enabled: false,
60
+ verified_phone_label_enabled: false,
61
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
62
+ responsive_web_graphql_timeline_navigation_enabled: true,
63
+ },
64
+ queryId: '4lSOF4GqldI-NbiFET4ofQ',
65
+
66
+ /* eslint-enable @typescript-eslint/naming-convention */
67
+ },
68
+ };
69
+ }
70
+
71
+ /**
72
+ * @param id - The ID of the list to delete.
73
+ */
74
+ public static delete(id: string): AxiosRequestConfig {
75
+ return {
76
+ method: 'post',
77
+ headers: { referer: `https://x.com/i/lists/${id}/info` },
78
+ url: 'https://x.com/i/api/graphql/UnN9Th1BDbeLjpgjGSpL3Q/DeleteList',
79
+ data: {
80
+ variables: {
81
+ listId: id,
82
+ },
83
+ queryId: 'UnN9Th1BDbeLjpgjGSpL3Q',
84
+ },
85
+ };
86
+ }
87
+
38
88
  /**
39
89
  * @param id - The id of the list whose details are to be fetched.
40
90
  */
@@ -116,6 +166,23 @@ export class ListRequests {
116
166
  };
117
167
  }
118
168
 
169
+ /**
170
+ * @param id - The ID of the list to mute.
171
+ */
172
+ public static mute(id: string): AxiosRequestConfig {
173
+ return {
174
+ method: 'post',
175
+ headers: { referer: `https://x.com/i/lists/${id}` },
176
+ url: 'https://x.com/i/api/graphql/ZYyanJsskNUcltu9bliMLA/MuteList',
177
+ data: {
178
+ variables: {
179
+ listId: id,
180
+ },
181
+ queryId: 'ZYyanJsskNUcltu9bliMLA',
182
+ },
183
+ };
184
+ }
185
+
119
186
  /**
120
187
  * @param listId - The ID of the target list.
121
188
  * @param userId - The ID of the user to remove as a member.
@@ -202,4 +269,54 @@ export class ListRequests {
202
269
  paramsSerializer: { encode: encodeURIComponent },
203
270
  };
204
271
  }
272
+
273
+ /**
274
+ * @param id - The ID of the list to unmute.
275
+ */
276
+ public static unmute(id: string): AxiosRequestConfig {
277
+ return {
278
+ method: 'post',
279
+ headers: { referer: `https://x.com/i/lists/${id}` },
280
+ url: 'https://x.com/i/api/graphql/pMZrHRNsmEkXgbn3tOyr7Q/UnmuteList',
281
+ data: {
282
+ variables: {
283
+ listId: id,
284
+ },
285
+ queryId: 'pMZrHRNsmEkXgbn3tOyr7Q',
286
+ },
287
+ };
288
+ }
289
+
290
+ /**
291
+ * @param id - The ID of the list to update.
292
+ * @param updates - The updates to apply.
293
+ */
294
+ public static update(id: string, updates: IListUpdates): AxiosRequestConfig {
295
+ return {
296
+ method: 'post',
297
+ headers: { referer: `https://x.com/i/lists/${id}/info` },
298
+ url: 'https://x.com/i/api/graphql/UzVGAR_brbQw1n3mH_PqRA/UpdateList',
299
+ data: {
300
+ /* eslint-disable @typescript-eslint/naming-convention */
301
+
302
+ variables: {
303
+ listId: id,
304
+ ...(updates.isPrivate !== undefined ? { isPrivate: updates.isPrivate } : {}),
305
+ ...(updates.description !== undefined ? { description: updates.description } : {}),
306
+ ...(updates.name !== undefined ? { name: updates.name } : {}),
307
+ },
308
+ features: {
309
+ profile_label_improvements_pcf_label_in_post_enabled: true,
310
+ responsive_web_profile_redirect_enabled: false,
311
+ rweb_tipjar_consumption_enabled: false,
312
+ verified_phone_label_enabled: false,
313
+ responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
314
+ responsive_web_graphql_timeline_navigation_enabled: true,
315
+ },
316
+ queryId: 'UzVGAR_brbQw1n3mH_PqRA',
317
+
318
+ /* eslint-enable @typescript-eslint/naming-convention */
319
+ },
320
+ };
321
+ }
205
322
  }