CLAUDE: Fix draft channel configuration not persisting

Root cause: Field naming mismatch between bot model and database schema.

The database stores channel IDs in columns named 'result_channel' and
'ping_channel', but the bot's DraftData model incorrectly used
'result_channel_id' and 'ping_channel_id'.

Additionally, the draft data PATCH endpoint requires query parameters
instead of JSON body (like player, game, transaction, and injury endpoints).

Changes:
- models/draft_data.py: Renamed fields to match database schema
  - result_channel_id → result_channel
  - ping_channel_id → ping_channel
- services/draft_service.py: Added use_query_params=True to PATCH calls
- views/draft_views.py: Updated embed to use correct field names
- tasks/draft_monitor.py: Updated channel lookups to use correct field names
- tests/test_models.py: Updated test assertions to match new field names

This fixes:
- Channel configuration now saves correctly via /draft-admin channels
- Ping channel settings persist across bot restarts
- Result channel settings persist across bot restarts
- All draft data updates work properly

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2025-10-24 22:52:57 -05:00
parent 005c031062
commit 7370fa7006
5 changed files with 27 additions and 26 deletions

View File

@ -16,14 +16,14 @@ class DraftData(SBABaseModel):
currentpick: int = Field(0, description="Current pick number in progress") currentpick: int = Field(0, description="Current pick number in progress")
timer: bool = Field(False, description="Whether draft timer is active") timer: bool = Field(False, description="Whether draft timer is active")
pick_deadline: Optional[datetime] = Field(None, description="Deadline for current pick") pick_deadline: Optional[datetime] = Field(None, description="Deadline for current pick")
result_channel_id: Optional[int] = Field(None, description="Discord channel ID for draft results") result_channel: Optional[int] = Field(None, description="Discord channel ID for draft results")
ping_channel_id: Optional[int] = Field(None, description="Discord channel ID for draft pings") ping_channel: Optional[int] = Field(None, description="Discord channel ID for draft pings")
pick_minutes: int = Field(1, description="Minutes allowed per pick") pick_minutes: int = Field(1, description="Minutes allowed per pick")
@field_validator("result_channel_id", "ping_channel_id", mode="before") @field_validator("result_channel", "ping_channel", mode="before")
@classmethod @classmethod
def cast_channel_ids_to_int(cls, v): def cast_channel_ids_to_int(cls, v):
"""Ensure channel IDs are integers.""" """Ensure channel IDs are integers (database stores as string)."""
if v is None: if v is None:
return None return None
if isinstance(v, str): if isinstance(v, str):

View File

@ -78,7 +78,8 @@ class DraftService(BaseService[DraftData]):
Updated DraftData instance or None if update failed Updated DraftData instance or None if update failed
""" """
try: try:
updated = await self.patch(draft_id, updates) # Draft data API expects query parameters for PATCH requests
updated = await self.patch(draft_id, updates, use_query_params=True)
if updated: if updated:
logger.info(f"Updated draft data: {updates}") logger.info(f"Updated draft data: {updates}")
@ -277,9 +278,9 @@ class DraftService(BaseService[DraftData]):
try: try:
updates = {} updates = {}
if ping_channel_id is not None: if ping_channel_id is not None:
updates['ping_channel_id'] = ping_channel_id updates['ping_channel'] = ping_channel_id
if result_channel_id is not None: if result_channel_id is not None:
updates['result_channel_id'] = result_channel_id updates['result_channel'] = result_channel_id
if not updates: if not updates:
logger.warning("No channel updates provided") logger.warning("No channel updates provided")

View File

@ -162,9 +162,9 @@ class DraftMonitorTask:
config = get_config() config = get_config()
# Get ping channel # Get ping channel
ping_channel = guild.get_channel(draft_data.ping_channel_id) ping_channel = guild.get_channel(draft_data.ping_channel)
if not ping_channel: if not ping_channel:
self.logger.error(f"Could not find ping channel {draft_data.ping_channel_id}") self.logger.error(f"Could not find ping channel {draft_data.ping_channel}")
return return
# Get team's draft list # Get team's draft list
@ -309,7 +309,7 @@ class DraftMonitorTask:
if not guild: if not guild:
return return
ping_channel = guild.get_channel(draft_data.ping_channel_id) ping_channel = guild.get_channel(draft_data.ping_channel)
if not ping_channel: if not ping_channel:
return return

View File

@ -373,33 +373,33 @@ class TestDraftDataModel:
def test_draft_data_creation(self): def test_draft_data_creation(self):
"""Test draft data creation.""" """Test draft data creation."""
draft_data = DraftData( draft_data = DraftData(
result_channel_id=123456789, result_channel=123456789,
ping_channel_id=987654321, ping_channel=987654321,
pick_minutes=10 pick_minutes=10
) )
assert draft_data.result_channel_id == 123456789 assert draft_data.result_channel == 123456789
assert draft_data.ping_channel_id == 987654321 assert draft_data.ping_channel == 987654321
assert draft_data.pick_minutes == 10 assert draft_data.pick_minutes == 10
def test_draft_data_properties(self): def test_draft_data_properties(self):
"""Test draft data properties.""" """Test draft data properties."""
# Inactive draft # Inactive draft
draft_data = DraftData( draft_data = DraftData(
result_channel_id=123, result_channel=123,
ping_channel_id=456, ping_channel=456,
timer=False timer=False
) )
assert draft_data.is_draft_active is False assert draft_data.is_draft_active is False
# Active draft # Active draft
active_draft = DraftData( active_draft = DraftData(
result_channel_id=123, result_channel=123,
ping_channel_id=456, ping_channel=456,
timer=True timer=True
) )
assert active_draft.is_draft_active is True assert active_draft.is_draft_active is True

View File

@ -429,14 +429,14 @@ async def create_admin_draft_info_embed(
) )
# Channels # Channels
ping_channel_value = f"<#{draft_data.ping_channel_id}>" if draft_data.ping_channel_id else "Not configured" ping_channel_value = f"<#{draft_data.ping_channel}>" if draft_data.ping_channel else "Not configured"
embed.add_field( embed.add_field(
name="Ping Channel", name="Ping Channel",
value=ping_channel_value, value=ping_channel_value,
inline=True inline=True
) )
result_channel_value = f"<#{draft_data.result_channel_id}>" if draft_data.result_channel_id else "Not configured" result_channel_value = f"<#{draft_data.result_channel}>" if draft_data.result_channel else "Not configured"
embed.add_field( embed.add_field(
name="Result Channel", name="Result Channel",
value=result_channel_value, value=result_channel_value,