mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-04-05 15:08:14 +00:00
修复 #597;实现 #556;修复 #623与 #543;修复卡片图片问题
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { join, dirname, basename } from 'path'
|
||||
import { join, dirname, basename } from 'path'
|
||||
import { appendFileSync, existsSync, mkdirSync, readdirSync, statSync, readFileSync } from 'fs'
|
||||
import { tmpdir } from 'os'
|
||||
|
||||
@@ -92,6 +92,9 @@ export class WcdbCore {
|
||||
private wcdbResolveImageHardlinkBatch: any = null
|
||||
private wcdbResolveVideoHardlinkMd5: any = null
|
||||
private wcdbResolveVideoHardlinkMd5Batch: any = null
|
||||
private wcdbInstallMessageAntiRevokeTrigger: any = null
|
||||
private wcdbUninstallMessageAntiRevokeTrigger: any = null
|
||||
private wcdbCheckMessageAntiRevokeTrigger: any = null
|
||||
private wcdbInstallSnsBlockDeleteTrigger: any = null
|
||||
private wcdbUninstallSnsBlockDeleteTrigger: any = null
|
||||
private wcdbCheckSnsBlockDeleteTrigger: any = null
|
||||
@@ -163,7 +166,7 @@ export class WcdbCore {
|
||||
pipePath = this.koffi.decode(namePtr[0], 'char', -1)
|
||||
this.wcdbFreeString(namePtr[0])
|
||||
}
|
||||
} catch {}
|
||||
} catch { }
|
||||
}
|
||||
this.connectMonitorPipe(pipePath)
|
||||
return true
|
||||
@@ -181,7 +184,7 @@ export class WcdbCore {
|
||||
setTimeout(() => {
|
||||
if (!this.monitorCallback) return
|
||||
|
||||
this.monitorPipeClient = net.createConnection(this.monitorPipePath, () => {})
|
||||
this.monitorPipeClient = net.createConnection(this.monitorPipePath, () => { })
|
||||
|
||||
let buffer = ''
|
||||
this.monitorPipeClient.on('data', (data: Buffer) => {
|
||||
@@ -273,7 +276,7 @@ export class WcdbCore {
|
||||
const isArm64 = process.arch === 'arm64'
|
||||
const libName = isMac ? 'libwcdb_api.dylib' : isLinux ? 'libwcdb_api.so' : 'wcdb_api.dll'
|
||||
const subDir = isMac ? 'macos' : isLinux ? 'linux' : (isArm64 ? 'arm64' : '')
|
||||
|
||||
|
||||
const envDllPath = process.env.WCDB_DLL_PATH
|
||||
if (envDllPath && envDllPath.length > 0) {
|
||||
return envDllPath
|
||||
@@ -313,7 +316,7 @@ export class WcdbCore {
|
||||
'-2302': 'WCDB 初始化异常,请重试',
|
||||
'-2303': 'WCDB 未能成功初始化',
|
||||
}
|
||||
const msg = messages[String(code) as keyof typeof messages]
|
||||
const msg = messages[String(code) as unknown as keyof typeof messages]
|
||||
return msg ? `${msg} (错误码: ${code})` : `操作失败,错误码: ${code}`
|
||||
}
|
||||
|
||||
@@ -643,7 +646,7 @@ export class WcdbCore {
|
||||
const dllDir = dirname(dllPath)
|
||||
const isMac = process.platform === 'darwin'
|
||||
const isLinux = process.platform === 'linux'
|
||||
|
||||
|
||||
// 预加载依赖库
|
||||
if (isMac) {
|
||||
const wcdbCorePath = join(dllDir, 'libWCDB.dylib')
|
||||
@@ -1077,6 +1080,27 @@ export class WcdbCore {
|
||||
this.wcdbResolveVideoHardlinkMd5Batch = null
|
||||
}
|
||||
|
||||
// wcdb_status wcdb_install_message_anti_revoke_trigger(wcdb_handle handle, const char* session_id, char** out_error)
|
||||
try {
|
||||
this.wcdbInstallMessageAntiRevokeTrigger = this.lib.func('int32 wcdb_install_message_anti_revoke_trigger(int64 handle, const char* sessionId, _Out_ void** outError)')
|
||||
} catch {
|
||||
this.wcdbInstallMessageAntiRevokeTrigger = null
|
||||
}
|
||||
|
||||
// wcdb_status wcdb_uninstall_message_anti_revoke_trigger(wcdb_handle handle, const char* session_id, char** out_error)
|
||||
try {
|
||||
this.wcdbUninstallMessageAntiRevokeTrigger = this.lib.func('int32 wcdb_uninstall_message_anti_revoke_trigger(int64 handle, const char* sessionId, _Out_ void** outError)')
|
||||
} catch {
|
||||
this.wcdbUninstallMessageAntiRevokeTrigger = null
|
||||
}
|
||||
|
||||
// wcdb_status wcdb_check_message_anti_revoke_trigger(wcdb_handle handle, const char* session_id, int32_t* out_installed)
|
||||
try {
|
||||
this.wcdbCheckMessageAntiRevokeTrigger = this.lib.func('int32 wcdb_check_message_anti_revoke_trigger(int64 handle, const char* sessionId, _Out_ int32* outInstalled)')
|
||||
} catch {
|
||||
this.wcdbCheckMessageAntiRevokeTrigger = null
|
||||
}
|
||||
|
||||
// wcdb_status wcdb_install_sns_block_delete_trigger(wcdb_handle handle, char** out_error)
|
||||
try {
|
||||
this.wcdbInstallSnsBlockDeleteTrigger = this.lib.func('int32 wcdb_install_sns_block_delete_trigger(int64 handle, _Out_ void** outError)')
|
||||
@@ -1337,12 +1361,12 @@ export class WcdbCore {
|
||||
const raw = String(jsonStr || '')
|
||||
if (!raw) return []
|
||||
// 热路径优化:仅在检测到 16+ 位整数字段时才进行字符串包裹,避免每批次多轮全量 replace。
|
||||
const needsInt64Normalize = /"(?:server_id|serverId|ServerId|msg_server_id|msgServerId|MsgServerId)"\s*:\s*-?\d{16,}/.test(raw)
|
||||
const needsInt64Normalize = /"server_id"\s*:\s*-?\d{16,}/.test(raw)
|
||||
if (!needsInt64Normalize) {
|
||||
return JSON.parse(raw)
|
||||
}
|
||||
const normalized = raw.replace(
|
||||
/("(?:server_id|serverId|ServerId|msg_server_id|msgServerId|MsgServerId)"\s*:\s*)(-?\d{16,})/g,
|
||||
/("server_id"\s*:\s*)(-?\d{16,})/g,
|
||||
'$1"$2"'
|
||||
)
|
||||
return JSON.parse(normalized)
|
||||
@@ -1655,6 +1679,9 @@ export class WcdbCore {
|
||||
const outCount = [0]
|
||||
const result = this.wcdbGetMessageCount(this.handle, sessionId, outCount)
|
||||
if (result !== 0) {
|
||||
if (result === -7) {
|
||||
return { success: false, error: 'message schema mismatch:当前账号消息表结构与程序要求不一致' }
|
||||
}
|
||||
return { success: false, error: `获取消息总数失败: ${result}` }
|
||||
}
|
||||
return { success: true, count: outCount[0] }
|
||||
@@ -1685,6 +1712,9 @@ export class WcdbCore {
|
||||
const sessionId = normalizedSessionIds[i]
|
||||
const outCount = [0]
|
||||
const result = this.wcdbGetMessageCount(this.handle, sessionId, outCount)
|
||||
if (result === -7) {
|
||||
return { success: false, error: `message schema mismatch:会话 ${sessionId} 的消息表结构不匹配` }
|
||||
}
|
||||
counts[sessionId] = result === 0 && Number.isFinite(outCount[0]) ? Math.max(0, Math.floor(outCount[0])) : 0
|
||||
|
||||
if (i > 0 && i % 160 === 0) {
|
||||
@@ -1704,6 +1734,9 @@ export class WcdbCore {
|
||||
const outPtr = [null as any]
|
||||
const result = this.wcdbGetSessionMessageCounts(this.handle, JSON.stringify(sessionIds || []), outPtr)
|
||||
if (result !== 0 || !outPtr[0]) {
|
||||
if (result === -7) {
|
||||
return { success: false, error: 'message schema mismatch:当前账号消息表结构与程序要求不一致' }
|
||||
}
|
||||
return { success: false, error: `获取会话消息总数失败: ${result}` }
|
||||
}
|
||||
const jsonStr = this.decodeJsonPtr(outPtr[0])
|
||||
@@ -2661,7 +2694,9 @@ export class WcdbCore {
|
||||
)
|
||||
const hint = result === -3
|
||||
? `创建游标失败: ${result}(消息数据库未找到)。如果你最近重装过微信,请尝试重新指定数据目录后重试`
|
||||
: `创建游标失败: ${result},请查看日志`
|
||||
: result === -7
|
||||
? 'message schema mismatch:当前账号消息表结构与程序要求不一致'
|
||||
: `创建游标失败: ${result},请查看日志`
|
||||
return { success: false, error: hint }
|
||||
}
|
||||
return { success: true, cursor: outCursor[0] }
|
||||
@@ -2719,6 +2754,9 @@ export class WcdbCore {
|
||||
`openMessageCursorLite failed: sessionId=${sessionId} batchSize=${batchSize} ascending=${ascending ? 1 : 0} begin=${beginTimestamp} end=${endTimestamp} result=${result} cursor=${outCursor[0]}`,
|
||||
true
|
||||
)
|
||||
if (result === -7) {
|
||||
return { success: false, error: 'message schema mismatch:当前账号消息表结构与程序要求不一致' }
|
||||
}
|
||||
return { success: false, error: `创建游标失败: ${result},请查看日志` }
|
||||
}
|
||||
return { success: true, cursor: outCursor[0] }
|
||||
@@ -2790,14 +2828,14 @@ export class WcdbCore {
|
||||
if (!this.wcdbExecQuery) return { success: false, error: '接口未就绪' }
|
||||
const fallbackFlag = /fallback|diag|diagnostic/i.test(String(sql || ''))
|
||||
this.writeLog(`[audit:execQuery] kind=${kind} path=${path || ''} sql_len=${String(sql || '').length} fallback=${fallbackFlag ? 1 : 0}`)
|
||||
|
||||
|
||||
// 如果提供了参数,使用参数化查询(需要 C++ 层支持)
|
||||
// 注意:当前 wcdbExecQuery 可能不支持参数化,这是一个占位符实现
|
||||
// TODO: 需要更新 C++ 层的 wcdb_exec_query 以支持参数绑定
|
||||
if (params && params.length > 0) {
|
||||
console.warn('[wcdbCore] execQuery: 参数化查询暂未在 C++ 层实现,将使用原始 SQL(可能存在注入风险)')
|
||||
}
|
||||
|
||||
|
||||
const normalizedKind = String(kind || '').toLowerCase()
|
||||
const isContactQuery = normalizedKind === 'contact' || /\bfrom\s+contact\b/i.test(String(sql))
|
||||
let effectivePath = path || ''
|
||||
@@ -3481,6 +3519,122 @@ export class WcdbCore {
|
||||
return { success: false, error: String(e) }
|
||||
}
|
||||
}
|
||||
|
||||
async installMessageAntiRevokeTrigger(sessionId: string): Promise<{ success: boolean; alreadyInstalled?: boolean; error?: string }> {
|
||||
if (!this.ensureReady()) return { success: false, error: 'WCDB 未连接' }
|
||||
if (!this.wcdbInstallMessageAntiRevokeTrigger) return { success: false, error: '当前 DLL 版本不支持此功能' }
|
||||
const normalizedSessionId = String(sessionId || '').trim()
|
||||
if (!normalizedSessionId) return { success: false, error: 'sessionId 不能为空' }
|
||||
try {
|
||||
const outPtr = [null]
|
||||
const status = this.wcdbInstallMessageAntiRevokeTrigger(this.handle, normalizedSessionId, outPtr)
|
||||
let msg = ''
|
||||
if (outPtr[0]) {
|
||||
try { msg = this.koffi.decode(outPtr[0], 'char', -1) } catch { }
|
||||
try { this.wcdbFreeString(outPtr[0]) } catch { }
|
||||
}
|
||||
if (status === 1) {
|
||||
return { success: true, alreadyInstalled: true }
|
||||
}
|
||||
if (status !== 0) {
|
||||
return { success: false, error: msg || `DLL error ${status}` }
|
||||
}
|
||||
return { success: true, alreadyInstalled: false }
|
||||
} catch (e) {
|
||||
return { success: false, error: String(e) }
|
||||
}
|
||||
}
|
||||
|
||||
async uninstallMessageAntiRevokeTrigger(sessionId: string): Promise<{ success: boolean; error?: string }> {
|
||||
if (!this.ensureReady()) return { success: false, error: 'WCDB 未连接' }
|
||||
if (!this.wcdbUninstallMessageAntiRevokeTrigger) return { success: false, error: '当前 DLL 版本不支持此功能' }
|
||||
const normalizedSessionId = String(sessionId || '').trim()
|
||||
if (!normalizedSessionId) return { success: false, error: 'sessionId 不能为空' }
|
||||
try {
|
||||
const outPtr = [null]
|
||||
const status = this.wcdbUninstallMessageAntiRevokeTrigger(this.handle, normalizedSessionId, outPtr)
|
||||
let msg = ''
|
||||
if (outPtr[0]) {
|
||||
try { msg = this.koffi.decode(outPtr[0], 'char', -1) } catch { }
|
||||
try { this.wcdbFreeString(outPtr[0]) } catch { }
|
||||
}
|
||||
if (status !== 0) {
|
||||
return { success: false, error: msg || `DLL error ${status}` }
|
||||
}
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: String(e) }
|
||||
}
|
||||
}
|
||||
|
||||
async checkMessageAntiRevokeTrigger(sessionId: string): Promise<{ success: boolean; installed?: boolean; error?: string }> {
|
||||
if (!this.ensureReady()) return { success: false, error: 'WCDB 未连接' }
|
||||
if (!this.wcdbCheckMessageAntiRevokeTrigger) return { success: false, error: '当前 DLL 版本不支持此功能' }
|
||||
const normalizedSessionId = String(sessionId || '').trim()
|
||||
if (!normalizedSessionId) return { success: false, error: 'sessionId 不能为空' }
|
||||
try {
|
||||
const outInstalled = [0]
|
||||
const status = this.wcdbCheckMessageAntiRevokeTrigger(this.handle, normalizedSessionId, outInstalled)
|
||||
if (status !== 0) {
|
||||
return { success: false, error: `DLL error ${status}` }
|
||||
}
|
||||
return { success: true, installed: outInstalled[0] === 1 }
|
||||
} catch (e) {
|
||||
return { success: false, error: String(e) }
|
||||
}
|
||||
}
|
||||
|
||||
async checkMessageAntiRevokeTriggers(sessionIds: string[]): Promise<{
|
||||
success: boolean
|
||||
rows?: Array<{ sessionId: string; success: boolean; installed?: boolean; error?: string }>
|
||||
error?: string
|
||||
}> {
|
||||
if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
|
||||
return { success: true, rows: [] }
|
||||
}
|
||||
const uniqueIds = Array.from(new Set(sessionIds.map((id) => String(id || '').trim()).filter(Boolean)))
|
||||
const rows: Array<{ sessionId: string; success: boolean; installed?: boolean; error?: string }> = []
|
||||
for (const sessionId of uniqueIds) {
|
||||
const result = await this.checkMessageAntiRevokeTrigger(sessionId)
|
||||
rows.push({ sessionId, success: result.success, installed: result.installed, error: result.error })
|
||||
}
|
||||
return { success: true, rows }
|
||||
}
|
||||
|
||||
async installMessageAntiRevokeTriggers(sessionIds: string[]): Promise<{
|
||||
success: boolean
|
||||
rows?: Array<{ sessionId: string; success: boolean; alreadyInstalled?: boolean; error?: string }>
|
||||
error?: string
|
||||
}> {
|
||||
if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
|
||||
return { success: true, rows: [] }
|
||||
}
|
||||
const uniqueIds = Array.from(new Set(sessionIds.map((id) => String(id || '').trim()).filter(Boolean)))
|
||||
const rows: Array<{ sessionId: string; success: boolean; alreadyInstalled?: boolean; error?: string }> = []
|
||||
for (const sessionId of uniqueIds) {
|
||||
const result = await this.installMessageAntiRevokeTrigger(sessionId)
|
||||
rows.push({ sessionId, success: result.success, alreadyInstalled: result.alreadyInstalled, error: result.error })
|
||||
}
|
||||
return { success: true, rows }
|
||||
}
|
||||
|
||||
async uninstallMessageAntiRevokeTriggers(sessionIds: string[]): Promise<{
|
||||
success: boolean
|
||||
rows?: Array<{ sessionId: string; success: boolean; error?: string }>
|
||||
error?: string
|
||||
}> {
|
||||
if (!Array.isArray(sessionIds) || sessionIds.length === 0) {
|
||||
return { success: true, rows: [] }
|
||||
}
|
||||
const uniqueIds = Array.from(new Set(sessionIds.map((id) => String(id || '').trim()).filter(Boolean)))
|
||||
const rows: Array<{ sessionId: string; success: boolean; error?: string }> = []
|
||||
for (const sessionId of uniqueIds) {
|
||||
const result = await this.uninstallMessageAntiRevokeTrigger(sessionId)
|
||||
rows.push({ sessionId, success: result.success, error: result.error })
|
||||
}
|
||||
return { success: true, rows }
|
||||
}
|
||||
|
||||
/**
|
||||
* 为朋友圈安装删除
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user