From 96ccc6444ebbe5a8bd233201801593f5fac8d6d0 Mon Sep 17 00:00:00 2001 From: adrunkhuman <16039109+adrunkhuman@users.noreply.github.com> Date: Sun, 22 Mar 2026 02:22:55 +0100 Subject: [PATCH 1/2] fix: avoid cooldown on failed result calculation --- temp-pr-1.md | 7 +++++++ tests/test_admin_commands.py | 22 ++++++++++++++++++++++ typer_bot/commands/admin_commands.py | 4 ++-- 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 temp-pr-1.md diff --git a/temp-pr-1.md b/temp-pr-1.md new file mode 100644 index 0000000..419e4a9 --- /dev/null +++ b/temp-pr-1.md @@ -0,0 +1,7 @@ +## Summary +- Move the `/admin results calculate` cooldown write to the successful scoring path so validation failures do not throttle admins. +- Add a regression test covering the failed-calculation retry case. + +## Testing +- `uv run pytest tests/test_admin_commands.py -k "results_calculate"` +- `uv run ruff check typer_bot/commands/admin_commands.py tests/test_admin_commands.py` diff --git a/tests/test_admin_commands.py b/tests/test_admin_commands.py index 08018e9..105a13a 100644 --- a/tests/test_admin_commands.py +++ b/tests/test_admin_commands.py @@ -300,6 +300,28 @@ async def test_results_calculate_records_cooldown_and_calls_followup_steps( mock_interaction_admin, score_result ) + @pytest.mark.asyncio + async def test_results_calculate_does_not_record_cooldown_when_scoring_fails( + self, admin_cog, mock_interaction_admin, monkeypatch + ): + """Validation failures should not throttle a retry after the admin fixes results state.""" + fixture = {"id": 7, "week_number": 7, "games": ["A - B"], "deadline": datetime.now(UTC)} + + monkeypatch.setattr(admin_cog.db, "get_open_fixtures", AsyncMock(return_value=[fixture])) + admin_cog.service.calculate_fixture_scores = AsyncMock( + side_effect=ValueError("No results entered") + ) + admin_cog._create_backup = AsyncMock() + admin_cog._post_calculation_to_channel = AsyncMock() + + await admin_cog.results_calculate.callback(admin_cog, mock_interaction_admin, None) + + user_id = str(mock_interaction_admin.user.id) + assert admin_cog.workflow_state.get_calculate_cooldown(user_id) is None + assert mock_interaction_admin.response_sent[-1]["content"] == "No results entered" + admin_cog._create_backup.assert_not_called() + admin_cog._post_calculation_to_channel.assert_not_called() + class TestResultsPostFlow: @pytest.fixture diff --git a/typer_bot/commands/admin_commands.py b/typer_bot/commands/admin_commands.py index 5823167..c49a218 100644 --- a/typer_bot/commands/admin_commands.py +++ b/typer_bot/commands/admin_commands.py @@ -373,14 +373,14 @@ async def results_calculate(self, interaction: discord.Interaction, week: int | if not fixture: return - self.workflow_state.record_calculate_cooldown(user_id, current_time=current_time) - try: score_result = await self.service.calculate_fixture_scores(fixture["id"]) except ValueError as exc: await interaction.response.send_message(str(exc), ephemeral=True) return + self.workflow_state.record_calculate_cooldown(user_id, current_time=current_time) + await self._create_backup() await self._post_calculation_to_channel(interaction, score_result) From ac0f625f76369506083f794f91c132d7fbc491ed Mon Sep 17 00:00:00 2001 From: adrunkhuman <16039109+adrunkhuman@users.noreply.github.com> Date: Sun, 22 Mar 2026 02:23:13 +0100 Subject: [PATCH 2/2] chore: remove temporary PR notes --- temp-pr-1.md | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 temp-pr-1.md diff --git a/temp-pr-1.md b/temp-pr-1.md deleted file mode 100644 index 419e4a9..0000000 --- a/temp-pr-1.md +++ /dev/null @@ -1,7 +0,0 @@ -## Summary -- Move the `/admin results calculate` cooldown write to the successful scoring path so validation failures do not throttle admins. -- Add a regression test covering the failed-calculation retry case. - -## Testing -- `uv run pytest tests/test_admin_commands.py -k "results_calculate"` -- `uv run ruff check typer_bot/commands/admin_commands.py tests/test_admin_commands.py`