avatar: fetch tangled avatar before falling back to bsky & random color #893

open
opened by anirudh.fi targeting master from icy/tolqpt
Changed files
+31 -6
avatar
src
+31 -6
avatar/src/index.js
··· 23 23 } 24 24 25 25 const size = searchParams.get("size"); 26 + const blobUrl = searchParams.get("blob"); // URL to fetch Tangled avatar from PDS 26 27 const resizeToTiny = size === "tiny"; 27 28 28 29 const cache = caches.default; ··· 56 57 message: "avatar request for: " + actor, 57 58 computedSignature: computedSig, 58 59 providedSignature: signatureHex, 60 + hasBlobUrl: !!blobUrl, 59 61 }); 60 62 61 63 const sigBytes = Uint8Array.from( ··· 68 70 } 69 71 70 72 try { 71 - const profileResponse = await fetch( 72 - `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, 73 - ); 74 - const profile = await profileResponse.json(); 75 - const avatar = profile.avatar; 73 + let avatarUrl = null; 74 + 75 + // If blob URL is provided, use it (Tangled profile avatar from user's PDS) 76 + if (blobUrl) { 77 + try { 78 + const decodedBlobUrl = decodeURIComponent(blobUrl); 79 + console.log({ 80 + level: "debug", 81 + message: "fetching Tangled avatar from PDS", 82 + actor: actor, 83 + blobUrl: decodedBlobUrl, 84 + }); 85 + avatarUrl = decodedBlobUrl; 86 + } catch (e) { 87 + console.log({ 88 + level: "warn", 89 + message: "failed to decode blob URL, falling back to Bluesky", 90 + error: e.message, 91 + }); 92 + } 93 + } 76 94 77 - let avatarUrl = profile.avatar; 95 + // If no blob URL or it failed, fall back to Bluesky 96 + if (!avatarUrl) { 97 + const profileResponse = await fetch( 98 + `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, 99 + ); 100 + const profile = await profileResponse.json(); 101 + avatarUrl = profile.avatar; 102 + } 78 103 79 104 if (!avatarUrl) { 80 105 // Generate a random color based on the actor string