关键修复:
- 之前错误:直接发送 message.inbound 事件
- 现在正确:使用 Gateway 的 chat.send 方法
Gateway API 调用:
{
"type": "req",
"method": "chat.send",
"params": {
"sessionKey": "wecom:group:chatId",
"message": "文本内容",
"attachments": [{"type": "image", "path": "..."}],
"deliver": true,
"idempotencyKey": "messageId"
}
}
会话管理:
- sessionKey 格式:wecom:chatType:chatId
- 例如:wecom:group:123456789 或 wecom:direct:zhangsan
- OpenClaw 会自动创建或复用会话
媒体文件处理:
- 下载企业微信图片/文件
- 保存到本地媒体目录
- 通过 attachments 参数传递给 chat.send
这样才符合 OpenClaw Gateway 协议规范!
94 lines
2.8 KiB
JavaScript
94 lines
2.8 KiB
JavaScript
// 修复:使用正确的 Gateway API 发送消息
|
||
|
||
// 转发消息到 OpenClaw - 使用 chat.send 方法
|
||
async forwardMessageToOpenClaw(frame) {
|
||
if (!openclawConnection || !openclawConnection.isConnected) {
|
||
console.log('[WeCom] OpenClaw not connected, skipping forward');
|
||
return;
|
||
}
|
||
|
||
const body = frame.body;
|
||
const chatId = body.chatid || body.from.userid;
|
||
const chatType = body.chattype === 'group' ? 'group' : 'direct';
|
||
const messageId = body.msgid;
|
||
const reqId = frame.headers.req_id;
|
||
|
||
reqIdMap.set(chatId, reqId);
|
||
|
||
// 提取文本
|
||
let text = '';
|
||
if (body.text?.content) {
|
||
text = body.text.content;
|
||
} else if (body.mixed?.msg_item) {
|
||
for (const item of body.mixed.msg_item) {
|
||
if (item.msgtype === 'text' && item.text?.content) {
|
||
text += item.text.content + '\n';
|
||
}
|
||
}
|
||
} else if (body.voice?.content) {
|
||
text = body.voice.content;
|
||
}
|
||
|
||
if (body.chattype === 'group') {
|
||
text = text.replace(/@\S+/g, '').trim();
|
||
}
|
||
|
||
// 构建 sessionKey(格式:wecom:chatType:chatId)
|
||
const sessionKey = `wecom:${chatType}:${chatId}`;
|
||
|
||
// 处理媒体文件
|
||
const attachments = [];
|
||
|
||
// 下载图片
|
||
if (body.image?.url) {
|
||
try {
|
||
console.log('[WeCom] Downloading image:', body.image.url);
|
||
const { buffer, filename } = await downloadFile(body.image.url, body.image.aeskey);
|
||
const saved = await saveMediaFile(buffer, filename, 'inbound');
|
||
attachments.push({
|
||
type: 'image',
|
||
path: saved.path,
|
||
contentType: saved.contentType
|
||
});
|
||
console.log('[WeCom] Image saved:', saved.path);
|
||
} catch (error) {
|
||
console.error('[WeCom] Failed to download image:', error.message);
|
||
}
|
||
}
|
||
|
||
// 下载文件
|
||
if (body.file?.url) {
|
||
try {
|
||
console.log('[WeCom] Downloading file:', body.file.url);
|
||
const { buffer, filename } = await downloadFile(body.file.url, body.file.aeskey);
|
||
const saved = await saveMediaFile(buffer, filename, 'inbound');
|
||
attachments.push({
|
||
type: 'file',
|
||
path: saved.path,
|
||
contentType: saved.contentType
|
||
});
|
||
console.log('[WeCom] File saved:', saved.path);
|
||
} catch (error) {
|
||
console.error('[WeCom] Failed to download file:', error.message);
|
||
}
|
||
}
|
||
|
||
// 使用 chat.send 方法发送消息到 OpenClaw
|
||
const chatSendMessage = {
|
||
type: 'req',
|
||
id: this.nextId(),
|
||
method: 'chat.send',
|
||
params: {
|
||
sessionKey: sessionKey,
|
||
message: text,
|
||
attachments: attachments.length > 0 ? attachments : undefined,
|
||
deliver: true, // 立即投递到 AI
|
||
idempotencyKey: messageId // 使用消息 ID 作为幂等键
|
||
}
|
||
};
|
||
|
||
console.log('[OpenClaw] Sending via chat.send:', sessionKey);
|
||
openclawConnection.send(JSON.stringify(chatSendMessage));
|
||
console.log(`[Forward] WeCom -> OpenClaw: ${messageId}`);
|
||
}
|