Skip to content

Commit 0eb69cf

Browse files
committed
chore: add bsky and mastodon links + cleanup
1 parent 55db682 commit 0eb69cf

File tree

1 file changed

+55
-6
lines changed

1 file changed

+55
-6
lines changed

server/api/contributors.get.ts

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export interface GitHubUserData {
1010
location: string | null
1111
websiteUrl: string | null
1212
twitterUsername: string | null
13+
blueskyHandle: string | null
14+
mastodonUrl: string | null
1315
}
1416

1517
export interface GitHubContributor extends GitHubUserData {
@@ -30,7 +32,7 @@ type GitHubAPIContributor = Omit<GitHubContributor, 'role' | 'sponsors_url' | ke
3032

3133
// Fallback when no GitHub token is available (e.g. preview environments).
3234
// Only stewards are shown as maintainers; everyone else is a contributor.
33-
const FALLBACK_STEWARDS = new Set(['danielroe', 'patak-dev'])
35+
const FALLBACK_STEWARDS = new Set(['danielroe', 'patak-cat'])
3436

3537
const DEFAULT_USER_INFO: GitHubUserData = {
3638
name: null,
@@ -40,6 +42,8 @@ const DEFAULT_USER_INFO: GitHubUserData = {
4042
location: null,
4143
websiteUrl: null,
4244
twitterUsername: null,
45+
blueskyHandle: null,
46+
mastodonUrl: null,
4347
}
4448

4549
// Configure sanitize-html for GitHub's companyHTML and company fields
@@ -142,7 +146,7 @@ async function fetchGitHubUserData(
142146
// Build aliased GraphQL query: user0: user(login: "x") { hasSponsorsListing login }
143147
const fragments = logins.map(
144148
(login, i) =>
145-
`user${i}: user(login: "${login}") { hasSponsorsListing login name bio company companyHTML location websiteUrl twitterUsername }`,
149+
`user${i}: user(login: "${login}") { hasSponsorsListing login name bio company companyHTML location websiteUrl twitterUsername socialAccounts(first: 10) { nodes { provider url } } }`,
146150
)
147151
const query = `{ ${fragments.join('\n')} }`
148152

@@ -165,7 +169,12 @@ async function fetchGitHubUserData(
165169
const json = (await response.json()) as {
166170
data?: Record<
167171
string,
168-
(GitHubUserData & { login: string; hasSponsorsListing: boolean }) | null
172+
| (GitHubUserData & {
173+
login: string
174+
hasSponsorsListing: boolean
175+
socialAccounts: { nodes: { provider: string; url: string }[] }
176+
})
177+
| null
169178
>
170179
}
171180

@@ -176,6 +185,25 @@ async function fetchGitHubUserData(
176185
if (user.hasSponsorsListing) {
177186
sponsorable.add(user.login)
178187
}
188+
189+
// Extract Bluesky and Mastodon from socialAccounts
190+
let blueskyHandle: string | null = null
191+
let mastodonUrl: string | null = null
192+
193+
if (user.socialAccounts?.nodes) {
194+
for (const account of user.socialAccounts.nodes) {
195+
if (account.url.includes('bsky.app')) {
196+
// Extract handle from URL: https://bsky.app/profile/handle.bsky.social
197+
const match = account.url.match(/bsky\.app\/profile\/([^/?]+)/)
198+
if (match) {
199+
blueskyHandle = match[1] as string
200+
}
201+
} else if (account.provider === 'MASTODON') {
202+
mastodonUrl = account.url
203+
}
204+
}
205+
}
206+
179207
// --- SERVER-SIDE SANITIZATION AND BATCHING ---
180208
usersData.set(user.login, {
181209
name: cleanString(user.name),
@@ -186,6 +214,8 @@ async function fetchGitHubUserData(
186214
location: cleanString(user.location),
187215
websiteUrl: cleanString(user.websiteUrl, true),
188216
twitterUsername: cleanString(user.twitterUsername),
217+
blueskyHandle,
218+
mastodonUrl,
189219
})
190220
}
191221
}
@@ -272,11 +302,30 @@ export default defineCachedEventHandler(
272302
const sponsors_url = sponsorable.has(c.login)
273303
? `https://github.com/sponsors/${c.login}`
274304
: null
275-
Object.assign(c, { role, order, sponsors_url, ...userInfo })
276-
return c as GitHubContributor & { order: number; sponsors_url: string | null; role: Role }
305+
306+
// Construct the final object with only necessary fields
307+
return {
308+
id: c.id,
309+
login: c.login,
310+
name: userInfo.name,
311+
avatar_url: c.avatar_url,
312+
html_url: c.html_url,
313+
role,
314+
bio: userInfo.bio,
315+
company: userInfo.company,
316+
companyHTML: userInfo.companyHTML,
317+
location: userInfo.location,
318+
websiteUrl: userInfo.websiteUrl,
319+
twitterUsername: userInfo.twitterUsername,
320+
blueskyHandle: userInfo.blueskyHandle,
321+
mastodonUrl: userInfo.mastodonUrl,
322+
sponsors_url,
323+
contributions: c.contributions,
324+
order, // kept for sorting, removed in next step
325+
}
277326
})
278327
.sort((a, b) => a.order - b.order || b.contributions - a.contributions)
279-
.map(({ order: _, ...rest }) => rest)
328+
.map(({ order: _, ...rest }) => rest) as GitHubContributor[]
280329
},
281330
{
282331
maxAge: 3600, // Cache for 1 hour

0 commit comments

Comments
 (0)