@the-convocation/twitter-scraper 0.15.1 → 0.16.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/dist/default/cjs/index.js +172 -83
- package/dist/default/cjs/index.js.map +1 -1
- package/dist/default/esm/index.mjs +172 -84
- package/dist/default/esm/index.mjs.map +1 -1
- package/dist/node/cjs/index.cjs +172 -83
- package/dist/node/cjs/index.cjs.map +1 -1
- package/dist/node/esm/index.mjs +172 -84
- package/dist/node/esm/index.mjs.map +1 -1
- package/dist/types/index.d.ts +189 -8
- package/package.json +1 -1
|
@@ -26,6 +26,12 @@ class ApiError extends Error {
|
|
|
26
26
|
return new ApiError(response, data, `Response status: ${response.status}`);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
class AuthenticationError extends Error {
|
|
30
|
+
constructor(message) {
|
|
31
|
+
super(message || "Authentication failed");
|
|
32
|
+
this.name = "AuthenticationError";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
29
35
|
|
|
30
36
|
class WaitingRateLimitStrategy {
|
|
31
37
|
async onRateLimit({ response: res }) {
|
|
@@ -254,7 +260,9 @@ class TwitterGuestAuth {
|
|
|
254
260
|
}
|
|
255
261
|
const token = this.guestToken;
|
|
256
262
|
if (token == null) {
|
|
257
|
-
throw new
|
|
263
|
+
throw new AuthenticationError(
|
|
264
|
+
"Authentication token is null or undefined."
|
|
265
|
+
);
|
|
258
266
|
}
|
|
259
267
|
headers.set("authorization", `Bearer ${this.bearerToken}`);
|
|
260
268
|
headers.set("x-guest-token", token);
|
|
@@ -301,15 +309,15 @@ class TwitterGuestAuth {
|
|
|
301
309
|
});
|
|
302
310
|
await updateCookieJar(this.jar, res.headers);
|
|
303
311
|
if (!res.ok) {
|
|
304
|
-
throw new
|
|
312
|
+
throw new AuthenticationError(await res.text());
|
|
305
313
|
}
|
|
306
314
|
const o = await res.json();
|
|
307
315
|
if (o == null || o["guest_token"] == null) {
|
|
308
|
-
throw new
|
|
316
|
+
throw new AuthenticationError("guest_token not found.");
|
|
309
317
|
}
|
|
310
318
|
const newGuestToken = o["guest_token"];
|
|
311
319
|
if (typeof newGuestToken !== "string") {
|
|
312
|
-
throw new
|
|
320
|
+
throw new AuthenticationError("guest_token was not a string.");
|
|
313
321
|
}
|
|
314
322
|
this.guestToken = newGuestToken;
|
|
315
323
|
this.guestCreatedAt = /* @__PURE__ */ new Date();
|
|
@@ -330,6 +338,47 @@ const TwitterUserAuthSubtask = Type.Object({
|
|
|
330
338
|
class TwitterUserAuth extends TwitterGuestAuth {
|
|
331
339
|
constructor(bearerToken, options) {
|
|
332
340
|
super(bearerToken, options);
|
|
341
|
+
this.subtaskHandlers = /* @__PURE__ */ new Map();
|
|
342
|
+
this.initializeDefaultHandlers();
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Register a custom subtask handler or override an existing one
|
|
346
|
+
* @param subtaskId The ID of the subtask to handle
|
|
347
|
+
* @param handler The handler function that processes the subtask
|
|
348
|
+
*/
|
|
349
|
+
registerSubtaskHandler(subtaskId, handler) {
|
|
350
|
+
this.subtaskHandlers.set(subtaskId, handler);
|
|
351
|
+
}
|
|
352
|
+
initializeDefaultHandlers() {
|
|
353
|
+
this.subtaskHandlers.set(
|
|
354
|
+
"LoginJsInstrumentationSubtask",
|
|
355
|
+
this.handleJsInstrumentationSubtask.bind(this)
|
|
356
|
+
);
|
|
357
|
+
this.subtaskHandlers.set(
|
|
358
|
+
"LoginEnterUserIdentifierSSO",
|
|
359
|
+
this.handleEnterUserIdentifierSSO.bind(this)
|
|
360
|
+
);
|
|
361
|
+
this.subtaskHandlers.set(
|
|
362
|
+
"LoginEnterAlternateIdentifierSubtask",
|
|
363
|
+
this.handleEnterAlternateIdentifierSubtask.bind(this)
|
|
364
|
+
);
|
|
365
|
+
this.subtaskHandlers.set(
|
|
366
|
+
"LoginEnterPassword",
|
|
367
|
+
this.handleEnterPassword.bind(this)
|
|
368
|
+
);
|
|
369
|
+
this.subtaskHandlers.set(
|
|
370
|
+
"AccountDuplicationCheck",
|
|
371
|
+
this.handleAccountDuplicationCheck.bind(this)
|
|
372
|
+
);
|
|
373
|
+
this.subtaskHandlers.set(
|
|
374
|
+
"LoginTwoFactorAuthChallenge",
|
|
375
|
+
this.handleTwoFactorAuthChallenge.bind(this)
|
|
376
|
+
);
|
|
377
|
+
this.subtaskHandlers.set("LoginAcid", this.handleAcid.bind(this));
|
|
378
|
+
this.subtaskHandlers.set(
|
|
379
|
+
"LoginSuccessSubtask",
|
|
380
|
+
this.handleSuccessSubtask.bind(this)
|
|
381
|
+
);
|
|
333
382
|
}
|
|
334
383
|
async isLoggedIn() {
|
|
335
384
|
const res = await requestApi(
|
|
@@ -344,52 +393,49 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
344
393
|
}
|
|
345
394
|
async login(username, password, email, twoFactorSecret) {
|
|
346
395
|
await this.updateGuestToken();
|
|
396
|
+
const credentials = {
|
|
397
|
+
username,
|
|
398
|
+
password,
|
|
399
|
+
email,
|
|
400
|
+
twoFactorSecret
|
|
401
|
+
};
|
|
347
402
|
let next = await this.initLogin();
|
|
348
|
-
while ("
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
} else if (next.subtask.subtask_id === "AccountDuplicationCheck") {
|
|
361
|
-
next = await this.handleAccountDuplicationCheck(next);
|
|
362
|
-
} else if (next.subtask.subtask_id === "LoginTwoFactorAuthChallenge") {
|
|
363
|
-
if (twoFactorSecret) {
|
|
364
|
-
next = await this.handleTwoFactorAuthChallenge(next, twoFactorSecret);
|
|
365
|
-
} else {
|
|
366
|
-
throw new Error(
|
|
367
|
-
"Requested two factor authentication code but no secret provided"
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
} else if (next.subtask.subtask_id === "LoginAcid") {
|
|
371
|
-
next = await this.handleAcid(next, email);
|
|
372
|
-
} else if (next.subtask.subtask_id === "LoginSuccessSubtask") {
|
|
373
|
-
next = await this.handleSuccessSubtask(next);
|
|
403
|
+
while (next.status === "success" && next.response.subtasks?.length) {
|
|
404
|
+
const flowToken = next.response.flow_token;
|
|
405
|
+
if (flowToken == null) {
|
|
406
|
+
throw new Error("flow_token not found.");
|
|
407
|
+
}
|
|
408
|
+
const subtaskId = next.response.subtasks[0].subtask_id;
|
|
409
|
+
const handler = this.subtaskHandlers.get(subtaskId);
|
|
410
|
+
if (handler) {
|
|
411
|
+
next = await handler(subtaskId, next.response, credentials, {
|
|
412
|
+
sendFlowRequest: this.executeFlowTask.bind(this),
|
|
413
|
+
getFlowToken: () => flowToken
|
|
414
|
+
});
|
|
374
415
|
} else {
|
|
375
|
-
throw new Error(`Unknown subtask ${
|
|
416
|
+
throw new Error(`Unknown subtask ${subtaskId}`);
|
|
376
417
|
}
|
|
377
418
|
}
|
|
378
|
-
if ("
|
|
419
|
+
if (next.status === "error") {
|
|
379
420
|
throw next.err;
|
|
380
421
|
}
|
|
381
422
|
}
|
|
382
423
|
async logout() {
|
|
383
|
-
if (!this.
|
|
424
|
+
if (!this.hasToken()) {
|
|
384
425
|
return;
|
|
385
426
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
427
|
+
try {
|
|
428
|
+
await requestApi(
|
|
429
|
+
"https://api.twitter.com/1.1/account/logout.json",
|
|
430
|
+
this,
|
|
431
|
+
"POST"
|
|
432
|
+
);
|
|
433
|
+
} catch (error) {
|
|
434
|
+
console.warn("Error during logout:", error);
|
|
435
|
+
} finally {
|
|
436
|
+
this.deleteToken();
|
|
437
|
+
this.jar = new CookieJar();
|
|
438
|
+
}
|
|
393
439
|
}
|
|
394
440
|
async installCsrfToken(headers) {
|
|
395
441
|
const cookies = await this.getCookies();
|
|
@@ -428,12 +474,12 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
428
474
|
}
|
|
429
475
|
});
|
|
430
476
|
}
|
|
431
|
-
async handleJsInstrumentationSubtask(
|
|
432
|
-
return await
|
|
433
|
-
flow_token:
|
|
477
|
+
async handleJsInstrumentationSubtask(subtaskId, _prev, _credentials, api) {
|
|
478
|
+
return await api.sendFlowRequest({
|
|
479
|
+
flow_token: api.getFlowToken(),
|
|
434
480
|
subtask_inputs: [
|
|
435
481
|
{
|
|
436
|
-
subtask_id:
|
|
482
|
+
subtask_id: subtaskId,
|
|
437
483
|
js_instrumentation: {
|
|
438
484
|
response: "{}",
|
|
439
485
|
link: "next_link"
|
|
@@ -442,32 +488,32 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
442
488
|
]
|
|
443
489
|
});
|
|
444
490
|
}
|
|
445
|
-
async handleEnterAlternateIdentifierSubtask(
|
|
491
|
+
async handleEnterAlternateIdentifierSubtask(subtaskId, _prev, credentials, api) {
|
|
446
492
|
return await this.executeFlowTask({
|
|
447
|
-
flow_token:
|
|
493
|
+
flow_token: api.getFlowToken(),
|
|
448
494
|
subtask_inputs: [
|
|
449
495
|
{
|
|
450
|
-
subtask_id:
|
|
496
|
+
subtask_id: subtaskId,
|
|
451
497
|
enter_text: {
|
|
452
|
-
text: email,
|
|
498
|
+
text: credentials.email,
|
|
453
499
|
link: "next_link"
|
|
454
500
|
}
|
|
455
501
|
}
|
|
456
502
|
]
|
|
457
503
|
});
|
|
458
504
|
}
|
|
459
|
-
async handleEnterUserIdentifierSSO(
|
|
505
|
+
async handleEnterUserIdentifierSSO(subtaskId, _prev, credentials, api) {
|
|
460
506
|
return await this.executeFlowTask({
|
|
461
|
-
flow_token:
|
|
507
|
+
flow_token: api.getFlowToken(),
|
|
462
508
|
subtask_inputs: [
|
|
463
509
|
{
|
|
464
|
-
subtask_id:
|
|
510
|
+
subtask_id: subtaskId,
|
|
465
511
|
settings_list: {
|
|
466
512
|
setting_responses: [
|
|
467
513
|
{
|
|
468
514
|
key: "user_identifier",
|
|
469
515
|
response_data: {
|
|
470
|
-
text_data: { result: username }
|
|
516
|
+
text_data: { result: credentials.username }
|
|
471
517
|
}
|
|
472
518
|
}
|
|
473
519
|
],
|
|
@@ -477,26 +523,26 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
477
523
|
]
|
|
478
524
|
});
|
|
479
525
|
}
|
|
480
|
-
async handleEnterPassword(
|
|
526
|
+
async handleEnterPassword(subtaskId, _prev, credentials, api) {
|
|
481
527
|
return await this.executeFlowTask({
|
|
482
|
-
flow_token:
|
|
528
|
+
flow_token: api.getFlowToken(),
|
|
483
529
|
subtask_inputs: [
|
|
484
530
|
{
|
|
485
|
-
subtask_id:
|
|
531
|
+
subtask_id: subtaskId,
|
|
486
532
|
enter_password: {
|
|
487
|
-
password,
|
|
533
|
+
password: credentials.password,
|
|
488
534
|
link: "next_link"
|
|
489
535
|
}
|
|
490
536
|
}
|
|
491
537
|
]
|
|
492
538
|
});
|
|
493
539
|
}
|
|
494
|
-
async handleAccountDuplicationCheck(
|
|
540
|
+
async handleAccountDuplicationCheck(subtaskId, _prev, _credentials, api) {
|
|
495
541
|
return await this.executeFlowTask({
|
|
496
|
-
flow_token:
|
|
542
|
+
flow_token: api.getFlowToken(),
|
|
497
543
|
subtask_inputs: [
|
|
498
544
|
{
|
|
499
|
-
subtask_id:
|
|
545
|
+
subtask_id: subtaskId,
|
|
500
546
|
check_logged_in_account: {
|
|
501
547
|
link: "AccountDuplicationCheck_false"
|
|
502
548
|
}
|
|
@@ -504,16 +550,24 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
504
550
|
]
|
|
505
551
|
});
|
|
506
552
|
}
|
|
507
|
-
async handleTwoFactorAuthChallenge(
|
|
508
|
-
|
|
553
|
+
async handleTwoFactorAuthChallenge(subtaskId, _prev, credentials, api) {
|
|
554
|
+
if (!credentials.twoFactorSecret) {
|
|
555
|
+
return {
|
|
556
|
+
status: "error",
|
|
557
|
+
err: new AuthenticationError(
|
|
558
|
+
"Two-factor authentication is required but no secret was provided"
|
|
559
|
+
)
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
const totp = new OTPAuth.TOTP({ secret: credentials.twoFactorSecret });
|
|
509
563
|
let error;
|
|
510
564
|
for (let attempts = 1; attempts < 4; attempts += 1) {
|
|
511
565
|
try {
|
|
512
|
-
return await
|
|
513
|
-
flow_token:
|
|
566
|
+
return await api.sendFlowRequest({
|
|
567
|
+
flow_token: api.getFlowToken(),
|
|
514
568
|
subtask_inputs: [
|
|
515
569
|
{
|
|
516
|
-
subtask_id:
|
|
570
|
+
subtask_id: subtaskId,
|
|
517
571
|
enter_text: {
|
|
518
572
|
link: "next_link",
|
|
519
573
|
text: totp.generate()
|
|
@@ -528,23 +582,23 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
528
582
|
}
|
|
529
583
|
throw error;
|
|
530
584
|
}
|
|
531
|
-
async handleAcid(
|
|
585
|
+
async handleAcid(subtaskId, _prev, credentials, api) {
|
|
532
586
|
return await this.executeFlowTask({
|
|
533
|
-
flow_token:
|
|
587
|
+
flow_token: api.getFlowToken(),
|
|
534
588
|
subtask_inputs: [
|
|
535
589
|
{
|
|
536
|
-
subtask_id:
|
|
590
|
+
subtask_id: subtaskId,
|
|
537
591
|
enter_text: {
|
|
538
|
-
text: email,
|
|
592
|
+
text: credentials.email,
|
|
539
593
|
link: "next_link"
|
|
540
594
|
}
|
|
541
595
|
}
|
|
542
596
|
]
|
|
543
597
|
});
|
|
544
598
|
}
|
|
545
|
-
async handleSuccessSubtask(
|
|
599
|
+
async handleSuccessSubtask(_subtaskId, _prev, _credentials, api) {
|
|
546
600
|
return await this.executeFlowTask({
|
|
547
|
-
flow_token:
|
|
601
|
+
flow_token: api.getFlowToken(),
|
|
548
602
|
subtask_inputs: []
|
|
549
603
|
});
|
|
550
604
|
}
|
|
@@ -552,7 +606,9 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
552
606
|
const onboardingTaskUrl = "https://api.twitter.com/1.1/onboarding/task.json";
|
|
553
607
|
const token = this.guestToken;
|
|
554
608
|
if (token == null) {
|
|
555
|
-
throw new
|
|
609
|
+
throw new AuthenticationError(
|
|
610
|
+
"Authentication token is null or undefined."
|
|
611
|
+
);
|
|
556
612
|
}
|
|
557
613
|
const headers = new Headers({
|
|
558
614
|
authorization: `Bearer ${this.bearerToken}`,
|
|
@@ -577,12 +633,15 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
577
633
|
}
|
|
578
634
|
const flow = await res.json();
|
|
579
635
|
if (flow?.flow_token == null) {
|
|
580
|
-
return {
|
|
636
|
+
return {
|
|
637
|
+
status: "error",
|
|
638
|
+
err: new AuthenticationError("flow_token not found.")
|
|
639
|
+
};
|
|
581
640
|
}
|
|
582
641
|
if (flow.errors?.length) {
|
|
583
642
|
return {
|
|
584
643
|
status: "error",
|
|
585
|
-
err: new
|
|
644
|
+
err: new AuthenticationError(
|
|
586
645
|
`Authentication error (${flow.errors[0].code}): ${flow.errors[0].message}`
|
|
587
646
|
)
|
|
588
647
|
};
|
|
@@ -590,7 +649,7 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
590
649
|
if (typeof flow.flow_token !== "string") {
|
|
591
650
|
return {
|
|
592
651
|
status: "error",
|
|
593
|
-
err: new
|
|
652
|
+
err: new AuthenticationError("flow_token was not a string.")
|
|
594
653
|
};
|
|
595
654
|
}
|
|
596
655
|
const subtask = flow.subtasks?.length ? flow.subtasks[0] : void 0;
|
|
@@ -598,13 +657,12 @@ class TwitterUserAuth extends TwitterGuestAuth {
|
|
|
598
657
|
if (subtask && subtask.subtask_id === "DenyLoginSubtask") {
|
|
599
658
|
return {
|
|
600
659
|
status: "error",
|
|
601
|
-
err: new
|
|
660
|
+
err: new AuthenticationError("Authentication error: DenyLoginSubtask")
|
|
602
661
|
};
|
|
603
662
|
}
|
|
604
663
|
return {
|
|
605
664
|
status: "success",
|
|
606
|
-
|
|
607
|
-
flowToken: flow.flow_token
|
|
665
|
+
response: flow
|
|
608
666
|
};
|
|
609
667
|
}
|
|
610
668
|
}
|
|
@@ -1267,8 +1325,8 @@ async function fetchSearchProfiles(query, maxProfiles, auth, cursor) {
|
|
|
1267
1325
|
return parseSearchTimelineUsers(timeline);
|
|
1268
1326
|
}
|
|
1269
1327
|
async function getSearchTimeline(query, maxItems, searchMode, auth, cursor) {
|
|
1270
|
-
if (!auth.isLoggedIn()) {
|
|
1271
|
-
throw new
|
|
1328
|
+
if (!await auth.isLoggedIn()) {
|
|
1329
|
+
throw new AuthenticationError("Scraper is not logged-in for search.");
|
|
1272
1330
|
}
|
|
1273
1331
|
if (maxItems > 50) {
|
|
1274
1332
|
maxItems = 50;
|
|
@@ -1375,6 +1433,11 @@ function getFollowers(userId, maxProfiles, auth) {
|
|
|
1375
1433
|
});
|
|
1376
1434
|
}
|
|
1377
1435
|
async function fetchProfileFollowing(userId, maxProfiles, auth, cursor) {
|
|
1436
|
+
if (!await auth.isLoggedIn()) {
|
|
1437
|
+
throw new AuthenticationError(
|
|
1438
|
+
"Scraper is not logged-in for profile following."
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1378
1441
|
const timeline = await getFollowingTimeline(
|
|
1379
1442
|
userId,
|
|
1380
1443
|
maxProfiles,
|
|
@@ -1384,6 +1447,11 @@ async function fetchProfileFollowing(userId, maxProfiles, auth, cursor) {
|
|
|
1384
1447
|
return parseRelationshipTimeline(timeline);
|
|
1385
1448
|
}
|
|
1386
1449
|
async function fetchProfileFollowers(userId, maxProfiles, auth, cursor) {
|
|
1450
|
+
if (!await auth.isLoggedIn()) {
|
|
1451
|
+
throw new AuthenticationError(
|
|
1452
|
+
"Scraper is not logged-in for profile followers."
|
|
1453
|
+
);
|
|
1454
|
+
}
|
|
1387
1455
|
const timeline = await getFollowersTimeline(
|
|
1388
1456
|
userId,
|
|
1389
1457
|
maxProfiles,
|
|
@@ -1394,7 +1462,9 @@ async function fetchProfileFollowers(userId, maxProfiles, auth, cursor) {
|
|
|
1394
1462
|
}
|
|
1395
1463
|
async function getFollowingTimeline(userId, maxItems, auth, cursor) {
|
|
1396
1464
|
if (!auth.isLoggedIn()) {
|
|
1397
|
-
throw new
|
|
1465
|
+
throw new AuthenticationError(
|
|
1466
|
+
"Scraper is not logged-in for profile following."
|
|
1467
|
+
);
|
|
1398
1468
|
}
|
|
1399
1469
|
if (maxItems > 50) {
|
|
1400
1470
|
maxItems = 50;
|
|
@@ -1427,7 +1497,9 @@ async function getFollowingTimeline(userId, maxItems, auth, cursor) {
|
|
|
1427
1497
|
}
|
|
1428
1498
|
async function getFollowersTimeline(userId, maxItems, auth, cursor) {
|
|
1429
1499
|
if (!auth.isLoggedIn()) {
|
|
1430
|
-
throw new
|
|
1500
|
+
throw new AuthenticationError(
|
|
1501
|
+
"Scraper is not logged-in for profile followers."
|
|
1502
|
+
);
|
|
1431
1503
|
}
|
|
1432
1504
|
if (maxItems > 50) {
|
|
1433
1505
|
maxItems = 50;
|
|
@@ -1684,8 +1756,10 @@ function getTweetsAndRepliesByUserId(userId, maxTweets, auth) {
|
|
|
1684
1756
|
});
|
|
1685
1757
|
}
|
|
1686
1758
|
async function fetchLikedTweets(userId, maxTweets, cursor, auth) {
|
|
1687
|
-
if (!auth.isLoggedIn()) {
|
|
1688
|
-
throw new
|
|
1759
|
+
if (!await auth.isLoggedIn()) {
|
|
1760
|
+
throw new AuthenticationError(
|
|
1761
|
+
"Scraper is not logged-in for fetching liked tweets."
|
|
1762
|
+
);
|
|
1689
1763
|
}
|
|
1690
1764
|
if (maxTweets > 200) {
|
|
1691
1765
|
maxTweets = 200;
|
|
@@ -1790,6 +1864,20 @@ class Scraper {
|
|
|
1790
1864
|
this.token = bearerToken;
|
|
1791
1865
|
this.useGuestAuth();
|
|
1792
1866
|
}
|
|
1867
|
+
/**
|
|
1868
|
+
* Registers a subtask handler for the given subtask ID. This
|
|
1869
|
+
* will override any existing handler for the same subtask.
|
|
1870
|
+
* @param subtaskId The ID of the subtask to register the handler for.
|
|
1871
|
+
* @param subtaskHandler The handler function to register.
|
|
1872
|
+
*/
|
|
1873
|
+
registerAuthSubtaskHandler(subtaskId, subtaskHandler) {
|
|
1874
|
+
if (this.auth instanceof TwitterUserAuth) {
|
|
1875
|
+
this.auth.registerSubtaskHandler(subtaskId, subtaskHandler);
|
|
1876
|
+
}
|
|
1877
|
+
if (this.authTrends instanceof TwitterUserAuth) {
|
|
1878
|
+
this.authTrends.registerSubtaskHandler(subtaskId, subtaskHandler);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1793
1881
|
/**
|
|
1794
1882
|
* Initializes auth properties using a guest token.
|
|
1795
1883
|
* Used when creating a new instance of this class, and when logging out.
|
|
@@ -2123,5 +2211,5 @@ class Scraper {
|
|
|
2123
2211
|
}
|
|
2124
2212
|
}
|
|
2125
2213
|
|
|
2126
|
-
export { ApiError, ErrorRateLimitStrategy, Scraper, SearchMode, WaitingRateLimitStrategy };
|
|
2214
|
+
export { ApiError, AuthenticationError, ErrorRateLimitStrategy, Scraper, SearchMode, WaitingRateLimitStrategy };
|
|
2127
2215
|
//# sourceMappingURL=index.mjs.map
|