迁移wechat_ipad配置到环境变量并清理本地状态文件

This commit is contained in:
liuwei
2026-05-07 10:22:40 +08:00
parent fe8b7171fd
commit d0acd33b66
16 changed files with 271 additions and 67 deletions

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import asyncio
import os
import threading
import time
import tomllib
@@ -216,20 +217,22 @@ class Robot:
def init_wechat_ipad(self):
"""初始化wechat_ipad客户端"""
try:
# 读取config.toml文件
with open("wechat_ipad/config.toml", "rb") as f:
self.ipad_config = tomllib.load(f)
# wechat_ipad 静态配置统一走 Config
# 1. 用户现在只需要维护 `.env` / `config.yaml`,不必再手工维护独立 TOML
# 2. 登录态仍保留本地缓存文件,但只作为运行期状态,不再作为主配置源;
# 3. 这里先做一次“静态配置 + 本地状态缓存 + 历史 config.toml”的合并保证升级不中断。
self.ipad_config = self._build_wechat_ipad_runtime_config()
self.LOG.debug("正在初始化wechat_ipad客户端...")
# 检查必要的配置
server_url = self.ipad_config.get("server_url", "")
server_url = str(self.ipad_config.get("server_url", "") or "").strip()
if server_url == "":
self.LOG.error("server_url不能为空wechat_ipad初始化失败")
return False
server_ip = self.ipad_config.get("server_ip", "")
server_port = self.ipad_config.get("server_port", 8059)
server_ip = str(self.ipad_config.get("server_ip", "") or "").strip()
server_port = int(self.ipad_config.get("server_port", 8059) or 8059)
# 当前阶段先通过 Gateway 承接 provider 选择:
# 1. 默认仍走 legacy_855保持现有现网协议行为
@@ -275,7 +278,7 @@ class Robot:
# 3. 这样未来切到 864 时,主链路只需要替换 provider而不是继续改这里的大循环。
await self.ipad_bot.run_runtime(
ipad_config=self.ipad_config,
config_path="wechat_ipad/config.toml",
state_path=str(self.ipad_config.get("state_file", "temp/wechat_ipad/config.toml") or "temp/wechat_ipad/config.toml"),
logger=self.LOG,
on_login_ready=self._on_ipad_login_ready,
on_history_message=self._archive_startup_history_message,
@@ -289,6 +292,68 @@ class Robot:
self.LOG.exception(f"wechat_ipad客户端运行出错: {e}")
self.ipad_running = False
def _build_wechat_ipad_runtime_config(self) -> dict:
"""构建 wechat_ipad 的运行时配置快照。
合并顺序说明:
1. 先取 `config.yaml + .env` 里的静态连接配置,作为新的唯一人工维护入口;
2. 再补本地状态缓存中的 wxid / device 信息,避免每次启动都重新扫码;
3. 最后兼容历史 `wechat_ipad/config.toml`,让老环境升级后可以平滑迁移。
"""
base_config = dict(getattr(self.config, "wechat_ipad", {}) or {})
state_path = str(base_config.get("state_file", "temp/wechat_ipad/config.toml") or "temp/wechat_ipad/config.toml")
legacy_config_path = str(
base_config.get("legacy_config_path", "wechat_ipad/config.toml") or "wechat_ipad/config.toml"
)
state_config = self._load_toml_config_if_exists(state_path)
legacy_config = {}
if os.path.abspath(state_path) != os.path.abspath(legacy_config_path):
legacy_config = self._load_toml_config_if_exists(legacy_config_path)
merged_config = dict(base_config)
# 静态字段优先级:`.env/config.yaml` > 历史文件。
# 这样每个人只要改 `.env` 就能切换自己的 server不需要再同步别处。
for field_name in ("server_url", "server_ip", "server_port", "server_type"):
if not str(merged_config.get(field_name, "") or "").strip():
legacy_value = legacy_config.get(field_name)
if legacy_value not in (None, ""):
merged_config[field_name] = legacy_value
# 动态字段优先级:显式环境变量 > 新状态文件 > 历史 config.toml。
# 这样既支持用户手工覆盖,也保留现有登录缓存迁移能力。
for field_name in ("wxid", "device_name", "device_id", "login_time"):
current_value = merged_config.get(field_name)
if str(current_value or "").strip():
continue
state_value = state_config.get(field_name)
if state_value not in (None, ""):
merged_config[field_name] = state_value
continue
legacy_value = legacy_config.get(field_name)
if legacy_value not in (None, ""):
merged_config[field_name] = legacy_value
merged_config["state_file"] = state_path
merged_config["legacy_config_path"] = legacy_config_path
return merged_config
def _load_toml_config_if_exists(self, file_path: str) -> dict:
"""安全读取一个 TOML 文件,缺失或格式异常时回退为空配置。"""
normalized_path = str(file_path or "").strip()
if not normalized_path or not os.path.exists(normalized_path):
return {}
try:
with open(normalized_path, "rb") as f:
return tomllib.load(f)
except Exception as e:
self.LOG.warning(f"读取 TOML 配置失败,将按空配置继续: path={normalized_path}, error={e}")
return {}
async def _on_ipad_login_ready(self, login_identity: dict) -> None:
"""处理 provider 登录成功后的项目侧初始化动作。