/** * Previews links to this site's own dump, user and playlist pages, as * `parsePagePath` reads them, from the database, for * `rich-content-service.ts`. No request goes out, so this works even when the * site runs on a private host that `fetchWithTimeout` refuses. * * @module */ import type { RichContent } from "../../../shared/dump.ts"; import type { RichContentProvider } from "./provider.ts"; import { getDumpByPath } from "../../services/dump-service.ts"; import { resolveUsername } from "../../services/user-service.ts"; import { getPlaylistByPath } from "../../services/playlist-service.ts"; import { APIException } from "../../lib/api-exception.ts"; import { PUBLIC_URL, THEME_COLOR } from "../../config.ts"; import { isSelfUrl } from "../../lib/self-url.ts"; import { parsePagePath } from "../../../shared/paths.ts"; /** * Gives a link to this site without a thumbnail a placeholder in the site's * icon and color. */ const SELF_BRANDING = { siteName: "gerbeur", faviconUrl: `${PUBLIC_URL}/apple-touch-icon.png`, accentColor: THEME_COLOR, } as const; /** * Comes before the generic provider, and claims what `isSelfUrl` accepts. A * profile's tab previews as the profile. Its `fetch` rejects with a 404 * `APIException` for a missing page, a private dump or a private playlist: * the preview is stored in the linking dump, which others may see. */ export const selfProvider: RichContentProvider = { name: "self", matches(url: string): boolean { try { return isSelfUrl(new URL(url)); } catch { return false; } }, fetch(url: string): Promise { // matches() let only these paths through. const page = parsePagePath(new URL(url).pathname)!; const user = resolveUsername(page.username); if (page.kind === "dump") { const dump = getDumpByPath(user.id, page.slug); let thumbnailUrl: string | undefined; if (dump.kind === "file" && dump.fileMime?.startsWith("image/")) { thumbnailUrl = `${PUBLIC_URL}/api/dumps/${dump.id}/file`; } else if (dump.richContent?.thumbnailUrl) { thumbnailUrl = dump.richContent.thumbnailUrl; } return Promise.resolve({ type: "generic", url, ...SELF_BRANDING, title: dump.title, description: dump.comment, thumbnailUrl, }); } if (page.kind === "playlist") { const playlist = getPlaylistByPath(user.id, page.slug); if (!playlist.isPublic) { throw new APIException(404, "Playlist not found"); } const thumbnailUrl = playlist.imageMime ? `${PUBLIC_URL}/api/playlists/${playlist.id}/cover` : undefined; return Promise.resolve({ type: "generic", url, ...SELF_BRANDING, title: playlist.title, description: playlist.description, thumbnailUrl, }); } const thumbnailUrl = user.avatarMime ? `${PUBLIC_URL}/api/users/${user.id}/avatar` : undefined; return Promise.resolve({ type: "generic", url, ...SELF_BRANDING, title: user.username, description: user.description, thumbnailUrl, }); }, };