1use crate::invoker::Actions;
4use nagisa_types::event::ReactionKind;
5use nagisa_types::prelude::*;
6use serde_json::Value;
7use std::sync::atomic::{AtomicI64, Ordering};
8use std::sync::{Arc, Mutex, OnceLock};
9
10type OutgoingLogger = Box<dyn Fn(&Peer, &[Segment], Uin, &MessageId) + Send + Sync>;
17static OUTGOING_LOGGERS: OnceLock<Mutex<Vec<OutgoingLogger>>> = OnceLock::new();
18
19fn loggers() -> &'static Mutex<Vec<OutgoingLogger>> {
20 OUTGOING_LOGGERS.get_or_init(|| Mutex::new(Vec::new()))
21}
22
23pub fn add_outgoing_logger(f: OutgoingLogger) {
25 if let Ok(mut v) = loggers().lock() {
26 v.push(f);
27 }
28}
29
30pub fn set_outgoing_logger(f: OutgoingLogger) {
32 add_outgoing_logger(f);
33}
34
35fn log_outgoing(peer: &Peer, message: &[Segment], self_id: Uin, id: &MessageId) {
37 let guard = match loggers().lock() {
38 Ok(g) => g,
39 Err(_) => return,
40 };
41 if guard.is_empty() {
42 tracing::debug!(peer = ?peer, segments = message.len(), "发送消息");
43 return;
44 }
45 for log in guard.iter() {
46 log(peer, message, self_id, id);
47 }
48}
49
50#[derive(Clone)]
55pub struct Bot {
56 inner: Arc<dyn Actions>,
57 self_id: Arc<AtomicI64>,
58}
59
60impl Bot {
61 pub fn new(inner: Arc<dyn Actions>, self_id: Uin) -> Self {
62 Self { inner, self_id: Arc::new(AtomicI64::new(self_id.0)) }
63 }
64
65 pub fn self_id(&self) -> Uin {
66 Uin(self.self_id.load(Ordering::Relaxed))
67 }
68
69 pub fn set_self_id(&self, id: Uin) {
71 self.self_id.store(id.0, Ordering::Relaxed);
72 }
73
74 pub fn protocol(&self) -> Protocol {
75 self.inner.protocol()
76 }
77 pub fn vendor(&self) -> nagisa_types::vendor::Vendor {
78 self.inner.vendor()
79 }
80 pub fn supports(&self, cap: Capability) -> bool {
81 self.inner.supports(cap)
82 }
83
84 pub async fn send(&self, peer: &Peer, message: &[Segment]) -> Result<MessageId> {
85 let id = self.inner.send(peer, message).await?;
87 log_outgoing(peer, message, self.self_id(), &id);
88 Ok(id)
89 }
90 pub async fn recall(&self, id: &MessageId) -> Result<()> {
91 self.inner.recall(id).await
92 }
93 pub async fn get_message(&self, id: &MessageId) -> Result<MessageEvent> {
94 self.inner.get_message(id).await
95 }
96 pub async fn get_login_info(&self) -> Result<(Uin, String)> {
97 self.inner.get_login_info().await
98 }
99 pub async fn get_group_info(&self, group: Uin, no_cache: bool) -> Result<GroupInfo> {
100 self.inner.get_group_info(group, no_cache).await
101 }
102 pub async fn get_group_list(&self, no_cache: bool) -> Result<Vec<GroupInfo>> {
103 self.inner.get_group_list(no_cache).await
104 }
105 pub async fn get_group_member_info(&self, group: Uin, user: Uin, no_cache: bool) -> Result<MemberInfo> {
106 self.inner.get_group_member_info(group, user, no_cache).await
107 }
108 pub async fn get_group_member_list(&self, group: Uin, no_cache: bool) -> Result<Vec<MemberInfo>> {
109 self.inner.get_group_member_list(group, no_cache).await
110 }
111 pub async fn get_friend_list(&self, no_cache: bool) -> Result<Vec<FriendInfo>> {
112 self.inner.get_friend_list(no_cache).await
113 }
114 pub async fn set_group_member_mute(&self, group: Uin, user: Uin, duration: u32) -> Result<()> {
115 self.inner.set_group_member_mute(group, user, duration).await
116 }
117 pub async fn set_group_whole_mute(&self, group: Uin, enable: bool) -> Result<()> {
118 self.inner.set_group_whole_mute(group, enable).await
119 }
120 pub async fn set_group_admin(&self, group: Uin, user: Uin, enable: bool) -> Result<()> {
121 self.inner.set_group_admin(group, user, enable).await
122 }
123 pub async fn set_group_member_card(&self, group: Uin, user: Uin, card: &str) -> Result<()> {
124 self.inner.set_group_member_card(group, user, card).await
125 }
126 pub async fn set_group_name(&self, group: Uin, name: &str) -> Result<()> {
127 self.inner.set_group_name(group, name).await
128 }
129 pub async fn kick_group_member(&self, group: Uin, user: Uin, reject_add: bool) -> Result<()> {
130 self.inner.kick_group_member(group, user, reject_add).await
131 }
132 pub async fn handle_request(&self, token: &RequestToken, approve: bool, reason: Option<&str>) -> Result<()> {
133 self.inner.handle_request(token, approve, reason).await
134 }
135 pub async fn send_reaction(
136 &self,
137 group: Uin,
138 seq: i64,
139 face_id: &str,
140 kind: ReactionKind,
141 is_add: bool,
142 ) -> Result<()> {
143 self.inner.send_reaction(group, seq, face_id, kind, is_add).await
144 }
145 pub async fn send_nudge(&self, peer: &Peer, target: Uin) -> Result<()> {
146 self.inner.send_nudge(peer, target).await
147 }
148 pub async fn upload_group_file(
151 &self,
152 group: Uin,
153 src: ResourceSource,
154 name: &str,
155 parent_folder_id: Option<&str>,
156 ) -> Result<String> {
157 self.inner.upload_group_file(group, src, name, parent_folder_id).await
158 }
159 pub async fn upload_private_file(&self, user: Uin, src: ResourceSource, name: &str) -> Result<String> {
161 self.inner.upload_private_file(user, src, name).await
162 }
163 pub async fn get_user_info(&self, user: Uin, no_cache: bool) -> Result<UserInfo> {
165 self.inner.get_user_info(user, no_cache).await
166 }
167 pub async fn get_friend_info(&self, user: Uin) -> Result<FriendInfo> {
169 self.inner.get_friend_info(user).await
170 }
171 pub async fn get_message_history(
173 &self,
174 peer: &Peer,
175 start: Option<&MessageId>,
176 count: u32,
177 ) -> Result<Vec<MessageEvent>> {
178 self.inner.get_message_history(peer, start, count).await
179 }
180 pub async fn get_history_messages_paged(
183 &self,
184 peer: &Peer,
185 start_seq: Option<i64>,
186 limit: u32,
187 ) -> Result<(Vec<MessageEvent>, Option<i64>)> {
188 self.inner.get_history_messages_paged(peer, start_seq, limit).await
189 }
190 pub async fn leave_group(&self, group: Uin, dismiss: bool) -> Result<()> {
192 self.inner.leave_group(group, dismiss).await
193 }
194 pub async fn set_group_member_special_title(
196 &self,
197 group: Uin,
198 user: Uin,
199 title: &str,
200 duration: i64,
201 ) -> Result<()> {
202 self.inner.set_group_member_special_title(group, user, title, duration).await
203 }
204 pub async fn mark_message_as_read(&self, peer: &Peer, id: &MessageId) -> Result<()> {
206 self.inner.mark_message_as_read(peer, id).await
207 }
208 pub async fn set_essence(&self, group: Uin, id: &MessageId, enable: bool) -> Result<()> {
210 self.inner.set_essence(group, id, enable).await
211 }
212 pub async fn get_resource_url(&self, resource_id: &str) -> Result<String> {
214 self.inner.get_resource_url(resource_id).await
215 }
216 pub async fn get_group_file_download_url(&self, group: Uin, file_id: &str) -> Result<String> {
218 self.inner.get_group_file_download_url(group, file_id).await
219 }
220 pub async fn delete_group_file(&self, group: Uin, file_id: &str) -> Result<()> {
222 self.inner.delete_group_file(group, file_id).await
223 }
224 pub async fn get_group_requests(&self) -> Result<Vec<Request>> {
226 self.inner.get_group_requests().await
227 }
228 pub async fn get_cookies(&self, domain: Option<&str>) -> Result<String> {
230 self.inner.get_cookies(domain).await
231 }
232 pub async fn get_forward_messages(&self, forward_id: &str) -> Result<Vec<ForwardNode>> {
234 self.inner.get_forward_messages(forward_id).await
235 }
236 pub async fn delete_friend(&self, user: Uin) -> Result<()> {
238 self.inner.delete_friend(user).await
239 }
240 pub async fn set_friend_remark(&self, user: Uin, remark: &str) -> Result<()> {
242 self.inner.set_friend_remark(user, remark).await
243 }
244 pub async fn send_profile_like(&self, user: Uin, count: u32) -> Result<()> {
246 self.inner.send_profile_like(user, count).await
247 }
248 pub async fn get_friend_requests(&self) -> Result<Vec<Request>> {
250 self.inner.get_friend_requests().await
251 }
252 pub async fn send_group_announcement(
254 &self,
255 group: Uin,
256 content: &str,
257 image: Option<ResourceSource>,
258 ) -> Result<String> {
259 self.inner.send_group_announcement(group, content, image).await
260 }
261 pub async fn get_group_announcements(&self, group: Uin) -> Result<Vec<Announcement>> {
263 self.inner.get_group_announcements(group).await
264 }
265 pub async fn delete_group_announcement(&self, group: Uin, announcement_id: &str) -> Result<()> {
267 self.inner.delete_group_announcement(group, announcement_id).await
268 }
269 pub async fn get_essence_messages(&self, group: Uin) -> Result<Vec<EssenceMessage>> {
271 self.inner.get_essence_messages(group).await
272 }
273 pub async fn set_peer_pin(&self, peer: &Peer, pinned: bool) -> Result<()> {
275 self.inner.set_peer_pin(peer, pinned).await
276 }
277 pub async fn get_peer_pins(&self) -> Result<(Vec<FriendInfo>, Vec<GroupInfo>)> {
280 self.inner.get_peer_pins().await
281 }
282 pub async fn get_impl_info(&self) -> Result<crate::ImplInfo> {
285 self.inner.get_impl_info().await
286 }
287 pub async fn send_friend_nudge(&self, user: Uin, is_self: bool) -> Result<()> {
290 self.inner.send_friend_nudge(user, is_self).await
291 }
292 pub async fn get_group_notices_paged(
296 &self,
297 start_seq: Option<i64>,
298 limit: u32,
299 is_filtered: bool,
300 ) -> Result<(Vec<Notice>, Option<i64>)> {
301 self.inner.get_group_notices_paged(start_seq, limit, is_filtered).await
302 }
303 pub async fn get_group_files(&self, group: Uin, folder_id: Option<&str>) -> Result<GroupFileList> {
305 self.inner.get_group_files(group, folder_id).await
306 }
307 pub async fn get_private_file_download_url(&self, user: Uin, file_id: &str, hash: Option<&str>) -> Result<String> {
309 self.inner.get_private_file_download_url(user, file_id, hash).await
310 }
311 pub async fn create_group_folder(&self, group: Uin, name: &str) -> Result<String> {
313 self.inner.create_group_folder(group, name).await
314 }
315 pub async fn rename_group_folder(&self, group: Uin, folder_id: &str, new_name: &str) -> Result<()> {
317 self.inner.rename_group_folder(group, folder_id, new_name).await
318 }
319 pub async fn delete_group_folder(&self, group: Uin, folder_id: &str) -> Result<()> {
321 self.inner.delete_group_folder(group, folder_id).await
322 }
323 pub async fn move_group_file(
326 &self,
327 group: Uin,
328 file_id: &str,
329 source_folder_id: Option<&str>,
330 target_folder_id: Option<&str>,
331 ) -> Result<()> {
332 self.inner.move_group_file(group, file_id, source_folder_id, target_folder_id).await
333 }
334 pub async fn rename_group_file(
337 &self,
338 group: Uin,
339 file_id: &str,
340 source_folder_id: Option<&str>,
341 new_name: &str,
342 ) -> Result<()> {
343 self.inner.rename_group_file(group, file_id, source_folder_id, new_name).await
344 }
345 pub async fn set_group_avatar(&self, group: Uin, src: ResourceSource) -> Result<()> {
347 self.inner.set_group_avatar(group, src).await
348 }
349 pub async fn set_self_avatar(&self, src: ResourceSource) -> Result<()> {
351 self.inner.set_self_avatar(src).await
352 }
353 pub async fn set_self_nickname(&self, name: &str) -> Result<()> {
355 self.inner.set_self_nickname(name).await
356 }
357 pub async fn set_self_bio(&self, bio: &str) -> Result<()> {
359 self.inner.set_self_bio(bio).await
360 }
361 pub async fn get_status(&self) -> Result<ImplStatus> {
363 self.inner.get_status().await
364 }
365 pub async fn get_csrf_token(&self) -> Result<String> {
367 self.inner.get_csrf_token().await
368 }
369 pub async fn set_restart(&self, delay_ms: u32) -> Result<()> {
371 self.inner.set_restart(delay_ms).await
372 }
373 pub async fn clean_cache(&self) -> Result<()> {
375 self.inner.clean_cache().await
376 }
377 pub async fn can_send_image(&self) -> Result<bool> {
379 self.inner.can_send_image().await
380 }
381 pub async fn can_send_record(&self) -> Result<bool> {
383 self.inner.can_send_record().await
384 }
385 pub async fn get_group_honor_info(&self, group: Uin, kind: HonorKind) -> Result<HonorList> {
387 self.inner.get_group_honor_info(group, kind).await
388 }
389 pub async fn get_record(&self, file: &str, out_format: &str) -> Result<String> {
391 self.inner.get_record(file, out_format).await
392 }
393 pub async fn get_image(&self, file: &str) -> Result<String> {
395 self.inner.get_image(file).await
396 }
397 pub async fn call_raw(&self, action: &str, params: Value) -> Result<Value> {
399 self.inner.call_raw(action, params).await
400 }
401
402 pub fn actions(&self) -> &dyn Actions {
408 &*self.inner
409 }
410
411 pub fn noop() -> Self {
415 Self::new(Arc::new(NoopActions), Uin(0))
416 }
417}
418
419struct NoopActions;
421#[async_trait::async_trait]
422impl crate::invoker::ActionInvoker for NoopActions {
423 fn protocol(&self) -> Protocol {
424 Protocol::Milky
425 }
426 async fn send(&self, peer: &Peer, _message: &[Segment]) -> Result<MessageId> {
427 Ok(MessageId::from_seq(*peer, 0))
428 }
429 async fn call_raw(&self, _action: &str, _params: Value) -> Result<Value> {
430 Ok(Value::Null)
431 }
432}
433impl crate::invoker::OneBotActions for NoopActions {}
434impl crate::invoker::MilkyActions for NoopActions {}