From 19e467febefe78437cff4c3537eeeb568d917dc9 Mon Sep 17 00:00:00 2001 From: tcmofashi Date: Wed, 5 Mar 2025 23:13:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A2=AB=E7=A6=81=E8=A8=80=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E5=8F=91=E9=80=81=E7=BA=BF=E7=A8=8B=E6=AD=BB=E6=8E=89?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=89=80=E6=9C=89=E7=9A=84=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=EF=BC=8C=E4=BF=AE=E5=A4=8D=E7=A9=BA=E6=97=A5=E7=A8=8B?= =?UTF-8?q?=E7=9A=84key=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + src/plugins/chat/message_sender.py | 16 +++-- src/plugins/chat/utils_image.py | 73 +++++++++++++++------- src/plugins/models/utils_model.py | 3 + src/plugins/schedule/schedule_generator.py | 2 + 5 files changed, 70 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index f704a19ba..51a11d8c2 100644 --- a/.gitignore +++ b/.gitignore @@ -185,3 +185,6 @@ cython_debug/ # PyPI configuration file .pypirc .env + +# jieba +jieba.cache diff --git a/src/plugins/chat/message_sender.py b/src/plugins/chat/message_sender.py index 998586943..970fd3682 100644 --- a/src/plugins/chat/message_sender.py +++ b/src/plugins/chat/message_sender.py @@ -52,12 +52,16 @@ class Message_Sender: await asyncio.sleep(typing_time) # 发送消息 - await self._current_bot.send_group_msg( - group_id=group_id, - message=message, - auto_escape=auto_escape - ) - print(f"\033[1;34m[调试]\033[0m 发送消息{message}成功") + try: + await self._current_bot.send_group_msg( + group_id=group_id, + message=message, + auto_escape=auto_escape + ) + print(f"\033[1;34m[调试]\033[0m 发送消息{message}成功") + except Exception as e: + print(f"发生错误 {e}") + print(f"\033[1;34m[调试]\033[0m 发送消息{message}失败") class MessageContainer: diff --git a/src/plugins/chat/utils_image.py b/src/plugins/chat/utils_image.py index efe2f1c92..922ab5228 100644 --- a/src/plugins/chat/utils_image.py +++ b/src/plugins/chat/utils_image.py @@ -7,6 +7,7 @@ from ...common.database import Database import zlib # 用于 CRC32 import base64 from nonebot import get_driver +from loguru import logger driver = get_driver() config = driver.config @@ -213,11 +214,11 @@ def storage_image(image_data: bytes) -> bytes: print(f"\033[1;31m[错误]\033[0m 保存图片失败: {str(e)}") return image_data -def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str: - """按比例压缩base64格式的图片 +def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 1024 * 1024) -> str: + """压缩base64格式的图片到指定大小 Args: base64_data: base64编码的图片数据 - scale: 压缩比例(0-1之间的浮点数) + target_size: 目标文件大小(字节),默认0.8MB Returns: str: 压缩后的base64图片数据 """ @@ -225,34 +226,64 @@ def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str: # 将base64转换为字节数据 image_data = base64.b64decode(base64_data) + # 如果已经小于目标大小,直接返回原图 + if len(image_data) <= target_size: + return base64_data + # 将字节数据转换为图片对象 img = Image.open(io.BytesIO(image_data)) - # 如果是动图,直接返回原图 - if getattr(img, 'is_animated', False): - return base64_data - + # 获取原始尺寸 + original_width, original_height = img.size + + # 计算缩放比例 + scale = min(1.0, (target_size / len(image_data)) ** 0.5) + # 计算新的尺寸 - new_width = int(img.width * scale) - new_height = int(img.height * scale) + new_width = int(original_width * scale) + new_height = int(original_height * scale) - # 缩放图片 - img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + # 创建内存缓冲区 + output_buffer = io.BytesIO() - # 转换为RGB模式(去除透明通道) - if img.mode in ('RGBA', 'P'): - img = img.convert('RGB') + # 如果是GIF,处理所有帧 + if getattr(img, "is_animated", False): + frames = [] + for frame_idx in range(img.n_frames): + img.seek(frame_idx) + new_frame = img.copy() + new_frame = new_frame.resize((new_width, new_height), Image.Resampling.LANCZOS) + frames.append(new_frame) + + # 保存到缓冲区 + frames[0].save( + output_buffer, + format='GIF', + save_all=True, + append_images=frames[1:], + optimize=True, + duration=img.info.get('duration', 100), + loop=img.info.get('loop', 0) + ) + else: + # 处理静态图片 + resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) + + # 保存到缓冲区,保持原始格式 + if img.format == 'PNG' and img.mode in ('RGBA', 'LA'): + resized_img.save(output_buffer, format='PNG', optimize=True) + else: + resized_img.save(output_buffer, format='JPEG', quality=95, optimize=True) - # 保存压缩后的图片 - output = io.BytesIO() - img.save(output, format='JPEG', quality=85, optimize=True) - compressed_data = output.getvalue() + # 获取压缩后的数据并转换为base64 + compressed_data = output_buffer.getvalue() + logger.success(f"压缩图片: {original_width}x{original_height} -> {new_width}x{new_height}") + logger.info(f"压缩前大小: {len(image_data)/1024:.1f}KB, 压缩后大小: {len(compressed_data)/1024:.1f}KB") - # 转换回base64 return base64.b64encode(compressed_data).decode('utf-8') except Exception as e: - print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {str(e)}") + logger.error(f"压缩图片失败: {str(e)}") import traceback - print(traceback.format_exc()) + logger.error(traceback.format_exc()) return base64_data \ No newline at end of file diff --git a/src/plugins/models/utils_model.py b/src/plugins/models/utils_model.py index 3ba873d74..858755cc0 100644 --- a/src/plugins/models/utils_model.py +++ b/src/plugins/models/utils_model.py @@ -124,6 +124,7 @@ class LLM_request: base_wait_time = 15 current_image_base64 = image_base64 + current_image_base64 = compress_base64_image_by_scale(current_image_base64) for retry in range(max_retries): @@ -177,6 +178,8 @@ class LLM_request: "Content-Type": "application/json" } + image_base64=compress_base64_image_by_scale(image_base64) + # 构建请求体 data = { "model": self.model_name, diff --git a/src/plugins/schedule/schedule_generator.py b/src/plugins/schedule/schedule_generator.py index 7afa5e7ba..c9a1c8910 100644 --- a/src/plugins/schedule/schedule_generator.py +++ b/src/plugins/schedule/schedule_generator.py @@ -104,6 +104,8 @@ class ScheduleGenerator: min_diff = float('inf') # 检查今天的日程 + if not self.today_schedule.keys(): + return "摸鱼" for time_str in self.today_schedule.keys(): diff = abs(self._time_diff(current_time, time_str)) if closest_time is None or diff < min_diff: