1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
pub mod id;
use crate::bot::BotInformation;
use crate::event::id::ref_id::RefID;
use crate::message::Message;
use crate::types::{ApiAndOptOneshot, ApiAndRuturn};
use serde_json::Value;
use std::any::Any;
/// 满足此 trait 即可在Kovi运行时中监听并处理
///
/// # Warning
///
/// 最好不要阻塞解析事件,如果目标信息需要阻塞获取,请通知用户由用户处理,而非由事件解析器阻塞
///
/// 在 Kovi 0.12.4 之后,事件是并发解析的,所以阻塞解析事件并不会阻塞其他事件的解析,虽然如此,仍然不建议阻塞解析事件
pub trait Event: Any + Send + Sync {
/// 解析事件
///
/// 传入三个东西,按需所取。
/// - InternalEvent 内部消息,包含OneBot消息与由框架发出去的Api消息
/// - 借用的bot信息,可以通过 `BotInformation` 获取 `Bot` 相关的信息,例如管理员是谁。
/// - 借用的api发送通道,可以通过 `api_tx.clone()` 来让事件可以发送 api
///
/// 如果认为此 json 不符合事件要求,请返回 `None`。
///
/// 在一个消息周期内,Kovi 运行时会缓存此事件。
///
/// 不需要的信息用 `_` 忽略,例如:
///
/// ```ignore
///
/// impl Event for LifecycleEvent {
/// fn de(
/// event: &InternalEvent,
/// _: &BotInformation,
/// _: &tokio::sync::mpsc::Sender<ApiAndOptOneshot>,
/// ) -> Option<Self>
/// where
/// Self: Sized,
/// {
/// let InternalEvent::OneBotEvent(json_str) = event else {
/// return None;
/// };
/// let event: LifecycleEvent = serde_json::from_str(json_str).ok()?;
/// if event.meta_event_type == "lifecycle" {
/// Some(event)
/// } else {
/// None
/// }
/// }
/// }
/// ```
///
/// # Warning
///
/// 最好不要阻塞解析事件,如果目标信息需要阻塞获取,请通知用户由用户处理,而非由事件解析器阻塞
///
/// 在 Kovi 0.12.4 之后,事件是并发解析的,所以阻塞解析事件并不会阻塞其他事件的解析,虽然如此,仍然不建议阻塞解析事件
///
/// 可以使用类似于 `MsgSendFromKoviEvent` 的实现,将所需的交给用户就行。
///
/// ```ignore
///
/// pub struct MsgSendFromKoviEvent {
/// pub event_type: MsgSendFromKoviType,
/// pub send_api: SendApi,
/// pub res: Result<ApiReturn, ApiReturn>,
/// }
/// ```
fn de(
event: &InternalEvent,
bot_info: &BotInformation,
api_tx: &tokio::sync::mpsc::Sender<ApiAndOptOneshot>,
) -> Option<Self>
where
Self: Sized;
}
/// 事件
#[derive(Debug, Clone)]
pub enum InternalEvent {
/// 来自OneBot的事件
DriverEvent(Value),
/// 来自Kovi发送给服务端并包含了返回结果
DriverApiEvent(ApiAndRuturn),
}
pub trait MessageEventTrait: Event {
fn get_sender_name(&self) -> Option<&str>;
fn get_sender_id(&self) -> RefID<'_>;
fn get_message(&self) -> &Message;
fn get_message_type_str(&self) -> Option<&str>;
fn get_group_id(&self) -> Option<RefID<'_>>;
fn is_group_message(&self) -> bool {
self.get_group_id().is_some()
}
fn is_private_message(&self) -> bool {
self.get_group_id().is_none()
}
}
/// 满足此 trait 即可被回复
pub trait RepliableEvent {
/// 快速回复消息
fn reply<T>(&self, msg: T)
where
Message: From<T>,
T: serde::Serialize;
/// 快速回复消息并且**引用**
fn reply_and_quote<T>(&self, msg: T)
where
Message: From<T>,
T: serde::Serialize;
}
pub trait MessageEventUtil {
/// 便捷获取文本,如果没有文本则会返回空字符串,如果只需要借用,请使用 `borrow_text()`
fn get_text(&self) -> String;
/// 便捷获取发送者昵称,如果无名字,此处为空字符串
fn get_sender_nickname(&self) -> String;
/// 借用 event 的 text,只是做了一下self.text.as_deref()的包装
fn borrow_text(&self) -> Option<&str>;
}