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