diff --git a/src/plugins/built_in/Maizone/config_loader.py b/src/plugins/built_in/Maizone/config_loader.py index f429f3f23..d3b7ba811 100644 --- a/src/plugins/built_in/Maizone/config_loader.py +++ b/src/plugins/built_in/Maizone/config_loader.py @@ -106,68 +106,8 @@ class MaiZoneConfigLoader: self.config_file_path = self.plugin_dir / config_filename self.config_data: Dict[str, Any] = {} self.config_specs: Dict[str, ConfigSectionSpec] = {} - self.config_version = "2.0.0" + self.config_version = "2.1.0" - # 初始化配置规格 - self._init_config_specs() - - def _init_config_specs(self): - """初始化配置规格定义""" - # 插件基础配置节 - plugin_section = ConfigSectionSpec("plugin", "插件基础配置") - plugin_section.add_field(ConfigFieldSpec("enable", bool, True, "是否启用插件")) - plugin_section.add_field(ConfigFieldSpec("config_version", str, "2.0.0", "配置文件版本")) - plugin_section.add_field(ConfigFieldSpec("http_port", str, "3000", "NapCat HTTP服务器端口号")) - plugin_section.add_field(ConfigFieldSpec("http_host", str, "127.0.0.1", "NapCat HTTP服务器地址")) - self.config_specs["plugin"] = plugin_section - - # 模型相关配置节 - models_section = ConfigSectionSpec("models", "模型相关配置") - models_section.add_field(ConfigFieldSpec("text_model", str, "replyer_1", "生成文本的模型名称")) - models_section.add_field(ConfigFieldSpec("siliconflow_apikey", str, "", "硅基流动AI生图API密钥")) - self.config_specs["models"] = models_section - - # 发送说说配置节 - send_section = ConfigSectionSpec("send", "发送说说配置") - send_section.add_field(ConfigFieldSpec("permission", list, ["2488036428"], "发送权限QQ号列表")) - send_section.add_field(ConfigFieldSpec("permission_type", str, "whitelist", "权限类型", - choices=["whitelist", "blacklist"])) - send_section.add_field(ConfigFieldSpec("enable_image", bool, False, "是否启用说说配图")) - send_section.add_field(ConfigFieldSpec("enable_ai_image", bool, False, "是否启用AI生成配图")) - send_section.add_field(ConfigFieldSpec("enable_reply", bool, True, "生成完成时是否发出回复")) - send_section.add_field(ConfigFieldSpec("ai_image_number", int, 1, "AI生成图片数量", - min_value=1, max_value=4)) - send_section.add_field(ConfigFieldSpec("image_directory", str, "./plugins/built_in/Maizone/images", - "图片存储目录")) - self.config_specs["send"] = send_section - - # 阅读说说配置节 - read_section = ConfigSectionSpec("read", "阅读说说配置") - read_section.add_field(ConfigFieldSpec("permission", list, [], "阅读权限QQ号列表")) - read_section.add_field(ConfigFieldSpec("permission_type", str, "blacklist", "权限类型", - choices=["whitelist", "blacklist"])) - read_section.add_field(ConfigFieldSpec("read_number", int, 5, "一次读取的说说数量", - min_value=1, max_value=20)) - read_section.add_field(ConfigFieldSpec("like_possibility", float, 1.0, "点赞概率", - min_value=0.0, max_value=1.0)) - read_section.add_field(ConfigFieldSpec("comment_possibility", float, 0.3, "评论概率", - min_value=0.0, max_value=1.0)) - self.config_specs["read"] = read_section - - # 自动监控配置节 - monitor_section = ConfigSectionSpec("monitor", "自动监控配置") - monitor_section.add_field(ConfigFieldSpec("enable_auto_monitor", bool, False, "是否启用自动监控好友说说")) - monitor_section.add_field(ConfigFieldSpec("interval_minutes", int, 10, "监控间隔时间(分钟)", - min_value=1, max_value=1440)) - self.config_specs["monitor"] = monitor_section - - # 定时发送配置节 - schedule_section = ConfigSectionSpec("schedule", "定时发送配置") - schedule_section.add_field(ConfigFieldSpec("enable_schedule", bool, False, "是否启用定时发送说说")) - schedule_section.add_field(ConfigFieldSpec("schedules", dict, - {"08:00": "早安", "22:00": "晚安"}, - "定时发送任务列表, 格式为 {\"时间\": \"主题\"}")) - self.config_specs["schedule"] = schedule_section def load_config(self) -> bool: """ diff --git a/src/plugins/built_in/Maizone/monitor.py b/src/plugins/built_in/Maizone/monitor.py index 0bcce47f2..17f3f6674 100644 --- a/src/plugins/built_in/Maizone/monitor.py +++ b/src/plugins/built_in/Maizone/monitor.py @@ -83,14 +83,12 @@ class MonitorManager: try: # 获取配置 qq_account = config_api.get_global_config("bot.qq_account", "") - port = str(self.plugin.get_config("plugin.http_port", "3000")) - host = str(self.plugin.get_config("plugin.http_host", "127.0.0.1")) read_num = 10 # 监控时读取较少的说说数量 logger.info("监控任务: 开始检查好友说说") - # 创建QZone管理器 - qzone_manager = QZoneManager(port, host) + # 创建QZone管理器 (监控模式不需要stream_id) + qzone_manager = QZoneManager() # 获取监控说说列表 feeds_list = await qzone_manager.monitor_read_feed(qq_account, read_num) diff --git a/src/plugins/built_in/Maizone/plugin.py b/src/plugins/built_in/Maizone/plugin.py index 1efdae6cc..1a27a39b7 100644 --- a/src/plugins/built_in/Maizone/plugin.py +++ b/src/plugins/built_in/Maizone/plugin.py @@ -200,14 +200,15 @@ class SendFeedCommand(BaseCommand): """发送说说到QQ空间""" try: # 获取配置 - port = str(self.get_config("plugin.http_port", "3000")) - host = str(self.get_config("plugin.http_host", "127.0.0.1")) qq_account = config_api.get_global_config("bot.qq_account", "") enable_image = bool(self.get_config("send.enable_image", False)) image_dir = str(self.get_config("send.image_directory", "./plugins/Maizone/images")) + # 获取聊天流ID + stream_id = self.message.chat_stream.stream_id if self.message and self.message.chat_stream else None + # 创建QZone管理器并发送 - qzone_manager = QZoneManager(port, host) + qzone_manager = QZoneManager(stream_id) success = await qzone_manager.send_feed(story, image_dir, qq_account, enable_image) return success @@ -407,14 +408,15 @@ class SendFeedAction(BaseAction): """发送说说到QQ空间""" try: # 获取配置 - port = str(self.get_config("plugin.http_port", "3000")) - host = str(self.get_config("plugin.http_host", "127.0.0.1")) qq_account = config_api.get_global_config("bot.qq_account", "") enable_image = bool(self.get_config("send.enable_image", False)) image_dir = str(self.get_config("send.image_directory", "./plugins/Maizone/images")) + # 获取聊天流ID + stream_id = self.chat_stream.stream_id if self.chat_stream else None + # 创建QZone管理器并发送 - qzone_manager = QZoneManager(port, host) + qzone_manager = QZoneManager(stream_id) success = await qzone_manager.send_feed(story, image_dir, qq_account, enable_image) return success @@ -540,8 +542,6 @@ class ReadFeedAction(BaseAction): """读取并处理说说""" try: # 获取配置 - port = str(self.get_config("plugin.http_port", "3000")) - host = str(self.get_config("plugin.http_host", "127.0.0.1")) qq_account = config_api.get_global_config("bot.qq_account", "") num_raw = self.get_config("read.read_number", 5) num = int(num_raw if num_raw is not None else 5) @@ -550,8 +550,11 @@ class ReadFeedAction(BaseAction): comment_raw = self.get_config("read.comment_possibility", 1.0) comment_possibility = float(comment_raw if comment_raw is not None else 1.0) + # 获取聊天流ID + stream_id = self.chat_stream.stream_id if self.chat_stream else None + # 创建QZone管理器并读取说说 - qzone_manager = QZoneManager(port, host) + qzone_manager = QZoneManager(stream_id) feeds_list = await qzone_manager.read_feed(qq_account, target_qq, num) # 处理错误情况 @@ -709,9 +712,7 @@ class MaiZonePlugin(BasePlugin): config_schema: dict = { "plugin": { "enable": ConfigField(type=bool, default=True, description="是否启用插件"), - "config_version": ConfigField(type=str, default="2.0.0", description="配置文件版本"), - "http_port": ConfigField(type=str, default='3000', description="NapCat HTTP服务器端口号"), - "http_host": ConfigField(type=str, default='127.0.0.1', description="NapCat HTTP服务器地址"), + "config_version": ConfigField(type=str, default="2.1.0", description="配置文件版本"), }, "models": { "text_model": ConfigField(type=str, default="replyer_1", description="生成文本的模型名称"), diff --git a/src/plugins/built_in/Maizone/qzone_utils.py b/src/plugins/built_in/Maizone/qzone_utils.py index 635838956..ae092046f 100644 --- a/src/plugins/built_in/Maizone/qzone_utils.py +++ b/src/plugins/built_in/Maizone/qzone_utils.py @@ -16,7 +16,7 @@ import json5 from src.chat.utils.utils_image import get_image_manager from src.common.logger import get_logger -from src.plugin_system.apis import llm_api, config_api, emoji_api +from src.plugin_system.apis import llm_api, config_api, emoji_api, send_api # 获取日志记录器 logger = get_logger('MaiZone-Utils') @@ -62,45 +62,43 @@ class CookieManager: raise ValueError("无法从Cookie字符串中提取UIN") @staticmethod - async def fetch_cookies(domain: str, port: str, host: str) -> Dict[str, Any]: - """从NapCat获取Cookie""" - url = f"http://{host}:{port}/get_cookies?domain={domain}" - logger.info(f"正在从NapCat获取Cookie,URL: {url}") + async def fetch_cookies(domain: str, stream_id: Optional[str] = None) -> Dict[str, Any]: + """通过适配器API从NapCat获取Cookie""" + logger.info(f"正在通过适配器API获取Cookie,域名: {domain}") try: - async with httpx.AsyncClient(timeout=20.0, trust_env=False) as client: - logger.debug(f"发送GET请求到: {url}") - resp = await client.get(url) - logger.debug(f"响应状态码: {resp.status_code}") + # 使用适配器命令API获取cookie + response = await send_api.adapter_command_to_stream( + action="get_cookies", + params={"domain": domain}, + stream_id=stream_id, + timeout=40.0, + storage_message=False + ) + + logger.info(f"适配器响应: {response}") + + if response.get("status") == "ok": + data = response.get("data", {}) + if "cookies" in data: + logger.info("成功通过适配器API获取Cookie") + return data + else: + raise RuntimeError(f"适配器返回的数据中缺少cookies字段: {data}") + else: + error_msg = response.get("message", "未知错误") + raise RuntimeError(f"适配器API获取Cookie失败: {error_msg}") - resp.raise_for_status() - data = resp.json() - logger.info(f"响应数据: {data}") - - if data.get("status") != "ok" or "cookies" not in data.get("data", {}): - raise RuntimeError(f"获取Cookie失败: {data}") - - logger.info("成功从NapCat获取Cookie") - return data["data"] - except httpx.ConnectError as e: - logger.error(f"无法连接到NapCat服务器 {host}:{port} - 请检查NapCat是否运行: {str(e)}") - raise - except httpx.TimeoutException as e: - logger.error(f"连接NapCat超时: {str(e)}") - raise - except httpx.HTTPStatusError as e: - logger.error(f"NapCat返回错误状态码 {e.response.status_code}: {e.response.text}") - raise except Exception as e: - logger.error(f"从NapCat获取Cookie失败: {str(e)}") + logger.error(f"通过适配器API获取Cookie失败: {str(e)}") raise @staticmethod - async def renew_cookies(port: str, host: str) -> bool: + async def renew_cookies(stream_id: Optional[str] = None) -> bool: """更新Cookie文件""" try: domain = "user.qzone.qq.com" - cookie_data = await CookieManager.fetch_cookies(domain, port, host) + cookie_data = await CookieManager.fetch_cookies(domain, stream_id) cookie_str = cookie_data["cookies"] parsed_cookies = CookieManager.parse_cookie_string(cookie_str) uin = CookieManager.extract_uin_from_cookie(cookie_str) @@ -755,17 +753,16 @@ class QZoneAPI: class QZoneManager: """QQ空间管理器 - 高级封装类""" - def __init__(self, port: str, host: str): + def __init__(self, stream_id: Optional[str] = None): """初始化QZone管理器""" - self.port = port - self.host = host + self.stream_id = stream_id self.cookie_manager = CookieManager() async def _get_qzone_api(self, qq_account: str) -> Optional[QZoneAPI]: """获取QZone API实例""" try: # 更新Cookie - await self.cookie_manager.renew_cookies(self.port, self.host) + await self.cookie_manager.renew_cookies(self.stream_id) # 加载Cookie cookies = self.cookie_manager.load_cookies(qq_account) diff --git a/src/plugins/built_in/Maizone/scheduler.py b/src/plugins/built_in/Maizone/scheduler.py index 94bc3dba5..cb513b9f3 100644 --- a/src/plugins/built_in/Maizone/scheduler.py +++ b/src/plugins/built_in/Maizone/scheduler.py @@ -233,14 +233,12 @@ class ScheduleManager: """发送定时说说""" try: # 获取配置 - port = str(self.plugin.get_config("plugin.http_port", "3000")) - host = self.plugin.get_config("plugin.http_host", "127.0.0.1") qq_account = config_api.get_global_config("bot.qq_account", "") enable_image = self.plugin.get_config("send.enable_image", False) image_dir = str(self.plugin.get_config("send.image_directory", "./plugins/Maizone/images")) - # 创建QZone管理器并发送 - qzone_manager = QZoneManager(port, host) + # 创建QZone管理器并发送 (定时任务不需要stream_id) + qzone_manager = QZoneManager() success = await qzone_manager.send_feed(story, image_dir, qq_account, enable_image) if success: