diff --git a/AGENTS.md b/AGENTS.md index c5eac46..cfa1f75 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,7 @@ - 删除登录目录/小号前必须停止收尾、确认范围并持久化删除意图;只清理属于该账号的受管路径,禁止符号链接/junction 越界。目录与数据库部分成功时保留禁止启动状态,仅显式重试,不自动登录或恢复规则。 - 实时缓存非空不等于完成历史全量;同步基线、游标和完整标记必须与数据落库一致,失败/截断不得称为全部。历史入队须二次确认且校验规则/作品配置基线;相同通知由数据库去重。 - 异步 UI 回包按 account ID/request ID 隔离,选中项、启动勾选和未保存草稿分开;状态刷新不覆盖草稿,列表先按账号/原组过滤再分页。旧任务缺失的时间显示未知,不伪造阶段时间。 -- 实现变更先用现有测试、临时 SQLite、假 session/执行器覆盖启停竞态、分页、迁移、unknown 只读查询和存储故障;验收矩阵见 `docs/plan01.md`。不以真实关注、私信或标记已读作为回归测试,不新增无必要的调度/状态机框架。 +- 实现变更先用现有测试、临时 SQLite、假 session/执行器覆盖启停竞态、分页、迁移、unknown 只读查询和存储故障;验收矩阵见 `docs/plan01.md`。未获用户明确授权时,不以真实关注、私信或标记已读作为回归测试;用户明确要求发送时,仅允许自动化操作本机已登录浏览器进行功能调试验证,不扩展到远程或批量生产操作;不新增无必要的调度/状态机框架。 ## Windows 远程部署与连接 @@ -34,5 +34,5 @@ - Windows MCP 不满足需求或批量命令明显不便时,改用 SSH 执行文件传输、构建、安装和日志检查;连接地址、账号和密钥只从本机 SSH 配置读取,不写入代码、安装包或文档。 - Windows 原生构建必须在 Windows x64 主机执行 `build_windows.py`,不要把 Linux 构建产物伪装成 Windows 安装包。 - 部署顺序:先在本地完成测试,再将源码或构建产物传到 Windows;执行构建/安装后通过 Windows MCP 做 GUI 冒烟和人工验收。 -- 远程操作前先确认目标程序当前状态;不要自动登录、恢复业务规则或执行真实关注/私信等写操作。登录状态丢失时停止并交给用户登录。 +- 远程操作前先确认目标程序当前状态;不要自动登录、恢复业务规则或执行真实关注/私信等写操作。用户授权的发送调试仅限本机已登录浏览器,不适用于远程主机或批量生产操作。登录状态丢失时停止并交给用户登录。 - 远程部署记录写入 `docs/YYYY-MM-DD-HH-II-.md`,记录连接方式、执行命令、产物路径和验证结果,但不记录密码、Cookie、UID 或登录目录内容。 diff --git a/docs/2026-09-20-17-37-local-sdk-send-success.md b/docs/2026-09-20-17-37-local-sdk-send-success.md new file mode 100644 index 0000000..5a141da --- /dev/null +++ b/docs/2026-09-20-17-37-local-sdk-send-success.md @@ -0,0 +1,30 @@ +# 本机 SDK 私信发送验证 + +- 时间:2026-09-20 17:37 +- 范围:仅本机已登录浏览器,用户明确授权的单个目标 + +## 根因 + +本机 CDP 调用 `sendMessageManager` 时返回空结果且没有产生 `/v1/message/send` 请求。检查站内 builder 构造函数发现其参数只接受 `message/messageType/from/enterMethod`,不会读取工厂参数中的 `conversation`;原修复把 `conversation` 错放在工厂参数中,导致 builder 内部没有会话,manager 静默提前返回。 + +正确调用顺序是: + +```javascript +const builder = sendMessageManager.createMessageBuilder({messageType: 7, enterMethod: 'local_cdp_debug'}); +builder.conversation(conversation).toUid(uid).content(content); +await sendMessageManager.sendMessage(builder); +``` + +## 本机验证 + +- 修复后仅向用户指定的“肉宝儿”发送一条测试文本 `1111111`。 +- SDK 返回:`success=true`、`statusCode=0`、`checkCode=0`。 +- 监控同时捕获:`/v1/message/send` HTTP `200`,随后 `/v1/message/get_user_message` HTTP `200`。 +- 未发送其他目标;未执行关注、标记已读或远程业务操作。 +- 监控记录:`douyin-im-authorized-send`。 + +## 代码修复 + +- `src/douyin_im.py` 改为显式调用 `builder.conversation(conversation)`。 +- `src/test_douyin_im.py` mock 改为覆盖 builder conversation setter。 +- IM 测试 2 项通过,账号/计划/通知/activity、编译、diff、LSP 检查通过。 diff --git a/src/douyin_im.py b/src/douyin_im.py index 49c7c9a..f81957f 100644 --- a/src/douyin_im.py +++ b/src/douyin_im.py @@ -79,8 +79,8 @@ EXPRESSION = r""" // 复用站内 sendMessageManager,不直接调用 sdk.sendMessage:站内流程会在发送前 // 更新 identity security headers,并处理官方一次性风控验证/重试回调。 const builder = sendManager.createMessageBuilder({ - conversation, messageType: 7, enterMethod: 'douyin_accounts_worker'}); - builder.toUid(p.uid).content(JSON.stringify({ + messageType: 7, enterMethod: 'douyin_accounts_worker'}); + builder.conversation(conversation).toUid(p.uid).content(JSON.stringify({ aweType: 700, type: 0, richTextInfos: [], text: p.text})); const result = await sendManager.sendMessage(builder); const message = builder.getMessage(); diff --git a/src/test_douyin_im.py b/src/test_douyin_im.py index 31f25c5..e0a6a0c 100644 --- a/src/test_douyin_im.py +++ b/src/test_douyin_im.py @@ -32,11 +32,11 @@ const sdk = { } }; const sendMessageManager = { - createMessageBuilder: ({conversation: current, messageType}) => { - assert.equal(current, conversation); + createMessageBuilder: ({messageType}) => { assert.equal(messageType, 7); - let content = '', message; + let current, content = '', message; const builder = { + conversation: value => { assert.equal(value, conversation); current = value; return builder; }, toUid: uid => { assert.equal(uid, '12345'); return builder; }, content: value => { content = value; return builder; }, getMessage: () => message,