From 4cb64253c4b3a71eed5cba650bf9344d371a5558 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Fri, 24 Oct 2025 22:25:30 -0500 Subject: [PATCH] CLAUDE: Add complete draft command suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement all remaining draft commands for comprehensive draft management: New Commands: - /draft-admin (Group) - Admin controls for draft management * info - View current draft configuration * timer - Enable/disable draft timer * set-pick - Set current pick number * channels - Configure Discord channels * reset-deadline - Reset pick deadline - /draft-status - View current draft state - /draft-on-clock - Detailed "on the clock" information with recent/upcoming picks - /draft-list - View team's auto-draft queue - /draft-list-add - Add player to queue - /draft-list-remove - Remove player from queue - /draft-list-clear - Clear entire queue - /draft-board - View draft picks by round New Files: - commands/draft/admin.py - Admin commands (app_commands.Group pattern) - commands/draft/status.py - Status viewing commands - commands/draft/list.py - Auto-draft queue management - commands/draft/board.py - Draft board viewing Features: - Admin-only permissions for draft management - FA player autocomplete for draft list - Complete draft state visibility - Round-by-round draft board viewing - Lock status integration - Timer and deadline management Updated: - commands/draft/__init__.py - Register all new cogs and group All commands use @logged_command decorator for consistent logging and error handling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- commands/draft/__init__.py | 37 ++++- commands/draft/admin.py | 293 +++++++++++++++++++++++++++++++++ commands/draft/board.py | 79 +++++++++ commands/draft/list.py | 324 +++++++++++++++++++++++++++++++++++++ commands/draft/status.py | 147 +++++++++++++++++ 5 files changed, 877 insertions(+), 3 deletions(-) create mode 100644 commands/draft/admin.py create mode 100644 commands/draft/board.py create mode 100644 commands/draft/list.py create mode 100644 commands/draft/status.py diff --git a/commands/draft/__init__.py b/commands/draft/__init__.py index cc4449e..746f77a 100644 --- a/commands/draft/__init__.py +++ b/commands/draft/__init__.py @@ -3,13 +3,23 @@ Draft Commands Package for Discord Bot v2.0 Contains slash commands for draft operations: - /draft - Make a draft pick with autocomplete -- /draft-status - View current draft state (TODO) -- /draft-admin - Admin controls for draft management (TODO) +- /draft-status - View current draft state +- /draft-on-clock - Detailed on the clock information +- /draft-admin - Admin controls for draft management +- /draft-list - View auto-draft queue +- /draft-list-add - Add player to queue +- /draft-list-remove - Remove player from queue +- /draft-list-clear - Clear entire queue +- /draft-board - View draft picks by round """ import logging from discord.ext import commands from .picks import DraftPicksCog +from .status import DraftStatusCommands +from .list import DraftListCommands +from .board import DraftBoardCommands +from .admin import DraftAdminGroup logger = logging.getLogger(__name__) @@ -24,12 +34,16 @@ async def setup_draft(bot: commands.Bot): # Define all draft command cogs to load draft_cogs = [ ("DraftPicksCog", DraftPicksCog), + ("DraftStatusCommands", DraftStatusCommands), + ("DraftListCommands", DraftListCommands), + ("DraftBoardCommands", DraftBoardCommands), ] successful = 0 failed = 0 failed_modules = [] + # Load regular cogs for cog_name, cog_class in draft_cogs: try: await bot.add_cog(cog_class(bot)) @@ -40,6 +54,16 @@ async def setup_draft(bot: commands.Bot): failed += 1 failed_modules.append(cog_name) + # Load draft admin group (app_commands.Group pattern) + try: + bot.tree.add_command(DraftAdminGroup()) + logger.info("✅ Loaded DraftAdminGroup") + successful += 1 + except Exception as e: + logger.error(f"❌ Failed to load DraftAdminGroup: {e}", exc_info=True) + failed += 1 + failed_modules.append("DraftAdminGroup") + # Log summary if failed == 0: logger.info(f"🎉 All {successful} draft command modules loaded successfully") @@ -50,4 +74,11 @@ async def setup_draft(bot: commands.Bot): # Export the setup function for easy importing -__all__ = ['setup_draft', 'DraftPicksCog'] \ No newline at end of file +__all__ = [ + 'setup_draft', + 'DraftPicksCog', + 'DraftStatusCommands', + 'DraftListCommands', + 'DraftBoardCommands', + 'DraftAdminGroup' +] \ No newline at end of file diff --git a/commands/draft/admin.py b/commands/draft/admin.py new file mode 100644 index 0000000..e780757 --- /dev/null +++ b/commands/draft/admin.py @@ -0,0 +1,293 @@ +""" +Draft Admin Commands + +Admin-only commands for draft management and configuration. +""" +from typing import Optional + +import discord +from discord import app_commands +from discord.ext import commands + +from config import get_config +from services.draft_service import draft_service +from services.draft_pick_service import draft_pick_service +from utils.logging import get_contextual_logger +from utils.decorators import logged_command +from views.draft_views import create_admin_draft_info_embed +from views.embeds import EmbedTemplate + + +class DraftAdminGroup(app_commands.Group): + """Draft administration command group.""" + + def __init__(self): + super().__init__( + name="draft-admin", + description="Admin commands for draft management" + ) + self.logger = get_contextual_logger(f'{__name__}.DraftAdminGroup') + + @app_commands.command(name="info", description="View current draft configuration") + @app_commands.checks.has_permissions(administrator=True) + @logged_command("/draft-admin info") + async def draft_admin_info(self, interaction: discord.Interaction): + """Display current draft configuration and state.""" + await interaction.response.defer() + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get current pick + config = get_config() + current_pick = await draft_pick_service.get_pick( + config.sba_current_season, + draft_data.currentpick + ) + + # Create admin info embed + embed = await create_admin_draft_info_embed(draft_data, current_pick) + await interaction.followup.send(embed=embed) + + @app_commands.command(name="timer", description="Enable or disable draft timer") + @app_commands.describe( + enabled="Turn timer on or off", + minutes="Minutes per pick (optional, default uses current setting)" + ) + @app_commands.checks.has_permissions(administrator=True) + @logged_command("/draft-admin timer") + async def draft_admin_timer( + self, + interaction: discord.Interaction, + enabled: bool, + minutes: Optional[int] = None + ): + """Enable or disable the draft timer.""" + await interaction.response.defer() + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Update timer + updated = await draft_service.set_timer(draft_data.id, enabled, minutes) + + if not updated: + embed = EmbedTemplate.error( + "Update Failed", + "Failed to update draft timer." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + status = "enabled" if enabled else "disabled" + description = f"Draft timer has been **{status}**." + + if enabled and minutes: + description += f"\n\nPick duration: **{minutes} minutes**" + elif enabled: + description += f"\n\nPick duration: **{updated.pick_minutes} minutes**" + + embed = EmbedTemplate.success("Timer Updated", description) + await interaction.followup.send(embed=embed) + + @app_commands.command(name="set-pick", description="Set current pick number") + @app_commands.describe( + pick_number="Overall pick number to jump to (1-512)" + ) + @app_commands.checks.has_permissions(administrator=True) + @logged_command("/draft-admin set-pick") + async def draft_admin_set_pick( + self, + interaction: discord.Interaction, + pick_number: int + ): + """Set the current pick number (admin operation).""" + await interaction.response.defer() + + config = get_config() + + # Validate pick number + if pick_number < 1 or pick_number > config.draft_total_picks: + embed = EmbedTemplate.error( + "Invalid Pick Number", + f"Pick number must be between 1 and {config.draft_total_picks}." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Verify pick exists + pick = await draft_pick_service.get_pick(config.sba_current_season, pick_number) + if not pick: + embed = EmbedTemplate.error( + "Pick Not Found", + f"Pick #{pick_number} does not exist in the database." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Update current pick + updated = await draft_service.set_current_pick( + draft_data.id, + pick_number, + reset_timer=True + ) + + if not updated: + embed = EmbedTemplate.error( + "Update Failed", + "Failed to update current pick." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + from utils.draft_helpers import format_pick_display + + description = f"Current pick set to **{format_pick_display(pick_number)}**." + if pick.owner: + description += f"\n\n{pick.owner.abbrev} {pick.owner.sname} is now on the clock." + + embed = EmbedTemplate.success("Pick Updated", description) + await interaction.followup.send(embed=embed) + + @app_commands.command(name="channels", description="Configure draft Discord channels") + @app_commands.describe( + ping_channel="Channel for 'on the clock' pings", + result_channel="Channel for draft results" + ) + @app_commands.checks.has_permissions(administrator=True) + @logged_command("/draft-admin channels") + async def draft_admin_channels( + self, + interaction: discord.Interaction, + ping_channel: Optional[discord.TextChannel] = None, + result_channel: Optional[discord.TextChannel] = None + ): + """Configure draft Discord channels.""" + await interaction.response.defer() + + if not ping_channel and not result_channel: + embed = EmbedTemplate.error( + "No Channels Provided", + "Please specify at least one channel to update." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Update channels + updated = await draft_service.update_channels( + draft_data.id, + ping_channel_id=ping_channel.id if ping_channel else None, + result_channel_id=result_channel.id if result_channel else None + ) + + if not updated: + embed = EmbedTemplate.error( + "Update Failed", + "Failed to update draft channels." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + description = "Draft channels updated:\n\n" + if ping_channel: + description += f"**Ping Channel:** {ping_channel.mention}\n" + if result_channel: + description += f"**Result Channel:** {result_channel.mention}\n" + + embed = EmbedTemplate.success("Channels Updated", description) + await interaction.followup.send(embed=embed) + + @app_commands.command(name="reset-deadline", description="Reset current pick deadline") + @app_commands.describe( + minutes="Minutes to add (uses default if not provided)" + ) + @app_commands.checks.has_permissions(administrator=True) + @logged_command("/draft-admin reset-deadline") + async def draft_admin_reset_deadline( + self, + interaction: discord.Interaction, + minutes: Optional[int] = None + ): + """Reset the current pick deadline.""" + await interaction.response.defer() + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + if not draft_data.timer: + embed = EmbedTemplate.warning( + "Timer Inactive", + "Draft timer is currently disabled. Enable it with `/draft-admin timer on` first." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Reset deadline + updated = await draft_service.reset_draft_deadline(draft_data.id, minutes) + + if not updated: + embed = EmbedTemplate.error( + "Update Failed", + "Failed to reset draft deadline." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + deadline_timestamp = int(updated.pick_deadline.timestamp()) + minutes_used = minutes if minutes else updated.pick_minutes + + description = f"Pick deadline reset: **{minutes_used} minutes** added.\n\n" + description += f"New deadline: ()" + + embed = EmbedTemplate.success("Deadline Reset", description) + await interaction.followup.send(embed=embed) + + +async def setup(bot: commands.Bot): + """Setup function for loading the draft admin commands.""" + bot.tree.add_command(DraftAdminGroup()) diff --git a/commands/draft/board.py b/commands/draft/board.py new file mode 100644 index 0000000..86fc372 --- /dev/null +++ b/commands/draft/board.py @@ -0,0 +1,79 @@ +""" +Draft Board Commands + +View draft picks by round with pagination. +""" +from typing import Optional + +import discord +from discord.ext import commands + +from config import get_config +from services.draft_pick_service import draft_pick_service +from utils.logging import get_contextual_logger +from utils.decorators import logged_command +from views.draft_views import create_draft_board_embed +from views.embeds import EmbedTemplate + + +class DraftBoardCommands(commands.Cog): + """Draft board viewing command handlers.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + self.logger = get_contextual_logger(f'{__name__}.DraftBoardCommands') + + @discord.app_commands.command( + name="draft-board", + description="View draft picks by round" + ) + @discord.app_commands.describe( + round_number="Round number to view (1-32)" + ) + @logged_command("/draft-board") + async def draft_board( + self, + interaction: discord.Interaction, + round_number: Optional[int] = None + ): + """Display draft board for a specific round.""" + await interaction.response.defer() + + config = get_config() + + # Default to round 1 if not specified + if round_number is None: + round_number = 1 + + # Validate round number + if round_number < 1 or round_number > config.draft_rounds: + embed = EmbedTemplate.error( + "Invalid Round", + f"Round number must be between 1 and {config.draft_rounds}." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get picks for this round + picks = await draft_pick_service.get_picks_by_round( + config.sba_current_season, + round_number, + include_taken=True + ) + + if not picks: + embed = EmbedTemplate.error( + "No Picks Found", + f"Could not retrieve picks for round {round_number}." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Create draft board embed + embed = await create_draft_board_embed(round_number, picks) + await interaction.followup.send(embed=embed) + + +async def setup(bot: commands.Bot): + """Load the draft board commands cog.""" + await bot.add_cog(DraftBoardCommands(bot)) diff --git a/commands/draft/list.py b/commands/draft/list.py new file mode 100644 index 0000000..dcf6329 --- /dev/null +++ b/commands/draft/list.py @@ -0,0 +1,324 @@ +""" +Draft List Commands + +Manage team auto-draft queue (draft board). +""" +from typing import List, Optional + +import discord +from discord import app_commands +from discord.ext import commands + +from config import get_config +from services.draft_list_service import draft_list_service +from services.player_service import player_service +from services.team_service import team_service +from utils.logging import get_contextual_logger +from utils.decorators import logged_command +from views.draft_views import create_draft_list_embed +from views.embeds import EmbedTemplate + + +async def fa_player_autocomplete( + interaction: discord.Interaction, + current: str, +) -> List[discord.app_commands.Choice[str]]: + """Autocomplete for FA players only.""" + if len(current) < 2: + return [] + + try: + config = get_config() + players = await player_service.search_players( + current, + limit=25, + season=config.sba_current_season + ) + + # Filter to FA team + fa_players = [p for p in players if p.team_id == config.free_agent_team_id] + + return [ + discord.app_commands.Choice( + name=f"{p.name} ({p.primary_position}) - {p.wara:.2f} sWAR", + value=p.name + ) + for p in fa_players[:25] + ] + + except Exception: + return [] + + +class DraftListCommands(commands.Cog): + """Draft list management command handlers.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + self.logger = get_contextual_logger(f'{__name__}.DraftListCommands') + + @discord.app_commands.command( + name="draft-list", + description="View your team's auto-draft queue" + ) + @logged_command("/draft-list") + async def draft_list_view(self, interaction: discord.Interaction): + """Display team's draft list.""" + await interaction.response.defer() + + config = get_config() + + # Get user's team + team = await team_service.get_team_by_owner( + interaction.user.id, + config.sba_current_season + ) + + if not team: + embed = EmbedTemplate.error( + "Not a GM", + "You are not registered as a team owner." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get draft list + draft_list = await draft_list_service.get_team_list( + config.sba_current_season, + team.id + ) + + # Create embed + embed = await create_draft_list_embed(team, draft_list) + await interaction.followup.send(embed=embed) + + @discord.app_commands.command( + name="draft-list-add", + description="Add player to your auto-draft queue" + ) + @discord.app_commands.describe( + player="Player name to add (autocomplete shows FA players)", + rank="Position in queue (optional, adds to end if not specified)" + ) + @discord.app_commands.autocomplete(player=fa_player_autocomplete) + @logged_command("/draft-list-add") + async def draft_list_add( + self, + interaction: discord.Interaction, + player: str, + rank: Optional[int] = None + ): + """Add player to draft list.""" + await interaction.response.defer() + + config = get_config() + + # Get user's team + team = await team_service.get_team_by_owner( + interaction.user.id, + config.sba_current_season + ) + + if not team: + embed = EmbedTemplate.error( + "Not a GM", + "You are not registered as a team owner." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get player + players = await player_service.get_players_by_name(player, config.sba_current_season) + if not players: + embed = EmbedTemplate.error( + "Player Not Found", + f"Could not find player '{player}'." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + player_obj = players[0] + + # Validate player is FA + if player_obj.team_id != config.free_agent_team_id: + embed = EmbedTemplate.error( + "Player Not Available", + f"{player_obj.name} is not a free agent." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Check if player already in list + current_list = await draft_list_service.get_team_list( + config.sba_current_season, + team.id + ) + + if any(entry.player_id == player_obj.id for entry in current_list): + embed = EmbedTemplate.error( + "Already in Queue", + f"{player_obj.name} is already in your draft queue." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Validate rank + if rank is not None: + if rank < 1 or rank > len(current_list) + 1: + embed = EmbedTemplate.error( + "Invalid Rank", + f"Rank must be between 1 and {len(current_list) + 1}." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Add to list + entry = await draft_list_service.add_to_list( + config.sba_current_season, + team.id, + player_obj.id, + rank + ) + + if not entry: + embed = EmbedTemplate.error( + "Add Failed", + f"Failed to add {player_obj.name} to draft queue." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + rank_str = f"#{entry.rank}" if entry.rank else "at end" + description = f"Added **{player_obj.name}** to your draft queue at position **{rank_str}**." + + embed = EmbedTemplate.success("Player Added", description) + await interaction.followup.send(embed=embed) + + @discord.app_commands.command( + name="draft-list-remove", + description="Remove player from your auto-draft queue" + ) + @discord.app_commands.describe( + player="Player name to remove" + ) + @discord.app_commands.autocomplete(player=fa_player_autocomplete) + @logged_command("/draft-list-remove") + async def draft_list_remove( + self, + interaction: discord.Interaction, + player: str + ): + """Remove player from draft list.""" + await interaction.response.defer() + + config = get_config() + + # Get user's team + team = await team_service.get_team_by_owner( + interaction.user.id, + config.sba_current_season + ) + + if not team: + embed = EmbedTemplate.error( + "Not a GM", + "You are not registered as a team owner." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get player + players = await player_service.get_players_by_name(player, config.sba_current_season) + if not players: + embed = EmbedTemplate.error( + "Player Not Found", + f"Could not find player '{player}'." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + player_obj = players[0] + + # Remove from list + success = await draft_list_service.remove_player_from_list( + config.sba_current_season, + team.id, + player_obj.id + ) + + if not success: + embed = EmbedTemplate.error( + "Not in Queue", + f"{player_obj.name} is not in your draft queue." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + description = f"Removed **{player_obj.name}** from your draft queue." + embed = EmbedTemplate.success("Player Removed", description) + await interaction.followup.send(embed=embed) + + @discord.app_commands.command( + name="draft-list-clear", + description="Clear your entire auto-draft queue" + ) + @logged_command("/draft-list-clear") + async def draft_list_clear(self, interaction: discord.Interaction): + """Clear entire draft list.""" + await interaction.response.defer() + + config = get_config() + + # Get user's team + team = await team_service.get_team_by_owner( + interaction.user.id, + config.sba_current_season + ) + + if not team: + embed = EmbedTemplate.error( + "Not a GM", + "You are not registered as a team owner." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get current list size + current_list = await draft_list_service.get_team_list( + config.sba_current_season, + team.id + ) + + if not current_list: + embed = EmbedTemplate.info( + "Queue Empty", + "Your draft queue is already empty." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Clear list + success = await draft_list_service.clear_list( + config.sba_current_season, + team.id + ) + + if not success: + embed = EmbedTemplate.error( + "Clear Failed", + "Failed to clear draft queue." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Success message + description = f"Cleared **{len(current_list)} players** from your draft queue." + embed = EmbedTemplate.success("Queue Cleared", description) + await interaction.followup.send(embed=embed) + + +async def setup(bot: commands.Bot): + """Load the draft list commands cog.""" + await bot.add_cog(DraftListCommands(bot)) diff --git a/commands/draft/status.py b/commands/draft/status.py new file mode 100644 index 0000000..0190ec1 --- /dev/null +++ b/commands/draft/status.py @@ -0,0 +1,147 @@ +""" +Draft Status Commands + +Display current draft state and information. +""" +import discord +from discord.ext import commands + +from config import get_config +from services.draft_service import draft_service +from services.draft_pick_service import draft_pick_service +from utils.logging import get_contextual_logger +from utils.decorators import logged_command +from views.draft_views import create_draft_status_embed, create_on_the_clock_embed +from views.embeds import EmbedTemplate + + +class DraftStatusCommands(commands.Cog): + """Draft status display command handlers.""" + + def __init__(self, bot: commands.Bot): + self.bot = bot + self.logger = get_contextual_logger(f'{__name__}.DraftStatusCommands') + + @discord.app_commands.command( + name="draft-status", + description="View current draft state and timer information" + ) + @logged_command("/draft-status") + async def draft_status(self, interaction: discord.Interaction): + """Display current draft state.""" + await interaction.response.defer() + + config = get_config() + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get current pick + current_pick = await draft_pick_service.get_pick( + config.sba_current_season, + draft_data.currentpick + ) + + if not current_pick: + embed = EmbedTemplate.error( + "Pick Not Found", + f"Could not retrieve pick #{draft_data.currentpick}." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Check pick lock status + draft_picks_cog = self.bot.get_cog('DraftPicksCog') + lock_status = "🔓 No pick in progress" + + if draft_picks_cog and draft_picks_cog.pick_lock.locked(): + if draft_picks_cog.lock_acquired_by: + user = self.bot.get_user(draft_picks_cog.lock_acquired_by) + user_name = user.name if user else f"User {draft_picks_cog.lock_acquired_by}" + lock_status = f"🔒 Pick in progress by {user_name}" + else: + lock_status = "🔒 Pick in progress (system)" + + # Create status embed + embed = await create_draft_status_embed(draft_data, current_pick, lock_status) + await interaction.followup.send(embed=embed) + + @discord.app_commands.command( + name="draft-on-clock", + description="View detailed 'on the clock' information" + ) + @logged_command("/draft-on-clock") + async def draft_on_clock(self, interaction: discord.Interaction): + """Display detailed 'on the clock' information with recent and upcoming picks.""" + await interaction.response.defer() + + config = get_config() + + # Get draft data + draft_data = await draft_service.get_draft_data() + if not draft_data: + embed = EmbedTemplate.error( + "Draft Not Found", + "Could not retrieve draft configuration." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get current pick + current_pick = await draft_pick_service.get_pick( + config.sba_current_season, + draft_data.currentpick + ) + + if not current_pick or not current_pick.owner: + embed = EmbedTemplate.error( + "Pick Not Found", + f"Could not retrieve pick #{draft_data.currentpick}." + ) + await interaction.followup.send(embed=embed, ephemeral=True) + return + + # Get recent picks + recent_picks = await draft_pick_service.get_recent_picks( + config.sba_current_season, + draft_data.currentpick, + limit=5 + ) + + # Get upcoming picks + upcoming_picks = await draft_pick_service.get_upcoming_picks( + config.sba_current_season, + draft_data.currentpick, + limit=5 + ) + + # Get team roster sWAR (optional) + from services.team_service import team_service + team_roster_swar = None + + roster = await team_service.get_team_roster(current_pick.owner.id, 'current') + if roster and roster.get('active'): + team_roster_swar = roster['active'].get('WARa') + + # Create on the clock embed + embed = await create_on_the_clock_embed( + current_pick, + draft_data, + recent_picks, + upcoming_picks, + team_roster_swar + ) + + await interaction.followup.send(embed=embed) + + +async def setup(bot: commands.Bot): + """Load the draft status commands cog.""" + await bot.add_cog(DraftStatusCommands(bot))