import { STATUS_CODE, STATUS_TEXT } from "@std/http"; import { Client, simpleFetchHandler } from "@atcute/client"; import { is } from "@atcute/lexicons"; import { isActorIdentifier } from "@atcute/lexicons/syntax"; import { AppBskyActorProfile } from "@atcute/bluesky"; const ROOT = new URLPattern({ pathname: "/" }); const IDENTIFIER_ROUTE = new URLPattern({ pathname: "/avatar/:identifier" }); const slingshot = new Client({ handler: simpleFetchHandler({ service: "https://slingshot.microcosm.blue" }), }); function generateSpiel(origin: string) { return `

silhouette

Quickly get the URL to your Bluesky profile photo using an identifier (handle or DID). Go to:

${origin}/avatar/<your-identifier>

For example: ${origin}/avatar/graham.systems

`; } // Algorithm: // 1. Resolve minidoc from identifier in URL // 2. Resolve Bluesky actor profile from PDS // 3. Return 303 with profile picture blob URL export async function handler(req: Request): Promise { if (ROOT.exec(req.url)) { const url = new URL(req.url); return new Response(generateSpiel(url.origin), { status: STATUS_CODE.OK, statusText: STATUS_TEXT[STATUS_CODE.OK], headers: { "Content-Type": "text/html", }, }); } const match = IDENTIFIER_ROUTE.exec(req.url); if (!match) { return new Response(null, { status: STATUS_CODE.NotFound, statusText: STATUS_TEXT[STATUS_CODE.NotFound], }); } else if (req.method !== "GET") { return new Response(null, { status: STATUS_CODE.MethodNotAllowed, statusText: STATUS_TEXT[STATUS_CODE.MethodNotAllowed], }); } const identifier = match.pathname.groups.identifier; if (!isActorIdentifier(identifier)) { return Response.json({ identifier, message: `invalid identifier ${identifier}`, }, { status: STATUS_CODE.BadRequest, statusText: STATUS_TEXT[STATUS_CODE.BadRequest], }); } const minidoc = await slingshot.get( "com.bad-example.identity.resolveMiniDoc", { params: { identifier, }, }, ); if (!minidoc.ok) { return Response.json({ identifier, message: `failed to resolve identifier ${identifier}`, }, { status: STATUS_CODE.InternalServerError, statusText: STATUS_TEXT[STATUS_CODE.InternalServerError], }); } else if (minidoc.status > 400) { return Response.json({ identifier, message: `error from Slingshot`, error: minidoc.data, }, { status: STATUS_CODE.InternalServerError, statusText: STATUS_TEXT[STATUS_CODE.InternalServerError], }); } const pds = new Client({ handler: simpleFetchHandler({ service: minidoc.data.pds }), }); const record = await pds.get("com.atproto.repo.getRecord", { params: { collection: "app.bsky.actor.profile", rkey: "self", repo: minidoc.data.did, }, }); if (!record.ok || record.status > 400) { return Response.json({ identifier, pds: minidoc.data.pds, message: `failed to resolve app.bsky.actor.profile for ${identifier}`, }, { status: record.status || STATUS_CODE.InternalServerError, statusText: STATUS_TEXT[ STATUS_CODE.InternalServerError ], }); } const profile = record.data.value; if (!is(AppBskyActorProfile.mainSchema, profile)) { return Response.json({ identifier, pds: minidoc.data.pds, message: `profile record does not match app.bsky.actor.profile`, profile, }, { status: STATUS_CODE.PreconditionFailed, statusText: STATUS_TEXT[STATUS_CODE.PreconditionFailed], }); } else if (!profile.avatar) { return Response.json({ identifier, pds: minidoc.data.pds, message: "profile has no avatar", }, { status: STATUS_CODE.NotFound, statusText: STATUS_TEXT[STATUS_CODE.NotFound], }); } const blobUrl = new URL("/xrpc/com.atproto.sync.getBlob", minidoc.data.pds); const cid = "ref" in profile.avatar ? profile.avatar.ref.$link : profile.avatar.cid; blobUrl.searchParams.set("did", minidoc.data.did); blobUrl.searchParams.set("cid", cid); return Response.redirect(blobUrl, STATUS_CODE.SeeOther); } if (import.meta.main) { Deno.serve(handler); }