@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.
- package/.eslintrc.js +166 -0
- package/.gitattributes +3 -0
- package/.github/FUNDING.yml +4 -0
- package/.github/ISSUE_TEMPLATE/bug-report.yml +57 -0
- package/.github/ISSUE_TEMPLATE/feature-request.yml +20 -0
- package/.github/ISSUE_TEMPLATE/question.yml +15 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +32 -0
- package/.github/workflows/ci.yml +32 -0
- package/.github/workflows/publish.yml +23 -0
- package/.nvmrc +1 -0
- package/.prettierignore +3 -0
- package/.prettierrc +13 -0
- package/LICENSE +21 -0
- package/README.md +566 -0
- package/dist/cli.js +43 -0
- package/eslint.config.mjs +17 -0
- package/package.json +50 -0
- package/src/Rettiwt.ts +97 -0
- package/src/cli.ts +48 -0
- package/src/collections/Extractors.ts +155 -0
- package/src/collections/Groups.ts +81 -0
- package/src/collections/Requests.ts +89 -0
- package/src/collections/Tweet.ts +17 -0
- package/src/commands/DirectMessage.ts +62 -0
- package/src/commands/List.ts +90 -0
- package/src/commands/Tweet.ts +437 -0
- package/src/commands/User.ts +367 -0
- package/src/enums/Api.ts +10 -0
- package/src/enums/Authentication.ts +10 -0
- package/src/enums/Data.ts +13 -0
- package/src/enums/Logging.ts +14 -0
- package/src/enums/Media.ts +10 -0
- package/src/enums/Notification.ts +12 -0
- package/src/enums/Resource.ts +69 -0
- package/src/enums/Tweet.ts +8 -0
- package/src/enums/raw/Analytics.ts +32 -0
- package/src/enums/raw/Media.ts +10 -0
- package/src/enums/raw/Notification.ts +11 -0
- package/src/enums/raw/Tweet.ts +20 -0
- package/src/helper/CliUtils.ts +17 -0
- package/src/helper/JsonUtils.ts +70 -0
- package/src/index.ts +128 -0
- package/src/models/RettiwtConfig.ts +101 -0
- package/src/models/args/FetchArgs.ts +169 -0
- package/src/models/args/PostArgs.ts +93 -0
- package/src/models/args/ProfileArgs.ts +68 -0
- package/src/models/auth/AuthCookie.ts +58 -0
- package/src/models/auth/AuthCredential.ts +83 -0
- package/src/models/data/Analytics.ts +97 -0
- package/src/models/data/BookmarkFolder.ts +73 -0
- package/src/models/data/Conversation.ts +344 -0
- package/src/models/data/CursoredData.ts +64 -0
- package/src/models/data/DirectMessage.ts +335 -0
- package/src/models/data/Inbox.ts +124 -0
- package/src/models/data/List.ts +113 -0
- package/src/models/data/Notification.ts +84 -0
- package/src/models/data/Tweet.ts +388 -0
- package/src/models/data/User.ts +187 -0
- package/src/models/errors/TwitterError.ts +65 -0
- package/src/models/params/Variables.ts +62 -0
- package/src/requests/DirectMessage.ts +229 -0
- package/src/requests/List.ts +203 -0
- package/src/requests/Media.ts +67 -0
- package/src/requests/Tweet.ts +607 -0
- package/src/requests/User.ts +1191 -0
- package/src/services/internal/AuthService.ts +115 -0
- package/src/services/internal/ErrorService.ts +41 -0
- package/src/services/internal/LogService.ts +34 -0
- package/src/services/public/DirectMessageService.ts +159 -0
- package/src/services/public/FetcherService.ts +366 -0
- package/src/services/public/ListService.ts +241 -0
- package/src/services/public/TweetService.ts +886 -0
- package/src/services/public/UserService.ts +1154 -0
- package/src/types/ErrorHandler.ts +13 -0
- package/src/types/Fetch.ts +3 -0
- package/src/types/RettiwtConfig.ts +48 -0
- package/src/types/args/FetchArgs.ts +233 -0
- package/src/types/args/PostArgs.ts +142 -0
- package/src/types/args/ProfileArgs.ts +33 -0
- package/src/types/auth/AuthCookie.ts +22 -0
- package/src/types/auth/AuthCredential.ts +28 -0
- package/src/types/auth/TransactionHeader.ts +8 -0
- package/src/types/data/Analytics.ts +58 -0
- package/src/types/data/BookmarkFolder.ts +12 -0
- package/src/types/data/Conversation.ts +44 -0
- package/src/types/data/CursoredData.ts +24 -0
- package/src/types/data/DirectMessage.ts +33 -0
- package/src/types/data/Inbox.ts +23 -0
- package/src/types/data/List.ts +33 -0
- package/src/types/data/Notification.ts +26 -0
- package/src/types/data/Tweet.ts +99 -0
- package/src/types/data/User.ts +54 -0
- package/src/types/errors/TwitterError.ts +37 -0
- package/src/types/params/Variables.ts +41 -0
- package/src/types/raw/base/Analytic.ts +32 -0
- package/src/types/raw/base/BookmarkFolder.ts +12 -0
- package/src/types/raw/base/Cursor.ts +13 -0
- package/src/types/raw/base/Error.ts +38 -0
- package/src/types/raw/base/LimitedVisibilityTweet.ts +40 -0
- package/src/types/raw/base/List.ts +50 -0
- package/src/types/raw/base/Media.ts +53 -0
- package/src/types/raw/base/Message.ts +22 -0
- package/src/types/raw/base/Notification.ts +66 -0
- package/src/types/raw/base/Space.ts +35 -0
- package/src/types/raw/base/Tweet.ts +139 -0
- package/src/types/raw/base/User.ts +182 -0
- package/src/types/raw/composite/DataResult.ts +8 -0
- package/src/types/raw/composite/TimelineList.ts +10 -0
- package/src/types/raw/composite/TimelineTweet.ts +14 -0
- package/src/types/raw/composite/TimelineUser.ts +13 -0
- package/src/types/raw/dm/Conversation.ts +59 -0
- package/src/types/raw/dm/InboxInitial.ts +155 -0
- package/src/types/raw/dm/InboxTimeline.ts +301 -0
- package/src/types/raw/dm/UserUpdates.ts +46 -0
- package/src/types/raw/generic/Response.ts +10 -0
- package/src/types/raw/list/AddMember.ts +175 -0
- package/src/types/raw/list/Details.ts +176 -0
- package/src/types/raw/list/Members.ts +154 -0
- package/src/types/raw/list/RemoveMember.ts +174 -0
- package/src/types/raw/list/Tweets.ts +2296 -0
- package/src/types/raw/media/FinalizeUpload.ts +20 -0
- package/src/types/raw/media/InitalizeUpload.ts +12 -0
- package/src/types/raw/media/LiveVideoStream.ts +21 -0
- package/src/types/raw/space/Details.ts +359 -0
- package/src/types/raw/tweet/Bookmark.ts +14 -0
- package/src/types/raw/tweet/Details.ts +210 -0
- package/src/types/raw/tweet/DetailsBulk.ts +338 -0
- package/src/types/raw/tweet/Like.ts +14 -0
- package/src/types/raw/tweet/Likers.ts +200 -0
- package/src/types/raw/tweet/Post.ts +150 -0
- package/src/types/raw/tweet/Replies.ts +539 -0
- package/src/types/raw/tweet/Retweet.ts +31 -0
- package/src/types/raw/tweet/Retweeters.ts +208 -0
- package/src/types/raw/tweet/Schedule.ts +18 -0
- package/src/types/raw/tweet/Search.ts +597 -0
- package/src/types/raw/tweet/Unbookmark.ts +14 -0
- package/src/types/raw/tweet/Unlike.ts +14 -0
- package/src/types/raw/tweet/Unpost.ts +20 -0
- package/src/types/raw/tweet/Unretweet.ts +31 -0
- package/src/types/raw/tweet/Unschedule.ts +14 -0
- package/src/types/raw/user/Affiliates.ts +179 -0
- package/src/types/raw/user/Analytics.ts +23 -0
- package/src/types/raw/user/BookmarkFolderTweets.ts +53 -0
- package/src/types/raw/user/BookmarkFolders.ts +41 -0
- package/src/types/raw/user/Bookmarks.ts +637 -0
- package/src/types/raw/user/Details.ts +185 -0
- package/src/types/raw/user/DetailsBulk.ts +104 -0
- package/src/types/raw/user/Follow.ts +280 -0
- package/src/types/raw/user/Followed.ts +1942 -0
- package/src/types/raw/user/Followers.ts +215 -0
- package/src/types/raw/user/Following.ts +215 -0
- package/src/types/raw/user/Highlights.ts +1287 -0
- package/src/types/raw/user/Likes.ts +1254 -0
- package/src/types/raw/user/Lists.ts +378 -0
- package/src/types/raw/user/Media.ts +1738 -0
- package/src/types/raw/user/Notifications.ts +499 -0
- package/src/types/raw/user/ProfileUpdate.ts +80 -0
- package/src/types/raw/user/Recommended.ts +2319 -0
- package/src/types/raw/user/Scheduled.ts +37 -0
- package/src/types/raw/user/Search.ts +230 -0
- package/src/types/raw/user/Subscriptions.ts +176 -0
- package/src/types/raw/user/Tweets.ts +1254 -0
- package/src/types/raw/user/TweetsAndReplies.ts +1254 -0
- package/src/types/raw/user/Unfollow.ts +280 -0
- package/tsconfig.json +97 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { Command, createCommand } from 'commander';
|
|
2
|
+
|
|
3
|
+
import { RawAnalyticsGranularity, RawAnalyticsMetric } from '../enums/raw/Analytics';
|
|
4
|
+
import { output } from '../helper/CliUtils';
|
|
5
|
+
import { Rettiwt } from '../Rettiwt';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new 'user' command which uses the given Rettiwt instance.
|
|
9
|
+
*
|
|
10
|
+
* @param rettiwt - The Rettiwt instance to use.
|
|
11
|
+
* @returns The created 'user' command.
|
|
12
|
+
*/
|
|
13
|
+
function createUserCommand(rettiwt: Rettiwt): Command {
|
|
14
|
+
// Creating the 'user' command
|
|
15
|
+
const user = createCommand('user').description('Access resources related to users');
|
|
16
|
+
|
|
17
|
+
// Affiliates
|
|
18
|
+
user.command('affiliates')
|
|
19
|
+
.description('Fetch the list of users who affiliated to the given user')
|
|
20
|
+
.argument('<id>', 'The id of the user')
|
|
21
|
+
.argument('[count]', 'The number of affiliates to fetch')
|
|
22
|
+
.argument('[cursor]', 'The cursor to the batch of affiliates to fetch')
|
|
23
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
24
|
+
try {
|
|
25
|
+
const users = await rettiwt.user.affiliates(id, count ? parseInt(count) : undefined, cursor);
|
|
26
|
+
output(users);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
output(error);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Analytics
|
|
33
|
+
user.command('analytics')
|
|
34
|
+
.description('Fetch the analytics of the logged-in user (premium accounts only)')
|
|
35
|
+
.option('-f, --from-time <string>', 'The start time for fetching analytics')
|
|
36
|
+
.option('-t, --to-time <string>', 'The end time for fetching analytics')
|
|
37
|
+
.option(
|
|
38
|
+
'-g, --granularity <string>',
|
|
39
|
+
'The granularity of the analytics data. Defaults to daily. Check https://rishikant181.github.io/Rettiwt-API/enums/RawAnalyticsGranularity.html for granularity options',
|
|
40
|
+
)
|
|
41
|
+
.option(
|
|
42
|
+
'-m, --metrics <string>',
|
|
43
|
+
'Comma-separated list of metrics required. Check https://rishikant181.github.io/Rettiwt-API/enums/RawAnalyticsMetric.html for available metrics',
|
|
44
|
+
)
|
|
45
|
+
.option(
|
|
46
|
+
'-v, --verified-followers',
|
|
47
|
+
'Whether to include verified follower count and relationship counts in the response. Defaults to true',
|
|
48
|
+
)
|
|
49
|
+
.action(async (options?: UserAnalyticsOptions) => {
|
|
50
|
+
try {
|
|
51
|
+
const analytics = await rettiwt.user.analytics(
|
|
52
|
+
options?.fromTime ? new Date(options.fromTime) : undefined,
|
|
53
|
+
options?.toTime ? new Date(options.toTime) : undefined,
|
|
54
|
+
options?.granularity
|
|
55
|
+
? RawAnalyticsGranularity[options.granularity as keyof typeof RawAnalyticsGranularity]
|
|
56
|
+
: undefined,
|
|
57
|
+
options?.metrics
|
|
58
|
+
? options.metrics
|
|
59
|
+
.split(',')
|
|
60
|
+
.map((item) => RawAnalyticsMetric[item as keyof typeof RawAnalyticsMetric])
|
|
61
|
+
: undefined,
|
|
62
|
+
options?.verifiedFollowers,
|
|
63
|
+
);
|
|
64
|
+
output(analytics);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
output(error);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
user.command('bookmarks')
|
|
71
|
+
.description('Fetch your list of bookmarks')
|
|
72
|
+
.argument('[count]', 'The number of bookmarks to fetch')
|
|
73
|
+
.argument('[cursor]', 'The cursor to the batch of bookmarks to fetch')
|
|
74
|
+
.action(async (count?: string, cursor?: string) => {
|
|
75
|
+
try {
|
|
76
|
+
const bookmarks = await rettiwt.user.bookmarks(count ? parseInt(count) : undefined, cursor);
|
|
77
|
+
output(bookmarks);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
output(error);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
user.command('bookmark-folders')
|
|
84
|
+
.description('Fetch your list of bookmark folders')
|
|
85
|
+
.argument('[cursor]', 'The cursor to the batch of bookmark folders to fetch')
|
|
86
|
+
.action(async (cursor?: string) => {
|
|
87
|
+
try {
|
|
88
|
+
const folders = await rettiwt.user.bookmarkFolders(cursor);
|
|
89
|
+
output(folders);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
output(error);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
user.command('bookmark-folder-tweets')
|
|
96
|
+
.description('Fetch tweets from a specific bookmark folder')
|
|
97
|
+
.argument('<folderId>', 'The ID of the bookmark folder')
|
|
98
|
+
.argument('[count]', 'The number of tweets to fetch')
|
|
99
|
+
.argument('[cursor]', 'The cursor to the batch of tweets to fetch')
|
|
100
|
+
.action(async (folderId: string, count?: string, cursor?: string) => {
|
|
101
|
+
try {
|
|
102
|
+
const tweets = await rettiwt.user.bookmarkFolderTweets(
|
|
103
|
+
folderId,
|
|
104
|
+
count ? parseInt(count) : undefined,
|
|
105
|
+
cursor,
|
|
106
|
+
);
|
|
107
|
+
output(tweets);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
output(error);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Details
|
|
114
|
+
user.command('details')
|
|
115
|
+
.description('Fetch the details of the user with the given id/username')
|
|
116
|
+
.argument('<id>', 'The username/id of the user whose details are to be fetched')
|
|
117
|
+
.action(async (id: string) => {
|
|
118
|
+
try {
|
|
119
|
+
// Getting the different IDs
|
|
120
|
+
const ids: string[] = id.split(',');
|
|
121
|
+
|
|
122
|
+
// If single ID given
|
|
123
|
+
if (ids.length <= 1) {
|
|
124
|
+
const details = await rettiwt.user.details(ids[0]);
|
|
125
|
+
output(details);
|
|
126
|
+
}
|
|
127
|
+
// If multiple IDs given
|
|
128
|
+
else {
|
|
129
|
+
const details = await rettiwt.user.details(ids);
|
|
130
|
+
output(details);
|
|
131
|
+
}
|
|
132
|
+
} catch (error) {
|
|
133
|
+
output(error);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Follow
|
|
138
|
+
user.command('follow')
|
|
139
|
+
.description('Follow a user')
|
|
140
|
+
.argument('<id>', 'The user to follow')
|
|
141
|
+
.action(async (id: string) => {
|
|
142
|
+
try {
|
|
143
|
+
const result = await rettiwt.user.follow(id);
|
|
144
|
+
output(result);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
output(error);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Followed
|
|
151
|
+
user.command('followed')
|
|
152
|
+
.description('Fetch your followed feed')
|
|
153
|
+
.argument('[cursor]', 'The cursor to the batch of feed items to fetch')
|
|
154
|
+
.action(async (cursor?: string) => {
|
|
155
|
+
try {
|
|
156
|
+
const tweets = await rettiwt.user.followed(cursor);
|
|
157
|
+
output(tweets);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
output(error);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Followers
|
|
164
|
+
user.command('followers')
|
|
165
|
+
.description('Fetch the list of users who follow the given user')
|
|
166
|
+
.argument('<id>', 'The id of the user')
|
|
167
|
+
.argument('[count]', 'The number of followers to fetch')
|
|
168
|
+
.argument('[cursor]', 'The cursor to the batch of followers to fetch')
|
|
169
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
170
|
+
try {
|
|
171
|
+
const users = await rettiwt.user.followers(id, count ? parseInt(count) : undefined, cursor);
|
|
172
|
+
output(users);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
output(error);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Following
|
|
179
|
+
user.command('following')
|
|
180
|
+
.description('Fetch the list of users who are followed by the given user')
|
|
181
|
+
.argument('<id>', 'The id of the user')
|
|
182
|
+
.argument('[count]', 'The number of following to fetch')
|
|
183
|
+
.argument('[cursor]', 'The cursor to the batch of following to fetch')
|
|
184
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
185
|
+
try {
|
|
186
|
+
const users = await rettiwt.user.following(id, count ? parseInt(count) : undefined, cursor);
|
|
187
|
+
output(users);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
output(error);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Highlights
|
|
194
|
+
user.command('highlights')
|
|
195
|
+
.description('Fetch the list of highlighted tweets of the given user')
|
|
196
|
+
.argument('<id>', 'The id of the user')
|
|
197
|
+
.argument('[count]', 'The number of highlighted tweets to fetch')
|
|
198
|
+
.argument('[cursor]', 'The cursor to the batch of highlights to fetch')
|
|
199
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
200
|
+
try {
|
|
201
|
+
const tweets = await rettiwt.user.highlights(id, count ? parseInt(count) : undefined, cursor);
|
|
202
|
+
output(tweets);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
output(error);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Likes
|
|
209
|
+
user.command('likes')
|
|
210
|
+
.description('Fetch your list of liked tweet')
|
|
211
|
+
.argument('[count]', 'The number of liked tweets to fetch')
|
|
212
|
+
.argument('[cursor]', 'The cursor to the batch of liked tweets to fetch')
|
|
213
|
+
.action(async (count?: string, cursor?: string) => {
|
|
214
|
+
try {
|
|
215
|
+
const tweets = await rettiwt.user.likes(count ? parseInt(count) : undefined, cursor);
|
|
216
|
+
output(tweets);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
output(error);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Lists
|
|
223
|
+
user.command('lists')
|
|
224
|
+
.description('Fetch your lists')
|
|
225
|
+
.argument('[count]', 'The number of lists to fetch')
|
|
226
|
+
.argument('[cursor]', 'The cursor to the batch of lists to fetch')
|
|
227
|
+
.action(async (count?: string, cursor?: string) => {
|
|
228
|
+
try {
|
|
229
|
+
const lists = await rettiwt.user.lists(count ? parseInt(count) : undefined, cursor);
|
|
230
|
+
output(lists);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
output(error);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Media
|
|
237
|
+
user.command('media')
|
|
238
|
+
.description('Fetch the media timeline the given user')
|
|
239
|
+
.argument('<id>', 'The id of the user')
|
|
240
|
+
.argument('[count]', 'The number of media to fetch')
|
|
241
|
+
.argument('[cursor]', 'The cursor to the batch of media to fetch')
|
|
242
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
243
|
+
try {
|
|
244
|
+
const media = await rettiwt.user.media(id, count ? parseInt(count) : undefined, cursor);
|
|
245
|
+
output(media);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
output(error);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Recommended
|
|
252
|
+
user.command('recommended')
|
|
253
|
+
.description('Fetch your recommended feed')
|
|
254
|
+
.argument('[cursor]', 'The cursor to the batch of feed items to fetch')
|
|
255
|
+
.action(async (cursor?: string) => {
|
|
256
|
+
try {
|
|
257
|
+
const tweets = await rettiwt.user.recommended(cursor);
|
|
258
|
+
output(tweets);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
output(error);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Replies
|
|
265
|
+
user.command('replies')
|
|
266
|
+
.description('Fetch the replies timeline the given user')
|
|
267
|
+
.argument('<id>', 'The id of the user')
|
|
268
|
+
.argument('[count]', 'The number of replies to fetch')
|
|
269
|
+
.argument('[cursor]', 'The cursor to the batch of replies to fetch')
|
|
270
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
271
|
+
try {
|
|
272
|
+
const replies = await rettiwt.user.replies(id, count ? parseInt(count) : undefined, cursor);
|
|
273
|
+
output(replies);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
output(error);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Replies
|
|
280
|
+
user.command('search')
|
|
281
|
+
.description('Search for a username')
|
|
282
|
+
.argument('<username>', 'The username to search for')
|
|
283
|
+
.argument('[count]', 'The number of results to fetch')
|
|
284
|
+
.argument('[cursor]', 'The cursor to the batch of results to fetch')
|
|
285
|
+
.action(async (userName: string, count?: string, cursor?: string) => {
|
|
286
|
+
try {
|
|
287
|
+
const replies = await rettiwt.user.search(userName, count ? parseInt(count) : undefined, cursor);
|
|
288
|
+
output(replies);
|
|
289
|
+
} catch (error) {
|
|
290
|
+
output(error);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Timeline
|
|
295
|
+
user.command('timeline')
|
|
296
|
+
.description('Fetch the tweets timeline the given user')
|
|
297
|
+
.argument('<id>', 'The id of the user')
|
|
298
|
+
.argument('[count]', 'The number of tweets to fetch')
|
|
299
|
+
.argument('[cursor]', 'The cursor to the batch of tweets to fetch')
|
|
300
|
+
.action(async (id: string, count?: string, cursor?: string) => {
|
|
301
|
+
try {
|
|
302
|
+
const tweets = await rettiwt.user.timeline(id, count ? parseInt(count) : undefined, cursor);
|
|
303
|
+
output(tweets);
|
|
304
|
+
} catch (error) {
|
|
305
|
+
output(error);
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Unfollow
|
|
310
|
+
user.command('unfollow')
|
|
311
|
+
.description('Unfollow a user')
|
|
312
|
+
.argument('<id>', 'The user to unfollow')
|
|
313
|
+
.action(async (id: string) => {
|
|
314
|
+
try {
|
|
315
|
+
const result = await rettiwt.user.unfollow(id);
|
|
316
|
+
output(result);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
output(error);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Update Profile
|
|
323
|
+
user.command('update-profile')
|
|
324
|
+
.description('Update your profile information')
|
|
325
|
+
.option('-n, --name <string>', 'Display name (max 50 characters)')
|
|
326
|
+
.option('-u, --url <string>', 'Profile URL')
|
|
327
|
+
.option('-l, --location <string>', 'Location (max 30 characters)')
|
|
328
|
+
.option('-d, --description <string>', 'Description/bio (max 160 characters)')
|
|
329
|
+
.action(async (options?: UserProfileUpdateOptions) => {
|
|
330
|
+
try {
|
|
331
|
+
const result = await rettiwt.user.updateProfile({
|
|
332
|
+
name: options?.name,
|
|
333
|
+
url: options?.url,
|
|
334
|
+
location: options?.location,
|
|
335
|
+
description: options?.description,
|
|
336
|
+
});
|
|
337
|
+
output(result);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
output(error);
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
return user;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* The options for fetching user analytics.
|
|
348
|
+
*/
|
|
349
|
+
type UserAnalyticsOptions = {
|
|
350
|
+
fromTime?: string;
|
|
351
|
+
toTime?: string;
|
|
352
|
+
granularity?: string;
|
|
353
|
+
metrics?: string;
|
|
354
|
+
verifiedFollowers?: boolean;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* The options for updating user profile.
|
|
359
|
+
*/
|
|
360
|
+
type UserProfileUpdateOptions = {
|
|
361
|
+
name?: string;
|
|
362
|
+
url?: string;
|
|
363
|
+
location?: string;
|
|
364
|
+
description?: string;
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
export default createUserCommand;
|
package/src/enums/Api.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The different types of api error messages.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export enum ApiErrors {
|
|
7
|
+
COULD_NOT_AUTHENTICATE = 'Failed to authenticate',
|
|
8
|
+
BAD_AUTHENTICATION = 'Invalid authentication data',
|
|
9
|
+
RESOURCE_NOT_ALLOWED = 'Not authorized to access requested resource',
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The different base types of data contained in response.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export enum BaseType {
|
|
7
|
+
DIRECT_MESSAGE = 'DIRECT_MESSAGE',
|
|
8
|
+
NOTIFICATION = 'NOTIFICATION',
|
|
9
|
+
TWEET = 'TWEET',
|
|
10
|
+
USER = 'USER',
|
|
11
|
+
LIST = 'LIST',
|
|
12
|
+
BOOKMARK_FOLDER = 'BOOKMARK_FOLDER',
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The different types of actions that are logged.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export enum LogActions {
|
|
7
|
+
AUTHORIZATION = 'AUTHORIZATION',
|
|
8
|
+
DESERIALIZE = 'DESERIALIZE',
|
|
9
|
+
EXTRACT = 'EXTRACT',
|
|
10
|
+
GET = 'GET',
|
|
11
|
+
REQUEST = 'REQUEST',
|
|
12
|
+
VALIDATE = 'VALIDATE',
|
|
13
|
+
WARNING = 'WARNING',
|
|
14
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The different types of resources that can be interacted with.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export enum ResourceType {
|
|
7
|
+
// LIST
|
|
8
|
+
LIST_DETAILS = 'LIST_DETAILS',
|
|
9
|
+
LIST_MEMBER_ADD = 'LIST_MEMBER_ADD',
|
|
10
|
+
LIST_MEMBER_REMOVE = 'LIST_MEMBER_REMOVE',
|
|
11
|
+
LIST_MEMBERS = 'LIST_MEMBERS',
|
|
12
|
+
LIST_TWEETS = 'LIST_TWEETS',
|
|
13
|
+
|
|
14
|
+
// MEDIA
|
|
15
|
+
MEDIA_UPLOAD_APPEND = 'MEDIA_UPLOAD_APPEND',
|
|
16
|
+
MEDIA_UPLOAD_FINALIZE = 'MEDIA_UPLOAD_FINALIZE',
|
|
17
|
+
MEDIA_UPLOAD_INITIALIZE = 'MEDIA_UPLOAD_INITIALIZE',
|
|
18
|
+
|
|
19
|
+
// DM
|
|
20
|
+
DM_CONVERSATION = 'DM_CONVERSATION',
|
|
21
|
+
DM_INBOX_INITIAL_STATE = 'DM_INBOX_INITIAL_STATE',
|
|
22
|
+
DM_INBOX_TIMELINE = 'DM_INBOX_TIMELINE',
|
|
23
|
+
DM_DELETE_CONVERSATION = 'DM_DELETE_CONVERSATION',
|
|
24
|
+
|
|
25
|
+
// TWEET
|
|
26
|
+
TWEET_BOOKMARK = 'TWEET_BOOKMARK',
|
|
27
|
+
TWEET_DETAILS = 'TWEET_DETAILS',
|
|
28
|
+
TWEET_DETAILS_ALT = 'TWEET_DETAILS_ALT',
|
|
29
|
+
TWEET_DETAILS_BULK = 'TWEET_DETAILS_BULK',
|
|
30
|
+
TWEET_LIKE = 'TWEET_LIKE',
|
|
31
|
+
TWEET_LIKERS = 'TWEET_LIKERS',
|
|
32
|
+
TWEET_POST = 'TWEET_POST',
|
|
33
|
+
TWEET_REPLIES = 'TWEET_REPLIES',
|
|
34
|
+
TWEET_RETWEET = 'TWEET_RETWEET',
|
|
35
|
+
TWEET_RETWEETERS = 'TWEET_RETWEETERS',
|
|
36
|
+
TWEET_SCHEDULE = 'TWEET_SCHEDULE',
|
|
37
|
+
TWEET_SEARCH = 'TWEET_SEARCH',
|
|
38
|
+
TWEET_UNBOOKMARK = 'TWEET_UNBOOKMARK',
|
|
39
|
+
TWEET_UNLIKE = 'TWEET_UNLIKE',
|
|
40
|
+
TWEET_UNPOST = 'TWEET_UNPOST',
|
|
41
|
+
TWEET_UNRETWEET = 'TWEET_UNRETWEET',
|
|
42
|
+
TWEET_UNSCHEDULE = 'TWEET_UNSCHEDULE',
|
|
43
|
+
|
|
44
|
+
// USER
|
|
45
|
+
USER_AFFILIATES = 'USER_AFFILIATES',
|
|
46
|
+
USER_ANALYTICS = 'USER_ANALYTICS',
|
|
47
|
+
USER_BOOKMARKS = 'USER_BOOKMARKS',
|
|
48
|
+
USER_BOOKMARK_FOLDERS = 'USER_BOOKMARK_FOLDERS',
|
|
49
|
+
USER_BOOKMARK_FOLDER_TWEETS = 'USER_BOOKMARK_FOLDER_TWEETS',
|
|
50
|
+
USER_DETAILS_BY_USERNAME = 'USER_DETAILS_BY_USERNAME',
|
|
51
|
+
USER_DETAILS_BY_ID = 'USER_DETAILS_BY_ID',
|
|
52
|
+
USER_DETAILS_BY_IDS_BULK = 'USER_DETAILS_BY_IDS_BULK',
|
|
53
|
+
USER_FEED_FOLLOWED = 'USER_FEED_FOLLOWED',
|
|
54
|
+
USER_FEED_RECOMMENDED = 'USER_FEED_RECOMMENDED',
|
|
55
|
+
USER_FOLLOW = 'USER_FOLLOW',
|
|
56
|
+
USER_FOLLOWING = 'USER_FOLLOWING',
|
|
57
|
+
USER_FOLLOWERS = 'USER_FOLLOWERS',
|
|
58
|
+
USER_HIGHLIGHTS = 'USER_HIGHLIGHTS',
|
|
59
|
+
USER_LIKES = 'USER_LIKES',
|
|
60
|
+
USER_LISTS = 'USER_LISTS',
|
|
61
|
+
USER_MEDIA = 'USER_MEDIA',
|
|
62
|
+
USER_NOTIFICATIONS = 'USER_NOTIFICATIONS',
|
|
63
|
+
USER_SEARCH = 'USER_SEARCH',
|
|
64
|
+
USER_SUBSCRIPTIONS = 'USER_SUBSCRIPTIONS',
|
|
65
|
+
USER_TIMELINE = 'USER_TIMELINE',
|
|
66
|
+
USER_TIMELINE_AND_REPLIES = 'USER_TIMELINE_AND_REPLIES',
|
|
67
|
+
USER_UNFOLLOW = 'USER_UNFOLLOW',
|
|
68
|
+
USER_PROFILE_UPDATE = 'USER_PROFILE_UPDATE',
|
|
69
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Granularity types for analytics.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export enum RawAnalyticsGranularity {
|
|
7
|
+
DAILY = 'Daily',
|
|
8
|
+
WEEKLY = 'Weekly',
|
|
9
|
+
MONTHLY = 'Monthly',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The different types of metric someone can request.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export enum RawAnalyticsMetric {
|
|
18
|
+
ENGAGEMENTS = 'Engagements',
|
|
19
|
+
IMPRESSIONS = 'Impressions',
|
|
20
|
+
PROFILE_VISITS = 'ProfileVisits',
|
|
21
|
+
FOLLOWS = 'Follows',
|
|
22
|
+
REPLIES = 'Replies',
|
|
23
|
+
LIKES = 'Likes',
|
|
24
|
+
RETWEETS = 'Retweets',
|
|
25
|
+
BOOKMARK = 'Bookmark',
|
|
26
|
+
SHARE = 'Share',
|
|
27
|
+
URL_CLICKS = 'UrlClicks',
|
|
28
|
+
CREATE_TWEET = 'CreateTweet',
|
|
29
|
+
CREATE_QUOTE = 'CreateQuote',
|
|
30
|
+
CREATE_REPLY = 'CreateReply',
|
|
31
|
+
UNFOLLOWS = 'Unfollows',
|
|
32
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The different types of search results when searching for tweets.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export enum RawTweetSearchResultType {
|
|
7
|
+
LATEST = 'Latest',
|
|
8
|
+
TOP = 'Top',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The different types of sorting options when fetching replies to tweets.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export enum RawTweetRepliesSortType {
|
|
17
|
+
RELEVACE = 'Relevance',
|
|
18
|
+
LATEST = 'Recency',
|
|
19
|
+
LIKES = 'Likes',
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Outputs the given JSON data.
|
|
3
|
+
*
|
|
4
|
+
* @param data - The data to be output.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export function output(data: unknown): void {
|
|
9
|
+
// If data is string, output as is
|
|
10
|
+
if (typeof data == 'string') {
|
|
11
|
+
console.log(data);
|
|
12
|
+
}
|
|
13
|
+
// Else, format the output
|
|
14
|
+
else {
|
|
15
|
+
console.log(JSON.stringify(data, null, 4));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search for all the sub-objects (even deep-nested ones) that have the given key-value pair(filter).
|
|
3
|
+
*
|
|
4
|
+
* @param data - The data on which search is to be performed.
|
|
5
|
+
* @param key - The key of the key-value pair to search.
|
|
6
|
+
* @param value - The value of the key-value pait to search.
|
|
7
|
+
* @returns The list of sub-objects from the given object, having the given key-value pair.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export function findByFilter<T>(data: NonNullable<unknown>, key: string, value: string): T[] {
|
|
12
|
+
/**
|
|
13
|
+
* The list containing all the objects matching given filter.
|
|
14
|
+
*/
|
|
15
|
+
let res: T[] = [];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* If the data is an array, recursively run the function of each element of the array and merge the results.
|
|
19
|
+
*/
|
|
20
|
+
if (Array.isArray(data)) {
|
|
21
|
+
/**
|
|
22
|
+
* findByFilter returns an array.
|
|
23
|
+
* map() also returns an array.
|
|
24
|
+
* Therefore, map(item =\> findByFilter(.......)) returns an array of arrays.
|
|
25
|
+
* Therefore, using ... operator to spread the 2-D array in 1-D array.
|
|
26
|
+
*/
|
|
27
|
+
res = res.concat(...data.map((item: NonNullable<unknown>) => findByFilter<T>(item, key, value)));
|
|
28
|
+
}
|
|
29
|
+
// If the data is an object
|
|
30
|
+
else if (data != null && typeof data == 'object') {
|
|
31
|
+
/**
|
|
32
|
+
* If the object includes the key and the value specified by the key matches the filter, add it to the result.
|
|
33
|
+
*/
|
|
34
|
+
if (Object.keys(data).includes(key) && data[key as keyof typeof data] == value) {
|
|
35
|
+
res.push(data as T);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Recursively run the function on each value specified by each key in the object, for subsequent matches.
|
|
40
|
+
*/
|
|
41
|
+
for (const [, v] of Object.entries(data)) {
|
|
42
|
+
res = res.concat(findByFilter<T>(v as NonNullable<unknown>, key, value));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return res;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Searches for the key which has the given value in the given object.
|
|
51
|
+
*
|
|
52
|
+
* @param data - The data on which search is to be performed.
|
|
53
|
+
* @param value - The value to search.
|
|
54
|
+
* @returns The key with the given value.
|
|
55
|
+
*
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
58
|
+
export function findKeyByValue(data: NonNullable<unknown>, value: string): string | undefined {
|
|
59
|
+
// Finding the key-value pairs that have the given value
|
|
60
|
+
const kvPair = Object.entries(data).filter(([, v]) => v == value)[0];
|
|
61
|
+
|
|
62
|
+
// If a match is found
|
|
63
|
+
if (kvPair) {
|
|
64
|
+
return kvPair[0];
|
|
65
|
+
}
|
|
66
|
+
// If no match is found
|
|
67
|
+
else {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|