74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
/**
|
|
* Previews SoundCloud 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 { genericPreview } from "./generic.ts";
|
|
|
|
/** SoundCloud's own hosts, the short links' `on.` included. */
|
|
const SOUNDCLOUD_HOSTS = new Set([
|
|
"soundcloud.com",
|
|
"www.soundcloud.com",
|
|
"m.soundcloud.com",
|
|
"on.soundcloud.com",
|
|
]);
|
|
|
|
/**
|
|
* Returns the soundcloud.com address of the page, which the embed player
|
|
* takes: its `og:url`, or else the URL it was served from. A short link only
|
|
* redirects, so it is never the answer; tracking parameters are dropped.
|
|
*/
|
|
function pageAddress(ogUrl: string | undefined, finalUrl: string): string {
|
|
for (const raw of [ogUrl, finalUrl]) {
|
|
if (!raw) continue;
|
|
try {
|
|
const url = new URL(raw);
|
|
if (
|
|
!SOUNDCLOUD_HOSTS.has(url.hostname) ||
|
|
url.hostname === "on.soundcloud.com"
|
|
) continue;
|
|
return `https://soundcloud.com${url.pathname}`;
|
|
} catch {
|
|
continue;
|
|
}
|
|
}
|
|
return finalUrl;
|
|
}
|
|
|
|
/**
|
|
* Claims SoundCloud's hosts, short links included, and builds the embed
|
|
* player's URL from the page's address.
|
|
*/
|
|
export const soundcloudProvider: RichContentProvider = {
|
|
name: "soundcloud",
|
|
|
|
matches(url: string): boolean {
|
|
try {
|
|
return SOUNDCLOUD_HOSTS.has(new URL(url).hostname);
|
|
} catch {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
async fetch(url: string): Promise<RichContent> {
|
|
const fetched = await fetchPage(url);
|
|
const page = fetched.html === undefined
|
|
? undefined
|
|
: parsePage(fetched.html, fetched.url);
|
|
const address = pageAddress(page?.meta("og:url"), fetched.url);
|
|
return {
|
|
...(page ? genericPreview(page, url, fetched.url) : { url }),
|
|
type: "soundcloud",
|
|
siteName: "SoundCloud",
|
|
embedUrl: `https://w.soundcloud.com/player/?url=${
|
|
encodeURIComponent(address)
|
|
}&visual=true&auto_play=false`,
|
|
};
|
|
},
|
|
};
|