···8 ShTangledActorProfile,
9 shTangledActorProfileSchema,
10} from "@/lib/types/lexicons/sh/tangled/actor/profile";
01112+/**
13+ * Gets the avatar of the specified DID from their repository. Specifically, queries for sh.tangled.actor.profile self records first, then as a fallback, queries for app.bsky.actor.profile.
14+ * If both return invalid avatar blob URLs, then it returns "#" as a fallback.
15+ * You should **NOT** use '#' as the value to an <img> element's `src` attribute. Instead, call the function early then set some other fallback in the component return.
16+ * @param {Object} params - The supplied params object.
17+ * @param {string} params.did - The DID you want to fetch. This should be a "did:plc:..." or a "did:web:...". This is NOT checked at runtime.
18+ * @param {URL} params.repoUrl - The URL of the DID's home repository (PDS). Omit any trailing slashes. This is automatically trimmed at runtime.
19+ */
20export const getAvatar = async ({
21 did,
22 repoUrl,
···4546 return `${cleanedUrl}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${avatarCid}`;
47 }
48+49+ const bskyAvatarResult = await getBskyAvatar({
50+ did,
51+ repoUrl: cleanedUrl,
52+ });
53+54+ if (bskyAvatarResult.ok) {
55+ const { avatar } = bskyAvatarResult.data;
56+ if (!avatar) {
57+ throw new Error(
58+ "In `getAvatar`, the resulting Bluesky profile object did not contain an Avatar field, even though it passed validation for an explicit avatar field within `getBlueskyAvatar`. This should not happen.",
59+ );
60+ }
61+ const { ref } = avatar;
62+ const avatarCid = ref.$link;
63+64+ return `${cleanedUrl}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${avatarCid}`;
65+ }
66+67+ // at this point, both the tangled profile lookup and the bluesky profile lookup have failed. So, we will return '#'.
68+69+ return "#";
70};
7172const getTangledAvatar = async ({