接入event
This commit is contained in:
14
plugins/napcat_adapter_plugin/event_types.py
Normal file
14
plugins/napcat_adapter_plugin/event_types.py
Normal file
@@ -0,0 +1,14 @@
|
||||
class NapcatEvent:
|
||||
# napcat插件事件枚举类
|
||||
ON_RECEIVED_TEXT = "napcat_on_received_text"
|
||||
ON_RECEIVED_FACE = "napcat_on_received_face"
|
||||
ON_RECEIVED_REPLY = "napcat_on_received_reply"
|
||||
ON_RECEIVED_IMAGE = "napcat_on_received_image"
|
||||
ON_RECEIVED_RECORD = "napcat_on_received_record"
|
||||
ON_RECEIVED_VIDEO = "napcat_on_received_video"
|
||||
ON_RECEIVED_AT = "napcat_on_received_at"
|
||||
ON_RECEIVED_DICE = "napcat_on_received_dice"
|
||||
ON_RECEIVED_SHAKE = "napcat_on_received_shake"
|
||||
ON_RECEIVED_JSON = "napcat_on_received_json"
|
||||
ON_RECEIVED_RPS = "napcat_on_received_rps"
|
||||
ON_FRIEND_INPUT = "napcat_on_friend_input"
|
||||
@@ -35,6 +35,7 @@ class NoticeType: # 通知事件
|
||||
|
||||
class Notify:
|
||||
poke = "poke" # 戳一戳
|
||||
input_status = "input_status" # 正在输入
|
||||
|
||||
class GroupBan:
|
||||
ban = "ban" # 禁言
|
||||
@@ -56,6 +57,7 @@ class RealMessageType: # 实际消息分类
|
||||
reply = "reply" # 回复消息
|
||||
forward = "forward" # 转发消息
|
||||
node = "node" # 转发消息节点
|
||||
json = "json" # json消息
|
||||
|
||||
|
||||
class MessageSentType:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from ...event_types import NapcatEvent
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
from src.common.logger import get_logger
|
||||
logger = get_logger("napcat_adapter")
|
||||
|
||||
@@ -327,12 +329,14 @@ class MessageHandler:
|
||||
case RealMessageType.text:
|
||||
ret_seg = await self.handle_text_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_TEXT,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("text处理失败")
|
||||
case RealMessageType.face:
|
||||
ret_seg = await self.handle_face_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_FACE,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("face处理失败或不支持")
|
||||
@@ -340,6 +344,7 @@ class MessageHandler:
|
||||
if not in_reply:
|
||||
ret_seg = await self.handle_reply_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_REPLY,message_seg=ret_seg)
|
||||
seg_message += ret_seg
|
||||
else:
|
||||
logger.warning("reply处理失败")
|
||||
@@ -347,6 +352,7 @@ class MessageHandler:
|
||||
logger.debug(f"开始处理图片消息段")
|
||||
ret_seg = await self.handle_image_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_IMAGE,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
logger.debug(f"图片处理成功,添加到消息段")
|
||||
else:
|
||||
@@ -355,6 +361,7 @@ class MessageHandler:
|
||||
case RealMessageType.record:
|
||||
ret_seg = await self.handle_record_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_RECORD,message_seg=ret_seg)
|
||||
seg_message.clear()
|
||||
seg_message.append(ret_seg)
|
||||
break # 使得消息只有record消息
|
||||
@@ -363,6 +370,7 @@ class MessageHandler:
|
||||
case RealMessageType.video:
|
||||
ret_seg = await self.handle_video_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_VIDEO,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("video处理失败")
|
||||
@@ -373,17 +381,33 @@ class MessageHandler:
|
||||
raw_message.get("group_id"),
|
||||
)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_AT,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("at处理失败")
|
||||
case RealMessageType.rps:
|
||||
logger.warning("暂时不支持猜拳魔法表情解析")
|
||||
ret_seg = await self.handle_rps_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_RPS,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("rps处理失败")
|
||||
case RealMessageType.dice:
|
||||
logger.warning("暂时不支持骰子表情解析")
|
||||
ret_seg = await self.handle_dice_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_DICE,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("dice处理失败")
|
||||
case RealMessageType.shake:
|
||||
# 预计等价于戳一戳
|
||||
logger.warning("暂时不支持窗口抖动解析")
|
||||
ret_seg = await self.handle_shake_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_SHAKE,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("shake处理失败")
|
||||
case RealMessageType.share:
|
||||
print("\n\n哦哦哦噢噢噢哦哦你收到了一个超级无敌SHARE消息,快速速把你刚刚收到的消息截图发到MoFox-Bot群里!!!!\n\n")
|
||||
logger.warning("暂时不支持链接解析")
|
||||
case RealMessageType.forward:
|
||||
messages = await self._get_forward_message(sub_message)
|
||||
@@ -396,7 +420,15 @@ class MessageHandler:
|
||||
else:
|
||||
logger.warning("转发消息处理失败")
|
||||
case RealMessageType.node:
|
||||
print("\n\n哦哦哦噢噢噢哦哦你收到了一个超级无敌NODE消息,快速速把你刚刚收到的消息截图发到MoFox-Bot群里!!!!\n\n")
|
||||
logger.warning("不支持转发消息节点解析")
|
||||
case RealMessageType.json:
|
||||
ret_seg = await self.handle_json_message(sub_message)
|
||||
if ret_seg:
|
||||
await event_manager.trigger_event(NapcatEvent.ON_RECEIVED_JSON,message_seg=ret_seg)
|
||||
seg_message.append(ret_seg)
|
||||
else:
|
||||
logger.warning("json处理失败")
|
||||
case _:
|
||||
logger.warning(f"未知消息类型: {sub_message_type}")
|
||||
|
||||
@@ -643,25 +675,49 @@ class MessageHandler:
|
||||
processed_message: Seg
|
||||
if image_count < 5 and image_count > 0:
|
||||
# 处理图片数量小于5的情况,此时解析图片为base64
|
||||
logger.trace("图片数量小于5,开始解析图片为base64")
|
||||
logger.info("图片数量小于5,开始解析图片为base64")
|
||||
processed_message = await self._recursive_parse_image_seg(
|
||||
handled_message, True
|
||||
)
|
||||
elif image_count > 0:
|
||||
logger.trace("图片数量大于等于5,开始解析图片为占位符")
|
||||
logger.info("图片数量大于等于5,开始解析图片为占位符")
|
||||
# 处理图片数量大于等于5的情况,此时解析图片为占位符
|
||||
processed_message = await self._recursive_parse_image_seg(
|
||||
handled_message, False
|
||||
)
|
||||
else:
|
||||
# 处理没有图片的情况,此时直接返回
|
||||
logger.trace("没有图片,直接返回")
|
||||
logger.info("没有图片,直接返回")
|
||||
processed_message = handled_message
|
||||
|
||||
# 添加转发消息提示
|
||||
forward_hint = Seg(type="text", data="这是一条转发消息:\n")
|
||||
return Seg(type="seglist", data=[forward_hint, processed_message])
|
||||
|
||||
async def handle_dice_message(self, raw_message: dict) -> Seg:
|
||||
message_data: dict = raw_message.get("data",{})
|
||||
res = message_data.get("result","")
|
||||
return Seg(type="text", data=f"[扔了一个骰子,点数是{res}]")
|
||||
|
||||
async def handle_shake_message(self, raw_message: dict) -> Seg:
|
||||
return Seg(type="text", data="[向你发送了窗口抖动,现在你的屏幕猛烈地震了一下!]")
|
||||
|
||||
async def handle_json_message(self, raw_message: dict) -> Seg:
|
||||
message_data: str = raw_message.get("data","").get("data","")
|
||||
res = json.loads(message_data)
|
||||
return Seg(type="json", data=res)
|
||||
|
||||
async def handle_rps_message(self, raw_message: dict) -> Seg:
|
||||
message_data: dict = raw_message.get("data",{})
|
||||
res = message_data.get("result","")
|
||||
if res == "1":
|
||||
shape = "布"
|
||||
elif res == "2":
|
||||
shape = "剪刀"
|
||||
else:
|
||||
shape = "石头"
|
||||
return Seg(type="text", data=f"[发送了一个魔法猜拳表情,结果是:{shape}]")
|
||||
|
||||
async def _recursive_parse_image_seg(self, seg_data: Seg, to_image: bool) -> Seg:
|
||||
# sourcery skip: merge-else-if-into-elif
|
||||
if to_image:
|
||||
@@ -688,7 +744,7 @@ class MessageHandler:
|
||||
return Seg(type="text", data="[表情包]")
|
||||
return Seg(type="emoji", data=encoded_image)
|
||||
else:
|
||||
logger.trace(f"不处理类型: {seg_data.type}")
|
||||
logger.info(f"不处理类型: {seg_data.type}")
|
||||
return seg_data
|
||||
else:
|
||||
if seg_data.type == "seglist":
|
||||
@@ -702,7 +758,7 @@ class MessageHandler:
|
||||
elif seg_data.type == "emoji":
|
||||
return Seg(type="text", data="[动画表情]")
|
||||
else:
|
||||
logger.trace(f"不处理类型: {seg_data.type}")
|
||||
logger.info(f"不处理类型: {seg_data.type}")
|
||||
return seg_data
|
||||
|
||||
async def _handle_forward_message(self, message_list: list, layer: int) -> Tuple[Seg, int] | Tuple[None, int]:
|
||||
|
||||
@@ -115,6 +115,10 @@ class NoticeHandler:
|
||||
handled_message, user_info = await self.handle_poke_notify(raw_message, group_id, user_id)
|
||||
else:
|
||||
logger.warning("戳一戳消息被禁用,取消戳一戳处理")
|
||||
case NoticeType.Notify.input_status:
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
from ...event_types import NapcatEvent
|
||||
await event_manager.trigger_event(NapcatEvent.ON_FRIEND_INPUT)
|
||||
case _:
|
||||
logger.warning(f"不支持的notify类型: {notice_type}.{sub_type}")
|
||||
case NoticeType.group_ban:
|
||||
|
||||
@@ -12,7 +12,7 @@ response_time_dict: Dict = {}
|
||||
async def get_response(request_id: str, timeout: int = 10) -> dict:
|
||||
response = await asyncio.wait_for(_get_response(request_id), timeout)
|
||||
_ = response_time_dict.pop(request_id)
|
||||
logger.trace(f"响应信息id: {request_id} 已从响应字典中取出")
|
||||
logger.info(f"响应信息id: {request_id} 已从响应字典中取出")
|
||||
return response
|
||||
|
||||
async def _get_response(request_id: str) -> dict:
|
||||
@@ -28,7 +28,7 @@ async def put_response(response: dict):
|
||||
now_time = time.time()
|
||||
response_dict[echo_id] = response
|
||||
response_time_dict[echo_id] = now_time
|
||||
logger.trace(f"响应信息id: {echo_id} 已存入响应字典")
|
||||
logger.info(f"响应信息id: {echo_id} 已存入响应字典")
|
||||
|
||||
|
||||
async def check_timeout_response() -> None:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# TODO List:
|
||||
|
||||
[x] logger使用主程序的
|
||||
[ ] 使用插件系统的config系统
|
||||
[ ] 接收从napcat传递的所有信息
|
||||
@@ -5,3 +7,83 @@
|
||||
[ ] 单独一个模块负责与主程序通信
|
||||
[ ] 使用event系统完善接口api
|
||||
|
||||
|
||||
---
|
||||
Event分为两种,一种是对外输出的event,由napcat插件自主触发并传递参数,另一种是接收外界输入的event,由外部插件触发并向napcat传递参数
|
||||
|
||||
|
||||
## 例如,
|
||||
|
||||
### 对外输出的event:
|
||||
|
||||
napcat_on_received_text -> (message_seg: Seg) 接受到qq的文字消息,会向handler传递一个Seg
|
||||
napcat_on_received_face -> (message_seg: Seg) 接受到qq的表情消息,会向handler传递一个Seg
|
||||
napcat_on_received_reply -> (message_seg: Seg) 接受到qq的回复消息,会向handler传递一个Seg
|
||||
napcat_on_received_image -> (message_seg: Seg) 接受到qq的图片消息,会向handler传递一个Seg
|
||||
napcat_on_received_image -> (message_seg: Seg) 接受到qq的图片消息,会向handler传递一个Seg
|
||||
napcat_on_received_record -> (message_seg: Seg) 接受到qq的语音消息,会向handler传递一个Seg
|
||||
napcat_on_received_rps -> (message_seg: Seg) 接受到qq的猜拳魔法表情,会向handler传递一个Seg
|
||||
napcat_on_received_friend_invitation -> (user_id: str) 接受到qq的好友请求,会向handler传递一个user_id
|
||||
...
|
||||
|
||||
此类event不接受外部插件的触发,只能由napcat插件统一触发。
|
||||
|
||||
外部插件需要编写handler并订阅此类事件。
|
||||
```python
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
from src.plugin_system.base.base_event import HandlerResult
|
||||
|
||||
class MyEventHandler(BaseEventHandler):
|
||||
handler_name = "my_handler"
|
||||
handler_description = "我的自定义事件处理器"
|
||||
weight = 10 # 权重,越大越先执行
|
||||
intercept_message = False # 是否拦截消息
|
||||
init_subscribe = ["napcat_on_received_text"] # 初始订阅的事件
|
||||
|
||||
async def execute(self, params: dict) -> HandlerResult:
|
||||
"""处理事件"""
|
||||
try:
|
||||
message = params.get("message_seg")
|
||||
print(f"收到消息: {message.data}")
|
||||
|
||||
# 业务逻辑处理
|
||||
# ...
|
||||
|
||||
return HandlerResult(
|
||||
success=True,
|
||||
continue_process=True, # 是否继续让其他处理器处理
|
||||
message="处理成功",
|
||||
handler_name=self.handler_name
|
||||
)
|
||||
except Exception as e:
|
||||
return HandlerResult(
|
||||
success=False,
|
||||
continue_process=True,
|
||||
message=f"处理失败: {str(e)}",
|
||||
handler_name=self.handler_name
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
### 接收外界输入的event:
|
||||
|
||||
napcat_kick_group <- (user_id, group_id) 踢出某个群组中的某个用户
|
||||
napcat_mute_user <- (user_id, group_id, time) 禁言某个群组中的某个用户
|
||||
napcat_unmute_user <- (user_id, group_id) 取消禁言某个群组中的某个用户
|
||||
napcat_mute_group <- (user_id, group_id) 禁言某个群组
|
||||
napcat_unmute_group <- (user_id, group_id) 取消禁言某个群组
|
||||
napcat_add_friend <- (user_id) 向某个用户发出好友请求
|
||||
napcat_accept_friend <- (user_id) 接收某个用户的好友请求
|
||||
napcat_reject_friend <- (user_id) 拒绝某个用户的好友请求
|
||||
...
|
||||
此类事件只由外部插件触发并传递参数,由napcat完成请求任务。
|
||||
|
||||
外部插件需要触发此类的event并传递正确的参数。
|
||||
|
||||
```python
|
||||
from src.plugin_system.core.event_manager import event_manager
|
||||
|
||||
# 触发事件
|
||||
await event_manager.trigger_event("napcat_accept_friend", user_id = 1234123)
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user