rettiwt-api 5.0.0-alpha.0 → 5.0.0-alpha.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 +2 -3
- package/.github/workflows/documentation.yml +1 -1
- package/.github/workflows/publish-alpha.yml +1 -1
- package/.github/workflows/publish.yml +1 -1
- package/.prettierignore +1 -1
- package/.tool-versions +1 -1
- package/README.md +100 -100
- package/dist/Rettiwt.d.ts +1 -1
- package/dist/Rettiwt.js +15 -8
- package/dist/Rettiwt.js.map +1 -1
- package/dist/cli.js +8 -11
- package/dist/cli.js.map +1 -1
- package/dist/collections/Extractors.d.ts +1 -0
- package/dist/collections/Extractors.js +38 -69
- package/dist/collections/Extractors.js.map +1 -1
- package/dist/collections/Groups.js +2 -1
- package/dist/collections/Groups.js.map +1 -1
- package/dist/collections/Requests.d.ts +3 -3
- package/dist/collections/Requests.js +36 -35
- package/dist/collections/Requests.js.map +1 -1
- package/dist/commands/List.js +21 -78
- package/dist/commands/List.js.map +1 -1
- package/dist/commands/Tweet.js +185 -370
- package/dist/commands/Tweet.js.map +1 -1
- package/dist/commands/User.js +129 -306
- package/dist/commands/User.js.map +1 -1
- package/dist/enums/Authentication.d.ts +18 -0
- package/dist/enums/Authentication.js +24 -0
- package/dist/enums/Authentication.js.map +1 -0
- package/dist/enums/Data.d.ts +12 -0
- package/dist/enums/Data.js +14 -1
- package/dist/enums/Data.js.map +1 -1
- package/dist/enums/Resource.d.ts +1 -0
- package/dist/enums/Resource.js +1 -0
- package/dist/enums/Resource.js.map +1 -1
- package/dist/helper/CliUtils.js +1 -2
- package/dist/helper/CliUtils.js.map +1 -1
- package/dist/helper/JsonUtils.js +6 -11
- package/dist/helper/JsonUtils.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/models/args/FetchArgs.d.ts +4 -133
- package/dist/models/args/FetchArgs.js +12 -416
- package/dist/models/args/FetchArgs.js.map +1 -1
- package/dist/models/args/PostArgs.d.ts +16 -101
- package/dist/models/args/PostArgs.js +26 -258
- package/dist/models/args/PostArgs.js.map +1 -1
- package/dist/models/auth/AccountCredential.d.ts +13 -0
- package/dist/models/auth/AccountCredential.js +21 -0
- package/dist/models/auth/AccountCredential.js.map +1 -0
- package/dist/models/auth/AuthCookie.d.ts +19 -0
- package/dist/models/auth/AuthCookie.js +53 -0
- package/dist/models/auth/AuthCookie.js.map +1 -0
- package/dist/models/auth/AuthCredential.d.ts +28 -0
- package/dist/models/auth/AuthCredential.js +76 -0
- package/dist/models/auth/AuthCredential.js.map +1 -0
- package/dist/models/data/CursoredData.d.ts +3 -4
- package/dist/models/data/CursoredData.js +19 -19
- package/dist/models/data/CursoredData.js.map +1 -1
- package/dist/models/data/List.d.ts +2 -8
- package/dist/models/data/List.js +10 -4
- package/dist/models/data/List.js.map +1 -1
- package/dist/models/data/Notification.d.ts +5 -21
- package/dist/models/data/Notification.js +24 -33
- package/dist/models/data/Notification.js.map +1 -1
- package/dist/models/data/Tweet.d.ts +6 -23
- package/dist/models/data/Tweet.js +93 -97
- package/dist/models/data/Tweet.js.map +1 -1
- package/dist/models/data/User.d.ts +2 -15
- package/dist/models/data/User.js +33 -23
- package/dist/models/data/User.js.map +1 -1
- package/dist/models/errors/ApiError.js +8 -24
- package/dist/models/errors/ApiError.js.map +1 -1
- package/dist/models/errors/HttpError.js +8 -24
- package/dist/models/errors/HttpError.js.map +1 -1
- package/dist/models/errors/RettiwtError.js +5 -23
- package/dist/models/errors/RettiwtError.js.map +1 -1
- package/dist/models/errors/TimeoutError.js +5 -22
- package/dist/models/errors/TimeoutError.js.map +1 -1
- package/dist/services/{public → internal}/AuthService.d.ts +5 -34
- package/dist/services/internal/AuthService.js +109 -0
- package/dist/services/internal/AuthService.js.map +1 -0
- package/dist/services/internal/ErrorService.js +38 -40
- package/dist/services/internal/ErrorService.js.map +1 -1
- package/dist/services/internal/LogService.d.ts +0 -6
- package/dist/services/internal/LogService.js +12 -32
- package/dist/services/internal/LogService.js.map +1 -1
- package/dist/services/public/FetcherService.d.ts +5 -3
- package/dist/services/public/FetcherService.js +96 -141
- package/dist/services/public/FetcherService.js.map +1 -1
- package/dist/services/public/ListService.js +31 -100
- package/dist/services/public/ListService.js.map +1 -1
- package/dist/services/public/TweetService.d.ts +29 -4
- package/dist/services/public/TweetService.js +208 -386
- package/dist/services/public/TweetService.js.map +1 -1
- package/dist/services/public/UserService.js +186 -385
- package/dist/services/public/UserService.js.map +1 -1
- package/dist/types/RettiwtConfig.d.ts +8 -0
- package/dist/types/args/FetchArgs.d.ts +59 -0
- package/dist/types/args/FetchArgs.js +3 -0
- package/dist/types/args/FetchArgs.js.map +1 -0
- package/dist/types/args/PostArgs.d.ts +56 -0
- package/dist/types/args/PostArgs.js +3 -0
- package/dist/types/args/PostArgs.js.map +1 -0
- package/dist/types/auth/AccountCredential.d.ts +11 -0
- package/dist/types/auth/AccountCredential.js +3 -0
- package/dist/types/auth/AccountCredential.js.map +1 -0
- package/dist/types/auth/AuthCookie.d.ts +13 -0
- package/dist/types/auth/AuthCookie.js +3 -0
- package/dist/types/auth/AuthCookie.js.map +1 -0
- package/dist/types/auth/AuthCredential.d.ts +21 -0
- package/dist/types/auth/AuthCredential.js +3 -0
- package/dist/types/auth/AuthCredential.js.map +1 -0
- package/dist/types/data/CursoredData.d.ts +25 -0
- package/dist/types/data/CursoredData.js +3 -0
- package/dist/types/data/CursoredData.js.map +1 -0
- package/dist/types/data/List.d.ts +21 -0
- package/dist/types/data/List.js +3 -0
- package/dist/types/data/List.js.map +1 -0
- package/dist/types/data/Notification.d.ts +20 -0
- package/dist/types/data/Notification.js +3 -0
- package/dist/types/data/Notification.js.map +1 -0
- package/dist/types/data/Tweet.d.ts +71 -0
- package/dist/types/data/Tweet.js +3 -0
- package/dist/types/data/Tweet.js.map +1 -0
- package/dist/types/data/User.d.ts +35 -0
- package/dist/types/data/User.js +3 -0
- package/dist/types/data/User.js.map +1 -0
- package/eslint.config.mjs +17 -0
- package/package.json +22 -19
- package/src/Rettiwt.ts +1 -1
- package/src/cli.ts +0 -2
- package/src/collections/Extractors.ts +2 -0
- package/src/collections/Groups.ts +1 -0
- package/src/collections/Requests.ts +37 -36
- package/src/enums/Authentication.ts +19 -0
- package/src/enums/Data.ts +13 -0
- package/src/enums/Resource.ts +1 -0
- package/src/helper/JsonUtils.ts +1 -1
- package/src/index.ts +1 -2
- package/src/models/args/FetchArgs.ts +4 -470
- package/src/models/args/PostArgs.ts +20 -285
- package/src/models/auth/AccountCredential.ts +19 -0
- package/src/models/auth/AuthCookie.ts +56 -0
- package/src/models/auth/AuthCredential.ts +83 -0
- package/src/models/data/CursoredData.ts +12 -9
- package/src/models/data/List.ts +3 -14
- package/src/models/data/Notification.ts +6 -28
- package/src/models/data/Tweet.ts +28 -70
- package/src/models/data/User.ts +5 -31
- package/src/services/{public → internal}/AuthService.ts +28 -55
- package/src/services/internal/LogService.ts +4 -19
- package/src/services/public/FetcherService.ts +18 -8
- package/src/services/public/TweetService.ts +44 -4
- package/src/services/public/UserService.ts +2 -2
- package/src/types/RettiwtConfig.ts +7 -0
- package/src/types/args/FetchArgs.ts +64 -0
- package/src/types/args/PostArgs.ts +62 -0
- package/src/types/auth/AccountCredential.ts +13 -0
- package/src/types/auth/AuthCookie.ts +20 -0
- package/src/types/auth/AuthCredential.ts +26 -0
- package/src/types/data/CursoredData.ts +28 -0
- package/src/types/data/List.ts +27 -0
- package/src/types/data/Notification.ts +26 -0
- package/src/types/data/Tweet.ts +96 -0
- package/src/types/data/User.ts +48 -0
- package/tsconfig.json +7 -5
- package/.eslintignore +0 -3
- package/dist/commands/Auth.d.ts +0 -10
- package/dist/commands/Auth.js +0 -101
- package/dist/commands/Auth.js.map +0 -1
- package/dist/models/errors/DataValidationError.d.ts +0 -30
- package/dist/models/errors/DataValidationError.js +0 -34
- package/dist/models/errors/DataValidationError.js.map +0 -1
- package/dist/services/public/AuthService.js +0 -205
- package/dist/services/public/AuthService.js.map +0 -1
- package/src/commands/Auth.ts +0 -46
- package/src/models/errors/DataValidationError.ts +0 -44
package/src/models/data/Tweet.ts
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
ITweet as IRawTweet,
|
|
6
6
|
IEntities as IRawTweetEntities,
|
|
7
7
|
ITimelineTweet,
|
|
8
|
-
ITweet,
|
|
9
8
|
} from 'rettiwt-core';
|
|
10
9
|
|
|
11
10
|
import { ELogActions } from '../../enums/Logging';
|
|
@@ -13,6 +12,8 @@ import { findByFilter } from '../../helper/JsonUtils';
|
|
|
13
12
|
|
|
14
13
|
import { LogService } from '../../services/internal/LogService';
|
|
15
14
|
|
|
15
|
+
import { ITweet } from '../../types/data/Tweet';
|
|
16
|
+
|
|
16
17
|
import { User } from './User';
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -20,68 +21,39 @@ import { User } from './User';
|
|
|
20
21
|
*
|
|
21
22
|
* @public
|
|
22
23
|
*/
|
|
23
|
-
export class Tweet {
|
|
24
|
-
/** The number of bookmarks of a tweet. */
|
|
24
|
+
export class Tweet implements ITweet {
|
|
25
25
|
public bookmarkCount: number;
|
|
26
|
-
|
|
27
|
-
/** The date and time of creation of the tweet, in UTC string format. */
|
|
26
|
+
public conversationId: string;
|
|
28
27
|
public createdAt: string;
|
|
29
|
-
|
|
30
|
-
/** Additional tweet entities like urls, mentions, etc. */
|
|
31
28
|
public entities: TweetEntities;
|
|
32
|
-
|
|
33
|
-
/** The full text content of the tweet. */
|
|
34
29
|
public fullText: string;
|
|
35
|
-
|
|
36
|
-
/** The rest id of the tweet. */
|
|
37
30
|
public id: string;
|
|
38
|
-
|
|
39
|
-
/** The language in which the tweet is written. */
|
|
40
31
|
public lang: string;
|
|
41
|
-
|
|
42
|
-
/** The number of likes of the tweet. */
|
|
43
32
|
public likeCount: number;
|
|
44
|
-
|
|
45
|
-
/** The urls of the media contents of the tweet (if any). */
|
|
46
33
|
public media?: TweetMedia[];
|
|
47
|
-
|
|
48
|
-
/** The number of quotes of the tweet. */
|
|
49
34
|
public quoteCount: number;
|
|
50
|
-
|
|
51
|
-
/** The tweet which is quoted in the tweet. */
|
|
52
35
|
public quoted?: Tweet;
|
|
53
|
-
|
|
54
|
-
/** The number of replies to the tweet. */
|
|
55
36
|
public replyCount: number;
|
|
56
|
-
|
|
57
|
-
/** The rest id of the tweet to which the tweet is a reply. */
|
|
58
|
-
public replyTo?: Tweet;
|
|
59
|
-
|
|
60
|
-
/** The number of retweets of the tweet. */
|
|
37
|
+
public replyTo?: string;
|
|
61
38
|
public retweetCount: number;
|
|
62
|
-
|
|
63
|
-
/** The tweet which is retweeted in this tweet (if any). */
|
|
64
39
|
public retweetedTweet?: Tweet;
|
|
65
|
-
|
|
66
|
-
/** The details of the user who made the tweet. */
|
|
67
40
|
public tweetBy: User;
|
|
68
|
-
|
|
69
|
-
/** The number of views of a tweet. */
|
|
41
|
+
public url: string;
|
|
70
42
|
public viewCount: number;
|
|
71
43
|
|
|
72
44
|
/**
|
|
73
45
|
* @param tweet - The raw tweet details.
|
|
74
|
-
* @param response - The raw response
|
|
75
46
|
*/
|
|
76
|
-
public constructor(tweet: IRawTweet
|
|
47
|
+
public constructor(tweet: IRawTweet) {
|
|
77
48
|
this.id = tweet.rest_id;
|
|
49
|
+
this.conversationId = tweet.legacy.conversation_id_str;
|
|
78
50
|
this.createdAt = tweet.legacy.created_at;
|
|
79
51
|
this.tweetBy = new User(tweet.core.user_results.result);
|
|
80
52
|
this.entities = new TweetEntities(tweet.legacy.entities);
|
|
81
53
|
this.media = tweet.legacy.extended_entities?.media?.map((media) => new TweetMedia(media));
|
|
82
|
-
this.quoted = this.getQuotedTweet(tweet
|
|
54
|
+
this.quoted = this.getQuotedTweet(tweet);
|
|
83
55
|
this.fullText = tweet.note_tweet ? tweet.note_tweet.note_tweet_results.result.text : tweet.legacy.full_text;
|
|
84
|
-
this.replyTo =
|
|
56
|
+
this.replyTo = tweet.legacy.in_reply_to_status_id_str;
|
|
85
57
|
this.lang = tweet.legacy.lang;
|
|
86
58
|
this.quoteCount = tweet.legacy.quote_count;
|
|
87
59
|
this.replyCount = tweet.legacy.reply_count;
|
|
@@ -89,42 +61,29 @@ export class Tweet {
|
|
|
89
61
|
this.likeCount = tweet.legacy.favorite_count;
|
|
90
62
|
this.viewCount = tweet.views.count ? parseInt(tweet.views.count) : 0;
|
|
91
63
|
this.bookmarkCount = tweet.legacy.bookmark_count;
|
|
92
|
-
this.retweetedTweet = this.getRetweetedTweet(tweet
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
private getParentTweet(tweet: IRawTweet, response: NonNullable<unknown>): Tweet | undefined {
|
|
96
|
-
// Getting parent tweet ID, if any
|
|
97
|
-
const parentTweetId: string = tweet.legacy?.in_reply_to_status_id_str ?? '';
|
|
98
|
-
|
|
99
|
-
// If no parent tweet
|
|
100
|
-
if (parentTweetId.length == 0) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Getting the details of parent tweet
|
|
105
|
-
return Tweet.single(response, parentTweetId);
|
|
64
|
+
this.retweetedTweet = this.getRetweetedTweet(tweet);
|
|
65
|
+
this.url = `https://x.com/${this.tweetBy.userName}/status/${this.id}`;
|
|
106
66
|
}
|
|
107
67
|
|
|
108
68
|
/**
|
|
109
69
|
* Extract and deserialize the original quoted tweet from the given raw tweet.
|
|
110
70
|
*
|
|
111
71
|
* @param tweet - The raw tweet.
|
|
112
|
-
* @param response - The raw response
|
|
113
72
|
*
|
|
114
73
|
* @returns - The deserialized original quoted tweet.
|
|
115
74
|
*/
|
|
116
|
-
private getQuotedTweet(tweet: IRawTweet
|
|
75
|
+
private getQuotedTweet(tweet: IRawTweet): Tweet | undefined {
|
|
117
76
|
// If tweet with limited visibility
|
|
118
77
|
if (
|
|
119
78
|
tweet.quoted_status_result &&
|
|
120
79
|
tweet.quoted_status_result?.result?.__typename == 'TweetWithVisibilityResults' &&
|
|
121
80
|
(tweet.quoted_status_result.result as ILimitedVisibilityTweet)?.tweet?.legacy
|
|
122
81
|
) {
|
|
123
|
-
return new Tweet((tweet.quoted_status_result.result as ILimitedVisibilityTweet).tweet
|
|
82
|
+
return new Tweet((tweet.quoted_status_result.result as ILimitedVisibilityTweet).tweet);
|
|
124
83
|
}
|
|
125
84
|
// If normal tweet
|
|
126
|
-
else if ((tweet.quoted_status_result?.result as
|
|
127
|
-
return new Tweet(tweet.quoted_status_result.result as
|
|
85
|
+
else if ((tweet.quoted_status_result?.result as IRawTweet)?.rest_id) {
|
|
86
|
+
return new Tweet(tweet.quoted_status_result.result as IRawTweet);
|
|
128
87
|
}
|
|
129
88
|
// Else, skip
|
|
130
89
|
else {
|
|
@@ -136,22 +95,21 @@ export class Tweet {
|
|
|
136
95
|
* Extract and deserialize the original retweeted tweet from the given raw tweet.
|
|
137
96
|
*
|
|
138
97
|
* @param tweet - The raw tweet.
|
|
139
|
-
* @param response - The raw response
|
|
140
98
|
*
|
|
141
99
|
* @returns - The deserialized original retweeted tweet.
|
|
142
100
|
*/
|
|
143
|
-
private getRetweetedTweet(tweet: IRawTweet
|
|
101
|
+
private getRetweetedTweet(tweet: IRawTweet): Tweet | undefined {
|
|
144
102
|
// If retweet with limited visibility
|
|
145
103
|
if (
|
|
146
104
|
tweet.legacy?.retweeted_status_result &&
|
|
147
105
|
tweet.legacy?.retweeted_status_result?.result?.__typename == 'TweetWithVisibilityResults' &&
|
|
148
106
|
(tweet.legacy?.retweeted_status_result?.result as ILimitedVisibilityTweet)?.tweet?.legacy
|
|
149
107
|
) {
|
|
150
|
-
return new Tweet((tweet.legacy.retweeted_status_result.result as ILimitedVisibilityTweet).tweet
|
|
108
|
+
return new Tweet((tweet.legacy.retweeted_status_result.result as ILimitedVisibilityTweet).tweet);
|
|
151
109
|
}
|
|
152
110
|
// If normal tweet
|
|
153
|
-
else if ((tweet.legacy?.retweeted_status_result?.result as
|
|
154
|
-
return new Tweet(tweet.legacy.retweeted_status_result.result as
|
|
111
|
+
else if ((tweet.legacy?.retweeted_status_result?.result as IRawTweet)?.rest_id) {
|
|
112
|
+
return new Tweet(tweet.legacy.retweeted_status_result.result as IRawTweet);
|
|
155
113
|
}
|
|
156
114
|
// Else, skip
|
|
157
115
|
else {
|
|
@@ -182,14 +140,14 @@ export class Tweet {
|
|
|
182
140
|
item.tweet_results?.result?.__typename == 'TweetWithVisibilityResults' &&
|
|
183
141
|
(item.tweet_results?.result as ILimitedVisibilityTweet)?.tweet?.legacy
|
|
184
142
|
) {
|
|
185
|
-
tweets.push(new Tweet((item.tweet_results.result as ILimitedVisibilityTweet).tweet
|
|
143
|
+
tweets.push(new Tweet((item.tweet_results.result as ILimitedVisibilityTweet).tweet));
|
|
186
144
|
}
|
|
187
145
|
// If normal tweet
|
|
188
|
-
else if ((item.tweet_results?.result as
|
|
146
|
+
else if ((item.tweet_results?.result as IRawTweet)?.legacy) {
|
|
189
147
|
// Logging
|
|
190
|
-
LogService.log(ELogActions.DESERIALIZE, { id: (item.tweet_results.result as
|
|
148
|
+
LogService.log(ELogActions.DESERIALIZE, { id: (item.tweet_results.result as IRawTweet).rest_id });
|
|
191
149
|
|
|
192
|
-
tweets.push(new Tweet(item.tweet_results.result as
|
|
150
|
+
tweets.push(new Tweet(item.tweet_results.result as IRawTweet));
|
|
193
151
|
}
|
|
194
152
|
// If invalid/unrecognized tweet
|
|
195
153
|
else {
|
|
@@ -218,7 +176,7 @@ export class Tweet {
|
|
|
218
176
|
const tweets: Tweet[] = [];
|
|
219
177
|
|
|
220
178
|
// Extracting the matching data
|
|
221
|
-
const extract = findByFilter<
|
|
179
|
+
const extract = findByFilter<IRawTweet>(response, 'rest_id', id);
|
|
222
180
|
|
|
223
181
|
// Deserializing valid data
|
|
224
182
|
for (const item of extract) {
|
|
@@ -226,7 +184,7 @@ export class Tweet {
|
|
|
226
184
|
// Logging
|
|
227
185
|
LogService.log(ELogActions.DESERIALIZE, { id: item.rest_id });
|
|
228
186
|
|
|
229
|
-
tweets.push(new Tweet(item
|
|
187
|
+
tweets.push(new Tweet(item));
|
|
230
188
|
} else {
|
|
231
189
|
// Logging
|
|
232
190
|
LogService.log(ELogActions.WARNING, {
|
|
@@ -295,7 +253,7 @@ export class TweetMedia {
|
|
|
295
253
|
public type: EMediaType;
|
|
296
254
|
|
|
297
255
|
/** The direct URL to the media. */
|
|
298
|
-
public url
|
|
256
|
+
public url = '';
|
|
299
257
|
|
|
300
258
|
/**
|
|
301
259
|
* @param media - The raw media details.
|
|
@@ -316,7 +274,7 @@ export class TweetMedia {
|
|
|
316
274
|
this.thumbnailUrl = media.media_url_https;
|
|
317
275
|
|
|
318
276
|
/** The highest bitrate of all variants. */
|
|
319
|
-
let highestRate
|
|
277
|
+
let highestRate = 0;
|
|
320
278
|
|
|
321
279
|
/**
|
|
322
280
|
* Selecting the URL of the video variant with the highest bitrate.
|
package/src/models/data/User.ts
CHANGED
|
@@ -1,55 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ITimelineUser as IRawTimelineUser, IUser as IRawUser } from 'rettiwt-core';
|
|
2
2
|
|
|
3
3
|
import { ELogActions } from '../../enums/Logging';
|
|
4
4
|
import { findByFilter } from '../../helper/JsonUtils';
|
|
5
5
|
import { LogService } from '../../services/internal/LogService';
|
|
6
|
+
import { IUser } from '../../types/data/User';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* The details of a single user.
|
|
9
10
|
*
|
|
10
11
|
* @public
|
|
11
12
|
*/
|
|
12
|
-
export class User {
|
|
13
|
-
/** The creation date of user's account. */
|
|
13
|
+
export class User implements IUser {
|
|
14
14
|
public createdAt: string;
|
|
15
|
-
|
|
16
|
-
/** The user's description. */
|
|
17
15
|
public description?: string;
|
|
18
|
-
|
|
19
|
-
/** The number of followers of the user. */
|
|
20
16
|
public followersCount: number;
|
|
21
|
-
|
|
22
|
-
/** The number of following of the user. */
|
|
23
17
|
public followingsCount: number;
|
|
24
|
-
|
|
25
|
-
/** The full name of the user. */
|
|
26
18
|
public fullName: string;
|
|
27
|
-
|
|
28
|
-
/** The rest id of the user. */
|
|
29
19
|
public id: string;
|
|
30
|
-
|
|
31
|
-
/** Whether the account is verified or not. */
|
|
32
20
|
public isVerified: boolean;
|
|
33
|
-
|
|
34
|
-
/** The number of tweets liked by the user. */
|
|
35
21
|
public likeCount: number;
|
|
36
|
-
|
|
37
|
-
/** The location of user as provided by user. */
|
|
38
22
|
public location?: string;
|
|
39
|
-
|
|
40
|
-
/** The rest id of the tweet pinned in the user's profile. */
|
|
41
23
|
public pinnedTweet?: string;
|
|
42
|
-
|
|
43
|
-
/** The url of the profile banner image. */
|
|
44
24
|
public profileBanner?: string;
|
|
45
|
-
|
|
46
|
-
/** The url of the profile image. */
|
|
47
25
|
public profileImage: string;
|
|
48
|
-
|
|
49
|
-
/** The number of tweets made by the user. */
|
|
50
26
|
public statusesCount: number;
|
|
51
|
-
|
|
52
|
-
/** The username/screenname of the user. */
|
|
53
27
|
public userName: string;
|
|
54
28
|
|
|
55
29
|
/**
|
|
@@ -85,7 +59,7 @@ export class User {
|
|
|
85
59
|
const users: User[] = [];
|
|
86
60
|
|
|
87
61
|
// Extracting the matching data
|
|
88
|
-
const extract = findByFilter<
|
|
62
|
+
const extract = findByFilter<IRawTimelineUser>(response, '__typename', 'TimelineUser');
|
|
89
63
|
|
|
90
64
|
// Deserializing valid data
|
|
91
65
|
for (const item of extract) {
|
|
@@ -119,7 +93,7 @@ export class User {
|
|
|
119
93
|
const users: User[] = [];
|
|
120
94
|
|
|
121
95
|
// Extracting the matching data
|
|
122
|
-
const extract = findByFilter<
|
|
96
|
+
const extract = findByFilter<IRawUser>(response, '__typename', 'User');
|
|
123
97
|
|
|
124
98
|
// Deserializing valid data
|
|
125
99
|
for (const item of extract) {
|
|
@@ -1,23 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import https, { Agent } from 'https';
|
|
2
|
+
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
2
6
|
|
|
3
7
|
import { EApiErrors } from '../../enums/Api';
|
|
8
|
+
import { AuthCredential } from '../../models/auth/AuthCredential';
|
|
4
9
|
import { IRettiwtConfig } from '../../types/RettiwtConfig';
|
|
5
10
|
|
|
6
|
-
import { FetcherService } from './FetcherService';
|
|
7
|
-
|
|
8
11
|
/**
|
|
9
12
|
* The services that handles authentication.
|
|
10
13
|
*
|
|
11
14
|
* @public
|
|
12
15
|
*/
|
|
13
|
-
export class AuthService
|
|
16
|
+
export class AuthService {
|
|
17
|
+
/** The HTTPS Agent to use for requests to Twitter API. */
|
|
18
|
+
private readonly _httpsAgent: Agent;
|
|
19
|
+
|
|
14
20
|
/**
|
|
15
21
|
* @param config - The config object for configuring the `Rettiwt` instance.
|
|
16
22
|
*
|
|
17
23
|
* @internal
|
|
18
24
|
*/
|
|
19
25
|
public constructor(config?: IRettiwtConfig) {
|
|
20
|
-
|
|
26
|
+
this._httpsAgent = config?.proxyUrl ? new HttpsProxyAgent(config.proxyUrl) : new https.Agent();
|
|
21
27
|
}
|
|
22
28
|
|
|
23
29
|
/**
|
|
@@ -94,57 +100,24 @@ export class AuthService extends FetcherService {
|
|
|
94
100
|
* });
|
|
95
101
|
* ```
|
|
96
102
|
*/
|
|
97
|
-
public async guest(): Promise<
|
|
98
|
-
//
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
return guestKey;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Login to twitter using account credentials.
|
|
106
|
-
*
|
|
107
|
-
* @param email - The email id associated with the Twitter account.
|
|
108
|
-
* @param userName - The username associated with the Twitter account.
|
|
109
|
-
* @param password - The password to the Twitter account.
|
|
110
|
-
*
|
|
111
|
-
* @returns The `API_KEY` for the Twitter account.
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```
|
|
115
|
-
* import { Rettiwt } from 'rettiwt-api';
|
|
116
|
-
*
|
|
117
|
-
* // Creating a new Rettiwt instance
|
|
118
|
-
* const rettiwt = new Rettiwt();
|
|
119
|
-
*
|
|
120
|
-
* // Logging in an getting the API_KEY
|
|
121
|
-
* rettiwt.auth.login("email@domain.com", "username", "password")
|
|
122
|
-
* .then(apiKey => {
|
|
123
|
-
* // Use the API_KEY
|
|
124
|
-
* ...
|
|
125
|
-
* })
|
|
126
|
-
* .catch(err => {
|
|
127
|
-
* console.log(err);
|
|
128
|
-
* });
|
|
129
|
-
* ```
|
|
130
|
-
*
|
|
131
|
-
* @remarks
|
|
132
|
-
* Interchanging `email` and `userName` works too.
|
|
133
|
-
*/
|
|
134
|
-
public async login(email: string, userName: string, password: string): Promise<string> {
|
|
135
|
-
// Logging in and getting the credentials
|
|
136
|
-
let apiKey: string =
|
|
137
|
-
((
|
|
138
|
-
await new Auth({ proxyUrl: this.authProxyUrl }).getUserCredential({
|
|
139
|
-
email: email,
|
|
140
|
-
userName: userName,
|
|
141
|
-
password: password,
|
|
142
|
-
})
|
|
143
|
-
).toHeader().cookie as string) ?? '';
|
|
103
|
+
public async guest(): Promise<AuthCredential> {
|
|
104
|
+
// Creating a new blank credential
|
|
105
|
+
const cred: AuthCredential = new AuthCredential();
|
|
144
106
|
|
|
145
|
-
//
|
|
146
|
-
|
|
107
|
+
// Getting the guest token
|
|
108
|
+
await axios
|
|
109
|
+
.get<{
|
|
110
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
111
|
+
guest_token: string;
|
|
112
|
+
/* eslint-enable @typescript-eslint/naming-convention */
|
|
113
|
+
}>('https://api.twitter.com/1.1/guest/activate.json', {
|
|
114
|
+
headers: cred.toHeader(),
|
|
115
|
+
httpsAgent: this._httpsAgent,
|
|
116
|
+
})
|
|
117
|
+
.then((res) => {
|
|
118
|
+
cred.guestToken = res.data.guest_token;
|
|
119
|
+
});
|
|
147
120
|
|
|
148
|
-
return
|
|
121
|
+
return cred;
|
|
149
122
|
}
|
|
150
123
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
|
|
3
1
|
import { ELogActions } from '../../enums/Logging';
|
|
4
2
|
|
|
5
3
|
/**
|
|
@@ -9,20 +7,7 @@ import { ELogActions } from '../../enums/Logging';
|
|
|
9
7
|
*/
|
|
10
8
|
export class LogService {
|
|
11
9
|
/** Whether logging is enabled or not. */
|
|
12
|
-
public static enabled
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param action - The action to be logged.
|
|
16
|
-
*
|
|
17
|
-
* @returns - The colored text representing the action.
|
|
18
|
-
*/
|
|
19
|
-
private static getColoredAction(action: ELogActions): string {
|
|
20
|
-
if (action == ELogActions.WARNING) {
|
|
21
|
-
return chalk.yellow(action);
|
|
22
|
-
} else {
|
|
23
|
-
return chalk.green(action);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
10
|
+
public static enabled = false;
|
|
26
11
|
|
|
27
12
|
/**
|
|
28
13
|
* Logs the given data.
|
|
@@ -35,12 +20,12 @@ export class LogService {
|
|
|
35
20
|
// Proceed to log only if logging is enabled
|
|
36
21
|
if (this.enabled) {
|
|
37
22
|
// Preparing the log message
|
|
38
|
-
const logPrefix
|
|
23
|
+
const logPrefix = 'Rettiwt-API';
|
|
39
24
|
const logTime: string = new Date().toISOString();
|
|
40
|
-
const logAction: string =
|
|
25
|
+
const logAction: string = action;
|
|
41
26
|
const logData: string = JSON.stringify(data);
|
|
42
27
|
|
|
43
|
-
const logMessage
|
|
28
|
+
const logMessage = `[${logPrefix}] [${logTime}] [${logAction}] ${logData}`;
|
|
44
29
|
|
|
45
30
|
// Logging
|
|
46
31
|
console.log(logMessage);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import https, { Agent } from 'https';
|
|
2
2
|
|
|
3
3
|
import axios from 'axios';
|
|
4
|
+
import { Cookie } from 'cookiejar';
|
|
4
5
|
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
5
|
-
import { Auth, AuthCredential } from 'rettiwt-auth';
|
|
6
6
|
|
|
7
7
|
import { allowGuestAuthentication, fetchResources, postResources } from '../../collections/Groups';
|
|
8
8
|
import { requests } from '../../collections/Requests';
|
|
@@ -11,14 +11,16 @@ import { ELogActions } from '../../enums/Logging';
|
|
|
11
11
|
import { EResourceType } from '../../enums/Resource';
|
|
12
12
|
import { FetchArgs } from '../../models/args/FetchArgs';
|
|
13
13
|
import { PostArgs } from '../../models/args/PostArgs';
|
|
14
|
+
import { AuthCredential } from '../../models/auth/AuthCredential';
|
|
15
|
+
import { IFetchArgs } from '../../types/args/FetchArgs';
|
|
16
|
+
import { IPostArgs } from '../../types/args/PostArgs';
|
|
14
17
|
import { IErrorHandler } from '../../types/ErrorHandler';
|
|
15
18
|
import { IRettiwtConfig } from '../../types/RettiwtConfig';
|
|
16
19
|
|
|
20
|
+
import { AuthService } from '../internal/AuthService';
|
|
17
21
|
import { ErrorService } from '../internal/ErrorService';
|
|
18
22
|
import { LogService } from '../internal/LogService';
|
|
19
23
|
|
|
20
|
-
import { AuthService } from './AuthService';
|
|
21
|
-
|
|
22
24
|
/**
|
|
23
25
|
* The base service that handles all HTTP requests.
|
|
24
26
|
*
|
|
@@ -28,6 +30,9 @@ export class FetcherService {
|
|
|
28
30
|
/** The api key to use for authenticating against Twitter API as user. */
|
|
29
31
|
private readonly _apiKey?: string;
|
|
30
32
|
|
|
33
|
+
/** Custom headers to use for all requests */
|
|
34
|
+
private readonly _customHeaders?: { [key: string]: string };
|
|
35
|
+
|
|
31
36
|
/** The service used to handle HTTP and API errors */
|
|
32
37
|
private readonly _errorHandler: IErrorHandler;
|
|
33
38
|
|
|
@@ -58,6 +63,7 @@ export class FetcherService {
|
|
|
58
63
|
this._proxyUrl = config?.proxyUrl;
|
|
59
64
|
this._timeout = config?.timeout ?? 0;
|
|
60
65
|
this._errorHandler = config?.errorHandler ?? new ErrorService();
|
|
66
|
+
this._customHeaders = config?.headers;
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
/**
|
|
@@ -87,7 +93,11 @@ export class FetcherService {
|
|
|
87
93
|
// Logging
|
|
88
94
|
LogService.log(ELogActions.GET, { target: 'USER_CREDENTIAL' });
|
|
89
95
|
|
|
90
|
-
return new AuthCredential(
|
|
96
|
+
return new AuthCredential(
|
|
97
|
+
AuthService.decodeCookie(this._apiKey)
|
|
98
|
+
.split(';')
|
|
99
|
+
.map((item) => new Cookie(item)),
|
|
100
|
+
);
|
|
91
101
|
} else if (this._guestKey) {
|
|
92
102
|
// Logging
|
|
93
103
|
LogService.log(ELogActions.GET, { target: 'GUEST_CREDENTIAL' });
|
|
@@ -97,7 +107,7 @@ export class FetcherService {
|
|
|
97
107
|
// Logging
|
|
98
108
|
LogService.log(ELogActions.GET, { target: 'NEW_GUEST_CREDENTIAL' });
|
|
99
109
|
|
|
100
|
-
return await new
|
|
110
|
+
return await new AuthService({ proxyUrl: this.authProxyUrl }).guest();
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
|
|
@@ -130,7 +140,7 @@ export class FetcherService {
|
|
|
130
140
|
*
|
|
131
141
|
* @returns The validated args.
|
|
132
142
|
*/
|
|
133
|
-
private validateArgs(resource: EResourceType, args:
|
|
143
|
+
private validateArgs(resource: EResourceType, args: IFetchArgs | IPostArgs): FetchArgs | PostArgs | undefined {
|
|
134
144
|
if (fetchResources.includes(resource)) {
|
|
135
145
|
// Logging
|
|
136
146
|
LogService.log(ELogActions.VALIDATE, { target: 'FETCH_ARGS' });
|
|
@@ -172,7 +182,7 @@ export class FetcherService {
|
|
|
172
182
|
* })
|
|
173
183
|
* ```
|
|
174
184
|
*/
|
|
175
|
-
public async request<T>(resource: EResourceType, args:
|
|
185
|
+
public async request<T>(resource: EResourceType, args: IFetchArgs | IPostArgs): Promise<T> {
|
|
176
186
|
// Logging
|
|
177
187
|
LogService.log(ELogActions.REQUEST, { resource: resource, args: args });
|
|
178
188
|
|
|
@@ -192,7 +202,7 @@ export class FetcherService {
|
|
|
192
202
|
const config = requests[resource](args);
|
|
193
203
|
|
|
194
204
|
// Setting additional request parameters
|
|
195
|
-
config.headers = { ...config.headers, ...cred.toHeader() };
|
|
205
|
+
config.headers = { ...config.headers, ...cred.toHeader(), ...(this._customHeaders || {}) };
|
|
196
206
|
config.httpAgent = httpsAgent;
|
|
197
207
|
config.httpsAgent = httpsAgent;
|
|
198
208
|
config.timeout = this._timeout;
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ESearchResultType,
|
|
5
5
|
IInitializeMediaUploadResponse,
|
|
6
6
|
IListTweetsResponse,
|
|
7
|
+
INewTweet,
|
|
7
8
|
ITweetDetailsResponse,
|
|
8
9
|
ITweetLikeResponse,
|
|
9
10
|
ITweetPostResponse,
|
|
@@ -21,7 +22,6 @@ import {
|
|
|
21
22
|
|
|
22
23
|
import { extractors } from '../../collections/Extractors';
|
|
23
24
|
import { EResourceType } from '../../enums/Resource';
|
|
24
|
-
import { TweetArgs } from '../../models/args/PostArgs';
|
|
25
25
|
import { CursoredData } from '../../models/data/CursoredData';
|
|
26
26
|
import { Tweet } from '../../models/data/Tweet';
|
|
27
27
|
import { User } from '../../models/data/User';
|
|
@@ -263,7 +263,7 @@ export class TweetService extends FetcherService {
|
|
|
263
263
|
* });
|
|
264
264
|
* ```
|
|
265
265
|
*/
|
|
266
|
-
public async post(options:
|
|
266
|
+
public async post(options: INewTweet): Promise<string | undefined> {
|
|
267
267
|
const resource = EResourceType.TWEET_POST;
|
|
268
268
|
|
|
269
269
|
// Posting the tweet
|
|
@@ -275,6 +275,46 @@ export class TweetService extends FetcherService {
|
|
|
275
275
|
return data;
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
+
/**
|
|
279
|
+
* Get the list of replies to a tweet.
|
|
280
|
+
*
|
|
281
|
+
* @param id - The id of the target tweet.
|
|
282
|
+
* @param cursor - The cursor to the batch of replies to fetch.
|
|
283
|
+
*
|
|
284
|
+
* @returns The list of replies to the given tweet.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```
|
|
288
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
289
|
+
*
|
|
290
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
291
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
292
|
+
*
|
|
293
|
+
* // Fetching the first 100 replies to the Tweet with id '1234567890'
|
|
294
|
+
* rettiwt.tweet.replies('1234567890')
|
|
295
|
+
* .then(res => {
|
|
296
|
+
* console.log(res);
|
|
297
|
+
* })
|
|
298
|
+
* .catch(err => {
|
|
299
|
+
* console.log(err);
|
|
300
|
+
* });
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
public async replies(id: string, cursor?: string): Promise<CursoredData<Tweet>> {
|
|
304
|
+
const resource = EResourceType.TWEET_REPLIES;
|
|
305
|
+
|
|
306
|
+
// Fetching raw list of replies
|
|
307
|
+
const response = await this.request<ITweetDetailsResponse>(resource, {
|
|
308
|
+
id: id,
|
|
309
|
+
cursor: cursor,
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Deserializing response
|
|
313
|
+
const data = extractors[resource](response);
|
|
314
|
+
|
|
315
|
+
return data;
|
|
316
|
+
}
|
|
317
|
+
|
|
278
318
|
/**
|
|
279
319
|
* Retweet a tweet.
|
|
280
320
|
*
|
|
@@ -381,7 +421,7 @@ export class TweetService extends FetcherService {
|
|
|
381
421
|
* @remarks
|
|
382
422
|
* Scheduling a tweet is similar to {@link post}ing, except that an extra parameter called `scheduleFor` is used.
|
|
383
423
|
*/
|
|
384
|
-
public async schedule(options:
|
|
424
|
+
public async schedule(options: INewTweet): Promise<string | undefined> {
|
|
385
425
|
const resource = EResourceType.TWEET_SCHEDULE;
|
|
386
426
|
|
|
387
427
|
// Scheduling the tweet
|
|
@@ -479,7 +519,7 @@ export class TweetService extends FetcherService {
|
|
|
479
519
|
* streamTweets();
|
|
480
520
|
* ```
|
|
481
521
|
*/
|
|
482
|
-
public async *stream(filter: TweetFilter, pollingInterval
|
|
522
|
+
public async *stream(filter: TweetFilter, pollingInterval = 60000): AsyncGenerator<Tweet> {
|
|
483
523
|
const startDate = new Date();
|
|
484
524
|
|
|
485
525
|
let cursor: string | undefined = undefined;
|
|
@@ -465,11 +465,11 @@ export class UserService extends FetcherService {
|
|
|
465
465
|
* streamNotifications();
|
|
466
466
|
* ```
|
|
467
467
|
*/
|
|
468
|
-
public async *notifications(pollingInterval
|
|
468
|
+
public async *notifications(pollingInterval = 60000): AsyncGenerator<Notification> {
|
|
469
469
|
const resource = EResourceType.USER_NOTIFICATIONS;
|
|
470
470
|
|
|
471
471
|
/** Whether it's the first batch of notifications or not. */
|
|
472
|
-
let first
|
|
472
|
+
let first = true;
|
|
473
473
|
|
|
474
474
|
/** The cursor to the last notification received. */
|
|
475
475
|
let cursor: string | undefined = undefined;
|
|
@@ -36,4 +36,11 @@ export interface IRettiwtConfig {
|
|
|
36
36
|
|
|
37
37
|
/** Optional custom error handler to define error conditions and process API/HTTP errors in responses. */
|
|
38
38
|
errorHandler?: IErrorHandler;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Optional custom HTTP headers to add to all requests to Twitter API.
|
|
42
|
+
*
|
|
43
|
+
* @remarks Custom headers can be useful for proxies, avoiding rate limits, etc.
|
|
44
|
+
*/
|
|
45
|
+
headers?: { [key: string]: string };
|
|
39
46
|
}
|