Merge branch 'master' of https://github.com/MaiBot-Plus/MaiMbot-Pro-Max
This commit is contained in:
@@ -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:
|
||||
"""
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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="生成文本的模型名称"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user