rettiwt-api 6.3.0-alpha.0 → 7.0.0
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/README.md +81 -31
- package/dist/Rettiwt.d.ts +6 -2
- package/dist/Rettiwt.js +7 -3
- package/dist/Rettiwt.js.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/collections/Extractors.d.ts +15 -2
- package/dist/collections/Extractors.js +12 -1
- package/dist/collections/Extractors.js.map +1 -1
- package/dist/collections/Groups.js +8 -0
- package/dist/collections/Groups.js.map +1 -1
- package/dist/collections/Requests.js +8 -0
- package/dist/collections/Requests.js.map +1 -1
- package/dist/commands/Space.d.ts +10 -0
- package/dist/commands/Space.js +38 -0
- package/dist/commands/Space.js.map +1 -0
- package/dist/commands/User.js +139 -0
- package/dist/commands/User.js.map +1 -1
- package/dist/enums/Resource.d.ts +8 -1
- package/dist/enums/Resource.js +8 -0
- package/dist/enums/Resource.js.map +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/models/RettiwtConfig.d.ts +26 -3
- package/dist/models/RettiwtConfig.js +68 -3
- package/dist/models/RettiwtConfig.js.map +1 -1
- package/dist/models/args/FetchArgs.d.ts +3 -0
- package/dist/models/args/FetchArgs.js +6 -0
- package/dist/models/args/FetchArgs.js.map +1 -1
- package/dist/models/args/PostArgs.d.ts +24 -1
- package/dist/models/args/PostArgs.js +52 -1
- package/dist/models/args/PostArgs.js.map +1 -1
- package/dist/models/data/Space.d.ts +70 -0
- package/dist/models/data/Space.js +177 -0
- package/dist/models/data/Space.js.map +1 -0
- package/dist/models/data/UserAbout.d.ts +44 -0
- package/dist/models/data/UserAbout.js +129 -0
- package/dist/models/data/UserAbout.js.map +1 -0
- package/dist/requests/Space.d.ts +15 -0
- package/dist/requests/Space.js +74 -0
- package/dist/requests/Space.js.map +1 -0
- package/dist/requests/Tweet.d.ts +4 -0
- package/dist/requests/Tweet.js +57 -0
- package/dist/requests/Tweet.js.map +1 -1
- package/dist/requests/User.d.ts +21 -0
- package/dist/requests/User.js +64 -0
- package/dist/requests/User.js.map +1 -1
- package/dist/services/internal/AuthService.d.ts +25 -0
- package/dist/services/internal/AuthService.js +121 -0
- package/dist/services/internal/AuthService.js.map +1 -1
- package/dist/services/public/DirectMessageService.js +3 -3
- package/dist/services/public/DirectMessageService.js.map +1 -1
- package/dist/services/public/FetcherService.d.ts +4 -3
- package/dist/services/public/FetcherService.js +22 -16
- package/dist/services/public/FetcherService.js.map +1 -1
- package/dist/services/public/ListService.js +5 -5
- package/dist/services/public/ListService.js.map +1 -1
- package/dist/services/public/SpaceService.d.ts +42 -0
- package/dist/services/public/SpaceService.js +60 -0
- package/dist/services/public/SpaceService.js.map +1 -0
- package/dist/services/public/TweetService.js +26 -23
- package/dist/services/public/TweetService.js.map +1 -1
- package/dist/services/public/UserService.d.ts +79 -0
- package/dist/services/public/UserService.js +203 -23
- package/dist/services/public/UserService.js.map +1 -1
- package/dist/types/RettiwtConfig.d.ts +33 -3
- package/dist/types/args/FetchArgs.d.ts +35 -1
- package/dist/types/args/PostArgs.d.ts +44 -1
- package/dist/types/data/Space.d.ts +89 -0
- package/dist/types/data/Space.js +3 -0
- package/dist/types/data/Space.js.map +1 -0
- package/dist/types/data/UserAbout.d.ts +68 -0
- package/dist/types/data/UserAbout.js +3 -0
- package/dist/types/data/UserAbout.js.map +1 -0
- package/dist/types/raw/base/Space.d.ts +43 -22
- package/dist/types/raw/space/AudioSpaceById.d.ts +50 -0
- package/dist/types/raw/space/AudioSpaceById.js +4 -0
- package/dist/types/raw/space/AudioSpaceById.js.map +1 -0
- package/dist/types/raw/space/Details.d.ts +2 -309
- package/dist/types/raw/tweet/Post.d.ts +16 -1
- package/dist/types/raw/user/About.d.ts +65 -0
- package/dist/types/raw/user/About.js +4 -0
- package/dist/types/raw/user/About.js.map +1 -0
- package/dist/types/raw/user/ChangePassword.d.ts +8 -0
- package/dist/types/raw/user/ChangePassword.js +3 -0
- package/dist/types/raw/user/ChangePassword.js.map +1 -0
- package/dist/types/raw/user/ProfileUpdate.d.ts +1 -0
- package/dist/types/raw/user/Settings.d.ts +21 -0
- package/dist/types/raw/user/Settings.js +4 -0
- package/dist/types/raw/user/Settings.js.map +1 -0
- package/package.json +6 -4
- package/src/Rettiwt.ts +10 -3
- package/src/cli.ts +3 -1
- package/src/collections/Extractors.ts +22 -3
- package/src/collections/Groups.ts +8 -0
- package/src/collections/Requests.ts +11 -0
- package/src/commands/Space.ts +46 -0
- package/src/commands/User.ts +159 -0
- package/src/enums/Resource.ts +9 -0
- package/src/index.ts +11 -1
- package/src/models/RettiwtConfig.ts +81 -6
- package/src/models/args/FetchArgs.ts +6 -0
- package/src/models/args/PostArgs.ts +58 -1
- package/src/models/data/Space.ts +201 -0
- package/src/models/data/UserAbout.ts +161 -0
- package/src/requests/Space.ts +76 -0
- package/src/requests/Tweet.ts +59 -0
- package/src/requests/User.ts +69 -0
- package/src/services/internal/AuthService.ts +149 -1
- package/src/services/public/DirectMessageService.ts +3 -3
- package/src/services/public/FetcherService.ts +25 -18
- package/src/services/public/ListService.ts +5 -5
- package/src/services/public/SpaceService.ts +65 -0
- package/src/services/public/TweetService.ts +27 -24
- package/src/services/public/UserService.ts +247 -23
- package/src/types/RettiwtConfig.ts +35 -3
- package/src/types/args/FetchArgs.ts +41 -1
- package/src/types/args/PostArgs.ts +50 -1
- package/src/types/data/Space.ts +122 -0
- package/src/types/data/UserAbout.ts +87 -0
- package/src/types/raw/base/Space.ts +42 -22
- package/src/types/raw/space/AudioSpaceById.ts +57 -0
- package/src/types/raw/space/Details.ts +3 -352
- package/src/types/raw/tweet/Post.ts +19 -1
- package/src/types/raw/user/About.ts +77 -0
- package/src/types/raw/user/ChangePassword.ts +8 -0
- package/src/types/raw/user/ProfileUpdate.ts +1 -0
- package/src/types/raw/user/Settings.ts +23 -0
- package/tsconfig.json +2 -2
|
@@ -17,7 +17,7 @@ import { ITweetDetailsResponse } from '../../types/raw/tweet/Details';
|
|
|
17
17
|
import { ITweetDetailsBulkResponse } from '../../types/raw/tweet/DetailsBulk';
|
|
18
18
|
import { ITweetLikeResponse } from '../../types/raw/tweet/Like';
|
|
19
19
|
import { ITweetLikersResponse } from '../../types/raw/tweet/Likers';
|
|
20
|
-
import { ITweetPostResponse } from '../../types/raw/tweet/Post';
|
|
20
|
+
import { ITweetPostNoteResponse, ITweetPostResponse } from '../../types/raw/tweet/Post';
|
|
21
21
|
import { ITweetRepliesResponse } from '../../types/raw/tweet/Replies';
|
|
22
22
|
import { ITweetRetweetResponse } from '../../types/raw/tweet/Retweet';
|
|
23
23
|
import { ITweetRetweetersResponse } from '../../types/raw/tweet/Retweeters';
|
|
@@ -80,7 +80,7 @@ export class TweetService extends FetcherService {
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
// Deserializing response
|
|
83
|
-
const data = Extractors[resource](response) ?? false;
|
|
83
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
84
84
|
|
|
85
85
|
return data;
|
|
86
86
|
}
|
|
@@ -146,7 +146,7 @@ export class TweetService extends FetcherService {
|
|
|
146
146
|
const response = await this.request<ITweetRepliesResponse>(resource, { id: id });
|
|
147
147
|
|
|
148
148
|
// Deserializing response
|
|
149
|
-
const data = Extractors[resource](response, id);
|
|
149
|
+
const data = Extractors[resource](response.data, id);
|
|
150
150
|
|
|
151
151
|
return data as T extends string ? Tweet | undefined : Tweet[];
|
|
152
152
|
}
|
|
@@ -158,7 +158,7 @@ export class TweetService extends FetcherService {
|
|
|
158
158
|
const response = await this.request<ITweetDetailsBulkResponse>(resource, { ids: id });
|
|
159
159
|
|
|
160
160
|
// Deserializing response
|
|
161
|
-
const data = Extractors[resource](response, id);
|
|
161
|
+
const data = Extractors[resource](response.data, id);
|
|
162
162
|
|
|
163
163
|
return data as T extends string ? Tweet | undefined : Tweet[];
|
|
164
164
|
}
|
|
@@ -170,7 +170,7 @@ export class TweetService extends FetcherService {
|
|
|
170
170
|
const response = await this.request<ITweetDetailsResponse>(resource, { id: String(id) });
|
|
171
171
|
|
|
172
172
|
// Deserializing response
|
|
173
|
-
const data = Extractors[resource](response, String(id));
|
|
173
|
+
const data = Extractors[resource](response.data, String(id));
|
|
174
174
|
|
|
175
175
|
return data as T extends string ? Tweet | undefined : Tweet[];
|
|
176
176
|
}
|
|
@@ -210,7 +210,7 @@ export class TweetService extends FetcherService {
|
|
|
210
210
|
});
|
|
211
211
|
|
|
212
212
|
// Deserializing response
|
|
213
|
-
const data = Extractors[resource](response) ?? false;
|
|
213
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
214
214
|
|
|
215
215
|
return data;
|
|
216
216
|
}
|
|
@@ -253,7 +253,7 @@ export class TweetService extends FetcherService {
|
|
|
253
253
|
});
|
|
254
254
|
|
|
255
255
|
// Deserializing response
|
|
256
|
-
const data = Extractors[resource](response);
|
|
256
|
+
const data = Extractors[resource](response.data);
|
|
257
257
|
|
|
258
258
|
return data;
|
|
259
259
|
}
|
|
@@ -342,15 +342,18 @@ export class TweetService extends FetcherService {
|
|
|
342
342
|
* ```
|
|
343
343
|
*/
|
|
344
344
|
public async post(options: INewTweet): Promise<string | undefined> {
|
|
345
|
-
|
|
345
|
+
// Use CreateNoteTweet endpoint for long-form tweets (X Premium, >280 chars)
|
|
346
|
+
if ((options.text?.length ?? 0) > 280) {
|
|
347
|
+
const response = await this.request<ITweetPostNoteResponse>(ResourceType.TWEET_POST_NOTE, {
|
|
348
|
+
tweet: options,
|
|
349
|
+
});
|
|
346
350
|
|
|
347
|
-
|
|
348
|
-
|
|
351
|
+
return Extractors[ResourceType.TWEET_POST_NOTE](response.data);
|
|
352
|
+
}
|
|
349
353
|
|
|
350
|
-
|
|
351
|
-
const data = Extractors[resource](response);
|
|
354
|
+
const response = await this.request<ITweetPostResponse>(ResourceType.TWEET_POST, { tweet: options });
|
|
352
355
|
|
|
353
|
-
return data;
|
|
356
|
+
return Extractors[ResourceType.TWEET_POST](response.data);
|
|
354
357
|
}
|
|
355
358
|
|
|
356
359
|
/**
|
|
@@ -403,7 +406,7 @@ export class TweetService extends FetcherService {
|
|
|
403
406
|
});
|
|
404
407
|
|
|
405
408
|
// Deserializing response
|
|
406
|
-
const data = Extractors[resource](response);
|
|
409
|
+
const data = Extractors[resource](response.data);
|
|
407
410
|
|
|
408
411
|
return data;
|
|
409
412
|
}
|
|
@@ -440,7 +443,7 @@ export class TweetService extends FetcherService {
|
|
|
440
443
|
const response = await this.request<ITweetRetweetResponse>(resource, { id: id });
|
|
441
444
|
|
|
442
445
|
// Deserializing response
|
|
443
|
-
const data = Extractors[resource](response) ?? false;
|
|
446
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
444
447
|
|
|
445
448
|
return data;
|
|
446
449
|
}
|
|
@@ -483,7 +486,7 @@ export class TweetService extends FetcherService {
|
|
|
483
486
|
});
|
|
484
487
|
|
|
485
488
|
// Deserializing response
|
|
486
|
-
const data = Extractors[resource](response);
|
|
489
|
+
const data = Extractors[resource](response.data);
|
|
487
490
|
|
|
488
491
|
return data;
|
|
489
492
|
}
|
|
@@ -525,7 +528,7 @@ export class TweetService extends FetcherService {
|
|
|
525
528
|
const response = await this.request<ITweetScheduleResponse>(resource, { tweet: options });
|
|
526
529
|
|
|
527
530
|
// Deserializing response
|
|
528
|
-
const data = Extractors[resource](response);
|
|
531
|
+
const data = Extractors[resource](response.data);
|
|
529
532
|
|
|
530
533
|
return data;
|
|
531
534
|
}
|
|
@@ -573,7 +576,7 @@ export class TweetService extends FetcherService {
|
|
|
573
576
|
});
|
|
574
577
|
|
|
575
578
|
// Deserializing response
|
|
576
|
-
const data = Extractors[resource](response);
|
|
579
|
+
const data = Extractors[resource](response.data);
|
|
577
580
|
|
|
578
581
|
// Sorting the tweets by date, from recent to oldest
|
|
579
582
|
data.list.sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
|
|
@@ -682,7 +685,7 @@ export class TweetService extends FetcherService {
|
|
|
682
685
|
const response = await this.request<ITweetUnbookmarkResponse>(resource, { id: id });
|
|
683
686
|
|
|
684
687
|
// Deserializing the response
|
|
685
|
-
const data = Extractors[resource](response) ?? false;
|
|
688
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
686
689
|
|
|
687
690
|
return data;
|
|
688
691
|
}
|
|
@@ -719,7 +722,7 @@ export class TweetService extends FetcherService {
|
|
|
719
722
|
const response = await this.request<ITweetUnlikeResponse>(resource, { id: id });
|
|
720
723
|
|
|
721
724
|
// Deserializing the response
|
|
722
|
-
const data = Extractors[resource](response) ?? false;
|
|
725
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
723
726
|
|
|
724
727
|
return data;
|
|
725
728
|
}
|
|
@@ -756,7 +759,7 @@ export class TweetService extends FetcherService {
|
|
|
756
759
|
const response = await this.request<ITweetUnpostResponse>(resource, { id: id });
|
|
757
760
|
|
|
758
761
|
// Deserializing the response
|
|
759
|
-
const data = Extractors[resource](response) ?? false;
|
|
762
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
760
763
|
|
|
761
764
|
return data;
|
|
762
765
|
}
|
|
@@ -793,7 +796,7 @@ export class TweetService extends FetcherService {
|
|
|
793
796
|
const response = await this.request<ITweetUnretweetResponse>(resource, { id: id });
|
|
794
797
|
|
|
795
798
|
// Deserializing the response
|
|
796
|
-
const data = Extractors[resource](response) ?? false;
|
|
799
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
797
800
|
|
|
798
801
|
return data;
|
|
799
802
|
}
|
|
@@ -830,7 +833,7 @@ export class TweetService extends FetcherService {
|
|
|
830
833
|
const response = await this.request<ITweetUnscheduleResponse>(resource, { id: id });
|
|
831
834
|
|
|
832
835
|
// Deserializing the response
|
|
833
|
-
const data = Extractors[resource](response) ?? false;
|
|
836
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
834
837
|
|
|
835
838
|
return data;
|
|
836
839
|
}
|
|
@@ -873,7 +876,7 @@ export class TweetService extends FetcherService {
|
|
|
873
876
|
await this.request<IMediaInitializeUploadResponse>(ResourceType.MEDIA_UPLOAD_INITIALIZE, {
|
|
874
877
|
upload: { size: size },
|
|
875
878
|
})
|
|
876
|
-
).media_id_string;
|
|
879
|
+
).data.media_id_string;
|
|
877
880
|
|
|
878
881
|
// APPEND
|
|
879
882
|
await this.request<unknown>(ResourceType.MEDIA_UPLOAD_APPEND, { upload: { id: id, media: media } });
|
|
@@ -9,13 +9,16 @@ import { List } from '../../models/data/List';
|
|
|
9
9
|
import { Notification } from '../../models/data/Notification';
|
|
10
10
|
import { Tweet } from '../../models/data/Tweet';
|
|
11
11
|
import { User } from '../../models/data/User';
|
|
12
|
+
import { UserAbout } from '../../models/data/UserAbout';
|
|
12
13
|
import { RettiwtConfig } from '../../models/RettiwtConfig';
|
|
13
14
|
import { IProfileUpdateOptions } from '../../types/args/ProfileArgs';
|
|
15
|
+
import { IUserAboutResponse } from '../../types/raw/user/About';
|
|
14
16
|
import { IUserAffiliatesResponse } from '../../types/raw/user/Affiliates';
|
|
15
17
|
import { IUserAnalyticsResponse } from '../../types/raw/user/Analytics';
|
|
16
18
|
import { IUserBookmarkFoldersResponse } from '../../types/raw/user/BookmarkFolders';
|
|
17
19
|
import { IUserBookmarkFolderTweetsResponse } from '../../types/raw/user/BookmarkFolderTweets';
|
|
18
20
|
import { IUserBookmarksResponse } from '../../types/raw/user/Bookmarks';
|
|
21
|
+
import { IUserChangePasswordResponse } from '../../types/raw/user/ChangePassword';
|
|
19
22
|
import { IUserDetailsResponse } from '../../types/raw/user/Details';
|
|
20
23
|
import { IUserDetailsBulkResponse } from '../../types/raw/user/DetailsBulk';
|
|
21
24
|
import { IUserFollowResponse } from '../../types/raw/user/Follow';
|
|
@@ -30,11 +33,14 @@ import { IUserNotificationsResponse } from '../../types/raw/user/Notifications';
|
|
|
30
33
|
import { IUserProfileUpdateResponse } from '../../types/raw/user/ProfileUpdate';
|
|
31
34
|
import { IUserRecommendedResponse } from '../../types/raw/user/Recommended';
|
|
32
35
|
import { IUserSearchResponse } from '../../types/raw/user/Search';
|
|
36
|
+
import { IUserSettingsResponse } from '../../types/raw/user/Settings';
|
|
33
37
|
import { IUserSubscriptionsResponse } from '../../types/raw/user/Subscriptions';
|
|
34
38
|
import { IUserTweetsResponse } from '../../types/raw/user/Tweets';
|
|
35
39
|
import { IUserTweetsAndRepliesResponse } from '../../types/raw/user/TweetsAndReplies';
|
|
36
40
|
import { IUserUnfollowResponse } from '../../types/raw/user/Unfollow';
|
|
37
41
|
|
|
42
|
+
import { AuthService } from '../internal/AuthService';
|
|
43
|
+
|
|
38
44
|
import { FetcherService } from './FetcherService';
|
|
39
45
|
|
|
40
46
|
/**
|
|
@@ -52,6 +58,97 @@ export class UserService extends FetcherService {
|
|
|
52
58
|
super(config);
|
|
53
59
|
}
|
|
54
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Gets the size in bytes of a base64 string.
|
|
63
|
+
*
|
|
64
|
+
* @param base64Data - The base64 data show size is required.
|
|
65
|
+
*
|
|
66
|
+
* @returns The size in bytes of the data.
|
|
67
|
+
*/
|
|
68
|
+
private _base64ByteSize(base64Data: string): number {
|
|
69
|
+
const paddingMatch = base64Data.match(/=+$/);
|
|
70
|
+
const paddingLength = paddingMatch ? paddingMatch[0].length : 0;
|
|
71
|
+
|
|
72
|
+
return (base64Data.length * 3) / 4 - paddingLength;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Normalizes base64 data into just the raw base64 string.
|
|
77
|
+
*
|
|
78
|
+
* @param payload - The data to normalize.
|
|
79
|
+
*
|
|
80
|
+
* @returns The raw base64 part of the data.
|
|
81
|
+
*/
|
|
82
|
+
private _normalizeBase64(payload: string): string {
|
|
83
|
+
const trimmedPayload = payload.trim();
|
|
84
|
+
const lowerCasePayload = trimmedPayload.toLowerCase();
|
|
85
|
+
const base64Marker = ';base64,';
|
|
86
|
+
|
|
87
|
+
if (lowerCasePayload.startsWith('data:')) {
|
|
88
|
+
const markerIndex = lowerCasePayload.indexOf(base64Marker);
|
|
89
|
+
if (markerIndex !== -1) {
|
|
90
|
+
return trimmedPayload.slice(markerIndex + base64Marker.length).trim();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return trimmedPayload;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private _validateBase64Payload(payload: string, fieldName: string): string {
|
|
98
|
+
const normalizedPayload = this._normalizeBase64(payload).replace(/\s+/g, '');
|
|
99
|
+
|
|
100
|
+
if (normalizedPayload.length === 0) {
|
|
101
|
+
throw new Error(`${fieldName} cannot be empty`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(normalizedPayload)) {
|
|
105
|
+
throw new Error(`${fieldName} must be valid base64`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return normalizedPayload;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the about profile of a user.
|
|
113
|
+
*
|
|
114
|
+
* @param userName - The username/screenname of the target user.
|
|
115
|
+
*
|
|
116
|
+
* @returns The about profile of the user.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
*
|
|
120
|
+
* ```ts
|
|
121
|
+
* import { Rettiwt } from 'rettiwt-api';
|
|
122
|
+
*
|
|
123
|
+
* // Creating a new Rettiwt instance using the given 'API_KEY'
|
|
124
|
+
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
|
|
125
|
+
*
|
|
126
|
+
* // Fetching the about profile of the User with username 'user1' or '@user1'
|
|
127
|
+
* rettiwt.user.about('user1') // or @user1
|
|
128
|
+
* .then(res => {
|
|
129
|
+
* console.log(res);
|
|
130
|
+
* })
|
|
131
|
+
* .catch(err => {
|
|
132
|
+
* console.log(err);
|
|
133
|
+
* });
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
public async about(userName: string): Promise<UserAbout | undefined> {
|
|
137
|
+
const resource = ResourceType.USER_ABOUT_BY_USERNAME;
|
|
138
|
+
|
|
139
|
+
if (userName.startsWith('@')) {
|
|
140
|
+
userName = userName.slice(1);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Fetching raw about profile
|
|
144
|
+
const response = await this.request<IUserAboutResponse>(resource, { id: userName });
|
|
145
|
+
|
|
146
|
+
// Deserializing response
|
|
147
|
+
const data = Extractors[resource](response.data);
|
|
148
|
+
|
|
149
|
+
return data;
|
|
150
|
+
}
|
|
151
|
+
|
|
55
152
|
/**
|
|
56
153
|
* Get the list affiliates of a user.
|
|
57
154
|
*
|
|
@@ -90,7 +187,7 @@ export class UserService extends FetcherService {
|
|
|
90
187
|
});
|
|
91
188
|
|
|
92
189
|
// Deserializing response
|
|
93
|
-
const data = Extractors[resource](response);
|
|
190
|
+
const data = Extractors[resource](response.data);
|
|
94
191
|
|
|
95
192
|
return data;
|
|
96
193
|
}
|
|
@@ -148,7 +245,7 @@ export class UserService extends FetcherService {
|
|
|
148
245
|
showVerifiedFollowers,
|
|
149
246
|
});
|
|
150
247
|
|
|
151
|
-
const data = Extractors[resource](response);
|
|
248
|
+
const data = Extractors[resource](response.data);
|
|
152
249
|
|
|
153
250
|
return data;
|
|
154
251
|
}
|
|
@@ -191,7 +288,7 @@ export class UserService extends FetcherService {
|
|
|
191
288
|
});
|
|
192
289
|
|
|
193
290
|
// Deserializing response
|
|
194
|
-
const data = Extractors[resource](response);
|
|
291
|
+
const data = Extractors[resource](response.data);
|
|
195
292
|
|
|
196
293
|
return data;
|
|
197
294
|
}
|
|
@@ -230,7 +327,7 @@ export class UserService extends FetcherService {
|
|
|
230
327
|
});
|
|
231
328
|
|
|
232
329
|
// Deserializing response
|
|
233
|
-
const data = Extractors[resource](response);
|
|
330
|
+
const data = Extractors[resource](response.data);
|
|
234
331
|
|
|
235
332
|
return data;
|
|
236
333
|
}
|
|
@@ -271,11 +368,86 @@ export class UserService extends FetcherService {
|
|
|
271
368
|
});
|
|
272
369
|
|
|
273
370
|
// Deserializing response
|
|
274
|
-
const data = Extractors[resource](response);
|
|
371
|
+
const data = Extractors[resource](response.data);
|
|
372
|
+
|
|
373
|
+
return data;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Changes the password of the authenticated user.
|
|
378
|
+
*
|
|
379
|
+
* @param currentPassword - The current account password.
|
|
380
|
+
* @param newPassword - The new password to set.
|
|
381
|
+
* @returns Whether the password was changed successfully.
|
|
382
|
+
*
|
|
383
|
+
* @remarks
|
|
384
|
+
* After a successful password change, this method attempts to rotate the current
|
|
385
|
+
* `apiKey` using cookies returned by Twitter. If rotation is not possible, you
|
|
386
|
+
* must re-authenticate and obtain a new `apiKey` to continue making authenticated
|
|
387
|
+
* requests.
|
|
388
|
+
*/
|
|
389
|
+
public async changePassword(currentPassword: string, newPassword: string): Promise<boolean> {
|
|
390
|
+
const resource = ResourceType.USER_PASSWORD_CHANGE;
|
|
391
|
+
|
|
392
|
+
// Changing the password
|
|
393
|
+
const response = await this.request<IUserChangePasswordResponse>(resource, {
|
|
394
|
+
changePassword: { currentPassword, newPassword },
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// Getting if password change was successful or not
|
|
398
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
399
|
+
|
|
400
|
+
// If password change was successful
|
|
401
|
+
if (data === true) {
|
|
402
|
+
// Getting the new API key
|
|
403
|
+
const newApiKey = AuthService.getApiKeyFromReponse(response);
|
|
404
|
+
|
|
405
|
+
// If new API key is generated, update current API key
|
|
406
|
+
if (newApiKey !== undefined) {
|
|
407
|
+
this.config.apiKey = newApiKey;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Getting the new CSRF token and updating current API key
|
|
411
|
+
await AuthService.refreshCsrfToken(this.config);
|
|
412
|
+
}
|
|
275
413
|
|
|
276
414
|
return data;
|
|
277
415
|
}
|
|
278
416
|
|
|
417
|
+
/**
|
|
418
|
+
* Changes the username (screen_name) of the authenticated user.
|
|
419
|
+
*
|
|
420
|
+
* @param newUsername - The new username (with or without `@`).
|
|
421
|
+
* @returns Whether the username was changed successfully.
|
|
422
|
+
*/
|
|
423
|
+
public async changeUsername(newUsername: string): Promise<boolean> {
|
|
424
|
+
const resource = ResourceType.USER_USERNAME_CHANGE;
|
|
425
|
+
|
|
426
|
+
// Strip @ prefix if present
|
|
427
|
+
const username = newUsername.startsWith('@') ? newUsername.slice(1) : newUsername;
|
|
428
|
+
|
|
429
|
+
// Username validation
|
|
430
|
+
if (username.length < 4) {
|
|
431
|
+
throw new Error('Username must be at least 4 characters long');
|
|
432
|
+
}
|
|
433
|
+
if (username.length > 15) {
|
|
434
|
+
throw new Error('Username cannot exceed 15 characters');
|
|
435
|
+
}
|
|
436
|
+
if (!/^[A-Za-z0-9_]+$/.test(username)) {
|
|
437
|
+
throw new Error('Username can only contain letters, numbers, and underscores');
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Changing the username
|
|
441
|
+
const response = await this.request<IUserSettingsResponse>(resource, {
|
|
442
|
+
username,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// Getting the updated username
|
|
446
|
+
const updatedUsername = Extractors[resource](response.data);
|
|
447
|
+
|
|
448
|
+
return updatedUsername?.toLowerCase() === username.toLowerCase();
|
|
449
|
+
}
|
|
450
|
+
|
|
279
451
|
/**
|
|
280
452
|
* Get the details of the logged in user.
|
|
281
453
|
*
|
|
@@ -386,7 +558,7 @@ export class UserService extends FetcherService {
|
|
|
386
558
|
const response = await this.request<IUserDetailsBulkResponse>(resource, { ids: id });
|
|
387
559
|
|
|
388
560
|
// Deserializing response
|
|
389
|
-
const data = Extractors[resource](response, id);
|
|
561
|
+
const data = Extractors[resource](response.data, id);
|
|
390
562
|
|
|
391
563
|
return data;
|
|
392
564
|
}
|
|
@@ -413,7 +585,7 @@ export class UserService extends FetcherService {
|
|
|
413
585
|
const response = await this.request<IUserDetailsResponse>(resource, { id: id ?? this.config.userId });
|
|
414
586
|
|
|
415
587
|
// Deserializing response
|
|
416
|
-
const data = Extractors[resource](response);
|
|
588
|
+
const data = Extractors[resource](response.data);
|
|
417
589
|
|
|
418
590
|
return data;
|
|
419
591
|
}
|
|
@@ -453,7 +625,7 @@ export class UserService extends FetcherService {
|
|
|
453
625
|
const response = await this.request<IUserFollowResponse>(ResourceType.USER_FOLLOW, { id: id });
|
|
454
626
|
|
|
455
627
|
// Deserializing the response
|
|
456
|
-
const data = Extractors[resource](response) ?? false;
|
|
628
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
457
629
|
|
|
458
630
|
return data;
|
|
459
631
|
}
|
|
@@ -494,7 +666,7 @@ export class UserService extends FetcherService {
|
|
|
494
666
|
});
|
|
495
667
|
|
|
496
668
|
// Deserializing response
|
|
497
|
-
const data = Extractors[resource](response);
|
|
669
|
+
const data = Extractors[resource](response.data);
|
|
498
670
|
|
|
499
671
|
return data;
|
|
500
672
|
}
|
|
@@ -537,7 +709,7 @@ export class UserService extends FetcherService {
|
|
|
537
709
|
});
|
|
538
710
|
|
|
539
711
|
// Deserializing response
|
|
540
|
-
const data = Extractors[resource](response);
|
|
712
|
+
const data = Extractors[resource](response.data);
|
|
541
713
|
|
|
542
714
|
return data;
|
|
543
715
|
}
|
|
@@ -580,7 +752,7 @@ export class UserService extends FetcherService {
|
|
|
580
752
|
});
|
|
581
753
|
|
|
582
754
|
// Deserializing response
|
|
583
|
-
const data = Extractors[resource](response);
|
|
755
|
+
const data = Extractors[resource](response.data);
|
|
584
756
|
|
|
585
757
|
return data;
|
|
586
758
|
}
|
|
@@ -623,7 +795,7 @@ export class UserService extends FetcherService {
|
|
|
623
795
|
});
|
|
624
796
|
|
|
625
797
|
// Deserializing response
|
|
626
|
-
const data = Extractors[resource](response);
|
|
798
|
+
const data = Extractors[resource](response.data);
|
|
627
799
|
|
|
628
800
|
return data;
|
|
629
801
|
}
|
|
@@ -665,7 +837,7 @@ export class UserService extends FetcherService {
|
|
|
665
837
|
});
|
|
666
838
|
|
|
667
839
|
// Deserializing response
|
|
668
|
-
const data = Extractors[resource](response);
|
|
840
|
+
const data = Extractors[resource](response.data);
|
|
669
841
|
|
|
670
842
|
return data;
|
|
671
843
|
}
|
|
@@ -707,7 +879,7 @@ export class UserService extends FetcherService {
|
|
|
707
879
|
});
|
|
708
880
|
|
|
709
881
|
// Deserializing response
|
|
710
|
-
const data = Extractors[resource](response);
|
|
882
|
+
const data = Extractors[resource](response.data);
|
|
711
883
|
|
|
712
884
|
return data;
|
|
713
885
|
}
|
|
@@ -750,7 +922,7 @@ export class UserService extends FetcherService {
|
|
|
750
922
|
});
|
|
751
923
|
|
|
752
924
|
// Deserializing response
|
|
753
|
-
const data = Extractors[resource](response);
|
|
925
|
+
const data = Extractors[resource](response.data);
|
|
754
926
|
|
|
755
927
|
return data;
|
|
756
928
|
}
|
|
@@ -807,7 +979,7 @@ export class UserService extends FetcherService {
|
|
|
807
979
|
});
|
|
808
980
|
|
|
809
981
|
// Deserializing response
|
|
810
|
-
const notifications = Extractors[resource](response);
|
|
982
|
+
const notifications = Extractors[resource](response.data);
|
|
811
983
|
|
|
812
984
|
// Sorting the notifications by time, from oldest to recent
|
|
813
985
|
notifications.list.sort((a, b) => new Date(a.receivedAt).valueOf() - new Date(b.receivedAt).valueOf());
|
|
@@ -864,7 +1036,7 @@ export class UserService extends FetcherService {
|
|
|
864
1036
|
});
|
|
865
1037
|
|
|
866
1038
|
// Deserializing response
|
|
867
|
-
const data = Extractors[resource](response);
|
|
1039
|
+
const data = Extractors[resource](response.data);
|
|
868
1040
|
|
|
869
1041
|
return data;
|
|
870
1042
|
}
|
|
@@ -911,7 +1083,7 @@ export class UserService extends FetcherService {
|
|
|
911
1083
|
});
|
|
912
1084
|
|
|
913
1085
|
// Deserializing response
|
|
914
|
-
const data = Extractors[resource](response);
|
|
1086
|
+
const data = Extractors[resource](response.data);
|
|
915
1087
|
|
|
916
1088
|
return data;
|
|
917
1089
|
}
|
|
@@ -954,7 +1126,7 @@ export class UserService extends FetcherService {
|
|
|
954
1126
|
});
|
|
955
1127
|
|
|
956
1128
|
// Deserializing response
|
|
957
|
-
const data = Extractors[resource](response);
|
|
1129
|
+
const data = Extractors[resource](response.data);
|
|
958
1130
|
|
|
959
1131
|
return data;
|
|
960
1132
|
}
|
|
@@ -997,7 +1169,7 @@ export class UserService extends FetcherService {
|
|
|
997
1169
|
});
|
|
998
1170
|
|
|
999
1171
|
// Deserializing response
|
|
1000
|
-
const data = Extractors[resource](response);
|
|
1172
|
+
const data = Extractors[resource](response.data);
|
|
1001
1173
|
|
|
1002
1174
|
return data;
|
|
1003
1175
|
}
|
|
@@ -1045,7 +1217,7 @@ export class UserService extends FetcherService {
|
|
|
1045
1217
|
});
|
|
1046
1218
|
|
|
1047
1219
|
// Deserializing response
|
|
1048
|
-
const data = Extractors[resource](response);
|
|
1220
|
+
const data = Extractors[resource](response.data);
|
|
1049
1221
|
|
|
1050
1222
|
return data;
|
|
1051
1223
|
}
|
|
@@ -1082,7 +1254,7 @@ export class UserService extends FetcherService {
|
|
|
1082
1254
|
const response = await this.request<IUserUnfollowResponse>(ResourceType.USER_UNFOLLOW, { id: id });
|
|
1083
1255
|
|
|
1084
1256
|
// Deserializing the response
|
|
1085
|
-
const data = Extractors[resource](response) ?? false;
|
|
1257
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
1086
1258
|
|
|
1087
1259
|
return data;
|
|
1088
1260
|
}
|
|
@@ -1147,7 +1319,59 @@ export class UserService extends FetcherService {
|
|
|
1147
1319
|
const response = await this.request<IUserProfileUpdateResponse>(resource, { profileOptions: validatedOptions });
|
|
1148
1320
|
|
|
1149
1321
|
// Deserializing the response
|
|
1150
|
-
const data = Extractors[resource](response) ?? false;
|
|
1322
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
1323
|
+
|
|
1324
|
+
return data;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* Updates the profile banner of the authenticated user.
|
|
1329
|
+
*
|
|
1330
|
+
* @param bannerBase64 - The base64-encoded banner image data.
|
|
1331
|
+
* @returns Whether the profile banner was updated successfully.
|
|
1332
|
+
*/
|
|
1333
|
+
public async updateProfileBanner(bannerBase64: string): Promise<boolean> {
|
|
1334
|
+
const resource = ResourceType.USER_PROFILE_BANNER_UPDATE;
|
|
1335
|
+
|
|
1336
|
+
const validatedBanner = this._validateBase64Payload(bannerBase64, 'Profile banner');
|
|
1337
|
+
|
|
1338
|
+
// Banner size validation (max 5 MB)
|
|
1339
|
+
const bannerSizeBytes = this._base64ByteSize(validatedBanner);
|
|
1340
|
+
if (bannerSizeBytes > 5 * 1024 * 1024) {
|
|
1341
|
+
throw new Error('Profile banner cannot exceed 5 MB');
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
const response = await this.request<IUserProfileUpdateResponse>(resource, {
|
|
1345
|
+
profileBanner: validatedBanner,
|
|
1346
|
+
});
|
|
1347
|
+
|
|
1348
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
1349
|
+
|
|
1350
|
+
return data;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
/**
|
|
1354
|
+
* Updates the profile image of the authenticated user.
|
|
1355
|
+
*
|
|
1356
|
+
* @param imageBase64 - The base64-encoded image data.
|
|
1357
|
+
* @returns Whether the profile image was updated successfully.
|
|
1358
|
+
*/
|
|
1359
|
+
public async updateProfileImage(imageBase64: string): Promise<boolean> {
|
|
1360
|
+
const resource = ResourceType.USER_PROFILE_IMAGE_UPDATE;
|
|
1361
|
+
|
|
1362
|
+
const validatedImage = this._validateBase64Payload(imageBase64, 'Profile image');
|
|
1363
|
+
|
|
1364
|
+
// Image size validation (max 2 MB)
|
|
1365
|
+
const imageSizeBytes = this._base64ByteSize(validatedImage);
|
|
1366
|
+
if (imageSizeBytes > 2 * 1024 * 1024) {
|
|
1367
|
+
throw new Error('Profile image cannot exceed 2 MB');
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
const response = await this.request<IUserProfileUpdateResponse>(resource, {
|
|
1371
|
+
profileImage: validatedImage,
|
|
1372
|
+
});
|
|
1373
|
+
|
|
1374
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
1151
1375
|
|
|
1152
1376
|
return data;
|
|
1153
1377
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AxiosProxyConfig, AxiosResponse } from 'axios';
|
|
2
|
+
|
|
1
3
|
import { IErrorHandler } from './ErrorHandler';
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -10,11 +12,34 @@ export interface IRettiwtConfig {
|
|
|
10
12
|
apiKey?: string;
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
15
|
+
* The proxy to use.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* <br>
|
|
19
|
+
* - If set to anything besides `undefined`, disables Axios' built-in environment variable-set proxy.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```
|
|
23
|
+
* // Use custom proxy config via config object
|
|
24
|
+
* {
|
|
25
|
+
* proxy: {
|
|
26
|
+
* host: '127.0.0.1',
|
|
27
|
+
* port: 8080
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // Use custom proxy config via URL
|
|
32
|
+
* {
|
|
33
|
+
* proxy: 'https://127.0.0.1:8080'
|
|
34
|
+
* }
|
|
14
35
|
*
|
|
15
|
-
*
|
|
36
|
+
* // Use Axios environment variable for proxy
|
|
37
|
+
* {
|
|
38
|
+
* proxy: undefined
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
16
41
|
*/
|
|
17
|
-
|
|
42
|
+
proxy?: AxiosProxyConfig | string | null;
|
|
18
43
|
|
|
19
44
|
/** The max wait time (in milli-seconds) for a response; if not set, Twitter server timeout is used. */
|
|
20
45
|
timeout?: number;
|
|
@@ -22,6 +47,13 @@ export interface IRettiwtConfig {
|
|
|
22
47
|
/** Whether to write logs to console or not. */
|
|
23
48
|
logging?: boolean;
|
|
24
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Optional response middleware to be executed on obtaining a successful response.
|
|
52
|
+
*
|
|
53
|
+
* @param response - The raw `AxiosReponse` object.
|
|
54
|
+
*/
|
|
55
|
+
responseMiddleware?: (response: AxiosResponse) => void | Promise<void>;
|
|
56
|
+
|
|
25
57
|
/** Optional custom error handler to define error conditions and process API/HTTP errors in responses. */
|
|
26
58
|
errorHandler?: IErrorHandler;
|
|
27
59
|
|