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.
Files changed (179) hide show
  1. package/.eslintrc.js +2 -3
  2. package/.github/workflows/documentation.yml +1 -1
  3. package/.github/workflows/publish-alpha.yml +1 -1
  4. package/.github/workflows/publish.yml +1 -1
  5. package/.prettierignore +1 -1
  6. package/.tool-versions +1 -1
  7. package/README.md +100 -100
  8. package/dist/Rettiwt.d.ts +1 -1
  9. package/dist/Rettiwt.js +15 -8
  10. package/dist/Rettiwt.js.map +1 -1
  11. package/dist/cli.js +8 -11
  12. package/dist/cli.js.map +1 -1
  13. package/dist/collections/Extractors.d.ts +1 -0
  14. package/dist/collections/Extractors.js +38 -69
  15. package/dist/collections/Extractors.js.map +1 -1
  16. package/dist/collections/Groups.js +2 -1
  17. package/dist/collections/Groups.js.map +1 -1
  18. package/dist/collections/Requests.d.ts +3 -3
  19. package/dist/collections/Requests.js +36 -35
  20. package/dist/collections/Requests.js.map +1 -1
  21. package/dist/commands/List.js +21 -78
  22. package/dist/commands/List.js.map +1 -1
  23. package/dist/commands/Tweet.js +185 -370
  24. package/dist/commands/Tweet.js.map +1 -1
  25. package/dist/commands/User.js +129 -306
  26. package/dist/commands/User.js.map +1 -1
  27. package/dist/enums/Authentication.d.ts +18 -0
  28. package/dist/enums/Authentication.js +24 -0
  29. package/dist/enums/Authentication.js.map +1 -0
  30. package/dist/enums/Data.d.ts +12 -0
  31. package/dist/enums/Data.js +14 -1
  32. package/dist/enums/Data.js.map +1 -1
  33. package/dist/enums/Resource.d.ts +1 -0
  34. package/dist/enums/Resource.js +1 -0
  35. package/dist/enums/Resource.js.map +1 -1
  36. package/dist/helper/CliUtils.js +1 -2
  37. package/dist/helper/CliUtils.js.map +1 -1
  38. package/dist/helper/JsonUtils.js +6 -11
  39. package/dist/helper/JsonUtils.js.map +1 -1
  40. package/dist/index.d.ts +1 -2
  41. package/dist/index.js +1 -2
  42. package/dist/index.js.map +1 -1
  43. package/dist/models/args/FetchArgs.d.ts +4 -133
  44. package/dist/models/args/FetchArgs.js +12 -416
  45. package/dist/models/args/FetchArgs.js.map +1 -1
  46. package/dist/models/args/PostArgs.d.ts +16 -101
  47. package/dist/models/args/PostArgs.js +26 -258
  48. package/dist/models/args/PostArgs.js.map +1 -1
  49. package/dist/models/auth/AccountCredential.d.ts +13 -0
  50. package/dist/models/auth/AccountCredential.js +21 -0
  51. package/dist/models/auth/AccountCredential.js.map +1 -0
  52. package/dist/models/auth/AuthCookie.d.ts +19 -0
  53. package/dist/models/auth/AuthCookie.js +53 -0
  54. package/dist/models/auth/AuthCookie.js.map +1 -0
  55. package/dist/models/auth/AuthCredential.d.ts +28 -0
  56. package/dist/models/auth/AuthCredential.js +76 -0
  57. package/dist/models/auth/AuthCredential.js.map +1 -0
  58. package/dist/models/data/CursoredData.d.ts +3 -4
  59. package/dist/models/data/CursoredData.js +19 -19
  60. package/dist/models/data/CursoredData.js.map +1 -1
  61. package/dist/models/data/List.d.ts +2 -8
  62. package/dist/models/data/List.js +10 -4
  63. package/dist/models/data/List.js.map +1 -1
  64. package/dist/models/data/Notification.d.ts +5 -21
  65. package/dist/models/data/Notification.js +24 -33
  66. package/dist/models/data/Notification.js.map +1 -1
  67. package/dist/models/data/Tweet.d.ts +4 -17
  68. package/dist/models/data/Tweet.js +83 -73
  69. package/dist/models/data/Tweet.js.map +1 -1
  70. package/dist/models/data/User.d.ts +2 -15
  71. package/dist/models/data/User.js +33 -23
  72. package/dist/models/data/User.js.map +1 -1
  73. package/dist/models/errors/ApiError.js +8 -24
  74. package/dist/models/errors/ApiError.js.map +1 -1
  75. package/dist/models/errors/HttpError.js +8 -24
  76. package/dist/models/errors/HttpError.js.map +1 -1
  77. package/dist/models/errors/RettiwtError.js +5 -23
  78. package/dist/models/errors/RettiwtError.js.map +1 -1
  79. package/dist/models/errors/TimeoutError.js +5 -22
  80. package/dist/models/errors/TimeoutError.js.map +1 -1
  81. package/dist/services/{public → internal}/AuthService.d.ts +5 -34
  82. package/dist/services/internal/AuthService.js +109 -0
  83. package/dist/services/internal/AuthService.js.map +1 -0
  84. package/dist/services/internal/ErrorService.js +38 -40
  85. package/dist/services/internal/ErrorService.js.map +1 -1
  86. package/dist/services/internal/LogService.d.ts +0 -6
  87. package/dist/services/internal/LogService.js +12 -32
  88. package/dist/services/internal/LogService.js.map +1 -1
  89. package/dist/services/public/FetcherService.d.ts +5 -3
  90. package/dist/services/public/FetcherService.js +96 -141
  91. package/dist/services/public/FetcherService.js.map +1 -1
  92. package/dist/services/public/ListService.js +31 -100
  93. package/dist/services/public/ListService.js.map +1 -1
  94. package/dist/services/public/TweetService.d.ts +29 -4
  95. package/dist/services/public/TweetService.js +208 -386
  96. package/dist/services/public/TweetService.js.map +1 -1
  97. package/dist/services/public/UserService.js +186 -385
  98. package/dist/services/public/UserService.js.map +1 -1
  99. package/dist/types/RettiwtConfig.d.ts +8 -0
  100. package/dist/types/args/FetchArgs.d.ts +59 -0
  101. package/dist/types/args/FetchArgs.js +3 -0
  102. package/dist/types/args/FetchArgs.js.map +1 -0
  103. package/dist/types/args/PostArgs.d.ts +56 -0
  104. package/dist/types/args/PostArgs.js +3 -0
  105. package/dist/types/args/PostArgs.js.map +1 -0
  106. package/dist/types/auth/AccountCredential.d.ts +11 -0
  107. package/dist/types/auth/AccountCredential.js +3 -0
  108. package/dist/types/auth/AccountCredential.js.map +1 -0
  109. package/dist/types/auth/AuthCookie.d.ts +13 -0
  110. package/dist/types/auth/AuthCookie.js +3 -0
  111. package/dist/types/auth/AuthCookie.js.map +1 -0
  112. package/dist/types/auth/AuthCredential.d.ts +21 -0
  113. package/dist/types/auth/AuthCredential.js +3 -0
  114. package/dist/types/auth/AuthCredential.js.map +1 -0
  115. package/dist/types/data/CursoredData.d.ts +25 -0
  116. package/dist/types/data/CursoredData.js +3 -0
  117. package/dist/types/data/CursoredData.js.map +1 -0
  118. package/dist/types/data/List.d.ts +21 -0
  119. package/dist/types/data/List.js +3 -0
  120. package/dist/types/data/List.js.map +1 -0
  121. package/dist/types/data/Notification.d.ts +20 -0
  122. package/dist/types/data/Notification.js +3 -0
  123. package/dist/types/data/Notification.js.map +1 -0
  124. package/dist/types/data/Tweet.d.ts +71 -0
  125. package/dist/types/data/Tweet.js +3 -0
  126. package/dist/types/data/Tweet.js.map +1 -0
  127. package/dist/types/data/User.d.ts +35 -0
  128. package/dist/types/data/User.js +3 -0
  129. package/dist/types/data/User.js.map +1 -0
  130. package/eslint.config.mjs +17 -0
  131. package/package.json +22 -19
  132. package/src/Rettiwt.ts +1 -1
  133. package/src/cli.ts +0 -2
  134. package/src/collections/Extractors.ts +2 -0
  135. package/src/collections/Groups.ts +1 -0
  136. package/src/collections/Requests.ts +37 -36
  137. package/src/enums/Authentication.ts +19 -0
  138. package/src/enums/Data.ts +13 -0
  139. package/src/enums/Resource.ts +1 -0
  140. package/src/helper/JsonUtils.ts +1 -1
  141. package/src/index.ts +1 -2
  142. package/src/models/args/FetchArgs.ts +4 -470
  143. package/src/models/args/PostArgs.ts +20 -285
  144. package/src/models/auth/AccountCredential.ts +19 -0
  145. package/src/models/auth/AuthCookie.ts +56 -0
  146. package/src/models/auth/AuthCredential.ts +83 -0
  147. package/src/models/data/CursoredData.ts +12 -9
  148. package/src/models/data/List.ts +3 -14
  149. package/src/models/data/Notification.ts +6 -28
  150. package/src/models/data/Tweet.ts +17 -43
  151. package/src/models/data/User.ts +5 -31
  152. package/src/services/{public → internal}/AuthService.ts +28 -55
  153. package/src/services/internal/LogService.ts +4 -19
  154. package/src/services/public/FetcherService.ts +18 -8
  155. package/src/services/public/TweetService.ts +44 -4
  156. package/src/services/public/UserService.ts +2 -2
  157. package/src/types/RettiwtConfig.ts +7 -0
  158. package/src/types/args/FetchArgs.ts +64 -0
  159. package/src/types/args/PostArgs.ts +62 -0
  160. package/src/types/auth/AccountCredential.ts +13 -0
  161. package/src/types/auth/AuthCookie.ts +20 -0
  162. package/src/types/auth/AuthCredential.ts +26 -0
  163. package/src/types/data/CursoredData.ts +28 -0
  164. package/src/types/data/List.ts +27 -0
  165. package/src/types/data/Notification.ts +26 -0
  166. package/src/types/data/Tweet.ts +96 -0
  167. package/src/types/data/User.ts +48 -0
  168. package/tsconfig.json +7 -5
  169. package/.eslintignore +0 -3
  170. package/dist/commands/Auth.d.ts +0 -10
  171. package/dist/commands/Auth.js +0 -101
  172. package/dist/commands/Auth.js.map +0 -1
  173. package/dist/models/errors/DataValidationError.d.ts +0 -30
  174. package/dist/models/errors/DataValidationError.js +0 -34
  175. package/dist/models/errors/DataValidationError.js.map +0 -1
  176. package/dist/services/public/AuthService.js +0 -205
  177. package/dist/services/public/AuthService.js.map +0 -1
  178. package/src/commands/Auth.ts +0 -46
  179. package/src/models/errors/DataValidationError.ts +0 -44
