1use crate::protocol::Tool;
2
3use crate::protocol::*;
4use crate::utils::asynchronous::{BoxPlatformSendFuture, BoxPlatformSendStream};
5use std::sync::{Arc, Mutex};
6
7struct Inner<C: BotClient> {
8 client: C,
9 map_bots: Option<Box<dyn FnMut(Vec<Bot>) -> Vec<Bot> + Send + 'static>>,
10 map_send: Option<Box<dyn FnMut(MessageContent) -> MessageContent + Send + 'static>>,
11}
12
13pub struct MapClient<C: BotClient> {
20 inner: Arc<Mutex<Inner<C>>>,
21}
22
23impl<C: BotClient> Clone for MapClient<C> {
24 fn clone(&self) -> Self {
25 MapClient {
26 inner: Arc::clone(&self.inner),
27 }
28 }
29}
30
31impl<C: BotClient> MapClient<C> {
32 pub fn new(client: C) -> Self {
33 MapClient {
34 inner: Arc::new(Mutex::new(Inner {
35 client,
36 map_bots: None,
37 map_send: None,
38 })),
39 }
40 }
41
42 pub fn set_map_bots(&mut self, map: impl FnMut(Vec<Bot>) -> Vec<Bot> + Send + 'static) {
44 let mut inner = self.inner.lock().unwrap();
45 inner.map_bots = Some(Box::new(map));
46 }
47
48 pub fn set_map_send(
50 &mut self,
51 map: impl FnMut(MessageContent) -> MessageContent + Send + 'static,
52 ) {
53 let mut inner = self.inner.lock().unwrap();
54 inner.map_send = Some(Box::new(map));
55 }
56}
57
58impl<C: BotClient> From<C> for MapClient<C> {
59 fn from(client: C) -> Self {
60 MapClient::new(client)
61 }
62}
63
64impl<C: BotClient + 'static> BotClient for MapClient<C> {
65 fn clone_box(&self) -> Box<dyn BotClient> {
66 Box::new(self.clone())
67 }
68
69 fn bots(&self) -> BoxPlatformSendFuture<'static, ClientResult<Vec<Bot>>> {
70 let inner = self.inner.clone();
71 let future = self.inner.lock().unwrap().client.bots();
72
73 Box::pin(async move {
74 let result = future.await;
75
76 if result.has_errors() {
77 return result;
78 }
79
80 let mut bots = result.into_value().unwrap();
81
82 if let Some(map_bots) = &mut inner.lock().unwrap().map_bots {
83 bots = map_bots(bots);
84 }
85
86 ClientResult::new_ok(bots)
87 })
88 }
89
90 fn send(
91 &mut self,
92 bot_id: &BotId,
93 messages: &[Message],
94 tools: &[Tool],
95 ) -> BoxPlatformSendStream<'static, ClientResult<MessageContent>> {
96 let inner = self.inner.clone();
97 let stream = self
98 .inner
99 .lock()
100 .unwrap()
101 .client
102 .send(bot_id, messages, tools);
103
104 let stream = async_stream::stream! {
105 for await result in stream {
106 if result.has_errors() {
107 yield result;
108 continue;
109 }
110
111 let mut content = result.into_value().unwrap();
112
113 if let Some(map_send) = &mut inner.lock().unwrap().map_send {
114 content = map_send(content);
115 }
116
117 yield ClientResult::new_ok(content);
118 }
119 };
120
121 Box::pin(stream)
122 }
123}