diff --git a/api_service/dashboard_api_endpoints.py b/api_service/dashboard_api_endpoints.py index 0e7b3bb..183894d 100644 --- a/api_service/dashboard_api_endpoints.py +++ b/api_service/dashboard_api_endpoints.py @@ -105,19 +105,121 @@ async def get_user_guilds( ): """Get all guilds the user is an admin of.""" try: - # This would normally fetch guilds from Discord API or the bot - # For now, we'll return a mock response - # TODO: Replace mock data with actual API call to Discord - guilds = [ - Guild(id="123456789", name="My Awesome Server", icon_url="https://cdn.discordapp.com/icons/123456789/abc123def456ghi789jkl012mno345pqr.png"), - Guild(id="987654321", name="Another Great Server", icon_url="https://cdn.discordapp.com/icons/987654321/zyx987wvu654tsr321qpo098mlk765jih.png") - ] - return guilds + # First, try to use the real implementation from api_server.py + try: + # Import the dashboard_get_user_guilds function from api_server + from api_service.api_server import dashboard_get_user_guilds + + # Call the function with the user + guilds_data = await dashboard_get_user_guilds(user) + + # Convert the data to Guild objects + guilds = [] + for guild in guilds_data: + # Create icon URL if icon is available + icon_url = None + if guild.get('icon'): + icon_url = f"https://cdn.discordapp.com/icons/{guild['id']}/{guild['icon']}.png" + + guilds.append(Guild( + id=guild['id'], + name=guild['name'], + icon_url=icon_url + )) + + log.info(f"Successfully fetched {len(guilds)} guilds for user {user.get('user_id')} using api_server implementation") + return guilds + + except ImportError as e: + log.warning(f"Could not import dashboard_get_user_guilds from api_server: {e}") + # Fall back to direct implementation + except Exception as e: + log.warning(f"Error using dashboard_get_user_guilds from api_server: {e}") + # Fall back to direct implementation + + # Direct implementation as fallback + from global_bot_accessor import get_bot_instance + import aiohttp + + # Check if settings_manager is available + bot = get_bot_instance() + if not bot or not bot.pg_pool: + log.warning("Bot instance or PostgreSQL pool not available for get_user_guilds") + # Fall back to mock data since we can't access the real data + log.info("Using mock data for user guilds as fallback") + return [ + Guild(id="123456789", name="My Awesome Server (Mock)", icon_url=None), + Guild(id="987654321", name="Another Great Server (Mock)", icon_url=None) + ] + + # Get Discord API URLs from environment or use defaults + DISCORD_API_URL = "https://discord.com/api/v10" + DISCORD_USER_GUILDS_URL = f"{DISCORD_API_URL}/users/@me/guilds" + + # Get access token from user + access_token = user.get('access_token') + if not access_token: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Access token not found in user session" + ) + + # Create headers for Discord API request + user_headers = {'Authorization': f'Bearer {access_token}'} + + # Create a temporary aiohttp session + async with aiohttp.ClientSession() as session: + # 1. Fetch guilds user is in from Discord + log.debug(f"Fetching user guilds from {DISCORD_USER_GUILDS_URL}") + async with session.get(DISCORD_USER_GUILDS_URL, headers=user_headers) as resp: + if resp.status == 401: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Discord API authentication failed. Please log in again." + ) + resp.raise_for_status() + user_guilds = await resp.json() + log.debug(f"Fetched {len(user_guilds)} guilds for user {user.get('user_id')}") + + # 2. Get bot guilds from the bot instance + bot_guild_ids = set() + if bot.guilds: + bot_guild_ids = {guild.id for guild in bot.guilds} + log.debug(f"Bot is in {len(bot_guild_ids)} guilds") + else: + log.warning("Bot has no guilds or bot.guilds is not accessible") + + # 3. Filter user guilds + manageable_guilds = [] + ADMINISTRATOR_PERMISSION = 0x8 + for guild in user_guilds: + guild_id = int(guild['id']) + permissions = int(guild['permissions']) + + if (permissions & ADMINISTRATOR_PERMISSION) == ADMINISTRATOR_PERMISSION and guild_id in bot_guild_ids: + # Create icon URL if icon is available + icon_url = None + if guild.get('icon'): + icon_url = f"https://cdn.discordapp.com/icons/{guild['id']}/{guild['icon']}.png" + + manageable_guilds.append(Guild( + id=guild['id'], + name=guild['name'], + icon_url=icon_url + )) + + log.info(f"Found {len(manageable_guilds)} manageable guilds for user {user.get('user_id')}") + return manageable_guilds + + except HTTPException: + # Re-raise HTTP exceptions + raise except Exception as e: log.error(f"Error getting user guilds: {e}") + # Return a more user-friendly error message raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Error getting user guilds: {str(e)}" + detail="Failed to retrieve your Discord servers. Please try again later." ) @router.get("/guilds/{guild_id}/channels", response_model=List[Channel]) diff --git a/api_service/dashboard_web/js/main.js b/api_service/dashboard_web/js/main.js index 6dd31c4..7ff08a9 100644 --- a/api_service/dashboard_web/js/main.js +++ b/api_service/dashboard_web/js/main.js @@ -467,7 +467,7 @@ function loadUserGuilds() { serverListContainer.innerHTML = ''; // Clear loading state if (!guilds || guilds.length === 0) { - serverListContainer.innerHTML = '
No servers found where you have admin permissions.
'; + serverListContainer.innerHTML = 'Error loading servers. Please try again.
'; - Toast.error('Failed to load your servers.'); + + // Create a more detailed error message with troubleshooting steps + let errorMessage = 'We encountered a problem while trying to load your servers. This could be due to:
'; + errorMessage += 'Troubleshooting steps:
'; + errorMessage += '