forked from flowmemo/github-index
-
Notifications
You must be signed in to change notification settings - Fork 1
/
github.js
83 lines (72 loc) · 2.37 KB
/
github.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
const debug = require('debug')('gh-index');
class GitHub {
constructor(run) {
this.run = run;
this.limit = undefined;
}
onPagination(updateBar) {
this.updateBar = updateBar;
}
static getRestLinks(link) {
const regex = /(?<=<https:\/\/api\.github\.com)(.*?&page=)([0-9]+)(?=>)/g;
let m = regex.exec(link);
const base = m[1];
const next = +m[2];
m = regex.exec(link);
const last = +m[2];
debug({ base, next, last });
const res = [];
for (let i = next; i <= last; i++) res.push(base + i);
return res;
}
getRateLimit() {
return this.run({ method: 'get', url: '/rate_limit', headers: undefined });
}
async requires(n) {
if (this.limit === undefined) {
this.limit = +(await this.getRateLimit()).headers['x-ratelimit-remaining'];
if (!this.limit) throw Error('X-RateLimit-Remaining has reached 0!');
}
if (this.limit < n) throw Error('The X-RateLimit-Remaining is not enough!');
debug(`Requiring ${n} request(s), ${this.limit - n} left`);
this.limit -= n;
}
async paginated(url) {
await this.requires(1);
const { headers: { link }, data } = await this.run({ method: 'get', url });
if (data.length === 0) return [];
const pages = [data];
if (link) {
debug({ link });
const restLinks = GitHub.getRestLinks(link);
if (this.updateBar) this.updateBar(restLinks.length, 0);
await this.requires(restLinks.length);
await Promise.all(restLinks.map(async (l, i) => {
const { data: d } = await this.run({ method: 'get', url: l });
if (this.updateBar) this.updateBar(0, 1);
pages[1 + i] = d;
}));
}
return pages.flat();
}
async getMe() {
const { data } = await this.run({ method: 'get', url: '/user' });
return data.login;
}
async getRepos(user) {
const res = await this.paginated(`/users/${user}/repos?per_page=100`);
debug({ user, repoCount: res.length });
return res;
}
async getFollowers(user) {
const res = await this.paginated(`/users/${user}/followers?per_page=100`);
debug({ user, followersCount: res.length });
return res.map(({ login }) => login);
}
async getFollowing(user) {
const res = await this.paginated(`/users/${user}/following?per_page=100`);
debug({ user, followingCount: res.length });
return res.map(({ login }) => login);
}
}
module.exports = GitHub;