keybase-proofs 2.3.25 → 2.3.28
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/CHANGELOG.md +12 -0
- package/lib/constants.js +2 -1
- package/lib/scrapers/base.js +140 -12
- package/lib/scrapers/dns.js +18 -6
- package/lib/scrapers/reddit.js +168 -13
- package/lib/scrapers/twitter.js +59 -134
- package/package.json +1 -1
- package/src/constants.iced +1 -0
- package/src/scrapers/base.iced +92 -5
- package/src/scrapers/dns.iced +13 -3
- package/src/scrapers/reddit.iced +74 -6
- package/src/scrapers/twitter.iced +23 -70
- package/SIGNED.md +0 -131
package/lib/scrapers/twitter.js
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
// Generated by IcedCoffeeScript 108.0.
|
|
1
|
+
// Generated by IcedCoffeeScript 108.0.11
|
|
2
2
|
(function() {
|
|
3
|
-
var
|
|
3
|
+
var BaseBearerToken, BaseScraper, TwitterBearerToken, TwitterScraper, bearer_token, constants, decode_sig, iced, make_ids, schema, sncmp, urlmod, v_codes, ws_normalize, __iced_k, __iced_k_noop, _bearer_token, _ref,
|
|
4
4
|
__hasProp = {}.hasOwnProperty,
|
|
5
5
|
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
|
6
6
|
|
|
7
7
|
iced = require('iced-runtime');
|
|
8
8
|
__iced_k = __iced_k_noop = function() {};
|
|
9
9
|
|
|
10
|
-
_ref = require('./base'), sncmp = _ref.sncmp, BaseScraper = _ref.BaseScraper;
|
|
10
|
+
_ref = require('./base'), sncmp = _ref.sncmp, BaseScraper = _ref.BaseScraper, BaseBearerToken = _ref.BaseBearerToken;
|
|
11
11
|
|
|
12
12
|
make_ids = require('../base').make_ids;
|
|
13
13
|
|
|
14
14
|
constants = require('../constants').constants;
|
|
15
15
|
|
|
16
|
-
Lock = require('../util').Lock;
|
|
17
|
-
|
|
18
16
|
v_codes = constants.v_codes;
|
|
19
17
|
|
|
20
18
|
decode_sig = require('kbpgp').ukm.decode_sig;
|
|
@@ -35,108 +33,22 @@
|
|
|
35
33
|
return v.join(' ');
|
|
36
34
|
};
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
TwitterBearerToken = (function(_super) {
|
|
37
|
+
__extends(TwitterBearerToken, _super);
|
|
38
|
+
|
|
39
|
+
function TwitterBearerToken(_arg) {
|
|
40
40
|
this.base = _arg.base;
|
|
41
|
-
this
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
TwitterBearerToken.__super__.constructor.call(this, {
|
|
42
|
+
name: "Twitter",
|
|
43
|
+
base: this.base,
|
|
44
|
+
access_token_url: "https://api.twitter.com/oauth2/token",
|
|
45
|
+
scope: ['history', 'read']
|
|
46
|
+
});
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
var body, cred, e, err, now, opts, rc, req, res, tok, ___iced_passed_deferral, __iced_deferrals, __iced_k;
|
|
49
|
-
__iced_k = __iced_k_noop;
|
|
50
|
-
___iced_passed_deferral = iced.findDeferral(arguments);
|
|
51
|
-
(function(_this) {
|
|
52
|
-
return (function(__iced_k) {
|
|
53
|
-
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
54
|
-
parent: ___iced_passed_deferral,
|
|
55
|
-
filename: "/home/zapu/Projects/KB/proofs/src/scrapers/twitter.iced",
|
|
56
|
-
funcname: "BearerToken.get"
|
|
57
|
-
});
|
|
58
|
-
_this._lock.acquire(__iced_deferrals.defer({
|
|
59
|
-
lineno: 32
|
|
60
|
-
}));
|
|
61
|
-
__iced_deferrals._fulfill();
|
|
62
|
-
});
|
|
63
|
-
})(this)((function(_this) {
|
|
64
|
-
return function() {
|
|
65
|
-
err = null;
|
|
66
|
-
now = Math.floor(Date.now() / 1000);
|
|
67
|
-
(function(__iced_k) {
|
|
68
|
-
if (((res = _this._tok) == null) || (now - _this._created > _this.auth.lifespan)) {
|
|
69
|
-
_this.base.log("+ Request for bearer token");
|
|
70
|
-
cred = (Buffer.from([_this.auth.key, _this.auth.secret].join(":"))).toString('base64');
|
|
71
|
-
req = 'grant_type=client_credentials';
|
|
72
|
-
opts = {
|
|
73
|
-
url: "https://api.twitter.com/oauth2/token",
|
|
74
|
-
headers: {
|
|
75
|
-
Authorization: "Basic " + cred,
|
|
76
|
-
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
|
77
|
-
'Content-Length': req.length
|
|
78
|
-
},
|
|
79
|
-
method: "post",
|
|
80
|
-
body: req
|
|
81
|
-
};
|
|
82
|
-
(function(__iced_k) {
|
|
83
|
-
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
84
|
-
parent: ___iced_passed_deferral,
|
|
85
|
-
filename: "/home/zapu/Projects/KB/proofs/src/scrapers/twitter.iced",
|
|
86
|
-
funcname: "BearerToken.get"
|
|
87
|
-
});
|
|
88
|
-
_this.base._get_url_body(opts, __iced_deferrals.defer({
|
|
89
|
-
assign_fn: (function() {
|
|
90
|
-
return function() {
|
|
91
|
-
err = arguments[0];
|
|
92
|
-
rc = arguments[1];
|
|
93
|
-
return body = arguments[2];
|
|
94
|
-
};
|
|
95
|
-
})(),
|
|
96
|
-
lineno: 52
|
|
97
|
-
}));
|
|
98
|
-
__iced_deferrals._fulfill();
|
|
99
|
-
})(function() {
|
|
100
|
-
if (err != null) {
|
|
101
|
-
_this.base.logl('error', "In getting bearer_token: " + err.message);
|
|
102
|
-
} else if (rc !== v_codes.OK) {
|
|
103
|
-
_this.base.logl('error', "HTTP error in getting bearer token: " + rc);
|
|
104
|
-
err = new Error("HTTP error: " + rc);
|
|
105
|
-
} else {
|
|
106
|
-
try {
|
|
107
|
-
body = JSON.parse(body);
|
|
108
|
-
} catch (_error) {
|
|
109
|
-
e = _error;
|
|
110
|
-
_this.base.logl('warn', "Could not parse JSON reply: " + e);
|
|
111
|
-
err = e;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
if (err != null) {
|
|
115
|
-
|
|
116
|
-
} else if ((tok = body.access_token) == null) {
|
|
117
|
-
_this.base.logl('warn', "No access token found in reply");
|
|
118
|
-
err = new Error("Twitter error: no access token");
|
|
119
|
-
} else {
|
|
120
|
-
_this._tok = tok;
|
|
121
|
-
_this._created = Math.floor(Date.now() / 1000);
|
|
122
|
-
res = _this._tok;
|
|
123
|
-
}
|
|
124
|
-
return __iced_k(_this.base.log("- Request for bearer token -> " + err));
|
|
125
|
-
});
|
|
126
|
-
} else {
|
|
127
|
-
return __iced_k();
|
|
128
|
-
}
|
|
129
|
-
})(function() {
|
|
130
|
-
_this._lock.release();
|
|
131
|
-
return cb(err, res);
|
|
132
|
-
});
|
|
133
|
-
};
|
|
134
|
-
})(this));
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
return BearerToken;
|
|
49
|
+
return TwitterBearerToken;
|
|
138
50
|
|
|
139
|
-
})();
|
|
51
|
+
})(BaseBearerToken);
|
|
140
52
|
|
|
141
53
|
_bearer_token = null;
|
|
142
54
|
|
|
@@ -144,7 +56,7 @@
|
|
|
144
56
|
var base;
|
|
145
57
|
base = _arg.base;
|
|
146
58
|
if (!_bearer_token) {
|
|
147
|
-
_bearer_token = new
|
|
59
|
+
_bearer_token = new TwitterBearerToken({
|
|
148
60
|
base: base
|
|
149
61
|
});
|
|
150
62
|
}
|
|
@@ -152,8 +64,12 @@
|
|
|
152
64
|
};
|
|
153
65
|
|
|
154
66
|
exports.TwitterScraper = TwitterScraper = (function(_super) {
|
|
67
|
+
var username_regexp;
|
|
68
|
+
|
|
155
69
|
__extends(TwitterScraper, _super);
|
|
156
70
|
|
|
71
|
+
username_regexp = /^[a-z0-9_-]{2,15}$/;
|
|
72
|
+
|
|
157
73
|
function TwitterScraper(opts) {
|
|
158
74
|
this.auth = opts.auth;
|
|
159
75
|
TwitterScraper.__super__.constructor.call(this, opts);
|
|
@@ -164,13 +80,15 @@
|
|
|
164
80
|
return new Error("Bad args to Twitter proof: no username given");
|
|
165
81
|
} else if (!(args.name != null) || (args.name !== 'twitter')) {
|
|
166
82
|
return new Error("Bad args to Twitter proof: type is " + args.name);
|
|
83
|
+
} else if (!args.username.match(username_regexp)) {
|
|
84
|
+
return new Error("Invalid username passed to Twitter proof");
|
|
167
85
|
} else {
|
|
168
86
|
return null;
|
|
169
87
|
}
|
|
170
88
|
};
|
|
171
89
|
|
|
172
90
|
TwitterScraper.prototype.hunt2 = function(_arg, cb) {
|
|
173
|
-
var api_url, err, human_url, i,
|
|
91
|
+
var api_url, endpoint_name, err, human_url, i, id, json, name, out, proof_text_check, rc, remote_id, text, u, username, ___iced_passed_deferral, __iced_deferrals, __iced_k;
|
|
174
92
|
__iced_k = __iced_k_noop;
|
|
175
93
|
___iced_passed_deferral = iced.findDeferral(arguments);
|
|
176
94
|
username = _arg.username, name = _arg.name, proof_text_check = _arg.proof_text_check;
|
|
@@ -182,24 +100,25 @@
|
|
|
182
100
|
})) != null) {
|
|
183
101
|
return cb(err, out);
|
|
184
102
|
}
|
|
103
|
+
endpoint_name = "/2/tweets/search/recent";
|
|
185
104
|
u = urlmod.format({
|
|
186
105
|
host: "api.twitter.com",
|
|
187
106
|
protocol: "https:",
|
|
188
|
-
pathname:
|
|
107
|
+
pathname: endpoint_name,
|
|
189
108
|
query: {
|
|
190
|
-
|
|
191
|
-
screen_name: username
|
|
109
|
+
query: "\"Verifying myself\" \"Keybase.io\" from:" + username
|
|
192
110
|
}
|
|
193
111
|
});
|
|
194
112
|
(function(_this) {
|
|
195
113
|
return (function(__iced_k) {
|
|
196
114
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
197
115
|
parent: ___iced_passed_deferral,
|
|
198
|
-
filename: "/
|
|
116
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
199
117
|
funcname: "TwitterScraper.hunt2"
|
|
200
118
|
});
|
|
201
119
|
_this._get_body_api({
|
|
202
|
-
url: u
|
|
120
|
+
url: u,
|
|
121
|
+
endpoint_name: endpoint_name
|
|
203
122
|
}, __iced_deferrals.defer({
|
|
204
123
|
assign_fn: (function() {
|
|
205
124
|
return function() {
|
|
@@ -208,28 +127,32 @@
|
|
|
208
127
|
return json = arguments[2];
|
|
209
128
|
};
|
|
210
129
|
})(),
|
|
211
|
-
lineno:
|
|
130
|
+
lineno: 73
|
|
212
131
|
}));
|
|
213
132
|
__iced_deferrals._fulfill();
|
|
214
133
|
});
|
|
215
134
|
})(this)((function(_this) {
|
|
216
135
|
return function() {
|
|
217
|
-
var _i, _len, _ref1;
|
|
136
|
+
var _i, _len, _ref1, _ref2;
|
|
218
137
|
_this.log("| search index " + u + " -> " + rc);
|
|
219
138
|
if (rc !== v_codes.OK) {
|
|
220
139
|
|
|
221
140
|
} else if ((typeof json === "undefined" || json === null) || (json.length === 0)) {
|
|
222
141
|
rc = v_codes.EMPTY_JSON;
|
|
142
|
+
} else if (json.data == null) {
|
|
143
|
+
rc = v_codes.INVALID_JSON;
|
|
223
144
|
} else {
|
|
224
|
-
|
|
225
|
-
|
|
145
|
+
rc = v_codes.NOT_FOUND;
|
|
146
|
+
_ref1 = json.data;
|
|
147
|
+
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
|
|
148
|
+
_ref2 = _ref1[i], text = _ref2.text, id = _ref2.id;
|
|
226
149
|
if ((_this.find_sig_in_tweet({
|
|
227
150
|
inside: text,
|
|
228
151
|
proof_text_check: proof_text_check
|
|
229
152
|
})) === v_codes.OK) {
|
|
230
153
|
_this.log("| found valid tweet in stream @ " + i);
|
|
231
154
|
rc = v_codes.OK;
|
|
232
|
-
remote_id =
|
|
155
|
+
remote_id = id;
|
|
233
156
|
api_url = human_url = _this._id_to_url(username, remote_id);
|
|
234
157
|
out = {
|
|
235
158
|
remote_id: remote_id,
|
|
@@ -295,7 +218,7 @@
|
|
|
295
218
|
(function(__iced_k) {
|
|
296
219
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
297
220
|
parent: ___iced_passed_deferral,
|
|
298
|
-
filename: "/
|
|
221
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
299
222
|
funcname: "TwitterScraper.users_lookup"
|
|
300
223
|
});
|
|
301
224
|
_this._get_body_api({
|
|
@@ -308,7 +231,7 @@
|
|
|
308
231
|
return json = arguments[2];
|
|
309
232
|
};
|
|
310
233
|
})(),
|
|
311
|
-
lineno:
|
|
234
|
+
lineno: 123
|
|
312
235
|
}));
|
|
313
236
|
__iced_deferrals._fulfill();
|
|
314
237
|
})(function() {
|
|
@@ -338,11 +261,11 @@
|
|
|
338
261
|
(function(__iced_k) {
|
|
339
262
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
340
263
|
parent: ___iced_passed_deferral,
|
|
341
|
-
filename: "/
|
|
264
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
342
265
|
funcname: "TwitterScraper.users_lookup"
|
|
343
266
|
});
|
|
344
267
|
setTimeout(__iced_deferrals.defer({
|
|
345
|
-
lineno:
|
|
268
|
+
lineno: 137
|
|
346
269
|
}), cursor_wait);
|
|
347
270
|
__iced_deferrals._fulfill();
|
|
348
271
|
})(__iced_k);
|
|
@@ -424,7 +347,7 @@
|
|
|
424
347
|
(function(__iced_k) {
|
|
425
348
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
426
349
|
parent: ___iced_passed_deferral,
|
|
427
|
-
filename: "/
|
|
350
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
428
351
|
funcname: "TwitterScraper.get_follower_ids"
|
|
429
352
|
});
|
|
430
353
|
_this._get_body_api({
|
|
@@ -437,7 +360,7 @@
|
|
|
437
360
|
return json = arguments[2];
|
|
438
361
|
};
|
|
439
362
|
})(),
|
|
440
|
-
lineno:
|
|
363
|
+
lineno: 175
|
|
441
364
|
}));
|
|
442
365
|
__iced_deferrals._fulfill();
|
|
443
366
|
})(function() {
|
|
@@ -470,11 +393,11 @@
|
|
|
470
393
|
(function(__iced_k) {
|
|
471
394
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
472
395
|
parent: ___iced_passed_deferral,
|
|
473
|
-
filename: "/
|
|
396
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
474
397
|
funcname: "TwitterScraper.get_follower_ids"
|
|
475
398
|
});
|
|
476
399
|
setTimeout(__iced_deferrals.defer({
|
|
477
|
-
lineno:
|
|
400
|
+
lineno: 191
|
|
478
401
|
}), cursor_wait);
|
|
479
402
|
__iced_deferrals._fulfill();
|
|
480
403
|
})(__iced_k);
|
|
@@ -576,7 +499,7 @@
|
|
|
576
499
|
return (function(__iced_k) {
|
|
577
500
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
578
501
|
parent: ___iced_passed_deferral,
|
|
579
|
-
filename: "/
|
|
502
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
580
503
|
funcname: "TwitterScraper.check_status"
|
|
581
504
|
});
|
|
582
505
|
_this._get_url_body({
|
|
@@ -590,7 +513,7 @@
|
|
|
590
513
|
return body_obj = arguments[2];
|
|
591
514
|
};
|
|
592
515
|
})(),
|
|
593
|
-
lineno:
|
|
516
|
+
lineno: 282
|
|
594
517
|
}));
|
|
595
518
|
__iced_deferrals._fulfill();
|
|
596
519
|
});
|
|
@@ -663,7 +586,7 @@
|
|
|
663
586
|
return (function(__iced_k) {
|
|
664
587
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
665
588
|
parent: ___iced_passed_deferral,
|
|
666
|
-
filename: "/
|
|
589
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
667
590
|
funcname: "TwitterScraper._get_bearer_token"
|
|
668
591
|
});
|
|
669
592
|
bt.get(__iced_deferrals.defer({
|
|
@@ -673,7 +596,7 @@
|
|
|
673
596
|
return tok = arguments[1];
|
|
674
597
|
};
|
|
675
598
|
})(),
|
|
676
|
-
lineno:
|
|
599
|
+
lineno: 343
|
|
677
600
|
}));
|
|
678
601
|
__iced_deferrals._fulfill();
|
|
679
602
|
});
|
|
@@ -686,16 +609,16 @@
|
|
|
686
609
|
};
|
|
687
610
|
|
|
688
611
|
TwitterScraper.prototype._get_body_api = function(_arg, cb) {
|
|
689
|
-
var args, body, err, rc, tok, url, ___iced_passed_deferral, __iced_deferrals, __iced_k;
|
|
612
|
+
var args, body, endpoint_name, err, rc, tok, url, ___iced_passed_deferral, __iced_deferrals, __iced_k;
|
|
690
613
|
__iced_k = __iced_k_noop;
|
|
691
614
|
___iced_passed_deferral = iced.findDeferral(arguments);
|
|
692
|
-
url = _arg.url;
|
|
615
|
+
url = _arg.url, endpoint_name = _arg.endpoint_name;
|
|
693
616
|
rc = body = err = null;
|
|
694
617
|
(function(_this) {
|
|
695
618
|
return (function(__iced_k) {
|
|
696
619
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
697
620
|
parent: ___iced_passed_deferral,
|
|
698
|
-
filename: "/
|
|
621
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
699
622
|
funcname: "TwitterScraper._get_body_api"
|
|
700
623
|
});
|
|
701
624
|
_this._get_bearer_token(__iced_deferrals.defer({
|
|
@@ -706,7 +629,7 @@
|
|
|
706
629
|
return tok = arguments[2];
|
|
707
630
|
};
|
|
708
631
|
})(),
|
|
709
|
-
lineno:
|
|
632
|
+
lineno: 352
|
|
710
633
|
}));
|
|
711
634
|
__iced_deferrals._fulfill();
|
|
712
635
|
});
|
|
@@ -721,12 +644,14 @@
|
|
|
721
644
|
Authorization: "Bearer " + tok
|
|
722
645
|
},
|
|
723
646
|
method: "get",
|
|
724
|
-
json: true
|
|
647
|
+
json: true,
|
|
648
|
+
log_ratelimit: endpoint_name != null,
|
|
649
|
+
endpoint_name: endpoint_name
|
|
725
650
|
};
|
|
726
651
|
(function(__iced_k) {
|
|
727
652
|
__iced_deferrals = new iced.Deferrals(__iced_k, {
|
|
728
653
|
parent: ___iced_passed_deferral,
|
|
729
|
-
filename: "/
|
|
654
|
+
filename: "/Users/michal/SourceCode/keybase/go/src/github.com/keybase/server_test_progs/proofs/src/scrapers/twitter.iced",
|
|
730
655
|
funcname: "TwitterScraper._get_body_api"
|
|
731
656
|
});
|
|
732
657
|
_this._get_url_body(args, __iced_deferrals.defer({
|
|
@@ -737,7 +662,7 @@
|
|
|
737
662
|
return body = arguments[2];
|
|
738
663
|
};
|
|
739
664
|
})(),
|
|
740
|
-
lineno:
|
|
665
|
+
lineno: 363
|
|
741
666
|
}));
|
|
742
667
|
__iced_deferrals._fulfill();
|
|
743
668
|
})(__iced_k);
|
package/package.json
CHANGED
package/src/constants.iced
CHANGED
package/src/scrapers/base.iced
CHANGED
|
@@ -6,6 +6,7 @@ pkg = require '../../package.json'
|
|
|
6
6
|
{b64find} = require '../b64extract'
|
|
7
7
|
urlmod = require 'url'
|
|
8
8
|
{callbackify} = require 'util'
|
|
9
|
+
{Lock} = require '../util'
|
|
9
10
|
|
|
10
11
|
#==============================================================
|
|
11
12
|
|
|
@@ -78,6 +79,14 @@ class BaseScraper
|
|
|
78
79
|
|
|
79
80
|
#-------------------------------------------------------------
|
|
80
81
|
|
|
82
|
+
_get_rate_limit_header : (headers, name) ->
|
|
83
|
+
# Twitter and Github can't agree on rate limit header names.
|
|
84
|
+
if ((v = parse_int_or_undefined headers.get("X-RateLimit-#{name}")) or
|
|
85
|
+
(v = parse_int_or_undefined headers.get("X-Rate-Limit-#{name}")))
|
|
86
|
+
return v
|
|
87
|
+
else
|
|
88
|
+
return undefined
|
|
89
|
+
|
|
81
90
|
_get_url_body: (opts, cb) ->
|
|
82
91
|
###
|
|
83
92
|
cb(err, status, body) only replies with body if status is 200
|
|
@@ -87,13 +96,17 @@ class BaseScraper
|
|
|
87
96
|
opts.headers["User-Agent"] ?= (opts.user_agent or user_agent)
|
|
88
97
|
await @libs.fetch opts.url, opts, defer(err, response)
|
|
89
98
|
if opts.log_ratelimit and response?
|
|
90
|
-
rl_limit =
|
|
91
|
-
rl_remaining =
|
|
92
|
-
rl_reset =
|
|
99
|
+
rl_limit = @_get_rate_limit_header response.headers, 'Limit' # 5000 for github # https://developer.github.com/v3/#rate-limiting
|
|
100
|
+
rl_remaining = @_get_rate_limit_header response.headers, 'Remaining'
|
|
101
|
+
rl_reset = @_get_rate_limit_header response.headers, 'Reset' # utc timestamp in seconds when limit will replenish
|
|
93
102
|
if rl_limit?
|
|
94
103
|
@log "| ratelimit info limit=#{rl_limit} remaining=#{rl_remaining} reset=#{rl_reset}"
|
|
95
|
-
@libs.ratelimit_inform? {
|
|
96
|
-
|
|
104
|
+
@libs.ratelimit_inform? {
|
|
105
|
+
limit: rl_limit
|
|
106
|
+
remaining: rl_remaining
|
|
107
|
+
reset: rl_reset
|
|
108
|
+
endpoint_name : opts.endpoint_name
|
|
109
|
+
}
|
|
97
110
|
rc = if err?
|
|
98
111
|
if err.message.includes('network timeout') then v_codes.TIMEOUT
|
|
99
112
|
else v_codes.HOST_UNREACHABLE
|
|
@@ -118,6 +131,8 @@ class BaseScraper
|
|
|
118
131
|
catch err
|
|
119
132
|
cb err, rc, null
|
|
120
133
|
else
|
|
134
|
+
# TODO: It's possible to get response body here, which might be useful
|
|
135
|
+
# for debugging and logging.
|
|
121
136
|
cb err, rc, null
|
|
122
137
|
|
|
123
138
|
#--------------------------------------------------------------
|
|
@@ -128,6 +143,78 @@ exports.BaseScraper = BaseScraper
|
|
|
128
143
|
|
|
129
144
|
#==============================================================
|
|
130
145
|
|
|
146
|
+
exports.BaseBearerToken = class BaseBearerToken
|
|
147
|
+
constructor : ({@name, @base, @access_token_url, @scope, @user_agent}) ->
|
|
148
|
+
unless @access_token_url?
|
|
149
|
+
throw new Error "@access_token_url is required"
|
|
150
|
+
if @scope? and not Array.isArray(@scope)
|
|
151
|
+
throw new Error "@scope has to be an array if present"
|
|
152
|
+
|
|
153
|
+
@_tok = null
|
|
154
|
+
@_created = 0
|
|
155
|
+
@_lock = new Lock()
|
|
156
|
+
@auth = @base.auth
|
|
157
|
+
|
|
158
|
+
#----------------
|
|
159
|
+
|
|
160
|
+
get : (cb) ->
|
|
161
|
+
await @_lock.acquire defer()
|
|
162
|
+
err = null
|
|
163
|
+
now = Math.floor(Date.now() / 1000)
|
|
164
|
+
|
|
165
|
+
if not (res = @_tok)? or (now - @_created > @auth.lifespan)
|
|
166
|
+
|
|
167
|
+
@base.log "+ Request for bearer token"
|
|
168
|
+
|
|
169
|
+
# Very crypto! Not sure why this is done, but it's done
|
|
170
|
+
cred = (Buffer.from [ @auth.key, @auth.secret ].join(":")).toString('base64')
|
|
171
|
+
|
|
172
|
+
req = 'grant_type=client_credentials'
|
|
173
|
+
if @scope
|
|
174
|
+
req += "&scope=#{encodeURIComponent(@scope.join(' '))}"
|
|
175
|
+
|
|
176
|
+
opts =
|
|
177
|
+
url : @access_token_url
|
|
178
|
+
headers :
|
|
179
|
+
Authorization : "Basic #{cred}"
|
|
180
|
+
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
|
181
|
+
'Content-Length': req.length
|
|
182
|
+
method : "post"
|
|
183
|
+
body : req
|
|
184
|
+
if @user_agent
|
|
185
|
+
opts.user_agent = @user_agent
|
|
186
|
+
await @base._get_url_body opts, defer err, rc, body
|
|
187
|
+
|
|
188
|
+
if err?
|
|
189
|
+
@base.logl 'error', "In getting bearer_token: #{err.message}"
|
|
190
|
+
else if (rc isnt v_codes.OK)
|
|
191
|
+
@base.logl 'error', "error in getting bearer token: #{rc}"
|
|
192
|
+
err = new Error "error: #{rc}"
|
|
193
|
+
else
|
|
194
|
+
try
|
|
195
|
+
body = JSON.parse body
|
|
196
|
+
catch e
|
|
197
|
+
@base.logl 'warn', "Could not parse JSON reply: #{e}"
|
|
198
|
+
err = e
|
|
199
|
+
|
|
200
|
+
if err? then # noop
|
|
201
|
+
else if not (tok = body.access_token)?
|
|
202
|
+
@base.logl 'warn', "No access token found in reply"
|
|
203
|
+
err = new Error "#{@name} error: no access token"
|
|
204
|
+
else
|
|
205
|
+
@_tok = tok
|
|
206
|
+
@_created = Math.floor(Date.now() / 1000)
|
|
207
|
+
res = @_tok
|
|
208
|
+
|
|
209
|
+
@base.log "- Request for bearer token for #{@name} -> err: #{err}"
|
|
210
|
+
unless err
|
|
211
|
+
@base.log "Bearer token for #{@name} is: #{res?.substr(0,5)}..."
|
|
212
|
+
|
|
213
|
+
@_lock.release()
|
|
214
|
+
cb err, res
|
|
215
|
+
|
|
216
|
+
#==============================================================
|
|
217
|
+
|
|
131
218
|
parse_int_or_undefined = (value) ->
|
|
132
219
|
if (out = Number(value)) is parseInt(value) and !isNaN(out)
|
|
133
220
|
return out
|
package/src/scrapers/dns.iced
CHANGED
|
@@ -97,13 +97,23 @@ exports.DnsScraper = class DnsScraper extends BaseScraper
|
|
|
97
97
|
|
|
98
98
|
# ---------------------------------------------------------------------------
|
|
99
99
|
|
|
100
|
+
_resolve_txt : (domain, cb) ->
|
|
101
|
+
# We can use a DNS library passed in (in the case of native-dns running on
|
|
102
|
+
# the server)
|
|
103
|
+
dnslib = @libs.dns or dns
|
|
104
|
+
try
|
|
105
|
+
dnslib.resolveTxt domain, (err, records) ->
|
|
106
|
+
cb err, records
|
|
107
|
+
catch err
|
|
108
|
+
cb err
|
|
109
|
+
|
|
110
|
+
# ---------------------------------------------------------------------------
|
|
111
|
+
|
|
100
112
|
# calls back with a v_code or null if it was ok
|
|
101
113
|
_check_status: ({domain, proof_text_check}, cb) ->
|
|
102
114
|
@log "+ DNS check for #{domain}"
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
dnslib = @libs.dns or dns
|
|
106
|
-
await dnslib.resolveTxt domain, defer err, records
|
|
116
|
+
await @_resolve_txt domain, defer err, records
|
|
107
117
|
rc = if err?
|
|
108
118
|
@log "| DNS error: #{err}"
|
|
109
119
|
v_codes.DNS_ERROR
|