Files
abot/plugins/xiuren_image/main.py

208 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
from loguru import logger
import os
from typing import Dict, Any, List, Optional, Tuple
from db.connection import DBConnectionManager
from base.plugin_common.message_plugin_interface import MessagePluginInterface
from base.plugin_common.plugin_interface import PluginStatus
from plugins.xiuren_image.images_cache import ImageCacheManager
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.revoke.message_auto_revoke import MessageAutoRevoke
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
from utils.decorator.points_decorator import plugin_points_cost
from wechat_ipad import WechatAPIClient
class XiurenImagePlugin(MessagePluginInterface):
"""秀人图片插件"""
@property
def name(self) -> str:
return "秀人图片"
@property
def version(self) -> str:
return "1.0.0"
@property
def description(self) -> str:
return "提供随机秀人网图片功能"
@property
def author(self) -> str:
return "Trae AI"
@property
def command_prefix(self) -> Optional[str]:
return "" # 不需要前缀,直接匹配命令
@property
def commands(self) -> List[str]:
return self._commands
def __init__(self):
super().__init__()
# 使用Path对象处理路径自动适应不同操作系统
self.image_folder = str(Path(Path(__file__).parent.parent.parent, "xiuren"))
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件"""
self.LOG = logger
self.LOG.info(f"正在初始化 {self.name} 插件...")
# 保存上下文对象
self.event_system = context.get("event_system")
self._commands = self._config.get("XiurenImage", {}).get("command", ["图来", "秀人"])
self.command_format = self._config.get("XiurenImage", {}).get("command-format", "图来")
self.enable = self._config.get("XiurenImage", {}).get("enable", True)
# 从配置获取图片文件夹,如果配置中有值则使用配置值
config_image_folder = self._config.get("XiurenImage", {}).get("image_folder")
if config_image_folder:
self.image_folder = config_image_folder
# 检查图片文件夹是否存在
try:
if not os.path.exists(self.image_folder):
self.LOG.warning(f"图片文件夹不存在: {self.image_folder}")
os.makedirs(self.image_folder, exist_ok=True)
except Exception as e:
self.LOG.error(f"创建图片文件夹失败: {e}")
self.LOG.info(f"[{self.name}] 插件初始化完成,指令:{self._commands},图片目录:{self.image_folder}")
return True
def start(self) -> bool:
"""启动插件"""
self.LOG.info(f"[{self.name}] 插件已启动")
self.status = PluginStatus.RUNNING
return True
def stop(self) -> bool:
"""停止插件"""
self.LOG.info(f"[{self.name}] 插件已停止")
self.status = PluginStatus.STOPPED
return True
def can_process(self, message: Dict[str, Any]) -> bool:
"""检查是否可以处理该消息"""
if not self.enable:
return False
content = str(message.get("content", "")).strip()
command = content.split(" ")[0]
return command in self._commands
@plugin_stats_decorator(plugin_name="秀人图片")
@plugin_points_cost(2, "秀人图片消耗积分", Feature.PIC)
async def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""处理消息"""
content = str(message.get("content", "")).strip()
self.LOG.debug(f"插件执行: {self.name}{content}")
sender = message.get("sender")
roomid = message.get("roomid", "")
gbm: GroupBotManager = message.get("gbm")
bot: WechatAPIClient = message.get("bot")
revoke: MessageAutoRevoke = message.get("revoke")
# 检查权限
if roomid and gbm.get_group_permission(roomid, Feature.PIC) == PermissionStatus.DISABLED:
return False, "没有权限"
try:
# 获取随机图片
pic_path = self._get_random_pic()
self.LOG.info(f"返回图片地址:{pic_path}")
if not pic_path:
client_msg_id, create_time, new_msg_id = await bot.send_text_message((roomid if roomid else sender),
f"❌未找到图片资源",
sender)
revoke.add_message_to_revoke(roomid, client_msg_id, create_time, new_msg_id, 5)
return False, "未找到图片资源"
# 发送图片
client_msg_id, create_time, new_msg_id = await bot.send_image_message((roomid if roomid else sender),
Path(pic_path))
# revoke.add_message_to_revoke(roomid, client_msg_id, create_time, new_msg_id, 90)
self.LOG.info(
f"发送图片结果,client_msg_id= {client_msg_id},create_time={create_time},new_msg_id={new_msg_id}")
return True, "发送成功"
except Exception as e:
self.LOG.error(f"处理图片请求出错: {e}")
return False, f"处理出错: {e}"
def _get_random_pic(self) -> Optional[str]:
"""
从 Redis 随机获取图片路径
"""
redis_key = ImageCacheManager.IMAGE_KEY_PREFIX + "all"
try:
img = DBConnectionManager.get_instance().get_redis_connection().srandmember(redis_key)
if img:
# redis 返回 bytes转字符串
return img.decode('utf-8') if isinstance(img, bytes) else img
else:
self.LOG.warning("Redis 中没有图片数据")
return None
except Exception as e:
self.LOG.error(f"从 Redis 获取随机图片失败: {e}")
return None
# def _get_random_pic(self) -> Optional[str]:
# """获取随机图片路径"""
# try:
# # 获取图片文件夹中的所有图片
# if not os.path.exists(self.image_folder):
# self.LOG.error(f"图片文件夹不存在: {self.image_folder}")
# return None
#
# # 检查读取权限
# if not os.access(self.image_folder, os.R_OK):
# self.LOG.error(f"没有图片文件夹的读取权限: {self.image_folder}")
# return None
#
# self.LOG.debug(f"扫描图片目录: {self.image_folder} (包括子目录)")
#
# image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'}
# image_files = []
#
# # 使用 os.walk() 递归遍历所有子目录
# try:
# for root, _, files in os.walk(self.image_folder):
# for file in files:
# try:
# _, ext = os.path.splitext(file)
# if ext.lower() in image_extensions:
# full_path = os.path.join(root, file)
# # 检查文件是否可读
# if os.access(full_path, os.R_OK):
# image_files.append(full_path)
# else:
# self.LOG.warning(f"文件无法读取: {full_path}")
# except Exception as file_err:
# self.LOG.warning(f"处理文件时出错: {file} - {file_err}")
# except Exception as walk_err:
# self.LOG.error(f"遍历目录时出错: {walk_err}")
# return None
#
# if not image_files:
# self.LOG.warning("在目录中未找到图片文件(包括子目录)")
# return None
#
# # 随机选择一张图片
# try:
# random_pic = random.choice(image_files)
# return random_pic # 直接返回路径不需要再调用os.path.abspath
# except Exception as choice_err:
# self.LOG.error(f"选择随机图片时出错: {choice_err}")
# return None
#
# except Exception as e:
# self.LOG.error(f"获取随机图片出错: {e}")
# return None