增加了群id和私聊id的显示

This commit is contained in:
Prometheus-first
2026-10-16 12:26:23 +08:00
parent 68eb19ea35
commit 516e82483d
5 changed files with 110 additions and 15 deletions
+10
View File
@@ -61,6 +61,16 @@ python main.py
`--check` 只检查配置、插件清单与语法,不注入微信,也不调用模型。正常运行前打开微信并登录配置中的账号。
默认 `INFO` 日志级别下,启动后会在控制台实时显示当前连接的微信账号、收到私聊的发送者 ID 和正文,以及收到群消息的群 ID;这些日志也会保存到 `logs/bot.log`:
```text
当前登录微信ID=wxid_example_robot;好友和群聊文本已就绪
私聊消息 | 发送者微信ID=wxid_example_friend | 内容="你好"
群消息 | 群ID=12345678@chatroom
```
消息显示在会话白名单过滤之前,因此新群尚未加入白名单时,也可以让群里的人发一条文本,从控制台复制群 ID。自动消息日志不打印群正文或群成员 ID;总结功能使用的群聊天缓存按原有配置保存。私聊中的换行会显示为 `\n`,一条消息占一行。`logs/` 已被 Git 忽略。
也可以运行 `start_bot.ps1`:脚本优先使用项目的 `.venv`,其次使用 PATH 中的 Python;可通过 `-Python` 或环境变量 `WXBOT_PYTHON` 指定解释器,不依赖某台电脑的安装路径。
控制台命令:
+3 -15
View File
@@ -77,7 +77,7 @@ class NativeTextService(NativeFileHelperService):
# 手动指定 PID 时也先只读核对,避免向其他账号加载 DLL。
raise RuntimeError("目标进程登录的不是绑定的机器人账号,等待正确账号登录")
result = super().start()
logger.info("当前账号已自动识别:%s;好友和群聊文本已就绪", self.self_wxid)
logger.info("当前登录微信ID=%s;好友和群聊文本已就绪", self.self_wxid)
return result
def _read_account(self):
@@ -143,20 +143,8 @@ class NativeTextService(NativeFileHelperService):
data["dispatch_to_plugins"] = False
elif data["is_at_self"]:
data["dispatch_to_plugins"] = True
if "WXBOT_AT_CHAT_PROBE" in data["msg"]:
import json
from pathlib import Path
path = Path(__file__).resolve().parents[1] / ".runtime/at_receive_probe.json"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps({"room": data["chat_id"], "sender": data["sender_id"],
"at_members": data["at_members"], "is_at_self": data["is_at_self"],
"source": source}, ensure_ascii=False, indent=2), encoding="utf-8")
logger.info("艾特接收探针:at_members=%s is_at_self=%s", data["at_members"], data["is_at_self"])
self.chats[data["chat_id"]] = {"chat_id": data["chat_id"],
"is_group": bool(data["room_wxid"])}
if data["msg"].startswith(("WXBOT_", "echo WXBOT_")):
logger.info("测试消息已接收:chat_id=%s sender_id=%s group=%s marker=%s",
data["chat_id"], data["sender_id"], bool(data["room_wxid"]), data["msg"])
elif self.router.unparsed_groups > previous_unparsed:
# 第一条失败时提示;后续通过 status 查看累计数。
if self.router.unparsed_groups == 1:
@@ -180,7 +168,7 @@ class NativeTextService(NativeFileHelperService):
self.last_result = self._run("--dispatch", pid=self.pid, text=content, target=to_wxid,
keep_loaded=True, preserve_report=self.preserve_reports, mentions=mentions)
if content.startswith("WXBOT_"):
logger.info("测试文本发送完成:chat_id=%s marker=%s success=%s native_thread=%s",
to_wxid, content, self.last_result["success"],
logger.info("测试文本发送完成:chat_id=%s success=%s native_thread=%s",
to_wxid, self.last_result["success"],
self.last_result.get("report", {}).get("thread_id"))
return self.last_result["success"]
+16
View File
@@ -178,6 +178,22 @@ class AccountTests(unittest.TestCase):
with self.assertRaisesRegex(RuntimeError, "自动等待"):
service._prepare_channel()
@unittest.skipUnless(sys.platform == "win32", "本机原生服务检查")
def test_start_logs_identity_read_from_current_process(self):
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "native"))
from text_service import NativeTextService
service = NativeTextService(pid=123)
def prepare_channel():
service.router.set_account(SELF)
return True
with patch("filehelper_service.NativeFileHelperService.start", side_effect=prepare_channel), \
self.assertLogs("NativeText", "INFO") as captured:
self.assertTrue(service.start())
self.assertIn(SELF, "\n".join(captured.output))
self.assertIn("当前登录微信ID", "\n".join(captured.output))
@unittest.skipUnless(sys.platform == "win32", "本机原生服务检查")
def test_explicit_wrong_pid_is_rejected_before_loading_bridge(self):
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "native"))
+74
View File
@@ -12,6 +12,7 @@ import threading
import time
import unittest
import uuid
from unittest.mock import Mock, patch
from wxbot_framework.backend import CAPABILITIES
from wxbot_framework.config import ConfigStore
@@ -285,6 +286,79 @@ class FrameworkTests(unittest.TestCase):
finally:
app.plugins.shutdown()
def test_new_group_is_logged_before_allowlist_without_body_or_member(self):
self.config["chat_allowlist"] = ["filehelper"]
self.write_config()
app = BotApplication(self.root, self.store, backend_factory=lambda: self.backend)
app.members = Mock()
room = "87654321@chatroom"
sender = "wxid_example_member"
body = "本条群正文不应出现在日志中"
# 同时覆盖标准消息和仅有会话 ID、缺少群标记的消息,避免误当私聊泄露正文。
logging.disable(logging.NOTSET)
with patch.object(app.plugins, "dispatch") as dispatch, self.assertLogs("Bot", "INFO") as captured:
for is_group in (True, False):
app._emit(Message(body, room, sender, is_group=is_group))
self.assertEqual(len(captured.records), 2)
for record in captured.records:
self.assertIn(room, record.getMessage())
self.assertNotIn(body, record.getMessage())
self.assertNotIn(sender, record.getMessage())
app.members.record.assert_not_called()
dispatch.assert_not_called()
def test_private_log_keeps_sender_and_unicode_but_escapes_line_breaks(self):
app = BotApplication(self.root, self.store, backend_factory=lambda: self.backend)
sender = "wxid_example_sender"
body = "你好 🌸\r\n第二行\t100%"
# 文件传输助手的会话 ID 与实际作者不同,必须显示作者。
message = Message.from_native(11046, {"msg": body, "chat_id": "filehelper",
"sender_id": sender, "dispatch_to_plugins": False}, "logging")
logging.disable(logging.NOTSET)
with self.assertLogs("Bot", "INFO") as captured:
app._emit(message)
self.assertEqual(len(captured.records), 1)
rendered = captured.records[0].getMessage()
self.assertIn(sender, rendered)
self.assertIn("你好 🌸", rendered)
self.assertNotIn("\n", rendered)
self.assertNotIn("\r", rendered)
self.assertEqual(json.loads(rendered.split("内容=", 1)[1]), body)
@unittest.skipUnless(sys.platform == "win32", "本机原生服务检查")
def test_native_test_messages_do_not_bypass_group_log_privacy(self):
native = str(ROOT / "native")
if native not in sys.path:
sys.path.insert(0, native)
from text_service import NativeTextService
from filehelper_service import ReceivedTextMessage
service = NativeTextService(pid=123)
account, sender, room = "wxid_example_self", "wxid_example_member", "87654321@chatroom"
service.router.set_account(account)
service._sender_wechat_name = Mock(return_value=None)
app = BotApplication(self.root, self.store, backend_factory=lambda: self.backend)
markers = ("WXBOT_AT_CHAT_PROBE", "WXBOT_GROUP_TEST", "echo WXBOT_GROUP_TEST")
logging.disable(logging.NOTSET)
with self.assertLogs(level="INFO") as captured:
for body in markers:
raw = ReceivedTextMessage(type=1, sender=room.encode(), receiver=account.encode(),
text=(sender + ":\n" + body).encode())
app._emit(Message.from_native(11046, service._map_message(raw), "logging"))
self.assertEqual(len(captured.records), len(markers))
rendered = "\n".join(captured.output)
self.assertIn(room, rendered)
self.assertNotIn(sender, rendered)
for body in markers:
self.assertNotIn(body, rendered)
service._owns_bridge = True
service._check_account = Mock()
service._run = Mock(return_value={"success": True})
with self.assertLogs("NativeText", "INFO") as sent_logs:
self.assertTrue(service.send_text(room, "WXBOT_GROUP_SEND_TEST"))
self.assertIn(room, "\n".join(sent_logs.output))
self.assertNotIn("WXBOT_GROUP_SEND_TEST", "\n".join(sent_logs.output))
if __name__ == "__main__":
unittest.main()
+7
View File
@@ -61,6 +61,13 @@ class BotApplication:
self._disconnect()
def _emit(self, message):
# 先显示会话 ID,未加入白名单的新群也能被发现;群正文不进入消息日志。
if message.is_group or message.chat_id.endswith("@chatroom"):
logger.info("群消息 | 群ID=%s", message.chat_id)
else:
logger.info("私聊消息 | 发送者微信ID=%s | 内容=%s",
message.sender_id or message.chat_id,
json.dumps(message.text, ensure_ascii=False))
allowed = self.config.get("chat_allowlist", [])
if not allowed or message.chat_id in allowed:
if self.members is not None: