@youmind-openlab/rettiwt-api 1.0.3 → 1.0.4
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/.devcontainer/devcontainer.json +20 -0
- package/README.md +326 -256
- package/dist/collections/Extractors.d.ts +9 -2
- package/dist/collections/Extractors.js +8 -1
- package/dist/collections/Extractors.js.map +1 -1
- package/dist/collections/Groups.js +5 -0
- package/dist/collections/Groups.js.map +1 -1
- package/dist/collections/Requests.js +5 -0
- package/dist/collections/Requests.js.map +1 -1
- package/dist/commands/User.js +126 -0
- package/dist/commands/User.js.map +1 -1
- package/dist/enums/Resource.d.ts +6 -1
- package/dist/enums/Resource.js +5 -0
- package/dist/enums/Resource.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js.map +1 -1
- package/dist/models/args/PostArgs.d.ts +16 -1
- package/dist/models/args/PostArgs.js +44 -1
- package/dist/models/args/PostArgs.js.map +1 -1
- 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 +25 -0
- package/dist/requests/User.js +59 -0
- package/dist/requests/User.js.map +1 -1
- package/dist/services/public/FetcherService.d.ts +14 -2
- package/dist/services/public/FetcherService.js +21 -6
- package/dist/services/public/FetcherService.js.map +1 -1
- package/dist/services/public/TweetService.js +9 -6
- package/dist/services/public/TweetService.js.map +1 -1
- package/dist/services/public/UserService.d.ts +45 -0
- package/dist/services/public/UserService.js +211 -0
- package/dist/services/public/UserService.js.map +1 -1
- package/dist/types/args/PostArgs.d.ts +44 -1
- package/dist/types/raw/tweet/Post.d.ts +16 -1
- 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 +4 -2
- package/src/collections/Extractors.ts +15 -3
- package/src/collections/Groups.ts +5 -0
- package/src/collections/Requests.ts +6 -0
- package/src/commands/User.ts +146 -0
- package/src/enums/Resource.ts +5 -0
- package/src/index.ts +2 -0
- package/src/models/args/PostArgs.ts +49 -1
- package/src/requests/Tweet.ts +59 -0
- package/src/requests/User.ts +63 -0
- package/src/services/public/FetcherService.ts +27 -7
- package/src/services/public/TweetService.ts +10 -7
- package/src/services/public/UserService.ts +265 -0
- package/src/types/args/PostArgs.ts +50 -1
- package/src/types/raw/tweet/Post.ts +19 -1
- 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/.claude/settings.local.json +0 -9
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
|
|
3
|
+
import { Cookie } from 'cookiejar';
|
|
4
|
+
|
|
1
5
|
import { Extractors } from '../../collections/Extractors';
|
|
2
6
|
import { RawAnalyticsGranularity, RawAnalyticsMetric } from '../../enums/raw/Analytics';
|
|
3
7
|
import { ResourceType } from '../../enums/Resource';
|
|
4
8
|
import { ProfileUpdateOptions } from '../../models/args/ProfileArgs';
|
|
9
|
+
import { AuthCredential } from '../../models/auth/AuthCredential';
|
|
5
10
|
import { Analytics } from '../../models/data/Analytics';
|
|
6
11
|
import { BookmarkFolder } from '../../models/data/BookmarkFolder';
|
|
7
12
|
import { CursoredData } from '../../models/data/CursoredData';
|
|
@@ -18,6 +23,7 @@ import { IUserAnalyticsResponse } from '../../types/raw/user/Analytics';
|
|
|
18
23
|
import { IUserBookmarkFoldersResponse } from '../../types/raw/user/BookmarkFolders';
|
|
19
24
|
import { IUserBookmarkFolderTweetsResponse } from '../../types/raw/user/BookmarkFolderTweets';
|
|
20
25
|
import { IUserBookmarksResponse } from '../../types/raw/user/Bookmarks';
|
|
26
|
+
import { IUserChangePasswordResponse } from '../../types/raw/user/ChangePassword';
|
|
21
27
|
import { IUserDetailsResponse } from '../../types/raw/user/Details';
|
|
22
28
|
import { IUserDetailsBulkResponse } from '../../types/raw/user/DetailsBulk';
|
|
23
29
|
import { IUserFollowResponse } from '../../types/raw/user/Follow';
|
|
@@ -32,11 +38,14 @@ import { IUserNotificationsResponse } from '../../types/raw/user/Notifications';
|
|
|
32
38
|
import { IUserProfileUpdateResponse } from '../../types/raw/user/ProfileUpdate';
|
|
33
39
|
import { IUserRecommendedResponse } from '../../types/raw/user/Recommended';
|
|
34
40
|
import { IUserSearchResponse } from '../../types/raw/user/Search';
|
|
41
|
+
import { IUserSettingsResponse } from '../../types/raw/user/Settings';
|
|
35
42
|
import { IUserSubscriptionsResponse } from '../../types/raw/user/Subscriptions';
|
|
36
43
|
import { IUserTweetsResponse } from '../../types/raw/user/Tweets';
|
|
37
44
|
import { IUserTweetsAndRepliesResponse } from '../../types/raw/user/TweetsAndReplies';
|
|
38
45
|
import { IUserUnfollowResponse } from '../../types/raw/user/Unfollow';
|
|
39
46
|
|
|
47
|
+
import { AuthService } from '../internal/AuthService';
|
|
48
|
+
|
|
40
49
|
import { FetcherService } from './FetcherService';
|
|
41
50
|
|
|
42
51
|
/**
|
|
@@ -54,6 +63,149 @@ export class UserService extends FetcherService {
|
|
|
54
63
|
super(config);
|
|
55
64
|
}
|
|
56
65
|
|
|
66
|
+
private _base64ByteSize(base64Data: string): number {
|
|
67
|
+
const paddingMatch = base64Data.match(/=+$/);
|
|
68
|
+
const paddingLength = paddingMatch ? paddingMatch[0].length : 0;
|
|
69
|
+
|
|
70
|
+
return (base64Data.length * 3) / 4 - paddingLength;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private _normalizeBase64(payload: string): string {
|
|
74
|
+
const trimmedPayload = payload.trim();
|
|
75
|
+
const lowerCasePayload = trimmedPayload.toLowerCase();
|
|
76
|
+
const base64Marker = ';base64,';
|
|
77
|
+
|
|
78
|
+
if (lowerCasePayload.startsWith('data:')) {
|
|
79
|
+
const markerIndex = lowerCasePayload.indexOf(base64Marker);
|
|
80
|
+
if (markerIndex !== -1) {
|
|
81
|
+
return trimmedPayload.slice(markerIndex + base64Marker.length).trim();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return trimmedPayload;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private _refreshApiKeyFromResponseCookies(setCookieHeader: string | string[] | undefined): void {
|
|
89
|
+
if (!this.config.apiKey || !setCookieHeader) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const requiredCookieNames = new Set(['auth_token', 'ct0', 'kdt', 'twid']);
|
|
94
|
+
const currentCookieString = AuthService.decodeCookie(this.config.apiKey);
|
|
95
|
+
const cookiePairs = this._splitSetCookieHeader(setCookieHeader);
|
|
96
|
+
const cookiesMap = new Map<string, string>();
|
|
97
|
+
|
|
98
|
+
for (const cookieEntry of currentCookieString.split(';')) {
|
|
99
|
+
const trimmedEntry = cookieEntry.trim();
|
|
100
|
+
const separatorIndex = trimmedEntry.indexOf('=');
|
|
101
|
+
|
|
102
|
+
if (!trimmedEntry || separatorIndex < 1) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const key = trimmedEntry.slice(0, separatorIndex).trim();
|
|
107
|
+
const value = trimmedEntry.slice(separatorIndex + 1).trim();
|
|
108
|
+
if (!key || !value || !requiredCookieNames.has(key)) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
cookiesMap.set(key, value);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let hasUpdate = false;
|
|
116
|
+
for (const cookiePair of cookiePairs) {
|
|
117
|
+
const cookieValuePair = cookiePair.split(';', 1)[0]?.trim();
|
|
118
|
+
const separatorIndex = cookieValuePair?.indexOf('=') ?? -1;
|
|
119
|
+
|
|
120
|
+
if (!cookieValuePair || separatorIndex < 1) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const key = cookieValuePair.slice(0, separatorIndex).trim();
|
|
125
|
+
const value = cookieValuePair.slice(separatorIndex + 1).trim();
|
|
126
|
+
if (!key || !value || !requiredCookieNames.has(key)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
cookiesMap.set(key, value);
|
|
131
|
+
hasUpdate = true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!hasUpdate || !cookiesMap.has('twid')) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let mergedCookieString = '';
|
|
139
|
+
for (const [key, value] of cookiesMap.entries()) {
|
|
140
|
+
mergedCookieString += `${key}=${value};`;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!mergedCookieString) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
this.config.apiKey = AuthService.encodeCookie(mergedCookieString);
|
|
149
|
+
} catch {
|
|
150
|
+
// Ignore cookie rotation errors and leave existing apiKey unchanged.
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Fetches a fresh ct0 (CSRF token) from Twitter by making a lightweight
|
|
156
|
+
* authenticated request, then rotates the apiKey with the updated cookie.
|
|
157
|
+
*/
|
|
158
|
+
private async _refreshCsrfToken(): Promise<void> {
|
|
159
|
+
if (!this.config.apiKey) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const cred = new AuthCredential(
|
|
165
|
+
AuthService.decodeCookie(this.config.apiKey)
|
|
166
|
+
.split(';')
|
|
167
|
+
.map((item) => new Cookie(item)),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const refreshResponse = await axios.get('https://x.com/i/api/1.1/account/verify_credentials.json', {
|
|
171
|
+
headers: {
|
|
172
|
+
...cred.toHeader(),
|
|
173
|
+
authorization:
|
|
174
|
+
'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA',
|
|
175
|
+
},
|
|
176
|
+
httpAgent: this.config.httpsAgent,
|
|
177
|
+
httpsAgent: this.config.httpsAgent,
|
|
178
|
+
validateStatus: () => true,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
this._refreshApiKeyFromResponseCookies(refreshResponse.headers['set-cookie']);
|
|
182
|
+
} catch {
|
|
183
|
+
// Best-effort: if ct0 refresh fails, leave apiKey as-is
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private _splitSetCookieHeader(setCookieHeader: string | string[]): string[] {
|
|
188
|
+
if (Array.isArray(setCookieHeader)) {
|
|
189
|
+
return setCookieHeader;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return setCookieHeader.split(/,(?=\s*[^;,]+=)/g);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private _validateBase64Payload(payload: string, fieldName: string): string {
|
|
196
|
+
const normalizedPayload = this._normalizeBase64(payload).replace(/\s+/g, '');
|
|
197
|
+
|
|
198
|
+
if (normalizedPayload.length === 0) {
|
|
199
|
+
throw new Error(`${fieldName} cannot be empty`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(normalizedPayload)) {
|
|
203
|
+
throw new Error(`${fieldName} must be valid base64`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return normalizedPayload;
|
|
207
|
+
}
|
|
208
|
+
|
|
57
209
|
/**
|
|
58
210
|
* Get the about profile of a user.
|
|
59
211
|
*
|
|
@@ -319,6 +471,67 @@ export class UserService extends FetcherService {
|
|
|
319
471
|
return data;
|
|
320
472
|
}
|
|
321
473
|
|
|
474
|
+
/**
|
|
475
|
+
* Changes the password of the authenticated user.
|
|
476
|
+
*
|
|
477
|
+
* @param currentPassword - The current account password.
|
|
478
|
+
* @param newPassword - The new password to set.
|
|
479
|
+
* @returns Whether the password was changed successfully.
|
|
480
|
+
*
|
|
481
|
+
* @remarks
|
|
482
|
+
* After a successful password change, this method attempts to rotate the current
|
|
483
|
+
* `apiKey` using cookies returned by Twitter. If rotation is not possible, you
|
|
484
|
+
* must re-authenticate and obtain a new `apiKey` to continue making authenticated
|
|
485
|
+
* requests.
|
|
486
|
+
*/
|
|
487
|
+
public async changePassword(currentPassword: string, newPassword: string): Promise<boolean> {
|
|
488
|
+
const resource = ResourceType.USER_PASSWORD_CHANGE;
|
|
489
|
+
|
|
490
|
+
const response = await this.requestWithResponse<IUserChangePasswordResponse>(resource, {
|
|
491
|
+
changePassword: { currentPassword, newPassword },
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
const data = Extractors[resource](response.data) ?? false;
|
|
495
|
+
if (data) {
|
|
496
|
+
this._refreshApiKeyFromResponseCookies(response.headers['set-cookie']);
|
|
497
|
+
await this._refreshCsrfToken();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return data;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Changes the username (screen_name) of the authenticated user.
|
|
505
|
+
*
|
|
506
|
+
* @param newUsername - The new username (with or without `@`).
|
|
507
|
+
* @returns Whether the username was changed successfully.
|
|
508
|
+
*/
|
|
509
|
+
public async changeUsername(newUsername: string): Promise<boolean> {
|
|
510
|
+
const resource = ResourceType.USER_USERNAME_CHANGE;
|
|
511
|
+
|
|
512
|
+
// Strip @ prefix if present
|
|
513
|
+
const username = newUsername.startsWith('@') ? newUsername.slice(1) : newUsername;
|
|
514
|
+
|
|
515
|
+
// Username validation
|
|
516
|
+
if (username.length < 4) {
|
|
517
|
+
throw new Error('Username must be at least 4 characters long');
|
|
518
|
+
}
|
|
519
|
+
if (username.length > 15) {
|
|
520
|
+
throw new Error('Username cannot exceed 15 characters');
|
|
521
|
+
}
|
|
522
|
+
if (!/^[A-Za-z0-9_]+$/.test(username)) {
|
|
523
|
+
throw new Error('Username can only contain letters, numbers, and underscores');
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const response = await this.request<IUserSettingsResponse>(resource, {
|
|
527
|
+
username,
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
const updatedUsername = Extractors[resource](response);
|
|
531
|
+
|
|
532
|
+
return updatedUsername?.toLowerCase() === username.toLowerCase();
|
|
533
|
+
}
|
|
534
|
+
|
|
322
535
|
/**
|
|
323
536
|
* Get the details of the logged in user.
|
|
324
537
|
*
|
|
@@ -1194,4 +1407,56 @@ export class UserService extends FetcherService {
|
|
|
1194
1407
|
|
|
1195
1408
|
return data;
|
|
1196
1409
|
}
|
|
1410
|
+
|
|
1411
|
+
/**
|
|
1412
|
+
* Updates the profile banner of the authenticated user.
|
|
1413
|
+
*
|
|
1414
|
+
* @param bannerBase64 - The base64-encoded banner image data.
|
|
1415
|
+
* @returns Whether the profile banner was updated successfully.
|
|
1416
|
+
*/
|
|
1417
|
+
public async updateProfileBanner(bannerBase64: string): Promise<boolean> {
|
|
1418
|
+
const resource = ResourceType.USER_PROFILE_BANNER_UPDATE;
|
|
1419
|
+
|
|
1420
|
+
const validatedBanner = this._validateBase64Payload(bannerBase64, 'Profile banner');
|
|
1421
|
+
|
|
1422
|
+
// Banner size validation (max 5 MB)
|
|
1423
|
+
const bannerSizeBytes = this._base64ByteSize(validatedBanner);
|
|
1424
|
+
if (bannerSizeBytes > 5 * 1024 * 1024) {
|
|
1425
|
+
throw new Error('Profile banner cannot exceed 5 MB');
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
const response = await this.request<IUserProfileUpdateResponse>(resource, {
|
|
1429
|
+
profileBanner: validatedBanner,
|
|
1430
|
+
});
|
|
1431
|
+
|
|
1432
|
+
const data = Extractors[resource](response) ?? false;
|
|
1433
|
+
|
|
1434
|
+
return data;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
/**
|
|
1438
|
+
* Updates the profile image of the authenticated user.
|
|
1439
|
+
*
|
|
1440
|
+
* @param imageBase64 - The base64-encoded image data.
|
|
1441
|
+
* @returns Whether the profile image was updated successfully.
|
|
1442
|
+
*/
|
|
1443
|
+
public async updateProfileImage(imageBase64: string): Promise<boolean> {
|
|
1444
|
+
const resource = ResourceType.USER_PROFILE_IMAGE_UPDATE;
|
|
1445
|
+
|
|
1446
|
+
const validatedImage = this._validateBase64Payload(imageBase64, 'Profile image');
|
|
1447
|
+
|
|
1448
|
+
// Image size validation (max 2 MB)
|
|
1449
|
+
const imageSizeBytes = this._base64ByteSize(validatedImage);
|
|
1450
|
+
if (imageSizeBytes > 2 * 1024 * 1024) {
|
|
1451
|
+
throw new Error('Profile image cannot exceed 2 MB');
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
const response = await this.request<IUserProfileUpdateResponse>(resource, {
|
|
1455
|
+
profileImage: validatedImage,
|
|
1456
|
+
});
|
|
1457
|
+
|
|
1458
|
+
const data = Extractors[resource](response) ?? false;
|
|
1459
|
+
|
|
1460
|
+
return data;
|
|
1461
|
+
}
|
|
1197
1462
|
}
|
|
@@ -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
|
}
|
|
@@ -143,3 +179,16 @@ export interface IUploadArgs {
|
|
|
143
179
|
*/
|
|
144
180
|
size?: number;
|
|
145
181
|
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Arguments for changing the account password.
|
|
185
|
+
*
|
|
186
|
+
* @public
|
|
187
|
+
*/
|
|
188
|
+
export interface IChangePasswordArgs {
|
|
189
|
+
/** The current account password. */
|
|
190
|
+
currentPassword: string;
|
|
191
|
+
|
|
192
|
+
/** The new password to set. */
|
|
193
|
+
newPassword: string;
|
|
194
|
+
}
|
|
@@ -10,7 +10,8 @@ export interface ITweetPostResponse {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
interface Data {
|
|
13
|
-
create_tweet
|
|
13
|
+
create_tweet?: CreateTweet;
|
|
14
|
+
create_note_tweet?: CreateTweet;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
interface CreateTweet {
|
|
@@ -148,3 +149,20 @@ interface UserMention {
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
interface UnmentionInfo {}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* The raw data received after creating a note tweet (long-form tweet for X Premium accounts).
|
|
155
|
+
*
|
|
156
|
+
* @public
|
|
157
|
+
*/
|
|
158
|
+
export interface ITweetPostNoteResponse {
|
|
159
|
+
data: NoteTweetData;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
interface NoteTweetData {
|
|
163
|
+
notetweet_create: NoteTweetCreate;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
interface NoteTweetCreate {
|
|
167
|
+
tweet_results: TweetResults;
|
|
168
|
+
}
|
|
@@ -39,6 +39,7 @@ export interface IUserProfileUpdateResponse {
|
|
|
39
39
|
profile_image_url: string;
|
|
40
40
|
profile_image_url_https: string;
|
|
41
41
|
profile_banner_url: string;
|
|
42
|
+
profile_banner_url_https?: string;
|
|
42
43
|
profile_link_color: string;
|
|
43
44
|
profile_sidebar_border_color: string;
|
|
44
45
|
profile_sidebar_fill_color: string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The raw data received from the account settings endpoint.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export interface IUserSettingsResponse {
|
|
9
|
+
screen_name: string;
|
|
10
|
+
protected: boolean;
|
|
11
|
+
language: string;
|
|
12
|
+
geo_enabled: boolean;
|
|
13
|
+
discoverable_by_email: boolean;
|
|
14
|
+
discoverable_by_mobile_phone: boolean;
|
|
15
|
+
use_cookie_personalization: boolean;
|
|
16
|
+
sleep_time: {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
end_time: any;
|
|
19
|
+
start_time: any;
|
|
20
|
+
};
|
|
21
|
+
display_sensitive_media: boolean;
|
|
22
|
+
allow_media_tagging: string;
|
|
23
|
+
}
|