diff --git a/source/app/action/index.mjs b/source/app/action/index.mjs index f480acf6..c7c39098 100644 --- a/source/app/action/index.mjs +++ b/source/app/action/index.mjs @@ -14,7 +14,7 @@ const info = (left, right, {token = false} = {}) => console.log(`${`${left}`.padEnd(56 + 9*(/0m$/.test(left)))} │ ${ Array.isArray(right) ? right.join(", ") || "(none)" : right === undefined ? "(default)" : - token ? /^MOCKED/.test(right) ? "(MOCKED TOKEN)" : (right ? "(provided)" : "(missing)") : + token ? /^MOCKED/.test(right) ? "(MOCKED TOKEN)" : /^NOT_NEEDED$/.test(right) ? "(NOT NEEDED)" : (right ? "(provided)" : "(missing)") : typeof right === "object" ? JSON.stringify(right) : right }`) @@ -62,7 +62,7 @@ //Docker image if (_image) - info("Using prebuilt image", image) + info("Using prebuilt image", _image) //Debug mode and flags info("Debug mode", debug) @@ -76,6 +76,7 @@ info("GitHub token", token, {token:true}) if (!token) throw new Error("You must provide a valid GitHub token to gather your metrics") + conf.settings.token = token const api = {} api.graphql = octokit.graphql.defaults({headers:{authorization: `token ${token}`}}) info("Github GraphQL API", "ok") @@ -179,7 +180,7 @@ //Register user inputs if (enabled) { info.break() - info.group({metadata, name, inputs:enabled ? inputs : {}}) + info.group({metadata, name, inputs}) q[name] = true for (const [key, value] of Object.entries(inputs)) { //Store token in plugin configuration diff --git a/source/app/metrics/setup.mjs b/source/app/metrics/setup.mjs index fd35c075..b2cedd50 100644 --- a/source/app/metrics/setup.mjs +++ b/source/app/metrics/setup.mjs @@ -193,6 +193,9 @@ //Load metadata (plugins) conf.metadata = await metadata({log}) + //Set no token property + Object.defineProperty(conf.settings, "notoken", {get() { return conf.settings.token === "NOT_NEEDED" }}) + //Conf logger(`metrics/setup > setup > success`) return {Templates, Plugins, conf} diff --git a/source/app/mocks/api/axios/get/pagespeed.mjs b/source/app/mocks/api/axios/get/pagespeed.mjs index 2ac69652..0e23f99d 100644 --- a/source/app/mocks/api/axios/get/pagespeed.mjs +++ b/source/app/mocks/api/axios/get/pagespeed.mjs @@ -3,7 +3,7 @@ //Tested url const tested = url.match(/&url=(?.*?)(?:&|$)/)?.groups?.tested ?? faker.internet.url() //Pagespeed api - if (/^https:..www.googleapis.com.pagespeedonline.v5/.test(url)) { + if (/^https:..www.googleapis.com.pagespeedonline.v5.*$/.test(url)) { //Pagespeed result if (/v5.runPagespeed.*&key=MOCKED_TOKEN/.test(url)) { console.debug(`metrics/compute/mocks > mocking pagespeed api result > ${url}`) diff --git a/source/app/mocks/api/axios/get/spotify.mjs b/source/app/mocks/api/axios/get/spotify.mjs index 708a943b..4aa65faa 100644 --- a/source/app/mocks/api/axios/get/spotify.mjs +++ b/source/app/mocks/api/axios/get/spotify.mjs @@ -1,7 +1,7 @@ /** Mocked data */ export default function ({faker, url, options, login = faker.internet.userName()}) { //Spotify api - if (/^https:..api.spotify.com/.test(url)) { + if (/^https:..api.spotify.com.*$/.test(url)) { //Get recently played tracks if (/me.player.recently-played/.test(url)&&(options?.headers?.Authorization === "Bearer MOCKED_TOKEN_ACCESS")) { console.debug(`metrics/compute/mocks > mocking spotify api result > ${url}`) diff --git a/source/app/mocks/api/axios/get/twitter.mjs b/source/app/mocks/api/axios/get/twitter.mjs index f4b97dc3..d9b37dcc 100644 --- a/source/app/mocks/api/axios/get/twitter.mjs +++ b/source/app/mocks/api/axios/get/twitter.mjs @@ -1,7 +1,7 @@ /** Mocked data */ export default function ({faker, url, options, login = faker.internet.userName()}) { //Twitter api - if (/^https:..api.twitter.com/.test(url)) { + if (/^https:..api.twitter.com.*$/.test(url)) { //Get user profile if ((/users.by.username/.test(url))&&(options?.headers?.Authorization === "Bearer MOCKED_TOKEN")) { console.debug(`metrics/compute/mocks > mocking twitter api result > ${url}`) diff --git a/source/app/mocks/api/axios/post/anilist.mjs b/source/app/mocks/api/axios/post/anilist.mjs index 1cdd18f7..22123bdb 100644 --- a/source/app/mocks/api/axios/post/anilist.mjs +++ b/source/app/mocks/api/axios/post/anilist.mjs @@ -1,6 +1,6 @@ /** Mocked data */ export default function ({faker, url, body, login = faker.internet.userName()}) { - if (/^https:..graphql.anilist.co/.test(url)) { + if (/^https:..graphql.anilist.co.*$/.test(url)) { //Initialization and media generator const query = body.query const media = ({type}) => ({ diff --git a/source/app/mocks/api/axios/post/spotify.mjs b/source/app/mocks/api/axios/post/spotify.mjs index c4d8239c..2c92b2e4 100644 --- a/source/app/mocks/api/axios/post/spotify.mjs +++ b/source/app/mocks/api/axios/post/spotify.mjs @@ -3,7 +3,7 @@ /** Mocked data */ export default function ({faker, url, body, login = faker.internet.userName()}) { - if (/^https:..accounts.spotify.com.api.token/.test(url)) { + if (/^https:..accounts.spotify.com.api.token.*$/.test(url)) { //Access token generator const params = new urls.URLSearchParams(body) if ((params.get("grant_type") === "refresh_token")&&(params.get("client_id") === "MOCKED_CLIENT_ID")&&(params.get("client_secret") === "MOCKED_CLIENT_SECRET")&&(params.get("refresh_token") === "MOCKED_REFRESH_TOKEN")) { diff --git a/source/app/web/instance.mjs b/source/app/web/instance.mjs index 5a9de790..eed6203b 100644 --- a/source/app/web/instance.mjs +++ b/source/app/web/instance.mjs @@ -72,8 +72,11 @@ const enabled = Object.entries(metadata).map(([name]) => ({name, enabled:plugins[name]?.enabled ?? false})) const templates = Object.entries(Templates).map(([name]) => ({name, enabled:(conf.settings.templates.enabled.length ? conf.settings.templates.enabled.includes(name) : true) ?? false})) const actions = {flush:new Map()} - let requests = (await rest.rateLimit.get()).data.rate - setInterval(async () => requests = (await rest.rateLimit.get()).data.rate, 30*1000) + let requests = {limit:0, used:0, remaining:0, reset:NaN} + if (!conf.settings.notoken) { + requests = (await rest.rateLimit.get()).data.rate + setInterval(async () => requests = (await rest.rateLimit.get()).data.rate, 30*1000) + } //Web app.get("/", limiter, (req, res) => res.sendFile(`${conf.paths.statics}/index.html`)) app.get("/index.html", limiter, (req, res) => res.sendFile(`${conf.paths.statics}/index.html`)) diff --git a/source/plugins/base/index.mjs b/source/plugins/base/index.mjs index f339b118..e42afaab 100644 --- a/source/plugins/base/index.mjs +++ b/source/plugins/base/index.mjs @@ -9,6 +9,10 @@ console.debug(`metrics/compute/${login}/base > started`) let {repositories, repositories_forks:forks} = imports.metadata.plugins.base.inputs({data, q, account:"bypass"}, {repositories:conf.settings.repositories ?? 100}) + //Skip initial data gathering if not needed + if (conf.settings.notoken) + return (postprocess.skip({login, data}), {}) + //Base parts (legacy handling for web instance) const defaulted = ("base" in q) ? !!q.base : true for (const part of conf.settings.plugins.base.parts) @@ -85,5 +89,23 @@ issueComments:{totalCount:0}, organizations:{totalCount:0}, }) + }, + //Skip base content query and instantiate an empty user instance + skip({login, data}) { + data.user = {} + for (const account of ["user", "organization"]) + postprocess?.[account]({login, data}) + data.account = "bypass" + Object.assign(data.user, { + databaseId:0, + name:login, + login, + createdAt:new Date(), + avatarUrl:`https://github.com/${login}.png`, + websiteUrl:null, + twitterUsername:login, + repositories:{totalCount:0, totalDiskUsage:0, nodes:[]}, + packages:{totalCount:0}, + }) } } \ No newline at end of file diff --git a/source/plugins/core/index.mjs b/source/plugins/core/index.mjs index 3fd58af7..8c29ae9a 100644 --- a/source/plugins/core/index.mjs +++ b/source/plugins/core/index.mjs @@ -90,7 +90,7 @@ computed.avatar = await avatar || "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" //Token scopes - computed.token.scopes = (await rest.request("HEAD /")).headers["x-oauth-scopes"].split(", ") + computed.token.scopes = conf.settings.notoken ? [] : (await rest.request("HEAD /")).headers["x-oauth-scopes"].split(", ") //Meta data.meta = {version:conf.package.version, author:conf.package.author} diff --git a/source/plugins/core/metadata.yml b/source/plugins/core/metadata.yml index 3b5db5fb..415da242 100644 --- a/source/plugins/core/metadata.yml +++ b/source/plugins/core/metadata.yml @@ -9,6 +9,8 @@ inputs: # User account personal token # No additional scopes are needed unless you want to include private repositories metrics # Some plugins may also require additional scopes + # ──────────────────────────────────────────────────────────────── + # If you're only using plugins which don't really require a GitHub token, you may pass "NOT_NEEDED" as value token: description: GitHub Personal Token type: token