rettiwt-api 3.1.0 → 4.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/.github/FUNDING.yml +4 -0
- package/.github/workflows/documentation.yml +5 -0
- package/.github/workflows/publish.yml +3 -0
- package/.yarnrc.yml +1 -0
- package/README.md +50 -10
- package/dist/collections/Extractors.d.ts +4 -2
- package/dist/collections/Extractors.js +3 -3
- package/dist/collections/Extractors.js.map +1 -1
- package/dist/collections/Groups.js +3 -1
- package/dist/collections/Groups.js.map +1 -1
- package/dist/collections/Requests.js +3 -1
- package/dist/collections/Requests.js.map +1 -1
- package/dist/commands/Tweet.js +73 -41
- package/dist/commands/Tweet.js.map +1 -1
- package/dist/commands/User.js +3 -4
- package/dist/commands/User.js.map +1 -1
- package/dist/enums/Resource.d.ts +3 -1
- package/dist/enums/Resource.js +3 -1
- package/dist/enums/Resource.js.map +1 -1
- package/dist/helper/CliUtils.d.ts +2 -0
- package/dist/helper/CliUtils.js +2 -0
- package/dist/helper/CliUtils.js.map +1 -1
- package/dist/helper/JsonUtils.d.ts +2 -0
- package/dist/helper/JsonUtils.js +2 -0
- package/dist/helper/JsonUtils.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/models/args/FetchArgs.d.ts +0 -2
- package/dist/models/args/FetchArgs.js +126 -10
- package/dist/models/args/FetchArgs.js.map +1 -1
- package/dist/models/args/PostArgs.d.ts +3 -1
- package/dist/models/args/PostArgs.js +62 -24
- package/dist/models/args/PostArgs.js.map +1 -1
- package/dist/models/data/Tweet.d.ts +3 -3
- package/dist/models/data/Tweet.js +1 -1
- package/dist/models/data/Tweet.js.map +1 -1
- package/dist/services/public/AuthService.d.ts +21 -0
- package/dist/services/public/AuthService.js +44 -1
- package/dist/services/public/AuthService.js.map +1 -1
- package/dist/services/public/FetcherService.d.ts +2 -2
- package/dist/services/public/FetcherService.js +5 -6
- package/dist/services/public/FetcherService.js.map +1 -1
- package/dist/services/public/TweetService.d.ts +55 -32
- package/dist/services/public/TweetService.js +96 -55
- package/dist/services/public/TweetService.js.map +1 -1
- package/dist/services/public/UserService.d.ts +4 -5
- package/dist/services/public/UserService.js +5 -6
- package/dist/services/public/UserService.js.map +1 -1
- package/package.json +3 -2
- package/src/collections/Extractors.ts +6 -3
- package/src/collections/Groups.ts +3 -1
- package/src/collections/Requests.ts +3 -1
- package/src/commands/Tweet.ts +43 -18
- package/src/commands/User.ts +3 -4
- package/src/enums/Resource.ts +3 -1
- package/src/helper/CliUtils.ts +2 -0
- package/src/helper/JsonUtils.ts +2 -0
- package/src/index.ts +5 -1
- package/src/models/args/FetchArgs.ts +128 -11
- package/src/models/args/PostArgs.ts +65 -24
- package/src/models/data/Tweet.ts +4 -4
- package/src/services/public/AuthService.ts +51 -1
- package/src/services/public/FetcherService.ts +9 -8
- package/src/services/public/TweetService.ts +103 -60
- package/src/services/public/UserService.ts +5 -6
|
@@ -3,14 +3,16 @@ import {
|
|
|
3
3
|
IListTweetsResponse,
|
|
4
4
|
ITweetDetailsResponse,
|
|
5
5
|
ITweetLikeResponse,
|
|
6
|
-
ITweetLikersResponse,
|
|
7
6
|
ITweetPostResponse,
|
|
7
|
+
ITweetRepliesResponse,
|
|
8
8
|
ITweetRetweetersResponse,
|
|
9
9
|
ITweetRetweetResponse,
|
|
10
|
+
ITweetScheduleResponse,
|
|
10
11
|
ITweetSearchResponse,
|
|
11
12
|
ITweetUnlikeResponse,
|
|
12
13
|
ITweetUnpostResponse,
|
|
13
14
|
ITweetUnretweetResponse,
|
|
15
|
+
ITweetUnscheduleResponse,
|
|
14
16
|
IUserDetailsResponse,
|
|
15
17
|
IUserFollowedResponse,
|
|
16
18
|
IUserFollowersResponse,
|
|
@@ -47,20 +49,21 @@ export const extractors = {
|
|
|
47
49
|
response.media_id_string ?? undefined,
|
|
48
50
|
|
|
49
51
|
TWEET_DETAILS: (response: ITweetDetailsResponse, id: string): Tweet | undefined => Tweet.single(response, id),
|
|
52
|
+
TWEET_DETAILS_ALT: (response: ITweetRepliesResponse, id: string): Tweet | undefined => Tweet.single(response, id),
|
|
50
53
|
TWEET_LIKE: (response: ITweetLikeResponse): boolean => (response?.data?.favorite_tweet ? true : false),
|
|
51
|
-
TWEET_LIKERS: (response: ITweetLikersResponse): CursoredData<User> =>
|
|
52
|
-
new CursoredData<User>(response, EBaseType.USER),
|
|
53
54
|
TWEET_POST: (response: ITweetPostResponse): string =>
|
|
54
55
|
response?.data?.create_tweet?.tweet_results?.result?.rest_id ?? undefined,
|
|
55
56
|
TWEET_RETWEET: (response: ITweetRetweetResponse): boolean => (response?.data?.create_retweet ? true : false),
|
|
56
57
|
TWEET_RETWEETERS: (response: ITweetRetweetersResponse): CursoredData<User> =>
|
|
57
58
|
new CursoredData<User>(response, EBaseType.USER),
|
|
59
|
+
TWEET_SCHEDULE: (response: ITweetScheduleResponse): string => response?.data?.tweet?.rest_id ?? undefined,
|
|
58
60
|
TWEET_SEARCH: (response: ITweetSearchResponse): CursoredData<Tweet> =>
|
|
59
61
|
new CursoredData<Tweet>(response, EBaseType.TWEET),
|
|
60
62
|
TWEET_UNLIKE: (response: ITweetUnlikeResponse): boolean => (response?.data?.unfavorite_tweet ? true : false),
|
|
61
63
|
TWEET_UNPOST: (response: ITweetUnpostResponse): boolean => (response?.data?.delete_tweet ? true : false),
|
|
62
64
|
TWEET_UNRETWEET: (response: ITweetUnretweetResponse): boolean =>
|
|
63
65
|
response?.data?.unretweet?.source_tweet_results?.result ? true : false,
|
|
66
|
+
TWEET_UNSCHEDULE: (response: ITweetUnscheduleResponse): boolean => response?.data?.scheduledtweet_delete == 'Done',
|
|
64
67
|
|
|
65
68
|
USER_DETAILS_BY_USERNAME: (response: IUserDetailsResponse): User | undefined => User.single(response),
|
|
66
69
|
USER_DETAILS_BY_ID: (response: IUserDetailsResponse): User | undefined => User.single(response),
|
|
@@ -19,7 +19,7 @@ export const allowGuestAuthentication = [
|
|
|
19
19
|
export const fetchResources = [
|
|
20
20
|
EResourceType.LIST_TWEETS,
|
|
21
21
|
EResourceType.TWEET_DETAILS,
|
|
22
|
-
EResourceType.
|
|
22
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
23
23
|
EResourceType.TWEET_RETWEETERS,
|
|
24
24
|
EResourceType.TWEET_SEARCH,
|
|
25
25
|
EResourceType.USER_DETAILS_BY_USERNAME,
|
|
@@ -48,9 +48,11 @@ export const postResources = [
|
|
|
48
48
|
EResourceType.TWEET_LIKE,
|
|
49
49
|
EResourceType.TWEET_POST,
|
|
50
50
|
EResourceType.TWEET_RETWEET,
|
|
51
|
+
EResourceType.TWEET_SCHEDULE,
|
|
51
52
|
EResourceType.TWEET_UNLIKE,
|
|
52
53
|
EResourceType.TWEET_UNPOST,
|
|
53
54
|
EResourceType.TWEET_UNRETWEET,
|
|
55
|
+
EResourceType.TWEET_UNSCHEDULE,
|
|
54
56
|
EResourceType.USER_FOLLOW,
|
|
55
57
|
EResourceType.USER_UNFOLLOW,
|
|
56
58
|
];
|
|
@@ -26,15 +26,17 @@ export const requests: { [key in keyof typeof EResourceType]: (args: FetchArgs |
|
|
|
26
26
|
MEDIA_UPLOAD_INITIALIZE: (args: PostArgs) => request.media.initializeUpload(args.upload!.size!),
|
|
27
27
|
|
|
28
28
|
TWEET_DETAILS: (args: FetchArgs) => request.tweet.details(args.id!),
|
|
29
|
+
TWEET_DETAILS_ALT: (args: FetchArgs) => request.tweet.replies(args.id!),
|
|
29
30
|
TWEET_LIKE: (args: PostArgs) => request.tweet.like(args.id!),
|
|
30
|
-
TWEET_LIKERS: (args: FetchArgs) => request.tweet.likers(args.id!, args.count, args.cursor),
|
|
31
31
|
TWEET_POST: (args: PostArgs) => request.tweet.post(args.tweet!),
|
|
32
32
|
TWEET_RETWEET: (args: PostArgs) => request.tweet.retweet(args.id!),
|
|
33
33
|
TWEET_RETWEETERS: (args: FetchArgs) => request.tweet.retweeters(args.id!, args.count, args.cursor),
|
|
34
|
+
TWEET_SCHEDULE: (args: PostArgs) => request.tweet.schedule(args.tweet!, args.tweet!.scheduleFor!),
|
|
34
35
|
TWEET_SEARCH: (args: FetchArgs) => request.tweet.search(args.filter!, args.count, args.cursor),
|
|
35
36
|
TWEET_UNLIKE: (args: PostArgs) => request.tweet.unlike(args.id!),
|
|
36
37
|
TWEET_UNPOST: (args: PostArgs) => request.tweet.unpost(args.id!),
|
|
37
38
|
TWEET_UNRETWEET: (args: PostArgs) => request.tweet.unretweet(args.id!),
|
|
39
|
+
TWEET_UNSCHEDULE: (args: PostArgs) => request.tweet.unschedule(args.id!),
|
|
38
40
|
|
|
39
41
|
USER_DETAILS_BY_USERNAME: (args: FetchArgs) => request.user.detailsByUsername(args.id!),
|
|
40
42
|
USER_DETAILS_BY_ID: (args: FetchArgs) => request.user.detailsById(args.id!),
|
package/src/commands/Tweet.ts
CHANGED
|
@@ -42,22 +42,6 @@ function createTweetCommand(rettiwt: Rettiwt): Command {
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
// Likers
|
|
46
|
-
tweet
|
|
47
|
-
.command('likers')
|
|
48
|
-
.description('Fetch the list of users who liked the given tweets')
|
|
49
|
-
.argument('<id>', 'The id of the tweet')
|
|
50
|
-
.argument('[count]', 'The number of likers to fetch')
|
|
51
|
-
.argument('[cursor]', 'The cursor to the batch of likers to fetch')
|
|
52
|
-
.action(async (id: string, count?: string, cursor?: string) => {
|
|
53
|
-
try {
|
|
54
|
-
const tweets = await rettiwt.tweet.likers(id, count ? parseInt(count) : undefined, cursor);
|
|
55
|
-
output(tweets);
|
|
56
|
-
} catch (error) {
|
|
57
|
-
output(error);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
45
|
// List
|
|
62
46
|
tweet
|
|
63
47
|
.command('list')
|
|
@@ -129,6 +113,33 @@ function createTweetCommand(rettiwt: Rettiwt): Command {
|
|
|
129
113
|
}
|
|
130
114
|
});
|
|
131
115
|
|
|
116
|
+
// Schedule
|
|
117
|
+
tweet
|
|
118
|
+
.command('schedule')
|
|
119
|
+
.description('Schedule a tweet to be posted at a given date/time')
|
|
120
|
+
.argument('<text>', 'The text to post as a tweet')
|
|
121
|
+
.argument('<time>', 'The date/time at which the tweet is to be scheduled (valid date/time string)')
|
|
122
|
+
.option('-m, --media [string]', 'Comma-separated list of ids of the media item(s) to be posted')
|
|
123
|
+
.option('-q, --quote [string]', 'The id of the tweet to quote in the tweet to be posted')
|
|
124
|
+
.option(
|
|
125
|
+
'-r, --reply [string]',
|
|
126
|
+
'The id of the tweet to which the reply is to be made, if the tweet is to be a reply',
|
|
127
|
+
)
|
|
128
|
+
.action(async (text: string, time: string, options?: { media?: string; quote?: string; reply?: string }) => {
|
|
129
|
+
try {
|
|
130
|
+
const result = await rettiwt.tweet.schedule({
|
|
131
|
+
text: text,
|
|
132
|
+
media: options?.media ? options?.media.split(',').map((item) => ({ id: item })) : undefined,
|
|
133
|
+
quote: options?.quote,
|
|
134
|
+
replyTo: options?.reply,
|
|
135
|
+
scheduleFor: new Date(time),
|
|
136
|
+
});
|
|
137
|
+
output(result);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
output(error);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
132
143
|
// Search
|
|
133
144
|
tweet
|
|
134
145
|
.command('search')
|
|
@@ -158,8 +169,8 @@ function createTweetCommand(rettiwt: Rettiwt): Command {
|
|
|
158
169
|
.option('-q, --quoted <string>', 'Matches the tweets that quote the tweet with the given id')
|
|
159
170
|
.option('--exclude-links', 'Matches tweets that do not contain links')
|
|
160
171
|
.option('--exclude-replies', 'Matches the tweets that are not replies')
|
|
161
|
-
.option('-s, --start <string>', 'Matches the tweets made since the given date (valid date string)')
|
|
162
|
-
.option('-e, --end <string>', 'Matches the tweets made upto the given date (valid date string)')
|
|
172
|
+
.option('-s, --start <string>', 'Matches the tweets made since the given date (valid date/time string)')
|
|
173
|
+
.option('-e, --end <string>', 'Matches the tweets made upto the given date (valid date/time string)')
|
|
163
174
|
.option('--stream', 'Stream the filtered tweets in pseudo-realtime')
|
|
164
175
|
.option('-i, --interval <number>', 'The polling interval (in ms) to use for streaming. Default is 60000')
|
|
165
176
|
.action(async (count?: string, cursor?: string, options?: TweetSearchOptions) => {
|
|
@@ -229,6 +240,20 @@ function createTweetCommand(rettiwt: Rettiwt): Command {
|
|
|
229
240
|
}
|
|
230
241
|
});
|
|
231
242
|
|
|
243
|
+
// Unschedule
|
|
244
|
+
tweet
|
|
245
|
+
.command('unschedule')
|
|
246
|
+
.description('Unschedule a tweet')
|
|
247
|
+
.argument('<id>', 'The id of the tweet')
|
|
248
|
+
.action(async (id: string) => {
|
|
249
|
+
try {
|
|
250
|
+
const result = await rettiwt.tweet.unschedule(id);
|
|
251
|
+
output(result);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
output(error);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
232
257
|
// Upload
|
|
233
258
|
tweet
|
|
234
259
|
.command('upload')
|
package/src/commands/User.ts
CHANGED
|
@@ -99,13 +99,12 @@ function createUserCommand(rettiwt: Rettiwt): Command {
|
|
|
99
99
|
|
|
100
100
|
// Likes
|
|
101
101
|
user.command('likes')
|
|
102
|
-
.description('Fetch
|
|
103
|
-
.argument('<id>', 'The id of the user')
|
|
102
|
+
.description('Fetch your list of liked tweet')
|
|
104
103
|
.argument('[count]', 'The number of liked tweets to fetch')
|
|
105
104
|
.argument('[cursor]', 'The cursor to the batch of liked tweets to fetch')
|
|
106
|
-
.action(async (
|
|
105
|
+
.action(async (count?: string, cursor?: string) => {
|
|
107
106
|
try {
|
|
108
|
-
const tweets = await rettiwt.user.likes(
|
|
107
|
+
const tweets = await rettiwt.user.likes(count ? parseInt(count) : undefined, cursor);
|
|
109
108
|
output(tweets);
|
|
110
109
|
} catch (error) {
|
|
111
110
|
output(error);
|
package/src/enums/Resource.ts
CHANGED
|
@@ -14,15 +14,17 @@ export enum EResourceType {
|
|
|
14
14
|
|
|
15
15
|
// TWEET
|
|
16
16
|
TWEET_DETAILS = 'TWEET_DETAILS',
|
|
17
|
+
TWEET_DETAILS_ALT = 'TWEET_DETAILS_ALT',
|
|
17
18
|
TWEET_LIKE = 'TWEET_LIKE',
|
|
18
|
-
TWEET_LIKERS = 'TWEET_LIKERS',
|
|
19
19
|
TWEET_POST = 'TWEET_POST',
|
|
20
20
|
TWEET_RETWEET = 'TWEET_RETWEET',
|
|
21
21
|
TWEET_RETWEETERS = 'TWEET_RETWEETERS',
|
|
22
|
+
TWEET_SCHEDULE = 'TWEET_SCHEDULE',
|
|
22
23
|
TWEET_SEARCH = 'TWEET_SEARCH',
|
|
23
24
|
TWEET_UNLIKE = 'TWEET_UNLIKE',
|
|
24
25
|
TWEET_UNPOST = 'TWEET_UNPOST',
|
|
25
26
|
TWEET_UNRETWEET = 'TWEET_UNRETWEET',
|
|
27
|
+
TWEET_UNSCHEDULE = 'TWEET_UNSCHEDULE',
|
|
26
28
|
|
|
27
29
|
// USER
|
|
28
30
|
USER_DETAILS_BY_USERNAME = 'USER_DETAILS_BY_USERNAME',
|
package/src/helper/CliUtils.ts
CHANGED
package/src/helper/JsonUtils.ts
CHANGED
|
@@ -52,6 +52,8 @@ export function findByFilter<T>(data: NonNullable<unknown>, key: string, value:
|
|
|
52
52
|
* @param data - The data on which search is to be performed.
|
|
53
53
|
* @param value - The value to search.
|
|
54
54
|
* @returns The key with the given value.
|
|
55
|
+
*
|
|
56
|
+
* @internal
|
|
55
57
|
*/
|
|
56
58
|
export function findKeyByValue(data: NonNullable<unknown>, value: string): string | undefined {
|
|
57
59
|
// Finding the key-value pairs that have the given value
|
package/src/index.ts
CHANGED
|
@@ -39,23 +39,27 @@ export {
|
|
|
39
39
|
IListTweetsResponse,
|
|
40
40
|
ITweetDetailsResponse,
|
|
41
41
|
ITweetLikeResponse,
|
|
42
|
-
ITweetLikersResponse,
|
|
43
42
|
ITweetPostResponse,
|
|
43
|
+
ITweetRepliesResponse,
|
|
44
44
|
ITweetRetweetersResponse,
|
|
45
45
|
ITweetRetweetResponse,
|
|
46
|
+
ITweetScheduleResponse,
|
|
46
47
|
ITweetSearchResponse,
|
|
47
48
|
ITweetUnlikeResponse,
|
|
48
49
|
ITweetUnpostResponse,
|
|
50
|
+
ITweetUnscheduleResponse,
|
|
49
51
|
ITweetUnretweetResponse,
|
|
50
52
|
} from 'rettiwt-core';
|
|
51
53
|
export {
|
|
52
54
|
IUserDetailsResponse,
|
|
55
|
+
IUserFollowedResponse,
|
|
53
56
|
IUserFollowersResponse,
|
|
54
57
|
IUserFollowingResponse,
|
|
55
58
|
IUserFollowResponse,
|
|
56
59
|
IUserHighlightsResponse,
|
|
57
60
|
IUserLikesResponse,
|
|
58
61
|
IUserMediaResponse,
|
|
62
|
+
IUserRecommendedResponse,
|
|
59
63
|
IUserSubscriptionsResponse,
|
|
60
64
|
IUserTweetsAndRepliesResponse,
|
|
61
65
|
IUserTweetsResponse,
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
IsArray,
|
|
3
3
|
IsBoolean,
|
|
4
4
|
IsDate,
|
|
5
|
+
IsEmpty,
|
|
5
6
|
IsNotEmpty,
|
|
6
7
|
IsNumber,
|
|
7
8
|
IsNumberString,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
IsOptional,
|
|
10
11
|
IsString,
|
|
11
12
|
Max,
|
|
13
|
+
Min,
|
|
12
14
|
validateSync,
|
|
13
15
|
} from 'class-validator';
|
|
14
16
|
|
|
@@ -37,14 +39,50 @@ export class FetchArgs {
|
|
|
37
39
|
* - Has not effect for:
|
|
38
40
|
* - {@link EResourceType.USER_FEED_FOLLOWED}
|
|
39
41
|
* - {@link EResourceType.USER_FEED_RECOMMENDED}
|
|
40
|
-
*
|
|
41
|
-
* @defaultValue 20
|
|
42
42
|
*/
|
|
43
|
-
@
|
|
43
|
+
@IsEmpty({
|
|
44
|
+
groups: [
|
|
45
|
+
EResourceType.TWEET_DETAILS,
|
|
46
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
47
|
+
EResourceType.USER_DETAILS_BY_ID,
|
|
48
|
+
EResourceType.USER_DETAILS_BY_USERNAME,
|
|
49
|
+
EResourceType.USER_FEED_FOLLOWED,
|
|
50
|
+
EResourceType.USER_FEED_RECOMMENDED,
|
|
51
|
+
],
|
|
52
|
+
})
|
|
53
|
+
@IsOptional({
|
|
54
|
+
groups: [
|
|
55
|
+
EResourceType.LIST_TWEETS,
|
|
56
|
+
EResourceType.TWEET_RETWEETERS,
|
|
57
|
+
EResourceType.TWEET_SEARCH,
|
|
58
|
+
EResourceType.USER_FOLLOWERS,
|
|
59
|
+
EResourceType.USER_FOLLOWING,
|
|
60
|
+
EResourceType.USER_HIGHLIGHTS,
|
|
61
|
+
EResourceType.USER_LIKES,
|
|
62
|
+
EResourceType.USER_MEDIA,
|
|
63
|
+
EResourceType.USER_SUBSCRIPTIONS,
|
|
64
|
+
EResourceType.USER_TIMELINE,
|
|
65
|
+
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
66
|
+
],
|
|
67
|
+
})
|
|
68
|
+
@Min(1, {
|
|
69
|
+
groups: [
|
|
70
|
+
EResourceType.LIST_TWEETS,
|
|
71
|
+
EResourceType.TWEET_RETWEETERS,
|
|
72
|
+
EResourceType.TWEET_SEARCH,
|
|
73
|
+
EResourceType.USER_FOLLOWERS,
|
|
74
|
+
EResourceType.USER_FOLLOWING,
|
|
75
|
+
EResourceType.USER_HIGHLIGHTS,
|
|
76
|
+
EResourceType.USER_LIKES,
|
|
77
|
+
EResourceType.USER_MEDIA,
|
|
78
|
+
EResourceType.USER_SUBSCRIPTIONS,
|
|
79
|
+
EResourceType.USER_TIMELINE,
|
|
80
|
+
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
81
|
+
],
|
|
82
|
+
})
|
|
44
83
|
@Max(100, {
|
|
45
84
|
groups: [
|
|
46
85
|
EResourceType.LIST_TWEETS,
|
|
47
|
-
EResourceType.TWEET_LIKERS,
|
|
48
86
|
EResourceType.TWEET_RETWEETERS,
|
|
49
87
|
EResourceType.USER_FOLLOWERS,
|
|
50
88
|
EResourceType.USER_FOLLOWING,
|
|
@@ -66,8 +104,48 @@ export class FetchArgs {
|
|
|
66
104
|
* - May be used for cursored resources.
|
|
67
105
|
* - Has no effect for other resources.
|
|
68
106
|
*/
|
|
69
|
-
@
|
|
70
|
-
|
|
107
|
+
@IsEmpty({
|
|
108
|
+
groups: [
|
|
109
|
+
EResourceType.TWEET_DETAILS,
|
|
110
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
111
|
+
EResourceType.USER_DETAILS_BY_ID,
|
|
112
|
+
EResourceType.USER_DETAILS_BY_USERNAME,
|
|
113
|
+
],
|
|
114
|
+
})
|
|
115
|
+
@IsOptional({
|
|
116
|
+
groups: [
|
|
117
|
+
EResourceType.LIST_TWEETS,
|
|
118
|
+
EResourceType.TWEET_RETWEETERS,
|
|
119
|
+
EResourceType.TWEET_SEARCH,
|
|
120
|
+
EResourceType.USER_FEED_FOLLOWED,
|
|
121
|
+
EResourceType.USER_FEED_RECOMMENDED,
|
|
122
|
+
EResourceType.USER_FOLLOWING,
|
|
123
|
+
EResourceType.USER_FOLLOWERS,
|
|
124
|
+
EResourceType.USER_HIGHLIGHTS,
|
|
125
|
+
EResourceType.USER_LIKES,
|
|
126
|
+
EResourceType.USER_MEDIA,
|
|
127
|
+
EResourceType.USER_SUBSCRIPTIONS,
|
|
128
|
+
EResourceType.USER_TIMELINE,
|
|
129
|
+
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
130
|
+
],
|
|
131
|
+
})
|
|
132
|
+
@IsString({
|
|
133
|
+
groups: [
|
|
134
|
+
EResourceType.LIST_TWEETS,
|
|
135
|
+
EResourceType.TWEET_RETWEETERS,
|
|
136
|
+
EResourceType.TWEET_SEARCH,
|
|
137
|
+
EResourceType.USER_FEED_FOLLOWED,
|
|
138
|
+
EResourceType.USER_FEED_RECOMMENDED,
|
|
139
|
+
EResourceType.USER_FOLLOWING,
|
|
140
|
+
EResourceType.USER_FOLLOWERS,
|
|
141
|
+
EResourceType.USER_HIGHLIGHTS,
|
|
142
|
+
EResourceType.USER_LIKES,
|
|
143
|
+
EResourceType.USER_MEDIA,
|
|
144
|
+
EResourceType.USER_SUBSCRIPTIONS,
|
|
145
|
+
EResourceType.USER_TIMELINE,
|
|
146
|
+
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
147
|
+
],
|
|
148
|
+
})
|
|
71
149
|
public cursor?: string;
|
|
72
150
|
|
|
73
151
|
/**
|
|
@@ -76,7 +154,26 @@ export class FetchArgs {
|
|
|
76
154
|
* @remarks
|
|
77
155
|
* Required when searching for tweets using {@link EResourceType.TWEET_SEARCH}.
|
|
78
156
|
*/
|
|
79
|
-
@
|
|
157
|
+
@IsEmpty({
|
|
158
|
+
groups: [
|
|
159
|
+
EResourceType.LIST_TWEETS,
|
|
160
|
+
EResourceType.TWEET_DETAILS,
|
|
161
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
162
|
+
EResourceType.TWEET_RETWEETERS,
|
|
163
|
+
EResourceType.USER_DETAILS_BY_USERNAME,
|
|
164
|
+
EResourceType.USER_DETAILS_BY_ID,
|
|
165
|
+
EResourceType.USER_FEED_FOLLOWED,
|
|
166
|
+
EResourceType.USER_FEED_RECOMMENDED,
|
|
167
|
+
EResourceType.USER_FOLLOWING,
|
|
168
|
+
EResourceType.USER_FOLLOWERS,
|
|
169
|
+
EResourceType.USER_HIGHLIGHTS,
|
|
170
|
+
EResourceType.USER_LIKES,
|
|
171
|
+
EResourceType.USER_MEDIA,
|
|
172
|
+
EResourceType.USER_SUBSCRIPTIONS,
|
|
173
|
+
EResourceType.USER_TIMELINE,
|
|
174
|
+
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
175
|
+
],
|
|
176
|
+
})
|
|
80
177
|
@IsNotEmpty({ groups: [EResourceType.TWEET_SEARCH] })
|
|
81
178
|
@IsObject({ groups: [EResourceType.TWEET_SEARCH] })
|
|
82
179
|
public filter?: TweetFilter;
|
|
@@ -88,12 +185,14 @@ export class FetchArgs {
|
|
|
88
185
|
* - Required for all resources except {@link EResourceType.TWEET_SEARCH} and {@link EResourceType.USER_TIMELINE_RECOMMENDED}.
|
|
89
186
|
* - For {@link EResourceType.USER_DETAILS_BY_USERNAME}, can be alphanumeric, while for others, is strictly numeric.
|
|
90
187
|
*/
|
|
91
|
-
@
|
|
188
|
+
@IsEmpty({
|
|
189
|
+
groups: [EResourceType.USER_FEED_FOLLOWED, EResourceType.USER_FEED_RECOMMENDED],
|
|
190
|
+
})
|
|
92
191
|
@IsNotEmpty({
|
|
93
192
|
groups: [
|
|
94
193
|
EResourceType.LIST_TWEETS,
|
|
95
194
|
EResourceType.TWEET_DETAILS,
|
|
96
|
-
EResourceType.
|
|
195
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
97
196
|
EResourceType.TWEET_RETWEETERS,
|
|
98
197
|
EResourceType.USER_DETAILS_BY_USERNAME,
|
|
99
198
|
EResourceType.USER_DETAILS_BY_ID,
|
|
@@ -107,11 +206,29 @@ export class FetchArgs {
|
|
|
107
206
|
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
108
207
|
],
|
|
109
208
|
})
|
|
209
|
+
@IsString({
|
|
210
|
+
groups: [
|
|
211
|
+
EResourceType.LIST_TWEETS,
|
|
212
|
+
EResourceType.TWEET_DETAILS,
|
|
213
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
214
|
+
EResourceType.TWEET_RETWEETERS,
|
|
215
|
+
EResourceType.USER_DETAILS_BY_USERNAME,
|
|
216
|
+
EResourceType.USER_DETAILS_BY_ID,
|
|
217
|
+
EResourceType.USER_FOLLOWING,
|
|
218
|
+
EResourceType.USER_FOLLOWERS,
|
|
219
|
+
EResourceType.USER_HIGHLIGHTS,
|
|
220
|
+
EResourceType.USER_LIKES,
|
|
221
|
+
EResourceType.USER_MEDIA,
|
|
222
|
+
EResourceType.USER_SUBSCRIPTIONS,
|
|
223
|
+
EResourceType.USER_TIMELINE,
|
|
224
|
+
EResourceType.USER_TIMELINE_AND_REPLIES,
|
|
225
|
+
],
|
|
226
|
+
})
|
|
110
227
|
@IsNumberString(undefined, {
|
|
111
228
|
groups: [
|
|
112
229
|
EResourceType.LIST_TWEETS,
|
|
113
230
|
EResourceType.TWEET_DETAILS,
|
|
114
|
-
EResourceType.
|
|
231
|
+
EResourceType.TWEET_DETAILS_ALT,
|
|
115
232
|
EResourceType.TWEET_RETWEETERS,
|
|
116
233
|
EResourceType.USER_DETAILS_BY_ID,
|
|
117
234
|
EResourceType.USER_FOLLOWERS,
|
|
@@ -132,7 +249,7 @@ export class FetchArgs {
|
|
|
132
249
|
*/
|
|
133
250
|
public constructor(resource: EResourceType, args: FetchArgs) {
|
|
134
251
|
this.id = args.id;
|
|
135
|
-
this.count = args.count
|
|
252
|
+
this.count = args.count;
|
|
136
253
|
this.cursor = args.cursor;
|
|
137
254
|
this.filter = args.filter ? new TweetFilter(args.filter) : undefined;
|
|
138
255
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ArrayMaxSize,
|
|
3
3
|
IsArray,
|
|
4
|
+
IsDate,
|
|
5
|
+
IsEmpty,
|
|
4
6
|
IsNotEmpty,
|
|
5
7
|
IsNumberString,
|
|
6
8
|
IsObject,
|
|
@@ -8,6 +10,7 @@ import {
|
|
|
8
10
|
IsString,
|
|
9
11
|
Max,
|
|
10
12
|
MaxLength,
|
|
13
|
+
MinDate,
|
|
11
14
|
validateSync,
|
|
12
15
|
} from 'class-validator';
|
|
13
16
|
|
|
@@ -35,7 +38,15 @@ export class PostArgs {
|
|
|
35
38
|
* - {@link EResourceType.USER_FOLLOW}
|
|
36
39
|
* - {@link EResourceType.USER_UNFOLLOW}
|
|
37
40
|
*/
|
|
38
|
-
@
|
|
41
|
+
@IsEmpty({
|
|
42
|
+
groups: [
|
|
43
|
+
EResourceType.MEDIA_UPLOAD_APPEND,
|
|
44
|
+
EResourceType.MEDIA_UPLOAD_FINALIZE,
|
|
45
|
+
EResourceType.MEDIA_UPLOAD_INITIALIZE,
|
|
46
|
+
EResourceType.TWEET_POST,
|
|
47
|
+
EResourceType.TWEET_SCHEDULE,
|
|
48
|
+
],
|
|
49
|
+
})
|
|
39
50
|
@IsNotEmpty({
|
|
40
51
|
groups: [
|
|
41
52
|
EResourceType.TWEET_LIKE,
|
|
@@ -43,6 +54,7 @@ export class PostArgs {
|
|
|
43
54
|
EResourceType.TWEET_UNLIKE,
|
|
44
55
|
EResourceType.TWEET_UNPOST,
|
|
45
56
|
EResourceType.TWEET_UNRETWEET,
|
|
57
|
+
EResourceType.TWEET_UNSCHEDULE,
|
|
46
58
|
EResourceType.USER_FOLLOW,
|
|
47
59
|
EResourceType.USER_UNFOLLOW,
|
|
48
60
|
],
|
|
@@ -54,6 +66,7 @@ export class PostArgs {
|
|
|
54
66
|
EResourceType.TWEET_UNLIKE,
|
|
55
67
|
EResourceType.TWEET_UNPOST,
|
|
56
68
|
EResourceType.TWEET_UNRETWEET,
|
|
69
|
+
EResourceType.TWEET_UNSCHEDULE,
|
|
57
70
|
EResourceType.USER_FOLLOW,
|
|
58
71
|
EResourceType.USER_UNFOLLOW,
|
|
59
72
|
],
|
|
@@ -66,9 +79,23 @@ export class PostArgs {
|
|
|
66
79
|
* @remarks
|
|
67
80
|
* Required only when posting a tweet using {@link EResourceType.TWEET_POST}
|
|
68
81
|
*/
|
|
69
|
-
@
|
|
70
|
-
|
|
71
|
-
|
|
82
|
+
@IsEmpty({
|
|
83
|
+
groups: [
|
|
84
|
+
EResourceType.MEDIA_UPLOAD_APPEND,
|
|
85
|
+
EResourceType.MEDIA_UPLOAD_FINALIZE,
|
|
86
|
+
EResourceType.MEDIA_UPLOAD_INITIALIZE,
|
|
87
|
+
EResourceType.TWEET_LIKE,
|
|
88
|
+
EResourceType.TWEET_RETWEET,
|
|
89
|
+
EResourceType.TWEET_UNLIKE,
|
|
90
|
+
EResourceType.TWEET_UNPOST,
|
|
91
|
+
EResourceType.TWEET_UNRETWEET,
|
|
92
|
+
EResourceType.TWEET_UNSCHEDULE,
|
|
93
|
+
EResourceType.USER_FOLLOW,
|
|
94
|
+
EResourceType.USER_UNFOLLOW,
|
|
95
|
+
],
|
|
96
|
+
})
|
|
97
|
+
@IsNotEmpty({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
98
|
+
@IsObject({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
72
99
|
public tweet?: TweetArgs;
|
|
73
100
|
|
|
74
101
|
/**
|
|
@@ -80,7 +107,13 @@ export class PostArgs {
|
|
|
80
107
|
* - {@link EResourceType.MEDIA_UPLOAD_FINALIZE}
|
|
81
108
|
* - {@link EResourceType.MEDIA_UPLOAD_INITIALIZE}
|
|
82
109
|
*/
|
|
83
|
-
@
|
|
110
|
+
@IsEmpty({
|
|
111
|
+
groups: [
|
|
112
|
+
EResourceType.MEDIA_UPLOAD_APPEND,
|
|
113
|
+
EResourceType.MEDIA_UPLOAD_FINALIZE,
|
|
114
|
+
EResourceType.MEDIA_UPLOAD_INITIALIZE,
|
|
115
|
+
],
|
|
116
|
+
})
|
|
84
117
|
@IsNotEmpty({
|
|
85
118
|
groups: [
|
|
86
119
|
EResourceType.MEDIA_UPLOAD_INITIALIZE,
|
|
@@ -103,7 +136,7 @@ export class PostArgs {
|
|
|
103
136
|
*/
|
|
104
137
|
public constructor(resource: EResourceType, args: PostArgs) {
|
|
105
138
|
this.id = args.id;
|
|
106
|
-
this.tweet = args.tweet ? new TweetArgs(args.tweet) : undefined;
|
|
139
|
+
this.tweet = args.tweet ? new TweetArgs(resource, args.tweet) : undefined;
|
|
107
140
|
this.upload = args.upload ? new UploadArgs(resource, args.upload) : undefined;
|
|
108
141
|
|
|
109
142
|
// Validating this object
|
|
@@ -128,45 +161,53 @@ export class TweetArgs extends NewTweet {
|
|
|
128
161
|
* @remarks
|
|
129
162
|
* Maximum number of media items that can be posted is 4.
|
|
130
163
|
*/
|
|
131
|
-
@IsOptional()
|
|
132
|
-
@IsArray()
|
|
133
|
-
@ArrayMaxSize(4)
|
|
134
|
-
@IsObject({ each: true })
|
|
164
|
+
@IsOptional({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
165
|
+
@IsArray({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
166
|
+
@ArrayMaxSize(4, { groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
167
|
+
@IsObject({ each: true, groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
135
168
|
public media?: TweetMediaArgs[];
|
|
136
169
|
|
|
137
170
|
/** The id of the tweet to quote. */
|
|
138
|
-
@IsOptional()
|
|
139
|
-
@IsNumberString()
|
|
171
|
+
@IsOptional({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
172
|
+
@IsNumberString(undefined, { groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
140
173
|
public quote?: string;
|
|
141
174
|
|
|
142
175
|
/** The id of the tweet to which the given tweet must be a reply. */
|
|
143
|
-
@IsOptional()
|
|
144
|
-
@IsNumberString()
|
|
176
|
+
@IsOptional({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
177
|
+
@IsNumberString(undefined, { groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
145
178
|
public replyTo?: string;
|
|
146
179
|
|
|
180
|
+
/** The date/time at which the tweet must be scheduled to be posted. */
|
|
181
|
+
@IsEmpty({ groups: [EResourceType.TWEET_POST] })
|
|
182
|
+
@IsNotEmpty({ groups: [EResourceType.TWEET_SCHEDULE] })
|
|
183
|
+
@IsDate({ groups: [EResourceType.TWEET_SCHEDULE] })
|
|
184
|
+
@MinDate(() => new Date(), { groups: [EResourceType.TWEET_SCHEDULE] })
|
|
185
|
+
public scheduleFor?: Date;
|
|
186
|
+
|
|
147
187
|
/**
|
|
148
188
|
* The text for the tweet to be created.
|
|
149
189
|
*
|
|
150
190
|
* @remarks
|
|
151
191
|
* Length of the tweet must be \<= 280 characters.
|
|
152
192
|
*/
|
|
153
|
-
@IsNotEmpty()
|
|
154
|
-
@IsString()
|
|
155
|
-
@MaxLength(280)
|
|
193
|
+
@IsNotEmpty({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
194
|
+
@IsString({ groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
195
|
+
@MaxLength(280, { groups: [EResourceType.TWEET_POST, EResourceType.TWEET_SCHEDULE] })
|
|
156
196
|
public text: string;
|
|
157
197
|
|
|
158
198
|
/**
|
|
159
199
|
* @param args - Arguments specifying the tweet to be posted.
|
|
160
200
|
*/
|
|
161
|
-
public constructor(args: TweetArgs) {
|
|
201
|
+
public constructor(resource: EResourceType, args: TweetArgs) {
|
|
162
202
|
super();
|
|
163
|
-
this.text = args.text;
|
|
164
|
-
this.quote = args.quote;
|
|
165
203
|
this.media = args.media ? args.media.map((item) => new TweetMediaArgs(item)) : undefined;
|
|
204
|
+
this.quote = args.quote;
|
|
166
205
|
this.replyTo = args.replyTo;
|
|
206
|
+
this.scheduleFor = args.scheduleFor;
|
|
207
|
+
this.text = args.text;
|
|
167
208
|
|
|
168
209
|
// Validating this object
|
|
169
|
-
const validationResult = validateSync(this);
|
|
210
|
+
const validationResult = validateSync(this, { groups: [resource] });
|
|
170
211
|
|
|
171
212
|
// If valiation error occured
|
|
172
213
|
if (validationResult.length) {
|
|
@@ -223,13 +264,13 @@ export class TweetMediaArgs extends NewTweetMedia {
|
|
|
223
264
|
*/
|
|
224
265
|
export class UploadArgs {
|
|
225
266
|
/** The id allocated to the media file to be uploaded. */
|
|
226
|
-
@
|
|
267
|
+
@IsEmpty({ groups: [EResourceType.MEDIA_UPLOAD_INITIALIZE] })
|
|
227
268
|
@IsNotEmpty({ groups: [EResourceType.MEDIA_UPLOAD_APPEND, EResourceType.MEDIA_UPLOAD_FINALIZE] })
|
|
228
269
|
@IsNumberString(undefined, { groups: [EResourceType.MEDIA_UPLOAD_APPEND, EResourceType.MEDIA_UPLOAD_FINALIZE] })
|
|
229
270
|
public id?: string;
|
|
230
271
|
|
|
231
272
|
/** The media file to be uploaded. */
|
|
232
|
-
@
|
|
273
|
+
@IsEmpty({ groups: [EResourceType.MEDIA_UPLOAD_FINALIZE, EResourceType.MEDIA_UPLOAD_INITIALIZE] })
|
|
233
274
|
@IsNotEmpty({ groups: [EResourceType.MEDIA_UPLOAD_APPEND] })
|
|
234
275
|
public media?: string | ArrayBuffer;
|
|
235
276
|
|
|
@@ -238,7 +279,7 @@ export class UploadArgs {
|
|
|
238
279
|
*
|
|
239
280
|
* @remarks The size must be \<= 5242880 bytes.
|
|
240
281
|
*/
|
|
241
|
-
@
|
|
282
|
+
@IsEmpty({ groups: [EResourceType.MEDIA_UPLOAD_APPEND, EResourceType.MEDIA_UPLOAD_FINALIZE] })
|
|
242
283
|
@IsNotEmpty({ groups: [EResourceType.MEDIA_UPLOAD_INITIALIZE] })
|
|
243
284
|
@Max(5242880, { groups: [EResourceType.MEDIA_UPLOAD_INITIALIZE] })
|
|
244
285
|
public size?: number;
|
package/src/models/data/Tweet.ts
CHANGED
|
@@ -48,8 +48,8 @@ export class Tweet {
|
|
|
48
48
|
/** The number of quotes of the tweet. */
|
|
49
49
|
public quoteCount: number;
|
|
50
50
|
|
|
51
|
-
/** The
|
|
52
|
-
public quoted?:
|
|
51
|
+
/** The tweet which is quoted in the tweet. */
|
|
52
|
+
public quoted?: Tweet;
|
|
53
53
|
|
|
54
54
|
/** The number of replies to the tweet. */
|
|
55
55
|
public replyCount: number;
|
|
@@ -60,7 +60,7 @@ export class Tweet {
|
|
|
60
60
|
/** The number of retweets of the tweet. */
|
|
61
61
|
public retweetCount: number;
|
|
62
62
|
|
|
63
|
-
/** The tweet which
|
|
63
|
+
/** The tweet which is retweeted in this tweet (if any). */
|
|
64
64
|
public retweetedTweet?: Tweet;
|
|
65
65
|
|
|
66
66
|
/** The details of the user who made the tweet. */
|
|
@@ -78,7 +78,7 @@ export class Tweet {
|
|
|
78
78
|
this.tweetBy = new User(tweet.core.user_results.result);
|
|
79
79
|
this.entities = new TweetEntities(tweet.legacy.entities);
|
|
80
80
|
this.media = tweet.legacy.extended_entities?.media?.map((media) => new TweetMedia(media));
|
|
81
|
-
this.quoted = tweet.
|
|
81
|
+
this.quoted = tweet.quoted_status_result ? new Tweet(tweet.quoted_status_result.result) : undefined;
|
|
82
82
|
this.fullText = tweet.note_tweet ? tweet.note_tweet.note_tweet_results.result.text : tweet.legacy.full_text;
|
|
83
83
|
this.replyTo = tweet.legacy.in_reply_to_status_id_str;
|
|
84
84
|
this.lang = tweet.legacy.lang;
|