diff --git a/config.py b/config.py index a7055b4..444eb53 100644 --- a/config.py +++ b/config.py @@ -1,15 +1,18 @@ """ 配置加载器 - 从 config.json 读取路径配置 -首次运行时自动生成 config.json 模板 +首次运行时自动检测微信数据目录,检测失败则提示手动配置 """ +import glob import json import os import sys CONFIG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.json") +_DEFAULT_TEMPLATE_DIR = r"D:\xwechat_files\your_wxid\db_storage" + _DEFAULT = { - "db_dir": r"D:\xwechat_files\your_wxid\db_storage", + "db_dir": _DEFAULT_TEMPLATE_DIR, "keys_file": "all_keys.json", "decrypted_dir": "decrypted", "decoded_image_dir": "decoded_images", @@ -17,16 +20,91 @@ _DEFAULT = { } -def load_config(): - if not os.path.exists(CONFIG_FILE): - with open(CONFIG_FILE, "w") as f: - json.dump(_DEFAULT, f, indent=4) - print(f"[!] 已生成配置文件: {CONFIG_FILE}") - print(" 请修改 config.json 中的路径后重新运行") - sys.exit(1) +def auto_detect_db_dir(): + """从微信本地配置自动检测 db_storage 路径。 - with open(CONFIG_FILE) as f: - cfg = json.load(f) + 读取 %APPDATA%\\Tencent\\xwechat\\config\\*.ini, + 找到数据存储根目录,然后匹配 xwechat_files\\*\\db_storage。 + """ + appdata = os.environ.get("APPDATA", "") + config_dir = os.path.join(appdata, "Tencent", "xwechat", "config") + if not os.path.isdir(config_dir): + return None + + # 从 ini 文件中找到有效的目录路径 + data_roots = [] + for ini_file in glob.glob(os.path.join(config_dir, "*.ini")): + try: + with open(ini_file, "r", encoding="utf-8") as f: + content = f.read(1024).strip() + if not content or "\n" in content or "\x00" in content: + continue + if os.path.isdir(content): + data_roots.append(content) + except (OSError, UnicodeDecodeError): + continue + + # 在每个根目录下搜索 xwechat_files\*\db_storage + seen = set() + candidates = [] + for root in data_roots: + pattern = os.path.join(root, "xwechat_files", "*", "db_storage") + for match in glob.glob(pattern): + normalized = os.path.normcase(os.path.normpath(match)) + if os.path.isdir(match) and normalized not in seen: + seen.add(normalized) + candidates.append(match) + + if len(candidates) == 1: + return candidates[0] + if len(candidates) > 1: + # 非交互环境(MCP、无 stdin 管道等)直接取第一个 + if not sys.stdin.isatty(): + return candidates[0] + print("[!] 检测到多个微信数据目录:") + for i, c in enumerate(candidates, 1): + print(f" {i}. {c}") + print(" 0. 跳过,稍后手动配置") + try: + while True: + choice = input("请选择 [0-{}]: ".format(len(candidates))).strip() + if choice == "0": + return None + if choice.isdigit() and 1 <= int(choice) <= len(candidates): + return candidates[int(choice) - 1] + print(" 无效输入,请重新选择") + except (EOFError, KeyboardInterrupt): + print() + return None + return None + + +def load_config(): + cfg = {} + if os.path.exists(CONFIG_FILE): + with open(CONFIG_FILE) as f: + cfg = json.load(f) + + # db_dir 缺失或仍为模板值时,尝试自动检测 + db_dir = cfg.get("db_dir", "") + if not db_dir or db_dir == _DEFAULT_TEMPLATE_DIR or "your_wxid" in db_dir: + detected = auto_detect_db_dir() + if detected: + print(f"[+] 自动检测到微信数据目录: {detected}") + cfg["db_dir"] = detected + # 合并默认值并保存 + cfg = {**_DEFAULT, **cfg, "db_dir": detected} + with open(CONFIG_FILE, "w") as f: + json.dump(cfg, f, indent=4, ensure_ascii=False) + print(f"[+] 已保存到: {CONFIG_FILE}") + else: + if not os.path.exists(CONFIG_FILE): + with open(CONFIG_FILE, "w") as f: + json.dump(_DEFAULT, f, indent=4) + print(f"[!] 未能自动检测微信数据目录") + print(f" 请手动编辑 {CONFIG_FILE} 中的 db_dir 字段") + print(f" 路径可在 微信设置 → 文件管理 中找到") + sys.exit(1) # 将相对路径转为绝对路径 base = os.path.dirname(os.path.abspath(__file__))