import { resolveDid, resolveHandle } from "../common/identity.ts"; import { VIDEO_PATTERN } from "../common/routes.ts"; type BlobRef = { $type: "blob"; ref: { $link: string }; mimeType?: string; size?: number; }; type VideoRecord = { video: BlobRef; title?: string; description?: string }; const fetchVideoRecord = async ( did: string, rkey: string ): Promise => { // TODO: we do lots of casting here that we shouldn't need once we have lexicon.ts validations const didDoc = await resolveDid(did); const pds = didDoc.service?.find((it) => it.id === "#atproto_pds") ?.serviceEndpoint as string | undefined; if (!pds) throw new Error("could not resolve pds for requested repo"); const getRecordURL = new URL("/xrpc/com.atproto.repo.getRecord", pds); getRecordURL.searchParams.set("collection", "blue.cerulea.video.video"); getRecordURL.searchParams.set("repo", did); getRecordURL.searchParams.set("rkey", rkey); const recordResponse = await fetch(getRecordURL); if (recordResponse.status !== 200) throw new Error("got error fetching record"); const record = (await recordResponse.json()).value as VideoRecord; return record; }; const resolveVideoURL = async (did: string, blob: string): Promise => { const res = await fetch("/xrpc/blue.cerulea.video.fetchVideo", { method: "POST", headers: { "content-encoding": "application/json" }, body: JSON.stringify({ repo: did, blob }), }).then((r) => r.json()); return `/user-content/${res.filename}`; }; const main = async () => { const player = document.querySelector("#player")! as HTMLElement; const location = VIDEO_PATTERN.exec(globalThis.location.href); if (!location) throw new Error("video pattern did not match url"); const { repo, rkey } = location.pathname.groups as { repo: string; rkey: string; }; const did = repo.startsWith("did:") ? repo : await resolveHandle(repo); const video = await fetchVideoRecord(did, rkey); const videoURL = await resolveVideoURL(did, video.video.ref.$link); player.append( ); if (video.title) { player.append(

{video.title}

); document.title = `${video.title} | video.cerulea.blue`; } if (video.description) player.append(

{video.description}

); }; main();