mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-01-19 17:58:26 +08:00
✨ implement event parser
This commit is contained in:
parent
20c3c24a6d
commit
7a8f881b04
@ -9,7 +9,7 @@ from nonebot.adapters import Bot as BaseBot
|
|||||||
from nonebot.drivers import Driver, HTTPRequest, HTTPResponse
|
from nonebot.drivers import Driver, HTTPRequest, HTTPResponse
|
||||||
|
|
||||||
from .config import Config as FeishuConfig
|
from .config import Config as FeishuConfig
|
||||||
from .event import Event
|
from .event import Event, get_event_model
|
||||||
from .message import Message, MessageSegment
|
from .message import Message, MessageSegment
|
||||||
from .utils import log, AESCipher
|
from .utils import log, AESCipher
|
||||||
|
|
||||||
@ -17,6 +17,48 @@ if TYPE_CHECKING:
|
|||||||
from nonebot.config import Config
|
from nonebot.config import Config
|
||||||
|
|
||||||
|
|
||||||
|
async def _check_reply(bot: "Bot", event: "Event"):
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
|
||||||
|
检查消息中存在的回复,去除并赋值 ``event.reply``, ``event.to_me``
|
||||||
|
|
||||||
|
:参数:
|
||||||
|
|
||||||
|
* ``bot: Bot``: Bot 对象
|
||||||
|
* ``event: Event``: Event 对象
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def _check_at_me(bot: "Bot", event: "Event"):
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
|
||||||
|
检查消息开头或结尾是否存在 @机器人,去除并赋值 ``event.to_me``
|
||||||
|
|
||||||
|
:参数:
|
||||||
|
|
||||||
|
* ``bot: Bot``: Bot 对象
|
||||||
|
* ``event: Event``: Event 对象
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def _check_nickname(bot: "Bot", event: "Event"):
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
|
||||||
|
检查消息开头是否存在,去除并赋值 ``event.to_me``
|
||||||
|
|
||||||
|
:参数:
|
||||||
|
|
||||||
|
* ``bot: Bot``: Bot 对象
|
||||||
|
* ``event: Event``: Event 对象
|
||||||
|
"""
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
class Bot(BaseBot):
|
class Bot(BaseBot):
|
||||||
"""
|
"""
|
||||||
飞书 协议 Bot 适配。继承属性参考 `BaseBot <./#class-basebot>`_ 。
|
飞书 协议 Bot 适配。继承属性参考 `BaseBot <./#class-basebot>`_ 。
|
||||||
@ -52,7 +94,7 @@ class Bot(BaseBot):
|
|||||||
|
|
||||||
challenge = data.get("challenge")
|
challenge = data.get("challenge")
|
||||||
if challenge:
|
if challenge:
|
||||||
return None, HTTPResponse(
|
return data.get("token"), HTTPResponse(
|
||||||
200,
|
200,
|
||||||
json.dumps({
|
json.dumps({
|
||||||
"challenge": challenge
|
"challenge": challenge
|
||||||
@ -85,8 +127,22 @@ class Bot(BaseBot):
|
|||||||
处理事件并转换为 `Event <#class-event>`_
|
处理事件并转换为 `Event <#class-event>`_
|
||||||
"""
|
"""
|
||||||
data = json.loads(message)
|
data = json.loads(message)
|
||||||
|
print(data)
|
||||||
|
if data.get("type") == "url_verification":
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
event = Event.parse_obj(message)
|
header = data["header"]
|
||||||
|
event_type = header["event_type"]
|
||||||
|
models = get_event_model(event_type)
|
||||||
|
for model in models:
|
||||||
|
try:
|
||||||
|
event = model.parse_obj(data)
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
log("DEBUG", "Event Parser Error", e)
|
||||||
|
else:
|
||||||
|
event = Event.parse_obj(data)
|
||||||
await handle_event(self, event)
|
await handle_event(self, event)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.opt(colors=True, exception=e).error(
|
logger.opt(colors=True, exception=e).error(
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
from typing import List, Literal
|
import inspect
|
||||||
from pydantic import BaseModel, root_validator
|
import json
|
||||||
|
from nonebot import message
|
||||||
|
|
||||||
|
from typing import Any, List, Literal, Optional, Type, Union
|
||||||
|
from pygtrie import StringTrie
|
||||||
|
from pydantic import BaseModel, root_validator, Field
|
||||||
|
|
||||||
from nonebot.adapters import Event as BaseEvent
|
from nonebot.adapters import Event as BaseEvent
|
||||||
from nonebot.typing import overrides
|
from nonebot.typing import overrides
|
||||||
@ -7,6 +12,15 @@ from nonebot.typing import overrides
|
|||||||
from .message import Message, MessageSegment
|
from .message import Message, MessageSegment
|
||||||
|
|
||||||
|
|
||||||
|
class EventHeader(BaseModel):
|
||||||
|
event_id: str
|
||||||
|
event_type: str
|
||||||
|
create_time: str
|
||||||
|
token: str
|
||||||
|
app_id: str
|
||||||
|
tenant_key: str
|
||||||
|
|
||||||
|
|
||||||
class Event(BaseEvent):
|
class Event(BaseEvent):
|
||||||
"""
|
"""
|
||||||
飞书协议事件。各事件字段参考 `飞书文档`_
|
飞书协议事件。各事件字段参考 `飞书文档`_
|
||||||
@ -14,16 +28,18 @@ class Event(BaseEvent):
|
|||||||
.. _飞书事件列表文档:
|
.. _飞书事件列表文档:
|
||||||
https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list
|
https://open.feishu.cn/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/event-list
|
||||||
"""
|
"""
|
||||||
app_id: int
|
__event__ = ""
|
||||||
event_type: str
|
schema_: str = Field("", alias='schema')
|
||||||
|
header: EventHeader
|
||||||
|
event: Any
|
||||||
|
|
||||||
@overrides(BaseEvent)
|
@overrides(BaseEvent)
|
||||||
def get_type(self) -> str:
|
def get_type(self) -> str:
|
||||||
return self.event_type
|
return self.header.event_type
|
||||||
|
|
||||||
@overrides(BaseEvent)
|
@overrides(BaseEvent)
|
||||||
def get_event_name(self) -> str:
|
def get_event_name(self) -> str:
|
||||||
return self.event_type
|
return self.header.event_type
|
||||||
|
|
||||||
@overrides(BaseEvent)
|
@overrides(BaseEvent)
|
||||||
def get_event_description(self) -> str:
|
def get_event_description(self) -> str:
|
||||||
@ -69,39 +85,31 @@ class Mention(BaseModel):
|
|||||||
tenant_key: str
|
tenant_key: str
|
||||||
|
|
||||||
|
|
||||||
class MessageBody(BaseModel):
|
class EventMessage(BaseModel):
|
||||||
message_id: str
|
message_id: str
|
||||||
root_id: str
|
root_id: Optional[str]
|
||||||
parent_id: str
|
parent_id: Optional[str]
|
||||||
create_time: str
|
create_time: str
|
||||||
chat_id: str
|
chat_id: str
|
||||||
chat_type: str
|
chat_type: str
|
||||||
message_type: str
|
message_type: str
|
||||||
content: Message
|
content: Message
|
||||||
mentions: List[Mention]
|
mentions: Optional[List[Mention]]
|
||||||
|
|
||||||
plaintext: str
|
|
||||||
|
|
||||||
@root_validator(pre=True)
|
@root_validator(pre=True)
|
||||||
def gen_message(cls, values: dict):
|
def parse_message(cls, values: dict):
|
||||||
content = []
|
values["content"] = json.loads(values["content"])
|
||||||
for piece in values["content"]:
|
|
||||||
for segment in piece:
|
|
||||||
content.append(
|
|
||||||
MessageSegment(segment["tag"], segment.pop('name', segment)))
|
|
||||||
|
|
||||||
values["content"] = Message(content)
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
@root_validator
|
|
||||||
def gen_plaintext(cls, values: dict):
|
class MessageEventDetail(BaseModel):
|
||||||
values["plaintext"] = str(values["content"])
|
sender: Sender
|
||||||
return values
|
message: EventMessage
|
||||||
|
|
||||||
|
|
||||||
class MessageEvent(Event):
|
class MessageEvent(Event):
|
||||||
sender: Sender
|
__event__ = "im.message.receive_v1"
|
||||||
message: MessageBody
|
event: MessageEventDetail
|
||||||
|
|
||||||
@overrides(Event)
|
@overrides(Event)
|
||||||
def get_type(self) -> Literal["message", "notice", "meta_event"]:
|
def get_type(self) -> Literal["message", "notice", "meta_event"]:
|
||||||
@ -115,32 +123,40 @@ class MessageEvent(Event):
|
|||||||
def get_event_description(self) -> str:
|
def get_event_description(self) -> str:
|
||||||
return (
|
return (
|
||||||
f"Message[{super().get_type()}]"
|
f"Message[{super().get_type()}]"
|
||||||
f" {self.message.message_id} from {self.sender.sender_id.user_id}"
|
f" {self.event.message.message_id} from {self.event.sender.sender_id.user_id}"
|
||||||
f" {self.message.content}")
|
f" {self.event.message.content}")
|
||||||
|
|
||||||
@overrides(Event)
|
@overrides(Event)
|
||||||
def get_message(self) -> Message:
|
def get_message(self) -> Message:
|
||||||
return self.message.content
|
return self.event.message.content
|
||||||
|
|
||||||
@overrides(Event)
|
@overrides(Event)
|
||||||
def get_plaintext(self) -> str:
|
def get_plaintext(self) -> str:
|
||||||
return self.message.plaintext
|
return str(self.event.message.content)
|
||||||
|
|
||||||
@overrides(Event)
|
@overrides(Event)
|
||||||
def get_user_id(self) -> str:
|
def get_user_id(self) -> str:
|
||||||
return self.sender.sender_id.user_id
|
return self.event.sender.sender_id.user_id
|
||||||
|
|
||||||
@overrides(Event)
|
@overrides(Event)
|
||||||
def get_session_id(self) -> str:
|
def get_session_id(self) -> str:
|
||||||
return self.sender.sender_id.user_id
|
return self.event.sender.sender_id.user_id
|
||||||
|
|
||||||
|
|
||||||
class PrivateMessageEvent(MessageEvent):
|
class MessageReader(BaseModel):
|
||||||
...
|
reader_id: UserId
|
||||||
|
read_time: str
|
||||||
|
tenant_key: str
|
||||||
|
|
||||||
|
|
||||||
class GroupMessageEvent(MessageEvent):
|
class MessageReadEventDetail(BaseModel):
|
||||||
...
|
reader: MessageReader
|
||||||
|
message_id_list: List[str]
|
||||||
|
|
||||||
|
|
||||||
|
class MessageReadEvent(Event):
|
||||||
|
__event__ = "im.message.message_read_v1"
|
||||||
|
event: MessageReadEventDetail
|
||||||
|
|
||||||
|
|
||||||
class NoticeEvent(Event):
|
class NoticeEvent(Event):
|
||||||
@ -149,3 +165,26 @@ class NoticeEvent(Event):
|
|||||||
|
|
||||||
class MetaEvent(Event):
|
class MetaEvent(Event):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
_t = StringTrie(separator=".")
|
||||||
|
|
||||||
|
# define `model` first to avoid globals changing while `for`
|
||||||
|
model = None
|
||||||
|
for model in globals().values():
|
||||||
|
if not inspect.isclass(model) or not issubclass(model, Event):
|
||||||
|
continue
|
||||||
|
_t["." + model.__event__] = model
|
||||||
|
|
||||||
|
|
||||||
|
def get_event_model(event_name) -> List[Type[Event]]:
|
||||||
|
"""
|
||||||
|
:说明:
|
||||||
|
|
||||||
|
根据事件名获取对应 ``Event Model`` 及 ``FallBack Event Model`` 列表
|
||||||
|
|
||||||
|
:返回:
|
||||||
|
|
||||||
|
- ``List[Type[Event]]``
|
||||||
|
"""
|
||||||
|
return [model.value for model in _t.prefixes("." + event_name)][::-1]
|
||||||
|
Loading…
Reference in New Issue
Block a user