mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-08-17 03:27:00 +08:00
fix(paths): 同步 imageKeyRoot 与 dbRoot,仅识别 xwechat_files
之前的状态面板(chat.getCurrentAccountRoot())和自动获取图片密钥(settings.imageKeyRoot) 走两个完全不同的来源,二者漂移导致状态显示 D 盘但实际扫描到 C 盘。 index.ts: - key:autoGetImageKey 优先级调整为 chat.getCurrentAccountRoot() → self.accountRoot → settings.imageKeyRoot → settings.dbRoot,让运行时识别的目录永远最优先。 - db:init:保存 dbRoot 时同步更新 imageKeyRoot,避免 settings 缓存漂移。 - db:reopenWithRoot:用户手动切换根目录时同步更新 imageKeyRoot。 settings-store.ts: - loadSettings:dbRoot 修正时同步 imageKeyRoot;若 imageKeyRoot 指向旧路径或不存在, 回退到 dbRoot。 - 新增 redirectLegacyWeChatFilesToXwechat():当 settings 里的 dbRoot/imageKeyRoot 仍指向 V3 时代的 "Documents\WeChat Files" 路径时,自动重定向到同目录下的 xwechat_files(如果存在)。 老用户升级时无需手动迁移。 wcdb4-client / windows-db-root-discovery / key-service-win: - 候选目录列表只保留 xwechat_files 形态(Documents\xwechat_files、 AppData\Roaming\Tencent\xwechat_files、macOS 的 Library/Containers/.../xwechat_files), 移除 V3 时代的 "WeChat Files" 候选。 - DB_ROOT_NAMES 只包含 xwechat_files,自动扫描也只认 V4 路径。 V3 数据(V1 头 dat / WeChat Files 目录结构)如果用户机器上还存在,仅作为残留, 不会被 WechatExplorer 当成有效数据源。
This commit is contained in:
+18
-2
@@ -297,7 +297,12 @@ app.whenReady().then(async () => {
|
|||||||
const nextWechatDb = await WechatDb.create(key, settings.dbRoot)
|
const nextWechatDb = await WechatDb.create(key, settings.dbRoot)
|
||||||
const resolvedRoot = nextWechatDb.getWcdb4Client().getAccountRoot()
|
const resolvedRoot = nextWechatDb.getWcdb4Client().getAccountRoot()
|
||||||
if (resolvedRoot && resolvedRoot !== settings.dbRoot) {
|
if (resolvedRoot && resolvedRoot !== settings.dbRoot) {
|
||||||
saveSettings({ ...settings, dbRoot: resolvedRoot })
|
// 同步更新 imageKeyRoot,避免自动获取图片密钥时扫描到错误目录
|
||||||
|
saveSettings({
|
||||||
|
...settings,
|
||||||
|
dbRoot: resolvedRoot,
|
||||||
|
imageKeyRoot: resolvedRoot
|
||||||
|
})
|
||||||
}
|
}
|
||||||
chat.setChatDb(nextWechatDb)
|
chat.setChatDb(nextWechatDb)
|
||||||
const wcdb4Client = nextWechatDb.getWcdb4Client()
|
const wcdb4Client = nextWechatDb.getWcdb4Client()
|
||||||
@@ -411,7 +416,13 @@ app.whenReady().then(async () => {
|
|||||||
ipcMain.handle('key:autoGetImageKey', async (event, options?: { save?: boolean }) => {
|
ipcMain.handle('key:autoGetImageKey', async (event, options?: { save?: boolean }) => {
|
||||||
const settings = loadSettings()
|
const settings = loadSettings()
|
||||||
const self = chat.getSelfAccountInfo()
|
const self = chat.getSelfAccountInfo()
|
||||||
const accountRoot = settings.imageKeyRoot || self?.accountRoot || settings.dbRoot
|
// 优先级:chat 真实识别到的根 → self.accountRoot → settings.imageKeyRoot → settings.dbRoot
|
||||||
|
// 必须先看 chat.getCurrentAccountRoot(),否则 settings 缓存漂移会导致扫错目录。
|
||||||
|
const accountRoot =
|
||||||
|
chat.getCurrentAccountRoot() ||
|
||||||
|
self?.accountRoot ||
|
||||||
|
settings.imageKeyRoot ||
|
||||||
|
settings.dbRoot
|
||||||
const wxid = self?.wxid
|
const wxid = self?.wxid
|
||||||
const onStatus = (message: string): void => {
|
const onStatus = (message: string): void => {
|
||||||
if (!event.sender.isDestroyed()) event.sender.send('key:imageKeyStatus', { message })
|
if (!event.sender.isDestroyed()) event.sender.send('key:imageKeyStatus', { message })
|
||||||
@@ -788,6 +799,11 @@ app.whenReady().then(async () => {
|
|||||||
ipcMain.handle('db:reopenWithRoot', (_, accountRoot: string) => {
|
ipcMain.handle('db:reopenWithRoot', (_, accountRoot: string) => {
|
||||||
const ok = chat.reopenWithRoot(accountRoot)
|
const ok = chat.reopenWithRoot(accountRoot)
|
||||||
if (!ok) return { success: false, error: '数据库未初始化或重新打开失败' }
|
if (!ok) return { success: false, error: '数据库未初始化或重新打开失败' }
|
||||||
|
// 同步 imageKeyRoot,避免自动获取扫描到旧目录
|
||||||
|
const settings = loadSettings()
|
||||||
|
if (accountRoot && accountRoot !== settings.imageKeyRoot) {
|
||||||
|
saveSettings({ ...settings, imageKeyRoot: accountRoot })
|
||||||
|
}
|
||||||
const info = chat.getSelfAccountInfo()
|
const info = chat.getSelfAccountInfo()
|
||||||
return { success: true, info }
|
return { success: true, info }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,6 +4,22 @@ import path from 'path'
|
|||||||
import os from 'os'
|
import os from 'os'
|
||||||
import { discoverWindowsDbRoots } from '../windows-db-root-discovery'
|
import { discoverWindowsDbRoots } from '../windows-db-root-discovery'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把 V3 时代的 "...\\Documents\\WeChat Files" 路径重定向到
|
||||||
|
* "...\\Documents\\xwechat_files"(V4)。如果 xwechat_files 不存在则保留原值。
|
||||||
|
* 仅支持 WeChat 4.0:自动纠正用户机器上残留的旧路径。
|
||||||
|
*/
|
||||||
|
function redirectLegacyWeChatFilesToXwechat(candidate: string): string {
|
||||||
|
if (!candidate) return candidate
|
||||||
|
const normalized = candidate.replace(/[\\/]+$/, '')
|
||||||
|
const lowered = normalized.toLowerCase()
|
||||||
|
const legacyMarker = `${path.sep}wechat files`
|
||||||
|
if (!lowered.endsWith(legacyMarker)) return candidate
|
||||||
|
const redirected = `${normalized.slice(0, -legacyMarker.length)}${path.sep}xwechat_files`
|
||||||
|
if (fs.existsSync(redirected)) return redirected
|
||||||
|
return candidate
|
||||||
|
}
|
||||||
|
|
||||||
export interface AppSettings {
|
export interface AppSettings {
|
||||||
dbRoot: string
|
dbRoot: string
|
||||||
apiEnabled: boolean
|
apiEnabled: boolean
|
||||||
@@ -25,16 +41,17 @@ function getDefaultDbRoot(): string {
|
|||||||
|
|
||||||
function getDefaultDbRootCandidates(home: string): string[] {
|
function getDefaultDbRootCandidates(home: string): string[] {
|
||||||
if (process.platform !== 'win32') {
|
if (process.platform !== 'win32') {
|
||||||
|
// macOS 仅支持 WeChat 4.0 路径(xwechat_files)
|
||||||
return [
|
return [
|
||||||
path.join(home, 'Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files')
|
path.join(home, 'Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files')
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 仅支持 WeChat 4.0:剔除 V3 时代的 "WeChat Files" 目录,
|
||||||
|
// 只认 xwechat_files(含 Documents\ 和 AppData\Roaming\Tencent\ 两种合法位置)。
|
||||||
const candidates = [
|
const candidates = [
|
||||||
...getWeflowDbPathCandidates(home),
|
...getWeflowDbPathCandidates(home),
|
||||||
path.join(home, 'Documents', 'WeChat Files'),
|
|
||||||
path.join(home, 'Documents', 'xwechat_files'),
|
path.join(home, 'Documents', 'xwechat_files'),
|
||||||
path.join(home, 'WeChat Files'),
|
|
||||||
path.join(os.homedir(), 'AppData', 'Roaming', 'Tencent', 'xwechat_files')
|
path.join(os.homedir(), 'AppData', 'Roaming', 'Tencent', 'xwechat_files')
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -123,9 +140,19 @@ export function loadSettings(): AppSettings {
|
|||||||
if (process.platform === 'win32' && !isUsableDbRoot(cache.dbRoot)) {
|
if (process.platform === 'win32' && !isUsableDbRoot(cache.dbRoot)) {
|
||||||
cache.dbRoot = getDefaultDbRoot()
|
cache.dbRoot = getDefaultDbRoot()
|
||||||
}
|
}
|
||||||
if (!cache.imageKeyRoot) {
|
// 同步:imageKeyRoot 必须跟随 dbRoot 更新,
|
||||||
|
// 否则自动获取会扫错目录(旧 bug:状态面板显示 D 盘,自动获取扫 C 盘)。
|
||||||
|
if (!cache.imageKeyRoot || !isUsableDbRoot(cache.imageKeyRoot)) {
|
||||||
cache.imageKeyRoot = cache.dbRoot
|
cache.imageKeyRoot = cache.dbRoot
|
||||||
}
|
}
|
||||||
|
// V4-only 兜底:如果 imageKeyRoot 指向旧的 "WeChat Files"(V3 路径),
|
||||||
|
// 重定向到同一父目录下的 xwechat_files(V4)。
|
||||||
|
if (cache.imageKeyRoot) {
|
||||||
|
cache.imageKeyRoot = redirectLegacyWeChatFilesToXwechat(cache.imageKeyRoot)
|
||||||
|
}
|
||||||
|
if (cache.dbRoot) {
|
||||||
|
cache.dbRoot = redirectLegacyWeChatFilesToXwechat(cache.dbRoot)
|
||||||
|
}
|
||||||
return cache
|
return cache
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -311,11 +311,10 @@ export class Wcdb4Client {
|
|||||||
private static getDefaultRootCandidates(): string[] {
|
private static getDefaultRootCandidates(): string[] {
|
||||||
const home = os.homedir()
|
const home = os.homedir()
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
|
// 仅支持 WeChat 4.0:只认 xwechat_files,V3 时代的 "WeChat Files" 不再加入候选
|
||||||
const candidates = [
|
const candidates = [
|
||||||
...Wcdb4Client.getWeflowDbPathCandidates(home),
|
...Wcdb4Client.getWeflowDbPathCandidates(home),
|
||||||
path.join(home, 'Documents', 'WeChat Files'),
|
|
||||||
path.join(home, 'Documents', 'xwechat_files'),
|
path.join(home, 'Documents', 'xwechat_files'),
|
||||||
path.join(home, 'WeChat Files'),
|
|
||||||
path.join(home, 'AppData', 'Roaming', 'Tencent', 'xwechat_files')
|
path.join(home, 'AppData', 'Roaming', 'Tencent', 'xwechat_files')
|
||||||
]
|
]
|
||||||
candidates.push(...discoverWindowsDbRoots())
|
candidates.push(...discoverWindowsDbRoots())
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import fs from 'fs-extra'
|
import fs from 'fs-extra'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
const DB_ROOT_NAMES = new Set(['xwechat_files', 'wechat files'])
|
// 仅支持 WeChat 4.0:只扫描 xwechat_files;旧 V3 时代的 "WeChat Files" 不再纳入候选
|
||||||
|
const DB_ROOT_NAMES = new Set(['xwechat_files'])
|
||||||
const SKIPPED_DIRECTORY_NAMES = new Set([
|
const SKIPPED_DIRECTORY_NAMES = new Set([
|
||||||
'$recycle.bin',
|
'$recycle.bin',
|
||||||
'system volume information',
|
'system volume information',
|
||||||
|
|||||||
Reference in New Issue
Block a user