Resolve your Bluesky avatar with a human URL silhouette.town
atproto deno

serve help text at root route

graham.systems c5db16b6 0ee8a6e8

verified
+33
+33
main.ts
··· 4 4 import { isActorIdentifier } from "@atcute/lexicons/syntax"; 5 5 import { AppBskyActorProfile } from "@atcute/bluesky"; 6 6 7 + const ROOT = new URLPattern({ pathname: "/" }); 7 8 const IDENTIFIER_ROUTE = new URLPattern({ pathname: "/avatar/:identifier" }); 8 9 const slingshot = new Client({ 9 10 handler: simpleFetchHandler({ service: "https://slingshot.microcosm.blue" }), 10 11 }); 11 12 13 + function generateSpiel(origin: string) { 14 + return `<h1> 15 + silhouette 16 + </h1> 17 + 18 + <p> 19 + Quickly get the URL to your Bluesky profile photo using an identifier (handle or DID). Go to: 20 + </p> 21 + 22 + <p> 23 + <code>${origin}/avatar/&lt;your-identifier&gt;</code> 24 + </p> 25 + 26 + <p> 27 + For example: 28 + <a href="${origin}/avatar/graham.systems"> 29 + ${origin}/avatar/graham.systems 30 + </a> 31 + </p>`; 32 + } 33 + 12 34 // Algorithm: 13 35 // 1. Resolve minidoc from identifier in URL 14 36 // 2. Resolve Bluesky actor profile from PDS 15 37 // 3. Return 303 with profile picture blob URL 16 38 17 39 export async function handler(req: Request): Promise<Response> { 40 + if (ROOT.exec(req.url)) { 41 + const url = new URL(req.url); 42 + return new Response(generateSpiel(url.origin), { 43 + status: STATUS_CODE.OK, 44 + statusText: STATUS_TEXT[STATUS_CODE.OK], 45 + headers: { 46 + "Content-Type": "text/html", 47 + }, 48 + }); 49 + } 50 + 18 51 const match = IDENTIFIER_ROUTE.exec(req.url); 19 52 20 53 if (!match) {