mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
124 lines
3.4 KiB
TypeScript
124 lines
3.4 KiB
TypeScript
export type CloneRole = 'target' | 'me'
|
|
|
|
export interface CloneMessage {
|
|
role: CloneRole
|
|
content: string
|
|
createTime: number
|
|
}
|
|
|
|
const CONTENT_FIELDS = [
|
|
'message_content',
|
|
'messageContent',
|
|
'content',
|
|
'msg_content',
|
|
'msgContent',
|
|
'WCDB_CT_message_content',
|
|
'WCDB_CT_messageContent'
|
|
]
|
|
const COMPRESS_FIELDS = [
|
|
'compress_content',
|
|
'compressContent',
|
|
'compressed_content',
|
|
'WCDB_CT_compress_content',
|
|
'WCDB_CT_compressContent'
|
|
]
|
|
const LOCAL_TYPE_FIELDS = ['local_type', 'localType', 'type', 'msg_type', 'msgType', 'WCDB_CT_local_type']
|
|
const IS_SEND_FIELDS = ['computed_is_send', 'computedIsSend', 'is_send', 'isSend', 'WCDB_CT_is_send']
|
|
const SENDER_FIELDS = ['sender_username', 'senderUsername', 'sender', 'WCDB_CT_sender_username']
|
|
const CREATE_TIME_FIELDS = [
|
|
'create_time',
|
|
'createTime',
|
|
'createtime',
|
|
'msg_create_time',
|
|
'msgCreateTime',
|
|
'msg_time',
|
|
'msgTime',
|
|
'time',
|
|
'WCDB_CT_create_time'
|
|
]
|
|
|
|
const TYPE_LABELS: Record<number, string> = {
|
|
1: '',
|
|
3: '[图片]',
|
|
34: '[语音]',
|
|
43: '[视频]',
|
|
47: '[表情]',
|
|
49: '[分享]',
|
|
62: '[小视频]',
|
|
10000: '[系统消息]'
|
|
}
|
|
|
|
export function mapRowToCloneMessage(
|
|
row: Record<string, any>,
|
|
myWxid?: string | null
|
|
): CloneMessage | null {
|
|
const content = decodeMessageContent(getRowField(row, CONTENT_FIELDS), getRowField(row, COMPRESS_FIELDS))
|
|
const localType = getRowInt(row, LOCAL_TYPE_FIELDS, 1)
|
|
const createTime = getRowInt(row, CREATE_TIME_FIELDS, 0)
|
|
const senderUsername = getRowField(row, SENDER_FIELDS)
|
|
const isSendRaw = getRowField(row, IS_SEND_FIELDS)
|
|
let isSend = isSendRaw === null ? null : parseInt(String(isSendRaw), 10)
|
|
|
|
if (senderUsername && myWxid) {
|
|
const senderLower = String(senderUsername).toLowerCase()
|
|
const myLower = myWxid.toLowerCase()
|
|
if (isSend === null) {
|
|
isSend = senderLower === myLower ? 1 : 0
|
|
}
|
|
}
|
|
|
|
const parsedContent = parseMessageContent(content, localType)
|
|
if (!parsedContent) return null
|
|
|
|
const role: CloneRole = isSend === 1 ? 'me' : 'target'
|
|
return { role, content: parsedContent, createTime }
|
|
}
|
|
|
|
export function parseMessageContent(content: string, localType: number): string {
|
|
if (!content) {
|
|
return TYPE_LABELS[localType] || ''
|
|
}
|
|
if (Buffer.isBuffer(content as unknown)) {
|
|
content = (content as unknown as Buffer).toString('utf-8')
|
|
}
|
|
if (localType === 1) {
|
|
return stripSenderPrefix(content)
|
|
}
|
|
return TYPE_LABELS[localType] || content
|
|
}
|
|
|
|
function stripSenderPrefix(content: string): string {
|
|
const trimmed = content.trim()
|
|
const separatorIdx = trimmed.indexOf(':\n')
|
|
if (separatorIdx > 0 && separatorIdx < 64) {
|
|
return trimmed.slice(separatorIdx + 2).trim()
|
|
}
|
|
return trimmed
|
|
}
|
|
|
|
function decodeMessageContent(raw: unknown, compressed: unknown): string {
|
|
const source = raw ?? compressed
|
|
if (source == null) return ''
|
|
if (typeof source === 'string') return source
|
|
if (Buffer.isBuffer(source)) return source.toString('utf-8')
|
|
try {
|
|
return String(source)
|
|
} catch {
|
|
return ''
|
|
}
|
|
}
|
|
|
|
function getRowField(row: Record<string, any>, keys: string[]): any {
|
|
for (const key of keys) {
|
|
if (row[key] !== undefined && row[key] !== null) return row[key]
|
|
}
|
|
return null
|
|
}
|
|
|
|
function getRowInt(row: Record<string, any>, keys: string[], fallback: number): number {
|
|
const raw = getRowField(row, keys)
|
|
if (raw === null || raw === undefined) return fallback
|
|
const parsed = parseInt(String(raw), 10)
|
|
return Number.isFinite(parsed) ? parsed : fallback
|
|
}
|