## Injury Command Enhancements ### Pitcher-Specific Injury Display - Added rest requirement note for pitcher injuries with game duration - Shows "X games plus their current rest requirement" for pitchers - Removed redundant footer text from FATIGUED result - Cleaner, more concise pitcher injury messaging ### Bot Configuration - Registered injuries command package in bot.py - Added proper import and setup for InjuryGroup ### Code Cleanup - Fixed misplaced import in views/embeds.py (moved to top) - Standardized import ordering across command files - Minor formatting improvements ## Files Changed - commands/injuries/management.py: Pitcher rest requirement display - bot.py: Injuries package registration - views/embeds.py: Import cleanup - Various: Import standardization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
372 lines
13 KiB
Python
372 lines
13 KiB
Python
"""
|
|
Enhanced Player Command Example using Views v2.0
|
|
|
|
Demonstrates modern Discord UI components with the new view system.
|
|
This is an example of how to upgrade existing commands to use the new views.
|
|
"""
|
|
from typing import Optional, List
|
|
|
|
import discord
|
|
from discord.ext import commands
|
|
|
|
from config import get_config
|
|
from services.player_service import player_service
|
|
from models.player import Player
|
|
from utils.logging import get_contextual_logger
|
|
from utils.decorators import logged_command
|
|
from exceptions import BotException
|
|
|
|
# Import our new view components
|
|
from views import (
|
|
SBAEmbedTemplate,
|
|
EmbedTemplate,
|
|
EmbedColors,
|
|
PlayerSelectionView,
|
|
DetailedInfoView,
|
|
SearchResultsView,
|
|
PlayerSearchModal,
|
|
PaginationView
|
|
)
|
|
|
|
|
|
class EnhancedPlayerCommands(commands.Cog):
|
|
"""Enhanced player commands using modern view system."""
|
|
|
|
def __init__(self, bot: commands.Bot):
|
|
self.bot = bot
|
|
self.logger = get_contextual_logger(f'{__name__}.EnhancedPlayerCommands')
|
|
self.logger.info("EnhancedPlayerCommands cog initialized")
|
|
|
|
@discord.app_commands.command(
|
|
name="player-enhanced",
|
|
description="Enhanced player search with modern UI"
|
|
)
|
|
@discord.app_commands.describe(
|
|
name="Player name to search for (optional - leave blank for advanced search)",
|
|
season="Season to show stats for (defaults to current season)"
|
|
)
|
|
@logged_command("/player-enhanced")
|
|
async def enhanced_player_info(
|
|
self,
|
|
interaction: discord.Interaction,
|
|
name: Optional[str] = None,
|
|
season: Optional[int] = None
|
|
):
|
|
"""Enhanced player search with modern UI components."""
|
|
await interaction.response.defer()
|
|
|
|
# If no name provided, show search modal
|
|
if not name:
|
|
modal = PlayerSearchModal()
|
|
await interaction.followup.send("Please fill out the search form:", ephemeral=True)
|
|
await interaction.user.send("Opening player search form...")
|
|
|
|
# Note: In real implementation, you'd handle modal differently
|
|
# This is just for demonstration
|
|
embed = EmbedTemplate.info(
|
|
title="Advanced Player Search",
|
|
description="Use the `/player-enhanced` command with a name, or we'll add modal support soon!"
|
|
)
|
|
await interaction.followup.send(embed=embed)
|
|
return
|
|
|
|
# Use current season if not specified
|
|
search_season = season or get_config().sba_current_season
|
|
|
|
# Search for players
|
|
players = await player_service.get_players_by_name(name, search_season)
|
|
|
|
if not players:
|
|
# Try fuzzy search
|
|
fuzzy_players = await player_service.search_players_fuzzy(name, limit=25)
|
|
|
|
if not fuzzy_players:
|
|
embed = EmbedTemplate.error(
|
|
title="No Players Found",
|
|
description=f"No players found matching '{name}' in season {search_season}."
|
|
)
|
|
await interaction.followup.send(embed=embed)
|
|
return
|
|
|
|
# Show search results with selection
|
|
await self._show_search_results(interaction, fuzzy_players, name, search_season)
|
|
return
|
|
|
|
# Handle multiple exact matches
|
|
if len(players) > 1:
|
|
await self._show_player_selection(interaction, players, search_season)
|
|
return
|
|
|
|
# Single player found - show detailed view
|
|
await self._show_player_details(interaction, players[0], search_season)
|
|
|
|
async def _show_search_results(
|
|
self,
|
|
interaction: discord.Interaction,
|
|
players: List[Player],
|
|
search_term: str,
|
|
season: int
|
|
):
|
|
"""Show search results with modern pagination and selection."""
|
|
# Prepare results for SearchResultsView
|
|
results = []
|
|
for player in players:
|
|
results.append({
|
|
'name': player.name,
|
|
'detail': f"{player.primary_position} • WARA: {player.wara:.1f}",
|
|
'player_obj': player
|
|
})
|
|
|
|
async def handle_selection(interaction: discord.Interaction, result: dict):
|
|
"""Handle player selection from search results."""
|
|
selected_player = result['player_obj']
|
|
await self._show_player_details(interaction, selected_player, season)
|
|
|
|
# Create search results view with selection
|
|
view = SearchResultsView(
|
|
results=results,
|
|
search_term=search_term,
|
|
user_id=interaction.user.id,
|
|
selection_callback=handle_selection,
|
|
results_per_page=10
|
|
)
|
|
|
|
# Send with first page
|
|
embed = view.get_current_embed()
|
|
await interaction.followup.send(embed=embed, view=view)
|
|
|
|
async def _show_player_selection(
|
|
self,
|
|
interaction: discord.Interaction,
|
|
players: List[Player],
|
|
season: int
|
|
):
|
|
"""Show player selection dropdown for multiple exact matches."""
|
|
async def handle_player_choice(interaction: discord.Interaction, player: Player):
|
|
"""Handle player selection."""
|
|
await self._show_player_details(interaction, player, season)
|
|
|
|
# Create player selection view
|
|
view = PlayerSelectionView(
|
|
players=players,
|
|
user_id=interaction.user.id,
|
|
callback=handle_player_choice
|
|
)
|
|
|
|
# Setup the select options
|
|
view.setup_options()
|
|
|
|
# Create embed for selection
|
|
embed = EmbedTemplate.info(
|
|
title="Multiple Players Found",
|
|
description=f"Found {len(players)} players matching your search. Please select one:"
|
|
)
|
|
|
|
await interaction.followup.send(embed=embed, view=view)
|
|
|
|
async def _show_player_details(
|
|
self,
|
|
interaction: discord.Interaction,
|
|
player: Player,
|
|
season: int
|
|
):
|
|
"""Show detailed player information with action buttons."""
|
|
# Get full player data (API already includes team information)
|
|
player_with_team = await player_service.get_player(player.id)
|
|
if player_with_team is None:
|
|
player_with_team = player
|
|
|
|
# Create comprehensive player embed
|
|
embed = self._create_enhanced_player_embed(player_with_team, season)
|
|
|
|
# Create detailed info view with action buttons
|
|
async def refresh_player_data(interaction: discord.Interaction) -> discord.Embed:
|
|
"""Refresh player data."""
|
|
updated_player = await player_service.get_player(player.id)
|
|
return self._create_enhanced_player_embed(updated_player or player, season)
|
|
|
|
async def show_more_details(interaction: discord.Interaction):
|
|
"""Show additional player details."""
|
|
# Create detailed stats embed
|
|
stats_embed = self._create_player_stats_embed(player_with_team, season)
|
|
await interaction.response.send_message(embed=stats_embed, ephemeral=True)
|
|
|
|
view = DetailedInfoView(
|
|
embed=embed,
|
|
user_id=interaction.user.id,
|
|
show_refresh=True,
|
|
show_details=True,
|
|
refresh_callback=refresh_player_data,
|
|
details_callback=show_more_details
|
|
)
|
|
|
|
if interaction.response.is_done():
|
|
await interaction.followup.send(embed=embed, view=view)
|
|
else:
|
|
await interaction.response.send_message(embed=embed, view=view)
|
|
|
|
def _create_enhanced_player_embed(self, player: Player, season: int) -> discord.Embed:
|
|
"""Create enhanced player embed with additional information."""
|
|
# Get team info if available
|
|
team_abbrev = None
|
|
team_name = None
|
|
team_color = None
|
|
|
|
if hasattr(player, 'team') and player.team:
|
|
team_abbrev = player.team.abbrev
|
|
team_name = player.team.sname
|
|
team_color = getattr(player.team, 'color', None)
|
|
|
|
# Create base embed
|
|
embed = SBAEmbedTemplate.player_card(
|
|
player_name=player.name,
|
|
position=player.primary_position,
|
|
team_abbrev=team_abbrev,
|
|
team_name=team_name,
|
|
wara=player.wara,
|
|
season=season,
|
|
player_image=getattr(player, 'image', None),
|
|
team_color=team_color
|
|
)
|
|
|
|
# Add additional fields
|
|
additional_fields = []
|
|
|
|
# All positions if multiple
|
|
if len(player.positions) > 1:
|
|
additional_fields.append({
|
|
'name': 'All Positions',
|
|
'value': ', '.join(player.positions),
|
|
'inline': True
|
|
})
|
|
|
|
# Add salary info if available
|
|
if hasattr(player, 'salary') and player.salary:
|
|
additional_fields.append({
|
|
'name': 'Salary',
|
|
'value': f"${player.salary:,}",
|
|
'inline': True
|
|
})
|
|
|
|
# Add contract info if available
|
|
if hasattr(player, 'contract_years') and player.contract_years:
|
|
additional_fields.append({
|
|
'name': 'Contract',
|
|
'value': f"{player.contract_years} years",
|
|
'inline': True
|
|
})
|
|
|
|
# Add the additional fields to embed
|
|
for field in additional_fields:
|
|
embed.add_field(
|
|
name=field['name'],
|
|
value=field['value'],
|
|
inline=field['inline']
|
|
)
|
|
|
|
# Add footer with player ID
|
|
embed.set_footer(text=f"Player ID: {player.id} • Use buttons below for more options")
|
|
|
|
return embed
|
|
|
|
def _create_player_stats_embed(self, player: Player, season: int) -> discord.Embed:
|
|
"""Create detailed player statistics embed."""
|
|
embed = EmbedTemplate.create_base_embed(
|
|
title=f"📊 {player.name} - Detailed Stats",
|
|
description=f"Season {season} Statistics",
|
|
color=EmbedColors.INFO
|
|
)
|
|
|
|
# Add batting stats if available
|
|
if hasattr(player, 'batting_avg') and player.batting_avg is not None:
|
|
embed.add_field(
|
|
name="Batting Average",
|
|
value=f"{player.batting_avg:.3f}",
|
|
inline=True
|
|
)
|
|
|
|
if hasattr(player, 'home_runs') and player.home_runs is not None:
|
|
embed.add_field(
|
|
name="Home Runs",
|
|
value=str(player.home_runs),
|
|
inline=True
|
|
)
|
|
|
|
if hasattr(player, 'rbi') and player.rbi is not None:
|
|
embed.add_field(
|
|
name="RBI",
|
|
value=str(player.rbi),
|
|
inline=True
|
|
)
|
|
|
|
# Add pitching stats if available
|
|
if hasattr(player, 'era') and player.era is not None:
|
|
embed.add_field(
|
|
name="ERA",
|
|
value=f"{player.era:.2f}",
|
|
inline=True
|
|
)
|
|
|
|
if hasattr(player, 'wins') and player.wins is not None:
|
|
embed.add_field(
|
|
name="Wins",
|
|
value=str(player.wins),
|
|
inline=True
|
|
)
|
|
|
|
if hasattr(player, 'strikeouts') and player.strikeouts is not None:
|
|
embed.add_field(
|
|
name="Strikeouts",
|
|
value=str(player.strikeouts),
|
|
inline=True
|
|
)
|
|
|
|
return embed
|
|
|
|
@discord.app_commands.command(
|
|
name="player-search-modal",
|
|
description="Advanced player search using modal form"
|
|
)
|
|
@logged_command("/player-search-modal")
|
|
async def player_search_modal(self, interaction: discord.Interaction):
|
|
"""Demonstrate modal-based player search."""
|
|
modal = PlayerSearchModal()
|
|
await interaction.response.send_modal(modal)
|
|
|
|
# Wait for modal completion
|
|
await modal.wait()
|
|
|
|
if modal.is_submitted and modal.result:
|
|
search_criteria = modal.result
|
|
|
|
# Perform search based on criteria
|
|
players = await player_service.get_players_by_name(
|
|
search_criteria['name'],
|
|
search_criteria['season'] or get_config().sba_current_season
|
|
)
|
|
|
|
if players:
|
|
# Show results using our views
|
|
if len(players) == 1:
|
|
await self._show_player_details(
|
|
interaction,
|
|
players[0],
|
|
search_criteria['season'] or get_config().sba_current_season
|
|
)
|
|
else:
|
|
await self._show_player_selection(
|
|
interaction,
|
|
players,
|
|
search_criteria['season'] or get_config().sba_current_season
|
|
)
|
|
else:
|
|
embed = EmbedTemplate.warning(
|
|
title="No Results",
|
|
description=f"No players found matching your search criteria."
|
|
)
|
|
await interaction.followup.send(embed=embed, ephemeral=True)
|
|
|
|
|
|
async def setup(bot: commands.Bot):
|
|
"""Load the enhanced player commands cog."""
|
|
await bot.add_cog(EnhancedPlayerCommands(bot)) |