diff --git a/src/lib/api.ts b/src/lib/api.ts index 0eefe4f..b45d2e7 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -102,13 +102,57 @@ export async function getProfile(actor: string): Promise { try { const agent = getAgent(endpoint) const res = await agent.getProfile({ actor }) + + let avatar = res.data.avatar + let banner = res.data.banner + + // If avatar uses cdn.bsky.app but user's PDS is not bsky, fetch from their PDS + const did = res.data.did + if (avatar && avatar.includes('cdn.bsky.app')) { + try { + const pds = await resolvePds(did) + console.log('[getProfile] PDS resolved:', pds, 'for DID:', did) + // If PDS is not bsky.social/bsky.network, reconstruct avatar URL from blob + if (pds && !pds.includes('bsky.social') && !pds.includes('bsky.network')) { + console.log('[getProfile] Non-bsky PDS detected, fetching profile record...') + const pdsAgent = getAgent(pds) + const profileRecord = await pdsAgent.com.atproto.repo.getRecord({ + repo: did, + collection: 'app.bsky.actor.profile', + rkey: 'self', + }) + console.log('[getProfile] Profile record fetched:', profileRecord.data) + const avatarBlob = (profileRecord.data.value as any)?.avatar + if (avatarBlob?.ref) { + // ref can be either { $link: "..." } or a CID object with toString() + const cid = avatarBlob.ref.$link || avatarBlob.ref.toString?.() + console.log('[getProfile] Avatar CID:', cid) + if (cid) { + avatar = `${pds}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}` + console.log('[getProfile] Avatar URL constructed:', avatar) + } + } + const bannerBlob = (profileRecord.data.value as any)?.banner + if (bannerBlob?.ref) { + const cid = bannerBlob.ref.$link || bannerBlob.ref.toString?.() + if (cid) { + banner = `${pds}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}` + } + } + } + } catch (err) { + console.error('[getProfile] Error fetching blob URL:', err) + // Keep original avatar if blob fetch fails + } + } + return { did: res.data.did, handle: res.data.handle, displayName: res.data.displayName, description: res.data.description, - avatar: res.data.avatar, - banner: res.data.banner, + avatar, + banner, } } catch { continue