qq_bot/wss/
message_event.rs1use std::{path::PathBuf, time::Duration};
2
3use reqwest::{header::USER_AGENT, Client};
4use tokio::{fs::File, io::AsyncWriteExt};
5
6use super::*;
7
8#[derive(Serialize, Deserialize, Debug)]
9pub struct MessageEvent {
10 pub id: String,
11 #[serde(deserialize_with = "crate::utils::read_u64")]
12 pub guild_id: u64,
13 #[serde(deserialize_with = "crate::utils::read_u64")]
14 pub channel_id: u64,
15 pub author: MessageAuthor,
16 #[serde(default)]
17 pub content: String,
18 pub member: MessageMember,
19 pub seq: i64,
20 #[serde(deserialize_with = "crate::utils::read_u64")]
21 pub seq_in_channel: u64,
22 pub timestamp: String,
23 #[serde(default)]
24 pub attachments: Vec<MessageAttachment>,
25}
26
27#[derive(Serialize, Deserialize, Debug)]
28pub struct MessageMember {
29 pub nick: String,
30 pub joined_at: String,
31 pub roles: Vec<String>,
32}
33
34#[derive(Serialize, Deserialize, Debug)]
35pub struct MessageAuthor {
36 #[serde(deserialize_with = "crate::utils::read_u64")]
37 pub id: u64,
38 pub username: String,
39 pub avatar: String,
40 pub bot: bool,
41}
42
43#[derive(Serialize, Deserialize, Debug)]
44pub struct MessageAttachment {
45 pub id: String,
46 pub content_type: String,
47 pub filename: String,
48 pub height: u32,
49 pub width: u32,
50 pub size: u32,
51 pub url: String,
52}
53
54impl MessageAttachment {
55 pub fn aspect_ratio(&self) -> f32 {
56 self.width as f32 / self.height as f32
57 }
58 pub async fn download(&self, dir: &PathBuf) -> QQResult<Vec<u8>> {
59 let url = Url::from_str(&format!("https://{}", self.url))?;
60 let request = Client::default()
61 .request(Method::GET, url)
62 .header(USER_AGENT, "BotNodeSDK/v2.9.4")
63 .timeout(Duration::from_secs(30));
64 let bytes = request.send().await?.bytes().await?;
65 let path = dir.join(&self.filename);
66 let mut file = File::create(path).await?;
67 file.write_all(&bytes).await?;
68 Ok(bytes.to_vec())
69 }
70}