nonebot_rs/
message.rs

1use serde::{Deserialize, Serialize};
2
3/// Onebot 协议消息定义
4#[derive(Debug, Deserialize, Serialize, Clone)]
5#[serde(tag = "type", content = "data")]
6pub enum Message {
7    /// 纯文本
8    #[serde(rename = "text")]
9    Text {
10        /// 纯文本内容
11        text: String,
12    },
13
14    /// QQ 表情
15    #[serde(rename = "face")]
16    Face {
17        /// QQ 表情 ID
18        id: String,
19    },
20
21    /// 图片
22    #[serde(rename = "image")]
23    Image {
24        /// 图片文件名
25        file: String,
26        /// 图片类型 flash 闪照
27        #[serde(rename = "type")]
28        type_: Option<String>,
29        /// 图片 URL
30        url: Option<String>,
31        /// 是否使用缓存文件 1|0
32        cache: Option<u8>,
33        /// 是否使用代理 1|0
34        proxy: Option<u8>,
35        /// 网络文件下载超时 单位秒
36        timeout: Option<i64>,
37    },
38
39    /// 语音
40    #[serde(rename = "record")]
41    Record {
42        /// 语音文件名
43        file: String,
44        /// 是否变声 1|0
45        magic: Option<u8>,
46        /// 语音 URL    
47        url: Option<String>,
48        /// 是否使用缓存文件 1|0
49        cache: Option<u8>,
50        /// 是否使用代理 1|0
51        proxy: Option<u8>,
52        /// 网络文件下载超时 单位秒
53        timeout: Option<i64>,
54    },
55
56    /// 短视频
57    #[serde(rename = "video")]
58    Video {
59        /// 视频文件名
60        file: String,
61        /// 视频 URL
62        url: Option<String>,
63        /// 是否使用缓存文件 1|0
64        cache: Option<u8>,
65        /// 是否使用代理 1|0
66        proxy: Option<u8>,
67        /// 网络文件下载超时 单位秒
68        timeout: Option<i64>,
69    },
70
71    /// @某人
72    #[serde(rename = "at")]
73    At {
74        /// @QQ ID all 表示全体
75        qq: String,
76    },
77
78    /// 猜拳魔法表情
79    #[serde(rename = "rps")]
80    Rps,
81
82    /// 掷骰子魔法表情
83    #[serde(rename = "dice")]
84    Dice,
85
86    /// 窗口抖动(戳一戳)
87    #[serde(rename = "shake")]
88    Shake,
89
90    /// 戳一戳
91    #[serde(rename = "poke")]
92    Poke {
93        /// 类型
94        #[serde(rename = "type")]
95        type_: String,
96        /// ID
97        id: String,
98        /// 表情名
99        name: Option<String>,
100    },
101
102    /// 匿名发消息
103    #[serde(rename = "anonymous")]
104    Anonymous,
105
106    /// 链接分享
107    #[serde(rename = "share")]
108    Share {
109        /// URL
110        url: String,
111        /// 标题
112        title: String,
113        /// 内容描述
114        content: Option<String>,
115        /// 图片 URl
116        image: Option<String>,
117    },
118
119    /// 推荐好友|群
120    #[serde(rename = "contact")]
121    Contact {
122        /// 类型 qq|group
123        #[serde(rename = "type")]
124        type_: String,
125        /// QQ号|群号
126        id: String,
127    },
128
129    /// 位置
130    #[serde(rename = "location")]
131    Lacation {
132        /// 纬度
133        lat: String,
134        /// 经度           
135        lon: String,
136        /// 标题  
137        title: Option<String>,
138        /// 内容描述
139        content: Option<String>,
140    },
141
142    /// 音乐分享
143    #[serde(rename = "music")]
144    Music {
145        /// 类型 qq|163|xm|custom
146        #[serde(rename = "type")]
147        type_: String,
148        /// 歌曲 ID
149        id: Option<String>,
150        /// 点击后跳转 URL
151        url: Option<String>,
152        /// 歌曲 URL  
153        audio: Option<String>,
154        /// 标题   
155        title: Option<String>,
156        /// 内容描述
157        content: Option<String>,
158        /// 图片 URl
159        image: Option<String>,
160    },
161
162    /// 回复
163    #[serde(rename = "reply")]
164    Reply {
165        /// 回复的消息 ID
166        id: String,
167    },
168
169    /// 合并转发
170    #[serde(rename = "forward")]
171    Forward {
172        /// 合并转发 ID
173        id: String,
174    },
175
176    /// 合并转发节点
177    #[serde(rename = "node")]
178    Node {
179        /// 转发的消息 ID
180        id: Option<String>,
181        /// 发送者 QQ 号        
182        user_id: Option<String>,
183        /// 发送者昵称   
184        nickname: Option<String>,
185        /// 消息内容     
186        content: Option<Vec<Message>>,
187    },
188
189    /// XML 消息
190    #[serde(rename = "xml")]
191    Xml {
192        /// 合并转发 ID
193        data: String,
194    },
195
196    /// JSON 消息
197    #[serde(rename = "json")]
198    Json {
199        /// 合并转发 ID
200        data: String,
201    },
202}
203
204macro_rules! message_builder {
205    ($fn_name: ident, $message_type: tt) => {
206        pub fn $fn_name() -> Message {
207            Message::$message_type
208        }
209    };
210    ($fn_name: ident, $message_type: tt, $param: ident: $param_ty: ty) => {
211        pub fn $fn_name($param: $param_ty) -> Message {
212            Message::$message_type { $param: $param }
213        }
214    };
215    ($fn_name: ident, $message_type: tt, $($param: ident: $param_ty: ty),*) => {
216        pub fn $fn_name($($param: $param_ty,)*) -> Message {
217            Message::$message_type { $($param: $param,)* }
218        }
219    };
220}
221
222impl Message {
223    // pub fn text(text: &str) -> Message {
224    //     Message::Text {
225    //         text: text.to_string(),
226    //     }
227    // }
228    message_builder!(text, Text, text: String);
229    message_builder!(face, Face, id: String);
230    message_builder!(
231        image,
232        Image,
233        file: String,
234        type_: Option<String>,
235        url: Option<String>,
236        cache: Option<u8>,
237        proxy: Option<u8>,
238        timeout: Option<i64>
239    );
240    message_builder!(
241        record,
242        Record,
243        file: String,
244        magic: Option<u8>,
245        url: Option<String>,
246        cache: Option<u8>,
247        proxy: Option<u8>,
248        timeout: Option<i64>
249    );
250    message_builder!(
251        video,
252        Video,
253        file: String,
254        url: Option<String>,
255        cache: Option<u8>,
256        proxy: Option<u8>,
257        timeout: Option<i64>
258    );
259    message_builder!(at, At, qq: String);
260    message_builder!(rps, Rps);
261    message_builder!(dice, Dice);
262    message_builder!(shake, Shake);
263    message_builder!(poke, Poke, type_: String, id: String, name: Option<String>);
264    message_builder!(anonymous, Anonymous);
265    message_builder!(
266        share,
267        Share,
268        url: String,
269        title: String,
270        content: Option<String>,
271        image: Option<String>
272    );
273    message_builder!(contact, Contact, type_: String, id: String);
274    message_builder!(
275        location,
276        Lacation,
277        lat: String,
278        lon: String,
279        title: Option<String>,
280        content: Option<String>
281    );
282    message_builder!(
283        music,
284        Music,
285        type_: String,
286        id: Option<String>,
287        url: Option<String>,
288        audio: Option<String>,
289        title: Option<String>,
290        content: Option<String>,
291        image: Option<String>
292    );
293    message_builder!(reply, Reply, id: String);
294    message_builder!(forward, Forward, id: String);
295    message_builder!(
296        node,
297        Node,
298        id: Option<String>,
299        user_id: Option<String>,
300        nickname: Option<String>,
301        content: Option<Vec<Message>>
302    );
303    message_builder!(xml, Xml, data: String);
304    message_builder!(json, Json, data: String);
305}