emusks 2.0.3 → 2.0.5

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/build/graphql.js CHANGED
@@ -3,21 +3,13 @@ const URL = `https://raw.githubusercontent.com/fa0311/TwitterInternalAPIDocument
3
3
  const json = await fetch(URL).then((r) => r.json());
4
4
  const graphql = json.graphql;
5
5
 
6
- const buildUrl = (base, features) => {
7
- const params = new URLSearchParams();
8
-
9
- if (features && Object.keys(features).length) {
10
- params.set(`features`, JSON.stringify(features));
11
- }
12
-
13
- const query = params.toString();
14
- return query ? `${base}?${query}` : base;
15
- };
16
-
17
6
  const transformed = Object.fromEntries(
18
7
  Object.entries(graphql).map(([name, data]) => {
19
- const constructedUrl = buildUrl(data.url, data.features);
20
- return [name, [data.method, constructedUrl]];
8
+ const features = data.features
9
+ ? Object.fromEntries(Object.keys(data.features).map((k) => [k, true]))
10
+ : undefined;
11
+ const queryId = data.url.match(/\/graphql\/([^\/]+)\//)?.[1];
12
+ return [name, [data.method, data.url, features, queryId]];
21
13
  }),
22
14
  );
23
15
 
package/package.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
2
  "name": "emusks",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "Reverse-engineered Twitter API client. Log in and interact with the unofficial X API using any client identity — web, Android, iOS, or TweetDeck",
5
- "keywords": ["twitter", "twitter-api", "x", "x-api", "reverse-engineering", "client"],
5
+ "keywords": [
6
+ "client",
7
+ "reverse-engineering",
8
+ "twitter",
9
+ "twitter-api",
10
+ "x",
11
+ "x-api"
12
+ ],
6
13
  "homepage": "https://github.com/tiagozip/emusks",
7
- "main": "src/index.js",
8
14
  "bugs": {
9
15
  "url": "https://github.com/tiagozip/emusks/issues"
10
16
  },
@@ -13,6 +19,11 @@
13
19
  "type": "git",
14
20
  "url": "https://github.com/tiagozip/emusks.git"
15
21
  },
22
+ "type": "module",
23
+ "main": "src/index.js",
24
+ "exports": {
25
+ ".": "./src/index.js"
26
+ },
16
27
  "dependencies": {
17
28
  "cycletls": "^2.0.5",
18
29
  "x-client-transaction-id": "^0.1.9"
package/src/graphql.js CHANGED
@@ -7,18 +7,35 @@ export default async function graphql(queryName, { variables, fieldToggles, body
7
7
  throw new Error(`graphql query ${queryName} not found`);
8
8
  }
9
9
 
10
- const [method, baseUrl] = entry;
10
+ const [method, baseUrl, features, queryId] = entry;
11
+ const isPost = method.toLowerCase() === "post";
11
12
 
12
13
  let finalUrl = baseUrl;
14
+ let requestBody;
13
15
 
14
- if (variables && Object.keys(variables).length) {
15
- const separator = baseUrl.includes("?") ? "&" : "?";
16
- finalUrl = `${baseUrl}${separator}variables=${encodeURIComponent(JSON.stringify(variables))}`;
17
- }
18
-
19
- if (fieldToggles && Object.keys(fieldToggles).length) {
20
- const separator = finalUrl.includes("?") ? "&" : "?";
21
- finalUrl = `${finalUrl}${separator}fieldToggles=${encodeURIComponent(JSON.stringify(fieldToggles))}`;
16
+ if (isPost) {
17
+ requestBody = {
18
+ ...body,
19
+ variables: { ...variables, ...body?.variables },
20
+ queryId,
21
+ };
22
+ if (features) requestBody.features = features;
23
+ if (fieldToggles && Object.keys(fieldToggles).length) {
24
+ requestBody.fieldToggles = fieldToggles;
25
+ }
26
+ } else {
27
+ if (variables && Object.keys(variables).length) {
28
+ const separator = finalUrl.includes("?") ? "&" : "?";
29
+ finalUrl = `${finalUrl}${separator}variables=${encodeURIComponent(JSON.stringify(variables))}`;
30
+ }
31
+ if (features) {
32
+ const separator = finalUrl.includes("?") ? "&" : "?";
33
+ finalUrl = `${finalUrl}${separator}features=${encodeURIComponent(JSON.stringify(features))}`;
34
+ }
35
+ if (fieldToggles && Object.keys(fieldToggles).length) {
36
+ const separator = finalUrl.includes("?") ? "&" : "?";
37
+ finalUrl = `${finalUrl}${separator}fieldToggles=${encodeURIComponent(JSON.stringify(fieldToggles))}`;
38
+ }
22
39
  }
23
40
 
24
41
  const url = new URL(finalUrl);
@@ -51,8 +68,7 @@ export default async function graphql(queryName, { variables, fieldToggles, body
51
68
  };
52
69
 
53
70
  const cycleTLS = await getCycleTLS();
54
-
55
- return await (
71
+ const res = await (
56
72
  await cycleTLS(
57
73
  finalUrl,
58
74
  {
@@ -60,11 +76,17 @@ export default async function graphql(queryName, { variables, fieldToggles, body
60
76
  userAgent: this.auth.client.fingerprints.userAgent,
61
77
  ja3: this.auth.client.fingerprints.ja3,
62
78
  ja4r: this.auth.client.fingerprints.ja4r,
63
- body: typeof body === "object" ? JSON.stringify(body) : undefined,
79
+ body: isPost ? JSON.stringify(requestBody) : undefined,
64
80
  proxy: this.proxy || undefined,
65
81
  referrer: "https://x.com/",
66
82
  },
67
83
  method,
68
84
  )
69
85
  ).json();
86
+
87
+ if (res?.errors?.[0]) {
88
+ throw new Error(res.errors.map((err) => err.message).join(", "));
89
+ }
90
+
91
+ return res;
70
92
  }