major-domo-v2/commands/teams/__init__.py
Cal Corum 5133dc3d0f Add /branding command for team color/logo management (v2.20.0)
Implemented comprehensive team branding management system allowing team owners
to update colors and logos for major league, minor league, and dice rolls.

Features:
- Modal-based interactive form input with validation
- Hex color validation with normalization (6 chars, optional # prefix)
- Image URL accessibility testing with aiohttp (5 second timeout)
- Preview + confirmation workflow with ConfirmationView
- Support for both major league and minor league affiliate updates
- Dice color customization for game rolls
- Discord role color sync (non-blocking with graceful fallback)
- Comprehensive error handling and user feedback

Technical Implementation:
- BrandingModal class with 5 optional fields
- Concurrent URL validation using asyncio.gather
- Fixed team_service.update_team() to use PATCH with query parameters
- Enhanced TeamService documentation with correct method signatures
- 33 comprehensive tests (100% passing)

Bug Fixes:
- Fixed modal send timing (immediate response vs deferred)
- Fixed interaction handling for cancel button
- Fixed database API communication (PATCH query params vs PUT JSON)

Files:
- commands/teams/branding.py (NEW - ~500 lines)
- commands/teams/__init__.py (added BrandingCommands registration)
- commands/teams/CLAUDE.md (added comprehensive documentation)
- tests/test_commands_teams_branding.py (NEW - 33 tests)
- services/team_service.py (fixed update_team to use query params)
- VERSION (2.19.2 → 2.20.0)

Docker: manticorum67/major-domo-discord-app-v2:2.20.0

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 10:39:52 -06:00

54 lines
1.6 KiB
Python

"""
Team command package for Discord Bot v2.0
Provides team-related slash commands for the SBA league.
"""
import logging
from typing import List, Tuple, Type
import discord
from discord.ext import commands
from .info import TeamInfoCommands
from .roster import TeamRosterCommands
from .branding import BrandingCommands
logger = logging.getLogger(f'{__name__}.setup_teams')
async def setup_teams(bot: commands.Bot) -> Tuple[int, int, List[str]]:
"""
Set up team command modules.
Returns:
Tuple of (successful_loads, failed_loads, failed_modules)
"""
team_cogs: List[Tuple[str, Type[commands.Cog]]] = [
("TeamInfoCommands", TeamInfoCommands),
("TeamRosterCommands", TeamRosterCommands),
("BrandingCommands", BrandingCommands),
]
successful = 0
failed = 0
failed_modules = []
for cog_name, cog_class in team_cogs:
try:
await bot.add_cog(cog_class(bot))
logger.info(f"✅ Loaded team command module: {cog_name}")
successful += 1
except Exception as e:
logger.error(f"❌ Failed to load team command module {cog_name}: {e}")
failed += 1
failed_modules.append(cog_name)
# Log summary
if failed == 0:
logger.info(f"🎉 All {successful} team command modules loaded successfully")
else:
logger.warning(f"⚠️ Team commands loaded with issues: {successful} successful, {failed} failed")
if failed_modules:
logger.warning(f"Failed modules: {', '.join(failed_modules)}")
return successful, failed, failed_modules