From cf94eef683509bae516934579c7109f82582d609 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 12 Oct 2025 00:43:58 +0000 Subject: [PATCH] Fix Discord OAuth data format --- .../functions/process-oauth-profile/index.ts | 83 +++++++++---------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/supabase/functions/process-oauth-profile/index.ts b/supabase/functions/process-oauth-profile/index.ts index e2c7947b..9eae5aa1 100644 --- a/supabase/functions/process-oauth-profile/index.ts +++ b/supabase/functions/process-oauth-profile/index.ts @@ -29,14 +29,18 @@ interface GoogleUserMetadata { interface DiscordUserMetadata { email?: string; - username?: string; - global_name?: string; - discriminator?: string; - avatar?: string; - id?: string; - verified?: boolean; - flags?: number; - premium_type?: number; + name?: string; // "username#0" format + full_name?: string; // "username" without discriminator + custom_claims?: { + global_name?: string; // Display name like "PacNPal" + }; + avatar_url?: string; // Full CDN URL + picture?: string; // Alternative full CDN URL + provider_id?: string; // Discord user ID + sub?: string; // Alternative Discord user ID + email_verified?: boolean; + phone_verified?: boolean; + iss?: string; } Deno.serve(async (req) => { @@ -80,17 +84,12 @@ Deno.serve(async (req) => { if (discordIdentity) { userMetadata = discordIdentity.identity_data || {}; - // Debug: Log full identity_data to see what Discord actually returns - console.log('[OAuth Profile] Discord identity_data (full):', JSON.stringify(discordIdentity.identity_data)); - - console.log('[OAuth Profile] Using Discord identity data:', { - hasAvatar: !!userMetadata.avatar, - hasUsername: !!userMetadata.username, - hasGlobalName: !!userMetadata.global_name, - hasId: !!userMetadata.id, - hasEmail: !!userMetadata.email, - avatarValue: userMetadata.avatar, - idValue: userMetadata.id + console.log('[OAuth Profile] Discord identity_data:', { + hasAvatarUrl: !!(userMetadata as DiscordUserMetadata).avatar_url, + hasFullName: !!(userMetadata as DiscordUserMetadata).full_name, + hasGlobalName: !!(userMetadata as DiscordUserMetadata).custom_claims?.global_name, + hasProviderId: !!(userMetadata as DiscordUserMetadata).provider_id, + hasEmail: !!(userMetadata as DiscordUserMetadata).email }); } else { console.warn('[OAuth Profile] Discord provider found but no Discord identity in user.identities'); @@ -111,43 +110,39 @@ Deno.serve(async (req) => { } else if (provider === 'discord') { const discordData = userMetadata as DiscordUserMetadata; - // Prefer global_name, fall back to username - displayName = discordData.global_name || discordData.username || null; - usernameBase = discordData.username || null; + // Extract Discord user ID from provider_id or sub + const discordId = discordData.provider_id || discordData.sub || null; - // Extract email (Discord provides it with email scope) + // Extract display name: custom_claims.global_name > full_name > name + displayName = discordData.custom_claims?.global_name || discordData.full_name || discordData.name || null; + + // Extract username base: full_name or name without discriminator + usernameBase = discordData.full_name || discordData.name?.split('#')[0] || null; + + // Extract email const discordEmail = discordData.email || null; - // Validate we have minimum required data - if (!discordData.id) { - console.error('[OAuth Profile] Discord user ID missing - OAuth scopes may not be configured correctly'); + // Use the avatar URL that Supabase already provides (full CDN URL) + avatarUrl = discordData.avatar_url || discordData.picture || null; + + // Validation logging + if (!discordId) { + console.error('[OAuth Profile] Discord user ID missing from provider_id/sub - OAuth data incomplete'); } - if (!discordData.username) { + if (!usernameBase) { console.warn('[OAuth Profile] Discord username missing - using ID as fallback'); - usernameBase = discordData.id || null; + usernameBase = discordId; } - // Construct Discord avatar URL with proper format detection - if (discordData.avatar && discordData.id) { - // Discord animated avatars have 'a_' prefix and use .gif extension - const isAnimated = discordData.avatar.startsWith('a_'); - const extension = isAnimated ? 'gif' : 'png'; - avatarUrl = `https://cdn.discordapp.com/avatars/${discordData.id}/${discordData.avatar}.${extension}?size=512`; - } else if (!discordData.avatar && discordData.id) { - // User has no custom avatar - use Discord default avatar - const defaultAvatarIndex = (parseInt(discordData.id) >> 22) % 6; - avatarUrl = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarIndex}.png`; - console.log('[OAuth Profile] Using Discord default avatar for user without custom avatar'); - } - - console.log('[OAuth Profile] Discord user:', { + console.log('[OAuth Profile] Discord user (Supabase format):', { avatarUrl, displayName, usernameBase, + discordId, email: discordEmail, - hasAnimatedAvatar: discordData.avatar?.startsWith('a_'), - hasCustomAvatar: !!discordData.avatar + hasAvatar: !!avatarUrl, + source: discordData.avatar_url ? 'avatar_url' : discordData.picture ? 'picture' : 'none' }); } else { console.log('[OAuth Profile] Unsupported provider:', provider);