Skip to content

Commit 220deb0

Browse files
authored
feat(plugins/sponsorships): add plugin (lowlighter#1358)
1 parent cdf2c03 commit 220deb0

File tree

13 files changed

+268
-0
lines changed

13 files changed

+268
-0
lines changed

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
deno
22
gpgarmor
33
github
4+
githubassets
45
https
56
leetcode
67
pgn

source/app/web/statics/embed/app.placeholder.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,26 @@
458458
},
459459
})
460460
: null),
461+
//Sponsorships
462+
...(set.plugins.enabled.sponsorships
463+
? ({
464+
sponsorships: {
465+
sections: options["sponsorships.sections"].split(",").map(x => x.trim()),
466+
amount: faker.datatype.number(1000),
467+
list: new Array(2+faker.datatype.number(8)).fill(null).map(_ => ({
468+
login: faker.internet.userName(),
469+
avatar: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==",
470+
type: "user",
471+
tier: `$${faker.datatype.number(100) * 10} per month`,
472+
private: false,
473+
past: faker.datatype.boolean(),
474+
})),
475+
size: Number(options["sponsorships.size"]),
476+
image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==",
477+
started: faker.date.recent(),
478+
},
479+
})
480+
: null),
461481
//Languages
462482
...(set.plugins.enabled.languages
463483
? ({
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!--header-->
2+
<!--/header-->
3+
4+
## ➡️ Available options
5+
6+
<!--options-->
7+
<!--/options-->
8+
9+
## ℹ️ Examples workflows
10+
11+
<!--examples-->
12+
<!--/examples-->
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- name: 💝 GitHub sponsorships
2+
uses: lowlighter/metrics@latest
3+
with:
4+
filename: metrics.plugin.sponsorships.svg
5+
token: ${{ secrets.METRICS_TOKEN }}
6+
base: ""
7+
plugin_sponsorships: yes
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//Setup
2+
export default async function({login, q, imports, data, graphql, queries, account}, {enabled = false, extras = false} = {}) {
3+
//Plugin execution
4+
try {
5+
//Check if plugin is enabled and requirements are met
6+
if ((!q.sponsorships) || (!imports.metadata.plugins.sponsorships.enabled(enabled, {extras})))
7+
return null
8+
9+
//Load inputs
10+
let {sections, size} = await imports.metadata.plugins.sponsorships.inputs({data, account, q})
11+
12+
//Query description and goal
13+
let amount = NaN, image = null, started = null
14+
if (sections.includes("amount")) {
15+
console.debug(`metrics/compute/${login}/plugins > sponsorships > querying total amount spend`)
16+
const {totalSponsorshipAmountAsSponsorInCents, sponsorshipsAsSponsor} = (await graphql(queries.sponsorships({login, account})))[account]
17+
amount = totalSponsorshipAmountAsSponsorInCents/100
18+
image = "https://github.githubassets.com/images/icons/emoji/hearts_around.png"
19+
started = sponsorshipsAsSponsor.nodes[0]?.createdAt ? new Date(sponsorshipsAsSponsor.nodes[0]?.createdAt) : null
20+
}
21+
image = await imports.imgb64(image)
22+
23+
//Query sponsorships
24+
const list = []
25+
if (sections.includes("sponsorships")) {
26+
console.debug(`metrics/compute/${login}/plugins > sponsorships > querying sponsorships`)
27+
{
28+
const fetched = []
29+
let cursor = null
30+
let pushed = 0
31+
do {
32+
console.debug(`metrics/compute/${login}/sponsorships > retrieving sponsorships after ${cursor}`)
33+
const {[account]: {sponsorshipsAsSponsor: {edges, nodes}}} = await graphql(queries.sponsorships.all({login, account, after: cursor ? `after: "${cursor}"` : "", size: Math.round(size * 1.5)}))
34+
cursor = edges?.[edges?.length - 1]?.cursor
35+
fetched.push(...nodes)
36+
pushed = nodes.length
37+
console.debug(`metrics/compute/${login}/sponsorships > retrieved ${pushed} sponsorships events after ${cursor}`)
38+
} while ((pushed) && (cursor))
39+
list.push(...fetched.map(({sponsorable: {login, avatarUrl, url: organization = null}, tier:{name:tier}, privacyLevel:privacy, isActive:active}) => ({login, avatarUrl, type: organization ? "organization" : "user", tier, private: privacy !== "PUBLIC", past:!active})))
40+
}
41+
await Promise.all(list.map(async user => user.avatar = await imports.imgb64(user.avatarUrl)))
42+
}
43+
44+
//Results
45+
return {amount, list, sections, size, image, started}
46+
}
47+
//Handle errors
48+
catch (error) {
49+
throw imports.format.error(error)
50+
}
51+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: 💝 GitHub Sponsorships
2+
category: github
3+
description: |
4+
This plugin displays sponsorships funded through [GitHub sponsors](https://github.com/sponsors/).
5+
examples:
6+
default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.sponsorships.svg
7+
supports:
8+
- user
9+
- organization
10+
scopes:
11+
- read:user
12+
- read:org
13+
inputs:
14+
15+
plugin_sponsorships:
16+
description: |
17+
Enable sponsorships plugin
18+
type: boolean
19+
default: no
20+
21+
plugin_sponsorships_sections:
22+
description: |
23+
Displayed sections
24+
25+
- `amount`: display total amount sponsored
26+
- `sponsorships`: display GitHub sponsorships
27+
type: array
28+
format: comma-separated
29+
default: amount, sponsorships
30+
example: amount, sponsorships
31+
values:
32+
- amount
33+
- sponsorships
34+
35+
plugin_sponsorships_size:
36+
description: |
37+
Profile picture display size
38+
type: number
39+
default: 24
40+
min: 8
41+
max: 64
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
query SponsorshipsAll {
2+
$account(login: "$login") {
3+
sponsorshipsAsSponsor($after first: 100, activeOnly: false, orderBy: {field: CREATED_AT, direction: DESC}) {
4+
edges {
5+
cursor
6+
}
7+
nodes {
8+
createdAt
9+
isActive
10+
isOneTimePayment
11+
tier {
12+
name
13+
}
14+
privacyLevel
15+
sponsorable {
16+
... on User {
17+
avatarUrl(size: $size)
18+
login
19+
}
20+
... on Organization {
21+
login
22+
avatarUrl(size: $size)
23+
url
24+
}
25+
}
26+
}
27+
}
28+
}
29+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
query SponsorshipsDefault {
2+
$account(login: "$login") {
3+
totalSponsorshipAmountAsSponsorInCents
4+
sponsorshipsAsSponsor(first: 1, activeOnly: false, orderBy: {field: CREATED_AT, direction: ASC}) {
5+
nodes {
6+
createdAt
7+
}
8+
}
9+
}
10+
}

source/templates/classic/partials/_.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"code",
4040
"chess",
4141
"sponsors",
42+
"sponsorships",
4243
"poopmap",
4344
"fortune",
4445
"splatoon"
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<% if (plugins.sponsorships) { %>
2+
<section>
3+
<h2 class="field">
4+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path d="M10.586 1C12.268 1 13.5 2.37 13.5 4.25c0 1.745-.996 3.359-2.622 4.831-.166.15-.336.297-.509.438l1.116 5.584a.75.75 0 0 1-.991.852l-2.409-.876a.25.25 0 0 0-.17 0l-2.409.876a.75.75 0 0 1-.991-.852L5.63 9.519a13.78 13.78 0 0 1-.51-.438C3.497 7.609 2.5 5.995 2.5 4.25 2.5 2.37 3.732 1 5.414 1c.963 0 1.843.403 2.474 1.073L8 2.198l.112-.125a3.385 3.385 0 0 1 2.283-1.068L10.586 1Zm-3.621 9.495-.718 3.594 1.155-.42a1.75 1.75 0 0 1 1.028-.051l.168.051 1.154.42-.718-3.592c-.199.13-.37.235-.505.314l-.169.097a.75.75 0 0 1-.72 0 9.54 9.54 0 0 1-.515-.308l-.16-.105ZM10.586 2.5c-.863 0-1.611.58-1.866 1.459-.209.721-1.231.721-1.44 0C7.025 3.08 6.277 2.5 5.414 2.5 4.598 2.5 4 3.165 4 4.25c0 1.23.786 2.504 2.128 3.719.49.443 1.018.846 1.546 1.198l.325.21.076-.047.251-.163a13.341 13.341 0 0 0 1.546-1.198C11.214 6.754 12 5.479 12 4.25c0-1.085-.598-1.75-1.414-1.75Z"></path></svg>
5+
Sponsorships
6+
</h2>
7+
<% if (plugins.sponsorships.error) { %>
8+
<div class="row fill-width">
9+
<section>
10+
<div class="field error">
11+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg>
12+
<%= plugins.sponsorships.error.message %>
13+
</div>
14+
</section>
15+
</div>
16+
<% } else { %>
17+
<% for (const section of plugins.sponsorships.sections) { %>
18+
<div class="row fill-width">
19+
<% if (section === "amount") { %>
20+
<section class="sponsorships sponsors goal">
21+
<img src="<%= plugins.sponsorships.image %>" alt="" />
22+
<div><span class="bold"><%= user.login %></span> has given a total of <span class="bold"><%= new Intl.NumberFormat("en", {style:"currency", currency:"USD"}).format(plugins.sponsorships.amount) %></span> to open source software<% if (plugins.sponsorships.started) { %> since <span class="bold"><%= f.date(plugins.sponsorships.started, { date:true, timeZone:config.timezone?.name}) %></span><% } %>.</div>
23+
</section>
24+
<% } else if (section === "sponsorships") { %>
25+
<section class="sponsors goal">
26+
<div class="goal-text">
27+
<span>
28+
<%= user.login %> helped funding the work of <%= plugins.sponsorships.list.length %> users and organizations.
29+
</span>
30+
</div>
31+
<div class="row">
32+
<% for (const user of plugins.sponsorships.list) { %><img class="avatar <%= user.past ? 'past' : '' %> <%= user.type === "organization" ? "organization" : "" %>" src="<%= user.avatar %>" width="<%= 0.8*plugins.sponsorships.size %>" height="<%= 0.8*plugins.sponsorships.size %>" alt="" /><% } %>
33+
</div>
34+
</section>
35+
<% } %>
36+
</div>
37+
<% } %>
38+
<% } %>
39+
</section>
40+
<% } %>

0 commit comments

Comments
 (0)