/// const API_URL = Deno.env.get("API_URL"); const SLICE_URI = Deno.env.get("VITE_SLICE_URI"); interface TokenInfo { accessToken: string; tokenType: string; } /** * Initialize user profile by: * 1. Checking if profile already exists * 2. Syncing user collections (Bluesky data) * 3. Fetching Bluesky profile * 4. Creating network.slices.actor.profile with Bluesky data */ export async function initializeUserProfile( userDid: string, userHandle: string, tokens: TokenInfo, ): Promise { if (!API_URL || !SLICE_URI) { console.error("Missing API_URL or VITE_SLICE_URI environment variables"); return; } try { const graphqlUrl = `${API_URL}/graphql?slice=${ encodeURIComponent(SLICE_URI) }`; const authHeader = `${tokens.tokenType} ${tokens.accessToken}`; // 1. Check if profile already exists const checkQuery = ` query CheckProfile($did: String!) { networkSlicesActorProfiles(where: { did: { eq: $did } }, first: 1) { edges { node { id } } } } `; const checkResponse = await fetch(graphqlUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": authHeader, }, body: JSON.stringify({ query: checkQuery, variables: { did: userDid }, }), }); if (!checkResponse.ok) { throw new Error(`Profile check failed: ${checkResponse.statusText}`); } const checkData = await checkResponse.json(); const hasProfile = (checkData?.data?.networkSlicesActorProfiles?.edges?.length ?? 0) > 0; if (hasProfile) { // User already has a profile, nothing to do console.log("Profile already exists for", userDid); return; } // 2. Sync user collections (to get Bluesky data) const syncMutation = ` mutation SyncUserCollections($did: String!) { syncUserCollections(did: $did) { success message } } `; const syncResponse = await fetch(graphqlUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": authHeader, }, body: JSON.stringify({ query: syncMutation, variables: { did: userDid }, }), }); if (!syncResponse.ok) { throw new Error(`Sync collections failed: ${syncResponse.statusText}`); } const syncResult = await syncResponse.json(); if (syncResult.errors) { console.error("Sync collections errors:", syncResult.errors); throw new Error("Failed to sync user collections"); } // 3. Fetch Bluesky profile data const bskyQuery = ` query GetBskyProfile($did: String!) { appBskyActorProfiles(where: { did: { eq: $did } }, first: 1) { edges { node { displayName description avatar { ref mimeType size } } } } } `; const bskyResponse = await fetch(graphqlUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": authHeader, }, body: JSON.stringify({ query: bskyQuery, variables: { did: userDid }, }), }); if (!bskyResponse.ok) { throw new Error( `Fetch Bluesky profile failed: ${bskyResponse.statusText}`, ); } const bskyData = await bskyResponse.json(); const bskyProfile = bskyData?.data?.appBskyActorProfiles?.edges?.[0]?.node; // 4. Create network.slices.actor.profile with Bluesky data const profileInput: { displayName: string; description?: string; avatar?: unknown; createdAt: string; } = { displayName: bskyProfile?.displayName || userHandle || "User", createdAt: new Date().toISOString(), }; if (bskyProfile?.description) { profileInput.description = bskyProfile.description; } if ( bskyProfile?.avatar?.ref && bskyProfile?.avatar?.mimeType && bskyProfile?.avatar?.size ) { // Reconstruct blob format for AT Protocol profileInput.avatar = { ref: bskyProfile.avatar.ref, mimeType: bskyProfile.avatar.mimeType, size: bskyProfile.avatar.size, }; } const createMutation = ` mutation CreateProfile( $input: NetworkSlicesActorProfileInput! $rkey: String ) { createNetworkSlicesActorProfile(input: $input, rkey: $rkey) { id } } `; const createResponse = await fetch(graphqlUrl, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": authHeader, }, body: JSON.stringify({ query: createMutation, variables: { input: profileInput, rkey: "self", }, }), }); if (!createResponse.ok) { throw new Error(`Create profile failed: ${createResponse.statusText}`); } const createResult = await createResponse.json(); if (createResult.errors) { console.error("Create profile errors:", createResult.errors); throw new Error("Failed to create profile"); } console.log("Successfully initialized profile for", userDid); } catch (error) { // Silent failure - user can set up profile manually later console.error("Profile initialization failed:", error); } }