Skip to main content

kovi_onebot/event/
msg_send_from_server_event.rs

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