Skip to main content

kovi_onebot/
onebot_message.rs

1use ahash::HashMap;
2use kovi::error::MessageError;
3use kovi::message::{Message, Segment};
4use serde::{Deserialize, Serialize};
5use serde_json::{Value, json};
6use std::ops::Add;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct OneBotSegment {
10    #[serde(rename = "type")]
11    pub type_: String,
12    pub data: Value,
13}
14
15impl OneBotSegment {
16    pub fn new(type_: &str, data: Value) -> Self {
17        OneBotSegment {
18            type_: type_.to_string(),
19            data,
20        }
21    }
22}
23
24impl PartialEq for OneBotSegment {
25    fn eq(&self, other: &Self) -> bool {
26        self.type_ == other.type_ && self.data == other.data
27    }
28}
29
30/// 消息
31///
32/// **不保证 data 里的 Value 格式是否正确,需要自行检查**
33#[derive(Debug, Clone, Serialize, Deserialize, Default)]
34pub struct OneBotMessage(Vec<OneBotSegment>);
35
36impl From<Message> for OneBotMessage {
37    fn from(v: Message) -> Self {
38        let vec: Vec<OneBotSegment> = v.into_iter().map(OneBotSegment::from).collect();
39        Self(vec)
40    }
41}
42impl From<OneBotMessage> for Message {
43    fn from(v: OneBotMessage) -> Self {
44        let vec: Message = v
45            .into_iter()
46            .map(|v| Segment {
47                kind: v.type_,
48                data: v.data,
49            })
50            .collect::<Vec<Segment>>()
51            .into();
52        vec
53    }
54}
55
56impl From<Segment> for OneBotSegment {
57    fn from(v: Segment) -> Self {
58        Self {
59            type_: v.kind,
60            data: v.data,
61        }
62    }
63}
64
65impl From<Vec<OneBotSegment>> for OneBotMessage {
66    fn from(v: Vec<OneBotSegment>) -> Self {
67        OneBotMessage(v)
68    }
69}
70
71impl From<OneBotMessage> for Vec<OneBotSegment> {
72    fn from(v: OneBotMessage) -> Self {
73        v.0
74    }
75}
76
77impl From<&str> for OneBotMessage {
78    fn from(v: &str) -> Self {
79        OneBotMessage(vec![OneBotSegment {
80            type_: "text".to_string(),
81            data: json!({
82                "text":v,
83            }),
84        }])
85    }
86}
87
88impl From<String> for OneBotMessage {
89    fn from(v: String) -> Self {
90        OneBotMessage(vec![OneBotSegment {
91            type_: "text".to_string(),
92            data: json!({
93                "text":v,
94            }),
95        }])
96    }
97}
98
99impl From<&String> for OneBotMessage {
100    fn from(v: &String) -> Self {
101        OneBotMessage(vec![OneBotSegment {
102            type_: "text".to_string(),
103            data: json!({
104                "text":v,
105            }),
106        }])
107    }
108}
109
110impl PartialEq for OneBotMessage {
111    fn eq(&self, other: &Self) -> bool {
112        self.0 == other.0
113    }
114}
115
116impl Add for OneBotMessage {
117    type Output = OneBotMessage;
118
119    fn add(mut self, rhs: Self) -> Self::Output {
120        for seg in rhs.into_iter() {
121            self.push(seg);
122        }
123        self
124    }
125}
126
127impl OneBotMessage {
128    pub fn iter(&self) -> std::slice::Iter<'_, OneBotSegment> {
129        self.0.iter()
130    }
131
132    pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, OneBotSegment> {
133        self.0.iter_mut()
134    }
135
136    pub fn push(&mut self, s: OneBotSegment) {
137        self.0.push(s);
138    }
139}
140
141impl IntoIterator for OneBotMessage {
142    type Item = OneBotSegment;
143    type IntoIter = std::vec::IntoIter<OneBotSegment>;
144
145    fn into_iter(self) -> Self::IntoIter {
146        self.0.into_iter()
147    }
148}
149
150impl std::ops::Index<usize> for OneBotMessage {
151    type Output = OneBotSegment;
152
153    fn index(&self, index: usize) -> &Self::Output {
154        &self.0[index]
155    }
156}
157
158impl std::ops::IndexMut<usize> for OneBotMessage {
159    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
160        &mut self.0[index]
161    }
162}
163
164impl OneBotMessage {
165    pub fn from_value(v: Value) -> Result<OneBotMessage, MessageError> {
166        if let Some(v) = v.as_array() {
167            match OneBotMessage::from_vec_segment_value(v.clone()) {
168                Ok(msg) => return Ok(msg),
169                Err(err) => return Err(MessageError::ParseError(err.to_string())),
170            };
171        }
172        if let Some(v) = v.as_str() {
173            return Ok(OneBotMessage::from(v));
174        }
175
176        Err(MessageError::ParseError(
177            "OneBotMessage::from_value only accept array".to_string(),
178        ))
179    }
180
181    pub fn from_vec_segment_value(v: Vec<Value>) -> Result<OneBotMessage, serde_json::Error> {
182        let segments: Result<Vec<OneBotSegment>, serde_json::Error> = v
183            .into_iter()
184            .map(|value| {
185                let segment: OneBotSegment = serde_json::from_value(value)?;
186                Ok(segment)
187            })
188            .collect();
189
190        match segments {
191            Ok(segments) => Ok(OneBotMessage(segments)),
192            Err(err) => Err(err),
193        }
194    }
195}
196
197pub(crate) fn cq_to_arr_inner(message: &str) -> Vec<serde_json::Value> {
198    let cqstr = message.chars().collect::<Vec<char>>();
199    let mut text = "".to_owned();
200    let mut type_ = "".to_owned();
201    let mut val = "".to_owned();
202    let mut key = "".to_owned();
203    let mut jsonarr: Vec<serde_json::Value> = vec![];
204    let mut cqcode: HashMap<String, serde_json::Value> = ahash::HashMap::default();
205    let mut stat = 0; //0:text 1:cqcode_type 2:cqcode_key 3:cqcode_val
206    let mut i = 0usize;
207    while i < cqstr.len() {
208        let cur_ch = cqstr[i];
209        if stat == 0 {
210            if cur_ch == '[' {
211                if i + 4 <= cqstr.len() {
212                    let t = &cqstr[i..i + 4];
213                    if t.starts_with(&['[', 'C', 'Q', ':']) {
214                        if !text.is_empty() {
215                            let mut node: HashMap<String, serde_json::Value> =
216                                ahash::HashMap::default();
217                            node.insert("type".to_string(), serde_json::json!("text"));
218                            node.insert("data".to_string(), serde_json::json!({"text": text}));
219                            jsonarr.push(serde_json::json!(node));
220                            text.clear();
221                        }
222                        stat = 1;
223                        i += 3;
224                    } else {
225                        text.push(cqstr[i]);
226                    }
227                } else {
228                    text.push(cqstr[i]);
229                }
230            } else if cur_ch == '&' {
231                if i + 5 <= cqstr.len() {
232                    let t = &cqstr[i..i + 5];
233                    if t.starts_with(&['&', '#', '9', '1', ';']) {
234                        text.push('[');
235                        i += 4;
236                    } else if t.starts_with(&['&', '#', '9', '3', ';']) {
237                        text.push(']');
238                        i += 4;
239                    } else if t.starts_with(&['&', 'a', 'm', 'p', ';']) {
240                        text.push('&');
241                        i += 4;
242                    } else {
243                        text.push(cqstr[i]);
244                    }
245                } else {
246                    text.push(cqstr[i]);
247                }
248            } else {
249                text.push(cqstr[i]);
250            }
251        } else if stat == 1 {
252            if cur_ch == ',' {
253                stat = 2;
254            } else if cur_ch == '&' {
255                if i + 5 <= cqstr.len() {
256                    let t = &cqstr[i..i + 5];
257                    if t.starts_with(&['&', '#', '9', '1', ';']) {
258                        type_.push('[');
259                        i += 4;
260                    } else if t.starts_with(&['&', '#', '9', '3', ';']) {
261                        type_.push(']');
262                        i += 4;
263                    } else if t.starts_with(&['&', 'a', 'm', 'p', ';']) {
264                        type_.push('&');
265                        i += 4;
266                    } else if t.starts_with(&['&', '#', '4', '4', ';']) {
267                        type_.push(',');
268                        i += 4;
269                    } else {
270                        type_.push(cqstr[i]);
271                    }
272                } else {
273                    type_.push(cqstr[i]);
274                }
275            } else {
276                type_.push(cqstr[i]);
277            }
278        } else if stat == 2 {
279            if cur_ch == '=' {
280                stat = 3;
281            } else if cur_ch == '&' {
282                if i + 5 <= cqstr.len() {
283                    let t = &cqstr[i..i + 5];
284                    if t.starts_with(&['&', '#', '9', '1', ';']) {
285                        key.push('[');
286                        i += 4;
287                    } else if t.starts_with(&['&', '#', '9', '3', ';']) {
288                        key.push(']');
289                        i += 4;
290                    } else if t.starts_with(&['&', 'a', 'm', 'p', ';']) {
291                        key.push('&');
292                        i += 4;
293                    } else if t.starts_with(&['&', '#', '4', '4', ';']) {
294                        key.push(',');
295                        i += 4;
296                    } else {
297                        key.push(cqstr[i]);
298                    }
299                } else {
300                    key.push(cqstr[i]);
301                }
302            } else {
303                key.push(cqstr[i]);
304            }
305        } else if stat == 3 {
306            if cur_ch == ']' {
307                let mut node: HashMap<String, serde_json::Value> = ahash::HashMap::default();
308                cqcode.insert(key.clone(), serde_json::json!(val));
309                node.insert("type".to_string(), serde_json::json!(type_));
310                node.insert("data".to_string(), serde_json::json!(cqcode));
311                jsonarr.push(serde_json::json!(node));
312                key.clear();
313                val.clear();
314                text.clear();
315                type_.clear();
316                cqcode.clear();
317                stat = 0;
318            } else if cur_ch == ',' {
319                cqcode.insert(key.clone(), serde_json::json!(val));
320                key.clear();
321                val.clear();
322                stat = 2;
323            } else if cur_ch == '&' {
324                if i + 5 <= cqstr.len() {
325                    let t = &cqstr[i..i + 5];
326                    if t.starts_with(&['&', '#', '9', '1', ';']) {
327                        val.push('[');
328                        i += 4;
329                    } else if t.starts_with(&['&', '#', '9', '3', ';']) {
330                        val.push(']');
331                        i += 4;
332                    } else if t.starts_with(&['&', 'a', 'm', 'p', ';']) {
333                        val.push('&');
334                        i += 4;
335                    } else if t.starts_with(&['&', '#', '4', '4', ';']) {
336                        val.push(',');
337                        i += 4;
338                    } else {
339                        val.push(cqstr[i]);
340                    }
341                } else {
342                    val.push(cqstr[i]);
343                }
344            } else {
345                val.push(cqstr[i]);
346            }
347        }
348        i += 1;
349    }
350    if !text.is_empty() {
351        let mut node: HashMap<String, serde_json::Value> = ahash::HashMap::default();
352        node.insert("type".to_string(), serde_json::json!("text"));
353        node.insert("data".to_string(), serde_json::json!({"text": text}));
354        jsonarr.push(serde_json::json!(node));
355    }
356    jsonarr
357}