优化导出

This commit is contained in:
xuncha
2026-02-05 18:14:31 +08:00
committed by xuncha
parent d7419669d6
commit 64d5e721af

View File

@@ -590,6 +590,47 @@ class ExportService {
return content.replace(/^[\s]*([a-zA-Z0-9_-]+):(?!\/\/)/, '') return content.replace(/^[\s]*([a-zA-Z0-9_-]+):(?!\/\/)/, '')
} }
/**
* 从撤回消息内容中提取撤回者的 wxid
* 撤回消息 XML 格式通常包含 <session> 或 <newmsgid> 等字段
* 以及撤回者的 wxid 在某些字段中
* @returns { isRevoke: true, isSelfRevoke: true } - 是自己撤回的消息
* @returns { isRevoke: true, revokerWxid: string } - 是别人撤回的消息,提取到撤回者
* @returns { isRevoke: false } - 不是撤回消息
*/
private extractRevokerInfo(content: string): { isRevoke: boolean; isSelfRevoke?: boolean; revokerWxid?: string } {
if (!content) return { isRevoke: false }
// 检查是否是撤回消息
if (!content.includes('revokemsg') && !content.includes('撤回')) {
return { isRevoke: false }
}
// 检查是否是 "你撤回了" - 自己撤回
if (content.includes('你撤回')) {
return { isRevoke: true, isSelfRevoke: true }
}
// 尝试从 <session> 标签提取(格式: wxid_xxx
const sessionMatch = /<session>([^<]+)<\/session>/i.exec(content)
if (sessionMatch) {
const session = sessionMatch[1].trim()
// 如果 session 是 wxid 格式,返回它
if (session.startsWith('wxid_') || /^[a-zA-Z][a-zA-Z0-9_-]+$/.test(session)) {
return { isRevoke: true, revokerWxid: session }
}
}
// 尝试从 <fromusername> 提取
const fromUserMatch = /<fromusername>([^<]+)<\/fromusername>/i.exec(content)
if (fromUserMatch) {
return { isRevoke: true, revokerWxid: fromUserMatch[1].trim() }
}
// 是撤回消息但无法提取撤回者
return { isRevoke: true }
}
private extractXmlValue(xml: string, tagName: string): string { private extractXmlValue(xml: string, tagName: string): string {
const regex = new RegExp(`<${tagName}>([\\s\\S]*?)<\/${tagName}>`, 'i') const regex = new RegExp(`<${tagName}>([\\s\\S]*?)<\/${tagName}>`, 'i')
const match = regex.exec(xml) const match = regex.exec(xml)
@@ -1408,7 +1449,30 @@ class ExportService {
const isSend = parseInt(isSendRaw, 10) === 1 const isSend = parseInt(isSendRaw, 10) === 1
const localId = parseInt(row.local_id || row.localId || '0', 10) const localId = parseInt(row.local_id || row.localId || '0', 10)
const actualSender = isSend ? cleanedMyWxid : (senderUsername || sessionId) // 确定实际发送者
let actualSender: string
if (localType === 10000 || localType === 266287972401) {
// 系统消息特殊处理
const revokeInfo = this.extractRevokerInfo(content)
if (revokeInfo.isRevoke) {
// 撤回消息
if (revokeInfo.isSelfRevoke) {
// "你撤回了" - 发送者是当前用户
actualSender = cleanedMyWxid
} else if (revokeInfo.revokerWxid) {
// 提取到了撤回者的 wxid
actualSender = revokeInfo.revokerWxid
} else {
// 无法确定撤回者,使用 sessionId
actualSender = sessionId
}
} else {
// 普通系统消息(如"xxx加入群聊"发送者是群聊ID
actualSender = sessionId
}
} else {
actualSender = isSend ? cleanedMyWxid : (senderUsername || sessionId)
}
senderSet.add(actualSender) senderSet.add(actualSender)
// 提取媒体相关字段 // 提取媒体相关字段