65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
/**
|
|
* Previews Bandcamp links from their page, for `rich-content-service.ts`.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
import type { RichContent } from "../../../shared/dump.ts";
|
|
import type { RichContentProvider } from "./provider.ts";
|
|
import { parsePage } from "../html.ts";
|
|
import { fetchPage } from "../fetch.ts";
|
|
import { BANDCAMP_HOST_RE } from "../bandcamp-tralbum.ts";
|
|
import { genericPreview } from "./generic.ts";
|
|
|
|
/**
|
|
* Returns the embed player's URL a page's `og:video` names, over https; only
|
|
* a player on bandcamp.com counts, since the frontend frames it.
|
|
*/
|
|
function embeddedPlayerUrl(raw: string | undefined): string | undefined {
|
|
if (!raw) return undefined;
|
|
try {
|
|
const url = new URL(raw);
|
|
if (
|
|
(url.protocol !== "https:" && url.protocol !== "http:") ||
|
|
url.hostname !== "bandcamp.com" ||
|
|
!url.pathname.startsWith("/EmbeddedPlayer/")
|
|
) return undefined;
|
|
url.protocol = "https:";
|
|
return url.href;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Claims bandcamp.com and its subdomains, where artists have their pages, and
|
|
* 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/remote/bandcamp`.
|
|
*/
|
|
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<RichContent> {
|
|
const fetched = await fetchPage(url);
|
|
if (fetched.html === undefined) {
|
|
return { type: "bandcamp", siteName: "Bandcamp", url };
|
|
}
|
|
const page = parsePage(fetched.html, fetched.url);
|
|
return {
|
|
...genericPreview(page, url, fetched.url),
|
|
type: "bandcamp",
|
|
siteName: "Bandcamp",
|
|
embedUrl: embeddedPlayerUrl(page.meta("og:video")),
|
|
};
|
|
},
|
|
};
|