@@ -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 ITweet)?.rest_id) {
112
- return new Tweet(tweet.quoted_status_result.result as ITweet);
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 ITweet)?.rest_id) {
138
- return new Tweet(tweet.legacy.retweeted_status_result.result as ITweet);
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 ITweet)?.legacy) {
146
+ else if ((item.tweet_results?.result as IRawTweet)?.legacy) {
173
147
  // Logging
174
- LogService.log(ELogActions.DESERIALIZE, { id: (item.tweet_results.result as ITweet).rest_id });
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 ITweet));
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<ITweet>(response, 'rest_id', id);
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: string = '';
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: number = 0;
277
+ let highestRate = 0;
304
278
 
305
279
  /**
306
280
  * Selecting the URL of the video variant with the highest bitrate.
@@ -1,55 +1,29 @@
1
- import { IUser as IRawUser, ITimelineUser, IUser } from 'rettiwt-core';
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<ITimelineUser>(response, '__typename', 'TimelineUser');
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<IUser>(response, '__typename', 'User');
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 { Auth } from 'rettiwt-auth';
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 extends FetcherService {
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
- super(config);
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<string> {
98
- // Getting a new guest key
99
- const guestKey: string = (await new Auth().getGuestCredential()).guestToken ?? '';
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
- // Converting the credentials to base64 string
146
- apiKey = AuthService.encodeCookie(apiKey);
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 apiKey;
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: boolean = false;
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: string = chalk.blue('Rettiwt-API');
23
+ const logPrefix = 'Rettiwt-API';
39
24
  const logTime: string = new Date().toISOString();
40
- const logAction: string = LogService.getColoredAction(action);
25
+ const logAction: string = action;
41
26
  const logData: string = JSON.stringify(data);
42
27
 
43
- const logMessage: string = `[${logPrefix}] [${logTime}] [${logAction}] ${logData}`;
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(AuthService.decodeCookie(this._apiKey).split(';'));
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 Auth({ proxyUrl: this.authProxyUrl }).getGuestCredential();
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: FetchArgs | PostArgs): FetchArgs | PostArgs | undefined {
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: FetchArgs | PostArgs): Promise<T> {
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: TweetArgs): Promise<string | undefined> {
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: TweetArgs): Promise<string | undefined> {
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: number = 60000): AsyncGenerator<Tweet> {
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: number = 60000): AsyncGenerator<Notification> {
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: boolean = true;
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
+ }