emusks 0.0.2 → 2.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 +4 -277
- package/build/graphql.js +24 -0
- package/build/v1.1.js +28 -0
- package/build/v2.js +28 -0
- package/package.json +16 -8
- package/src/clients.js +62 -0
- package/src/cycletls.js +26 -0
- package/src/flow.js +399 -0
- package/src/graphql.js +70 -0
- package/src/helpers/account.js +271 -0
- package/src/helpers/bookmarks.js +120 -0
- package/src/helpers/communities.js +271 -0
- package/src/helpers/dms.js +131 -0
- package/src/helpers/index.js +32 -0
- package/src/helpers/lists.js +229 -0
- package/src/helpers/media.js +290 -0
- package/src/helpers/notifications.js +49 -0
- package/src/helpers/search.js +129 -0
- package/src/helpers/spaces.js +55 -0
- package/src/helpers/syndication.js +33 -0
- package/src/helpers/timelines.js +84 -0
- package/src/helpers/topics.js +99 -0
- package/src/helpers/trends.js +86 -0
- package/src/helpers/tweets.js +405 -0
- package/src/helpers/users.js +321 -0
- package/src/index.js +125 -55
- package/src/parsers/timeline.js +141 -0
- package/src/parsers/tweet.js +9 -2
- package/src/static/graphql.js +1 -0
- package/src/static/v1.1.js +1 -0
- package/src/static/v2.js +1 -0
- package/src/v1.1.js +64 -0
- package/src/v2.js +64 -0
- package/src/methods/bookmarks.js +0 -91
- package/src/methods/follow.js +0 -88
- package/src/methods/like.js +0 -87
- package/src/methods/notifications.js +0 -121
- package/src/methods/retweet.js +0 -91
- package/src/methods/search.js +0 -124
- package/src/methods/timeline.js +0 -215
- package/src/methods/tweet.js +0 -396
- package/src/methods/users.js +0 -209
- package/src/utils/headers.js +0 -23
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {"account/multi/list":["get","https://api.x.com/1.1/account/multi/list.json"],"onboarding/sso_init":["post","https://api.x.com/1.1/onboarding/sso_init.json"],"account/logout":["post","https://api.x.com/1.1/account/logout.json"],"account/multi/clean":["post","https://api.x.com/1.1/account/multi/clean.json"],"account/multi/add":["post","https://api.x.com/1.1/account/multi/add.json"],"account/multi/switch":["post","https://api.x.com/1.1/account/multi/switch.json"],"account/multi/logout_all":["post","https://api.x.com/1.1/account/multi/logout_all.json"],"dm/welcome_messages/add_to_conversation":["post","https://api.x.com/1.1/dm/welcome_messages/add_to_conversation.json"],"dm/conversation/bulk_delete":["post","https://api.x.com/1.1/dm/conversation/bulk_delete.json"],"dm/edit":["post","https://api.x.com/1.1/dm/edit.json"],"dm/conversation":["get","https://api.x.com/1.1/dm/conversation.json"],"dm/inbox_initial_state":["get","https://api.x.com/1.1/dm/inbox_initial_state.json"],"dm/user_updates":["get","https://api.x.com/1.1/dm/user_updates.json"],"dm/search/query":["post","https://api.x.com/1.1/dm/search/query.json"],"dm/user/update_relationship_state":["post","https://api.x.com/1.1/dm/user/update_relationship_state.json"],"dm/permissions":["get","https://api.x.com/1.1/dm/permissions.json"],"dm/permissions/secret":["get","https://api.x.com/1.1/dm/permissions/secret.json"],"direct_messages/report_spam":["post","https://api.x.com/1.1/direct_messages/report_spam.json"],"dm/report":["post","https://api.x.com/1.1/dm/report.json"],"dm/update_last_seen_event_id":["post","https://api.x.com/1.1/dm/update_last_seen_event_id.json"],"friendships/incoming":["get","https://api.x.com/1.1/friendships/incoming.json"],"friends/list":["get","https://api.x.com/1.1/friends/list.json"],"friends/following/list":["get","https://api.x.com/1.1/friends/following/list.json"],"friendships/accept":["post","https://api.x.com/1.1/friendships/accept.json"],"friendships/deny":["post","https://api.x.com/1.1/friendships/deny.json"],"friendships/update":["post","https://api.x.com/1.1/friendships/update.json"],"friendships/create_all":["post","https://api.x.com/1.1/friendships/create_all.json"],"friendships/destroy_all":["post","https://api.x.com/1.1/friendships/destroy_all.json"],"jot/external_referer":["post","https://api.x.com/1.1/jot/external_referer.json"],"lists/memberships":["get","https://api.x.com/1.1/lists/memberships.json"],"onboarding/task":["post","https://api.x.com/1.1/onboarding/task.json"],"onboarding/contacts_authorize":["post","https://api.x.com/1.1/onboarding/contacts_authorize.json"],"onboarding/contacts_import_status":["get","https://api.x.com/1.1/onboarding/contacts_import_status.json"],"onboarding/verification_status":["get","https://api.x.com/1.1/onboarding/verification_status.json"],"onboarding/referrer":["post","https://api.x.com/1.1/onboarding/referrer.json"],"contacts/destroy/all":["post","https://api.x.com/1.1/contacts/destroy/all.json"],"onboarding/begin_verification":["post","https://api.x.com/1.1/onboarding/begin_verification.json"],"onboarding/verify":["post","https://api.x.com/1.1/onboarding/verify.json"],"onboarding/fetch_user_recommendations":["post","https://api.x.com/1.1/onboarding/fetch_user_recommendations.json"],"promoted_content/log":["post","https://api.x.com/1.1/promoted_content/log.json"],"get:account/settings":["get","https://api.x.com/1.1/account/settings.json"],"post:account/settings":["post","https://api.x.com/1.1/account/settings.json"],"sso/delete_connection":["post","https://api.x.com/1.1/sso/delete_connection.json"],"account/remove_profile_banner":["post","https://api.x.com/1.1/account/remove_profile_banner.json"],"account/update_profile_image":["post","https://api.x.com/1.1/account/update_profile_image.json"],"account/update_profile_banner":["post","https://api.x.com/1.1/account/update_profile_banner.json"],"account/deactivate":["post","https://api.x.com/1.1/account/deactivate.json"],"account/verify_password":["post","https://api.x.com/1.1/account/verify_password.json"],"application/rate_limit_status":["get","https://api.x.com/1.1/application/rate_limit_status.json"],"hashflags":["get","https://api.x.com/1.1/hashflags.json"],"geo/delete_location_data":["post","https://api.x.com/1.1/geo/delete_location_data.json"],"get:mutes/advanced_filters":["get","https://api.x.com/1.1/mutes/advanced_filters.json"],"post:mutes/advanced_filters":["post","https://api.x.com/1.1/mutes/advanced_filters.json"],"account/update_profile":["post","https://api.x.com/1.1/account/update_profile.json"],"oauth/list":["get","https://api.x.com/1.1/oauth/list.json"],"oauth/revoke":["post","https://api.x.com/1.1/oauth/revoke.json"],"account/change_password":["post","https://x.com/i/api/1.1/account/change_password.json"],"trends/available":["get","https://api.x.com/1.1/trends/available.json"],"get:account/backup_code":["get","https://api.x.com/1.1/account/backup_code.json"],"post:account/backup_code":["post","https://api.x.com/1.1/account/backup_code.json"],"account/login_verification/temporary_password":["post","https://api.x.com/1.1/account/login_verification/temporary_password.json"],"account/login_verification_enrollment":["delete","https://api.x.com/1.1/account/login_verification_enrollment.json"],"account/login_verification/remove_method":["post","https://api.x.com/1.1/account/login_verification/remove_method.json"],"account/login_verification/rename_security_key_method":["post","https://api.x.com/1.1/account/login_verification/rename_security_key_method.json"],"search/typeahead":["get","https://api.x.com/1.1/search/typeahead.json"],"friendships/create":["post","https://api.x.com/1.1/friendships/create.json"],"friendships/destroy":["post","https://api.x.com/1.1/friendships/destroy.json"],"friendships/cancel":["post","https://api.x.com/1.1/friendships/cancel.json"],"blocks/create":["post","https://api.x.com/1.1/blocks/create.json"],"blocks/destroy":["post","https://api.x.com/1.1/blocks/destroy.json"],"mutes/users/create":["post","https://api.x.com/1.1/mutes/users/create.json"],"mutes/users/destroy":["post","https://api.x.com/1.1/mutes/users/destroy.json"],"users/lookup":["get","https://api.x.com/1.1/users/lookup.json"],"users/email_phone_info":["get","https://api.x.com/1.1/users/email_phone_info.json"],"account/resend_confirmation_email":["post","https://api.x.com/1.1/account/resend_confirmation_email.json"],"device/unregister":["post","https://api.x.com/1.1/device/unregister.json"],"notifications/settings/save":["post","https://api.x.com/1.1/notifications/settings/save.json"],"notifications/settings/login":["post","https://api.x.com/1.1/notifications/settings/login.json"],"notifications/settings/checkin":["post","https://api.x.com/1.1/notifications/settings/checkin.json"],"notifications/settings/logout":["post","https://api.x.com/1.1/notifications/settings/logout.json"],"help/settings":["get","https://api.x.com/1.1/help/settings.json"],"media/metadata/create":["post","https://api.x.com/1.1/media/metadata/create.json"],"media/subtitles/create":["post","https://api.x.com/1.1/media/subtitles/create.json"],"account/personalization/twitter_interests":["get","https://api.x.com/1.1/account/personalization/twitter_interests.json"],"account/personalization/email_your_data":["post","https://api.x.com/1.1/account/personalization/email_your_data.json"],"account/personalization/set_optout_cookies":["get","https://api.x.com/1.1/account/personalization/set_optout_cookies.json"],"live_pipeline/update_subscriptions":["post","https://api.x.com/1.1/live_pipeline/update_subscriptions.json"],"geo/places":["get","https://api.x.com/1.1/geo/places.json"],"users/recommendations":["get","https://api.x.com/1.1/users/recommendations.json"],"saved_searches/list":["get","https://api.x.com/1.1/saved_searches/list.json"],"saved_searches/create":["post","https://api.x.com/1.1/saved_searches/create.json"],"keyregistry/register":["post","https://api.x.com/1.1/keyregistry/register.json"],"account/not_my_account/disassociate":["post","https://api.x.com/1.1/account/not_my_account/disassociate.json"],"account/not_my_account/get_masked_data":["get","https://api.x.com/1.1/account/not_my_account/get_masked_data.json"],"collections/entries":["get","https://api.x.com/1.1/collections/entries.json"],"foundmedia/categories":["get","https://api.x.com/1.1/foundmedia/categories.json"],"foundmedia/search":["get","https://api.x.com/1.1/foundmedia/search.json"],"get:account/user_twitter_data":["get","https://api.x.com/1.1/account/user_twitter_data.json"],"put:account/user_twitter_data":["put","https://api.x.com/1.1/account/user_twitter_data.json"],"contacts/addressbook":["get","https://api.x.com/1.1/contacts/addressbook.json"],"mutes/keywords/list":["get","https://api.x.com/1.1/mutes/keywords/list.json"],"mutes/keywords/destroy":["post","https://api.x.com/1.1/mutes/keywords/destroy.json"],"mutes/keywords/update":["post","https://api.x.com/1.1/mutes/keywords/update.json"],"onboarding/bounce":["post","https://api.x.com/1.1/onboarding/bounce.json"],"report/flow":["post","https://api.x.com/1.1/report/flow.json"],"account/password_strength":["post","https://api.x.com/1.1/account/password_strength.json"],"users/phone_number_available":["get","https://api.x.com/1.1/users/phone_number_available.json"],"users/email_available":["get","https://x.com/i/api/1.1/users/email_available.json"],"moments/create":["post","https://api.x.com/1.1/moments/create.json"]};
|
package/src/static/v2.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {"badge_count/badge_count":["get","https://x.com/i/api/2/badge_count/badge_count.json"],"guide/get_explore_settings":["get","https://x.com/i/api/2/guide/get_explore_settings.json"],"guide/set_explore_settings":["post","https://x.com/i/api/2/guide/set_explore_settings.json"],"guide/explore_locations_with_auto_complete":["get","https://x.com/i/api/2/guide/explore_locations_with_auto_complete.json"],"timeline/reactive":["get","https://x.com/i/api/2/timeline/reactive.json"],"moments/list_user_moments":["get","https://x.com/i/api/2/moments/list_user_moments.json"],"guide":["get","https://x.com/i/api/2/guide.json"],"guide/topic":["get","https://x.com/i/api/2/guide/topic.json"],"onboarding/fetch_user_recommendations_urt":["get","https://x.com/i/api/2/onboarding/fetch_user_recommendations_urt.json"],"people_discovery/modules_urt":["get","https://x.com/i/api/2/people_discovery/modules_urt.json"],"search/adaptive":["get","https://x.com/i/api/2/search/adaptive.json"],"timeline/fixture":["get","https://x.com/i/api/2/timeline/fixture.json"]};
|
package/src/v1.1.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import getCycleTLS from "./cycletls.js";
|
|
2
|
+
import v1_1Api from "./static/v1.1.js";
|
|
3
|
+
|
|
4
|
+
export default async function v1_1(queryName, { params, body, headers } = {}) {
|
|
5
|
+
let entry = v1_1Api[queryName];
|
|
6
|
+
if (!entry) {
|
|
7
|
+
throw new Error(`v1.1 endpoint ${queryName} not found`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const [method, baseUrl] = entry;
|
|
11
|
+
|
|
12
|
+
let finalUrl = baseUrl;
|
|
13
|
+
|
|
14
|
+
if (params && Object.keys(params).length) {
|
|
15
|
+
const searchParams = new URLSearchParams(params);
|
|
16
|
+
const separator = baseUrl.includes("?") ? "&" : "?";
|
|
17
|
+
finalUrl = `${baseUrl}${separator}${searchParams.toString()}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const url = new URL(finalUrl);
|
|
21
|
+
const pathname = url.pathname;
|
|
22
|
+
|
|
23
|
+
const requestHeaders = {
|
|
24
|
+
accept: "*/*",
|
|
25
|
+
"accept-language": "en-US,en;q=0.9",
|
|
26
|
+
authorization: `Bearer ${this.auth.client.bearer}`,
|
|
27
|
+
"content-type": "application/json",
|
|
28
|
+
"x-csrf-token": this.auth.csrfToken,
|
|
29
|
+
"x-twitter-active-user": "yes",
|
|
30
|
+
"x-twitter-auth-type": "OAuth2Session",
|
|
31
|
+
"x-twitter-client-language": "en",
|
|
32
|
+
"x-client-transaction-id": await this.auth.generateTransactionId(
|
|
33
|
+
method.toUpperCase(),
|
|
34
|
+
pathname,
|
|
35
|
+
),
|
|
36
|
+
priority: "u=1, i",
|
|
37
|
+
"sec-ch-ua": '"Not(A:Brand";v="8", "Chromium";v="144"',
|
|
38
|
+
"sec-ch-ua-mobile": "?0",
|
|
39
|
+
"sec-ch-ua-platform": '"macOS"',
|
|
40
|
+
"sec-fetch-dest": "empty",
|
|
41
|
+
"sec-fetch-mode": "cors",
|
|
42
|
+
"sec-fetch-site": "same-origin",
|
|
43
|
+
"sec-gpc": "1",
|
|
44
|
+
cookie:
|
|
45
|
+
this.auth.client.headers.cookie + (this.elevatedCookies ? `; ${this.elevatedCookies}` : ""),
|
|
46
|
+
...headers,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const cycleTLS = await getCycleTLS();
|
|
50
|
+
|
|
51
|
+
return await cycleTLS(
|
|
52
|
+
finalUrl,
|
|
53
|
+
{
|
|
54
|
+
headers: requestHeaders,
|
|
55
|
+
userAgent: this.auth.client.fingerprints.userAgent,
|
|
56
|
+
ja3: this.auth.client.fingerprints.ja3,
|
|
57
|
+
ja4r: this.auth.client.fingerprints.ja4r,
|
|
58
|
+
body: body || undefined,
|
|
59
|
+
proxy: this.proxy || undefined,
|
|
60
|
+
referrer: "https://x.com/",
|
|
61
|
+
},
|
|
62
|
+
method,
|
|
63
|
+
);
|
|
64
|
+
}
|
package/src/v2.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import getCycleTLS from "./cycletls.js";
|
|
2
|
+
import v2Api from "./static/v2.js";
|
|
3
|
+
|
|
4
|
+
export default async function v2(queryName, { params, body, headers } = {}) {
|
|
5
|
+
let entry = v2Api[queryName];
|
|
6
|
+
if (!entry) {
|
|
7
|
+
throw new Error(`v2 endpoint ${queryName} not found`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const [method, baseUrl] = entry;
|
|
11
|
+
|
|
12
|
+
let finalUrl = baseUrl;
|
|
13
|
+
|
|
14
|
+
if (params && Object.keys(params).length) {
|
|
15
|
+
const searchParams = new URLSearchParams(params);
|
|
16
|
+
const separator = baseUrl.includes("?") ? "&" : "?";
|
|
17
|
+
finalUrl = `${baseUrl}${separator}${searchParams.toString()}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const url = new URL(finalUrl);
|
|
21
|
+
const pathname = url.pathname;
|
|
22
|
+
|
|
23
|
+
const requestHeaders = {
|
|
24
|
+
accept: "*/*",
|
|
25
|
+
"accept-language": "en-US,en;q=0.9",
|
|
26
|
+
authorization: `Bearer ${this.auth.client.bearer}`,
|
|
27
|
+
"content-type": "application/json",
|
|
28
|
+
"x-csrf-token": this.auth.csrfToken,
|
|
29
|
+
"x-twitter-active-user": "yes",
|
|
30
|
+
"x-twitter-auth-type": "OAuth2Session",
|
|
31
|
+
"x-twitter-client-language": "en",
|
|
32
|
+
"x-client-transaction-id": await this.auth.generateTransactionId(
|
|
33
|
+
method.toUpperCase(),
|
|
34
|
+
pathname,
|
|
35
|
+
),
|
|
36
|
+
priority: "u=1, i",
|
|
37
|
+
"sec-ch-ua": '"Not(A:Brand";v="8", "Chromium";v="144"',
|
|
38
|
+
"sec-ch-ua-mobile": "?0",
|
|
39
|
+
"sec-ch-ua-platform": '"macOS"',
|
|
40
|
+
"sec-fetch-dest": "empty",
|
|
41
|
+
"sec-fetch-mode": "cors",
|
|
42
|
+
"sec-fetch-site": "same-origin",
|
|
43
|
+
"sec-gpc": "1",
|
|
44
|
+
cookie:
|
|
45
|
+
this.auth.client.headers.cookie + (this.elevatedCookies ? `; ${this.elevatedCookies}` : ""),
|
|
46
|
+
...headers,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const cycleTLS = await getCycleTLS();
|
|
50
|
+
|
|
51
|
+
return await cycleTLS(
|
|
52
|
+
finalUrl,
|
|
53
|
+
{
|
|
54
|
+
headers: requestHeaders,
|
|
55
|
+
userAgent: this.auth.client.fingerprints.userAgent,
|
|
56
|
+
ja3: this.auth.client.fingerprints.ja3,
|
|
57
|
+
ja4r: this.auth.client.fingerprints.ja4r,
|
|
58
|
+
body: body || undefined,
|
|
59
|
+
proxy: this.proxy || undefined,
|
|
60
|
+
referrer: "https://x.com/",
|
|
61
|
+
},
|
|
62
|
+
method,
|
|
63
|
+
);
|
|
64
|
+
}
|
package/src/methods/bookmarks.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import headers from "../utils/headers.js";
|
|
2
|
-
|
|
3
|
-
export async function bookmark(tweetId) {
|
|
4
|
-
if (!this.auth.cookies) {
|
|
5
|
-
throw new Error("you must be logged in to bookmark a tweet");
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const out = await (
|
|
9
|
-
await fetch(
|
|
10
|
-
"https://pro.x.com/i/api/graphql/aoDbu3RHznuiSkQ9aNM67Q/CreateBookmark",
|
|
11
|
-
{
|
|
12
|
-
headers: {
|
|
13
|
-
Accept: "*/*",
|
|
14
|
-
"accept-language": "en-US,en;q=0.9",
|
|
15
|
-
|
|
16
|
-
authorization:
|
|
17
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
18
|
-
"content-type": "application/json",
|
|
19
|
-
|
|
20
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
21
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
22
|
-
|
|
23
|
-
"x-twitter-active-user": "yes",
|
|
24
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
25
|
-
"x-twitter-client-language": "en",
|
|
26
|
-
|
|
27
|
-
cookie: this.auth.cookies,
|
|
28
|
-
...headers,
|
|
29
|
-
},
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
variables: { tweet_id: tweetId },
|
|
32
|
-
queryId: "aoDbu3RHznuiSkQ9aNM67Q",
|
|
33
|
-
}),
|
|
34
|
-
method: "POST",
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
).json();
|
|
38
|
-
|
|
39
|
-
if (!out?.data?.tweet_bookmark_put) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
`failed to bookmark tweet: ${JSON.stringify(out, null, 2)}`
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function unbookmark(tweetId) {
|
|
49
|
-
if (!this.auth.cookies) {
|
|
50
|
-
throw new Error("you must be logged in to unbookmark a tweet");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const out = await (
|
|
54
|
-
await fetch(
|
|
55
|
-
"https://pro.x.com/i/api/graphql/Wlmlj2-xzyS1GN3a6cj-mQ/DeleteBookmark",
|
|
56
|
-
{
|
|
57
|
-
headers: {
|
|
58
|
-
Accept: "*/*",
|
|
59
|
-
"accept-language": "en-US,en;q=0.9",
|
|
60
|
-
|
|
61
|
-
authorization:
|
|
62
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
63
|
-
"content-type": "application/json",
|
|
64
|
-
|
|
65
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
66
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
67
|
-
|
|
68
|
-
"x-twitter-active-user": "yes",
|
|
69
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
70
|
-
"x-twitter-client-language": "en",
|
|
71
|
-
|
|
72
|
-
cookie: this.auth.cookies,
|
|
73
|
-
...headers,
|
|
74
|
-
},
|
|
75
|
-
body: JSON.stringify({
|
|
76
|
-
variables: { tweet_id: tweetId },
|
|
77
|
-
queryId: "Wlmlj2-xzyS1GN3a6cj-mQ",
|
|
78
|
-
}),
|
|
79
|
-
method: "POST",
|
|
80
|
-
}
|
|
81
|
-
)
|
|
82
|
-
).json();
|
|
83
|
-
|
|
84
|
-
if (!out?.data?.tweet_bookmark_delete) {
|
|
85
|
-
throw new Error(
|
|
86
|
-
`failed to unbookmark tweet: ${JSON.stringify(out, null, 2)}`
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return true;
|
|
91
|
-
}
|
package/src/methods/follow.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import parseUser from "../parsers/user.js";
|
|
2
|
-
import headers from "../utils/headers.js";
|
|
3
|
-
|
|
4
|
-
export async function follow(userId) {
|
|
5
|
-
if (!this.auth.cookies) {
|
|
6
|
-
throw new Error("you must be logged in to follow someone");
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const out = await (
|
|
10
|
-
await fetch("https://pro.x.com/i/api/1.1/friendships/create.json", {
|
|
11
|
-
headers: {
|
|
12
|
-
Accept: "*/*",
|
|
13
|
-
"accept-language": "en-US,en;q=0.9",
|
|
14
|
-
|
|
15
|
-
authorization:
|
|
16
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
17
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
18
|
-
|
|
19
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
20
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
21
|
-
|
|
22
|
-
"x-twitter-active-user": "yes",
|
|
23
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
24
|
-
"x-twitter-client-language": "en",
|
|
25
|
-
|
|
26
|
-
cookie: this.auth.cookies,
|
|
27
|
-
...headers,
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
// i'm too lazy to make form data manually and this works
|
|
31
|
-
// well so i'm just gonna use that
|
|
32
|
-
body: `include_profile_interstitial_type=1&include_blocking=1&include_blocked_by=1&include_followed_by=1&include_want_retweets=1&include_mute_edge=1&include_can_dm=1&include_can_media_tag=1&include_ext_is_blue_verified=1&include_ext_verified_type=1&include_ext_profile_image_shape=1&skip_status=1&user_id=${encodeURIComponent(
|
|
33
|
-
userId
|
|
34
|
-
)}`,
|
|
35
|
-
method: "POST",
|
|
36
|
-
})
|
|
37
|
-
).json();
|
|
38
|
-
|
|
39
|
-
if (!out?.id) {
|
|
40
|
-
throw new Error(`failed to follow user: ${JSON.stringify(out, null, 2)}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
user: parseUser(out),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function unfollow(userId) {
|
|
49
|
-
if (!this.auth.cookies) {
|
|
50
|
-
throw new Error("you must be logged in to follow someone");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const out = await (
|
|
54
|
-
await fetch("https://pro.x.com/i/api/1.1/friendships/destroy.json", {
|
|
55
|
-
headers: {
|
|
56
|
-
Accept: "*/*",
|
|
57
|
-
"accept-language": "en-US,en;q=0.9",
|
|
58
|
-
|
|
59
|
-
authorization:
|
|
60
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
61
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
62
|
-
|
|
63
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
64
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
65
|
-
|
|
66
|
-
"x-twitter-active-user": "yes",
|
|
67
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
68
|
-
"x-twitter-client-language": "en",
|
|
69
|
-
|
|
70
|
-
cookie: this.auth.cookies,
|
|
71
|
-
...headers,
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
body: `include_profile_interstitial_type=1&include_blocking=1&include_blocked_by=1&include_followed_by=1&include_want_retweets=1&include_mute_edge=1&include_can_dm=1&include_can_media_tag=1&include_ext_is_blue_verified=1&include_ext_verified_type=1&include_ext_profile_image_shape=1&skip_status=1&user_id=${encodeURIComponent(
|
|
75
|
-
userId
|
|
76
|
-
)}`,
|
|
77
|
-
method: "POST",
|
|
78
|
-
})
|
|
79
|
-
).json();
|
|
80
|
-
|
|
81
|
-
if (!out?.id) {
|
|
82
|
-
throw new Error(`failed to unfollow user: ${JSON.stringify(out, null, 2)}`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
user: parseUser(out),
|
|
87
|
-
};
|
|
88
|
-
}
|
package/src/methods/like.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import headers from "../utils/headers.js";
|
|
2
|
-
|
|
3
|
-
export async function like(tweetId) {
|
|
4
|
-
if (!this.auth.cookies) {
|
|
5
|
-
throw new Error("you must be logged in to like a tweet");
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const out = await (
|
|
9
|
-
await fetch(
|
|
10
|
-
"https://pro.x.com/i/api/graphql/lI07N6Otwv1PhnEgXILM7A/FavoriteTweet",
|
|
11
|
-
{
|
|
12
|
-
headers: {
|
|
13
|
-
Accept: "*/*",
|
|
14
|
-
"accept-language": "en-US,en;q=0.9",
|
|
15
|
-
|
|
16
|
-
authorization:
|
|
17
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
18
|
-
"content-type": "application/json",
|
|
19
|
-
|
|
20
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
21
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
22
|
-
|
|
23
|
-
"x-twitter-active-user": "yes",
|
|
24
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
25
|
-
"x-twitter-client-language": "en",
|
|
26
|
-
|
|
27
|
-
cookie: this.auth.cookies,
|
|
28
|
-
...headers,
|
|
29
|
-
},
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
variables: { tweet_id: tweetId },
|
|
32
|
-
queryId: "lI07N6Otwv1PhnEgXILM7A",
|
|
33
|
-
}),
|
|
34
|
-
method: "POST",
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
).json();
|
|
38
|
-
|
|
39
|
-
if (!out?.data?.favorite_tweet) {
|
|
40
|
-
throw new Error(`failed to like tweet: ${JSON.stringify(out, null, 2)}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function dislike(tweetId) {
|
|
47
|
-
if (!this.auth.cookies) {
|
|
48
|
-
throw new Error("you must be logged in to dislike a tweet");
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const out = await (
|
|
52
|
-
await fetch(
|
|
53
|
-
"https://pro.x.com/i/api/graphql/ZYKSe-w7KEslx3JhSIk5LA/UnfavoriteTweet",
|
|
54
|
-
{
|
|
55
|
-
headers: {
|
|
56
|
-
Accept: "*/*",
|
|
57
|
-
"accept-language": "en-US,en;q=0.9",
|
|
58
|
-
|
|
59
|
-
authorization:
|
|
60
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
61
|
-
"content-type": "application/json",
|
|
62
|
-
|
|
63
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
64
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
65
|
-
|
|
66
|
-
"x-twitter-active-user": "yes",
|
|
67
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
68
|
-
"x-twitter-client-language": "en",
|
|
69
|
-
|
|
70
|
-
cookie: this.auth.cookies,
|
|
71
|
-
...headers,
|
|
72
|
-
},
|
|
73
|
-
body: JSON.stringify({
|
|
74
|
-
variables: { tweet_id: tweetId },
|
|
75
|
-
queryId: "ZYKSe-w7KEslx3JhSIk5LA",
|
|
76
|
-
}),
|
|
77
|
-
method: "POST",
|
|
78
|
-
}
|
|
79
|
-
)
|
|
80
|
-
).json();
|
|
81
|
-
|
|
82
|
-
if (!out?.data?.unfavorite_tweet) {
|
|
83
|
-
throw new Error(`failed to dislike tweet: ${JSON.stringify(out, null, 2)}`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import headers from "../utils/headers.js";
|
|
2
|
-
|
|
3
|
-
export async function getNotifications(
|
|
4
|
-
{ type = "All", limit = 20, cursor = undefined } = {
|
|
5
|
-
type: "All",
|
|
6
|
-
limit: 20,
|
|
7
|
-
cursor: undefined,
|
|
8
|
-
}
|
|
9
|
-
) {
|
|
10
|
-
if (!this.auth.cookies) {
|
|
11
|
-
throw new Error("you must be logged in to get notifications");
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const variables = { timeline_type: type, count: limit };
|
|
15
|
-
if (cursor) {
|
|
16
|
-
variables.cursor = cursor;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const response = await (
|
|
20
|
-
await fetch(
|
|
21
|
-
`https://pro.x.com/i/api/graphql/WERRji0vXRGrMiQ8LPZ3sw/NotificationsTimeline?variables=${encodeURIComponent(
|
|
22
|
-
JSON.stringify(variables)
|
|
23
|
-
)}&features=${encodeURIComponent(
|
|
24
|
-
JSON.stringify({
|
|
25
|
-
rweb_video_screen_enabled: false,
|
|
26
|
-
profile_label_improvements_pcf_label_in_post_enabled: true,
|
|
27
|
-
rweb_tipjar_consumption_enabled: true,
|
|
28
|
-
responsive_web_graphql_exclude_directive_enabled: true,
|
|
29
|
-
verified_phone_label_enabled: false,
|
|
30
|
-
creator_subscriptions_tweet_preview_api_enabled: true,
|
|
31
|
-
responsive_web_graphql_timeline_navigation_enabled: true,
|
|
32
|
-
responsive_web_graphql_skip_user_profile_image_extensions_enabled: false,
|
|
33
|
-
premium_content_api_read_enabled: false,
|
|
34
|
-
communities_web_enable_tweet_community_results_fetch: true,
|
|
35
|
-
c9s_tweet_anatomy_moderator_badge_enabled: true,
|
|
36
|
-
responsive_web_grok_analyze_button_fetch_trends_enabled: false,
|
|
37
|
-
responsive_web_grok_analyze_post_followups_enabled: true,
|
|
38
|
-
responsive_web_jetfuel_frame: false,
|
|
39
|
-
responsive_web_grok_share_attachment_enabled: true,
|
|
40
|
-
articles_preview_enabled: true,
|
|
41
|
-
responsive_web_edit_tweet_api_enabled: true,
|
|
42
|
-
graphql_is_translatable_rweb_tweet_is_translatable_enabled: true,
|
|
43
|
-
view_counts_everywhere_api_enabled: true,
|
|
44
|
-
longform_notetweets_consumption_enabled: true,
|
|
45
|
-
responsive_web_twitter_article_tweet_consumption_enabled: true,
|
|
46
|
-
tweet_awards_web_tipping_enabled: false,
|
|
47
|
-
responsive_web_grok_show_grok_translated_post: false,
|
|
48
|
-
responsive_web_grok_analysis_button_from_backend: false,
|
|
49
|
-
creator_subscriptions_quote_tweet_preview_enabled: false,
|
|
50
|
-
freedom_of_speech_not_reach_fetch_enabled: true,
|
|
51
|
-
standardized_nudges_misinfo: true,
|
|
52
|
-
tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled: true,
|
|
53
|
-
longform_notetweets_rich_text_read_enabled: true,
|
|
54
|
-
longform_notetweets_inline_media_enabled: true,
|
|
55
|
-
responsive_web_grok_image_annotation_enabled: true,
|
|
56
|
-
responsive_web_enhance_cards_enabled: false,
|
|
57
|
-
})
|
|
58
|
-
)}`,
|
|
59
|
-
{
|
|
60
|
-
headers: {
|
|
61
|
-
Accept: "*/*",
|
|
62
|
-
authorization:
|
|
63
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
64
|
-
"content-type": "application/json",
|
|
65
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
66
|
-
"x-twitter-active-user": "yes",
|
|
67
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
68
|
-
"x-twitter-client-language": "en",
|
|
69
|
-
cookie: this.auth.cookies,
|
|
70
|
-
...headers,
|
|
71
|
-
},
|
|
72
|
-
}
|
|
73
|
-
)
|
|
74
|
-
).json();
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
!response?.data?.viewer_v2?.user_results?.result?.notification_timeline
|
|
78
|
-
?.timeline?.instructions
|
|
79
|
-
) {
|
|
80
|
-
throw new Error(
|
|
81
|
-
`failed to get notifications: ${JSON.stringify(response, null, 2)}`
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const instructions =
|
|
86
|
-
response.data.viewer_v2.user_results.result.notification_timeline.timeline
|
|
87
|
-
.instructions;
|
|
88
|
-
|
|
89
|
-
const addEntriesInstruction = instructions.find(
|
|
90
|
-
(instruction) => instruction.type === "TimelineAddEntries"
|
|
91
|
-
);
|
|
92
|
-
|
|
93
|
-
if (!addEntriesInstruction) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
"failed to find timeline entries in notifications response"
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const entries = addEntriesInstruction.entries;
|
|
100
|
-
|
|
101
|
-
// Extract cursors for pagination
|
|
102
|
-
const cursors = {
|
|
103
|
-
top: null,
|
|
104
|
-
bottom: null,
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
entries.forEach((entry) => {
|
|
108
|
-
if (entry.entryId.startsWith("cursor-")) {
|
|
109
|
-
if (entry.entryId.includes("top")) {
|
|
110
|
-
cursors.top = entry.content?.value;
|
|
111
|
-
} else if (entry.entryId.includes("bottom")) {
|
|
112
|
-
cursors.bottom = entry.content?.value;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
entries: entries.filter((entry) => !entry.entryId.startsWith("cursor-")),
|
|
119
|
-
cursors,
|
|
120
|
-
};
|
|
121
|
-
}
|
package/src/methods/retweet.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import headers from "../utils/headers.js";
|
|
2
|
-
|
|
3
|
-
export async function retweet(tweetId) {
|
|
4
|
-
if (!this.auth.cookies) {
|
|
5
|
-
throw new Error("you must be logged in to retweet");
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const out = await (
|
|
9
|
-
await fetch(
|
|
10
|
-
"https://pro.x.com/i/api/graphql/ojPdsZsimiJrUGLR1sjUtA/CreateRetweet",
|
|
11
|
-
{
|
|
12
|
-
headers: {
|
|
13
|
-
Accept: "*/*",
|
|
14
|
-
"accept-language": "en-US,en;q=0.9",
|
|
15
|
-
|
|
16
|
-
authorization:
|
|
17
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
18
|
-
"content-type": "application/json",
|
|
19
|
-
|
|
20
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
21
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
22
|
-
|
|
23
|
-
"x-twitter-active-user": "yes",
|
|
24
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
25
|
-
"x-twitter-client-language": "en",
|
|
26
|
-
|
|
27
|
-
cookie: this.auth.cookies,
|
|
28
|
-
...headers,
|
|
29
|
-
},
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
variables: { tweet_id: tweetId, dark_request: false },
|
|
32
|
-
queryId: "ojPdsZsimiJrUGLR1sjUtA",
|
|
33
|
-
}),
|
|
34
|
-
method: "POST",
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
).json();
|
|
38
|
-
|
|
39
|
-
if (!out?.data?.create_retweet) {
|
|
40
|
-
throw new Error(`failed to retweet: ${JSON.stringify(out, null, 2)}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
post_id: out?.data?.create_retweet?.retweet_results?.result?.rest_id,
|
|
45
|
-
post_url: `https://x.com/i/status/${out?.data?.create_retweet?.retweet_results?.result?.rest_id}`,
|
|
46
|
-
response: out,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function unretweet(tweetId) {
|
|
51
|
-
if (!this.auth.cookies) {
|
|
52
|
-
throw new Error("you must be logged in to undo a retweet");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const out = await (
|
|
56
|
-
await fetch(
|
|
57
|
-
"https://pro.x.com/i/api/graphql/iQtK4dl5hBmXewYZuEOKVw/DeleteRetweet",
|
|
58
|
-
{
|
|
59
|
-
headers: {
|
|
60
|
-
Accept: "*/*",
|
|
61
|
-
"accept-language": "en-US,en;q=0.9",
|
|
62
|
-
|
|
63
|
-
authorization:
|
|
64
|
-
"Bearer AAAAAAAAAAAAAAAAAAAAAFQODgEAAAAAVHTp76lzh3rFzcHbmHVvQxYYpTw%3DckAlMINMjmCwxUcaXbAN4XqJVdgMJaHqNOFgPMK0zN1qLqLQCF",
|
|
65
|
-
"content-type": "application/json",
|
|
66
|
-
|
|
67
|
-
"x-client-transaction-id": Math.random().toString().replace("0.", ""),
|
|
68
|
-
"x-csrf-token": this.auth.csrfToken,
|
|
69
|
-
|
|
70
|
-
"x-twitter-active-user": "yes",
|
|
71
|
-
"x-twitter-auth-type": "OAuth2Session",
|
|
72
|
-
"x-twitter-client-language": "en",
|
|
73
|
-
|
|
74
|
-
cookie: this.auth.cookies,
|
|
75
|
-
...headers,
|
|
76
|
-
},
|
|
77
|
-
body: JSON.stringify({
|
|
78
|
-
variables: { source_tweet_id: tweetId, dark_request: false },
|
|
79
|
-
queryId: "iQtK4dl5hBmXewYZuEOKVw",
|
|
80
|
-
}),
|
|
81
|
-
method: "POST",
|
|
82
|
-
}
|
|
83
|
-
)
|
|
84
|
-
).json();
|
|
85
|
-
|
|
86
|
-
if (!out?.data?.unretweet) {
|
|
87
|
-
throw new Error(`failed to unretweet: ${JSON.stringify(out, null, 2)}`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return true;
|
|
91
|
-
}
|