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.
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 +6 -23
  68. package/dist/models/data/Tweet.js +93 -97
  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 +28 -70
  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,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, response: NonNullable<unknown>) {
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, response);
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 = this.getParentTweet(tweet, response);
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, response);
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, response: NonNullable<unknown>): Tweet | undefined {
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, response);
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 ITweet)?.rest_id) {
127
- return new Tweet(tweet.quoted_status_result.result as ITweet, response);
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, response: NonNullable<unknown>): Tweet | undefined {
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, response);
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 ITweet)?.rest_id) {
154
- return new Tweet(tweet.legacy.retweeted_status_result.result as ITweet, response);
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, response));
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 ITweet)?.legacy) {
146
+ else if ((item.tweet_results?.result as IRawTweet)?.legacy) {
189
147
  // Logging
190
- 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 });
191
149
 
192
- tweets.push(new Tweet(item.tweet_results.result as ITweet, response));
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<ITweet>(response, 'rest_id', id);
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, response));
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: string = '';
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: number = 0;
277
+ let highestRate = 0;
320
278
 
321
279
  /**
322
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
  }