From 4e728d1134a8f987a9bec3417205f92b6fdc47b2 Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Fri, 12 Dec 2025 11:28:28 +0200 Subject: [PATCH] avatar: fetch tangled avatar before falling back to bsky & random color Change-Id: tsoxpkopqrvomxkloswmsqzxowlvvulr Signed-off-by: Anirudh Oppiliappan --- avatar/src/index.js | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/avatar/src/index.js b/avatar/src/index.js index 23a7e00f..f09a5bb0 100644 --- a/avatar/src/index.js +++ b/avatar/src/index.js @@ -23,6 +23,7 @@ You can't use this directly unfortunately since all requests are signed and may } const size = searchParams.get("size"); + const blobUrl = searchParams.get("blob"); // URL to fetch Tangled avatar from PDS const resizeToTiny = size === "tiny"; const cache = caches.default; @@ -56,6 +57,7 @@ You can't use this directly unfortunately since all requests are signed and may message: "avatar request for: " + actor, computedSignature: computedSig, providedSignature: signatureHex, + hasBlobUrl: !!blobUrl, }); const sigBytes = Uint8Array.from( @@ -68,13 +70,36 @@ You can't use this directly unfortunately since all requests are signed and may } try { - const profileResponse = await fetch( - `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, - ); - const profile = await profileResponse.json(); - const avatar = profile.avatar; + let avatarUrl = null; + + // If blob URL is provided, use it (Tangled profile avatar from user's PDS) + if (blobUrl) { + try { + const decodedBlobUrl = decodeURIComponent(blobUrl); + console.log({ + level: "debug", + message: "fetching Tangled avatar from PDS", + actor: actor, + blobUrl: decodedBlobUrl, + }); + avatarUrl = decodedBlobUrl; + } catch (e) { + console.log({ + level: "warn", + message: "failed to decode blob URL, falling back to Bluesky", + error: e.message, + }); + } + } - let avatarUrl = profile.avatar; + // If no blob URL or it failed, fall back to Bluesky + if (!avatarUrl) { + const profileResponse = await fetch( + `https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=${actor}`, + ); + const profile = await profileResponse.json(); + avatarUrl = profile.avatar; + } if (!avatarUrl) { // Generate a random color based on the actor string -- 2.43.0