"""iamai 事件。
事件类的基类。适配器开发者应实现此事件类基类的子类。
"""
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Generic, Optional, Union
from typing_extensions import Self
from pydantic import BaseModel, ConfigDict
from iamai.typing import AdapterT
__all__ = ["Event", "MessageEvent"]
[docs]
class Event(ABC, BaseModel, Generic[AdapterT]):
"""事件类的基类。
Attributes:
adapter: 产生当前事件的适配器对象。
type: 事件类型。
__handled__: 表示事件是否被处理过了,用于适配器处理。警告:请勿手动更改此属性的值。
"""
model_config = ConfigDict(extra="allow")
if TYPE_CHECKING:
adapter: AdapterT
else:
adapter: Any
type: Optional[str]
__handled__: bool = False
def __str__(self) -> str:
"""返回事件的文本表示。
Returns:
事件的文本表示。
"""
return f"Event<{self.type}>"
def __repr__(self) -> str:
"""返回事件的描述。
Returns:
事件的描述。
"""
return self.__str__()
[docs]
class MessageEvent(Event[AdapterT], Generic[AdapterT]):
"""通用的消息事件类的基类。"""
[docs]
@abstractmethod
def get_plain_text(self) -> str:
"""获取消息的纯文本内容。
Returns:
消息的纯文本内容。
"""
[docs]
@abstractmethod
async def reply(self, message: str) -> Any:
"""回复消息。
Args:
message: 回复消息的内容。
Returns:
回复消息动作的响应。
"""
[docs]
@abstractmethod
async def is_same_sender(self, other: Self) -> bool:
"""判断自身和另一个事件是否是同一个发送者。
Args:
other: 另一个事件。
Returns:
是否是同一个发送者。
"""
[docs]
async def get(
self,
*,
max_try_times: Optional[int] = None,
timeout: Optional[Union[int, float]] = None,
) -> Self:
"""获取用户回复消息。
相当于 `Bot` 的 `get()`,条件为适配器、事件类型、发送人相同。
Args:
max_try_times: 最大事件数。
timeout: 超时时间。
Returns:
用户回复的消息事件。
Raises:
GetEventTimeout: 超过最大事件数或超时。
"""
return await self.adapter.get(
self.is_same_sender,
event_type=type(self),
max_try_times=max_try_times,
timeout=timeout,
)
[docs]
async def ask(
self,
message: str,
max_try_times: Optional[int] = None,
timeout: Optional[Union[int, float]] = None,
) -> Self:
"""询问消息。
表示回复一个消息后获取用户的回复。
相当于 `reply()` 后执行 `get()`。
Args:
message: 回复消息的内容。
max_try_times: 最大事件数。
timeout: 超时时间。
Returns:
用户回复的消息事件。
"""
await self.reply(message)
return await self.get(max_try_times=max_try_times, timeout=timeout)