diff --git a/api/index.js b/api/index.js index 392b694..803680e 100644 --- a/api/index.js +++ b/api/index.js @@ -18,7 +18,9 @@ module.exports = async (req, res) => { } = req.query; let stats; + res.setHeader("Cache-Control", "public, max-age=300"); res.setHeader("Content-Type", "image/svg+xml"); + try { stats = await fetchStats(username); } catch (err) { diff --git a/api/pin.js b/api/pin.js index 2d69c0e..a28733c 100644 --- a/api/pin.js +++ b/api/pin.js @@ -14,6 +14,8 @@ module.exports = async (req, res) => { } = req.query; let repoData; + + res.setHeader("Cache-Control", "public, max-age=300"); res.setHeader("Content-Type", "image/svg+xml"); try { diff --git a/src/fetchRepo.js b/src/fetchRepo.js index c7b7c3e..a248a7e 100644 --- a/src/fetchRepo.js +++ b/src/fetchRepo.js @@ -5,8 +5,9 @@ async function fetchRepo(username, reponame) { throw new Error("Invalid username or reponame"); } - const res = await request({ - query: ` + const res = await request( + { + query: ` fragment RepoInfo on Repository { name stargazers { @@ -33,11 +34,15 @@ async function fetchRepo(username, reponame) { } } `, - variables: { - login: username, - repo: reponame, + variables: { + login: username, + repo: reponame, + }, }, - }); + { + Authorization: `bearer ${process.env.PAT_1}`, + } + ); const data = res.data.data; diff --git a/src/fetchStats.js b/src/fetchStats.js index dc28590..a3cd3cd 100644 --- a/src/fetchStats.js +++ b/src/fetchStats.js @@ -2,25 +2,25 @@ const { request } = require("./utils"); const calculateRank = require("./calculateRank"); require("dotenv").config(); -async function fetchStats(username) { - if (!username) throw Error("Invalid username"); - - const res = await request({ - query: ` +// creating a fetcher function to reduce duplication +const fetcher = (username, token) => { + return request( + { + query: ` query userInfo($login: String!) { user(login: $login) { name login - repositoriesContributedTo(first: 100, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) { - totalCount - } contributionsCollection { totalCommitContributions } - pullRequests(first: 100) { + repositoriesContributedTo(first: 1, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) { totalCount } - issues(first: 100) { + pullRequests(first: 1) { + totalCount + } + issues(first: 1) { totalCount } followers { @@ -36,9 +36,45 @@ async function fetchStats(username) { } } } - `, - variables: { login: username }, - }); + `, + variables: { login: username }, + }, + { + // set the token + Authorization: `bearer ${token}`, + } + ); +}; + +async function retryer(username, RETRIES) { + try { + console.log(`Trying PAT_${RETRIES + 1}`); + + // try to fetch with the first token since RETRIES is 0 index i'm adding +1 + let response = await fetcher(username, process.env[`PAT_${RETRIES + 1}`]); + + // if rate limit is hit increase the RETRIES and recursively call the retryer + // with username, and current RETRIES + if ( + response.data.errors && + response.data.errors[0].type === "RATE_LIMITED" + ) { + console.log(`PAT_${RETRIES} Failed`); + RETRIES++; + // directly return from the function + return await retryer(username, RETRIES); + } + + // finally return the response + return response; + } catch (err) { + console.log(err); + } +} + +async function fetchStats(username) { + let RETRIES = 0; + if (!username) throw Error("Invalid username"); const stats = { name: "", @@ -47,12 +83,14 @@ async function fetchStats(username) { totalIssues: 0, totalStars: 0, contributedTo: 0, - rank: "C", + rank: { level: "C", score: 0 }, }; + let res = await retryer(username, RETRIES); + if (res.data.errors) { console.log(res.data.errors); - throw Error("Could not fetch user"); + throw Error(res.data.errors[0].message || "Could not fetch user"); } const user = res.data.data.user; diff --git a/src/utils.js b/src/utils.js index 470a9e8..b6b74f5 100644 --- a/src/utils.js +++ b/src/utils.js @@ -33,13 +33,13 @@ function isValidHexColor(hexColor) { ).test(hexColor); } -function request(data) { +function request(data, headers) { return new Promise((resolve, reject) => { axios({ url: "https://api.github.com/graphql", method: "post", headers: { - Authorization: `bearer ${process.env.GITHUB_TOKEN}`, + ...headers, }, data, }) @@ -48,4 +48,10 @@ function request(data) { }); } -module.exports = { renderError, kFormatter, encodeHTML, isValidHexColor, request }; +module.exports = { + renderError, + kFormatter, + encodeHTML, + isValidHexColor, + request, +}; diff --git a/tests/fetchStats.test.js b/tests/fetchStats.test.js index 8ae45fa..ebcfde4 100644 --- a/tests/fetchStats.test.js +++ b/tests/fetchStats.test.js @@ -74,7 +74,7 @@ describe("Test fetchStats", () => { mock.onPost("https://api.github.com/graphql").reply(200, error); await expect(fetchStats("anuraghazra")).rejects.toThrow( - "Could not fetch user" + "Could not resolve to a User with the login of 'noname'." ); }); });