Skip to main content

kovi_onebot/event/
private_msg_event.rs

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