//Setup export default async function({login, q, imports, data, computed, graphql, queries, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled)||(!q.achievements)) return null //Load inputs let {threshold, secrets, only, ignored, limit} = imports.metadata.plugins.achievements.inputs({data, q, account}) //Initinalization const list = [] const {user} = await graphql(queries.achievements({login})) const ranks = await graphql(queries.achievements.ranking({followers:user.followers.totalCount, stars:user.popular.nodes?.[0]?.stargazers?.totalCount ?? 0})) //Developer { const value = user.repositories.totalCount const unlock = user.repositories.nodes?.shift() list.push({ title:"Developer", text:`Published ${value} public repositor${imports.s(value, "y")}`, icon:"", ...rank(value, [1, 20, 50, 100]), value, unlock:new Date(unlock?.createdAt), }) } //Forker { const value = user.forks.totalCount const unlock = user.forks.nodes?.shift() list.push({ title:"Forker", text:`Forked ${value} public repositor${imports.s(value, "y")}`, icon:"", ...rank(value, [1, 5, 10, 20]), value, unlock:new Date(unlock?.createdAt), }) } //Contributor { const value = user.pullRequests.totalCount const unlock = user.pullRequests.nodes?.shift() list.push({ title:"Contributor", text:`Opened ${value} pull request${imports.s(value)}`, icon:"", ...rank(value, [1, 200, 500, 1000]), value, unlock:new Date(unlock?.createdAt), }) } //Manager { const value = user.projects.totalCount const unlock = user.projects.nodes?.shift() list.push({ title:"Manager", text:`Created ${value} user project${imports.s(value)}`, icon:"", ...rank(value, [1, 2, 3, 4]), value, unlock:new Date(unlock?.createdAt), }) } //Reviewer { const value = user.contributionsCollection.pullRequestReviewContributions.totalCount const unlock = user.contributionsCollection.pullRequestReviewContributions.nodes?.shift() list.push({ title:"Reviewer", text:`Reviewed ${value} pull request${imports.s(value)}`, icon:"", ...rank(value, [1, 200, 500, 1000]), value, unlock:new Date(unlock?.createdAt), }) } //Packager { const value = user.packages.totalCount const unlock = user.packages.nodes?.shift() list.push({ title:"Packager", text:`Created ${value} package${imports.s(value)}`, icon:"", ...rank(value, [1, 5, 10, 20]), value, unlock:new Date(unlock?.createdAt), }) } //Scripter { const value = user.gists.totalCount const unlock = user.gists.nodes?.shift() list.push({ title:"Scripter", text:`Published ${value} gist${imports.s(value)}`, icon:"", ...rank(value, [1, 20, 50, 100]), value, unlock:new Date(unlock?.createdAt), }) } //Worker { const value = user.organizations.totalCount const unlock = user.organizations.nodes?.shift() list.push({ title:"Worker", text:`Joined ${value} organization${imports.s(value)}`, icon:"", ...rank(value, [1, 2, 3, 4]), value, unlock:new Date(unlock?.createdAt), }) } //Stargazer { const value = user.starredRepositories.totalCount const unlock = user.starredRepositories.nodes?.shift() list.push({ title:"Stargazer", text:`Starred ${value} repositor${imports.s(value, "y")}`, icon:"", ...rank(value, [1, 200, 500, 1000]), value, unlock:new Date(unlock?.createdAt), }) } //Follower { const value = user.following.totalCount const unlock = user.following.nodes?.shift() list.push({ title:"Follower", text:`Following ${value} user${imports.s(value)}`, icon:"", ...rank(value, [1, 200, 500, 1000]), value, unlock:new Date(unlock?.createdAt), }) } //Influencer { const value = user.followers.totalCount const unlock = user.followers.nodes?.shift() list.push({ title:"Influencer", text:`Followed by ${value} user${imports.s(value)}`, icon:"", ...rank(value, [1, 200, 500, 1000]), value, unlock:new Date(unlock?.createdAt), gh:Number(`1${"0".repeat(Math.ceil(Math.log10(1+ranks.user_rank.userCount)))}`), }) } //Maintainer { const value = user.popular.nodes?.shift()?.stargazers?.totalCount ?? 0 const unlock = null list.push({ title:"Maintainer", text:`Maintaining a repository with ${value} star${imports.s(value)}`, icon:"", ...rank(value, [1, 1000, 5000, 10000]), value, unlock:new Date(unlock?.createdAt), gh:Number(`1${"0".repeat(Math.ceil(Math.log10(1+ranks.repo_rank.repositoryCount)))}`), }) } //Polyglot { const value = new Set(data.user.repositories.nodes.flatMap(repository => repository.languages.edges.map(({node:{name}}) => name))).size const unlock = null list.push({ title:"Polyglot", text:`Using ${value} different programming language${imports.s(value)}`, icon:"", ...rank(value, [1, 4, 8, 16]), value, unlock:new Date(unlock?.createdAt), }) } //Member { const value = computed.registered.diff const unlock = null list.push({ title:"Member", text:`Registered ${Math.floor(value)} year${imports.s(Math.floor(value))} ago`, icon:"", ...rank(value, [1, 3, 5, 10]), value, unlock:new Date(unlock?.createdAt), }) } //Verified { const value = !/This user hasn't uploaded any GPG keys/i.test((await imports.axios.get(`https://github.com/${login}.gpg`)).data) const unlock = null list.push({ title:"Verified", text:"Registered a GPG key to sign commits", icon:"", rank:value ? "$" : "X", progress:1, value, unlock:new Date(unlock?.createdAt), }) } //Explorer { const value = !/doesn’t have any starred topics yet/i.test((await imports.axios.get(`https://github.com/stars/${login}/topics`)).data) const unlock = null list.push({ title:"Explorer", text:"Starred a topic on GitHub Explore", icon:"", rank:value ? "$" : "X", progress:1, value, unlock:new Date(unlock?.createdAt), }) } //Automater { const value = process.env.GITHUB_ACTIONS const unlock = null list.push({ title:"Automater", text:"Use GitHub Actions to automate profile updates", icon:"", rank:value ? "$" : "X", progress:1, value, unlock:new Date(unlock?.createdAt), }) } //Infographile { const {repository:{viewerHasStarred:value}, viewer:{login:_login}} = await graphql(queries.achievements.metrics()) const unlock = null list.push({ title:"Infographile", text:"Fervent supporter of metrics", icon:"", rank:(value)&&(login === _login) ? "$" : "X", progress:1, value, unlock:new Date(unlock?.createdAt), }) } //Octonaut { const {user:{viewerIsFollowing:value}, viewer:{login:_login}} = await graphql(queries.achievements.octocat()) const unlock = null list.push({ title:"Octonaut", text:"Following octocat", icon:"", rank:(value)&&(login === _login) ? "$" : "X", progress:1, value, unlock:new Date(unlock?.createdAt), }) } //Results const order = {S:5, A:4, B:3, C:2, $:1, X:0} const colors = {S:["#FF0000", "#FF8500"], A:["#B59151", "#FFD576"], B:["#7D6CFF", "#B2A8FF"], C:["#2088FF", "#79B8FF"], $:["#FF48BD", "#FF92D8"], X:["#7A7A7A", "#B0B0B0"]} const achievements = list .filter(a => (order[a.rank] >= order[threshold])||((a.rank === "$")&&(secrets))) .filter(a => (!only.length)||((only.length)&&(only.includes(a.title.toLocaleLowerCase())))) .filter(a => !ignored.includes(a.title.toLocaleLowerCase())) .sort((a, b) => (order[b.rank]+b.progress*0.99) - (order[a.rank]+a.progress*0.99)) .map(({title, unlock, ...achievement}) => ({title:({S:`Master ${title.toLocaleLowerCase()}`, A:`Super ${title.toLocaleLowerCase()}`, B:`Great ${title.toLocaleLowerCase()}`}[achievement.rank] ?? title), unlock:!/invalid date/i.test(unlock) ? `${imports.date(unlock, {timeStyle:"short", timeZone:data.config.timezone?.name})} on ${imports.date(unlock, {dateStyle:"short", timeZone:data.config.timezone?.name})}` : null, ...achievement})) .map(({icon, ...achievement}) => ({icon:icon.replace(/#primary/g, colors[achievement.rank][0]).replace(/#secondary/g, colors[achievement.rank][1]), ...achievement})) .slice(0, limit || Infinity) return {list:achievements} } //Handle errors catch (error) { throw {error:{message:"An error occured", instance:error}} } } /**Rank */ function rank(x, [c, b, a, m]) { if (x >= a) return {rank:"A", progress:(x-a)/(m-a)} else if (x >= b) return {rank:"B", progress:(x-b)/(a-b)} else if (x >= c) return {rank:"C", progress:(x-c)/(b-c)} return {rank:"X", progress:x/c} }