Compare commits
1 Commits
8e984d1d07
...
4e75656225
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e75656225 |
@ -61,7 +61,7 @@ class ScorecardTracker:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save scorecard data: {e}")
|
||||
|
||||
def publish_scorecard(
|
||||
async def publish_scorecard(
|
||||
self, text_channel_id: int, sheet_url: str, publisher_id: int
|
||||
) -> None:
|
||||
"""
|
||||
@ -82,7 +82,7 @@ class ScorecardTracker:
|
||||
self.save_data()
|
||||
logger.info(f"Published scorecard to channel {text_channel_id}: {sheet_url}")
|
||||
|
||||
def unpublish_scorecard(self, text_channel_id: int) -> bool:
|
||||
async def unpublish_scorecard(self, text_channel_id: int) -> bool:
|
||||
"""
|
||||
Remove scorecard from a text channel.
|
||||
|
||||
@ -103,7 +103,7 @@ class ScorecardTracker:
|
||||
|
||||
return False
|
||||
|
||||
def get_scorecard(self, text_channel_id: int) -> Optional[str]:
|
||||
async def get_scorecard(self, text_channel_id: int) -> Optional[str]:
|
||||
"""
|
||||
Get scorecard URL for a text channel.
|
||||
|
||||
@ -118,7 +118,7 @@ class ScorecardTracker:
|
||||
scorecard_data = scorecards.get(str(text_channel_id))
|
||||
return scorecard_data["sheet_url"] if scorecard_data else None
|
||||
|
||||
def get_all_scorecards(self) -> List[Tuple[int, str]]:
|
||||
async def get_all_scorecards(self) -> List[Tuple[int, str]]:
|
||||
"""
|
||||
Get all published scorecards.
|
||||
|
||||
@ -132,7 +132,7 @@ class ScorecardTracker:
|
||||
for channel_id, data in scorecards.items()
|
||||
]
|
||||
|
||||
def update_timestamp(self, text_channel_id: int) -> None:
|
||||
async def update_timestamp(self, text_channel_id: int) -> None:
|
||||
"""
|
||||
Update the last_updated timestamp for a scorecard.
|
||||
|
||||
@ -146,7 +146,7 @@ class ScorecardTracker:
|
||||
scorecards[channel_key]["last_updated"] = datetime.now(UTC).isoformat()
|
||||
self.save_data()
|
||||
|
||||
def cleanup_stale_entries(self, valid_channel_ids: List[int]) -> int:
|
||||
async def cleanup_stale_entries(self, valid_channel_ids: List[int]) -> int:
|
||||
"""
|
||||
Remove tracking entries for text channels that no longer exist.
|
||||
|
||||
|
||||
@ -128,7 +128,7 @@ class VoiceChannelCleanupService:
|
||||
if channel_data and channel_data.get("text_channel_id"):
|
||||
try:
|
||||
text_channel_id_int = int(channel_data["text_channel_id"])
|
||||
was_unpublished = self.scorecard_tracker.unpublish_scorecard(
|
||||
was_unpublished = await self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
)
|
||||
if was_unpublished:
|
||||
@ -218,8 +218,10 @@ class VoiceChannelCleanupService:
|
||||
if text_channel_id:
|
||||
try:
|
||||
text_channel_id_int = int(text_channel_id)
|
||||
was_unpublished = self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
was_unpublished = (
|
||||
await self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
)
|
||||
)
|
||||
if was_unpublished:
|
||||
self.logger.info(
|
||||
@ -244,8 +246,10 @@ class VoiceChannelCleanupService:
|
||||
if text_channel_id:
|
||||
try:
|
||||
text_channel_id_int = int(text_channel_id)
|
||||
was_unpublished = self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
was_unpublished = (
|
||||
await self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
)
|
||||
)
|
||||
if was_unpublished:
|
||||
self.logger.info(
|
||||
@ -330,7 +334,7 @@ class VoiceChannelCleanupService:
|
||||
if text_channel_id:
|
||||
try:
|
||||
text_channel_id_int = int(text_channel_id)
|
||||
was_unpublished = self.scorecard_tracker.unpublish_scorecard(
|
||||
was_unpublished = await self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
)
|
||||
if was_unpublished:
|
||||
@ -358,7 +362,7 @@ class VoiceChannelCleanupService:
|
||||
if text_channel_id:
|
||||
try:
|
||||
text_channel_id_int = int(text_channel_id)
|
||||
was_unpublished = self.scorecard_tracker.unpublish_scorecard(
|
||||
was_unpublished = await self.scorecard_tracker.unpublish_scorecard(
|
||||
text_channel_id_int
|
||||
)
|
||||
if was_unpublished:
|
||||
|
||||
@ -24,7 +24,8 @@ from utils.scorebug_helpers import create_scorebug_embed, create_team_progress_b
|
||||
class TestScorecardTrackerFreshReads:
|
||||
"""Tests that ScorecardTracker reads fresh data from disk (fix for #40)."""
|
||||
|
||||
def test_get_all_scorecards_reads_fresh_data(self, tmp_path):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_all_scorecards_reads_fresh_data(self, tmp_path):
|
||||
"""get_all_scorecards() should pick up scorecards written by another process.
|
||||
|
||||
Simulates the background task having a stale tracker instance while
|
||||
@ -34,7 +35,7 @@ class TestScorecardTrackerFreshReads:
|
||||
data_file.write_text(json.dumps({"scorecards": {}}))
|
||||
|
||||
tracker = ScorecardTracker(data_file=str(data_file))
|
||||
assert tracker.get_all_scorecards() == []
|
||||
assert await tracker.get_all_scorecards() == []
|
||||
|
||||
# Another process writes a scorecard to the same file
|
||||
new_data = {
|
||||
@ -51,17 +52,18 @@ class TestScorecardTrackerFreshReads:
|
||||
data_file.write_text(json.dumps(new_data))
|
||||
|
||||
# Should see the new scorecard without restart
|
||||
result = tracker.get_all_scorecards()
|
||||
result = await tracker.get_all_scorecards()
|
||||
assert len(result) == 1
|
||||
assert result[0] == (111, "https://docs.google.com/spreadsheets/d/abc123")
|
||||
|
||||
def test_get_scorecard_reads_fresh_data(self, tmp_path):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_scorecard_reads_fresh_data(self, tmp_path):
|
||||
"""get_scorecard() should pick up a scorecard written by another process."""
|
||||
data_file = tmp_path / "scorecards.json"
|
||||
data_file.write_text(json.dumps({"scorecards": {}}))
|
||||
|
||||
tracker = ScorecardTracker(data_file=str(data_file))
|
||||
assert tracker.get_scorecard(222) is None
|
||||
assert await tracker.get_scorecard(222) is None
|
||||
|
||||
# Another process writes a scorecard
|
||||
new_data = {
|
||||
@ -79,7 +81,7 @@ class TestScorecardTrackerFreshReads:
|
||||
|
||||
# Should see the new scorecard
|
||||
assert (
|
||||
tracker.get_scorecard(222)
|
||||
await tracker.get_scorecard(222)
|
||||
== "https://docs.google.com/spreadsheets/d/xyz789"
|
||||
)
|
||||
|
||||
|
||||
@ -328,7 +328,6 @@ class TradeAcceptanceView(discord.ui.View):
|
||||
def __init__(self, builder: TradeBuilder):
|
||||
super().__init__(timeout=3600.0) # 1 hour timeout
|
||||
self.builder = builder
|
||||
self._checked_team: Optional[Team] = None
|
||||
|
||||
async def _get_user_team(self, interaction: discord.Interaction) -> Optional[Team]:
|
||||
"""Get the team owned by the interacting user."""
|
||||
@ -354,7 +353,6 @@ class TradeAcceptanceView(discord.ui.View):
|
||||
)
|
||||
return False
|
||||
|
||||
self._checked_team = user_team
|
||||
return True
|
||||
|
||||
async def on_timeout(self) -> None:
|
||||
@ -368,7 +366,7 @@ class TradeAcceptanceView(discord.ui.View):
|
||||
self, interaction: discord.Interaction, button: discord.ui.Button
|
||||
):
|
||||
"""Handle accept button click."""
|
||||
user_team = self._checked_team
|
||||
user_team = await self._get_user_team(interaction)
|
||||
if not user_team:
|
||||
return
|
||||
|
||||
@ -403,7 +401,7 @@ class TradeAcceptanceView(discord.ui.View):
|
||||
self, interaction: discord.Interaction, button: discord.ui.Button
|
||||
):
|
||||
"""Handle reject button click - moves trade back to DRAFT."""
|
||||
user_team = self._checked_team
|
||||
user_team = await self._get_user_team(interaction)
|
||||
if not user_team:
|
||||
return
|
||||
|
||||
@ -710,10 +708,10 @@ async def create_trade_embed(builder: TradeBuilder) -> discord.Embed:
|
||||
Returns:
|
||||
Discord embed with current trade state
|
||||
"""
|
||||
validation = await builder.validate_trade()
|
||||
if builder.is_empty:
|
||||
color = EmbedColors.SECONDARY
|
||||
else:
|
||||
validation = await builder.validate_trade()
|
||||
color = EmbedColors.SUCCESS if validation.is_legal else EmbedColors.WARNING
|
||||
|
||||
embed = EmbedTemplate.create_base_embed(
|
||||
@ -768,6 +766,7 @@ async def create_trade_embed(builder: TradeBuilder) -> discord.Embed:
|
||||
inline=False,
|
||||
)
|
||||
|
||||
validation = await builder.validate_trade()
|
||||
if validation.is_legal:
|
||||
status_text = "Trade appears legal"
|
||||
else:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user