@the-convocation/twitter-scraper 0.0.8
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/.commitlintrc +5 -0
- package/.eslintcache +1 -0
- package/.eslintrc.js +24 -0
- package/.gitattributes +78 -0
- package/.prettierignore +2 -0
- package/.prettierrc +5 -0
- package/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/api.js +77 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.js +119 -0
- package/dist/auth.js.map +1 -0
- package/dist/profile.js +103 -0
- package/dist/profile.js.map +1 -0
- package/dist/scraper.js +153 -0
- package/dist/scraper.js.map +1 -0
- package/dist/search.js +84 -0
- package/dist/search.js.map +1 -0
- package/dist/timeline-async.js +59 -0
- package/dist/timeline-async.js.map +1 -0
- package/dist/timeline.js +228 -0
- package/dist/timeline.js.map +1 -0
- package/dist/trends.js +46 -0
- package/dist/trends.js.map +1 -0
- package/dist/tweets.js +59 -0
- package/dist/tweets.js.map +1 -0
- package/dist/types/api.d.ts +16 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/auth.d.ts +55 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/profile.d.ts +67 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/scraper.d.ts +102 -0
- package/dist/types/scraper.d.ts.map +1 -0
- package/dist/types/search.d.ts +19 -0
- package/dist/types/search.d.ts.map +1 -0
- package/dist/types/timeline-async.d.ts +15 -0
- package/dist/types/timeline-async.d.ts.map +1 -0
- package/dist/types/timeline.d.ts +154 -0
- package/dist/types/timeline.d.ts.map +1 -0
- package/dist/types/trends.d.ts +3 -0
- package/dist/types/trends.d.ts.map +1 -0
- package/dist/types/tweets.d.ts +52 -0
- package/dist/types/tweets.d.ts.map +1 -0
- package/package.json +52 -0
package/.commitlintrc
ADDED
package/.eslintcache
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\gh-pages.js":"1","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\api.ts":"2","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\auth.ts":"3","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\profile.ts":"4","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\scraper.ts":"5","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\search.ts":"6","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\timeline.ts":"7","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\trends.ts":"8","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\tweets.ts":"9","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\search.test.ts":"10","D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\trends.test.ts":"11"},{"size":214,"mtime":1653244686068,"results":"12","hashOfConfig":"13"},{"size":2684,"mtime":1653242281934,"results":"14","hashOfConfig":"13"},{"size":3541,"mtime":1653242491067,"results":"15","hashOfConfig":"13"},{"size":4052,"mtime":1653242369416,"results":"16","hashOfConfig":"13"},{"size":6508,"mtime":1653242879269,"results":"17","hashOfConfig":"13"},{"size":2948,"mtime":1653242319801,"results":"18","hashOfConfig":"13"},{"size":10820,"mtime":1653242429993,"results":"19","hashOfConfig":"13"},{"size":1490,"mtime":1653241871443,"results":"20","hashOfConfig":"13"},{"size":2819,"mtime":1653242343249,"results":"21","hashOfConfig":"13"},{"size":1802,"mtime":1653243993888,"results":"22","hashOfConfig":"13"},{"size":259,"mtime":1653244015428,"results":"23","hashOfConfig":"13"},{"filePath":"24","messages":"25","suppressedMessages":"26","errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"iisw30",{"filePath":"27","messages":"28","suppressedMessages":"29","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"30","messages":"31","suppressedMessages":"32","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"33","messages":"34","suppressedMessages":"35","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","suppressedMessages":"38","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"39","messages":"40","suppressedMessages":"41","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","suppressedMessages":"44","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"45","messages":"46","suppressedMessages":"47","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"48","messages":"49","suppressedMessages":"50","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"51","messages":"52","suppressedMessages":"53","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"54","messages":"55","suppressedMessages":"56","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\gh-pages.js",["57"],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\api.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\auth.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\profile.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\scraper.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\search.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\timeline.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\trends.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\tweets.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\search.test.ts",[],[],"D:\\Users\\luca\\Documents\\GitHub\\twitter-scraper\\src\\trends.test.ts",[],[],{"ruleId":"58","severity":2,"message":"59","line":1,"column":17,"nodeType":"60","messageId":"61","endLine":1,"endColumn":36},"@typescript-eslint/no-var-requires","Require statement not part of import statement.","CallExpression","noVarReqs"]
|
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: '@typescript-eslint/parser',
|
|
3
|
+
parserOptions: {
|
|
4
|
+
tsconfigRootDir: __dirname,
|
|
5
|
+
sourceType: 'module',
|
|
6
|
+
},
|
|
7
|
+
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
8
|
+
extends: [
|
|
9
|
+
'plugin:@typescript-eslint/recommended',
|
|
10
|
+
'plugin:prettier/recommended',
|
|
11
|
+
],
|
|
12
|
+
root: true,
|
|
13
|
+
env: {
|
|
14
|
+
node: true,
|
|
15
|
+
jest: true,
|
|
16
|
+
},
|
|
17
|
+
ignorePatterns: ['**/*.js'],
|
|
18
|
+
rules: {
|
|
19
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
20
|
+
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
21
|
+
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
22
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
23
|
+
},
|
|
24
|
+
};
|
package/.gitattributes
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Auto detect text files and perform LF normalization
|
|
2
|
+
* text=auto
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# The above will handle all files NOT found below
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
# Code
|
|
9
|
+
*.js text eol=lf
|
|
10
|
+
*.ts text eol=lf
|
|
11
|
+
|
|
12
|
+
# Documents
|
|
13
|
+
*.bibtex text diff=bibtex
|
|
14
|
+
*.doc diff=astextplain
|
|
15
|
+
*.DOC diff=astextplain
|
|
16
|
+
*.docx diff=astextplain
|
|
17
|
+
*.DOCX diff=astextplain
|
|
18
|
+
*.dot diff=astextplain
|
|
19
|
+
*.DOT diff=astextplain
|
|
20
|
+
*.pdf diff=astextplain
|
|
21
|
+
*.PDF diff=astextplain
|
|
22
|
+
*.rtf diff=astextplain
|
|
23
|
+
*.RTF diff=astextplain
|
|
24
|
+
*.md text diff=markdown
|
|
25
|
+
*.mdx text diff=markdown
|
|
26
|
+
*.tex text diff=tex
|
|
27
|
+
*.adoc text
|
|
28
|
+
*.textile text
|
|
29
|
+
*.mustache text
|
|
30
|
+
*.csv text
|
|
31
|
+
*.tab text
|
|
32
|
+
*.tsv text
|
|
33
|
+
*.txt text
|
|
34
|
+
*.sql text
|
|
35
|
+
|
|
36
|
+
# Graphics
|
|
37
|
+
*.png binary
|
|
38
|
+
*.jpg binary
|
|
39
|
+
*.jpeg binary
|
|
40
|
+
*.gif binary
|
|
41
|
+
*.tif binary
|
|
42
|
+
*.tiff binary
|
|
43
|
+
*.ico binary
|
|
44
|
+
*.svg text
|
|
45
|
+
*.eps binary
|
|
46
|
+
|
|
47
|
+
# Scripts
|
|
48
|
+
*.bash text eol=lf
|
|
49
|
+
*.fish text eol=lf
|
|
50
|
+
*.sh text eol=lf
|
|
51
|
+
*.zsh text eol=lf
|
|
52
|
+
*.bat text eol=crlf
|
|
53
|
+
*.cmd text eol=crlf
|
|
54
|
+
*.ps1 text eol=crlf
|
|
55
|
+
|
|
56
|
+
# Serialisation
|
|
57
|
+
*.json text
|
|
58
|
+
*.toml text
|
|
59
|
+
*.xml text
|
|
60
|
+
*.yaml text
|
|
61
|
+
*.yml text
|
|
62
|
+
|
|
63
|
+
# Archives
|
|
64
|
+
*.7z binary
|
|
65
|
+
*.gz binary
|
|
66
|
+
*.tar binary
|
|
67
|
+
*.tgz binary
|
|
68
|
+
*.zip binary
|
|
69
|
+
|
|
70
|
+
# Text files where line endings should be preserved
|
|
71
|
+
*.patch -text
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# Exclude files from exporting
|
|
75
|
+
#
|
|
76
|
+
|
|
77
|
+
.gitattributes export-ignore
|
|
78
|
+
.gitignore export-ignore
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 karashiiro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# twitter-scraper
|
|
2
|
+
[](https://the-convocation.github.io/twitter-scraper/)
|
|
3
|
+
|
|
4
|
+
A port of [n0madic/twitter-scraper](https://github.com/n0madic/twitter-scraper) to Node.js.
|
|
5
|
+
|
|
6
|
+
> Twitter's API is annoying to work with, and has lots of limitations — luckily their frontend (JavaScript) has it's own API, which I reverse-engineered. No API rate limits. No tokens needed. No restrictions. Extremely fast.
|
|
7
|
+
>
|
|
8
|
+
> You can use this library to get the text of any user's Tweets trivially.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
This package requires Node.js v15.10.0 or greater.
|
|
12
|
+
|
|
13
|
+
NPM:
|
|
14
|
+
```sh
|
|
15
|
+
npm install @the-convocation/twitter-scraper
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Yarn:
|
|
19
|
+
```sh
|
|
20
|
+
yarn add @the-convocation/twitter-scraper
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
TypeScript types have been bundled with the distribution.
|
|
24
|
+
|
|
25
|
+
## Contributing
|
|
26
|
+
We use [Conventional Commits](https://www.conventionalcommits.org), and enforce this with precommit checks.
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { gotScraping } from 'got-scraping';
|
|
11
|
+
export const bearerToken = 'AAAAAAAAAAAAAAAAAAAAAPYXBAAAAAAACLXUNDekMxqa8h%2F40K4moUkGsoc%3DTYfbDKbT3jJPCEVnMYqilB28NHfOPqkca3qaAxGfsyKCs0wRbw';
|
|
12
|
+
export const bearerToken2 = 'AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA';
|
|
13
|
+
export function requestApi(url, auth) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const headers = {};
|
|
16
|
+
yield auth.installTo(headers);
|
|
17
|
+
let res;
|
|
18
|
+
try {
|
|
19
|
+
res = yield gotScraping.get({
|
|
20
|
+
url,
|
|
21
|
+
headers,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (!(err instanceof Error)) {
|
|
26
|
+
throw err;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
err: new Error('Failed to perform request.'),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (res.statusCode != 200 && res.statusCode != 403) {
|
|
34
|
+
return {
|
|
35
|
+
success: false,
|
|
36
|
+
err: new Error(`Response status: ${res.statusCode}`),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const value = JSON.parse(res.body);
|
|
40
|
+
if (res.headers['x-rate-limit-incoming'] == '0') {
|
|
41
|
+
auth.deleteToken();
|
|
42
|
+
return { success: true, value };
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return { success: true, value };
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export function addApiParams(params, includeTweetReplies) {
|
|
50
|
+
params.set('include_profile_interstitial_type', '1');
|
|
51
|
+
params.set('include_blocking', '1');
|
|
52
|
+
params.set('include_blocked_by', '1');
|
|
53
|
+
params.set('include_followed_by', '1');
|
|
54
|
+
params.set('include_want_retweets', '1');
|
|
55
|
+
params.set('include_mute_edge', '1');
|
|
56
|
+
params.set('include_can_dm', '1');
|
|
57
|
+
params.set('include_can_media_tag', '1');
|
|
58
|
+
params.set('include_ext_has_nft_avatar', '1');
|
|
59
|
+
params.set('skip_status', '1');
|
|
60
|
+
params.set('cards_platform', 'Web-12');
|
|
61
|
+
params.set('include_cards', '1');
|
|
62
|
+
params.set('include_ext_alt_text', 'true');
|
|
63
|
+
params.set('include_quote_count', 'true');
|
|
64
|
+
params.set('include_reply_count', '1');
|
|
65
|
+
params.set('tweet_mode', 'extended');
|
|
66
|
+
params.set('include_entities', 'true');
|
|
67
|
+
params.set('include_user_entities', 'true');
|
|
68
|
+
params.set('include_ext_media_color', 'true');
|
|
69
|
+
params.set('include_ext_media_availability', 'true');
|
|
70
|
+
params.set('include_ext_sensitive_media_warning', 'true');
|
|
71
|
+
params.set('send_error_codes', 'true');
|
|
72
|
+
params.set('simple_quoted_tweet', 'true');
|
|
73
|
+
params.set('include_tweet_replies', `${includeTweetReplies}`);
|
|
74
|
+
params.set('ext', 'mediaStats,highlightedLabel,hasNftAvatar,voiceInfo,superFollowMetadata');
|
|
75
|
+
return params;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { gotScraping } from 'got-scraping';
|
|
11
|
+
/**
|
|
12
|
+
* A guest authentication token manager. Automatically handles token refreshes.
|
|
13
|
+
*/
|
|
14
|
+
export class TwitterGuestAuth {
|
|
15
|
+
constructor(bearerToken, cookie, xCsrfToken) {
|
|
16
|
+
this.bearerToken = bearerToken;
|
|
17
|
+
this.cookie = cookie;
|
|
18
|
+
this.xCsrfToken = xCsrfToken;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Deletes the authentication token.
|
|
22
|
+
*/
|
|
23
|
+
deleteToken() {
|
|
24
|
+
delete this.guestToken;
|
|
25
|
+
delete this.guestCreatedAt;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns if the authentication state has a token.
|
|
29
|
+
* @returns `true` if the authentication state has a token; `false` otherwise.
|
|
30
|
+
*/
|
|
31
|
+
hasToken() {
|
|
32
|
+
return this.guestToken != null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns the time that authentication was performed.
|
|
36
|
+
* @returns The time at which the authentication token was created, or `null` if it hasn't been created yet.
|
|
37
|
+
*/
|
|
38
|
+
authenticatedAt() {
|
|
39
|
+
if (this.guestCreatedAt == null) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return new Date(this.guestCreatedAt);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Sets a cookie string for use in requests.
|
|
46
|
+
* @param value The new cookie to use in requests.
|
|
47
|
+
*/
|
|
48
|
+
useCookie(value) {
|
|
49
|
+
this.cookie = value;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Sets a new CSRF token for use in requests.
|
|
53
|
+
* @param value The new CSRF token to use in requests.
|
|
54
|
+
*/
|
|
55
|
+
useCsrfToken(value) {
|
|
56
|
+
this.xCsrfToken = value;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Installs the authentication information into a headers-like object. If needed, the
|
|
60
|
+
* authentication token will be updated from the API automatically.
|
|
61
|
+
* @param headers A key-value object representing a request's headers.
|
|
62
|
+
* @returns A builder that can be used to add or override other relevant data, or to
|
|
63
|
+
* complete the task.
|
|
64
|
+
*/
|
|
65
|
+
installTo(headers) {
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
if (this.shouldUpdate()) {
|
|
68
|
+
yield this.updateToken();
|
|
69
|
+
}
|
|
70
|
+
const token = this.guestToken;
|
|
71
|
+
if (token == null) {
|
|
72
|
+
throw new Error('Authentication token is null or undefined.');
|
|
73
|
+
}
|
|
74
|
+
headers['Authorization'] = `Bearer ${this.bearerToken}`;
|
|
75
|
+
headers['X-Guest-Token'] = token;
|
|
76
|
+
if (this.cookie != null && this.xCsrfToken != null) {
|
|
77
|
+
headers['Cookie'] = this.cookie;
|
|
78
|
+
headers['x-csrf-token'] = this.xCsrfToken;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Updates the authentication state with a new guest token from the Twitter API.
|
|
84
|
+
*/
|
|
85
|
+
updateToken() {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const res = yield gotScraping.post({
|
|
88
|
+
url: 'https://api.twitter.com/1.1/guest/activate.json',
|
|
89
|
+
headers: {
|
|
90
|
+
Authorization: `Bearer ${this.bearerToken}`,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
if (res.statusCode != 200) {
|
|
94
|
+
throw new Error(res.body);
|
|
95
|
+
}
|
|
96
|
+
const o = JSON.parse(res.body);
|
|
97
|
+
if (o == null || o['guest_token'] == null) {
|
|
98
|
+
throw new Error('guest_token not found.');
|
|
99
|
+
}
|
|
100
|
+
const newGuestToken = o['guest_token'];
|
|
101
|
+
if (typeof newGuestToken !== 'string') {
|
|
102
|
+
throw new Error('guest_token was not a string.');
|
|
103
|
+
}
|
|
104
|
+
this.guestToken = newGuestToken;
|
|
105
|
+
this.guestCreatedAt = new Date();
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Returns if the authentication token needs to be updated or not.
|
|
110
|
+
* @returns `true` if the token needs to be updated; `false` otherwise.
|
|
111
|
+
*/
|
|
112
|
+
shouldUpdate() {
|
|
113
|
+
return (!this.hasToken() ||
|
|
114
|
+
(this.guestCreatedAt != null &&
|
|
115
|
+
this.guestCreatedAt <
|
|
116
|
+
new Date(new Date().valueOf() - 3 * 60 * 60 * 1000)));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/profile.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { requestApi } from './api';
|
|
11
|
+
export function parseProfile(user) {
|
|
12
|
+
var _a, _b;
|
|
13
|
+
const profile = {
|
|
14
|
+
avatar: user.profile_image_url_https,
|
|
15
|
+
banner: user.profile_banner_url,
|
|
16
|
+
biography: user.description,
|
|
17
|
+
followersCount: user.followers_count,
|
|
18
|
+
followingCount: user.favourites_count,
|
|
19
|
+
friendsCount: user.friends_count,
|
|
20
|
+
isPrivate: user.protected,
|
|
21
|
+
isVerified: user.verified,
|
|
22
|
+
likesCount: user.favourites_count,
|
|
23
|
+
listedCount: user.listed_count,
|
|
24
|
+
location: user.location,
|
|
25
|
+
name: user.name,
|
|
26
|
+
pinnedTweetIds: user.pinned_tweet_ids_str,
|
|
27
|
+
tweetsCount: user.statuses_count,
|
|
28
|
+
url: `https://twitter.com/${user.screen_name}`,
|
|
29
|
+
userId: user.id_str,
|
|
30
|
+
username: user.screen_name,
|
|
31
|
+
};
|
|
32
|
+
if (user.created_at != null) {
|
|
33
|
+
profile.joined = new Date(Date.parse(user.created_at));
|
|
34
|
+
}
|
|
35
|
+
const urls = (_b = (_a = user.entities) === null || _a === void 0 ? void 0 : _a.url) === null || _b === void 0 ? void 0 : _b.urls;
|
|
36
|
+
if ((urls === null || urls === void 0 ? void 0 : urls.length) != null && (urls === null || urls === void 0 ? void 0 : urls.length) > 0) {
|
|
37
|
+
profile.website = urls[0].expanded_url;
|
|
38
|
+
}
|
|
39
|
+
return profile;
|
|
40
|
+
}
|
|
41
|
+
export function getProfile(username, auth) {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
const res = yield requestApi('https://api.twitter.com/graphql/4S2ihIKfF3xhp-ENxvUAfQ/UserByScreenName?variables=%7B%22screen_name%22%3A%22' +
|
|
44
|
+
username +
|
|
45
|
+
'%22%2C%22withHighlightedLabel%22%3Atrue%7D', auth);
|
|
46
|
+
if (!res.success) {
|
|
47
|
+
throw res.err;
|
|
48
|
+
}
|
|
49
|
+
const { value } = res;
|
|
50
|
+
const { errors } = value;
|
|
51
|
+
if (errors != null && errors.length > 0) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
err: new Error(errors[0].message),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const { user } = value.data;
|
|
58
|
+
const { legacy } = user;
|
|
59
|
+
if (user.rest_id == null || user.rest_id.length === 0) {
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
err: new Error('rest_id not found.'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
legacy.id_str = user.rest_id;
|
|
66
|
+
if (legacy.screen_name == null || legacy.screen_name.length === 0) {
|
|
67
|
+
return {
|
|
68
|
+
success: false,
|
|
69
|
+
err: new Error(`Either ${username} does not exist or is private.`),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
success: true,
|
|
74
|
+
value: parseProfile(user.legacy),
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const idCache = new Map();
|
|
79
|
+
export function getUserIdByScreenName(screenName, auth) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const cached = idCache.get(screenName);
|
|
82
|
+
if (cached != null) {
|
|
83
|
+
return { success: true, value: cached };
|
|
84
|
+
}
|
|
85
|
+
const profileRes = yield getProfile(screenName, auth);
|
|
86
|
+
if (!profileRes.success) {
|
|
87
|
+
return profileRes;
|
|
88
|
+
}
|
|
89
|
+
const profile = profileRes.value;
|
|
90
|
+
if (profile.userId != null) {
|
|
91
|
+
idCache.set(screenName, profile.userId);
|
|
92
|
+
return {
|
|
93
|
+
success: true,
|
|
94
|
+
value: profile.userId,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
err: new Error('User ID is undefined.'),
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"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"}
|
package/dist/scraper.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { bearerToken, bearerToken2 } from './api';
|
|
11
|
+
import { TwitterGuestAuth } from './auth';
|
|
12
|
+
import { getProfile, getUserIdByScreenName } from './profile';
|
|
13
|
+
import { fetchSearchProfiles, fetchSearchTweets, SearchMode, searchProfiles, searchTweets, } from './search';
|
|
14
|
+
import { getTrends } from './trends';
|
|
15
|
+
import { getTweet, getTweets } from './tweets';
|
|
16
|
+
/**
|
|
17
|
+
* An interface to Twitter's undocumented API.
|
|
18
|
+
* Reusing Scraper objects is recommended to minimize the time spent authenticating unnecessarily.
|
|
19
|
+
*/
|
|
20
|
+
export class Scraper {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new Scraper object. Scrapers maintain their own guest tokens for Twitter's internal API.
|
|
23
|
+
* Reusing Scraper objects is recommended to minimize the time spent authenticating unnecessarily.
|
|
24
|
+
*/
|
|
25
|
+
constructor() {
|
|
26
|
+
this.auth = new TwitterGuestAuth(bearerToken);
|
|
27
|
+
this.authTrends = new TwitterGuestAuth(bearerToken2);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetches a Twitter profile.
|
|
31
|
+
* @param username The Twitter username of the profile to fetch, without an `@` at the beginning.
|
|
32
|
+
* @returns The requested profile.
|
|
33
|
+
*/
|
|
34
|
+
getProfile(username) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
const res = yield getProfile(username, this.auth);
|
|
37
|
+
return this.handleResponse(res);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Fetches the user ID corresponding to the provided screen name.
|
|
42
|
+
* @param screenName The Twitter screen name of the profile to fetch.
|
|
43
|
+
* @returns The ID of the corresponding account.
|
|
44
|
+
*/
|
|
45
|
+
getUserIdByScreenName(screenName) {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const res = yield getUserIdByScreenName(screenName, this.auth);
|
|
48
|
+
return this.handleResponse(res);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fetches tweets from Twitter.
|
|
53
|
+
* @param query The search query. Any Twitter-compatible query format can be used.
|
|
54
|
+
* @param maxTweets The maximum number of tweets to return.
|
|
55
|
+
* @param includeReplies Whether or not replies should be included in the response.
|
|
56
|
+
* @param searchMode The category filter to apply to the search. Defaults to `Top`.
|
|
57
|
+
* @returns An async generator of tweets matching the provided filters.
|
|
58
|
+
*/
|
|
59
|
+
searchTweets(query, maxTweets, includeReplies, searchMode = SearchMode.Top) {
|
|
60
|
+
return searchTweets(query, maxTweets, includeReplies, searchMode, this.auth);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Fetches profiles from Twitter.
|
|
64
|
+
* @param query The search query. Any Twitter-compatible query format can be used.
|
|
65
|
+
* @param maxProfiles The maximum number of profiles to return.
|
|
66
|
+
* @returns An async generator of tweets matching the provided filters.
|
|
67
|
+
*/
|
|
68
|
+
searchProfiles(query, maxProfiles) {
|
|
69
|
+
return searchProfiles(query, maxProfiles, this.auth);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Fetches tweets from Twitter.
|
|
73
|
+
* @param query The search query. Any Twitter-compatible query format can be used.
|
|
74
|
+
* @param maxTweets The maximum number of tweets to return.
|
|
75
|
+
* @param includeReplies Whether or not replies should be included in the response.
|
|
76
|
+
* @param searchMode The category filter to apply to the search. Defaults to `Top`.
|
|
77
|
+
* @param cursor The search cursor, which can be passed into further requests for more results.
|
|
78
|
+
* @returns A page of results, containing a cursor that can be used in further requests.
|
|
79
|
+
*/
|
|
80
|
+
fetchSearchTweets(query, maxTweets, includeReplies, searchMode, cursor) {
|
|
81
|
+
return fetchSearchTweets(query, maxTweets, includeReplies, searchMode, this.auth, cursor);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Fetches profiles from Twitter.
|
|
85
|
+
* @param query The search query. Any Twitter-compatible query format can be used.
|
|
86
|
+
* @param maxProfiles The maximum number of profiles to return.
|
|
87
|
+
* @param cursor The search cursor, which can be passed into further requests for more results.
|
|
88
|
+
* @returns A page of results, containing a cursor that can be used in further requests.
|
|
89
|
+
*/
|
|
90
|
+
fetchSearchProfiles(query, maxProfiles, cursor) {
|
|
91
|
+
return fetchSearchProfiles(query, maxProfiles, this.auth, cursor);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fetches the current trends from Twitter.
|
|
95
|
+
* @returns The current list of trends.
|
|
96
|
+
*/
|
|
97
|
+
getTrends() {
|
|
98
|
+
return getTrends(this.authTrends);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Fetches tweets from a Twitter user.
|
|
102
|
+
* @param user The user whose tweets should be returned.
|
|
103
|
+
* @param maxTweets The maximum number of tweets to return.
|
|
104
|
+
* @param includeReplies Whether or not to include tweet replies.
|
|
105
|
+
* @returns An async generator of tweets from the provided user.
|
|
106
|
+
*/
|
|
107
|
+
getTweets(user, maxTweets, includeReplies) {
|
|
108
|
+
return getTweets(user, maxTweets, includeReplies, this.auth);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Fetches a single tweet.
|
|
112
|
+
* @param id The ID of the tweet to fetch.
|
|
113
|
+
* @param includeReplies Whether or not to include tweet replies.
|
|
114
|
+
* @returns The request tweet, or `null` if it couldn't be fetched.
|
|
115
|
+
*/
|
|
116
|
+
getTweet(id, includeReplies) {
|
|
117
|
+
return getTweet(id, includeReplies, this.auth);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns if the scraper has a guest token. The token may not be valid.
|
|
121
|
+
* @returns `true` if the scraper has a guest token; otherwise `false`.
|
|
122
|
+
*/
|
|
123
|
+
hasGuestToken() {
|
|
124
|
+
return this.auth.hasToken() || this.authTrends.hasToken();
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Sets the optional cookie to be used in requests.
|
|
128
|
+
* @param cookie The cookie to be used in requests.
|
|
129
|
+
* @returns This scraper instance.
|
|
130
|
+
*/
|
|
131
|
+
withCookie(cookie) {
|
|
132
|
+
this.auth.useCookie(cookie);
|
|
133
|
+
this.authTrends.useCookie(cookie);
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Sets the optional CSRF token to be used in requests.
|
|
138
|
+
* @param token The CSRF token to be used in requests.
|
|
139
|
+
* @returns This scraper instance.
|
|
140
|
+
*/
|
|
141
|
+
withXCsrfToken(token) {
|
|
142
|
+
this.auth.useCsrfToken(token);
|
|
143
|
+
this.authTrends.useCsrfToken(token);
|
|
144
|
+
return this;
|
|
145
|
+
}
|
|
146
|
+
handleResponse(res) {
|
|
147
|
+
if (!res.success) {
|
|
148
|
+
throw res.err;
|
|
149
|
+
}
|
|
150
|
+
return res.value;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=scraper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scraper.js","sourceRoot":"","sources":["../src/scraper.ts"],"names":[],"mappings":"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"}
|