/** * Previews Bandcamp links from their page's OG tags, for * `rich-content-service.ts`. * * @module */ import type { RichContent } from "../../../shared/dump.ts"; import type { RichContentProvider } from "./provider.ts"; import { extractOgTag } from "../html.ts"; import { fetchWithTimeout, readTextCapped } from "../fetch.ts"; import { BANDCAMP_HOST_RE } from "../bandcamp-tralbum.ts"; /** * Claims bandcamp.com and its subdomains, where artists have their pages. Takes * the embed player's URL from the page's `og:video`. The native player fetches the page's streams * itself at play time, through `GET /api/bandcamp/tracks`. */ export const bandcampProvider: RichContentProvider = { name: "bandcamp", matches(url: string): boolean { try { return BANDCAMP_HOST_RE.test(new URL(url).hostname); } catch { return false; } }, async fetch(url: string): Promise { const res = await fetchWithTimeout(url); const contentType = res.headers.get("content-type") ?? ""; if (!contentType.startsWith("text/html")) { await res.body?.cancel(); return { type: "bandcamp", siteName: "Bandcamp", url }; } const html = await readTextCapped(res); return { type: "bandcamp", siteName: "Bandcamp", url, title: extractOgTag(html, "title"), description: extractOgTag(html, "description"), thumbnailUrl: extractOgTag(html, "image"), embedUrl: extractOgTag(html, "video") ?? undefined, }; }, };