import React, { createContext, useContext, useEffect, useState } from "react"; interface DiscordUser { id: string; discord_id: string; full_name: string | null; username: string | null; avatar_url: string | null; bio: string | null; user_type: string | null; primary_arm: string | null; } interface DiscordActivityContextType { isActivity: boolean; isLoading: boolean; user: DiscordUser | null; error: string | null; discordSdk: any | null; } const DiscordActivityContext = createContext({ isActivity: false, isLoading: false, user: null, error: null, discordSdk: null, }); export const useDiscordActivity = () => { const context = useContext(DiscordActivityContext); if (!context) { throw new Error( "useDiscordActivity must be used within DiscordActivityProvider", ); } return context; }; interface DiscordActivityProviderProps { children: React.ReactNode; } export const DiscordActivityProvider: React.FC< DiscordActivityProviderProps > = ({ children }) => { const [isActivity, setIsActivity] = useState(false); const [isLoading, setIsLoading] = useState(false); const [user, setUser] = useState(null); const [error, setError] = useState(null); const [discordSdk, setDiscordSdk] = useState(null); useEffect(() => { const initializeActivity = async () => { // Check if we're running inside a Discord Activity // Discord passes frame_id as a query parameter when launching an Activity const searchParams = new URLSearchParams(window.location.search); const frameId = searchParams.get("frame_id"); const isInDiscordActivity = frameId !== null; console.log("[Discord Activity] Initialization starting...", { frameId, isInDiscordActivity, userAgent: navigator.userAgent, href: window.location.href, }); if (isInDiscordActivity) { try { setIsActivity(true); setIsLoading(true); // Import the Discord SDK dynamically const { DiscordSDK } = await import("@discord/embedded-app-sdk"); const clientId = import.meta.env.VITE_DISCORD_CLIENT_ID || "578971245454950421"; console.log( "[Discord Activity] Creating SDK with clientId:", clientId, ); const sdk = new DiscordSDK({ clientId, }); setDiscordSdk(sdk); // Wait for SDK to be ready console.log("[Discord Activity] Waiting for SDK to be ready..."); await sdk.ready(); console.log("[Discord Activity] SDK is ready"); // Get the current user from the SDK const currentUser = await sdk.user.getUser(); console.log( "[Discord Activity] Current user:", currentUser ? "exists" : "null", ); if (!currentUser) { // User not authenticated, authorize them console.log("[Discord Activity] Authorizing user..."); const { access_token } = await sdk.commands.authorize({ scopes: ["identify", "guilds"], }); console.log( "[Discord Activity] Got access token, calling activity-auth...", ); // Exchange access token for user data via our proxy const response = await fetch("/api/discord/activity-auth", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ access_token }), }); if (!response.ok) { const errorData = await response.json(); const errMsg = errorData.error || "Failed to authenticate"; console.error("[Discord Activity] Auth failed:", errMsg); setError(errMsg); setIsLoading(false); return; } const data = await response.json(); if (data.success && data.user) { console.log("[Discord Activity] User authenticated successfully"); setUser(data.user); setError(null); } else { console.error( "[Discord Activity] Authentication response invalid:", data, ); setError("Authentication failed"); } } else { // User already authenticated, just fetch via our proxy console.log( "[Discord Activity] User already authenticated, fetching user data...", ); const response = await fetch("/api/discord/activity-auth", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ access_token: currentUser.access_token || "", }), }); if (!response.ok) { const errorData = await response.json(); const errMsg = errorData.error || "Failed to fetch user data"; console.error("[Discord Activity] Fetch failed:", errMsg); setError(errMsg); setIsLoading(false); return; } const data = await response.json(); if (data.success && data.user) { console.log("[Discord Activity] User data loaded successfully"); setUser(data.user); setError(null); } else { console.error( "[Discord Activity] User data response invalid:", data, ); setError("Failed to load user data"); } } } catch (err: any) { console.error("Discord Activity initialization error:", err); console.error("Error details:", { message: err?.message, code: err?.code, stack: err?.stack, }); setError( `${err?.message || "Failed to initialize Discord Activity"}. Check browser console for details.`, ); } finally { setIsLoading(false); } } else { // Not in a Discord iframe console.log( "[Discord Activity] Not in Discord Activity context (no frame_id)", ); setIsActivity(false); setIsLoading(false); } }; initializeActivity(); }, []); return ( {children} ); }; export default DiscordActivityContext;