Pārlūkot izejas kodu

fix: clean up check-in replies and keyboard

AI-Co-Authored-By: Codex
chendeben 2 mēneši atpakaļ
vecāks
revīzija
5bed60c256

+ 3 - 2
tests/test_point_settings.py

@@ -7,7 +7,7 @@ import pytest
 from pyrogram.types import ReplyKeyboardMarkup, ReplyKeyboardRemove
 
 
-async def test_enabling_checkin_button_sends_persistent_keyboard(
+async def test_enabling_checkin_button_sends_hideable_keyboard(
     app_modules, monkeypatch
 ):
     points = app_modules.load("wbb.utils.dbpoints")
@@ -29,8 +29,9 @@ async def test_enabling_checkin_button_sends_persistent_keyboard(
     assert chat_id == -100
     assert "签到快捷按钮已开启" in text
     assert isinstance(reply_markup, ReplyKeyboardMarkup)
-    assert reply_markup.is_persistent is True
+    assert reply_markup.is_persistent is False
     assert reply_markup.resize_keyboard is True
+    assert reply_markup.one_time_keyboard is True
     assert reply_markup.keyboard[0][0].text == "签到"
 
 

+ 98 - 0
tests/test_points_commands.py

@@ -0,0 +1,98 @@
+from __future__ import annotations
+
+import sys
+import types
+from types import SimpleNamespace
+from unittest.mock import AsyncMock
+
+import pytest
+
+
+@pytest.fixture
+def points_module(app_modules, monkeypatch):
+    permissions = types.ModuleType("wbb.core.decorators.permissions")
+
+    def admins_only(*_args, **_kwargs):
+        return lambda function: function
+
+    permissions.adminsOnly = admins_only
+    monkeypatch.setitem(
+        sys.modules, "wbb.core.decorators.permissions", permissions
+    )
+    module = app_modules.load("wbb.modules.points")
+    return module
+
+
+def _checkin_message() -> SimpleNamespace:
+    response = SimpleNamespace(
+        chat=SimpleNamespace(id=-100, type=SimpleNamespace(value="supergroup")),
+        id=11,
+    )
+    return SimpleNamespace(
+        chat=SimpleNamespace(id=-100, type=SimpleNamespace(value="supergroup")),
+        id=10,
+        from_user=SimpleNamespace(
+            id=20,
+            username="customer",
+            first_name="顾客",
+            last_name=None,
+        ),
+        reply_text=AsyncMock(return_value=response),
+    )
+
+
+@pytest.mark.parametrize(
+    ("created", "expected_text"),
+    [
+        (True, "签到成功"),
+        (False, "已经签到过"),
+    ],
+)
+async def test_checkin_schedules_user_and_bot_messages_for_cleanup(
+    points_module, monkeypatch, created, expected_text
+):
+    message = _checkin_message()
+    account = {"balance": 10}
+    cleanup = []
+    monkeypatch.setattr(
+        points_module,
+        "award_checkin",
+        AsyncMock(return_value=(account, created)),
+    )
+    monkeypatch.setattr(
+        points_module,
+        "get_point_rules",
+        AsyncMock(return_value={"checkin_points": 10}),
+    )
+    monkeypatch.setattr(
+        points_module,
+        "schedule_group_cleanup",
+        lambda *messages: cleanup.extend(messages),
+    )
+
+    response = await points_module.points_checkin_command(None, message)
+
+    assert expected_text in message.reply_text.await_args.args[0]
+    assert cleanup == [message, response]
+
+
+async def test_checkin_error_schedules_user_and_bot_messages_for_cleanup(
+    points_module, monkeypatch
+):
+    message = _checkin_message()
+    cleanup = []
+    monkeypatch.setattr(
+        points_module,
+        "award_checkin",
+        AsyncMock(side_effect=points_module.PointsError("签到暂不可用")),
+    )
+    monkeypatch.setattr(
+        points_module,
+        "schedule_group_cleanup",
+        lambda *messages: cleanup.extend(messages),
+    )
+
+    response = await points_module.points_checkin_command(None, message)
+
+    assert message.reply_text.await_args.args == ("签到暂不可用",)
+    assert cleanup == [message, response]

+ 14 - 5
wbb/modules/points.py

@@ -11,6 +11,7 @@ from pyrogram.types import Message, User
 from wbb import app, log
 from wbb.core.decorators.permissions import adminsOnly
 from wbb.services.member_identity import non_mention_account_name
+from wbb.services.message_cleanup import schedule_group_cleanup
 from wbb.services.point_settings import (
     CHECKIN_BUTTON_TEXT,
     apply_point_rules,
@@ -89,6 +90,12 @@ def _message_content(message: Message) -> str:
     return f"media:{unique_id}" if unique_id else ""
 
 
+async def _reply_checkin(message: Message, text: str) -> Message:
+    response = await message.reply_text(text)
+    schedule_group_cleanup(message, response)
+    return response
+
+
 async def _resolve_target(message: Message, raw: str | None = None) -> User | None:
     if message.reply_to_message and message.reply_to_message.from_user:
         return message.reply_to_message.from_user
@@ -131,7 +138,7 @@ async def points_balance_command(_, message: Message):
 )
 async def points_checkin_command(_, message: Message):
     if not message.from_user:
-        return await message.reply_text("匿名管理员无法签到。")
+        return await _reply_checkin(message, "匿名管理员无法签到。")
     try:
         account, created = await award_checkin(
             chat_id=message.chat.id,
@@ -141,15 +148,17 @@ async def points_checkin_command(_, message: Message):
             display_name=_user_display_name(message.from_user),
         )
     except PointsError as exc:
-        return await message.reply_text(str(exc))
+        return await _reply_checkin(message, str(exc))
     if not created:
-        return await message.reply_text(
+        return await _reply_checkin(
+            message,
             f"你今天已经签到过了,当前余额:{int(account['balance'])}。"
         )
     rules = await get_point_rules(message.chat.id)
-    return await message.reply_text(
+    return await _reply_checkin(
+        message,
         f"签到成功:+{rules['checkin_points']} 积分,"
-        f"当前余额:{int(account['balance'])}。"
+        f"当前余额:{int(account['balance'])}。",
     )
 
 

+ 2 - 1
wbb/services/point_settings.py

@@ -26,8 +26,9 @@ def checkin_button_active(rules: dict[str, Any]) -> bool:
 def checkin_keyboard() -> ReplyKeyboardMarkup:
     return ReplyKeyboardMarkup(
         [[KeyboardButton(CHECKIN_BUTTON_TEXT)]],
-        is_persistent=True,
+        is_persistent=False,
         resize_keyboard=True,
+        one_time_keyboard=True,
         selective=False,
         placeholder="输入消息",
     )