action, command, event_handler易用方法更新,增加语音,混合,转发消息的发送

This commit is contained in:
UnCLAS-Prommer
2025-09-14 00:14:01 +08:00
parent 45cc6a7f7d
commit ab64eee343
10 changed files with 734 additions and 168 deletions

View File

@@ -2,9 +2,10 @@ import time
import asyncio
from abc import ABC, abstractmethod
from typing import Tuple, Optional, TYPE_CHECKING, Dict
from typing import Tuple, Optional, TYPE_CHECKING, Dict, List
from src.common.logger import get_logger
from src.common.data_models.message_data_model import ReplyContentType, ReplyContent, ReplySetModel, ForwardNode
from src.chat.message_receive.chat_stream import ChatStream
from src.plugin_system.base.component_types import ActionActivationType, ActionInfo, ComponentType
from src.plugin_system.apis import send_api, database_api, message_api
@@ -171,12 +172,15 @@ class BaseAction(ABC):
set_reply: bool = False,
reply_message: Optional["DatabaseMessages"] = None,
typing: bool = False,
storage_message: bool = True,
) -> bool:
"""发送文本消息
Args:
content: 文本内容
reply_to: 回复消息,格式为"发送者:消息内容"
set_reply: 是否作为回复发送
reply_message: 回复的消息对象当set_reply为True时必填
typing: 是否计算输入时间
Returns:
bool: 是否发送成功
@@ -191,15 +195,22 @@ class BaseAction(ABC):
set_reply=set_reply,
reply_message=reply_message,
typing=typing,
storage_message=storage_message,
)
async def send_emoji(
self, emoji_base64: str, set_reply: bool = False, reply_message: Optional["DatabaseMessages"] = None
self,
emoji_base64: str,
set_reply: bool = False,
reply_message: Optional["DatabaseMessages"] = None,
storage_message: bool = True,
) -> bool:
"""发送表情包
Args:
emoji_base64: 表情包的base64编码
set_reply: 是否作为回复发送
reply_message: 回复的消息对象当set_reply为True时必填
Returns:
bool: 是否发送成功
@@ -209,16 +220,26 @@ class BaseAction(ABC):
return False
return await send_api.emoji_to_stream(
emoji_base64, self.chat_id, set_reply=set_reply, reply_message=reply_message
emoji_base64,
self.chat_id,
set_reply=set_reply,
reply_message=reply_message,
storage_message=storage_message,
)
async def send_image(
self, image_base64: str, set_reply: bool = False, reply_message: Optional["DatabaseMessages"] = None
self,
image_base64: str,
set_reply: bool = False,
reply_message: Optional["DatabaseMessages"] = None,
storage_message: bool = True,
) -> bool:
"""发送图片
Args:
image_base64: 图片的base64编码
set_reply: 是否作为回复发送
reply_message: 回复的消息对象当set_reply为True时必填
Returns:
bool: 是否发送成功
@@ -228,7 +249,11 @@ class BaseAction(ABC):
return False
return await send_api.image_to_stream(
image_base64, self.chat_id, set_reply=set_reply, reply_message=reply_message
image_base64,
self.chat_id,
set_reply=set_reply,
reply_message=reply_message,
storage_message=storage_message,
)
async def send_command(
@@ -237,13 +262,9 @@ class BaseAction(ABC):
args: Optional[dict] = None,
display_message: str = "",
storage_message: bool = True,
set_reply: bool = False,
reply_message: Optional["DatabaseMessages"] = None,
) -> bool:
"""发送命令消息
使用stream API发送命令
Args:
command_name: 命令名称
args: 命令参数
@@ -253,34 +274,20 @@ class BaseAction(ABC):
Returns:
bool: 是否发送成功
"""
try:
if not self.chat_id:
logger.error(f"{self.log_prefix} 缺少聊天ID")
return False
# 构造命令数据
command_data = {"name": command_name, "args": args or {}}
success = await send_api.command_to_stream(
command=command_data,
stream_id=self.chat_id,
storage_message=storage_message,
display_message=display_message,
set_reply=set_reply,
reply_message=reply_message,
)
if success:
logger.info(f"{self.log_prefix} 成功发送命令: {command_name}")
else:
logger.error(f"{self.log_prefix} 发送命令失败: {command_name}")
return success
except Exception as e:
logger.error(f"{self.log_prefix} 发送命令时出错: {e}")
if not self.chat_id:
logger.error(f"{self.log_prefix} 缺少聊天ID")
return False
# 构造命令数据
command_data = {"name": command_name, "args": args or {}}
return await send_api.command_to_stream(
command=command_data,
stream_id=self.chat_id,
storage_message=storage_message,
display_message=display_message,
)
async def send_custom(
self,
message_type: str,
@@ -288,6 +295,7 @@ class BaseAction(ABC):
typing: bool = False,
set_reply: bool = False,
reply_message: Optional["DatabaseMessages"] = None,
storage_message: bool = True,
) -> bool:
"""发送自定义类型消息
@@ -295,7 +303,9 @@ class BaseAction(ABC):
message_type: 消息类型,如"video""file""audio"
content: 消息内容
typing: 是否显示正在输入
reply_to: 回复消息,格式为"发送者:消息内容"
set_reply: 是否作为回复发送
reply_message: 回复的消息对象set_reply 为 True时必填
storage_message: 是否存储消息到数据库
Returns:
bool: 是否发送成功
@@ -311,6 +321,101 @@ class BaseAction(ABC):
typing=typing,
set_reply=set_reply,
reply_message=reply_message,
storage_message=storage_message,
)
async def send_hybrid(
self,
message_tuple_list: List[Tuple[ReplyContentType | str, str]],
typing: bool = False,
set_reply: bool = False,
reply_message: Optional["DatabaseMessages"] = None,
storage_message: bool = True,
) -> bool:
"""
发送混合类型消息
Args:
message_tuple_list: 包含消息类型和内容的元组列表,格式为 [(内容类型, 内容), ...]
typing: 是否计算打字时间
set_reply: 是否作为回复发送
reply_message: 回复的消息对象
"""
if not self.chat_id:
logger.error(f"{self.log_prefix} 缺少聊天ID")
return False
reply_set = ReplySetModel()
reply_set.add_hybrid_content_by_raw(message_tuple_list)
return await send_api.custom_reply_set_to_stream(
reply_set=reply_set,
stream_id=self.chat_id,
typing=typing,
set_reply=set_reply,
reply_message=reply_message,
storage_message=storage_message,
)
async def send_forward(
self,
messages_list: List[Tuple[str, str, List[Tuple[ReplyContentType | str, str]]] | str],
storage_message: bool = True,
) -> bool:
"""转发消息
Args:
messages_list: 包含消息信息的列表,当传入自行生成的数据时,元素格式为 (sender_id, nickname, 消息体)当传入消息ID时元素格式为 "message_id"
其中消息体的格式为 [(内容类型, 内容), ...]
任意长度的消息都需要使用列表的形式传入
storage_message: 是否存储消息到数据库
Returns:
bool: 是否发送成功
"""
if not self.chat_id:
logger.error(f"{self.log_prefix} 缺少聊天ID")
return False
reply_set = ReplySetModel()
forward_message_nodes: List[ForwardNode] = []
for message in messages_list:
if isinstance(message, str):
forward_message_node = ForwardNode.construct_as_id_reference(message)
elif isinstance(message, Tuple) and len(message) == 3:
sender_id, nickname, content_list = message
single_node_content_list: List[ReplyContent] = []
for node_content_type, node_content in content_list:
reply_node_content = ReplyContent(content_type=node_content_type, content=node_content)
single_node_content_list.append(reply_node_content)
forward_message_node = ForwardNode.construct_as_created_node(
user_id=sender_id, user_nickname=nickname, content=single_node_content_list
)
else:
logger.warning(f"{self.log_prefix} 转发消息时遇到无效的消息格式: {message}")
continue
forward_message_nodes.append(forward_message_node)
reply_set.add_forward_content(forward_message_nodes)
return await send_api.custom_reply_set_to_stream(
reply_set=reply_set,
stream_id=self.chat_id,
storage_message=storage_message,
)
async def send_voice(self, audio_base64: str) -> bool:
"""
发送语音消息
Args:
audio_base64: 语音的base64编码
Returns:
bool: 是否发送成功
"""
if not audio_base64:
logger.error(f"{self.log_prefix} 缺少音频内容")
return False
reply_set = ReplySetModel()
reply_set.add_voice_content(audio_base64)
return await send_api.custom_reply_set_to_stream(
reply_set=reply_set,
stream_id=self.chat_id,
storage_message=False,
)
async def store_action_info(