@lizardbyte/contribkit 2025.315.185528 → 2025.327.11019
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -6
- package/dist/chunks/index.mjs +2 -3
- package/dist/cli.d.mts +1 -1
- package/dist/cli.mjs +3 -2
- package/dist/index.d.mts +77 -3
- package/dist/index.mjs +3 -2
- package/dist/shared/{contribkit.QISHqB4U.mjs → contribkit.ClLqkpuL.mjs} +240 -7
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -11,18 +11,45 @@ This is a fork of [sponsorkit](https://github.com/antfu-collective/sponsorkit) t
|
|
|
11
11
|
|
|
12
12
|
Supports:
|
|
13
13
|
|
|
14
|
-
-
|
|
15
|
-
- [**
|
|
16
|
-
- [**
|
|
17
|
-
- [**
|
|
18
|
-
-
|
|
19
|
-
- [**
|
|
14
|
+
- Contributors:
|
|
15
|
+
- [**CrowdIn**](https://crowdin.com)
|
|
16
|
+
- [**GitHub**](https://github.com)
|
|
17
|
+
- [**Gitlab**](https://gitlab.com)
|
|
18
|
+
- Sponsors:
|
|
19
|
+
- [**GitHub Sponsors**](https://github.com/sponsors)
|
|
20
|
+
- [**Patreon**](https://www.patreon.com/)
|
|
21
|
+
- [**OpenCollective**](https://opencollective.com/)
|
|
22
|
+
- [**Afdian**](https://afdian.com/)
|
|
23
|
+
- [**Polar**](https://polar.sh/)
|
|
24
|
+
- [**Liberapay**](https://liberapay.com/)
|
|
20
25
|
|
|
21
26
|
## Usage
|
|
22
27
|
|
|
23
28
|
Create `.env` file with:
|
|
24
29
|
|
|
25
30
|
```ini
|
|
31
|
+
;; Contributors
|
|
32
|
+
|
|
33
|
+
; CrowdInContributors provider.
|
|
34
|
+
CONTRIBKIT_CROWDIN_TOKEN=
|
|
35
|
+
CONTRIBKIT_CROWDIN_PROJECT_ID=
|
|
36
|
+
CONTRIBKIT_CROWDIN_MIN_TRANSLATIONS=1
|
|
37
|
+
|
|
38
|
+
; GitHubContributors provider.
|
|
39
|
+
; Token requires the `public_repo` and `read:user` scopes.
|
|
40
|
+
CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN=
|
|
41
|
+
CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN=
|
|
42
|
+
CONTRIBKIT_GITHUB_CONTRIBUTORS_MIN=1
|
|
43
|
+
CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO=
|
|
44
|
+
|
|
45
|
+
; GitlabContributors provider.
|
|
46
|
+
; Token requires the `read_api` and `read_user` scopes.
|
|
47
|
+
CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN=
|
|
48
|
+
CONTRIBKIT_GITLAB_CONTRIBUTORS_MIN=1
|
|
49
|
+
CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID=
|
|
50
|
+
|
|
51
|
+
;; Sponsors
|
|
52
|
+
|
|
26
53
|
; GitHub provider.
|
|
27
54
|
; Token requires the `read:user` and `read:org` scopes.
|
|
28
55
|
CONTRIBKIT_GITHUB_TOKEN=
|
|
@@ -64,6 +91,11 @@ CONTRIBKIT_LIBERAPAY_LOGIN=
|
|
|
64
91
|
|
|
65
92
|
> Only one provider is required to be configured.
|
|
66
93
|
|
|
94
|
+
> ![NOTE]
|
|
95
|
+
> The contributor providers are intended to be separated from each other, unlike the sponsor providers.
|
|
96
|
+
> This will require different env variables to be set for each provider, and to be created from separate
|
|
97
|
+
> commands.
|
|
98
|
+
|
|
67
99
|
Run:
|
|
68
100
|
|
|
69
101
|
```base
|
package/dist/chunks/index.mjs
CHANGED
package/dist/cli.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
|
|
2
|
-
export {
|
|
2
|
+
export { };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cac from 'cac';
|
|
2
|
-
import { S as SvgComposer, i as generateBadge, p as partitionTiers, t as tierPresets, v as version, l as loadConfig, k as resolveProviders, j as guessProviders, r as resolveAvatars, q as outputFormats, s as svgToPng, g as svgToWebp } from './shared/contribkit.
|
|
2
|
+
import { S as SvgComposer, i as generateBadge, p as partitionTiers, t as tierPresets, v as version, l as loadConfig, k as resolveProviders, j as guessProviders, r as resolveAvatars, q as outputFormats, s as svgToPng, g as svgToWebp } from './shared/contribkit.ClLqkpuL.mjs';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import fsp from 'node:fs/promises';
|
|
5
5
|
import { resolve, dirname, relative, join } from 'node:path';
|
|
@@ -9,9 +9,10 @@ import { consola } from 'consola';
|
|
|
9
9
|
import { Buffer } from 'node:buffer';
|
|
10
10
|
import 'unconfig';
|
|
11
11
|
import 'dotenv';
|
|
12
|
+
import 'node:crypto';
|
|
12
13
|
import 'ofetch';
|
|
13
14
|
import 'sharp';
|
|
14
|
-
import '
|
|
15
|
+
import '@crowdin/crowdin-api-client';
|
|
15
16
|
|
|
16
17
|
function notNullish(v) {
|
|
17
18
|
return v != null;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Buffer as Buffer$1 } from 'node:buffer';
|
|
2
|
-
import
|
|
2
|
+
import { consola } from 'consola';
|
|
3
3
|
|
|
4
4
|
declare function genSvgImage(x: number, y: number, size: number, radius: number, base64Image: string, imageFormat: ImageFormat): string;
|
|
5
5
|
declare function generateBadge(x: number, y: number, sponsor: Sponsor, preset: BadgePreset, radius: number, imageFormat: ImageFormat): Promise<string>;
|
|
@@ -83,7 +83,7 @@ interface Sponsorship {
|
|
|
83
83
|
}
|
|
84
84
|
declare const outputFormats: readonly ["svg", "png", "webp", "json"];
|
|
85
85
|
type OutputFormat = typeof outputFormats[number];
|
|
86
|
-
type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian' | 'polar' | 'liberapay';
|
|
86
|
+
type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian' | 'polar' | 'liberapay' | 'githubContributors' | 'gitlabContributors' | 'crowdinContributors';
|
|
87
87
|
type GitHubAccountType = 'user' | 'organization';
|
|
88
88
|
interface ProvidersConfig {
|
|
89
89
|
github?: {
|
|
@@ -208,6 +208,76 @@ interface ProvidersConfig {
|
|
|
208
208
|
*/
|
|
209
209
|
login?: string;
|
|
210
210
|
};
|
|
211
|
+
githubContributors?: {
|
|
212
|
+
/**
|
|
213
|
+
* User id of your GitHub account.
|
|
214
|
+
*
|
|
215
|
+
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN` environment variable if not set.
|
|
216
|
+
*/
|
|
217
|
+
login?: string;
|
|
218
|
+
/**
|
|
219
|
+
* GitHub Token that have access to your sponsorships.
|
|
220
|
+
*
|
|
221
|
+
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN` environment variable if not set.
|
|
222
|
+
*
|
|
223
|
+
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
|
|
224
|
+
*/
|
|
225
|
+
token?: string;
|
|
226
|
+
/**
|
|
227
|
+
* The minimum number of contributions to be considered a sponsor.
|
|
228
|
+
*
|
|
229
|
+
* @default 1
|
|
230
|
+
*/
|
|
231
|
+
minContributions?: number;
|
|
232
|
+
/**
|
|
233
|
+
* The repository to fetch contributors from.
|
|
234
|
+
*
|
|
235
|
+
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO` environment variable if not set.
|
|
236
|
+
*/
|
|
237
|
+
repo?: string;
|
|
238
|
+
};
|
|
239
|
+
gitlabContributors?: {
|
|
240
|
+
/**
|
|
241
|
+
* Gitlab Token that have access contributors.
|
|
242
|
+
*
|
|
243
|
+
* Will read from `CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN` environment variable if not set.
|
|
244
|
+
*
|
|
245
|
+
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
|
|
246
|
+
*/
|
|
247
|
+
token?: string;
|
|
248
|
+
/**
|
|
249
|
+
* The minimum number of contributions to be considered a sponsor.
|
|
250
|
+
*
|
|
251
|
+
* @default 1
|
|
252
|
+
*/
|
|
253
|
+
minContributions?: number;
|
|
254
|
+
/**
|
|
255
|
+
* The repository ID to fetch contributors from.
|
|
256
|
+
*
|
|
257
|
+
* Will read from `CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID` environment variable if not set.
|
|
258
|
+
*/
|
|
259
|
+
repoId?: number;
|
|
260
|
+
};
|
|
261
|
+
crowdinContributors?: {
|
|
262
|
+
/**
|
|
263
|
+
* The Crowdin API token.
|
|
264
|
+
*
|
|
265
|
+
* Will read from `CONTRIBKIT_CROWDIN_TOKEN` environment variable if not set.
|
|
266
|
+
*/
|
|
267
|
+
token?: string;
|
|
268
|
+
/**
|
|
269
|
+
* The project id on Crowdin.
|
|
270
|
+
*
|
|
271
|
+
* Will read from `CONTRIBKIT_CROWDIN_PROJECT_ID` environment variable if not set.
|
|
272
|
+
*/
|
|
273
|
+
projectId?: number;
|
|
274
|
+
/**
|
|
275
|
+
* The minimum number of translations to be considered a sponsor.
|
|
276
|
+
*
|
|
277
|
+
* @default 100
|
|
278
|
+
*/
|
|
279
|
+
minTranslations?: number;
|
|
280
|
+
};
|
|
211
281
|
}
|
|
212
282
|
interface ContribkitRenderOptions {
|
|
213
283
|
/**
|
|
@@ -486,9 +556,13 @@ declare const ProvidersMap: {
|
|
|
486
556
|
afdian: Provider;
|
|
487
557
|
polar: Provider;
|
|
488
558
|
liberapay: Provider;
|
|
559
|
+
githubContributors: Provider;
|
|
560
|
+
gitlabContributors: Provider;
|
|
561
|
+
crowdinContributors: Provider;
|
|
489
562
|
};
|
|
490
563
|
declare function guessProviders(config: ContribkitConfig): ProviderName[];
|
|
491
564
|
declare function resolveProviders(names: (ProviderName | Provider)[]): Provider[];
|
|
492
565
|
declare function fetchSponsors(config: ContribkitConfig): Promise<Sponsorship[]>;
|
|
493
566
|
|
|
494
|
-
export {
|
|
567
|
+
export { FALLBACK_AVATAR, GitHubProvider, ProvidersMap, SvgComposer, defaultConfig, defaultInlineCSS, defaultTiers, defineConfig, fetchGitHubSponsors, fetchSponsors, genSvgImage, generateBadge, guessProviders, loadConfig, makeQuery, outputFormats, partitionTiers, presets, resizeImage, resolveAvatars, resolveProviders, svgToPng, svgToWebp, tierPresets };
|
|
568
|
+
export type { BadgePreset, CircleRenderOptions, ContribkitConfig, ContribkitMainConfig, ContribkitRenderOptions, ContribkitRenderer, GitHubAccountType, ImageFormat, OutputFormat, Provider, ProviderName, ProvidersConfig, Sponsor, SponsorMatcher, Sponsorship, Tier, TierPartition };
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export { F as FALLBACK_AVATAR, G as GitHubProvider, P as ProvidersMap, S as SvgComposer, c as defaultConfig, b as defaultInlineCSS, a as defaultTiers, d as defineConfig, n as fetchGitHubSponsors, m as fetchSponsors, h as genSvgImage, i as generateBadge, j as guessProviders, l as loadConfig, o as makeQuery, q as outputFormats, p as partitionTiers, e as presets, f as resizeImage, r as resolveAvatars, k as resolveProviders, s as svgToPng, g as svgToWebp, t as tierPresets } from './shared/contribkit.
|
|
1
|
+
export { F as FALLBACK_AVATAR, G as GitHubProvider, P as ProvidersMap, S as SvgComposer, c as defaultConfig, b as defaultInlineCSS, a as defaultTiers, d as defineConfig, n as fetchGitHubSponsors, m as fetchSponsors, h as genSvgImage, i as generateBadge, j as guessProviders, l as loadConfig, o as makeQuery, q as outputFormats, p as partitionTiers, e as presets, f as resizeImage, r as resolveAvatars, k as resolveProviders, s as svgToPng, g as svgToWebp, t as tierPresets } from './shared/contribkit.ClLqkpuL.mjs';
|
|
2
2
|
import 'unconfig';
|
|
3
3
|
import 'node:process';
|
|
4
4
|
import 'dotenv';
|
|
5
|
+
import 'node:crypto';
|
|
5
6
|
import 'node:buffer';
|
|
6
7
|
import 'consola';
|
|
7
8
|
import 'ofetch';
|
|
8
9
|
import 'sharp';
|
|
9
|
-
import '
|
|
10
|
+
import '@crowdin/crowdin-api-client';
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { loadConfig as loadConfig$1 } from 'unconfig';
|
|
2
2
|
import process from 'node:process';
|
|
3
3
|
import dotenv from 'dotenv';
|
|
4
|
+
import crypto, { createHash } from 'node:crypto';
|
|
4
5
|
import { Buffer } from 'node:buffer';
|
|
5
6
|
import { consola } from 'consola';
|
|
6
7
|
import { $fetch, ofetch } from 'ofetch';
|
|
7
8
|
import sharp from 'sharp';
|
|
8
|
-
import {
|
|
9
|
+
import { ProjectsGroups, Reports } from '@crowdin/crowdin-api-client';
|
|
9
10
|
|
|
10
11
|
const none = {
|
|
11
12
|
avatar: {
|
|
@@ -179,12 +180,28 @@ function loadEnv() {
|
|
|
179
180
|
liberapay: {
|
|
180
181
|
login: process.env.CONTRIBKIT_LIBERAPAY_LOGIN || process.env.LIBERAPAY_LOGIN
|
|
181
182
|
},
|
|
182
|
-
outputDir: process.env.CONTRIBKIT_DIR
|
|
183
|
+
outputDir: process.env.CONTRIBKIT_DIR,
|
|
184
|
+
githubContributors: {
|
|
185
|
+
login: process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN,
|
|
186
|
+
token: process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN,
|
|
187
|
+
minContributions: Number(process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_MIN) || 1,
|
|
188
|
+
repo: process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO
|
|
189
|
+
},
|
|
190
|
+
gitlabContributors: {
|
|
191
|
+
token: process.env.CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN,
|
|
192
|
+
minContributions: Number(process.env.CONTRIBKIT_GITLAB_CONTRIBUTORS_MIN) || 1,
|
|
193
|
+
repoId: Number(process.env.CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID)
|
|
194
|
+
},
|
|
195
|
+
crowdinContributors: {
|
|
196
|
+
token: process.env.CONTRIBKIT_CROWDIN_TOKEN,
|
|
197
|
+
projectId: Number(process.env.CONTRIBKIT_CROWDIN_PROJECT_ID),
|
|
198
|
+
minTranslations: Number(process.env.CONTRIBKIT_CROWDIN_MIN_TRANSLATIONS) || 1
|
|
199
|
+
}
|
|
183
200
|
};
|
|
184
201
|
return JSON.parse(JSON.stringify(config));
|
|
185
202
|
}
|
|
186
203
|
|
|
187
|
-
const version = "2025.
|
|
204
|
+
const version = "2025.327.11019";
|
|
188
205
|
|
|
189
206
|
async function fetchImage(url) {
|
|
190
207
|
const arrayBuffer = await $fetch(url, {
|
|
@@ -265,10 +282,16 @@ async function loadConfig(inlineConfig = {}) {
|
|
|
265
282
|
const { config = {} } = await loadConfig$1({
|
|
266
283
|
sources: [
|
|
267
284
|
{
|
|
268
|
-
files: "
|
|
285
|
+
files: "contrib.config"
|
|
269
286
|
},
|
|
270
287
|
{
|
|
271
288
|
files: "contribkit.config"
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
files: "sponsor.config"
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
files: "sponsorkit.config"
|
|
272
295
|
}
|
|
273
296
|
],
|
|
274
297
|
merge: true
|
|
@@ -321,9 +344,8 @@ function partitionTiers(sponsors, tiers, includePastSponsors) {
|
|
|
321
344
|
return tierMappings;
|
|
322
345
|
}
|
|
323
346
|
|
|
324
|
-
let id = 0;
|
|
325
347
|
function genSvgImage(x, y, size, radius, base64Image, imageFormat) {
|
|
326
|
-
const cropId = `c${
|
|
348
|
+
const cropId = `c${crypto.createHash("md5").update(base64Image).digest("hex").slice(0, 6)}`;
|
|
327
349
|
return `
|
|
328
350
|
<clipPath id="${cropId}">
|
|
329
351
|
<rect x="${x}" y="${y}" width="${size}" height="${size}" rx="${size * radius}" ry="${size * radius}" />
|
|
@@ -503,6 +525,65 @@ function md5(token, params, ts, userId) {
|
|
|
503
525
|
return createHash("md5").update(`${token}params${params}ts${ts}user_id${userId}`).digest("hex");
|
|
504
526
|
}
|
|
505
527
|
|
|
528
|
+
const CrowdinContributorsProvider = {
|
|
529
|
+
name: "crowdinContributors",
|
|
530
|
+
fetchSponsors(config) {
|
|
531
|
+
return fetchCrowdinContributors(
|
|
532
|
+
config.crowdinContributors?.token || config.token,
|
|
533
|
+
config.crowdinContributors?.projectId || 0,
|
|
534
|
+
config.crowdinContributors?.minTranslations || 1
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
async function fetchCrowdinContributors(token, projectId, minTranslations = 1) {
|
|
539
|
+
if (!token)
|
|
540
|
+
throw new Error("Crowdin token is required");
|
|
541
|
+
if (!projectId)
|
|
542
|
+
throw new Error("Crowdin project ID is required");
|
|
543
|
+
const credentials = {
|
|
544
|
+
token
|
|
545
|
+
};
|
|
546
|
+
const projectsGroups = new ProjectsGroups(credentials);
|
|
547
|
+
const project = await projectsGroups.getProject(projectId);
|
|
548
|
+
const reports = new Reports(credentials);
|
|
549
|
+
const dateTo = (/* @__PURE__ */ new Date()).toISOString();
|
|
550
|
+
const dateFrom = project.data.createdAt;
|
|
551
|
+
const createReportRequestBody = {
|
|
552
|
+
name: "top-members",
|
|
553
|
+
schema: {
|
|
554
|
+
unit: "words",
|
|
555
|
+
format: "json",
|
|
556
|
+
dateFrom,
|
|
557
|
+
dateTo
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
const createReport = await reports.generateReport(projectId, createReportRequestBody);
|
|
561
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
562
|
+
const report = await reports.downloadReport(projectId, createReport.data.identifier);
|
|
563
|
+
const reportRaw = await fetch(report.data.url);
|
|
564
|
+
const reportData = await reportRaw.json();
|
|
565
|
+
const contributors = reportData.data.filter((entry) => entry.translated > minTranslations).map((entry) => ({
|
|
566
|
+
member: entry.user,
|
|
567
|
+
translations: entry.translated
|
|
568
|
+
}));
|
|
569
|
+
return contributors.filter(Boolean).map(({ member, translations }) => ({
|
|
570
|
+
sponsor: {
|
|
571
|
+
type: "User",
|
|
572
|
+
login: member.username,
|
|
573
|
+
name: member.username,
|
|
574
|
+
// fullName is also available
|
|
575
|
+
avatarUrl: member.avatarUrl,
|
|
576
|
+
linkUrl: `https://crowdin.com/profile/${member.username}`
|
|
577
|
+
},
|
|
578
|
+
isOneTime: false,
|
|
579
|
+
monthlyDollars: translations,
|
|
580
|
+
privacyLevel: "PUBLIC",
|
|
581
|
+
tierName: "Translator",
|
|
582
|
+
createdAt: member.joinedAt,
|
|
583
|
+
provider: "crowdinContributors"
|
|
584
|
+
}));
|
|
585
|
+
}
|
|
586
|
+
|
|
506
587
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
|
|
507
588
|
const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain';
|
|
508
589
|
const DATA_URL_DEFAULT_CHARSET = 'us-ascii';
|
|
@@ -939,6 +1020,149 @@ function makeQuery(login, type, activeOnly = true, cursor) {
|
|
|
939
1020
|
}`;
|
|
940
1021
|
}
|
|
941
1022
|
|
|
1023
|
+
const GitHubContributorsProvider = {
|
|
1024
|
+
name: "githubContributors",
|
|
1025
|
+
fetchSponsors(config) {
|
|
1026
|
+
if (!config.githubContributors?.repo)
|
|
1027
|
+
throw new Error("GitHub repository is required");
|
|
1028
|
+
return fetchGitHubContributors(
|
|
1029
|
+
config.githubContributors?.token || config.token,
|
|
1030
|
+
config.githubContributors?.login || config.login,
|
|
1031
|
+
config.githubContributors.repo,
|
|
1032
|
+
config.githubContributors?.minContributions
|
|
1033
|
+
);
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
async function fetchGitHubContributors(token, login, repo, minContributions = 1) {
|
|
1037
|
+
if (!token)
|
|
1038
|
+
throw new Error("GitHub token is required");
|
|
1039
|
+
if (!login)
|
|
1040
|
+
throw new Error("GitHub login is required");
|
|
1041
|
+
if (!repo)
|
|
1042
|
+
throw new Error("GitHub repository is required");
|
|
1043
|
+
const allContributors = [];
|
|
1044
|
+
let page = 1;
|
|
1045
|
+
let hasNextPage = true;
|
|
1046
|
+
while (hasNextPage) {
|
|
1047
|
+
const response = await $fetch(
|
|
1048
|
+
`https://api.github.com/repos/${login}/${repo}/contributors`,
|
|
1049
|
+
{
|
|
1050
|
+
query: {
|
|
1051
|
+
page: String(page),
|
|
1052
|
+
per_page: "100"
|
|
1053
|
+
},
|
|
1054
|
+
headers: {
|
|
1055
|
+
Authorization: `bearer ${token}`,
|
|
1056
|
+
Accept: "application/vnd.github.v3+json"
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
);
|
|
1060
|
+
if (!response || !response.length)
|
|
1061
|
+
break;
|
|
1062
|
+
allContributors.push(...response);
|
|
1063
|
+
hasNextPage = response.length === 100;
|
|
1064
|
+
page++;
|
|
1065
|
+
}
|
|
1066
|
+
return allContributors.filter(
|
|
1067
|
+
(contributor) => contributor.type === "User" && contributor.contributions >= minContributions
|
|
1068
|
+
).map((contributor) => ({
|
|
1069
|
+
sponsor: {
|
|
1070
|
+
type: "User",
|
|
1071
|
+
login: contributor.login,
|
|
1072
|
+
name: contributor.login,
|
|
1073
|
+
avatarUrl: contributor.avatar_url,
|
|
1074
|
+
linkUrl: contributor.url
|
|
1075
|
+
},
|
|
1076
|
+
isOneTime: false,
|
|
1077
|
+
monthlyDollars: contributor.contributions,
|
|
1078
|
+
privacyLevel: "PUBLIC",
|
|
1079
|
+
tierName: "Contributor",
|
|
1080
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1081
|
+
provider: "githubContributors"
|
|
1082
|
+
}));
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
const GitlabContributorsProvider = {
|
|
1086
|
+
name: "gitlabContributors",
|
|
1087
|
+
fetchSponsors(config) {
|
|
1088
|
+
if (!config.gitlabContributors?.repoId)
|
|
1089
|
+
throw new Error("Gitlab repoId is required");
|
|
1090
|
+
return fetchGitlabContributors(
|
|
1091
|
+
config.gitlabContributors?.token || config.token,
|
|
1092
|
+
config.gitlabContributors.repoId,
|
|
1093
|
+
config.gitlabContributors?.minContributions
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
async function fetchGitlabContributors(token, repoId, minContributions = 1) {
|
|
1098
|
+
if (!token)
|
|
1099
|
+
throw new Error("Gitlab token is required");
|
|
1100
|
+
if (!repoId)
|
|
1101
|
+
throw new Error("Gitlab repoId is required");
|
|
1102
|
+
const allContributors = [];
|
|
1103
|
+
let page = 1;
|
|
1104
|
+
let hasNextPage = true;
|
|
1105
|
+
while (hasNextPage) {
|
|
1106
|
+
const response = await $fetch(
|
|
1107
|
+
`https://gitlab.com/api/v4/projects/${repoId}/repository/contributors`,
|
|
1108
|
+
{
|
|
1109
|
+
query: {
|
|
1110
|
+
page: String(page),
|
|
1111
|
+
per_page: "100",
|
|
1112
|
+
sort: "desc"
|
|
1113
|
+
},
|
|
1114
|
+
headers: {
|
|
1115
|
+
"PRIVATE-TOKEN": token,
|
|
1116
|
+
"Content-Type": "application/json"
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
);
|
|
1120
|
+
if (!response || !response.length)
|
|
1121
|
+
break;
|
|
1122
|
+
allContributors.push(...response);
|
|
1123
|
+
hasNextPage = response.length === 100;
|
|
1124
|
+
page++;
|
|
1125
|
+
}
|
|
1126
|
+
const sponsorships = [];
|
|
1127
|
+
for (const contributor of allContributors) {
|
|
1128
|
+
if (contributor.commits < minContributions)
|
|
1129
|
+
continue;
|
|
1130
|
+
try {
|
|
1131
|
+
const userDetails = await $fetch("https://gitlab.com/api/v4/users", {
|
|
1132
|
+
query: {
|
|
1133
|
+
search: contributor.email
|
|
1134
|
+
},
|
|
1135
|
+
headers: {
|
|
1136
|
+
"PRIVATE-TOKEN": token,
|
|
1137
|
+
"Content-Type": "application/json"
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1140
|
+
if (userDetails && userDetails.length > 0) {
|
|
1141
|
+
const user = userDetails[0];
|
|
1142
|
+
sponsorships.push({
|
|
1143
|
+
sponsor: {
|
|
1144
|
+
type: "User",
|
|
1145
|
+
login: user.username,
|
|
1146
|
+
name: user.username,
|
|
1147
|
+
// user.name is also available
|
|
1148
|
+
avatarUrl: user.avatar_url,
|
|
1149
|
+
linkUrl: user.web_url
|
|
1150
|
+
},
|
|
1151
|
+
isOneTime: false,
|
|
1152
|
+
monthlyDollars: contributor.commits,
|
|
1153
|
+
privacyLevel: "PUBLIC",
|
|
1154
|
+
tierName: "Contributor",
|
|
1155
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1156
|
+
provider: "gitlabContributors"
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
console.warn(`Failed to fetch user details for ${contributor.email}:`, error);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
return sponsorships;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
942
1166
|
const LiberapayProvider = {
|
|
943
1167
|
name: "liberapay",
|
|
944
1168
|
fetchSponsors(config) {
|
|
@@ -1409,7 +1633,10 @@ const ProvidersMap = {
|
|
|
1409
1633
|
opencollective: OpenCollectiveProvider,
|
|
1410
1634
|
afdian: AfdianProvider,
|
|
1411
1635
|
polar: PolarProvider,
|
|
1412
|
-
liberapay: LiberapayProvider
|
|
1636
|
+
liberapay: LiberapayProvider,
|
|
1637
|
+
githubContributors: GitHubContributorsProvider,
|
|
1638
|
+
gitlabContributors: GitlabContributorsProvider,
|
|
1639
|
+
crowdinContributors: CrowdinContributorsProvider
|
|
1413
1640
|
};
|
|
1414
1641
|
function guessProviders(config) {
|
|
1415
1642
|
const items = [];
|
|
@@ -1425,6 +1652,12 @@ function guessProviders(config) {
|
|
|
1425
1652
|
items.push("polar");
|
|
1426
1653
|
if (config.liberapay && config.liberapay.login)
|
|
1427
1654
|
items.push("liberapay");
|
|
1655
|
+
if (config.githubContributors?.login && config.githubContributors?.token)
|
|
1656
|
+
items.push("githubContributors");
|
|
1657
|
+
if (config.gitlabContributors?.token && config.gitlabContributors?.repoId)
|
|
1658
|
+
items.push("gitlabContributors");
|
|
1659
|
+
if (config.crowdinContributors?.token && config.crowdinContributors?.projectId)
|
|
1660
|
+
items.push("crowdinContributors");
|
|
1428
1661
|
if (!items.length)
|
|
1429
1662
|
items.push("github");
|
|
1430
1663
|
return items;
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/LizardByte/contribkit.git"
|
|
7
7
|
},
|
|
8
|
-
"version": "2025.
|
|
8
|
+
"version": "2025.327.11019",
|
|
9
9
|
"description": "Toolkit for generating contributor images",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"funding": "https://app.lizardbyte.dev",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"release": "bumpp && pnpm publish"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
+
"@crowdin/crowdin-api-client": "^1.41.2",
|
|
49
50
|
"ansis": "^3.17.0",
|
|
50
51
|
"cac": "^6.7.14",
|
|
51
52
|
"consola": "^3.4.0",
|