rettiwt-api 6.3.0-alpha.1 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/User.d.ts +1 -1
- package/dist/models/data/User.js +3 -3
- package/dist/models/data/User.js.map +1 -1
- 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/User.d.ts +2 -2
- 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/base/User.d.ts +1 -1
- 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 +5 -3
- 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/User.ts +3 -3
- 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/User.ts +2 -2
- package/src/types/data/UserAbout.ts +87 -0
- package/src/types/raw/base/Space.ts +42 -22
- package/src/types/raw/base/User.ts +1 -1
- 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
|
@@ -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
|
|
|
@@ -71,7 +71,7 @@ export interface IFetchArgs {
|
|
|
71
71
|
*
|
|
72
72
|
* @remarks
|
|
73
73
|
* - Required for all resources except {@link ResourceType.TWEET_SEARCH} and {@link ResourceType.USER_TIMELINE_RECOMMENDED}.
|
|
74
|
-
* - For {@link ResourceType.USER_DETAILS_BY_USERNAME} and {@link ResourceType.USER_SEARCH}, can be alphanumeric, while for others, is strictly numeric.
|
|
74
|
+
* - For {@link ResourceType.USER_DETAILS_BY_USERNAME}, {@link ResourceType.USER_ABOUT_BY_USERNAME}, and {@link ResourceType.USER_SEARCH}, can be alphanumeric, while for others, is strictly numeric.
|
|
75
75
|
*/
|
|
76
76
|
id?: string;
|
|
77
77
|
|
|
@@ -83,6 +83,30 @@ export interface IFetchArgs {
|
|
|
83
83
|
*/
|
|
84
84
|
ids?: string[];
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Whether to include replay information when fetching space details.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
* - Only works for {@link ResourceType.SPACE_DETAILS}.
|
|
91
|
+
*/
|
|
92
|
+
withReplays?: boolean;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Whether to include listeners information when fetching space details.
|
|
96
|
+
*
|
|
97
|
+
* @remarks
|
|
98
|
+
* - Only works for {@link ResourceType.SPACE_DETAILS}.
|
|
99
|
+
*/
|
|
100
|
+
withListeners?: boolean;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Whether to request metatags for space details.
|
|
104
|
+
*
|
|
105
|
+
* @remarks
|
|
106
|
+
* - Only works for {@link ResourceType.SPACE_DETAILS}.
|
|
107
|
+
*/
|
|
108
|
+
isMetatagsQuery?: boolean;
|
|
109
|
+
|
|
86
110
|
/**
|
|
87
111
|
* The sorting to use for tweet results.
|
|
88
112
|
*
|
|
@@ -132,6 +156,22 @@ export interface IFetchArgs {
|
|
|
132
156
|
showVerifiedFollowers?: boolean;
|
|
133
157
|
}
|
|
134
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Options specifying the data that is to be fetched for space details.
|
|
161
|
+
*
|
|
162
|
+
* @public
|
|
163
|
+
*/
|
|
164
|
+
export interface ISpaceDetailsOptions {
|
|
165
|
+
/** Whether to include replay information. */
|
|
166
|
+
withReplays?: boolean;
|
|
167
|
+
|
|
168
|
+
/** Whether to include listeners information. */
|
|
169
|
+
withListeners?: boolean;
|
|
170
|
+
|
|
171
|
+
/** Whether the request is a metatags query. */
|
|
172
|
+
isMetatagsQuery?: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
135
175
|
/**
|
|
136
176
|
* The filter to be used for searching tweets.
|
|
137
177
|
*
|
|
@@ -20,9 +20,20 @@ export interface IPostArgs {
|
|
|
20
20
|
* - {@link ResourceType.TWEET_UNRETWEET}
|
|
21
21
|
* - {@link ResourceType.USER_FOLLOW}
|
|
22
22
|
* - {@link ResourceType.USER_UNFOLLOW}
|
|
23
|
+
*
|
|
24
|
+
* For {@link ResourceType.USER_USERNAME_CHANGE}, use {@link IPostArgs.username}.
|
|
25
|
+
* `id` is still accepted for backward compatibility.
|
|
23
26
|
*/
|
|
24
27
|
id?: string;
|
|
25
28
|
|
|
29
|
+
/**
|
|
30
|
+
* The new username to set.
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* Required only when changing username using {@link ResourceType.USER_USERNAME_CHANGE}.
|
|
34
|
+
*/
|
|
35
|
+
username?: string;
|
|
36
|
+
|
|
26
37
|
/**
|
|
27
38
|
* The tweet that is to be posted.
|
|
28
39
|
*
|
|
@@ -67,6 +78,30 @@ export interface IPostArgs {
|
|
|
67
78
|
* Required only when updating user profile using {@link ResourceType.USER_PROFILE_UPDATE}
|
|
68
79
|
*/
|
|
69
80
|
profileOptions?: IProfileUpdateOptions;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Base64-encoded profile image data.
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* Required only when updating profile image using {@link ResourceType.USER_PROFILE_IMAGE_UPDATE}.
|
|
87
|
+
*/
|
|
88
|
+
profileImage?: string;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Base64-encoded profile banner data.
|
|
92
|
+
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* Required only when updating profile banner using {@link ResourceType.USER_PROFILE_BANNER_UPDATE}.
|
|
95
|
+
*/
|
|
96
|
+
profileBanner?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Password change arguments.
|
|
100
|
+
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* Required only when changing password using {@link ResourceType.USER_PASSWORD_CHANGE}.
|
|
103
|
+
*/
|
|
104
|
+
changePassword?: IChangePasswordArgs;
|
|
70
105
|
}
|
|
71
106
|
|
|
72
107
|
/**
|
|
@@ -98,7 +133,8 @@ export interface INewTweet {
|
|
|
98
133
|
* The text for the tweet to be created.
|
|
99
134
|
*
|
|
100
135
|
* @remarks
|
|
101
|
-
* Length of the tweet must be \<= 280 characters.
|
|
136
|
+
* Length of the tweet must be \<= 280 characters for non-premium accounts.
|
|
137
|
+
* X Premium (Blue) accounts can post longer tweets (up to 25,000 characters).
|
|
102
138
|
*/
|
|
103
139
|
text?: string;
|
|
104
140
|
}
|
|
@@ -140,3 +176,16 @@ export interface IUploadArgs {
|
|
|
140
176
|
*/
|
|
141
177
|
size?: number;
|
|
142
178
|
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Arguments for changing the account password.
|
|
182
|
+
*
|
|
183
|
+
* @public
|
|
184
|
+
*/
|
|
185
|
+
export interface IChangePasswordArgs {
|
|
186
|
+
/** The current account password. */
|
|
187
|
+
currentPassword: string;
|
|
188
|
+
|
|
189
|
+
/** The new password to set. */
|
|
190
|
+
newPassword: string;
|
|
191
|
+
}
|