|
| 1 | +import type { Credentials, ReportsModel } from '@crowdin/crowdin-api-client' |
| 2 | +import type { Provider, Sponsorship } from '../types' |
| 3 | +import { ProjectsGroups, Reports } from '@crowdin/crowdin-api-client' |
| 4 | + |
| 5 | +interface Member { |
| 6 | + id: number |
| 7 | + username: string |
| 8 | + fullName: string |
| 9 | + avatarUrl: string |
| 10 | + joinedAt: string |
| 11 | +} |
| 12 | + |
| 13 | +export const CrowdinContributorsProvider: Provider = { |
| 14 | + name: 'crowdinContributors', |
| 15 | + fetchSponsors(config) { |
| 16 | + return fetchCrowdinContributors( |
| 17 | + config.crowdinContributors?.token || config.token!, |
| 18 | + config.crowdinContributors?.projectId || 0, |
| 19 | + config.crowdinContributors?.minTranslations || 1, |
| 20 | + ) |
| 21 | + }, |
| 22 | +} |
| 23 | + |
| 24 | +export async function fetchCrowdinContributors( |
| 25 | + token: string, |
| 26 | + projectId: number, |
| 27 | + minTranslations = 1, |
| 28 | +): Promise<Sponsorship[]> { |
| 29 | + if (!token) |
| 30 | + throw new Error('Crowdin token is required') |
| 31 | + if (!projectId) |
| 32 | + throw new Error('Crowdin project ID is required') |
| 33 | + |
| 34 | + const credentials: Credentials = { |
| 35 | + token, |
| 36 | + } |
| 37 | + |
| 38 | + // get the project |
| 39 | + const projectsGroups: ProjectsGroups = new ProjectsGroups(credentials) |
| 40 | + const project = await projectsGroups.getProject(projectId) |
| 41 | + |
| 42 | + // get top members report |
| 43 | + const reports: Reports = new Reports(credentials) |
| 44 | + |
| 45 | + // today's date in ISO 8601 format |
| 46 | + const dateTo = new Date().toISOString() |
| 47 | + const dateFrom = project.data.createdAt |
| 48 | + |
| 49 | + const createReportRequestBody: ReportsModel.GenerateReportRequest = { |
| 50 | + name: 'top-members', |
| 51 | + schema: { |
| 52 | + unit: 'words', |
| 53 | + format: 'json', |
| 54 | + dateFrom, |
| 55 | + dateTo, |
| 56 | + }, |
| 57 | + } |
| 58 | + |
| 59 | + const createReport = await reports.generateReport(projectId, createReportRequestBody) |
| 60 | + |
| 61 | + // get the report |
| 62 | + // sleep for 5 seconds |
| 63 | + await new Promise(resolve => setTimeout(resolve, 5000)) |
| 64 | + const report = await reports.downloadReport(projectId, createReport.data.identifier) |
| 65 | + |
| 66 | + // build contributors object from looping over the report data |
| 67 | + const reportRaw = await fetch(report.data.url) |
| 68 | + const reportData = await reportRaw.json() as { data: { user: Member, translated: number }[] } |
| 69 | + |
| 70 | + const contributors = reportData.data |
| 71 | + .filter((entry: { user: Member, translated: number }) => entry.translated > minTranslations) |
| 72 | + .map((entry: { user: Member, translated: number }) => ({ |
| 73 | + member: entry.user, |
| 74 | + translations: entry.translated, |
| 75 | + })) |
| 76 | + |
| 77 | + return contributors |
| 78 | + .filter(Boolean) |
| 79 | + .map(({ member, translations }: { member: Member, translations: number }) => ({ |
| 80 | + sponsor: { |
| 81 | + type: 'User', |
| 82 | + login: member.username, |
| 83 | + name: member.username, // fullName is also available |
| 84 | + avatarUrl: member.avatarUrl, |
| 85 | + linkUrl: `https://crowdin.com/profile/${member.username}`, |
| 86 | + }, |
| 87 | + isOneTime: false, |
| 88 | + monthlyDollars: translations, |
| 89 | + privacyLevel: 'PUBLIC', |
| 90 | + tierName: 'Translator', |
| 91 | + createdAt: member.joinedAt, |
| 92 | + provider: 'crowdinContributors', |
| 93 | + })) |
| 94 | +} |
0 commit comments