Skip to main content

kovi_onebot/event/
admin_msg_event.rs

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