import { NextResponse } from "next/server"; import { boardConfig } from "../../../board.config"; type GithubContent = { name: string; path: string; type: "file" | "dir"; download_url: string | null; html_url: string; }; type ShamePhoto = { name: string; path: string; url: string; htmlUrl: string; }; const imageExtensionPattern = /\.(avif|gif|jpe?g|png|webp)$/i; function parseRepo(value: string | null) { const clean = value?.trim().replace(/^https:\/\/github\.com\//, "") ?? ""; const [owner, repo] = clean.split("/"); if (!owner || !repo) { return null; } return { owner, repo: repo.replace(/\.git$/, "") }; } async function fetchDirectory(owner: string, repo: string, path: string, branch?: string) { const encodedPath = path .split("/") .filter(Boolean) .map((part) => encodeURIComponent(part)) .join("/"); const url = new URL(`https://api.github.com/repos/${owner}/${repo}/contents/${encodedPath}`); if (branch) { url.searchParams.set("ref", branch); } const response = await fetch(url, { headers: { Accept: "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28" }, next: { revalidate: 60 } }); if (!response.ok) { return { ok: false as const, status: response.status, message: response.status === 404 ? "Repository or folder was not found." : "GitHub did not return the photo list." }; } const content = (await response.json()) as GithubContent[] | GithubContent; const items = Array.isArray(content) ? content : [content]; return { ok: true as const, items }; } export async function GET() { const branch = boardConfig.branch || undefined; const path = boardConfig.photosPath; const parsedRepo = parseRepo(boardConfig.repo); if (!parsedRepo) { return NextResponse.json({ photos: [], repo: null, path, message: "Set a GitHub repository to load the board." }); } const directory = await fetchDirectory(parsedRepo.owner, parsedRepo.repo, path, branch); if (!directory.ok) { return NextResponse.json( { photos: [], repo: `${parsedRepo.owner}/${parsedRepo.repo}`, path, message: directory.message }, { status: directory.status } ); } const photos: ShamePhoto[] = directory.items .filter((item) => item.type === "file" && item.download_url && imageExtensionPattern.test(item.name)) .map((item) => ({ name: item.name.replace(imageExtensionPattern, ""), path: item.path, url: item.download_url as string, htmlUrl: item.html_url })); return NextResponse.json({ photos, repo: `${parsedRepo.owner}/${parsedRepo.repo}`, path, branch: branch ?? null, message: photos.length ? null : "No image files were found in that GitHub folder." }); }