1
This commit is contained in:
@@ -205,17 +205,27 @@ class ChatManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 统一 uid 为可比较的字符串(支持 number 或 { low, high }) */
|
||||
_normalizeUid(uid) {
|
||||
if (uid == null) return null;
|
||||
if (typeof uid === 'number' || typeof uid === 'string') return String(uid);
|
||||
if (typeof uid === 'object' && typeof uid.low === 'number') return String(uid.low);
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 过滤出 HR 发的、非系统、可回复的消息列表(已排除自己发的) */
|
||||
_filterHrReplyableMessages(messages, geek_uid) {
|
||||
if (!geek_uid || !Array.isArray(messages)) return [];
|
||||
let list = messages.filter(msg => {
|
||||
if (!msg.from || msg.from.uid === geek_uid) return false;
|
||||
const geekStr = this._normalizeUid(geek_uid);
|
||||
if (!geekStr) return [];
|
||||
const list = messages.filter(msg => {
|
||||
if (!msg.from) return false;
|
||||
const fromStr = this._normalizeUid(msg.from.uid);
|
||||
if (fromStr === geekStr) return false; // 自己发的,排除
|
||||
if (this._isSystemMessage(msg)) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return list
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/** AI 回复后写入 chat_reply_intent_log,options 含 sn_code/platform/friendId/encryptFriendId,securityId 为 HR 消息唯一 id */
|
||||
@@ -299,12 +309,14 @@ class ChatManager {
|
||||
const logModel = db.getModel('chat_reply_intent_log');
|
||||
const existing = await logModel.findOne({ where: { security_id } });
|
||||
if (existing) {
|
||||
// 已回复过的 HR 消息:不再重复发,避免每次扫描都发一条
|
||||
if (existing.replied) {
|
||||
return { replied: false, reason: '该条HR消息已回复过,跳过' };
|
||||
}
|
||||
// 之前记录为不回复:直接沿用,不再调 AI
|
||||
return {
|
||||
replied: !!existing.replied,
|
||||
action: existing.action || 'text',
|
||||
reply_content: existing.reply_content || '',
|
||||
hr_message_text: existing.hr_message_text || hr_message_text,
|
||||
reason: existing.reason || null
|
||||
replied: false,
|
||||
reason: existing.reason || '已记录为不回复'
|
||||
};
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -13,6 +13,8 @@ class MqttDispatcher {
|
||||
this.mqttClient = mqttClient;
|
||||
this.actionHandlers = new Map();
|
||||
this.subscribedTopics = new Set();
|
||||
// 去重防抖:记录最近处理过的 Boss 消息 securityId -> timestamp
|
||||
this.bossMessageDedupMap = new Map();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,6 +347,23 @@ class MqttDispatcher {
|
||||
raw: payload
|
||||
};
|
||||
|
||||
// 去重防抖:按 securityId(或 cmid)在一定时间窗口内只处理一次
|
||||
const securityId = firstMsg && firstMsg.securityId;
|
||||
const cmidObj = firstMsg && firstMsg.cmid;
|
||||
const cmid = cmidObj && typeof cmidObj.low === 'number' ? `${cmidObj.high}:${cmidObj.low}` : null;
|
||||
const dedupKey = securityId || cmid;
|
||||
const now = Date.now();
|
||||
const windowMs = 2 * 60 * 1000; // 2 分钟内视为重复
|
||||
|
||||
if (dedupKey) {
|
||||
const lastTs = this.bossMessageDedupMap.get(dedupKey);
|
||||
if (lastTs && now - lastTs < windowMs) {
|
||||
console.log('[MQTT Boss 消息] 检测到重复消息,跳过处理:', { sn_code, dedupKey });
|
||||
return;
|
||||
}
|
||||
this.bossMessageDedupMap.set(dedupKey, now);
|
||||
}
|
||||
|
||||
console.log('[MQTT Boss 消息] 解析结果:', {
|
||||
sn_code: normalized.sn_code,
|
||||
type: normalized.type,
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user