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 <noreply@anthropic.com>
325 lines
10 KiB
Python
325 lines
10 KiB
Python
"""
|
|
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))
|