Compare commits

...

2 commits

5 changed files with 24 additions and 55 deletions

4
.prettierrc Normal file
View file

@ -0,0 +1,4 @@
{
"printWidth": 96,
"arrowParens": "avoid"
}

View file

@ -20,19 +20,12 @@ CREATE TABLE IF NOT EXISTS videos (
`);
const selectAllowlist = conn.prepare("SELECT 1 FROM allowlist WHERE repo = ?");
const selectVideo = conn.prepare(
"SELECT filename FROM videos WHERE repo = ? AND cid = ?"
);
const insertVideo = conn.prepare(
"INSERT INTO videos (repo, cid, filename) VALUES (?, ?, ?)"
);
const selectVideo = conn.prepare("SELECT filename FROM videos WHERE repo = ? AND cid = ?");
const insertVideo = conn.prepare("INSERT INTO videos (repo, cid, filename) VALUES (?, ?, ?)");
export const db = {
db: conn,
inAllowlist: (did: string) =>
(selectAllowlist.value<[boolean]>(did)?.[0] && true) ?? false,
getVideo: (did: string, cid: string) =>
selectVideo.value<[string]>(did, cid)?.[0],
addVideo: (did: string, cid: string, filename: string) =>
insertVideo.run(did, cid, filename),
inAllowlist: (did: string) => (selectAllowlist.value<[boolean]>(did)?.[0] && true) ?? false,
getVideo: (did: string, cid: string) => selectVideo.value<[string]>(did, cid)?.[0],
addVideo: (did: string, cid: string, filename: string) => insertVideo.run(did, cid, filename),
};

View file

@ -4,20 +4,9 @@ import { serveDir, serveFile } from "@std/http/file-server";
import * as z from "@zod/mini";
import { db } from "./db.ts";
import {
CompositeDidDocumentResolver,
PlcDidDocumentResolver,
WebDidDocumentResolver,
} from "@atcute/identity-resolver";
import { resolveDid } from "../common/identity.ts";
import { VIDEO_PATTERN } from "../common/routes.ts";
const didResolver = new CompositeDidDocumentResolver({
methods: {
plc: new PlcDidDocumentResolver(),
web: new WebDidDocumentResolver(),
},
});
async function fetchVideo(req: Request): Promise<Response> {
if (req.method === "OPTIONS") {
return new Response(null, {
@ -59,18 +48,13 @@ async function fetchVideo(req: Request): Promise<Response> {
"content-type": "application/json",
"access-control-allow-origin": "*",
},
}
},
);
}
const doc = await didResolver.resolve(
body.repo as `did:${"plc" | "web"}:${string}`
);
const pdsBaseURL = doc.service?.find(
(it) => it.id === "#atproto_pds"
)?.serviceEndpoint;
if (!pdsBaseURL || typeof pdsBaseURL !== "string")
return new Response(null, { status: 400 });
const doc = await resolveDid(body.repo);
const pdsBaseURL = doc.service?.find(it => it.id === "#atproto_pds")?.serviceEndpoint;
if (!pdsBaseURL || typeof pdsBaseURL !== "string") return new Response(null, { status: 400 });
let filename: string = crypto.randomUUID();

View file

@ -9,13 +9,11 @@ import { XRPC } from "@char/lexicon.ts/rpc";
type VideoRecord = Infer<VideoLexiconUniverse, "blue.cerulea.video.video">;
const fetchVideoRecord = async (
did: string,
rkey: string
): Promise<VideoRecord> => {
const fetchVideoRecord = async (did: string, rkey: string): Promise<VideoRecord> => {
const didDoc = await resolveDid(did);
const pds = didDoc.service?.find((it) => it.id === "#atproto_pds")
?.serviceEndpoint as string | undefined;
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");
@ -32,10 +30,7 @@ const fetchVideoRecord = async (
return record.value as VideoRecord;
};
const resolveVideoURL = async (
repo: `did:${string}`,
blob: string
): Promise<string> => {
const resolveVideoURL = async (repo: `did:${string}`, blob: string): Promise<string> => {
try {
const xrpc = new XRPC<VideoLexiconUniverse>(globalThis.location.href);
const res = await xrpc.call("blue.cerulea.video.fetchVideo", {
@ -63,7 +58,7 @@ const main = async () => {
const record = await fetchVideoRecord(did, rkey);
const videoURL = await resolveVideoURL(
did,
"ref" in record.video ? record.video.ref.$link : record.video.cid
"ref" in record.video ? record.video.ref.$link : record.video.cid,
);
const video = (
<video crossOrigin="anonymous" controls>
@ -78,8 +73,7 @@ const main = async () => {
player.append(<h1>{record.title}</h1>);
document.title = `${record.title} | video.cerulea.blue`;
}
if (record.description)
player.append(<p className="description">{record.description}</p>);
if (record.description) player.append(<p className="description">{record.description}</p>);
};
main();

View file

@ -1,5 +1,4 @@
import type { DidDocument } from "@atcute/identity";
import type { WebDidDocumentResolver } from "@atcute/identity-resolver";
import type { ATProtoUniverse } from "@char/lexicon.ts/atproto";
import { XRPC } from "@char/lexicon.ts/rpc";
@ -14,17 +13,12 @@ export async function resolveHandle(handle: string): Promise<`did:${string}`> {
export async function resolveDid(did: string): Promise<DidDocument> {
if (did.startsWith("did:plc:")) {
const doc = await fetch("https://plc.directory/" + did).then((r) =>
r.json()
);
const doc = await fetch("https://plc.directory/" + did).then(r => r.json());
return doc;
} else if (did.startsWith("did:web:")) {
// TODO: write our own did:web resolver (maybe use a CORS proxy on clientside)
const resolver: WebDidDocumentResolver = await import(
"@atcute/identity-resolver"
)
.then((m) => m.WebDidDocumentResolver)
.then((r) => new r());
const { WebDidDocumentResolver } = await import("@atcute/identity-resolver");
const resolver = new WebDidDocumentResolver();
return resolver.resolve(did as `did:web:${string}`);
}