rettiwt-api 4.2.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 +4 -17
- package/dist/models/data/Tweet.js +83 -73
- 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 +17 -43
- 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,53 +21,24 @@ 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
37
|
public replyTo?: string;
|
|
59
|
-
|
|
60
|
-
/** The number of retweets of the tweet. */
|
|
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
|
/**
|
|
@@ -74,6 +46,7 @@ export class Tweet {
|
|
|
74
46
|
*/
|
|
75
47
|
public constructor(tweet: IRawTweet) {
|
|
76
48
|
this.id = tweet.rest_id;
|
|
49
|
+
this.conversationId = tweet.legacy.conversation_id_str;
|
|
77
50
|
this.createdAt = tweet.legacy.created_at;
|
|
78
51
|
this.tweetBy = new User(tweet.core.user_results.result);
|
|
79
52
|
this.entities = new TweetEntities(tweet.legacy.entities);
|
|
@@ -89,6 +62,7 @@ export class Tweet {
|
|
|
89
62
|
this.viewCount = tweet.views.count ? parseInt(tweet.views.count) : 0;
|
|
90
63
|
this.bookmarkCount = tweet.legacy.bookmark_count;
|
|
91
64
|
this.retweetedTweet = this.getRetweetedTweet(tweet);
|
|
65
|
+
this.url = `https://x.com/${this.tweetBy.userName}/status/${this.id}`;
|
|
92
66
|
}
|
|
93
67
|
|
|
94
68
|
/**
|
|
@@ -108,8 +82,8 @@ export class Tweet {
|
|
|
108
82
|
return new Tweet((tweet.quoted_status_result.result as ILimitedVisibilityTweet).tweet);
|
|
109
83
|
}
|
|
110
84
|
// If normal tweet
|
|
111
|
-
else if ((tweet.quoted_status_result?.result as
|
|
112
|
-
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);
|
|
113
87
|
}
|
|
114
88
|
// Else, skip
|
|
115
89
|
else {
|
|
@@ -134,8 +108,8 @@ export class Tweet {
|
|
|
134
108
|
return new Tweet((tweet.legacy.retweeted_status_result.result as ILimitedVisibilityTweet).tweet);
|
|
135
109
|
}
|
|
136
110
|
// If normal tweet
|
|
137
|
-
else if ((tweet.legacy?.retweeted_status_result?.result as
|
|
138
|
-
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);
|
|
139
113
|
}
|
|
140
114
|
// Else, skip
|
|
141
115
|
else {
|
|
@@ -169,11 +143,11 @@ export class Tweet {
|
|
|
169
143
|
tweets.push(new Tweet((item.tweet_results.result as ILimitedVisibilityTweet).tweet));
|
|
170
144
|
}
|
|
171
145
|
// If normal tweet
|
|
172
|
-
else if ((item.tweet_results?.result as
|
|
146
|
+
else if ((item.tweet_results?.result as IRawTweet)?.legacy) {
|
|
173
147
|
// Logging
|
|
174
|
-
LogService.log(ELogActions.DESERIALIZE, { id: (item.tweet_results.result as
|
|
148
|
+
LogService.log(ELogActions.DESERIALIZE, { id: (item.tweet_results.result as IRawTweet).rest_id });
|
|
175
149
|
|
|
176
|
-
tweets.push(new Tweet(item.tweet_results.result as
|
|
150
|
+
tweets.push(new Tweet(item.tweet_results.result as IRawTweet));
|
|
177
151
|
}
|
|
178
152
|
// If invalid/unrecognized tweet
|
|
179
153
|
else {
|
|
@@ -202,7 +176,7 @@ export class Tweet {
|
|
|
202
176
|
const tweets: Tweet[] = [];
|
|
203
177
|
|
|
204
178
|
// Extracting the matching data
|
|
205
|
-
const extract = findByFilter<
|
|
179
|
+
const extract = findByFilter<IRawTweet>(response, 'rest_id', id);
|
|
206
180
|
|
|
207
181
|
// Deserializing valid data
|
|
208
182
|
for (const item of extract) {
|
|
@@ -279,7 +253,7 @@ export class TweetMedia {
|
|
|
279
253
|
public type: EMediaType;
|
|
280
254
|
|
|
281
255
|
/** The direct URL to the media. */
|
|
282
|
-
public url
|
|
256
|
+
public url = '';
|
|
283
257
|
|
|
284
258
|
/**
|
|
285
259
|
* @param media - The raw media details.
|
|
@@ -300,7 +274,7 @@ export class TweetMedia {
|
|
|
300
274
|
this.thumbnailUrl = media.media_url_https;
|
|
301
275
|
|
|
302
276
|
/** The highest bitrate of all variants. */
|
|
303
|
-
let highestRate
|
|
277
|
+
let highestRate = 0;
|
|
304
278
|
|
|
305
279
|
/**
|
|
306
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
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ESearchResultType, ITweetFilter } from 'rettiwt-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options specifying the data that is to be fetched.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export interface IFetchArgs {
|
|
9
|
+
/**
|
|
10
|
+
* The number of data items to fetch.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* - Works only for cursored resources.
|
|
14
|
+
* - Does not work for {@link EResourceType.TWEET_REPLIES}.
|
|
15
|
+
* - Must be \<= 20 for:
|
|
16
|
+
* - {@link EResourceType.USER_TIMELINE}
|
|
17
|
+
* - {@link EResourceType.USER_TIMELINE}
|
|
18
|
+
* - {@link EResourceType.USER_TIMELINE_AND_REPLIES}
|
|
19
|
+
* - Must be \<= 100 for all other cursored resources.
|
|
20
|
+
* - Due a bug on Twitter's end, count does not work for {@link EResourceType.USER_FOLLOWERS} and {@link EResourceType.USER_FOLLOWING}.
|
|
21
|
+
* - Has not effect for:
|
|
22
|
+
* - {@link EResourceType.USER_FEED_FOLLOWED}
|
|
23
|
+
* - {@link EResourceType.USER_FEED_RECOMMENDED}
|
|
24
|
+
*/
|
|
25
|
+
count?: number;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The cursor to the batch of data to fetch.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* - May be used for cursored resources.
|
|
32
|
+
* - Has no effect for other resources.
|
|
33
|
+
*/
|
|
34
|
+
cursor?: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The filter for searching tweets.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Required when searching for tweets using {@link EResourceType.TWEET_SEARCH}.
|
|
41
|
+
*/
|
|
42
|
+
filter?: ITweetFilter;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The id of the target resource.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* - Required for all resources except {@link EResourceType.TWEET_SEARCH} and {@link EResourceType.USER_TIMELINE_RECOMMENDED}.
|
|
49
|
+
* - For {@link EResourceType.USER_DETAILS_BY_USERNAME}, can be alphanumeric, while for others, is strictly numeric.
|
|
50
|
+
*/
|
|
51
|
+
id?: string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The type of search results to fetch. Can be one of:
|
|
55
|
+
* - {@link EResourceType.LATEST}, for latest search results.
|
|
56
|
+
* - {@link EResourceType.TOP}, for top search results.
|
|
57
|
+
*
|
|
58
|
+
* @defaultValue {@link ESearchResultType.LATEST}.
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* - Applicable only for {@link EResourceType.TWEET_SEARCH}.
|
|
62
|
+
*/
|
|
63
|
+
results?: ESearchResultType;
|
|
64
|
+
}
|