wechaty-web-panel 1.6.121 → 1.6.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/handlers/on-callback-message.js +19 -10
- package/dist/handlers/on-claw-message.js +29 -14
- package/dist/handlers/on-message.js +3 -3
- package/dist/package-json.js +1 -1
- package/package.json +1 -1
- package/src/handlers/on-callback-message.js +19 -10
- package/src/handlers/on-claw-message.js +29 -14
- package/src/handlers/on-message.js +3 -3
- package/src/package-json.js +1 -1
|
@@ -34,6 +34,16 @@ async function onRecordMessage(msg) {
|
|
|
34
34
|
if (isOfficial)
|
|
35
35
|
return;
|
|
36
36
|
console.log('msg', msg);
|
|
37
|
+
let isMention = false;
|
|
38
|
+
if (room) {
|
|
39
|
+
const userSelfName = this.currentUser?.name() || '';
|
|
40
|
+
const msgText = msg.type() === this.Message.Type.Text ? msg.text() : '';
|
|
41
|
+
isMention = (await msg.mentionSelf()) || msgText.includes(`@${userSelfName}`);
|
|
42
|
+
const isMentionAll = await msg.isMentionAll();
|
|
43
|
+
if (isMentionAll && isMention) {
|
|
44
|
+
isMention = false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
37
47
|
const baseMsg = {
|
|
38
48
|
conversionId: room ? room.id : contact.id,
|
|
39
49
|
conversionName: room ? roomName : contactName,
|
|
@@ -43,7 +53,8 @@ async function onRecordMessage(msg) {
|
|
|
43
53
|
chatAlias: contactAlias,
|
|
44
54
|
chatUserWeixin: userWeixin,
|
|
45
55
|
isMyself: !!msgSelf,
|
|
46
|
-
|
|
56
|
+
isMention,
|
|
57
|
+
time: String(timestamp).length > 10 ? Math.floor(timestamp / 1000) : timestamp
|
|
47
58
|
};
|
|
48
59
|
switch (type) {
|
|
49
60
|
case this.Message.Type.Channel:
|
|
@@ -127,12 +138,12 @@ async function onRecordMessage(msg) {
|
|
|
127
138
|
break;
|
|
128
139
|
case this.Message.Type.ChatHistory:
|
|
129
140
|
const historys = await msg.toChatHistory();
|
|
130
|
-
const contents = await formatHistory(this, historys.payload, conversationRecord);
|
|
141
|
+
const contents = await formatHistory(this, historys.payload, conversationRecord, msgId);
|
|
131
142
|
baseMsg.type = '历史记录';
|
|
132
143
|
baseMsg.content = contents;
|
|
133
144
|
break;
|
|
134
145
|
case this.Message.Type.Location:
|
|
135
|
-
const
|
|
146
|
+
const locationInfo = await msg.toLocation();
|
|
136
147
|
const locationParse = `【位置解析结果】\n纬度:${locationInfo?.payload?.latitude}\n经度:${locationInfo?.payload?.longitude}\n地点名:${locationInfo?.payload?.name}\n城市:${locationInfo?.payload?.city || ''}\n具体地址:${locationInfo?.payload?.address}\nPoiId:${locationInfo?.payload?.poiId || ''}`;
|
|
137
148
|
baseMsg.type = '位置';
|
|
138
149
|
baseMsg.content = locationParse;
|
|
@@ -149,7 +160,6 @@ async function onRecordMessage(msg) {
|
|
|
149
160
|
baseMsg.content = sysText;
|
|
150
161
|
}
|
|
151
162
|
}
|
|
152
|
-
default:
|
|
153
163
|
break;
|
|
154
164
|
}
|
|
155
165
|
console.log('baseMsg', baseMsg);
|
|
@@ -159,9 +169,9 @@ async function onRecordMessage(msg) {
|
|
|
159
169
|
console.log('记录消息失败', e);
|
|
160
170
|
}
|
|
161
171
|
}
|
|
162
|
-
async function formatHistory(that,
|
|
172
|
+
async function formatHistory(that, historyList, conversationRecord, msgId) {
|
|
163
173
|
const contents = [];
|
|
164
|
-
for (const history of
|
|
174
|
+
for (const history of historyList) {
|
|
165
175
|
if (history.type === that.Message.Type.Text) {
|
|
166
176
|
contents.push(history.message);
|
|
167
177
|
}
|
|
@@ -169,20 +179,19 @@ async function formatHistory(that, history, conversationRecord) {
|
|
|
169
179
|
const attachFileBox = await history.message.toFileBox();
|
|
170
180
|
const fileExtname = path.extname(attachFileBox.name);
|
|
171
181
|
const isImage = fileExtname.includes('.png') || fileExtname.includes('.jpg') || fileExtname.includes('.jpeg') || fileExtname.includes('.gif');
|
|
172
|
-
baseMsg.type = isImage ? '图片' : '文件';
|
|
173
182
|
const buffer = await attachFileBox.toBuffer();
|
|
174
183
|
const url = await uploadOssFile(`${conversationRecord?.ossConfig?.custom_path || ''}${msgId}_${dayjs().valueOf()}_${attachFileBox.name}`, buffer);
|
|
175
|
-
contents.push(`
|
|
184
|
+
contents.push(`[${isImage ? '图片' : '文件'}](${url})`);
|
|
176
185
|
}
|
|
177
186
|
else if (history.type === that.Message.Type.ChatHistory) {
|
|
178
|
-
const res = await formatHistory(that, history.message, conversationRecord);
|
|
187
|
+
const res = await formatHistory(that, history.message, conversationRecord, msgId);
|
|
179
188
|
contents.push(res);
|
|
180
189
|
}
|
|
181
190
|
}
|
|
182
191
|
return contents.join('\n');
|
|
183
192
|
}
|
|
184
193
|
function sendMessage(msgInfo, recordConfig, robotInfo) {
|
|
185
|
-
const blackKey =
|
|
194
|
+
const blackKey = Object.keys(msgInfo);
|
|
186
195
|
const baseData = {
|
|
187
196
|
...msgInfo
|
|
188
197
|
};
|
|
@@ -19,15 +19,15 @@ async function checkAllow(clawConfig, contactId, roomId) {
|
|
|
19
19
|
}
|
|
20
20
|
else if (allowScope === 2) {
|
|
21
21
|
// 仅所有群
|
|
22
|
-
return !!
|
|
22
|
+
return !!roomId;
|
|
23
23
|
}
|
|
24
24
|
else if (allowScope === 3) {
|
|
25
25
|
// 仅所有好友
|
|
26
|
-
return !
|
|
26
|
+
return !roomId;
|
|
27
27
|
}
|
|
28
28
|
else if (allowScope === 4) {
|
|
29
29
|
// 部分群和部分好友
|
|
30
|
-
if (
|
|
30
|
+
if (roomId) {
|
|
31
31
|
return allowRooms.some(r => r.id === roomId);
|
|
32
32
|
}
|
|
33
33
|
else {
|
|
@@ -71,6 +71,16 @@ async function onClawMessage(msg) {
|
|
|
71
71
|
if (isOfficial)
|
|
72
72
|
return;
|
|
73
73
|
console.log('msg', msg);
|
|
74
|
+
let isMention = false;
|
|
75
|
+
if (room) {
|
|
76
|
+
const userSelfName = this.currentUser?.name() || '';
|
|
77
|
+
const msgText = type === this.Message.Type.Text ? msg.text() : '';
|
|
78
|
+
isMention = (await msg.mentionSelf()) || msgText.includes(`@${userSelfName}`);
|
|
79
|
+
const isMentionAll = await msg.isMentionAll();
|
|
80
|
+
if (isMentionAll && isMention) {
|
|
81
|
+
isMention = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
74
84
|
const baseMsg = {
|
|
75
85
|
conversionId: room ? room.id : contact.id,
|
|
76
86
|
conversionName: room ? roomName : contactName,
|
|
@@ -80,14 +90,15 @@ async function onClawMessage(msg) {
|
|
|
80
90
|
chatAlias: contactAlias,
|
|
81
91
|
chatUserWeixin: userWeixin,
|
|
82
92
|
isMyself: !!msgSelf,
|
|
83
|
-
time: timestamp.length > 10 ?
|
|
93
|
+
time: String(timestamp).length > 10 ? Math.floor(timestamp / 1000) : timestamp,
|
|
84
94
|
msgId: msg.id,
|
|
95
|
+
isMention,
|
|
85
96
|
};
|
|
86
97
|
switch (type) {
|
|
87
98
|
case this.Message.Type.Channel:
|
|
88
99
|
baseMsg.type = '视频号';
|
|
89
100
|
const channelInfo = await msg.toChannel();
|
|
90
|
-
baseMsg.content = `【视频号消息】\n视频号昵称:${channelInfo.nickname()}\n视频号简介:${channelInfo.desc}\n视频号链接:${channelInfo.url}`;
|
|
101
|
+
baseMsg.content = `【视频号消息】\n视频号昵称:${channelInfo.nickname()}\n视频号简介:${channelInfo.desc()}\n视频号链接:${channelInfo.url()}`;
|
|
91
102
|
baseMsg.mediaInfo = {
|
|
92
103
|
nickname: channelInfo.nickname(),
|
|
93
104
|
coverUrl: channelInfo.coverUrl(),
|
|
@@ -144,7 +155,7 @@ async function onClawMessage(msg) {
|
|
|
144
155
|
}
|
|
145
156
|
else {
|
|
146
157
|
// 没有配置OSS,使用base64
|
|
147
|
-
const base64 = attachFileBox.toBase64();
|
|
158
|
+
const base64 = await attachFileBox.toBase64();
|
|
148
159
|
baseMsg.url = base64;
|
|
149
160
|
baseMsg.content = `【${isImage ? '图片' : '文件'}消息】\n文件名:${attachFileBox.name}\n文件大小:${buffer.length} bytes\n(文件内容未上传,仅提供base64字符串)`;
|
|
150
161
|
}
|
|
@@ -165,7 +176,7 @@ async function onClawMessage(msg) {
|
|
|
165
176
|
}
|
|
166
177
|
else {
|
|
167
178
|
// 没有配置OSS,使用base64
|
|
168
|
-
const audioBase64 = audioFileBox.toBase64();
|
|
179
|
+
const audioBase64 = await audioFileBox.toBase64();
|
|
169
180
|
baseMsg.url = audioBase64;
|
|
170
181
|
baseMsg.content = `【语音消息】\n文件名:${audioFileBox.name}\n文件大小:${audioBuffer.length} bytes\n(文件内容未上传,仅提供base64字符串)`;
|
|
171
182
|
}
|
|
@@ -177,7 +188,7 @@ async function onClawMessage(msg) {
|
|
|
177
188
|
baseMsg.content = contents;
|
|
178
189
|
break;
|
|
179
190
|
case this.Message.Type.Location:
|
|
180
|
-
const
|
|
191
|
+
const locationInfo = await msg.toLocation();
|
|
181
192
|
const locationParse = `【位置解析结果】\n纬度:${locationInfo?.payload?.latitude}\n经度:${locationInfo?.payload?.longitude}\n地点名:${locationInfo?.payload?.name}\n城市:${locationInfo?.payload?.city || ''}\n具体地址:${locationInfo?.payload?.address}\nPoiId:${locationInfo?.payload?.poiId || ''}`;
|
|
182
193
|
baseMsg.type = '位置';
|
|
183
194
|
baseMsg.content = locationParse;
|
|
@@ -197,6 +208,10 @@ async function onClawMessage(msg) {
|
|
|
197
208
|
else {
|
|
198
209
|
if (!forwardMediaMsg)
|
|
199
210
|
return;
|
|
211
|
+
// 媒体消息无法 @,若 forwardMediaMsg 开启且在允许的群中,视为已提及,避免被 requireMention 拦截
|
|
212
|
+
if (room) {
|
|
213
|
+
baseMsg.isMention = true;
|
|
214
|
+
}
|
|
200
215
|
}
|
|
201
216
|
publishClawMessage(baseMsg, robotInfo);
|
|
202
217
|
}
|
|
@@ -204,9 +219,9 @@ async function onClawMessage(msg) {
|
|
|
204
219
|
console.log('claw 消息处理失败', e);
|
|
205
220
|
}
|
|
206
221
|
}
|
|
207
|
-
async function formatHistory(that,
|
|
222
|
+
async function formatHistory(that, historyList, clawConfig) {
|
|
208
223
|
const contents = [];
|
|
209
|
-
for (const history of
|
|
224
|
+
for (const history of historyList) {
|
|
210
225
|
if (history.type === that.Message.Type.Text) {
|
|
211
226
|
contents.push(history.message);
|
|
212
227
|
}
|
|
@@ -214,7 +229,6 @@ async function formatHistory(that, history, clawConfig) {
|
|
|
214
229
|
const attachFileBox = await history.message.toFileBox();
|
|
215
230
|
const fileExtname = path.extname(attachFileBox.name);
|
|
216
231
|
const isImage = fileExtname.includes('.png') || fileExtname.includes('.jpg') || fileExtname.includes('.jpeg') || fileExtname.includes('.gif');
|
|
217
|
-
baseMsg.type = isImage ? '图片' : '文件';
|
|
218
232
|
if (attachFileBox.remoteUrl) {
|
|
219
233
|
// 直接使用远程链接,无需上传
|
|
220
234
|
const url = attachFileBox.remoteUrl;
|
|
@@ -223,7 +237,7 @@ async function formatHistory(that, history, clawConfig) {
|
|
|
223
237
|
}
|
|
224
238
|
const buffer = await attachFileBox.toBuffer();
|
|
225
239
|
if (!clawConfig?.ossConfig.type) {
|
|
226
|
-
const base64 = attachFileBox.toBase64();
|
|
240
|
+
const base64 = await attachFileBox.toBase64();
|
|
227
241
|
contents.push(`【${isImage ? '图片' : '文件'}消息】\n文件名:${attachFileBox.name}\n文件大小:${buffer.length} bytes\n(文件内容未上传,仅提供base64字符串)`);
|
|
228
242
|
continue;
|
|
229
243
|
}
|
|
@@ -252,7 +266,8 @@ function publishClawMessage(baseMsg, robotInfo) {
|
|
|
252
266
|
isGroup: baseMsg.isRoom,
|
|
253
267
|
groupId: baseMsg.isRoom ? baseMsg.conversionId : undefined,
|
|
254
268
|
groupName: baseMsg.isRoom ? baseMsg.conversionName : undefined,
|
|
255
|
-
|
|
269
|
+
isGroupMention: baseMsg.isMention,
|
|
270
|
+
timestamp: baseMsg.time * 1000, // 转换为 13 位毫秒时间戳
|
|
256
271
|
messageId: baseMsg.msgId,
|
|
257
272
|
type: baseMsg.type,
|
|
258
273
|
mediaInfo: baseMsg.mediaInfo,
|
|
@@ -285,7 +300,7 @@ async function initClawMqtt(that) {
|
|
|
285
300
|
const { port, host, username, password, clientId, reciveTopic, sendTopic } = mqttConfig;
|
|
286
301
|
if (!host)
|
|
287
302
|
return;
|
|
288
|
-
clawMqttClient = mqtt.connect(
|
|
303
|
+
clawMqttClient = mqtt.connect(`${host}:${port}`, {
|
|
289
304
|
username,
|
|
290
305
|
password,
|
|
291
306
|
clientId: clientId + randomRange(1, 10000),
|
|
@@ -139,7 +139,7 @@ async function dispatchFriendFilterByMsgType(that, msg) {
|
|
|
139
139
|
const text = puppetInfo.puppetType.includes('PuppetService') && !msg.text().startsWith('@') ? msg.text().trim() : await getVoiceText(audioFileBox, finalConfig.botConfig.whisperConfig);
|
|
140
140
|
console.log('语音解析结果:', text);
|
|
141
141
|
const keyword = finalConfig.botConfig.whisperConfig?.keywords?.length ? finalConfig.botConfig?.whisperConfig.keywords?.find((item) => text.includes(item)) : true;
|
|
142
|
-
const isIgnore = checkIgnore(
|
|
142
|
+
const isIgnore = checkIgnore(text.trim(), aibotConfig.ignoreMessages);
|
|
143
143
|
if (text.trim() && !isIgnore && keyword) {
|
|
144
144
|
const gpt4vReplys = await getGpt4vChat({
|
|
145
145
|
that,
|
|
@@ -332,7 +332,7 @@ async function dispatchRoomFilterByMsgType(that, room, msg) {
|
|
|
332
332
|
const type = msg.type();
|
|
333
333
|
const receiver = msg.to();
|
|
334
334
|
let content = '';
|
|
335
|
-
let replys =
|
|
335
|
+
let replys = [];
|
|
336
336
|
let contactId = contact.id;
|
|
337
337
|
let contactAvatar = await contact.avatar();
|
|
338
338
|
const userSelfName = that.currentUser?.name() || that.userSelf()?.name();
|
|
@@ -526,7 +526,7 @@ async function dispatchRoomFilterByMsgType(that, room, msg) {
|
|
|
526
526
|
const text = puppetInfo.puppetType.includes('PuppetService') && !msg.text().startsWith('@') ? msg.text().trim() : await getVoiceText(audioFileBox, finalConfig.botConfig.whisperConfig);
|
|
527
527
|
console.log('语音解析结果', text);
|
|
528
528
|
const keyword = finalConfig.botConfig.whisperConfig?.keywords?.length ? finalConfig.botConfig?.whisperConfig?.keywords?.find((item) => text.includes(item)) : true;
|
|
529
|
-
const isIgnore = checkIgnore(
|
|
529
|
+
const isIgnore = checkIgnore(text.trim(), aibotConfig.ignoreMessages);
|
|
530
530
|
if (text.trim() && !isIgnore && keyword) {
|
|
531
531
|
const gpt4vReplys = await getGpt4vChat({
|
|
532
532
|
that,
|
package/dist/package-json.js
CHANGED
package/package.json
CHANGED
|
@@ -34,6 +34,16 @@ async function onRecordMessage(msg) {
|
|
|
34
34
|
const userWeixin = contact && contact.weixin() || ''
|
|
35
35
|
if (isOfficial) return
|
|
36
36
|
console.log('msg', msg)
|
|
37
|
+
let isMention = false
|
|
38
|
+
if (room) {
|
|
39
|
+
const userSelfName = this.currentUser?.name() || ''
|
|
40
|
+
const msgText = msg.type() === this.Message.Type.Text ? msg.text() : ''
|
|
41
|
+
isMention = (await msg.mentionSelf()) || msgText.includes(`@${userSelfName}`)
|
|
42
|
+
const isMentionAll = await msg.isMentionAll()
|
|
43
|
+
if (isMentionAll && isMention) {
|
|
44
|
+
isMention = false
|
|
45
|
+
}
|
|
46
|
+
}
|
|
37
47
|
const baseMsg = {
|
|
38
48
|
conversionId: room ? room.id : contact.id,
|
|
39
49
|
conversionName: room ? roomName : contactName,
|
|
@@ -43,7 +53,8 @@ async function onRecordMessage(msg) {
|
|
|
43
53
|
chatAlias: contactAlias,
|
|
44
54
|
chatUserWeixin: userWeixin,
|
|
45
55
|
isMyself: !!msgSelf,
|
|
46
|
-
|
|
56
|
+
isMention,
|
|
57
|
+
time: String(timestamp).length > 10 ? Math.floor(timestamp / 1000) : timestamp
|
|
47
58
|
}
|
|
48
59
|
switch (type) {
|
|
49
60
|
case this.Message.Type.Channel:
|
|
@@ -127,12 +138,12 @@ async function onRecordMessage(msg) {
|
|
|
127
138
|
break
|
|
128
139
|
case this.Message.Type.ChatHistory:
|
|
129
140
|
const historys = await msg.toChatHistory()
|
|
130
|
-
const contents = await formatHistory(this, historys.payload, conversationRecord)
|
|
141
|
+
const contents = await formatHistory(this, historys.payload, conversationRecord, msgId)
|
|
131
142
|
baseMsg.type = '历史记录'
|
|
132
143
|
baseMsg.content = contents
|
|
133
144
|
break
|
|
134
145
|
case this.Message.Type.Location:
|
|
135
|
-
const
|
|
146
|
+
const locationInfo = await msg.toLocation()
|
|
136
147
|
const locationParse = `【位置解析结果】\n纬度:${locationInfo?.payload?.latitude}\n经度:${locationInfo?.payload?.longitude}\n地点名:${locationInfo?.payload?.name}\n城市:${locationInfo?.payload?.city || ''}\n具体地址:${locationInfo?.payload?.address}\nPoiId:${locationInfo?.payload?.poiId || ''}`
|
|
137
148
|
baseMsg.type = '位置'
|
|
138
149
|
baseMsg.content = locationParse
|
|
@@ -148,7 +159,6 @@ async function onRecordMessage(msg) {
|
|
|
148
159
|
baseMsg.content = sysText
|
|
149
160
|
}
|
|
150
161
|
}
|
|
151
|
-
default:
|
|
152
162
|
break
|
|
153
163
|
}
|
|
154
164
|
console.log('baseMsg', baseMsg)
|
|
@@ -158,21 +168,20 @@ async function onRecordMessage(msg) {
|
|
|
158
168
|
}
|
|
159
169
|
}
|
|
160
170
|
|
|
161
|
-
async function formatHistory(that,
|
|
171
|
+
async function formatHistory(that, historyList, conversationRecord, msgId) {
|
|
162
172
|
const contents = []
|
|
163
|
-
for (const history of
|
|
173
|
+
for (const history of historyList) {
|
|
164
174
|
if (history.type === that.Message.Type.Text) {
|
|
165
175
|
contents.push(history.message)
|
|
166
176
|
} else if (history.type === that.Message.Type.Recalled || history.type === that.Message.Type.Attachment || history.type === that.Message.Type.Image || history.type === that.Message.Type.Video) {
|
|
167
177
|
const attachFileBox = await history.message.toFileBox();
|
|
168
178
|
const fileExtname = path.extname(attachFileBox.name);
|
|
169
179
|
const isImage = fileExtname.includes('.png') || fileExtname.includes('.jpg') || fileExtname.includes('.jpeg') || fileExtname.includes('.gif')
|
|
170
|
-
baseMsg.type = isImage ? '图片' : '文件'
|
|
171
180
|
const buffer = await attachFileBox.toBuffer()
|
|
172
181
|
const url = await uploadOssFile(`${conversationRecord?.ossConfig?.custom_path || ''}${msgId}_${dayjs().valueOf()}_${attachFileBox.name}`, buffer)
|
|
173
|
-
contents.push(`
|
|
182
|
+
contents.push(`[${isImage ? '图片' : '文件'}](${url})`)
|
|
174
183
|
} else if (history.type === that.Message.Type.ChatHistory) {
|
|
175
|
-
const res = await formatHistory(that, history.message, conversationRecord)
|
|
184
|
+
const res = await formatHistory(that, history.message, conversationRecord, msgId)
|
|
176
185
|
contents.push(res)
|
|
177
186
|
}
|
|
178
187
|
}
|
|
@@ -180,7 +189,7 @@ async function formatHistory(that, history, conversationRecord) {
|
|
|
180
189
|
}
|
|
181
190
|
|
|
182
191
|
function sendMessage(msgInfo, recordConfig, robotInfo) {
|
|
183
|
-
const blackKey =
|
|
192
|
+
const blackKey = Object.keys(msgInfo)
|
|
184
193
|
const baseData = {
|
|
185
194
|
...msgInfo
|
|
186
195
|
}
|
|
@@ -21,13 +21,13 @@ async function checkAllow(clawConfig, contactId, roomId) {
|
|
|
21
21
|
return true
|
|
22
22
|
} else if (allowScope === 2) {
|
|
23
23
|
// 仅所有群
|
|
24
|
-
return !!
|
|
24
|
+
return !!roomId
|
|
25
25
|
} else if (allowScope === 3) {
|
|
26
26
|
// 仅所有好友
|
|
27
|
-
return !
|
|
27
|
+
return !roomId
|
|
28
28
|
} else if (allowScope === 4) {
|
|
29
29
|
// 部分群和部分好友
|
|
30
|
-
if (
|
|
30
|
+
if (roomId) {
|
|
31
31
|
return allowRooms.some(r => r.id === roomId)
|
|
32
32
|
} else {
|
|
33
33
|
return allowFriends.some(f => f.id === contactId)
|
|
@@ -70,6 +70,16 @@ async function onClawMessage(msg) {
|
|
|
70
70
|
const userWeixin = contact && contact.weixin() || ''
|
|
71
71
|
if (isOfficial) return
|
|
72
72
|
console.log('msg', msg)
|
|
73
|
+
let isMention = false
|
|
74
|
+
if (room) {
|
|
75
|
+
const userSelfName = this.currentUser?.name() || ''
|
|
76
|
+
const msgText = type === this.Message.Type.Text ? msg.text() : ''
|
|
77
|
+
isMention = (await msg.mentionSelf()) || msgText.includes(`@${userSelfName}`)
|
|
78
|
+
const isMentionAll = await msg.isMentionAll()
|
|
79
|
+
if (isMentionAll && isMention) {
|
|
80
|
+
isMention = false
|
|
81
|
+
}
|
|
82
|
+
}
|
|
73
83
|
const baseMsg = {
|
|
74
84
|
conversionId: room ? room.id : contact.id,
|
|
75
85
|
conversionName: room ? roomName : contactName,
|
|
@@ -79,14 +89,15 @@ async function onClawMessage(msg) {
|
|
|
79
89
|
chatAlias: contactAlias,
|
|
80
90
|
chatUserWeixin: userWeixin,
|
|
81
91
|
isMyself: !!msgSelf,
|
|
82
|
-
time: timestamp.length > 10 ?
|
|
92
|
+
time: String(timestamp).length > 10 ? Math.floor(timestamp / 1000) : timestamp,
|
|
83
93
|
msgId: msg.id,
|
|
94
|
+
isMention,
|
|
84
95
|
}
|
|
85
96
|
switch (type) {
|
|
86
97
|
case this.Message.Type.Channel:
|
|
87
98
|
baseMsg.type = '视频号'
|
|
88
99
|
const channelInfo = await msg.toChannel();
|
|
89
|
-
baseMsg.content = `【视频号消息】\n视频号昵称:${channelInfo.nickname()}\n视频号简介:${channelInfo.desc}\n视频号链接:${channelInfo.url}`
|
|
100
|
+
baseMsg.content = `【视频号消息】\n视频号昵称:${channelInfo.nickname()}\n视频号简介:${channelInfo.desc()}\n视频号链接:${channelInfo.url()}`
|
|
90
101
|
baseMsg.mediaInfo = {
|
|
91
102
|
nickname: channelInfo.nickname(),
|
|
92
103
|
coverUrl: channelInfo.coverUrl(),
|
|
@@ -143,7 +154,7 @@ async function onClawMessage(msg) {
|
|
|
143
154
|
baseMsg.content = `【${isImage ? '图片' : '文件'}消息】\n文件名:${attachFileBox.name}\n下载链接:${url}`
|
|
144
155
|
} else {
|
|
145
156
|
// 没有配置OSS,使用base64
|
|
146
|
-
const base64 = attachFileBox.toBase64()
|
|
157
|
+
const base64 = await attachFileBox.toBase64()
|
|
147
158
|
baseMsg.url = base64
|
|
148
159
|
baseMsg.content = `【${isImage ? '图片' : '文件'}消息】\n文件名:${attachFileBox.name}\n文件大小:${buffer.length} bytes\n(文件内容未上传,仅提供base64字符串)`
|
|
149
160
|
}
|
|
@@ -163,7 +174,7 @@ async function onClawMessage(msg) {
|
|
|
163
174
|
baseMsg.content = `【语音消息】\n文件名:${audioFileBox.name}\n下载链接:${audioUrl}`
|
|
164
175
|
} else {
|
|
165
176
|
// 没有配置OSS,使用base64
|
|
166
|
-
const audioBase64 = audioFileBox.toBase64()
|
|
177
|
+
const audioBase64 = await audioFileBox.toBase64()
|
|
167
178
|
baseMsg.url = audioBase64
|
|
168
179
|
baseMsg.content = `【语音消息】\n文件名:${audioFileBox.name}\n文件大小:${audioBuffer.length} bytes\n(文件内容未上传,仅提供base64字符串)`
|
|
169
180
|
}
|
|
@@ -175,7 +186,7 @@ async function onClawMessage(msg) {
|
|
|
175
186
|
baseMsg.content = contents
|
|
176
187
|
break
|
|
177
188
|
case this.Message.Type.Location:
|
|
178
|
-
const
|
|
189
|
+
const locationInfo = await msg.toLocation()
|
|
179
190
|
const locationParse = `【位置解析结果】\n纬度:${locationInfo?.payload?.latitude}\n经度:${locationInfo?.payload?.longitude}\n地点名:${locationInfo?.payload?.name}\n城市:${locationInfo?.payload?.city || ''}\n具体地址:${locationInfo?.payload?.address}\nPoiId:${locationInfo?.payload?.poiId || ''}`
|
|
180
191
|
baseMsg.type = '位置'
|
|
181
192
|
baseMsg.content = locationParse
|
|
@@ -192,6 +203,10 @@ async function onClawMessage(msg) {
|
|
|
192
203
|
}
|
|
193
204
|
} else {
|
|
194
205
|
if (!forwardMediaMsg) return
|
|
206
|
+
// 媒体消息无法 @,若 forwardMediaMsg 开启且在允许的群中,视为已提及,避免被 requireMention 拦截
|
|
207
|
+
if (room) {
|
|
208
|
+
baseMsg.isMention = true
|
|
209
|
+
}
|
|
195
210
|
}
|
|
196
211
|
publishClawMessage(baseMsg, robotInfo)
|
|
197
212
|
} catch (e) {
|
|
@@ -199,16 +214,15 @@ async function onClawMessage(msg) {
|
|
|
199
214
|
}
|
|
200
215
|
}
|
|
201
216
|
|
|
202
|
-
async function formatHistory(that,
|
|
217
|
+
async function formatHistory(that, historyList, clawConfig) {
|
|
203
218
|
const contents = []
|
|
204
|
-
for (const history of
|
|
219
|
+
for (const history of historyList) {
|
|
205
220
|
if (history.type === that.Message.Type.Text) {
|
|
206
221
|
contents.push(history.message)
|
|
207
222
|
} else if (history.type === that.Message.Type.Recalled || history.type === that.Message.Type.Attachment || history.type === that.Message.Type.Image || history.type === that.Message.Type.Video) {
|
|
208
223
|
const attachFileBox = await history.message.toFileBox();
|
|
209
224
|
const fileExtname = path.extname(attachFileBox.name);
|
|
210
225
|
const isImage = fileExtname.includes('.png') || fileExtname.includes('.jpg') || fileExtname.includes('.jpeg') || fileExtname.includes('.gif')
|
|
211
|
-
baseMsg.type = isImage ? '图片' : '文件'
|
|
212
226
|
if (attachFileBox.remoteUrl) {
|
|
213
227
|
// 直接使用远程链接,无需上传
|
|
214
228
|
const url = attachFileBox.remoteUrl
|
|
@@ -217,7 +231,7 @@ async function formatHistory(that, history, clawConfig) {
|
|
|
217
231
|
}
|
|
218
232
|
const buffer = await attachFileBox.toBuffer()
|
|
219
233
|
if (!clawConfig?.ossConfig.type) {
|
|
220
|
-
const base64 = attachFileBox.toBase64()
|
|
234
|
+
const base64 = await attachFileBox.toBase64()
|
|
221
235
|
contents.push(`【${isImage ? '图片' : '文件'}消息】\n文件名:${attachFileBox.name}\n文件大小:${buffer.length} bytes\n(文件内容未上传,仅提供base64字符串)`)
|
|
222
236
|
continue
|
|
223
237
|
}
|
|
@@ -245,7 +259,8 @@ function publishClawMessage(baseMsg, robotInfo) {
|
|
|
245
259
|
isGroup: baseMsg.isRoom,
|
|
246
260
|
groupId: baseMsg.isRoom ? baseMsg.conversionId : undefined,
|
|
247
261
|
groupName: baseMsg.isRoom ? baseMsg.conversionName : undefined,
|
|
248
|
-
|
|
262
|
+
isGroupMention: baseMsg.isMention,
|
|
263
|
+
timestamp: baseMsg.time * 1000, // 转换为 13 位毫秒时间戳
|
|
249
264
|
messageId: baseMsg.msgId,
|
|
250
265
|
type: baseMsg.type,
|
|
251
266
|
mediaInfo: baseMsg.mediaInfo,
|
|
@@ -277,7 +292,7 @@ async function initClawMqtt(that) {
|
|
|
277
292
|
const { port, host, username, password, clientId, reciveTopic, sendTopic } = mqttConfig
|
|
278
293
|
if (!host) return
|
|
279
294
|
|
|
280
|
-
clawMqttClient = mqtt.connect(
|
|
295
|
+
clawMqttClient = mqtt.connect(`${host}:${port}`, {
|
|
281
296
|
username,
|
|
282
297
|
password,
|
|
283
298
|
clientId: clientId + randomRange(1, 10000),
|
|
@@ -137,7 +137,7 @@ async function dispatchFriendFilterByMsgType(that, msg) {
|
|
|
137
137
|
const text = puppetInfo.puppetType.includes('PuppetService') && !msg.text().startsWith('@') ? msg.text().trim() : await getVoiceText(audioFileBox, finalConfig.botConfig.whisperConfig)
|
|
138
138
|
console.log('语音解析结果:', text)
|
|
139
139
|
const keyword = finalConfig.botConfig.whisperConfig?.keywords?.length ? finalConfig.botConfig?.whisperConfig.keywords?.find((item) => text.includes(item)) : true
|
|
140
|
-
const isIgnore = checkIgnore(
|
|
140
|
+
const isIgnore = checkIgnore(text.trim(), aibotConfig.ignoreMessages)
|
|
141
141
|
if (text.trim() && !isIgnore && keyword) {
|
|
142
142
|
const gpt4vReplys = await getGpt4vChat({
|
|
143
143
|
that,
|
|
@@ -333,7 +333,7 @@ async function dispatchRoomFilterByMsgType(that, room, msg) {
|
|
|
333
333
|
const type = msg.type()
|
|
334
334
|
const receiver = msg.to()
|
|
335
335
|
let content = ''
|
|
336
|
-
let replys =
|
|
336
|
+
let replys = []
|
|
337
337
|
let contactId = contact.id
|
|
338
338
|
let contactAvatar = await contact.avatar()
|
|
339
339
|
const userSelfName = that.currentUser?.name() || that.userSelf()?.name()
|
|
@@ -532,7 +532,7 @@ async function dispatchRoomFilterByMsgType(that, room, msg) {
|
|
|
532
532
|
const text = puppetInfo.puppetType.includes('PuppetService') && !msg.text().startsWith('@') ? msg.text().trim() : await getVoiceText(audioFileBox, finalConfig.botConfig.whisperConfig)
|
|
533
533
|
console.log('语音解析结果', text)
|
|
534
534
|
const keyword = finalConfig.botConfig.whisperConfig?.keywords?.length ? finalConfig.botConfig?.whisperConfig?.keywords?.find((item) => text.includes(item)) : true
|
|
535
|
-
const isIgnore = checkIgnore(
|
|
535
|
+
const isIgnore = checkIgnore(text.trim(), aibotConfig.ignoreMessages)
|
|
536
536
|
if (text.trim() && !isIgnore && keyword) {
|
|
537
537
|
const gpt4vReplys = await getGpt4vChat({
|
|
538
538
|
that,
|