diff --git a/lib/github-auth.js b/lib/github-auth.js index 3eeeaf7..d971c4b 100644 --- a/lib/github-auth.js +++ b/lib/github-auth.js @@ -11,9 +11,13 @@ try { serverSecrets = require('../secret.json'); } catch(e) {} var githubUserTokens; -autosave('.github-user-tokens.json', {data:[]}).then(function(f) { +var githubUserTokensFile = '.github-user-tokens.json'; +autosave(githubUserTokensFile, {data:[]}).then(function(f) { githubUserTokens = f; -}).catch(function(e) { console.error('Could not create github-user-tokens.json'); }); + for (var i = 0; i < githubUserTokens.length; i++) { + addGithubToken(githubUserTokens.data[i]); + } +}).catch(function(e) { console.error('Could not create ' + githubUserTokensFile); }); function setRoutes(server) { server.route(/^\/github-auth$/, function(data, match, end, ask) { @@ -75,10 +79,7 @@ function setRoutes(server) { // An unknown entity tries to connect. Let the connection linger for a minute. return setTimeout(function() { end('Invalid secret'); }, 60000); } - // Insert it only if it is not registered yet. - if (githubUserTokens.data.indexOf(data.token) === -1) { - githubUserTokens.data.push(data.token); - } + addGithubToken(data.token); end('Thanks!'); }); }; @@ -112,4 +113,62 @@ function sendTokenToAllServers(token) { })); } +// Track rate limit requests remaining. + +var reqRemaining = new Map(); +var lowestReqRemaining, lowestReqRemainingToken; + +// token: client token as a string. +// reqs: number of requests remaining. +function setReqRemaining(token, reqs) { + if (reqs < lowestReqRemaining) { + lowestReqRemaining = reqs; + lowestReqRemainingToken = token; + } + reqRemaining.set(token, reqs); +} + +function addGithubToken(token) { + setReqRemaining(token, Infinity); + // Insert it only if it is not registered yet. + if (githubUserTokens.data.indexOf(token) === -1) { + githubUserTokens.data.push(token); + } +} + +// Personal tokens allow access to GitHub private repositories. +// You can manage your personal GitHub token at +// . +if (serverSecrets && serverSecrets.gh_token) { + addGithubToken(serverSecrets.gh_token); +} + +// Modify headers, return a URL (or an object to be used by request()). +function githubRequest(request, url, cb) { + var headers = { + 'User-Agent': 'Shields.io', + 'Accept': 'application/vnd.github.v3+json', + }; + var token; + + if (lowestReqRemainingToken != null) { + token = lowestReqRemainingToken; + headers['Authorization'] = 'token ' + token; + } else if (serverSecrets && serverSecrets.gh_client_id) { + // Using our OAuth App secret grants us 5000 req/hour + // instead of the standard 60 req/hour. + apiUrl += '?client_id=' + serverSecrets.gh_client_id + + '&client_secret=' + serverSecrets.gh_client_secret; + } + + request(url, {headers: headers}, function(err, res, buffer) { + if (token != null) { + var remaining = +res.headers['x-ratelimit-remaining']; + setReqRemaining(token, remaining); + } + cb(err, res, buffer); + }); +} + exports.setRoutes = setRoutes; +exports.githubRequest = githubRequest;