Skip to main content

kovi_onebot/event/
group_msg_event.rs

1use super::{Anonymous, Sender};
2use crate::event::{MsgEvent, PostType, RepliableEvent};
3use crate::message_trait::MessageRegistrar as _;
4use crate::onebot_message::OneBotMessage;
5use kovi::bot::runtimebot::{CanSendApi, send_api_request_with_forget};
6use kovi::bot::{BotInformation, SendApi};
7use kovi::error::EventBuildError;
8use kovi::event::{Event, InternalEvent};
9use kovi::message::Message as KoviMessage;
10use kovi::types::ApiAndOptOneshot;
11use log::info;
12use serde::Serialize;
13use serde_json::value::Index;
14use serde_json::{self, Value, json};
15use tokio::sync::mpsc;
16
17#[derive(Debug, Clone)]
18pub struct GroupMsgEvent {
19    /// 事件发生的时间戳
20    pub time: i64,
21    /// 收到事件的机器人 登陆号
22    pub self_id: i64,
23    /// 上报类型
24    pub post_type: PostType,
25    /// 消息类型
26    pub message_type: String,
27    /// 消息子类型,如果是好友则是 friend,如果是群临时会话则是 group
28    pub sub_type: String,
29    /// 消息内容
30    pub message: KoviMessage,
31    /// 消息 ID
32    pub message_id: i32,
33    /// 群号
34    pub group_id: i64,
35    /// 发送者号
36    pub user_id: i64,
37    /// 匿名信息,如果不是匿名消息则为 null
38    pub anonymous: Option<Anonymous>,
39    /// 原始消息内容
40    pub raw_message: String,
41    /// 字体
42    pub font: i32,
43    /// 发送人信息
44    pub sender: Sender,
45
46    /// 处理过的纯文本,如果是纯图片或无文本,此处为None
47    pub text: Option<String>,
48    /// 处理过的文本,会解析成人类易读形式,里面会包含\[image\]\[face\]等解析后字符串
49    pub human_text: String,
50    /// 原始的onebot消息,已处理成json格式
51    pub original_json: Value,
52
53    /// 不推荐的消息发送方式
54    pub api_tx: mpsc::Sender<ApiAndOptOneshot>,
55}
56
57impl Event for GroupMsgEvent {
58    fn de(
59        event: &InternalEvent,
60        _: &BotInformation,
61        api_tx: &mpsc::Sender<ApiAndOptOneshot>,
62    ) -> Option<Self> {
63        let InternalEvent::DriverEvent(json) = event else {
64            return None;
65        };
66        let event = Self::new(api_tx.clone(), json.clone()).ok()?;
67
68        Some(event)
69    }
70}
71
72impl GroupMsgEvent {
73    fn new(
74        api_tx: mpsc::Sender<ApiAndOptOneshot>,
75        json: Value,
76    ) -> Result<GroupMsgEvent, EventBuildError> {
77        let msg_event = MsgEvent::new(api_tx, json)?;
78
79        Ok(GroupMsgEvent {
80            time: msg_event.time,
81            self_id: msg_event.self_id,
82            post_type: msg_event.post_type,
83            message_type: msg_event.message_type,
84            sub_type: msg_event.sub_type,
85            message: msg_event.message,
86            message_id: msg_event.message_id,
87            group_id: match msg_event.group_id {
88                Some(id) => id,
89                None => {
90                    return Err(EventBuildError::ParseError(
91                        "group_id unreachable".to_string(),
92                    ));
93                }
94            },
95            user_id: msg_event.user_id,
96            anonymous: msg_event.anonymous,
97            raw_message: msg_event.raw_message,
98            font: msg_event.font,
99            sender: msg_event.sender,
100            text: msg_event.text,
101            human_text: msg_event.human_text,
102            original_json: msg_event.original_json,
103            api_tx: msg_event.api_tx,
104        })
105    }
106}
107
108impl GroupMsgEvent {
109    /// 直接从原始的 Json Value 获取某值
110    ///
111    /// # example
112    ///
113    /// ```ignore
114    /// use kovi::PluginBuilder;
115    ///
116    /// PluginBuilder::on_msg(|event| async move {
117    ///     let time = event.get("time").and_then(|v| v.as_i64()).unwrap();
118    ///
119    ///     assert_eq!(time, event.time);
120    /// });
121    /// ```
122    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
123        self.original_json.get(index)
124    }
125}
126
127impl<I> std::ops::Index<I> for GroupMsgEvent
128where
129    I: Index,
130{
131    type Output = Value;
132
133    fn index(&self, index: I) -> &Self::Output {
134        &self.original_json[index]
135    }
136}
137
138impl GroupMsgEvent {
139    fn reply_builder<M>(&self, msg: M, auto_escape: bool) -> SendApi
140    where
141        M: Into<OneBotMessage>,
142    {
143        RepliableEvent::reply_builder(self, msg, auto_escape)
144    }
145
146    #[cfg(not(feature = "cqstring"))]
147    pub fn reply<T>(&self, msg: T)
148    where
149        KoviMessage: From<T>,
150        T: Serialize,
151    {
152        RepliableEvent::reply(self, msg)
153    }
154
155    #[cfg(feature = "cqstring")]
156    pub fn reply<T>(&self, msg: T)
157    where
158        CQMessage: From<T>,
159        T: Serialize,
160    {
161        RepliableEvent::reply(self, msg)
162    }
163
164    #[cfg(not(feature = "cqstring"))]
165    pub fn reply_and_quote<T>(&self, msg: T)
166    where
167        KoviMessage: From<T>,
168        T: Serialize,
169    {
170        RepliableEvent::reply_and_quote(self, msg);
171    }
172
173    #[cfg(feature = "cqstring")]
174    fn reply_and_quote<T>(&self, msg: T)
175    where
176        CQMessage: From<T>,
177        T: Serialize,
178    {
179        RepliableEvent::reply_and_quote(self, msg);
180    }
181
182    #[cfg(feature = "cqstring")]
183    fn reply_text<T>(&self, msg: T)
184    where
185        String: From<T>,
186        T: Serialize,
187    {
188        RepliableEvent::reply_text(self, msg)
189    }
190
191    pub fn get_text(&self) -> String {
192        RepliableEvent::get_text(self)
193    }
194
195    pub fn get_sender_nickname(&self) -> String {
196        RepliableEvent::get_sender_nickname(self)
197    }
198
199    pub fn borrow_text(&self) -> Option<&str> {
200        RepliableEvent::borrow_text(self)
201    }
202}
203
204impl RepliableEvent for GroupMsgEvent {
205    fn reply_builder<M>(&self, msg: M, auto_escape: bool) -> SendApi
206    where
207        M: Into<OneBotMessage>,
208    {
209        let msg = msg.into();
210        SendApi::new(
211            "send_msg",
212            json!({
213                "message_type":"group",
214                "group_id":self.group_id,
215                "message":msg,
216                "auto_escape":auto_escape,
217            }),
218        )
219    }
220
221    #[cfg(not(feature = "cqstring"))]
222    /// 快速回复消息
223    fn reply<T>(&self, msg: T)
224    where
225        KoviMessage: From<T>,
226        T: Serialize,
227    {
228        let msg = KoviMessage::from(msg);
229        let nickname = self.get_sender_nickname();
230        let id = &self.sender.user_id;
231        let message_type = &self.message_type;
232        let group_id = &self.group_id;
233        let human_msg = msg.to_human_string();
234        info!("[reply] [to {message_type} {group_id} {nickname} {id}]: {human_msg}");
235
236        let send_msg = self.reply_builder(msg, false);
237        send_api_request_with_forget(&self.api_tx, send_msg)
238    }
239
240    #[cfg(feature = "cqstring")]
241    /// 快速回复消息
242    fn reply<T>(&self, msg: T)
243    where
244        CQMessage: From<T>,
245        T: Serialize,
246    {
247        let msg = CQMessage::from(msg);
248        let send_msg = self.reply_builder(&msg, false);
249        let nickname = self.get_sender_nickname();
250        let id = &self.sender.user_id;
251        let message_type = &self.message_type;
252        let group_id = &self.group_id;
253        let human_msg = Message::from(msg).to_human_string();
254        info!("[reply] [to {message_type} {group_id} {nickname} {id}]: {human_msg}");
255        send_api_request_with_forget(&self.api_tx, send_msg);
256    }
257
258    #[cfg(not(feature = "cqstring"))]
259    /// 快速回复消息并且**引用**
260    fn reply_and_quote<T>(&self, msg: T)
261    where
262        KoviMessage: From<T>,
263        T: Serialize,
264    {
265        let msg = KoviMessage::from(msg).add_reply(self.message_id);
266        let nickname = self.get_sender_nickname();
267        let id = &self.sender.user_id;
268        let message_type = &self.message_type;
269        let group_id = &self.group_id;
270        let human_msg = msg.to_human_string();
271        info!("[reply] [to {message_type} {group_id} {nickname} {id}]: {human_msg}");
272
273        let send_msg = self.reply_builder(msg, false);
274        send_api_request_with_forget(&self.api_tx, send_msg);
275    }
276
277    #[cfg(feature = "cqstring")]
278    /// 快速回复消息并且**引用**
279    fn reply_and_quote<T>(&self, msg: T)
280    where
281        CQMessage: From<T>,
282        T: Serialize,
283    {
284        let msg = CQMessage::from(msg).add_reply(self.message_id);
285        let send_msg = self.reply_builder(&msg, false);
286        let nickname = self.get_sender_nickname();
287        let id = &self.sender.user_id;
288        let message_type = &self.message_type;
289        let group_id = &self.group_id;
290        let human_msg = Message::from(msg).to_human_string();
291        info!("[reply] [to {message_type} {group_id} {nickname} {id}]: {human_msg}");
292        send_api_request_with_forget(&self.api_tx, send_msg);
293    }
294
295    #[cfg(feature = "cqstring")]
296    /// 快速回复消息,并且**kovi不进行解析,直接发送此字符串**
297    fn reply_text<T>(&self, msg: T)
298    where
299        String: From<T>,
300        T: Serialize,
301    {
302        let send_msg = self.reply_builder(&msg, true);
303        let nickname = self.get_sender_nickname();
304        let id = &self.sender.user_id;
305        let message_type = &self.message_type;
306        let group_id = &self.group_id;
307        let msg = String::from(msg);
308        info!("[reply] [to {message_type} {group_id} {nickname} {id}]: {msg}");
309        send_api_request_with_forget(&self.api_tx, send_msg);
310    }
311
312    /// 便捷获取文本,如果没有文本则会返回空字符串,如果只需要借用,请使用 `borrow_text()`
313    fn get_text(&self) -> String {
314        match self.text.clone() {
315            Some(v) => v,
316            None => "".to_string(),
317        }
318    }
319
320    /// 便捷获取发送者昵称,如果无名字,此处为空字符串
321    fn get_sender_nickname(&self) -> String {
322        if let Some(v) = &self.sender.nickname {
323            v.clone()
324        } else {
325            "".to_string()
326        }
327    }
328
329    /// 借用 event 的 text,只是做了一下self.text.as_deref()的包装
330    fn borrow_text(&self) -> Option<&str> {
331        self.text.as_deref()
332    }
333}
334
335impl CanSendApi for GroupMsgEvent {
336    fn __get_api_tx(&self) -> &tokio::sync::mpsc::Sender<kovi::types::ApiAndOptOneshot> {
337        &self.api_tx
338    }
339}