diff --git a/source/plugins/support/README.md b/source/plugins/support/README.md new file mode 100644 index 00000000..e9422cb7 --- /dev/null +++ b/source/plugins/support/README.md @@ -0,0 +1,23 @@ +### 🗨️ GitHub Community Support + +The *support* plugin lets you display your statistics from [GitHub Support Community](https://github.community/). + + + +
+ + +
+ +An account on [GitHub Support Community](https://github.community/) is required to use this plugin. + +#### ℹ️ Examples workflows + +[➡️ Available options for this plugin](metadata.yml) + +```yaml +- uses: lowlighter/metrics@latest + with: + # ... other options + plugin_support: yes +``` \ No newline at end of file diff --git a/source/plugins/support/index.mjs b/source/plugins/support/index.mjs new file mode 100644 index 00000000..86fe2b44 --- /dev/null +++ b/source/plugins/support/index.mjs @@ -0,0 +1,81 @@ +//Setup + export default async function({login, q, imports, data, account}, {enabled = false} = {}) { + //Plugin execution + try { + //Check if plugin is enabled and requirements are met + if ((!enabled)||(!q.support)) + return null + + //Load inputs + imports.metadata.plugins.stackoverflow.inputs({data, account, q}) + + //Start puppeteer and navigate to github.community + const result = {stats:{solutions:0, posts:0, topics:0, received:0}, badges:{count:0}} + console.debug(`metrics/compute/${login}/plugins > support > starting browser`) + const browser = await imports.puppeteer.launch() + console.debug(`metrics/compute/${login}/plugins > support > started ${await browser.version()}`) + const page = await browser.newPage() + + //Check account existence + { + await page.goto(`https://github.community/u/${login}`) + const frame = page.mainFrame() + try { + await frame.waitForSelector(".user-profile-names", {timeout:5000}) + } + catch { + throw {error:{message:"Could not find matching account on github.community"}} + } + } + + //Stats + { + await page.goto(`https://github.community/u/${login}/summary`) + const frame = page.mainFrame() + await frame.waitForSelector(".stats-section") + Object.assign(result.stats, Object.fromEntries((await frame.evaluate(() => [...document.querySelectorAll(".stats-section li")].map(el => [ + el.querySelector(".label").innerText.trim().toLocaleLowerCase(), + el.querySelector(".value").innerText.trim().toLocaleLowerCase(), + ]))).map(([key, value]) => { + switch (true) { + case /solutions?/.test(key): + return ["solutions", Number(value)] + case /posts? created/.test(key): + return ["posts", Number(value)] + case /topics? created/.test(key): + return ["topics", Number(value)] + case /received/.test(key): + return ["hearts", Number(value)] + default: + return null + } + }).filter(kv => kv))) + } + + //Badges + { + await page.goto(`https://github.community/u/${login}/badges`) + const frame = page.mainFrame() + await frame.waitForSelector(".user-badges-list") + const badges = await frame.evaluate(() => ({ + uniques:[...document.querySelectorAll(".badge-card .badge-link")].map(el => el.innerText), + multiples:[...document.querySelectorAll(".grant-count")].map(el => Number(el.innerText)), + })) + badges.count = badges.uniques.length + (badges.multiples.reduce((a, b) => a + b, 0) - badges.multiples.length) + result.badges = badges + } + + //Close browser + console.debug(`metrics/compute/${login}/plugins > support > closing browser`) + await browser.close() + + //Results + return result + } + //Handle errors + catch (error) { + if (error.error?.message) + throw error + throw {error:{message:"An error occured", instance:error}} + } + } \ No newline at end of file diff --git a/source/plugins/support/metadata.yml b/source/plugins/support/metadata.yml new file mode 100644 index 00000000..cf699e10 --- /dev/null +++ b/source/plugins/support/metadata.yml @@ -0,0 +1,12 @@ +name: "🗨️ GitHub Community Support" +cost: N/A +categorie: github +supports: + - user +inputs: + + # Enable or disable plugin + plugin_support: + description: GitHub Community Support metrics + type: boolean + default: no \ No newline at end of file diff --git a/source/plugins/support/tests.yml b/source/plugins/support/tests.yml new file mode 100644 index 00000000..cac6f9e5 --- /dev/null +++ b/source/plugins/support/tests.yml @@ -0,0 +1,5 @@ +- name: Support plugin (default) + uses: lowlighter/metrics@latest + with: + token: MOCKED_TOKEN + plugin_support: yes \ No newline at end of file diff --git a/source/templates/classic/partials/_.json b/source/templates/classic/partials/_.json index ae648607..cc4d8fc5 100644 --- a/source/templates/classic/partials/_.json +++ b/source/templates/classic/partials/_.json @@ -25,6 +25,7 @@ "anilist", "wakatime", "skyline", + "support", "stackoverflow", "stock", "achievements", diff --git a/source/templates/classic/partials/support.ejs b/source/templates/classic/partials/support.ejs new file mode 100644 index 00000000..27abf969 --- /dev/null +++ b/source/templates/classic/partials/support.ejs @@ -0,0 +1,45 @@ +<% if (plugins.support) { %> +
+

+ + GitHub Support Community +

+ <% if (plugins.support.error) { %> +
+
+
+ + <%= plugins.support.error.message %> +
+
+
+ <% } else { %> +
+
+
+ + <%= plugins.support.stats.hearts %> heart<%= s(plugins.support.stats.hearts) %> received +
+
+ + <%= plugins.support.stats.topics %> topic<%= s(plugins.support.stats.topics) %> created +
+
+ + <%= plugins.support.stats.posts %> post<%= s(plugins.support.stats.posts) %> +
+
+
+
+ + <%= plugins.support.badges.count %> badge<%= s(plugins.support.badges.count) %> +
+
+ + <%= plugins.support.stats.solutions %> solution<%= s(plugins.support.stats.solutions) %> +
+
+
+ <% } %> +
+<% } %>