fix: 被禁言导致发送线程死掉,修复所有的压缩,修复空日程的key error
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -185,3 +185,6 @@ cython_debug/
|
|||||||
# PyPI configuration file
|
# PyPI configuration file
|
||||||
.pypirc
|
.pypirc
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# jieba
|
||||||
|
jieba.cache
|
||||||
|
|||||||
@@ -52,12 +52,16 @@ class Message_Sender:
|
|||||||
await asyncio.sleep(typing_time)
|
await asyncio.sleep(typing_time)
|
||||||
|
|
||||||
# 发送消息
|
# 发送消息
|
||||||
await self._current_bot.send_group_msg(
|
try:
|
||||||
group_id=group_id,
|
await self._current_bot.send_group_msg(
|
||||||
message=message,
|
group_id=group_id,
|
||||||
auto_escape=auto_escape
|
message=message,
|
||||||
)
|
auto_escape=auto_escape
|
||||||
print(f"\033[1;34m[调试]\033[0m 发送消息{message}成功")
|
)
|
||||||
|
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:
|
class MessageContainer:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from ...common.database import Database
|
|||||||
import zlib # 用于 CRC32
|
import zlib # 用于 CRC32
|
||||||
import base64
|
import base64
|
||||||
from nonebot import get_driver
|
from nonebot import get_driver
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
config = driver.config
|
config = driver.config
|
||||||
@@ -213,11 +214,11 @@ def storage_image(image_data: bytes) -> bytes:
|
|||||||
print(f"\033[1;31m[错误]\033[0m 保存图片失败: {str(e)}")
|
print(f"\033[1;31m[错误]\033[0m 保存图片失败: {str(e)}")
|
||||||
return image_data
|
return image_data
|
||||||
|
|
||||||
def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str:
|
def compress_base64_image_by_scale(base64_data: str, target_size: int = 0.8 * 1024 * 1024) -> str:
|
||||||
"""按比例压缩base64格式的图片
|
"""压缩base64格式的图片到指定大小
|
||||||
Args:
|
Args:
|
||||||
base64_data: base64编码的图片数据
|
base64_data: base64编码的图片数据
|
||||||
scale: 压缩比例(0-1之间的浮点数)
|
target_size: 目标文件大小(字节),默认0.8MB
|
||||||
Returns:
|
Returns:
|
||||||
str: 压缩后的base64图片数据
|
str: 压缩后的base64图片数据
|
||||||
"""
|
"""
|
||||||
@@ -225,34 +226,64 @@ def compress_base64_image_by_scale(base64_data: str, scale: float = 0.5) -> str:
|
|||||||
# 将base64转换为字节数据
|
# 将base64转换为字节数据
|
||||||
image_data = base64.b64decode(base64_data)
|
image_data = base64.b64decode(base64_data)
|
||||||
|
|
||||||
|
# 如果已经小于目标大小,直接返回原图
|
||||||
|
if len(image_data) <= target_size:
|
||||||
|
return base64_data
|
||||||
|
|
||||||
# 将字节数据转换为图片对象
|
# 将字节数据转换为图片对象
|
||||||
img = Image.open(io.BytesIO(image_data))
|
img = Image.open(io.BytesIO(image_data))
|
||||||
|
|
||||||
# 如果是动图,直接返回原图
|
# 获取原始尺寸
|
||||||
if getattr(img, 'is_animated', False):
|
original_width, original_height = img.size
|
||||||
return base64_data
|
|
||||||
|
# 计算缩放比例
|
||||||
|
scale = min(1.0, (target_size / len(image_data)) ** 0.5)
|
||||||
|
|
||||||
# 计算新的尺寸
|
# 计算新的尺寸
|
||||||
new_width = int(img.width * scale)
|
new_width = int(original_width * scale)
|
||||||
new_height = int(img.height * scale)
|
new_height = int(original_height * scale)
|
||||||
|
|
||||||
# 缩放图片
|
# 创建内存缓冲区
|
||||||
img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
output_buffer = io.BytesIO()
|
||||||
|
|
||||||
# 转换为RGB模式(去除透明通道)
|
# 如果是GIF,处理所有帧
|
||||||
if img.mode in ('RGBA', 'P'):
|
if getattr(img, "is_animated", False):
|
||||||
img = img.convert('RGB')
|
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)
|
||||||
|
|
||||||
# 保存压缩后的图片
|
# 获取压缩后的数据并转换为base64
|
||||||
output = io.BytesIO()
|
compressed_data = output_buffer.getvalue()
|
||||||
img.save(output, format='JPEG', quality=85, optimize=True)
|
logger.success(f"压缩图片: {original_width}x{original_height} -> {new_width}x{new_height}")
|
||||||
compressed_data = output.getvalue()
|
logger.info(f"压缩前大小: {len(image_data)/1024:.1f}KB, 压缩后大小: {len(compressed_data)/1024:.1f}KB")
|
||||||
|
|
||||||
# 转换回base64
|
|
||||||
return base64.b64encode(compressed_data).decode('utf-8')
|
return base64.b64encode(compressed_data).decode('utf-8')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {str(e)}")
|
logger.error(f"压缩图片失败: {str(e)}")
|
||||||
import traceback
|
import traceback
|
||||||
print(traceback.format_exc())
|
logger.error(traceback.format_exc())
|
||||||
return base64_data
|
return base64_data
|
||||||
@@ -124,6 +124,7 @@ class LLM_request:
|
|||||||
base_wait_time = 15
|
base_wait_time = 15
|
||||||
|
|
||||||
current_image_base64 = image_base64
|
current_image_base64 = image_base64
|
||||||
|
current_image_base64 = compress_base64_image_by_scale(current_image_base64)
|
||||||
|
|
||||||
|
|
||||||
for retry in range(max_retries):
|
for retry in range(max_retries):
|
||||||
@@ -177,6 +178,8 @@ class LLM_request:
|
|||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
image_base64=compress_base64_image_by_scale(image_base64)
|
||||||
|
|
||||||
# 构建请求体
|
# 构建请求体
|
||||||
data = {
|
data = {
|
||||||
"model": self.model_name,
|
"model": self.model_name,
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ class ScheduleGenerator:
|
|||||||
min_diff = float('inf')
|
min_diff = float('inf')
|
||||||
|
|
||||||
# 检查今天的日程
|
# 检查今天的日程
|
||||||
|
if not self.today_schedule.keys():
|
||||||
|
return "摸鱼"
|
||||||
for time_str in self.today_schedule.keys():
|
for time_str in self.today_schedule.keys():
|
||||||
diff = abs(self._time_diff(current_time, time_str))
|
diff = abs(self._time_diff(current_time, time_str))
|
||||||
if closest_time is None or diff < min_diff:
|
if closest_time is None or diff < min_diff:
|
||||||
|
|||||||
Reference in New Issue
Block a user