rettiwt-api 2.7.1 → 3.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 +73 -5
- package/.tool-versions +1 -0
- package/README.md +87 -20
- package/dist/Rettiwt.js +0 -1
- package/dist/Rettiwt.js.map +1 -1
- package/dist/cli.js +2 -4
- package/dist/cli.js.map +1 -1
- package/dist/collections/Extractors.d.ts +10 -0
- package/dist/collections/Extractors.js +43 -0
- package/dist/collections/Extractors.js.map +1 -0
- package/dist/collections/Groups.d.ts +19 -0
- package/dist/collections/Groups.js +55 -0
- package/dist/collections/Groups.js.map +1 -0
- package/dist/collections/Requests.d.ts +12 -0
- package/dist/collections/Requests.js +46 -0
- package/dist/collections/Requests.js.map +1 -0
- package/dist/commands/Auth.d.ts +6 -0
- package/dist/commands/Auth.js +26 -8
- package/dist/commands/Auth.js.map +1 -1
- package/dist/commands/Tweet.js +237 -82
- package/dist/commands/Tweet.js.map +1 -1
- package/dist/commands/User.js +197 -36
- package/dist/commands/User.js.map +1 -1
- package/dist/enums/Api.d.ts +30 -0
- package/dist/enums/Api.js +32 -1
- package/dist/enums/Api.js.map +1 -1
- package/dist/enums/Data.d.ts +9 -0
- package/dist/enums/Data.js +14 -0
- package/dist/enums/Data.js.map +1 -0
- package/dist/enums/Http.d.ts +1 -1
- package/dist/enums/Http.js +1 -1
- package/dist/enums/Logging.d.ts +6 -5
- package/dist/enums/Logging.js +6 -5
- package/dist/enums/Logging.js.map +1 -1
- package/dist/enums/Resource.d.ts +33 -0
- package/dist/enums/Resource.js +42 -0
- package/dist/enums/Resource.js.map +1 -0
- package/dist/helper/CliUtils.d.ts +1 -1
- package/dist/helper/CliUtils.js.map +1 -1
- package/dist/index.d.ts +11 -9
- package/dist/index.js +11 -14
- package/dist/index.js.map +1 -1
- package/dist/models/args/FetchArgs.d.ts +129 -0
- package/dist/models/args/FetchArgs.js +263 -0
- package/dist/models/args/FetchArgs.js.map +1 -0
- package/dist/models/args/PostArgs.d.ts +116 -0
- package/dist/models/args/PostArgs.js +232 -0
- package/dist/models/args/PostArgs.js.map +1 -0
- package/dist/models/data/CursoredData.d.ts +11 -11
- package/dist/models/data/CursoredData.js +21 -16
- package/dist/models/data/CursoredData.js.map +1 -1
- package/dist/models/data/List.d.ts +8 -10
- package/dist/models/data/List.js +2 -4
- package/dist/models/data/List.js.map +1 -1
- package/dist/models/data/Tweet.d.ts +41 -29
- package/dist/models/data/Tweet.js +71 -15
- package/dist/models/data/Tweet.js.map +1 -1
- package/dist/models/data/User.d.ts +36 -20
- package/dist/models/data/User.js +69 -7
- package/dist/models/data/User.js.map +1 -1
- package/dist/models/errors/ApiError.d.ts +1 -3
- package/dist/models/errors/ApiError.js +1 -4
- package/dist/models/errors/ApiError.js.map +1 -1
- package/dist/models/errors/DataValidationError.d.ts +30 -0
- package/dist/models/errors/DataValidationError.js +34 -0
- package/dist/models/errors/DataValidationError.js.map +1 -0
- package/dist/models/errors/HttpError.d.ts +1 -3
- package/dist/models/errors/HttpError.js +1 -4
- package/dist/models/errors/HttpError.js.map +1 -1
- package/dist/models/errors/TimeoutError.d.ts +2 -4
- package/dist/models/errors/TimeoutError.js +2 -5
- package/dist/models/errors/TimeoutError.js.map +1 -1
- package/dist/services/internal/ErrorService.d.ts +45 -35
- package/dist/services/internal/ErrorService.js +70 -68
- package/dist/services/internal/ErrorService.js.map +1 -1
- package/dist/services/internal/LogService.d.ts +7 -5
- package/dist/services/internal/LogService.js +28 -9
- package/dist/services/internal/LogService.js.map +1 -1
- package/dist/services/public/AuthService.d.ts +24 -20
- package/dist/services/public/AuthService.js +38 -36
- package/dist/services/public/AuthService.js.map +1 -1
- package/dist/services/public/FetcherService.d.ts +99 -0
- package/dist/services/public/FetcherService.js +254 -0
- package/dist/services/public/FetcherService.js.map +1 -0
- package/dist/services/public/TweetService.d.ts +213 -94
- package/dist/services/public/TweetService.js +405 -208
- package/dist/services/public/TweetService.js.map +1 -1
- package/dist/services/public/UserService.d.ts +185 -52
- package/dist/services/public/UserService.js +333 -103
- package/dist/services/public/UserService.js.map +1 -1
- package/dist/types/ReturnTypes.d.ts +21 -0
- package/dist/types/ReturnTypes.js +3 -0
- package/dist/types/ReturnTypes.js.map +1 -0
- package/package.json +4 -2
- package/src/Rettiwt.ts +0 -3
- package/src/cli.ts +2 -4
- package/src/collections/Extractors.ts +63 -0
- package/src/collections/Groups.ts +54 -0
- package/src/collections/Requests.ts +52 -0
- package/src/commands/Auth.ts +19 -7
- package/src/commands/Tweet.ts +179 -91
- package/src/commands/User.ts +118 -25
- package/src/enums/Api.ts +31 -0
- package/src/enums/Data.ts +9 -0
- package/src/enums/Http.ts +1 -1
- package/src/enums/Logging.ts +6 -5
- package/src/enums/Resource.ts +40 -0
- package/src/helper/CliUtils.ts +1 -1
- package/src/index.ts +41 -14
- package/src/models/args/FetchArgs.ts +296 -0
- package/src/models/args/PostArgs.ts +263 -0
- package/src/models/data/CursoredData.ts +23 -15
- package/src/models/data/List.ts +12 -15
- package/src/models/data/Tweet.ts +105 -39
- package/src/models/data/User.ts +97 -30
- package/src/models/errors/ApiError.ts +1 -4
- package/src/models/errors/DataValidationError.ts +44 -0
- package/src/models/errors/HttpError.ts +1 -4
- package/src/models/errors/TimeoutError.ts +2 -5
- package/src/services/internal/ErrorService.ts +76 -75
- package/src/services/internal/LogService.ts +20 -10
- package/src/services/public/AuthService.ts +39 -38
- package/src/services/public/FetcherService.ts +230 -0
- package/src/services/public/TweetService.ts +381 -179
- package/src/services/public/UserService.ts +314 -86
- package/src/types/RettiwtConfig.ts +0 -1
- package/src/types/ReturnTypes.ts +24 -0
- package/dist/models/args/TweetArgs.d.ts +0 -44
- package/dist/models/args/TweetArgs.js +0 -82
- package/dist/models/args/TweetArgs.js.map +0 -1
- package/dist/models/data/Media.d.ts +0 -14
- package/dist/models/data/Media.js +0 -19
- package/dist/models/data/Media.js.map +0 -1
- package/dist/services/internal/FetcherService.d.ts +0 -106
- package/dist/services/internal/FetcherService.js +0 -365
- package/dist/services/internal/FetcherService.js.map +0 -1
- package/src/models/args/TweetArgs.ts +0 -98
- package/src/models/data/Media.ts +0 -19
- package/src/services/internal/FetcherService.ts +0 -365
|
@@ -1,20 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { statSync } from 'fs';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
IInitializeMediaUploadResponse,
|
|
5
|
+
IListTweetsResponse,
|
|
6
|
+
ITweetDetailsResponse,
|
|
7
|
+
ITweetLikeResponse,
|
|
8
|
+
ITweetLikersResponse,
|
|
9
|
+
ITweetPostResponse,
|
|
10
|
+
ITweetRetweetersResponse,
|
|
11
|
+
ITweetRetweetResponse,
|
|
12
|
+
ITweetSearchResponse,
|
|
13
|
+
ITweetUnlikeResponse,
|
|
14
|
+
ITweetUnpostResponse,
|
|
15
|
+
ITweetUnretweetResponse,
|
|
16
|
+
TweetFilter,
|
|
17
|
+
} from 'rettiwt-core';
|
|
18
|
+
|
|
19
|
+
import { EResourceType } from '../../enums/Resource';
|
|
20
|
+
import { TweetArgs } from '../../models/args/PostArgs';
|
|
21
|
+
import { CursoredData } from '../../models/data/CursoredData';
|
|
11
22
|
import { Tweet } from '../../models/data/Tweet';
|
|
12
23
|
import { User } from '../../models/data/User';
|
|
13
|
-
import {
|
|
14
|
-
|
|
24
|
+
import { IRettiwtConfig } from '../../types/RettiwtConfig';
|
|
25
|
+
|
|
26
|
+
import { FetcherService } from './FetcherService';
|
|
15
27
|
|
|
16
28
|
/**
|
|
17
|
-
* Handles
|
|
29
|
+
* Handles interacting with resources related to tweets.
|
|
18
30
|
*
|
|
19
31
|
* @public
|
|
20
32
|
*/
|
|
@@ -32,7 +44,10 @@ export class TweetService extends FetcherService {
|
|
|
32
44
|
* Get the details of a tweet.
|
|
33
45
|
*
|
|
34
46
|
* @param id - The id of the target tweet.
|
|
35
|
-
*
|
|
47
|
+
*
|
|
48
|
+
* @returns
|
|
49
|
+
* The details of the tweet with the given id.
|
|
50
|
+
* If no tweet matches the given id, returns `undefined`.
|
|
36
51
|
*
|
|
37
52
|
* @example
|
|
38
53
|
* ```
|
|
@@ -41,8 +56,8 @@ export class TweetService extends FetcherService {
|
|
|
41
56
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
42
57
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
43
58
|
*
|
|
44
|
-
* // Fetching the details of the tweet with the id '
|
|
45
|
-
* rettiwt.tweet.details('
|
|
59
|
+
* // Fetching the details of the tweet with the id '1234567890'
|
|
60
|
+
* rettiwt.tweet.details('1234567890')
|
|
46
61
|
* .then(res => {
|
|
47
62
|
* console.log(res);
|
|
48
63
|
* })
|
|
@@ -50,23 +65,25 @@ export class TweetService extends FetcherService {
|
|
|
50
65
|
* console.log(err);
|
|
51
66
|
* });
|
|
52
67
|
* ```
|
|
53
|
-
*
|
|
54
|
-
* @public
|
|
55
68
|
*/
|
|
56
|
-
public async details(id: string): Promise<Tweet> {
|
|
57
|
-
|
|
58
|
-
const data = await this.fetch<Tweet>(EResourceType.TWEET_DETAILS, { id: id });
|
|
69
|
+
public async details(id: string): Promise<Tweet | undefined> {
|
|
70
|
+
const resource = EResourceType.TWEET_DETAILS;
|
|
59
71
|
|
|
60
|
-
|
|
72
|
+
// Fetching raw tweet details
|
|
73
|
+
const response = await this.request<ITweetDetailsResponse>(resource, { id: id });
|
|
74
|
+
|
|
75
|
+
// Deserializing response
|
|
76
|
+
const data = this.extract<Tweet>(response, resource);
|
|
77
|
+
|
|
78
|
+
return data;
|
|
61
79
|
}
|
|
62
80
|
|
|
63
81
|
/**
|
|
64
|
-
*
|
|
82
|
+
* Like a tweet.
|
|
65
83
|
*
|
|
66
|
-
* @param
|
|
67
|
-
*
|
|
68
|
-
* @
|
|
69
|
-
* @returns The list of tweets that match the given filter.
|
|
84
|
+
* @param id - The id of the tweet to be liked.
|
|
85
|
+
*
|
|
86
|
+
* @returns Whether liking was successful or not.
|
|
70
87
|
*
|
|
71
88
|
* @example
|
|
72
89
|
* ```
|
|
@@ -75,8 +92,8 @@ export class TweetService extends FetcherService {
|
|
|
75
92
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
76
93
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
77
94
|
*
|
|
78
|
-
* //
|
|
79
|
-
* rettiwt.tweet.
|
|
95
|
+
* // Liking the Tweet with id '1234567890'
|
|
96
|
+
* rettiwt.tweet.like('1234567890')
|
|
80
97
|
* .then(res => {
|
|
81
98
|
* console.log(res);
|
|
82
99
|
* })
|
|
@@ -84,31 +101,27 @@ export class TweetService extends FetcherService {
|
|
|
84
101
|
* console.log(err);
|
|
85
102
|
* });
|
|
86
103
|
* ```
|
|
87
|
-
*
|
|
88
|
-
* @remarks For details about available filters, refer to {@link TweetFilter}
|
|
89
|
-
*
|
|
90
|
-
* @public
|
|
91
104
|
*/
|
|
92
|
-
public async
|
|
93
|
-
//
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
count: count,
|
|
97
|
-
cursor: cursor,
|
|
105
|
+
public async like(id: string): Promise<boolean> {
|
|
106
|
+
// Favoriting the tweet
|
|
107
|
+
const response = await this.request<ITweetLikeResponse>(EResourceType.TWEET_LIKE, {
|
|
108
|
+
id: id,
|
|
98
109
|
});
|
|
99
110
|
|
|
100
|
-
//
|
|
101
|
-
data.
|
|
111
|
+
// Deserializing response
|
|
112
|
+
const data = this.extract<boolean>(response, EResourceType.TWEET_LIKE) ?? false;
|
|
102
113
|
|
|
103
114
|
return data;
|
|
104
115
|
}
|
|
105
116
|
|
|
106
117
|
/**
|
|
107
|
-
*
|
|
118
|
+
* Get the list of users who liked a tweet.
|
|
108
119
|
*
|
|
109
|
-
* @param
|
|
110
|
-
* @param
|
|
111
|
-
* @
|
|
120
|
+
* @param id - The id of the target tweet.
|
|
121
|
+
* @param count - The number of likers to fetch, must be \<= 100.
|
|
122
|
+
* @param cursor - The cursor to the batch of likers to fetch.
|
|
123
|
+
*
|
|
124
|
+
* @returns The list of users who liked the given tweet.
|
|
112
125
|
*
|
|
113
126
|
* @example
|
|
114
127
|
* ```
|
|
@@ -117,64 +130,40 @@ export class TweetService extends FetcherService {
|
|
|
117
130
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
118
131
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
119
132
|
*
|
|
120
|
-
* //
|
|
121
|
-
* (
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* console.log(err);
|
|
129
|
-
* }
|
|
130
|
-
* })();
|
|
133
|
+
* // Fetching the most recent 100 likers of the Tweet with id '1234567890'
|
|
134
|
+
* rettiwt.tweet.likers('1234567890')
|
|
135
|
+
* .then(res => {
|
|
136
|
+
* console.log(res);
|
|
137
|
+
* })
|
|
138
|
+
* .catch(err => {
|
|
139
|
+
* console.log(err);
|
|
140
|
+
* });
|
|
131
141
|
* ```
|
|
132
|
-
*
|
|
133
|
-
* @public
|
|
134
142
|
*/
|
|
135
|
-
public async
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
let cursor: string | undefined = undefined;
|
|
139
|
-
let sinceId: string | undefined = undefined;
|
|
140
|
-
let nextSinceId: string | undefined = undefined;
|
|
141
|
-
|
|
142
|
-
while (true) {
|
|
143
|
-
// Pause execution for the specified polling interval before proceeding to the next iteration
|
|
144
|
-
await new Promise((resolve) => setTimeout(resolve, pollingInterval));
|
|
143
|
+
public async likers(id: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
|
|
144
|
+
const resource = EResourceType.TWEET_LIKERS;
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
146
|
+
// Fetching raw likers
|
|
147
|
+
const response = await this.request<ITweetLikersResponse>(resource, {
|
|
148
|
+
id: id,
|
|
149
|
+
count: count,
|
|
150
|
+
cursor: cursor,
|
|
151
|
+
});
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
nextSinceId = tweets.list[0].id;
|
|
157
|
-
}
|
|
153
|
+
// Deserializing response
|
|
154
|
+
const data = this.extract<CursoredData<User>>(response, resource)!;
|
|
158
155
|
|
|
159
|
-
|
|
160
|
-
if (tweets.list.length > 0 && tweets.next) {
|
|
161
|
-
cursor = tweets.next.value;
|
|
162
|
-
}
|
|
163
|
-
// Else, start the next iteration from this batch's most recent tweet
|
|
164
|
-
else {
|
|
165
|
-
sinceId = nextSinceId;
|
|
166
|
-
cursor = undefined;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
156
|
+
return data;
|
|
169
157
|
}
|
|
170
158
|
|
|
171
159
|
/**
|
|
172
|
-
* Get the tweets from
|
|
160
|
+
* Get the list of tweets from a tweet list.
|
|
173
161
|
*
|
|
174
|
-
* @param
|
|
162
|
+
* @param id - The id of target list.
|
|
175
163
|
* @param count - The number of tweets to fetch, must be \<= 100.
|
|
176
164
|
* @param cursor - The cursor to the batch of tweets to fetch.
|
|
177
|
-
*
|
|
165
|
+
*
|
|
166
|
+
* @returns The list tweets in the given list.
|
|
178
167
|
*
|
|
179
168
|
* @example
|
|
180
169
|
* ```
|
|
@@ -183,8 +172,8 @@ export class TweetService extends FetcherService {
|
|
|
183
172
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
184
173
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
185
174
|
*
|
|
186
|
-
* // Fetching the most recent 100 tweets of the Twitter list with id '
|
|
187
|
-
* rettiwt.tweet.list('
|
|
175
|
+
* // Fetching the most recent 100 tweets of the Twitter list with id '1234567890'
|
|
176
|
+
* rettiwt.tweet.list('1234567890')
|
|
188
177
|
* .then(res => {
|
|
189
178
|
* console.log(res);
|
|
190
179
|
* })
|
|
@@ -195,14 +184,19 @@ export class TweetService extends FetcherService {
|
|
|
195
184
|
*
|
|
196
185
|
* @remarks Due a bug in Twitter API, the count is ignored when no cursor is provided and defaults to 100.
|
|
197
186
|
*/
|
|
198
|
-
public async list(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
187
|
+
public async list(id: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
|
|
188
|
+
const resource = EResourceType.LIST_TWEETS;
|
|
189
|
+
|
|
190
|
+
// Fetching raw list tweets
|
|
191
|
+
const response = await this.request<IListTweetsResponse>(resource, {
|
|
192
|
+
id: id,
|
|
202
193
|
count: count,
|
|
203
194
|
cursor: cursor,
|
|
204
195
|
});
|
|
205
196
|
|
|
197
|
+
// Deserializing response
|
|
198
|
+
const data = this.extract<CursoredData<Tweet>>(response, resource)!;
|
|
199
|
+
|
|
206
200
|
// Sorting the tweets by date, from recent to oldest
|
|
207
201
|
data.list.sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
|
|
208
202
|
|
|
@@ -210,22 +204,22 @@ export class TweetService extends FetcherService {
|
|
|
210
204
|
}
|
|
211
205
|
|
|
212
206
|
/**
|
|
213
|
-
*
|
|
207
|
+
* Post a tweet.
|
|
214
208
|
*
|
|
215
|
-
* @param
|
|
216
|
-
*
|
|
217
|
-
* @
|
|
218
|
-
* @returns The list of users who liked the given tweet.
|
|
209
|
+
* @param options - The options describing the tweet to be posted. Check {@link TweetArgs} for available options.
|
|
210
|
+
*
|
|
211
|
+
* @returns Whether posting was successful or not.
|
|
219
212
|
*
|
|
220
213
|
* @example
|
|
214
|
+
* Posting a simple text
|
|
221
215
|
* ```
|
|
222
216
|
* import { Rettiwt } from 'rettiwt-api';
|
|
223
217
|
*
|
|
224
218
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
225
219
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
226
220
|
*
|
|
227
|
-
* //
|
|
228
|
-
* rettiwt.tweet.
|
|
221
|
+
* // Posting a tweet to twitter
|
|
222
|
+
* rettiwt.tweet.post({ text: 'Hello World!' })
|
|
229
223
|
* .then(res => {
|
|
230
224
|
* console.log(res);
|
|
231
225
|
* })
|
|
@@ -234,15 +228,104 @@ export class TweetService extends FetcherService {
|
|
|
234
228
|
* });
|
|
235
229
|
* ```
|
|
236
230
|
*
|
|
237
|
-
* @
|
|
231
|
+
* @example
|
|
232
|
+
* Posting a tweet with an image that has been already uploaded
|
|
233
|
+
* ```
|
|
234
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
235
|
+
*
|
|
236
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
237
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
238
|
+
*
|
|
239
|
+
* // Posting a tweet, containing an image called 'mountains.jpg', to twitter
|
|
240
|
+
* rettiwt.tweet.post({ text: 'What a nice view!', media: [{ id: '1234567890' }] })
|
|
241
|
+
* .then(res => {
|
|
242
|
+
* console.log(res);
|
|
243
|
+
* })
|
|
244
|
+
* .catch(err => {
|
|
245
|
+
* console.log(err);
|
|
246
|
+
* });
|
|
247
|
+
* ```
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* Posting a reply to a tweet
|
|
251
|
+
* ```
|
|
252
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
253
|
+
*
|
|
254
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
255
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
256
|
+
*
|
|
257
|
+
* // Posting a simple text reply, to a tweet with id "1234567890"
|
|
258
|
+
* rettiwt.tweet.post({ text: 'Hello!', replyTo: "1234567890" })
|
|
259
|
+
* .then(res => {
|
|
260
|
+
* console.log(res);
|
|
261
|
+
* })
|
|
262
|
+
* .catch(err => {
|
|
263
|
+
* console.log(err);
|
|
264
|
+
* });
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* * @example
|
|
268
|
+
* Posting a tweet that quotes another tweet
|
|
269
|
+
* ```
|
|
270
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
271
|
+
*
|
|
272
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
273
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
274
|
+
*
|
|
275
|
+
* // Posting a simple text tweet, quoting a tweet with id "1234567890"
|
|
276
|
+
* rettiwt.tweet.post({ text: 'Hello!', quote: "1234567890" })
|
|
277
|
+
* .then(res => {
|
|
278
|
+
* console.log(res);
|
|
279
|
+
* })
|
|
280
|
+
* .catch(err => {
|
|
281
|
+
* console.log(err);
|
|
282
|
+
* });
|
|
283
|
+
* ```
|
|
238
284
|
*/
|
|
239
|
-
public async
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
285
|
+
public async post(options: TweetArgs): Promise<string | undefined> {
|
|
286
|
+
const resource = EResourceType.TWEET_POST;
|
|
287
|
+
|
|
288
|
+
// Posting the tweet
|
|
289
|
+
const response = await this.request<ITweetPostResponse>(resource, { tweet: options });
|
|
290
|
+
|
|
291
|
+
// Deserializing response
|
|
292
|
+
const data = this.extract<string>(response, resource);
|
|
293
|
+
|
|
294
|
+
return data;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Retweet a tweet.
|
|
299
|
+
*
|
|
300
|
+
* @param id - The id of the target tweet.
|
|
301
|
+
*
|
|
302
|
+
* @returns Whether retweeting was successful or not.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```
|
|
306
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
307
|
+
*
|
|
308
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
309
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
310
|
+
*
|
|
311
|
+
* // Retweeting the Tweet with id '1234567890'
|
|
312
|
+
* rettiwt.tweet.retweet('1234567890')
|
|
313
|
+
* .then(res => {
|
|
314
|
+
* console.log(res);
|
|
315
|
+
* })
|
|
316
|
+
* .catch(err => {
|
|
317
|
+
* console.log(err);
|
|
318
|
+
* });
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
public async retweet(id: string): Promise<boolean> {
|
|
322
|
+
const resource = EResourceType.TWEET_RETWEET;
|
|
323
|
+
|
|
324
|
+
// Retweeting the tweet
|
|
325
|
+
const response = await this.request<ITweetRetweetResponse>(resource, { id: id });
|
|
326
|
+
|
|
327
|
+
// Deserializing response
|
|
328
|
+
const data = this.extract<boolean>(response, resource) ?? false;
|
|
246
329
|
|
|
247
330
|
return data;
|
|
248
331
|
}
|
|
@@ -250,9 +333,10 @@ export class TweetService extends FetcherService {
|
|
|
250
333
|
/**
|
|
251
334
|
* Get the list of users who retweeted a tweet.
|
|
252
335
|
*
|
|
253
|
-
* @param
|
|
336
|
+
* @param id - The id of the target tweet.
|
|
254
337
|
* @param count - The number of retweeters to fetch, must be \<= 100.
|
|
255
338
|
* @param cursor - The cursor to the batch of retweeters to fetch.
|
|
339
|
+
*
|
|
256
340
|
* @returns The list of users who retweeted the given tweet.
|
|
257
341
|
*
|
|
258
342
|
* @example
|
|
@@ -262,8 +346,8 @@ export class TweetService extends FetcherService {
|
|
|
262
346
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
263
347
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
264
348
|
*
|
|
265
|
-
* // Fetching the most recent 100 retweeters of the Tweet with id '
|
|
266
|
-
* rettiwt.tweet.retweeters('
|
|
349
|
+
* // Fetching the most recent 100 retweeters of the Tweet with id '1234567890'
|
|
350
|
+
* rettiwt.tweet.retweeters('1234567890')
|
|
267
351
|
* .then(res => {
|
|
268
352
|
* console.log(res);
|
|
269
353
|
* })
|
|
@@ -271,37 +355,41 @@ export class TweetService extends FetcherService {
|
|
|
271
355
|
* console.log(err);
|
|
272
356
|
* });
|
|
273
357
|
* ```
|
|
274
|
-
*
|
|
275
|
-
* @public
|
|
276
358
|
*/
|
|
277
|
-
public async retweeters(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
359
|
+
public async retweeters(id: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
|
|
360
|
+
const resource = EResourceType.TWEET_RETWEETERS;
|
|
361
|
+
|
|
362
|
+
// Fetching raw list of retweeters
|
|
363
|
+
const response = await this.request<ITweetRetweetersResponse>(resource, {
|
|
364
|
+
id: id,
|
|
281
365
|
count: count,
|
|
282
366
|
cursor: cursor,
|
|
283
367
|
});
|
|
284
368
|
|
|
369
|
+
// Deserializing response
|
|
370
|
+
const data = this.extract<CursoredData<User>>(response, resource)!;
|
|
371
|
+
|
|
285
372
|
return data;
|
|
286
373
|
}
|
|
287
374
|
|
|
288
375
|
/**
|
|
289
|
-
*
|
|
376
|
+
* Search for tweets using a filter.
|
|
290
377
|
*
|
|
291
|
-
* @param
|
|
292
|
-
* @param
|
|
293
|
-
* @param
|
|
294
|
-
* @returns Whether posting was successful or not.
|
|
378
|
+
* @param filter - The filter to be used for searching the tweets.
|
|
379
|
+
* @param count - The number of tweets to fetch, must be \<= 20.
|
|
380
|
+
* @param cursor - The cursor to the batch of tweets to fetch.
|
|
295
381
|
*
|
|
296
|
-
* @
|
|
382
|
+
* @returns The list of tweets that match the given filter.
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
297
385
|
* ```
|
|
298
386
|
* import { Rettiwt } from 'rettiwt-api';
|
|
299
387
|
*
|
|
300
388
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
301
389
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
302
390
|
*
|
|
303
|
-
* //
|
|
304
|
-
* rettiwt.tweet.
|
|
391
|
+
* // Fetching the most recent 5 tweets from user 'user1'
|
|
392
|
+
* rettiwt.tweet.search({ fromUsers: ['user1'] }, 5)
|
|
305
393
|
* .then(res => {
|
|
306
394
|
* console.log(res);
|
|
307
395
|
* })
|
|
@@ -310,15 +398,107 @@ export class TweetService extends FetcherService {
|
|
|
310
398
|
* });
|
|
311
399
|
* ```
|
|
312
400
|
*
|
|
313
|
-
* @
|
|
401
|
+
* @remarks For details about available filters, refer to {@link TweetFilter}
|
|
402
|
+
*/
|
|
403
|
+
public async search(filter: TweetFilter, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
|
|
404
|
+
const resource = EResourceType.TWEET_SEARCH;
|
|
405
|
+
|
|
406
|
+
// Fetching raw list of filtered tweets
|
|
407
|
+
const response = await this.request<ITweetSearchResponse>(resource, {
|
|
408
|
+
filter: filter,
|
|
409
|
+
count: count,
|
|
410
|
+
cursor: cursor,
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// Deserializing response
|
|
414
|
+
const data = this.extract<CursoredData<Tweet>>(response, resource)!;
|
|
415
|
+
|
|
416
|
+
// Sorting the tweets by date, from recent to oldest
|
|
417
|
+
data.list.sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
|
|
418
|
+
|
|
419
|
+
return data;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Stream tweets in pseudo real-time using a filter.
|
|
424
|
+
*
|
|
425
|
+
* @param filter - The filter to be used for searching the tweets.
|
|
426
|
+
* @param pollingInterval - The interval in milliseconds to poll for new tweets. Default interval is 60000 ms.
|
|
427
|
+
*
|
|
428
|
+
* @returns An async generator that yields matching tweets as they are found.
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
314
431
|
* ```
|
|
315
432
|
* import { Rettiwt } from 'rettiwt-api';
|
|
316
433
|
*
|
|
317
434
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
318
435
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
319
436
|
*
|
|
320
|
-
* //
|
|
321
|
-
*
|
|
437
|
+
* // Streaming all upcoming tweets from user 'user1'
|
|
438
|
+
* (async () => {
|
|
439
|
+
* try {
|
|
440
|
+
* for await (const tweet of rettiwt.tweet.stream({ fromUsers: ['user1'] }, 1000)) {
|
|
441
|
+
* console.log(tweet.fullText);
|
|
442
|
+
* }
|
|
443
|
+
* }
|
|
444
|
+
* catch (err) {
|
|
445
|
+
* console.log(err);
|
|
446
|
+
* }
|
|
447
|
+
* })();
|
|
448
|
+
* ```
|
|
449
|
+
*/
|
|
450
|
+
public async *stream(filter: TweetFilter, pollingInterval: number = 60000): AsyncGenerator<Tweet> {
|
|
451
|
+
const startDate = new Date();
|
|
452
|
+
|
|
453
|
+
let cursor: string | undefined = undefined;
|
|
454
|
+
let sinceId: string | undefined = undefined;
|
|
455
|
+
let nextSinceId: string | undefined = undefined;
|
|
456
|
+
|
|
457
|
+
while (true) {
|
|
458
|
+
// Pause execution for the specified polling interval before proceeding to the next iteration
|
|
459
|
+
await new Promise((resolve) => setTimeout(resolve, pollingInterval));
|
|
460
|
+
|
|
461
|
+
// Search for tweets
|
|
462
|
+
const tweets = await this.search({ ...filter, startDate: startDate, sinceId: sinceId }, undefined, cursor);
|
|
463
|
+
|
|
464
|
+
// Yield the matching tweets
|
|
465
|
+
for (const tweet of tweets.list) {
|
|
466
|
+
yield tweet;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Store the most recent tweet ID from this batch
|
|
470
|
+
if (tweets.list.length > 0 && cursor === undefined) {
|
|
471
|
+
nextSinceId = tweets.list[0].id;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// If there are more tweets to fetch, adjust the cursor value
|
|
475
|
+
if (tweets.list.length > 0 && tweets.next) {
|
|
476
|
+
cursor = tweets.next.value;
|
|
477
|
+
}
|
|
478
|
+
// Else, start the next iteration from this batch's most recent tweet
|
|
479
|
+
else {
|
|
480
|
+
sinceId = nextSinceId;
|
|
481
|
+
cursor = undefined;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Unlike a tweet.
|
|
488
|
+
*
|
|
489
|
+
* @param id - The id of the target tweet.
|
|
490
|
+
*
|
|
491
|
+
* @returns Whether unliking was successful or not.
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```
|
|
495
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
496
|
+
*
|
|
497
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
498
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
499
|
+
*
|
|
500
|
+
* // Unliking the Tweet with id '1234567890'
|
|
501
|
+
* rettiwt.tweet.unlike('1234567890')
|
|
322
502
|
* .then(res => {
|
|
323
503
|
* console.log(res);
|
|
324
504
|
* })
|
|
@@ -326,16 +506,35 @@ export class TweetService extends FetcherService {
|
|
|
326
506
|
* console.log(err);
|
|
327
507
|
* });
|
|
328
508
|
* ```
|
|
509
|
+
*/
|
|
510
|
+
public async unlike(id: string): Promise<boolean> {
|
|
511
|
+
const resource = EResourceType.TWEET_UNLIKE;
|
|
512
|
+
|
|
513
|
+
// Unliking the tweet
|
|
514
|
+
const response = await this.request<ITweetUnlikeResponse>(resource, { id: id });
|
|
515
|
+
|
|
516
|
+
// Deserializing the response
|
|
517
|
+
const data = this.extract<boolean>(response, resource) ?? false;
|
|
518
|
+
|
|
519
|
+
return data;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Unpost a tweet.
|
|
329
524
|
*
|
|
330
|
-
* @
|
|
525
|
+
* @param id - The id of the target tweet.
|
|
526
|
+
*
|
|
527
|
+
* @returns Whether unposting was successful or not.
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
331
530
|
* ```
|
|
332
531
|
* import { Rettiwt } from 'rettiwt-api';
|
|
333
532
|
*
|
|
334
533
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
335
534
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
336
535
|
*
|
|
337
|
-
* //
|
|
338
|
-
* rettiwt.tweet.
|
|
536
|
+
* // Unposting the Tweet with id '1234567890'
|
|
537
|
+
* rettiwt.tweet.unpost('1234567890')
|
|
339
538
|
* .then(res => {
|
|
340
539
|
* console.log(res);
|
|
341
540
|
* })
|
|
@@ -343,40 +542,25 @@ export class TweetService extends FetcherService {
|
|
|
343
542
|
* console.log(err);
|
|
344
543
|
* });
|
|
345
544
|
* ```
|
|
346
|
-
*
|
|
347
|
-
* @public
|
|
348
545
|
*/
|
|
349
|
-
public async
|
|
350
|
-
|
|
351
|
-
const tweet: TweetArgs = new TweetArgs({ text: text, media: media });
|
|
352
|
-
|
|
353
|
-
/** Stores the list of media that has been uploaded */
|
|
354
|
-
const uploadedMedia: MediaArgs[] = [];
|
|
546
|
+
public async unpost(id: string): Promise<boolean> {
|
|
547
|
+
const resource = EResourceType.TWEET_UNPOST;
|
|
355
548
|
|
|
356
|
-
//
|
|
357
|
-
|
|
358
|
-
for (const item of tweet.media) {
|
|
359
|
-
// Uploading the media item and getting it's allocated id
|
|
360
|
-
const id: string = await this.upload(item.path);
|
|
361
|
-
|
|
362
|
-
// Storing the uploaded media item
|
|
363
|
-
uploadedMedia.push(new MediaArgs({ id: id, tags: item.tags }));
|
|
364
|
-
}
|
|
365
|
-
}
|
|
549
|
+
// Unposting the tweet
|
|
550
|
+
const response = await this.request<ITweetUnpostResponse>(resource, { id: id });
|
|
366
551
|
|
|
367
|
-
//
|
|
368
|
-
const data =
|
|
369
|
-
tweet: { text: text, media: uploadedMedia, replyTo: replyTo },
|
|
370
|
-
});
|
|
552
|
+
// Deserializing the response
|
|
553
|
+
const data = this.extract<boolean>(response, resource) ?? false;
|
|
371
554
|
|
|
372
555
|
return data;
|
|
373
556
|
}
|
|
374
557
|
|
|
375
558
|
/**
|
|
376
|
-
*
|
|
559
|
+
* Unretweet a tweet.
|
|
560
|
+
*
|
|
561
|
+
* @param id - The id of the target tweet.
|
|
377
562
|
*
|
|
378
|
-
* @
|
|
379
|
-
* @returns Whether favoriting was successful or not.
|
|
563
|
+
* @returns Whether unretweeting was successful or not.
|
|
380
564
|
*
|
|
381
565
|
* @example
|
|
382
566
|
* ```
|
|
@@ -385,8 +569,8 @@ export class TweetService extends FetcherService {
|
|
|
385
569
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
386
570
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
387
571
|
*
|
|
388
|
-
* //
|
|
389
|
-
* rettiwt.tweet.
|
|
572
|
+
* // Unretweeting the Tweet with id '1234567890'
|
|
573
|
+
* rettiwt.tweet.unretweet('1234567890')
|
|
390
574
|
* .then(res => {
|
|
391
575
|
* console.log(res);
|
|
392
576
|
* })
|
|
@@ -394,21 +578,25 @@ export class TweetService extends FetcherService {
|
|
|
394
578
|
* console.log(err);
|
|
395
579
|
* });
|
|
396
580
|
* ```
|
|
397
|
-
*
|
|
398
|
-
* @public
|
|
399
581
|
*/
|
|
400
|
-
public async
|
|
401
|
-
|
|
402
|
-
|
|
582
|
+
public async unretweet(id: string): Promise<boolean> {
|
|
583
|
+
const resource = EResourceType.TWEET_UNRETWEET;
|
|
584
|
+
|
|
585
|
+
// Unretweeting the tweet
|
|
586
|
+
const response = await this.request<ITweetUnretweetResponse>(resource, { id: id });
|
|
587
|
+
|
|
588
|
+
// Deserializing the response
|
|
589
|
+
const data = this.extract<boolean>(response, resource) ?? false;
|
|
403
590
|
|
|
404
591
|
return data;
|
|
405
592
|
}
|
|
406
593
|
|
|
407
594
|
/**
|
|
408
|
-
*
|
|
595
|
+
* Upload a media file to Twitter.
|
|
409
596
|
*
|
|
410
|
-
* @param
|
|
411
|
-
*
|
|
597
|
+
* @param media - The path or ArrayBuffer to the media file to upload.
|
|
598
|
+
*
|
|
599
|
+
* @returns The id of the uploaded media.
|
|
412
600
|
*
|
|
413
601
|
* @example
|
|
414
602
|
* ```
|
|
@@ -417,8 +605,8 @@ export class TweetService extends FetcherService {
|
|
|
417
605
|
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
418
606
|
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
419
607
|
*
|
|
420
|
-
* //
|
|
421
|
-
* rettiwt.tweet.
|
|
608
|
+
* // Uploading a file called mountains.jpg
|
|
609
|
+
* rettiwt.tweet.upload('mountains.jpg')
|
|
422
610
|
* .then(res => {
|
|
423
611
|
* console.log(res);
|
|
424
612
|
* })
|
|
@@ -427,12 +615,26 @@ export class TweetService extends FetcherService {
|
|
|
427
615
|
* });
|
|
428
616
|
* ```
|
|
429
617
|
*
|
|
430
|
-
* @
|
|
618
|
+
* @remarks
|
|
619
|
+
* - The uploaded media exists for 24 hrs within which it can be included in a tweet to be posted.
|
|
620
|
+
* If not posted in a tweet within this period, the uploaded media is removed.
|
|
621
|
+
* - Instead of a path to the media, an ArrayBuffer containing the media can also be uploaded.
|
|
431
622
|
*/
|
|
432
|
-
public async
|
|
433
|
-
//
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
623
|
+
public async upload(media: string | ArrayBuffer): Promise<string> {
|
|
624
|
+
// INITIALIZE
|
|
625
|
+
const size = typeof media == 'string' ? statSync(media).size : media.byteLength;
|
|
626
|
+
const id: string = (
|
|
627
|
+
await this.request<IInitializeMediaUploadResponse>(EResourceType.MEDIA_UPLOAD_INITIALIZE, {
|
|
628
|
+
upload: { size: size },
|
|
629
|
+
})
|
|
630
|
+
).media_id_string;
|
|
631
|
+
|
|
632
|
+
// APPEND
|
|
633
|
+
await this.request<unknown>(EResourceType.MEDIA_UPLOAD_APPEND, { upload: { id: id, media: media } });
|
|
634
|
+
|
|
635
|
+
// FINALIZE
|
|
636
|
+
await this.request<unknown>(EResourceType.MEDIA_UPLOAD_FINALIZE, { upload: { id: id } });
|
|
637
|
+
|
|
638
|
+
return id;
|
|
437
639
|
}
|
|
438
640
|
}
|