diff --git a/source/plugins/achievements/index.mjs b/source/plugins/achievements/index.mjs index b950bc7e..0647d47c 100644 --- a/source/plugins/achievements/index.mjs +++ b/source/plugins/achievements/index.mjs @@ -14,7 +14,7 @@ export default async function({login, q, imports, data, computed, graphql, queri //Initialization const list = [] - await total({imports}) + await total({imports, graphql, queries}) await compute[account]({list, login, data, computed, imports, graphql, queries, rest, rank, leaderboard}) //Results @@ -72,31 +72,50 @@ function leaderboard({user, type, requirement}) { } /**Total extracter */ -async function total({imports}) { +async function total({imports, graphql, queries}) { if (!total.promise) { total.promise = new Promise(async (solve, reject) => { - //Setup browser - console.debug("metrics/compute/plugins > achievements > filling total from github.com/search") - const browser = await imports.puppeteer.launch() - console.debug(`metrics/compute/plugins > achievements > started ${await browser.version()}`) - //Extracting total from github.com/search - for (let i = 0; (i < 100) && ((!total.users) || (!total.repositories)); i++) { - const page = await browser.newPage() - await page.goto("https://github.com/search?q=created%3A%3E%3D1970") - const results = await page.evaluate(() => [...[...document.querySelectorAll("h2")].filter(node => /Filter by/.test(node.innerText)).shift()?.nextSibling?.innerText.trim().matchAll(/(?Repositories|Users|Issues)\n(?.*?)M/g) ?? []]) ?? null - for (const result of results) { - const type = result[1]?.toLowerCase() - console.debug(`metrics/compute/plugins > achievements > setup found ${type ?? "(?)"}`) - const count = result[2] ?? "" - if ((count !== "") && (!total[type])) { - total[type] = Number(count) * 10e5 - console.debug(`metrics/compute/plugins > achievements > set total.${type} to ${total[type]}`) + for (const method of ["graphql", "browser"]) { + console.debug(`metrics/compute/plugins > achievements > setup using ${method}`) + try { + //Setup using GraphQL + if (method === "graphql") { + const queried = await graphql(queries.achievements.total()) + Object.assign(total, Object.fromEntries(Object.entries(queried).map(([key, {count:value}]) => [key, value]))) } + //Setup using browser + if (method === "browser") { + //Setup browser + console.debug("metrics/compute/plugins > achievements > filling total from github.com/search") + const browser = await imports.puppeteer.launch() + console.debug(`metrics/compute/plugins > achievements > started ${await browser.version()}`) + //Extracting total from github.com/search + for (let i = 0; (i < 4) && ((!total.users) || (!total.repositories)); i++) { + const page = await browser.newPage() + await page.goto("https://github.com/search?q=created%3A%3E%3D1970") + const results = await page.evaluate(() => [...[...document.querySelectorAll("h2")].filter(node => /Filter by/.test(node.innerText)).shift()?.nextSibling?.innerText.trim().matchAll(/(?Repositories|Users|Issues)\n.*?(?\d+)M/g) ?? []]) ?? null + for (const result of results) { + const type = result[1]?.toLowerCase() + console.debug(`metrics/compute/plugins > achievements > setup found ${type ?? "(?)"}`) + const count = result[2] ?? "" + if ((count !== "") && (!total[type])) { + total[type] = Number(count) * 10e5 + console.debug(`metrics/compute/plugins > achievements > set total.${type} to ${total[type]}`) + } + } + await page.close() + await imports.wait(10 * Math.random()) + } + } + //Check setup state + if ((!total.users) || (!total.repositories)) + throw new Error("Uncomplete setup") + } + catch (error) { + console.debug(`metrics/compute/plugins > achievements > setup error > ${error}`) + continue } - await page.close() - await imports.wait(10 * Math.random()) } - //Check setup state if ((!total.users) || (!total.repositories)) return reject("Failed to initiate total for achievement plugin") console.debug("metrics/compute/plugins > achievements > total setup complete") diff --git a/source/plugins/achievements/queries/total.graphql b/source/plugins/achievements/queries/total.graphql new file mode 100644 index 00000000..95b00bfb --- /dev/null +++ b/source/plugins/achievements/queries/total.graphql @@ -0,0 +1,11 @@ +query AchievementsTotal { + issues:search(query: "created:>1970", type: ISSUE) { + count:issueCount + } + repositories:search(query: "created:>1970", type: REPOSITORY) { + count:repositoryCount + } + users:search(query: "created:>1970", type: USER) { + count:userCount + } +} diff --git a/tests/mocks/api/github/graphql/achievements.total.mjs b/tests/mocks/api/github/graphql/achievements.total.mjs new file mode 100644 index 00000000..f56fa976 --- /dev/null +++ b/tests/mocks/api/github/graphql/achievements.total.mjs @@ -0,0 +1,9 @@ +/**Mocked data */ +export default function({faker, query, login = faker.internet.userName()}) { + console.debug("metrics/compute/mocks > mocking graphql api result > achievements/total") + return ({ + repositories: {count: faker.number.int(100000)}, + issues: {count: faker.number.int(100000)}, + users: {count: faker.number.int(100000)}, + }) +}