a tool for shared writing and social publishing

handle failed image transforms in icon

+46 -42
+46 -42
app/lish/[did]/[publication]/icon.ts
··· 19 19 }: { 20 20 params: { did: string; publication: string }; 21 21 }) { 22 - let did = decodeURIComponent(params.did); 23 - let uri; 24 - if (/^(?!\.$|\.\.S)[A-Za-z0-9._:~-]{1,512}$/.test(params.publication)) { 25 - uri = AtUri.make( 26 - did, 27 - "pub.leaflet.publication", 28 - params.publication, 29 - ).toString(); 30 - } 31 - let { data: publication } = await supabaseServerClient 32 - .from("publications") 33 - .select( 34 - `*, 35 - publication_subscriptions(*), 36 - documents_in_publications(documents(*)) 37 - `, 38 - ) 39 - .eq("identity_did", did) 40 - .or(`name.eq."${params.publication}", uri.eq."${uri}"`) 41 - .single(); 22 + try { 23 + let did = decodeURIComponent(params.did); 24 + let uri; 25 + if (/^(?!\.$|\.\.S)[A-Za-z0-9._:~-]{1,512}$/.test(params.publication)) { 26 + uri = AtUri.make( 27 + did, 28 + "pub.leaflet.publication", 29 + params.publication, 30 + ).toString(); 31 + } 32 + let { data: publication } = await supabaseServerClient 33 + .from("publications") 34 + .select( 35 + `*, 36 + publication_subscriptions(*), 37 + documents_in_publications(documents(*)) 38 + `, 39 + ) 40 + .eq("identity_did", did) 41 + .or(`name.eq."${params.publication}", uri.eq."${uri}"`) 42 + .single(); 42 43 43 - let record = publication?.record as PubLeafletPublication.Record | null; 44 - if (!record?.icon) return redirect("/icon.png"); 44 + let record = publication?.record as PubLeafletPublication.Record | null; 45 + if (!record?.icon) return redirect("/icon.png"); 45 46 46 - let identity = await idResolver.did.resolve(did); 47 - let service = identity?.service?.find((f) => f.id === "#atproto_pds"); 48 - console.log(identity); 49 - if (!service) return null; 50 - let cid = (record.icon.ref as unknown as { $link: string })["$link"]; 51 - const response = await fetch( 52 - `${service.serviceEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`, 53 - ); 54 - let blob = await response.blob(); 55 - let resizedImage = await sharp(await blob.arrayBuffer()) 56 - .resize({ width: 32, height: 32 }) 57 - .toBuffer(); 58 - console.log("fetched favicon!"); 59 - return new Response(new Uint8Array(resizedImage), { 60 - headers: { 61 - "Content-Type": "image/png", 62 - "CDN-Cache-Control": "s-maxage=86400, stale-while-revalidate=86400", 63 - "Cache-Control": "public, max-age=3600", 64 - }, 65 - }); 47 + let identity = await idResolver.did.resolve(did); 48 + let service = identity?.service?.find((f) => f.id === "#atproto_pds"); 49 + console.log(identity); 50 + if (!service) return null; 51 + let cid = (record.icon.ref as unknown as { $link: string })["$link"]; 52 + const response = await fetch( 53 + `${service.serviceEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`, 54 + ); 55 + let blob = await response.blob(); 56 + let resizedImage = await sharp(await blob.arrayBuffer()) 57 + .resize({ width: 32, height: 32 }) 58 + .toBuffer(); 59 + console.log("fetched favicon!"); 60 + return new Response(new Uint8Array(resizedImage), { 61 + headers: { 62 + "Content-Type": "image/png", 63 + "CDN-Cache-Control": "s-maxage=86400, stale-while-revalidate=86400", 64 + "Cache-Control": "public, max-age=3600", 65 + }, 66 + }); 67 + } catch (e) { 68 + return redirect("/icon.png"); 69 + } 66 70 }