@the-convocation/twitter-scraper 0.1.4 → 0.2.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/README.md +4 -1
- package/dist/api.d.ts +2 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +39 -43
- package/dist/api.js.map +1 -1
- package/dist/auth-user.d.ts +14 -0
- package/dist/auth-user.d.ts.map +1 -0
- package/dist/auth-user.js +204 -0
- package/dist/auth-user.js.map +1 -0
- package/dist/auth.d.ts +45 -28
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +62 -81
- package/dist/auth.js.map +1 -1
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/profile.d.ts +3 -3
- package/dist/profile.d.ts.map +1 -1
- package/dist/profile.js +56 -67
- package/dist/profile.js.map +1 -1
- package/dist/requests.d.ts +9 -0
- package/dist/requests.d.ts.map +1 -0
- package/dist/requests.js +26 -0
- package/dist/requests.js.map +1 -0
- package/dist/scraper.d.ts +50 -4
- package/dist/scraper.d.ts.map +1 -1
- package/dist/scraper.js +88 -27
- package/dist/scraper.js.map +1 -1
- package/dist/search.d.ts +5 -5
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +46 -58
- package/dist/search.js.map +1 -1
- package/dist/timeline-async.d.ts.map +1 -1
- package/dist/timeline-async.js +34 -56
- package/dist/timeline-async.js.map +1 -1
- package/dist/timeline.d.ts +19 -1
- package/dist/timeline.d.ts.map +1 -1
- package/dist/timeline.js +157 -116
- package/dist/timeline.js.map +1 -1
- package/dist/trends.d.ts +2 -2
- package/dist/trends.d.ts.map +1 -1
- package/dist/trends.js +31 -42
- package/dist/trends.js.map +1 -1
- package/dist/tweets.d.ts +19 -5
- package/dist/tweets.d.ts.map +1 -1
- package/dist/tweets.js +54 -46
- package/dist/tweets.js.map +1 -1
- package/package.json +21 -13
package/README.md
CHANGED
|
@@ -7,8 +7,11 @@ A port of [n0madic/twitter-scraper](https://github.com/n0madic/twitter-scraper)
|
|
|
7
7
|
>
|
|
8
8
|
> You can use this library to get the text of any user's Tweets trivially.
|
|
9
9
|
|
|
10
|
+
Note that some API operations, such as search, require logging in with a real user account.
|
|
11
|
+
Refer to the [original README](https://github.com/n0madic/twitter-scraper) for details.
|
|
12
|
+
|
|
10
13
|
## Installation
|
|
11
|
-
This package requires Node.js
|
|
14
|
+
This package requires Node.js v16.0.0 or greater.
|
|
12
15
|
|
|
13
16
|
NPM:
|
|
14
17
|
```sh
|
package/dist/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TwitterAuth } from './auth';
|
|
2
2
|
export declare const bearerToken = "AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw";
|
|
3
3
|
export declare const bearerToken2 = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA";
|
|
4
4
|
/**
|
|
@@ -11,6 +11,6 @@ export type RequestApiResult<T> = {
|
|
|
11
11
|
success: false;
|
|
12
12
|
err: Error;
|
|
13
13
|
};
|
|
14
|
-
export declare function requestApi<T>(url: string, auth:
|
|
14
|
+
export declare function requestApi<T>(url: string, auth: TwitterAuth, method?: 'GET' | 'POST'): Promise<RequestApiResult<T>>;
|
|
15
15
|
export declare function addApiParams(params: URLSearchParams, includeTweetReplies: boolean): URLSearchParams;
|
|
16
16
|
//# sourceMappingURL=api.d.ts.map
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAMrC,eAAO,MAAM,WAAW,uHAC8F,CAAC;AACvH,eAAO,MAAM,YAAY,6GACmF,CAAC;AAE7G;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC3B;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,KAAK,CAAA;CAAE,CAAC;AAEnC,wBAAsB,UAAU,CAAC,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,KAAK,GAAG,MAAc,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAqC9B;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,eAAe,EACvB,mBAAmB,EAAE,OAAO,GAC3B,eAAe,CAoCjB"}
|
package/dist/api.js
CHANGED
|
@@ -1,53 +1,49 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
4
|
};
|
|
11
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
6
|
exports.addApiParams = exports.requestApi = exports.bearerToken2 = exports.bearerToken = void 0;
|
|
13
|
-
const
|
|
7
|
+
const errors_1 = require("./errors");
|
|
8
|
+
const requests_1 = require("./requests");
|
|
9
|
+
const headers_polyfill_1 = require("headers-polyfill");
|
|
10
|
+
const cross_fetch_1 = __importDefault(require("cross-fetch"));
|
|
14
11
|
exports.bearerToken = 'AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw';
|
|
15
12
|
exports.bearerToken2 = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
|
|
16
|
-
function requestApi(url, auth) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
async function requestApi(url, auth, method = 'GET') {
|
|
14
|
+
const headers = new headers_polyfill_1.Headers();
|
|
15
|
+
await auth.installTo(headers, url);
|
|
16
|
+
let res;
|
|
17
|
+
try {
|
|
18
|
+
res = await (0, cross_fetch_1.default)(url, {
|
|
19
|
+
method,
|
|
20
|
+
headers,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
if (!(err instanceof Error)) {
|
|
25
|
+
throw err;
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
else {
|
|
48
|
-
return { success: true, value };
|
|
49
|
-
}
|
|
50
|
-
});
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
err: new Error('Failed to perform request.'),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
await (0, requests_1.updateCookieJar)(auth.cookieJar(), res.headers);
|
|
33
|
+
if (!res.ok) {
|
|
34
|
+
return {
|
|
35
|
+
success: false,
|
|
36
|
+
err: new errors_1.ApiError(res, `Response status: ${res.status}`),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const value = await res.json();
|
|
40
|
+
if (res.headers.get('x-rate-limit-incoming') == '0') {
|
|
41
|
+
auth.deleteToken();
|
|
42
|
+
return { success: true, value };
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return { success: true, value };
|
|
46
|
+
}
|
|
51
47
|
}
|
|
52
48
|
exports.requestApi = requestApi;
|
|
53
49
|
function addApiParams(params, includeTweetReplies) {
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TwitterGuestAuth } from './auth';
|
|
2
|
+
import { Headers } from 'headers-polyfill';
|
|
3
|
+
/**
|
|
4
|
+
* A user authentication token manager.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TwitterUserAuth extends TwitterGuestAuth {
|
|
7
|
+
constructor(bearerToken: string);
|
|
8
|
+
isLoggedIn(): Promise<boolean>;
|
|
9
|
+
login(username: string, password: string, email?: string): Promise<void>;
|
|
10
|
+
logout(): Promise<void>;
|
|
11
|
+
installTo(headers: Headers, url: string): Promise<void>;
|
|
12
|
+
private executeFlowTask;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=auth-user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-user.d.ts","sourceRoot":"","sources":["../src/auth-user.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAI1C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AA2C3C;;GAEG;AACH,qBAAa,eAAgB,SAAQ,gBAAgB;gBACvC,WAAW,EAAE,MAAM;IAIzB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAa9B,KAAK,CACT,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAgHV,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAcvB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAW/C,eAAe;CA+E9B"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TwitterUserAuth = void 0;
|
|
7
|
+
const auth_1 = require("./auth");
|
|
8
|
+
const api_1 = require("./api");
|
|
9
|
+
const tough_cookie_1 = require("tough-cookie");
|
|
10
|
+
const requests_1 = require("./requests");
|
|
11
|
+
const headers_polyfill_1 = require("headers-polyfill");
|
|
12
|
+
const cross_fetch_1 = __importDefault(require("cross-fetch"));
|
|
13
|
+
/**
|
|
14
|
+
* A user authentication token manager.
|
|
15
|
+
*/
|
|
16
|
+
class TwitterUserAuth extends auth_1.TwitterGuestAuth {
|
|
17
|
+
constructor(bearerToken) {
|
|
18
|
+
super(bearerToken);
|
|
19
|
+
}
|
|
20
|
+
async isLoggedIn() {
|
|
21
|
+
const res = await (0, api_1.requestApi)('https://api.twitter.com/1.1/account/verify_credentials.json', this);
|
|
22
|
+
if (!res.success) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const { value: verify } = res;
|
|
26
|
+
return verify && !verify.errors?.length;
|
|
27
|
+
}
|
|
28
|
+
async login(username, password, email) {
|
|
29
|
+
await this.updateGuestToken();
|
|
30
|
+
// Executes the potential acid step in the login flow
|
|
31
|
+
const executeFlowAcid = (ft) => this.executeFlowTask({
|
|
32
|
+
flow_token: ft,
|
|
33
|
+
subtask_inputs: [
|
|
34
|
+
{
|
|
35
|
+
subtask_id: 'LoginAcid',
|
|
36
|
+
enter_text: {
|
|
37
|
+
text: email,
|
|
38
|
+
link: 'next_link',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
// Handles the result of a flow task
|
|
44
|
+
const handleFlowTokenResult = async (p) => {
|
|
45
|
+
const result = await p;
|
|
46
|
+
const { status } = result;
|
|
47
|
+
if (status === 'error') {
|
|
48
|
+
throw result.err;
|
|
49
|
+
}
|
|
50
|
+
else if (status === 'acid') {
|
|
51
|
+
return await handleFlowTokenResult(executeFlowAcid(result.flowToken));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return result.flowToken;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
// Executes a flow subtask and handles the result
|
|
58
|
+
const executeFlowSubtask = (data) => handleFlowTokenResult(this.executeFlowTask(data));
|
|
59
|
+
await executeFlowSubtask({
|
|
60
|
+
flow_name: 'login',
|
|
61
|
+
input_flow_data: {
|
|
62
|
+
flow_context: {
|
|
63
|
+
debug_overrides: {},
|
|
64
|
+
start_location: {
|
|
65
|
+
location: 'splash_screen',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
.then((ft) => executeFlowSubtask({
|
|
71
|
+
flow_token: ft,
|
|
72
|
+
subtask_inputs: [
|
|
73
|
+
{
|
|
74
|
+
subtask_id: 'LoginJsInstrumentationSubtask',
|
|
75
|
+
js_instrumentation: {
|
|
76
|
+
response: '{}',
|
|
77
|
+
link: 'next_link',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
}))
|
|
82
|
+
.then((ft) => executeFlowSubtask({
|
|
83
|
+
flow_token: ft,
|
|
84
|
+
subtask_inputs: [
|
|
85
|
+
{
|
|
86
|
+
subtask_id: 'LoginEnterUserIdentifierSSO',
|
|
87
|
+
settings_list: {
|
|
88
|
+
setting_responses: [
|
|
89
|
+
{
|
|
90
|
+
key: 'user_identifier',
|
|
91
|
+
response_data: {
|
|
92
|
+
text_data: { result: username },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
link: 'next_link',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}))
|
|
101
|
+
.then((ft) => executeFlowSubtask({
|
|
102
|
+
flow_token: ft,
|
|
103
|
+
subtask_inputs: [
|
|
104
|
+
{
|
|
105
|
+
subtask_id: 'LoginEnterPassword',
|
|
106
|
+
enter_password: {
|
|
107
|
+
password,
|
|
108
|
+
link: 'next_link',
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
}))
|
|
113
|
+
.then((ft) => executeFlowSubtask({
|
|
114
|
+
flow_token: ft,
|
|
115
|
+
subtask_inputs: [
|
|
116
|
+
{
|
|
117
|
+
subtask_id: 'AccountDuplicationCheck',
|
|
118
|
+
check_logged_in_account: {
|
|
119
|
+
link: 'AccountDuplicationCheck_false',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
async logout() {
|
|
126
|
+
if (!this.isLoggedIn()) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
await (0, api_1.requestApi)('https://api.twitter.com/1.1/account/logout.json', this, 'POST');
|
|
130
|
+
this.deleteToken();
|
|
131
|
+
this.jar = new tough_cookie_1.CookieJar();
|
|
132
|
+
}
|
|
133
|
+
async installTo(headers, url) {
|
|
134
|
+
headers.set('authorization', `Bearer ${this.bearerToken}`);
|
|
135
|
+
headers.set('cookie', await this.jar.getCookieString(url));
|
|
136
|
+
const cookies = await this.jar.getCookies(url);
|
|
137
|
+
const xCsrfToken = cookies.find((cookie) => cookie.key === 'ct0');
|
|
138
|
+
if (xCsrfToken) {
|
|
139
|
+
headers.set('x-csrf-token', xCsrfToken.value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async executeFlowTask(data) {
|
|
143
|
+
const onboardingTaskUrl = 'https://api.twitter.com/1.1/onboarding/task.json';
|
|
144
|
+
const token = this.guestToken;
|
|
145
|
+
if (token == null) {
|
|
146
|
+
throw new Error('Authentication token is null or undefined.');
|
|
147
|
+
}
|
|
148
|
+
const headers = new headers_polyfill_1.Headers({
|
|
149
|
+
authorization: `Bearer ${this.bearerToken}`,
|
|
150
|
+
cookie: await this.jar.getCookieString(onboardingTaskUrl),
|
|
151
|
+
'content-type': 'application/json',
|
|
152
|
+
'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',
|
|
153
|
+
'x-guest-token': token,
|
|
154
|
+
'x-twitter-auth-type': 'OAuth2Client',
|
|
155
|
+
'x-twitter-active-user': 'yes',
|
|
156
|
+
'x-twitter-client-language': 'en',
|
|
157
|
+
});
|
|
158
|
+
const res = await (0, cross_fetch_1.default)(onboardingTaskUrl, {
|
|
159
|
+
method: 'POST',
|
|
160
|
+
headers: headers,
|
|
161
|
+
body: JSON.stringify(data),
|
|
162
|
+
});
|
|
163
|
+
await (0, requests_1.updateCookieJar)(this.jar, res.headers);
|
|
164
|
+
if (!res.ok) {
|
|
165
|
+
return { status: 'error', err: new Error(await res.text()) };
|
|
166
|
+
}
|
|
167
|
+
const flow = await res.json();
|
|
168
|
+
if (flow?.flow_token == null) {
|
|
169
|
+
return { status: 'error', err: new Error('flow_token not found.') };
|
|
170
|
+
}
|
|
171
|
+
if (flow.errors?.length) {
|
|
172
|
+
return {
|
|
173
|
+
status: 'error',
|
|
174
|
+
err: new Error(`Authentication error (${flow.errors[0].code}): ${flow.errors[0].message}`),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (typeof flow.flow_token !== 'string') {
|
|
178
|
+
return {
|
|
179
|
+
status: 'error',
|
|
180
|
+
err: new Error('flow_token was not a string.'),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
if (flow.subtasks?.length) {
|
|
184
|
+
if (flow.subtasks[0].subtask_id === 'LoginEnterAlternateIdentifierSubtask') {
|
|
185
|
+
return {
|
|
186
|
+
status: 'error',
|
|
187
|
+
err: new Error('Authentication error: LoginEnterAlternateIdentifierSubtask'),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
else if (flow.subtasks[0].subtask_id === 'LoginAcid') {
|
|
191
|
+
return {
|
|
192
|
+
status: 'acid',
|
|
193
|
+
flowToken: flow.flow_token,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
status: 'success',
|
|
199
|
+
flowToken: flow.flow_token,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
exports.TwitterUserAuth = TwitterUserAuth;
|
|
204
|
+
//# sourceMappingURL=auth-user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-user.js","sourceRoot":"","sources":["../src/auth-user.ts"],"names":[],"mappings":";;;;;;AAAA,iCAA0C;AAC1C,+BAAmC;AACnC,+CAAyC;AACzC,yCAA6C;AAC7C,uDAA2C;AAC3C,8DAAgC;AA0ChC;;GAEG;AACH,MAAa,eAAgB,SAAQ,uBAAgB;IACnD,YAAY,WAAmB;QAC7B,KAAK,CAAC,WAAW,CAAC,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,GAAG,GAAG,MAAM,IAAA,gBAAU,EAC1B,6DAA6D,EAC7D,IAAI,CACL,CAAC;QACF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;YAChB,OAAO,KAAK,CAAC;SACd;QAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;QAC9B,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CACT,QAAgB,EAChB,QAAgB,EAChB,KAAc;QAEd,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAE9B,qDAAqD;QACrD,MAAM,eAAe,GAAG,CAAC,EAAU,EAAE,EAAE,CACrC,IAAI,CAAC,eAAe,CAAC;YACnB,UAAU,EAAE,EAAE;YACd,cAAc,EAAE;gBACd;oBACE,UAAU,EAAE,WAAW;oBACvB,UAAU,EAAE;wBACV,IAAI,EAAE,KAAK;wBACX,IAAI,EAAE,WAAW;qBAClB;iBACF;aACF;SACF,CAAC,CAAC;QAEL,oCAAoC;QACpC,MAAM,qBAAqB,GAAG,KAAK,EACjC,CAA2B,EACV,EAAE;YACnB,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC;YACvB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;YAC1B,IAAI,MAAM,KAAK,OAAO,EAAE;gBACtB,MAAM,MAAM,CAAC,GAAG,CAAC;aAClB;iBAAM,IAAI,MAAM,KAAK,MAAM,EAAE;gBAC5B,OAAO,MAAM,qBAAqB,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;aACvE;iBAAM;gBACL,OAAO,MAAM,CAAC,SAAS,CAAC;aACzB;QACH,CAAC,CAAC;QAEF,iDAAiD;QACjD,MAAM,kBAAkB,GAAG,CAAC,IAAgC,EAAE,EAAE,CAC9D,qBAAqB,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QAEpD,MAAM,kBAAkB,CAAC;YACvB,SAAS,EAAE,OAAO;YAClB,eAAe,EAAE;gBACf,YAAY,EAAE;oBACZ,eAAe,EAAE,EAAE;oBACnB,cAAc,EAAE;wBACd,QAAQ,EAAE,eAAe;qBAC1B;iBACF;aACF;SACF,CAAC;aACC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CACX,kBAAkB,CAAC;YACjB,UAAU,EAAE,EAAE;YACd,cAAc,EAAE;gBACd;oBACE,UAAU,EAAE,+BAA+B;oBAC3C,kBAAkB,EAAE;wBAClB,QAAQ,EAAE,IAAI;wBACd,IAAI,EAAE,WAAW;qBAClB;iBACF;aACF;SACF,CAAC,CACH;aACA,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CACX,kBAAkB,CAAC;YACjB,UAAU,EAAE,EAAE;YACd,cAAc,EAAE;gBACd;oBACE,UAAU,EAAE,6BAA6B;oBACzC,aAAa,EAAE;wBACb,iBAAiB,EAAE;4BACjB;gCACE,GAAG,EAAE,iBAAiB;gCACtB,aAAa,EAAE;oCACb,SAAS,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;iCAChC;6BACF;yBACF;wBACD,IAAI,EAAE,WAAW;qBAClB;iBACF;aACF;SACF,CAAC,CACH;aACA,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CACX,kBAAkB,CAAC;YACjB,UAAU,EAAE,EAAE;YACd,cAAc,EAAE;gBACd;oBACE,UAAU,EAAE,oBAAoB;oBAChC,cAAc,EAAE;wBACd,QAAQ;wBACR,IAAI,EAAE,WAAW;qBAClB;iBACF;aACF;SACF,CAAC,CACH;aACA,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CACX,kBAAkB,CAAC;YACjB,UAAU,EAAE,EAAE;YACd,cAAc,EAAE;gBACd;oBACE,UAAU,EAAE,yBAAyB;oBACrC,uBAAuB,EAAE;wBACvB,IAAI,EAAE,+BAA+B;qBACtC;iBACF;aACF;SACF,CAAC,CACH,CAAC;IACN,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE;YACtB,OAAO;SACR;QAED,MAAM,IAAA,gBAAU,EACd,iDAAiD,EACjD,IAAI,EACJ,MAAM,CACP,CAAC;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,GAAG,IAAI,wBAAS,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAgB,EAAE,GAAW;QAC3C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;QAE3D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC;QAClE,IAAI,UAAU,EAAE;YACd,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;SAC/C;IACH,CAAC;IAEO,KAAK,CAAC,eAAe,CAC3B,IAAgC;QAEhC,MAAM,iBAAiB,GACrB,kDAAkD,CAAC;QAErD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;QAC9B,IAAI,KAAK,IAAI,IAAI,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;SAC/D;QAED,MAAM,OAAO,GAAG,IAAI,0BAAO,CAAC;YAC1B,aAAa,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE;YAC3C,MAAM,EAAE,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,iBAAiB,CAAC;YACzD,cAAc,EAAE,kBAAkB;YAClC,YAAY,EACV,4HAA4H;YAC9H,eAAe,EAAE,KAAK;YACtB,qBAAqB,EAAE,cAAc;YACrC,uBAAuB,EAAE,KAAK;YAC9B,2BAA2B,EAAE,IAAI;SAClC,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,MAAM,IAAA,qBAAK,EAAC,iBAAiB,EAAE;YACzC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QAEH,MAAM,IAAA,0BAAe,EAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAE7C,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACX,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;SAC9D;QAED,MAAM,IAAI,GAAgC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3D,IAAI,IAAI,EAAE,UAAU,IAAI,IAAI,EAAE;YAC5B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,KAAK,CAAC,uBAAuB,CAAC,EAAE,CAAC;SACrE;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE;YACvB,OAAO;gBACL,MAAM,EAAE,OAAO;gBACf,GAAG,EAAE,IAAI,KAAK,CACZ,yBAAyB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAC3E;aACF,CAAC;SACH;QAED,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE;YACvC,OAAO;gBACL,MAAM,EAAE,OAAO;gBACf,GAAG,EAAE,IAAI,KAAK,CAAC,8BAA8B,CAAC;aAC/C,CAAC;SACH;QAED,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE;YACzB,IACE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,sCAAsC,EACtE;gBACA,OAAO;oBACL,MAAM,EAAE,OAAO;oBACf,GAAG,EAAE,IAAI,KAAK,CACZ,4DAA4D,CAC7D;iBACF,CAAC;aACH;iBAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,WAAW,EAAE;gBACtD,OAAO;oBACL,MAAM,EAAE,MAAM;oBACd,SAAS,EAAE,IAAI,CAAC,UAAU;iBAC3B,CAAC;aACH;SACF;QAED,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,IAAI,CAAC,UAAU;SAC3B,CAAC;IACJ,CAAC;CACF;AA9OD,0CA8OC"}
|
package/dist/auth.d.ts
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { CookieJar } from 'tough-cookie';
|
|
2
|
+
import { Headers } from 'headers-polyfill';
|
|
3
|
+
export interface TwitterAuth {
|
|
4
|
+
/**
|
|
5
|
+
* Returns the current cookie jar.
|
|
6
|
+
*/
|
|
7
|
+
cookieJar(): CookieJar;
|
|
8
|
+
/**
|
|
9
|
+
* Returns if a user is logged-in to Twitter through this instance.
|
|
10
|
+
* @returns `true` if a user is logged-in; otherwise `false`.
|
|
11
|
+
*/
|
|
12
|
+
isLoggedIn(): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Logs into a Twitter account.
|
|
15
|
+
* @param username The username to log in with.
|
|
16
|
+
* @param password The password to log in with.
|
|
17
|
+
* @param email The password to log in with, if you have email confirmation enabled.
|
|
18
|
+
*/
|
|
19
|
+
login(username: string, password: string, email?: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Logs out of the current session.
|
|
22
|
+
*/
|
|
23
|
+
logout(): Promise<void>;
|
|
11
24
|
/**
|
|
12
|
-
* Deletes the
|
|
25
|
+
* Deletes the current guest token token.
|
|
13
26
|
*/
|
|
14
27
|
deleteToken(): void;
|
|
15
28
|
/**
|
|
@@ -22,30 +35,34 @@ export declare class TwitterGuestAuth {
|
|
|
22
35
|
* @returns The time at which the authentication token was created, or `null` if it hasn't been created yet.
|
|
23
36
|
*/
|
|
24
37
|
authenticatedAt(): Date | null;
|
|
25
|
-
/**
|
|
26
|
-
* Sets a cookie string for use in requests.
|
|
27
|
-
* @param value The new cookie to use in requests.
|
|
28
|
-
*/
|
|
29
|
-
useCookie(value: string): void;
|
|
30
|
-
/**
|
|
31
|
-
* Sets a new CSRF token for use in requests.
|
|
32
|
-
* @param value The new CSRF token to use in requests.
|
|
33
|
-
*/
|
|
34
|
-
useCsrfToken(value: string): void;
|
|
35
38
|
/**
|
|
36
39
|
* Installs the authentication information into a headers-like object. If needed, the
|
|
37
40
|
* authentication token will be updated from the API automatically.
|
|
38
|
-
* @param headers A
|
|
39
|
-
* @returns A builder that can be used to add or override other relevant data, or to
|
|
40
|
-
* complete the task.
|
|
41
|
+
* @param headers A Headers instance representing a request's headers.
|
|
41
42
|
*/
|
|
42
|
-
installTo(headers:
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
installTo(headers: Headers, url: string): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A guest authentication token manager. Automatically handles token refreshes.
|
|
47
|
+
*/
|
|
48
|
+
export declare class TwitterGuestAuth implements TwitterAuth {
|
|
49
|
+
protected bearerToken: string;
|
|
50
|
+
protected jar: CookieJar;
|
|
51
|
+
protected guestToken?: string;
|
|
52
|
+
protected guestCreatedAt?: Date;
|
|
53
|
+
constructor(bearerToken: string);
|
|
54
|
+
cookieJar(): CookieJar;
|
|
55
|
+
isLoggedIn(): Promise<boolean>;
|
|
56
|
+
login(_username: string, _password: string, _email?: string): Promise<void>;
|
|
57
|
+
logout(): Promise<void>;
|
|
58
|
+
deleteToken(): void;
|
|
59
|
+
hasToken(): boolean;
|
|
60
|
+
authenticatedAt(): Date | null;
|
|
61
|
+
installTo(headers: Headers, url: string): Promise<void>;
|
|
45
62
|
/**
|
|
46
63
|
* Updates the authentication state with a new guest token from the Twitter API.
|
|
47
64
|
*/
|
|
48
|
-
|
|
65
|
+
protected updateGuestToken(): Promise<void>;
|
|
49
66
|
/**
|
|
50
67
|
* Returns if the authentication token needs to be updated or not.
|
|
51
68
|
* @returns `true` if the token needs to be updated; `false` otherwise.
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAG3C,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,SAAS,IAAI,SAAS,CAAC;IAEvB;;;OAGG;IACH,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE/B;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;OAEG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAExB;;OAEG;IACH,WAAW,IAAI,IAAI,CAAC;IAEpB;;;OAGG;IACH,QAAQ,IAAI,OAAO,CAAC;IAEpB;;;OAGG;IACH,eAAe,IAAI,IAAI,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAClD,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC;IACzB,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;gBAEpB,WAAW,EAAE,MAAM;IAK/B,SAAS,IAAI,SAAS;IAItB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAK9B,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAMvB,WAAW;IAKX,QAAQ,IAAI,OAAO;IAInB,eAAe,IAAI,IAAI,GAAG,IAAI;IAQxB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7D;;OAEG;cACa,gBAAgB;IAiChC;;;OAGG;IACH,OAAO,CAAC,YAAY;CAQrB"}
|