Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/dump-api-data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ on:
workflow_dispatch:

env:
HOMARR_DOCUMENTATION_GH_TOKEN: "${{ secrets.HOMARR_DOCUMENTATION_GH_TOKEN }}"
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
HOMARR_CROWDIN_TOKEN: "${{ secrets.HOMARR_CROWDIN_TOKEN }}"
HOMARR_LABS_CROWDIN_TOKEN: "${{ secrets.HOMARR_LABS_CROWDIN_TOKEN }}"

permissions:
contents: write
Expand All @@ -17,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20]
node-version: [22]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"api-dump-contributors": "node ./scripts/dump-contributors.js"
"api-dump-contributors": "node ./scripts/dump-contributors.mjs"
},
"dependencies": {
"@dipakparmar/docusaurus-plugin-umami": "^2.1.2",
Expand Down
74 changes: 0 additions & 74 deletions scripts/dump-contributors.js

This file was deleted.

103 changes: 103 additions & 0 deletions scripts/dump-contributors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { z } from 'zod';
import fs from 'fs/promises';

const sources = {
crowdin: [
{ projectId: 534422, tokenName: 'HOMARR_CROWDIN_TOKEN' },
{ projectId: 742587, tokenName: 'HOMARR_LABS_CROWDIN_TOKEN' },
],
github: [
{ repository: 'homarr', slug: 'ajnart' },
{ repository: 'homarr', slug: 'homarr-labs' },
],
};

const schema = z.object({
GITHUB_TOKEN: z.string().nonempty(),
HOMARR_CROWDIN_TOKEN: z.string().nonempty(),
HOMARR_LABS_CROWDIN_TOKEN: z.string().nonempty(),
});

const env = schema.parse(process.env);

const fetchGithubContributors = async (slug, repository) => {
const url = `https://api.github.com/repos/${slug}/${repository}/contributors?per_page=999`;
const options = {
method: 'GET',
headers: {
Authorization: `Bearer ${env.GITHUB_TOKEN}`,
Accept: 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
},
};

const response = await fetch(url, options);
const data = await response.json();

const dataSchema = z.array(
z.object({
login: z.string(),
avatar_url: z.string().url(),
contributions: z.number(),
})
);

return dataSchema.parse(data);
};

const fetchCrowdinMembers = async (projectId, tokenName) => {
const url = `https://crowdin.com/api/v2/projects/${projectId}/members`;
const options = {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${env[tokenName]}`,
},
};

const response = await fetch(url, options);
const data = await response.json();

const dataSchema = z.object({
data: z.array(
z.object({
data: z.object({
username: z.string(),
avatarUrl: z.string().url(),
}),
})
),
});

const contributionsData = dataSchema.parse(data);

return contributionsData.data.flatMap((data) => data.data);
};

const distinctBy = (callback) => (value, index, self) => {
return self.findIndex((item) => callback(item) == callback(value)) === index;
};

const githubContributors = [];
const crowdinContributors = [];

for (const { repository, slug } of sources.github) {
githubContributors.push(...(await fetchGithubContributors(slug, repository)));
}
const distinctGithubContributors = githubContributors
.filter(distinctBy((contributor) => contributor.login))
.sort((a, b) => b.contributions - a.contributions)
.map(({ contributions, ...props }) => props)
.filter((contributor) => !contributor.login.includes('[bot]'));
await fs.writeFile('./static/data/contributions.json', JSON.stringify(distinctGithubContributors));

for (const { projectId, tokenName } of sources.crowdin) {
crowdinContributors.push(...(await fetchCrowdinMembers(projectId, tokenName)));
}
const distinctCrowdinContributors = crowdinContributors.filter(
distinctBy((contributor) => contributor.username)
);
await fs.writeFile(
'./static/data/translation-contributions.json',
JSON.stringify(distinctCrowdinContributors)
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,37 @@ type Contributor = {
};

// do not add any real users here
const blacklistedUsernames = ['deepsource-autofix[bot]', 'deepsource-io[bot]', 'renovate[bot]', 'dependabot[bot]'];
const blacklistedUsernames = [
'deepsource-autofix[bot]',
'deepsource-io[bot]',
'renovate[bot]',
'dependabot[bot]',
];

export const CodeContributorList = () => {
const [contributors, setContributors] = useState<Contributor[]>([]);

useEffect(() => {
fetch('./data/contributions.json').then(async (response) => {
fetch('/data/contributions.json').then(async (response) => {
const data = await response.json();
setContributors(data.filter((contributor: Contributor) => !blacklistedUsernames.includes(contributor.login)));
setContributors(
data.filter((contributor: Contributor) => !blacklistedUsernames.includes(contributor.login))
);
});
}, []);

return (
<div className={'flex flex-wrap gap-3'}>
{contributors.map((contributor: Contributor) => (
<div className={'flex flex-col items-center w-24'}>
<img className={'w-24 h-24 aspect-square rounded mb-2'} src={contributor.avatar_url} alt={''} />
<h6 className={"truncate text-nowrap max-w-full"}>{contributor.login}</h6>
<img
className={'w-24 h-24 aspect-square rounded mb-2'}
src={contributor.avatar_url}
alt={''}
/>
<h6 className={'truncate text-nowrap max-w-full'}>{contributor.login}</h6>
</div>
))}
</div>
);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const TranslationContributorList = () => {
const [contributors, setContributors] = useState<Contributor[]>([]);

useEffect(() => {
fetch('./data/translation-contributions.json').then(async (response) => {
fetch('/data/translation-contributions.json').then(async (response) => {
const data = await response.json();
setContributors(data);
});
Expand All @@ -19,10 +19,14 @@ export const TranslationContributorList = () => {
<div className={'flex flex-wrap gap-3'}>
{contributors.map((contributor: Contributor) => (
<div className={'flex flex-col items-center w-24'}>
<img className={'w-24 h-24 aspect-square rounded mb-2'} src={contributor.avatarUrl} alt={''} />
<h6 className={"truncate text-nowrap max-w-full"}>{contributor.username}</h6>
<img
className={'w-24 h-24 aspect-square rounded mb-2'}
src={contributor.avatarUrl}
alt={''}
/>
<h6 className={'truncate text-nowrap max-w-full'}>{contributor.username}</h6>
</div>
))}
</div>
);
};
};
2 changes: 1 addition & 1 deletion static/data/contributions.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"login":"ajnart","avatar_url":"https://avatars.githubusercontent.com/u/49837342?v=4"},{"login":"manuel-rw","avatar_url":"https://avatars.githubusercontent.com/u/30572287?v=4"},{"login":"Meierschlumpf","avatar_url":"https://avatars.githubusercontent.com/u/63781622?v=4"},{"login":"renovate[bot]","avatar_url":"https://avatars.githubusercontent.com/in/2740?v=4"},{"login":"SeDemal","avatar_url":"https://avatars.githubusercontent.com/u/26098587?v=4"},{"login":"walkxcode","avatar_url":"https://avatars.githubusercontent.com/u/71191962?v=4"},{"login":"LarveyOfficial","avatar_url":"https://avatars.githubusercontent.com/u/39219859?v=4"},{"login":"c00ldude1oo","avatar_url":"https://avatars.githubusercontent.com/u/15677803?v=4"},{"login":"InterN0te","avatar_url":"https://avatars.githubusercontent.com/u/10882916?v=4"},{"login":"Aimsucks","avatar_url":"https://avatars.githubusercontent.com/u/1828486?v=4"},{"login":"JannesV","avatar_url":"https://avatars.githubusercontent.com/u/5984244?v=4"},{"login":"MauriceNino","avatar_url":"https://avatars.githubusercontent.com/u/18658092?v=4"},{"login":"hillaliy","avatar_url":"https://avatars.githubusercontent.com/u/950010?v=4"},{"login":"Skeeww","avatar_url":"https://avatars.githubusercontent.com/u/9639992?v=4"},{"login":"deepsource-autofix[bot]","avatar_url":"https://avatars.githubusercontent.com/in/57168?v=4"},{"login":"RichyHBM","avatar_url":"https://avatars.githubusercontent.com/u/5472275?v=4"},{"login":"Bonfire","avatar_url":"https://avatars.githubusercontent.com/u/5704760?v=4"},{"login":"wieli99","avatar_url":"https://avatars.githubusercontent.com/u/46794825?v=4"},{"login":"ishaanparlikar","avatar_url":"https://avatars.githubusercontent.com/u/43013132?v=4"},{"login":"Zareix","avatar_url":"https://avatars.githubusercontent.com/u/29818713?v=4"},{"login":"tuggan","avatar_url":"https://avatars.githubusercontent.com/u/4325608?v=4"},{"login":"dependabot[bot]","avatar_url":"https://avatars.githubusercontent.com/in/29110?v=4"},{"login":"deepsource-io[bot]","avatar_url":"https://avatars.githubusercontent.com/in/16372?v=4"},{"login":"Spillebulle","avatar_url":"https://avatars.githubusercontent.com/u/46653946?v=4"},{"login":"tancak","avatar_url":"https://avatars.githubusercontent.com/u/11760749?v=4"},{"login":"spkesDE","avatar_url":"https://avatars.githubusercontent.com/u/1682314?v=4"},{"login":"j3lte","avatar_url":"https://avatars.githubusercontent.com/u/2557568?v=4"},{"login":"dslatt","avatar_url":"https://avatars.githubusercontent.com/u/5211001?v=4"},{"login":"Malong11-007","avatar_url":"https://avatars.githubusercontent.com/u/40298510?v=4"},{"login":"Lollyde","avatar_url":"https://avatars.githubusercontent.com/u/11347524?v=4"}]
[{"login":"ajnart","avatar_url":"https://avatars.githubusercontent.com/u/49837342?v=4"},{"login":"manuel-rw","avatar_url":"https://avatars.githubusercontent.com/u/30572287?v=4"},{"login":"Meierschlumpf","avatar_url":"https://avatars.githubusercontent.com/u/63781622?v=4"},{"login":"SeDemal","avatar_url":"https://avatars.githubusercontent.com/u/26098587?v=4"},{"login":"walkxcode","avatar_url":"https://avatars.githubusercontent.com/u/71191962?v=4"},{"login":"LarveyOfficial","avatar_url":"https://avatars.githubusercontent.com/u/39219859?v=4"},{"login":"c00ldude1oo","avatar_url":"https://avatars.githubusercontent.com/u/15677803?v=4"},{"login":"InterN0te","avatar_url":"https://avatars.githubusercontent.com/u/10882916?v=4"},{"login":"Aimsucks","avatar_url":"https://avatars.githubusercontent.com/u/1828486?v=4"},{"login":"JannesV","avatar_url":"https://avatars.githubusercontent.com/u/5984244?v=4"},{"login":"MauriceNino","avatar_url":"https://avatars.githubusercontent.com/u/18658092?v=4"},{"login":"hillaliy","avatar_url":"https://avatars.githubusercontent.com/u/950010?v=4"},{"login":"Skeeww","avatar_url":"https://avatars.githubusercontent.com/u/9639992?v=4"},{"login":"RichyHBM","avatar_url":"https://avatars.githubusercontent.com/u/5472275?v=4"},{"login":"Bonfire","avatar_url":"https://avatars.githubusercontent.com/u/5704760?v=4"},{"login":"wieli99","avatar_url":"https://avatars.githubusercontent.com/u/46794825?v=4"},{"login":"ishaanparlikar","avatar_url":"https://avatars.githubusercontent.com/u/43013132?v=4"},{"login":"Zareix","avatar_url":"https://avatars.githubusercontent.com/u/29818713?v=4"},{"login":"tuggan","avatar_url":"https://avatars.githubusercontent.com/u/4325608?v=4"},{"login":"Spillebulle","avatar_url":"https://avatars.githubusercontent.com/u/46653946?v=4"},{"login":"tancak","avatar_url":"https://avatars.githubusercontent.com/u/11760749?v=4"},{"login":"spkesDE","avatar_url":"https://avatars.githubusercontent.com/u/1682314?v=4"},{"login":"j3lte","avatar_url":"https://avatars.githubusercontent.com/u/2557568?v=4"},{"login":"dslatt","avatar_url":"https://avatars.githubusercontent.com/u/5211001?v=4"},{"login":"Malong11-007","avatar_url":"https://avatars.githubusercontent.com/u/40298510?v=4"},{"login":"MaienM","avatar_url":"https://avatars.githubusercontent.com/u/583129?v=4"},{"login":"toineenzo","avatar_url":"https://avatars.githubusercontent.com/u/4921397?v=4"},{"login":"Lollyde","avatar_url":"https://avatars.githubusercontent.com/u/11347524?v=4"},{"login":"Havock94","avatar_url":"https://avatars.githubusercontent.com/u/7635248?v=4"},{"login":"Lumilias","avatar_url":"https://avatars.githubusercontent.com/u/10852161?v=4"},{"login":"marius-arch","avatar_url":"https://avatars.githubusercontent.com/u/72494359?v=4"},{"login":"Momcilo42","avatar_url":"https://avatars.githubusercontent.com/u/10118137?v=4"},{"login":"stark1tty","avatar_url":"https://avatars.githubusercontent.com/u/69326376?v=4"},{"login":"No-Maines-Land","avatar_url":"https://avatars.githubusercontent.com/u/20687725?v=4"},{"login":"NormanJS","avatar_url":"https://avatars.githubusercontent.com/u/83409549?v=4"},{"login":"Rikpat","avatar_url":"https://avatars.githubusercontent.com/u/33869814?v=4"},{"login":"SR3u","avatar_url":"https://avatars.githubusercontent.com/u/2380522?v=4"},{"login":"souravghosh01","avatar_url":"https://avatars.githubusercontent.com/u/37548139?v=4"},{"login":"StefanB7","avatar_url":"https://avatars.githubusercontent.com/u/22056509?v=4"},{"login":"devtobi","avatar_url":"https://avatars.githubusercontent.com/u/28538704?v=4"},{"login":"TyxTang","avatar_url":"https://avatars.githubusercontent.com/u/90897955?v=4"},{"login":"VinnyVynce","avatar_url":"https://avatars.githubusercontent.com/u/19630511?v=4"},{"login":"Willy-JL","avatar_url":"https://avatars.githubusercontent.com/u/49810075?v=4"},{"login":"anonysoul","avatar_url":"https://avatars.githubusercontent.com/u/105715150?v=4"},{"login":"cospeedster","avatar_url":"https://avatars.githubusercontent.com/u/52749645?v=4"},{"login":"diederbert","avatar_url":"https://avatars.githubusercontent.com/u/162878798?v=4"},{"login":"digdilem","avatar_url":"https://avatars.githubusercontent.com/u/4052275?v=4"},{"login":"dinghino","avatar_url":"https://avatars.githubusercontent.com/u/14729459?v=4"},{"login":"gfomichev","avatar_url":"https://avatars.githubusercontent.com/u/1596146?v=4"},{"login":"gnattu","avatar_url":"https://avatars.githubusercontent.com/u/12995396?v=4"},{"login":"tuxpizza","avatar_url":"https://avatars.githubusercontent.com/u/84710786?v=4"},{"login":"huanga","avatar_url":"https://avatars.githubusercontent.com/u/732970?v=4"},{"login":"taos15","avatar_url":"https://avatars.githubusercontent.com/u/122130728?v=4"},{"login":"arghyadipchak","avatar_url":"https://avatars.githubusercontent.com/u/32430374?v=4"},{"login":"AuthorShin","avatar_url":"https://avatars.githubusercontent.com/u/4959043?v=4"},{"login":"benniblot","avatar_url":"https://avatars.githubusercontent.com/u/47495914?v=4"},{"login":"bebsworthy","avatar_url":"https://avatars.githubusercontent.com/u/5266759?v=4"},{"login":"catrielmuller","avatar_url":"https://avatars.githubusercontent.com/u/2272323?v=4"},{"login":"Vysp3r","avatar_url":"https://avatars.githubusercontent.com/u/62019735?v=4"},{"login":"singular0","avatar_url":"https://avatars.githubusercontent.com/u/1925883?v=4"},{"login":"diogovalentte","avatar_url":"https://avatars.githubusercontent.com/u/49578155?v=4"},{"login":"codezninja","avatar_url":"https://avatars.githubusercontent.com/u/4400773?v=4"},{"login":"fabricionaweb","avatar_url":"https://avatars.githubusercontent.com/u/15933?v=4"},{"login":"nyok1912","avatar_url":"https://avatars.githubusercontent.com/u/32163949?v=4"},{"login":"bo3bdo","avatar_url":"https://avatars.githubusercontent.com/u/5271380?v=4"},{"login":"hskrtich","avatar_url":"https://avatars.githubusercontent.com/u/1214484?v=4"},{"login":"ishults","avatar_url":"https://avatars.githubusercontent.com/u/7275442?v=4"},{"login":"jelliuk","avatar_url":"https://avatars.githubusercontent.com/u/4790959?v=4"},{"login":"Moohan","avatar_url":"https://avatars.githubusercontent.com/u/5982260?v=4"},{"login":"jbruell","avatar_url":"https://avatars.githubusercontent.com/u/31685172?v=4"},{"login":"JasonLeeB06","avatar_url":"https://avatars.githubusercontent.com/u/82266978?v=4"},{"login":"jeffersonraimon","avatar_url":"https://avatars.githubusercontent.com/u/80064475?v=4"},{"login":"joser93","avatar_url":"https://avatars.githubusercontent.com/u/6912089?v=4"},{"login":"justijndepover","avatar_url":"https://avatars.githubusercontent.com/u/9008623?v=4"},{"login":"krishnamuppaneni","avatar_url":"https://avatars.githubusercontent.com/u/4703366?v=4"},{"login":"oben01","avatar_url":"https://avatars.githubusercontent.com/u/22369027?v=4"}]
2 changes: 1 addition & 1 deletion static/data/translation-contributions.json

Large diffs are not rendered by default.

Loading