@the-convocation/twitter-scraper 0.18.3 → 0.19.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.
@@ -51,13 +51,13 @@ class AuthenticationError extends Error {
51
51
  }
52
52
  }
53
53
 
54
- const log$3 = debug("twitter-scraper:rate-limit");
54
+ const log$4 = debug("twitter-scraper:rate-limit");
55
55
  class WaitingRateLimitStrategy {
56
56
  async onRateLimit({ response: res }) {
57
57
  const xRateLimitLimit = res.headers.get("x-rate-limit-limit");
58
58
  const xRateLimitRemaining = res.headers.get("x-rate-limit-remaining");
59
59
  const xRateLimitReset = res.headers.get("x-rate-limit-reset");
60
- log$3(
60
+ log$4(
61
61
  `Rate limit event: limit=${xRateLimitLimit}, remaining=${xRateLimitRemaining}, reset=${xRateLimitReset}`
62
62
  );
63
63
  if (xRateLimitRemaining == "0" && xRateLimitReset) {
@@ -86,16 +86,47 @@ class Platform {
86
86
  }
87
87
  }
88
88
 
89
+ const log$3 = debug("twitter-scraper:requests");
89
90
  async function updateCookieJar(cookieJar, headers) {
90
- const setCookieHeader = headers.get("set-cookie");
91
- if (setCookieHeader) {
92
- const cookies = setCookie.splitCookiesString(setCookieHeader);
93
- for (const cookie of cookies.map((c) => Cookie.parse(c))) {
94
- if (!cookie) continue;
95
- await cookieJar.setCookie(
96
- cookie,
97
- `${cookie.secure ? "https" : "http"}://${cookie.domain}${cookie.path}`
98
- );
91
+ let setCookieHeaders = [];
92
+ if (typeof headers.getSetCookie === "function") {
93
+ setCookieHeaders = headers.getSetCookie();
94
+ } else {
95
+ const setCookieHeader = headers.get("set-cookie");
96
+ if (setCookieHeader) {
97
+ setCookieHeaders = setCookie.splitCookiesString(setCookieHeader);
98
+ }
99
+ }
100
+ if (setCookieHeaders.length > 0) {
101
+ for (const cookieStr of setCookieHeaders) {
102
+ const cookie = Cookie.parse(cookieStr);
103
+ if (!cookie) {
104
+ log$3(`Failed to parse cookie: ${cookieStr.substring(0, 100)}`);
105
+ continue;
106
+ }
107
+ if (cookie.maxAge === 0 || cookie.expires && cookie.expires < /* @__PURE__ */ new Date()) {
108
+ if (cookie.key === "ct0") {
109
+ log$3(`Skipping deletion of ct0 cookie (Max-Age=0)`);
110
+ }
111
+ continue;
112
+ }
113
+ try {
114
+ const url = `${cookie.secure ? "https" : "http"}://${cookie.domain}${cookie.path}`;
115
+ await cookieJar.setCookie(cookie, url);
116
+ if (cookie.key === "ct0") {
117
+ log$3(
118
+ `Successfully set ct0 cookie with value: ${cookie.value.substring(
119
+ 0,
120
+ 20
121
+ )}...`
122
+ );
123
+ }
124
+ } catch (err) {
125
+ log$3(`Failed to set cookie ${cookie.key}: ${err}`);
126
+ if (cookie.key === "ct0") {
127
+ log$3(`FAILED to set ct0 cookie! Error: ${err}`);
128
+ }
129
+ }
99
130
  }
100
131
  } else if (typeof document !== "undefined") {
101
132
  for (const cookie of document.cookie.split(";")) {
@@ -113,9 +144,8 @@ async function jitter(maxMs) {
113
144
  const jitter2 = Math.random() * maxMs;
114
145
  await new Promise((resolve) => setTimeout(resolve, jitter2));
115
146
  }
116
- async function requestApi(url, auth, method = "GET", platform = new Platform()) {
147
+ async function requestApi(url, auth, method = "GET", platform = new Platform(), headers = new Headers()) {
117
148
  log$2(`Making ${method} request to ${url}`);
118
- const headers = new Headers();
119
149
  await auth.installTo(headers, url);
120
150
  await platform.randomizeCiphers();
121
151
  let res;
@@ -301,6 +331,16 @@ class TwitterGuestAuth {
301
331
  }
302
332
  headers.set("cookie", await this.getCookieString());
303
333
  }
334
+ async setCookie(key, value) {
335
+ const cookie = Cookie.parse(`${key}=${value}`);
336
+ if (!cookie) {
337
+ throw new Error("Failed to parse cookie.");
338
+ }
339
+ await this.jar.setCookie(cookie, this.getCookieJarUrl());
340
+ if (typeof document !== "undefined") {
341
+ document.cookie = cookie.toString();
342
+ }
343
+ }
304
344
  async getCookies() {
305
345
  return this.jar.getCookies(this.getCookieJarUrl());
306
346
  }
@@ -351,6 +391,8 @@ class TwitterGuestAuth {
351
391
  }
352
392
  this.guestToken = newGuestToken;
353
393
  this.guestCreatedAt = /* @__PURE__ */ new Date();
394
+ await this.setCookie("gt", newGuestToken);
395
+ log$1(`Updated guest token: ${newGuestToken}`);
354
396
  }
355
397
  /**
356
398
  * Returns if the authentication token needs to be updated or not.
@@ -477,7 +519,11 @@ class TwitterUserAuth extends TwitterGuestAuth {
477
519
  }
478
520
  async installTo(headers) {
479
521
  headers.set("authorization", `Bearer ${this.bearerToken}`);
480
- headers.set("cookie", await this.getCookieString());
522
+ const cookie = await this.getCookieString();
523
+ headers.set("cookie", cookie);
524
+ if (this.guestToken) {
525
+ headers.set("x-guest-token", this.guestToken);
526
+ }
481
527
  await this.installCsrfToken(headers);
482
528
  }
483
529
  async initLogin() {
@@ -690,16 +736,27 @@ class TwitterUserAuth extends TwitterGuestAuth {
690
736
  );
691
737
  }
692
738
  const headers = new Headers({
693
- authorization: `Bearer ${this.bearerToken}`,
694
- cookie: await this.getCookieString(),
739
+ accept: "*/*",
740
+ "accept-language": "en-US,en;q=0.9",
695
741
  "content-type": "application/json",
696
- "User-Agent": "Mozilla/5.0 (Linux; Android 11; Nokia G20) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.88 Mobile Safari/537.36",
742
+ "cache-control": "no-cache",
743
+ origin: "https://x.com",
744
+ pragma: "no-cache",
745
+ priority: "u=1, i",
746
+ referer: "https://x.com/",
747
+ "sec-ch-ua": '"Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135"',
748
+ "sec-ch-ua-mobile": "?0",
749
+ "sec-ch-ua-platform": '"Windows"',
750
+ "sec-fetch-dest": "empty",
751
+ "sec-fetch-mode": "cors",
752
+ "sec-fetch-site": "same-origin",
753
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
697
754
  "x-guest-token": token,
698
755
  "x-twitter-auth-type": "OAuth2Client",
699
756
  "x-twitter-active-user": "yes",
700
757
  "x-twitter-client-language": "en"
701
758
  });
702
- await this.installCsrfToken(headers);
759
+ await this.installTo(headers);
703
760
  let res;
704
761
  do {
705
762
  const fetchParameters = [