39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
const timeZone = 'America/New_York';
|
|
|
|
interface HeatmapEntry {
|
|
timestamp: number;
|
|
contributions: number;
|
|
}
|
|
|
|
export interface GiteaProfile {
|
|
baseUrl: string;
|
|
username: string;
|
|
profileUrl: string;
|
|
}
|
|
|
|
export function parseGiteaProfile(profileUrl: string | undefined): GiteaProfile | null {
|
|
if (!profileUrl) return null;
|
|
const url = new URL(profileUrl);
|
|
const username = url.pathname.split('/').filter(Boolean)[0];
|
|
return username ? { baseUrl: url.origin, username, profileUrl } : null;
|
|
}
|
|
|
|
function easternDate(timestampSeconds: number): string {
|
|
return new Intl.DateTimeFormat('en-CA', { timeZone, year: 'numeric', month: '2-digit', day: '2-digit' }).format(
|
|
new Date(timestampSeconds * 1000)
|
|
);
|
|
}
|
|
|
|
export async function fetchGiteaDailyCounts({ baseUrl, username }: GiteaProfile): Promise<Map<string, number>> {
|
|
const response = await fetch(`${baseUrl}/api/v1/users/${username}/heatmap`, { headers: { Accept: 'application/json' } });
|
|
if (!response.ok) throw new Error(`Gitea heatmap returned ${response.status}`);
|
|
|
|
const entries: HeatmapEntry[] = await response.json();
|
|
const dailyCounts = new Map<string, number>();
|
|
for (const { timestamp, contributions } of entries) {
|
|
const date = easternDate(timestamp);
|
|
dailyCounts.set(date, (dailyCounts.get(date) ?? 0) + contributions);
|
|
}
|
|
return dailyCounts;
|
|
}
|