@the-convocation/twitter-scraper 0.14.1 → 0.15.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.
@@ -50,6 +50,23 @@ class ApiError extends Error {
50
50
  }
51
51
  }
52
52
 
53
+ class WaitingRateLimitStrategy {
54
+ async onRateLimit({ response: res }) {
55
+ const xRateLimitRemaining = res.headers.get("x-rate-limit-remaining");
56
+ const xRateLimitReset = res.headers.get("x-rate-limit-reset");
57
+ if (xRateLimitRemaining == "0" && xRateLimitReset) {
58
+ const currentTime = (/* @__PURE__ */ new Date()).valueOf() / 1e3;
59
+ const timeDeltaMs = 1e3 * (parseInt(xRateLimitReset) - currentTime);
60
+ await new Promise((resolve) => setTimeout(resolve, timeDeltaMs));
61
+ }
62
+ }
63
+ }
64
+ class ErrorRateLimitStrategy {
65
+ onRateLimit({ response: res }) {
66
+ throw ApiError.fromResponse(res);
67
+ }
68
+ }
69
+
53
70
  class Platform {
54
71
  async randomizeCiphers() {
55
72
  const platform = await Platform.importPlatform();
@@ -91,12 +108,16 @@ async function requestApi(url, auth, method = "GET", platform = new Platform())
91
108
  await platform.randomizeCiphers();
92
109
  let res;
93
110
  do {
94
- try {
95
- res = await auth.fetch(url, {
111
+ const fetchParameters = [
112
+ url,
113
+ {
96
114
  method,
97
115
  headers,
98
116
  credentials: "include"
99
- });
117
+ }
118
+ ];
119
+ try {
120
+ res = await auth.fetch(...fetchParameters);
100
121
  } catch (err) {
101
122
  if (!(err instanceof Error)) {
102
123
  throw err;
@@ -108,13 +129,10 @@ async function requestApi(url, auth, method = "GET", platform = new Platform())
108
129
  }
109
130
  await updateCookieJar(auth.cookieJar(), res.headers);
110
131
  if (res.status === 429) {
111
- const xRateLimitRemaining = res.headers.get("x-rate-limit-remaining");
112
- const xRateLimitReset = res.headers.get("x-rate-limit-reset");
113
- if (xRateLimitRemaining == "0" && xRateLimitReset) {
114
- const currentTime = (/* @__PURE__ */ new Date()).valueOf() / 1e3;
115
- const timeDeltaMs = 1e3 * (parseInt(xRateLimitReset) - currentTime);
116
- await new Promise((resolve) => setTimeout(resolve, timeDeltaMs));
117
- }
132
+ await auth.onRateLimit({
133
+ fetchParameters,
134
+ response: res
135
+ });
118
136
  }
119
137
  } while (res.status === 429);
120
138
  if (!res.ok) {
@@ -215,9 +233,13 @@ class TwitterGuestAuth {
215
233
  constructor(bearerToken, options) {
216
234
  this.options = options;
217
235
  this.fetch = withTransform(options?.fetch ?? fetch, options?.transform);
236
+ this.rateLimitStrategy = options?.rateLimitStrategy ?? new WaitingRateLimitStrategy();
218
237
  this.bearerToken = bearerToken;
219
238
  this.jar = new toughCookie.CookieJar();
220
239
  }
240
+ async onRateLimit(event) {
241
+ await this.rateLimitStrategy.onRateLimit(event);
242
+ }
221
243
  cookieJar() {
222
244
  return this.jar;
223
245
  }
@@ -2109,7 +2131,8 @@ class Scraper {
2109
2131
  getAuthOptions() {
2110
2132
  return {
2111
2133
  fetch: this.options?.fetch,
2112
- transform: this.options?.transform
2134
+ transform: this.options?.transform,
2135
+ rateLimitStrategy: this.options?.rateLimitStrategy
2113
2136
  };
2114
2137
  }
2115
2138
  handleResponse(res) {
@@ -2151,6 +2174,9 @@ var index = /*#__PURE__*/Object.freeze({
2151
2174
  platform: platform
2152
2175
  });
2153
2176
 
2177
+ exports.ApiError = ApiError;
2178
+ exports.ErrorRateLimitStrategy = ErrorRateLimitStrategy;
2154
2179
  exports.Scraper = Scraper;
2155
2180
  exports.SearchMode = SearchMode;
2181
+ exports.WaitingRateLimitStrategy = WaitingRateLimitStrategy;
2156
2182
  //# sourceMappingURL=index.cjs.map