Skip to content

Commit b088ac3

Browse files
committed
refactor(request_handler): 提取审批回复文本解析
1 parent 02bff7e commit b088ac3

3 files changed

Lines changed: 79 additions & 13 deletions

File tree

src/plugins/request_handler/__init__.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
from src.features.cmd_perm.metadata_text import SCENE_GROUP, SCENE_PRIVATE, join_usage, usage_line
3030
from src.foundation.config import BotConfig, GroupConfig, UserConfig, get_bot_admins, user_is_bot_admin
3131
from src.foundation.paths import plugin_data_dir
32+
from src.plugins.request_handler.approval_reply_text import (
33+
classify_approval_reply_text,
34+
extract_approval_reply_text_from_body,
35+
)
3236
from src.plugins.request_handler.config import Config
3337
from src.plugins.request_handler.texts import (
3438
APPROVE_ALL_FRIENDS_COMMAND,
@@ -540,18 +544,6 @@ def clear_quick_approve_state(bot_key: str, kind: str, target_id: str) -> None:
540544
if _approval_notice_dirty:
541545
save_json(APPROVAL_NOTICE_FILE, approval_notice_map)
542546

543-
# 引用审批通知时允许的正文(小写比较);空字符串表示仅引用不打字(视为同意)
544-
_APPROVE_REPLY_TEXT = frozenset({"", "同意", "好", "yes", "y", "ok"})
545-
_REJECT_REPLY_TEXT = frozenset({"拒绝", "不要", "否", "no", "n"})
546-
547-
548-
def classify_approval_reply_text(text: str) -> str | None:
549-
if text in _APPROVE_REPLY_TEXT:
550-
return "approve"
551-
if text in _REJECT_REPLY_TEXT:
552-
return "reject"
553-
return None
554-
555547

556548
def rows_from_doubt_friends_api(result: object) -> list[dict]:
557549
if isinstance(result, list):
@@ -898,7 +890,10 @@ async def handle_approval_reply(bot: Bot, event: PrivateMessageEvent):
898890
meta = approval_notice_map.get(bot_key, {}).get(mid)
899891
if not meta:
900892
return
901-
text = event.get_plaintext().strip().lower()
893+
quoted_body = None
894+
if event.reply and event.reply.message is not None:
895+
quoted_body = event.reply.message.extract_plain_text()
896+
text = extract_approval_reply_text_from_body(event.get_plaintext() or "", quoted_body)
902897
action = classify_approval_reply_text(text)
903898
if action is None:
904899
await approval_reply_cmd.finish("引用审批消息后,正文须为:同意 / 好 / 留空,或 拒绝 / 不要 / 否。")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from __future__ import annotations
2+
3+
_INVISIBLE_CHARS = ("\u200b", "\u200c", "\u200d", "\ufeff", "\u2060")
4+
5+
_APPROVE_REPLY_TEXT = frozenset({"同意", "好", "yes", "y", "ok", "留空"})
6+
_REJECT_REPLY_TEXT = frozenset({"拒绝", "不要", "否", "no", "n"})
7+
8+
9+
def normalize_approval_reply_text(text: str) -> str:
10+
for ch in _INVISIBLE_CHARS:
11+
text = text.replace(ch, "")
12+
return text.strip().lower()
13+
14+
15+
def extract_approval_reply_text_from_body(body: str, quoted_body: str | None) -> str:
16+
normalized = normalize_approval_reply_text(body)
17+
if quoted_body is None:
18+
return normalized
19+
quoted = normalize_approval_reply_text(quoted_body)
20+
if normalized == quoted:
21+
return ""
22+
return normalized
23+
24+
25+
def classify_approval_reply_text(text: str) -> str | None:
26+
normalized = normalize_approval_reply_text(text)
27+
if not normalized:
28+
return "approve"
29+
if normalized in _APPROVE_REPLY_TEXT:
30+
return "approve"
31+
if normalized in _REJECT_REPLY_TEXT:
32+
return "reject"
33+
return None
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from src.plugins.request_handler.approval_reply_text import (
2+
classify_approval_reply_text,
3+
extract_approval_reply_text_from_body,
4+
)
5+
6+
7+
def test_empty_body_classifies_as_approve() -> None:
8+
assert classify_approval_reply_text("") == "approve"
9+
assert classify_approval_reply_text(" ") == "approve"
10+
assert classify_approval_reply_text("\u200b") == "approve"
11+
12+
13+
def test_explicit_approve_and_reject_keywords() -> None:
14+
assert classify_approval_reply_text("同意") == "approve"
15+
assert classify_approval_reply_text("好") == "approve"
16+
assert classify_approval_reply_text("OK") == "approve"
17+
assert classify_approval_reply_text("留空") == "approve"
18+
assert classify_approval_reply_text("拒绝") == "reject"
19+
assert classify_approval_reply_text("NO") == "reject"
20+
21+
22+
def test_unknown_body_is_not_classified() -> None:
23+
assert classify_approval_reply_text("随便") is None
24+
25+
26+
def test_quote_only_reply_body_matches_quoted_notice() -> None:
27+
quoted = (
28+
"[好友申请]\n申请人:测试(123456)\n"
29+
"验证:-\n帮助:牛牛帮助 申请管理"
30+
)
31+
assert extract_approval_reply_text_from_body(quoted, quoted) == ""
32+
assert classify_approval_reply_text(extract_approval_reply_text_from_body(quoted, quoted)) == "approve"
33+
34+
35+
def test_user_command_after_quote_is_preserved() -> None:
36+
quoted = "[好友申请]\n申请人:测试(123456)"
37+
assert extract_approval_reply_text_from_body("同意", quoted) == "同意"
38+
assert classify_approval_reply_text(extract_approval_reply_text_from_body("同意", quoted)) == "approve"

0 commit comments

Comments
 (0)