emusks 2.0.11 → 2.0.12
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/package.json +1 -1
- package/src/graphql.js +64 -8
- package/src/index.js +27 -5
package/package.json
CHANGED
package/src/graphql.js
CHANGED
|
@@ -1,16 +1,60 @@
|
|
|
1
|
+
import { ClientTransaction, handleXMigration } from "x-client-transaction-id";
|
|
1
2
|
import getCycleTLS from "./cycletls.js";
|
|
2
3
|
import graphqlApi from "./static/graphql.js";
|
|
3
4
|
|
|
5
|
+
const GRAPHQL_ENDPOINTS = {
|
|
6
|
+
main: {
|
|
7
|
+
base: "https://api.x.com/graphql",
|
|
8
|
+
referrer: "https://x.com/",
|
|
9
|
+
secFetchSite: "same-site",
|
|
10
|
+
},
|
|
11
|
+
main_twitter: {
|
|
12
|
+
base: "https://api.twitter.com/graphql",
|
|
13
|
+
referrer: "https://twitter.com/",
|
|
14
|
+
secFetchSite: "same-site",
|
|
15
|
+
},
|
|
16
|
+
web: {
|
|
17
|
+
base: "https://x.com/i/api/graphql",
|
|
18
|
+
referrer: "https://x.com/",
|
|
19
|
+
secFetchSite: "same-origin",
|
|
20
|
+
},
|
|
21
|
+
web_twitter: {
|
|
22
|
+
base: "https://twitter.com/i/api/graphql",
|
|
23
|
+
referrer: "https://twitter.com/",
|
|
24
|
+
secFetchSite: "same-origin",
|
|
25
|
+
},
|
|
26
|
+
tweetdeck: {
|
|
27
|
+
base: "https://pro.x.com/i/api/graphql",
|
|
28
|
+
referrer: "https://pro.x.com/",
|
|
29
|
+
secFetchSite: "same-origin",
|
|
30
|
+
},
|
|
31
|
+
tweetdeck_twitter: {
|
|
32
|
+
base: "https://pro.twitter.com/i/api/graphql",
|
|
33
|
+
referrer: "https://pro.twitter.com/",
|
|
34
|
+
secFetchSite: "same-origin",
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { GRAPHQL_ENDPOINTS };
|
|
39
|
+
|
|
4
40
|
export default async function graphql(queryName, { variables, fieldToggles, body, headers } = {}) {
|
|
5
41
|
const entry = graphqlApi[queryName];
|
|
6
42
|
if (!entry) {
|
|
7
43
|
throw new Error(`graphql query ${queryName} not found`);
|
|
8
44
|
}
|
|
9
45
|
|
|
10
|
-
const [method,
|
|
46
|
+
const [method, , features, queryId] = entry;
|
|
11
47
|
const isPost = method.toLowerCase() === "post";
|
|
12
48
|
|
|
13
|
-
|
|
49
|
+
const endpointName = this.graphqlEndpoint || "web";
|
|
50
|
+
const endpoint = GRAPHQL_ENDPOINTS[endpointName];
|
|
51
|
+
if (!endpoint) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`unknown graphql endpoint "${endpointName}", expected: ${Object.keys(GRAPHQL_ENDPOINTS).join(", ")}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let finalUrl = `${endpoint.base}/${queryId}/${queryName}`;
|
|
14
58
|
let requestBody;
|
|
15
59
|
|
|
16
60
|
if (isPost) {
|
|
@@ -41,6 +85,9 @@ export default async function graphql(queryName, { variables, fieldToggles, body
|
|
|
41
85
|
const url = new URL(finalUrl);
|
|
42
86
|
const pathname = url.pathname;
|
|
43
87
|
|
|
88
|
+
const useTransactionIds =
|
|
89
|
+
this.transactionIds !== undefined ? this.transactionIds : endpointName === "web";
|
|
90
|
+
|
|
44
91
|
const requestHeaders = {
|
|
45
92
|
accept: "*/*",
|
|
46
93
|
"accept-language": "en-US,en;q=0.9",
|
|
@@ -50,23 +97,32 @@ export default async function graphql(queryName, { variables, fieldToggles, body
|
|
|
50
97
|
"x-twitter-active-user": "yes",
|
|
51
98
|
"x-twitter-auth-type": "OAuth2Session",
|
|
52
99
|
"x-twitter-client-language": "en",
|
|
53
|
-
"x-client-transaction-id": await this.auth.generateTransactionId(
|
|
54
|
-
method.toUpperCase(),
|
|
55
|
-
pathname,
|
|
56
|
-
),
|
|
57
100
|
priority: "u=1, i",
|
|
58
101
|
"sec-ch-ua": '"Not(A:Brand";v="8", "Chromium";v="144"',
|
|
59
102
|
"sec-ch-ua-mobile": "?0",
|
|
60
103
|
"sec-ch-ua-platform": '"macOS"',
|
|
61
104
|
"sec-fetch-dest": "empty",
|
|
62
105
|
"sec-fetch-mode": "cors",
|
|
63
|
-
"sec-fetch-site":
|
|
106
|
+
"sec-fetch-site": endpoint.secFetchSite,
|
|
64
107
|
"sec-gpc": "1",
|
|
65
108
|
cookie:
|
|
66
109
|
this.auth.client.headers.cookie + (this.elevatedCookies ? `; ${this.elevatedCookies}` : ""),
|
|
67
110
|
...headers,
|
|
68
111
|
};
|
|
69
112
|
|
|
113
|
+
if (useTransactionIds) {
|
|
114
|
+
if (!this.auth.generateTransactionId) {
|
|
115
|
+
const document = await handleXMigration();
|
|
116
|
+
const transaction = new ClientTransaction(document);
|
|
117
|
+
await transaction.initialize();
|
|
118
|
+
this.auth.generateTransactionId = transaction.generateTransactionId.bind(transaction);
|
|
119
|
+
}
|
|
120
|
+
requestHeaders["x-client-transaction-id"] = await this.auth.generateTransactionId(
|
|
121
|
+
method.toUpperCase(),
|
|
122
|
+
pathname,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
70
126
|
const cycleTLS = await getCycleTLS();
|
|
71
127
|
const res = await (
|
|
72
128
|
await cycleTLS(
|
|
@@ -78,7 +134,7 @@ export default async function graphql(queryName, { variables, fieldToggles, body
|
|
|
78
134
|
ja4r: this.auth.client.fingerprints.ja4r,
|
|
79
135
|
body: isPost ? JSON.stringify(requestBody) : undefined,
|
|
80
136
|
proxy: this.proxy || undefined,
|
|
81
|
-
referrer:
|
|
137
|
+
referrer: endpoint.referrer,
|
|
82
138
|
},
|
|
83
139
|
method,
|
|
84
140
|
)
|
package/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ClientTransaction, handleXMigration } from "x-client-transaction-id";
|
|
|
2
2
|
import clients from "./clients.js";
|
|
3
3
|
import getCycleTLS from "./cycletls.js";
|
|
4
4
|
import flowLogin from "./flow.js";
|
|
5
|
-
import graphql from "./graphql.js";
|
|
5
|
+
import graphql, { GRAPHQL_ENDPOINTS } from "./graphql.js";
|
|
6
6
|
import initHelpers from "./helpers/index.js";
|
|
7
7
|
import parseUser from "./parsers/user.js";
|
|
8
8
|
import v1_1 from "./v1.1.js";
|
|
@@ -11,6 +11,8 @@ import v2 from "./v2.js";
|
|
|
11
11
|
export default class Emusks {
|
|
12
12
|
auth = null;
|
|
13
13
|
elevatedCookies = null;
|
|
14
|
+
graphqlEndpoint = "web";
|
|
15
|
+
transactionIds = undefined;
|
|
14
16
|
|
|
15
17
|
async elevate(password) {
|
|
16
18
|
if (!this.auth) throw new Error("must be logged in before calling elevate");
|
|
@@ -76,6 +78,19 @@ export default class Emusks {
|
|
|
76
78
|
if (!p.client) throw new Error("invalid client!");
|
|
77
79
|
if (p.proxy) this.proxy = p.proxy;
|
|
78
80
|
|
|
81
|
+
if (p.endpoint) {
|
|
82
|
+
if (!GRAPHQL_ENDPOINTS[p.endpoint]) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`unknown graphql endpoint "${p.endpoint}", expected: ${Object.keys(GRAPHQL_ENDPOINTS).join(", ")}`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
this.graphqlEndpoint = p.endpoint;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (p.transactionIds !== undefined) {
|
|
91
|
+
this.transactionIds = p.transactionIds;
|
|
92
|
+
}
|
|
93
|
+
|
|
79
94
|
if (!p.client.bearer) {
|
|
80
95
|
throw new Error("client is missing bearer token!");
|
|
81
96
|
}
|
|
@@ -139,10 +154,17 @@ export default class Emusks {
|
|
|
139
154
|
}
|
|
140
155
|
this.auth.client.headers.cookie = cookieParts.join("; ");
|
|
141
156
|
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
const needsTransactionIds =
|
|
158
|
+
this.transactionIds !== undefined
|
|
159
|
+
? this.transactionIds
|
|
160
|
+
: this.graphqlEndpoint === "web" || this.graphqlEndpoint === "web_twitter";
|
|
161
|
+
|
|
162
|
+
if (needsTransactionIds) {
|
|
163
|
+
const document = await handleXMigration();
|
|
164
|
+
const transaction = new ClientTransaction(document);
|
|
165
|
+
await transaction.initialize();
|
|
166
|
+
this.auth.generateTransactionId = transaction.generateTransactionId.bind(transaction);
|
|
167
|
+
}
|
|
146
168
|
|
|
147
169
|
const responseText = await res.text();
|
|
148
170
|
const initialStateMatch = responseText.match(/window\.__INITIAL_STATE__\s*=\s*({.*?});/s);
|