diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..75426fc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "rust-analyzer.linkedProjects": [ + ".\\Cargo.toml", + ".\\Cargo.toml", + ".\\Cargo.toml" + ] +} \ No newline at end of file diff --git a/src/bot.rs b/src/bot/mod.rs similarity index 78% rename from src/bot.rs rename to src/bot/mod.rs index 6612948..6058053 100644 --- a/src/bot.rs +++ b/src/bot/mod.rs @@ -1,18 +1,22 @@ use std::time::Duration; -use tokio_tungstenite::WebSocketStream; -use tokio::{net::TcpStream,time::sleep}; -use tokio_tungstenite::tungstenite::protocol::Message; use futures_util::StreamExt; +use tokio::{net::TcpStream, time::sleep}; +use tokio_tungstenite::tungstenite::protocol::Message; +use tokio_tungstenite::WebSocketStream; use url::Url; - +// 连接 WebSocket pub async fn connect(url: &str) -> WebSocketStream { // 解析 WebSocket URL let server_url = Url::parse(url).expect("Failed to parse WebSocket URL"); // 获取主机地址和端口 - let host = server_url.host_str().expect("No host found in the given URL"); - let port = server_url.port_or_known_default().expect("No port found in the given URL"); + let host = server_url + .host_str() + .expect("No host found in the given URL"); + let port = server_url + .port_or_known_default() + .expect("No port found in the given URL"); // 构建主机地址字符串,包含端口 let host_with_port = format!("{}:{}", host, port); @@ -33,23 +37,24 @@ pub struct Bot { ws_stream: WebSocketStream, reconnecting: bool, } -impl Bot { - pub async fn new(server_url: &str,wsport:i32) -> Self { +impl Bot { + // 创建 Bot 实例 + pub async fn new(server_url: &str, wsport: i32) -> Self { let ws_server_url = format!("ws://{}:{}", server_url, wsport); - let ws_stream = connect(&ws_server_url) - .await; + let ws_stream = connect(&ws_server_url).await; Bot { ws_server_url, ws_stream, - reconnecting : false, + reconnecting: false, } } - //ws返回json数据 - pub async fn receive_message(&mut self) -> Option> { - //self.ws_stream.next().await - loop{ + // 接收 WebSocket 的消息 + pub async fn receive_message( + &mut self, + ) -> Option> { + loop { match self.ws_stream.next().await { Some(Ok(message)) => { // 成功接收消息时,重置 reconnecting 字段 @@ -58,7 +63,6 @@ impl Bot { } Some(Err(err)) => { eprintln!("Error receiving message: {:?}", err); - // 处理错误,例如可以尝试重新连接 println!("WebSocket连接已断开,尝试重新连接"); self.start_reconnect().await; @@ -69,9 +73,9 @@ impl Bot { self.start_reconnect().await; } } - } } - + } + // 关闭 WebSocket 连接 pub async fn close_websocket(&mut self) { // 使用 WebSocketStream 的 close 方法,无需特定的 CloseFrame @@ -80,21 +84,18 @@ impl Bot { } } + // 尝试重新连接 pub async fn start_reconnect(&mut self) { // 防止同时进行多次重连 if !self.reconnecting { self.reconnecting = true; - println!("尝试重新连接..."); - // 重新连接前等待一段时间 sleep(Duration::from_secs(5)).await; - // 尝试重新连接 self.ws_stream = connect(&self.ws_server_url).await; - // 重置 reconnecting 字段 self.reconnecting = false; } } -} \ No newline at end of file +} diff --git a/src/event/message.rs b/src/event/message.rs index 9d08f1e..71b9afc 100644 --- a/src/event/message.rs +++ b/src/event/message.rs @@ -1,5 +1,6 @@ use serde_json::Value; -pub fn process_message_event(json: &Value) { + +pub async fn process_message_event(json: &Value, request: &crate::postrequest::Request) { // 处理 message 类型的逻辑 // 提取消息类型和子类型 let message_type = json["message_type"].as_str().unwrap_or("未知消息类型"); @@ -9,14 +10,19 @@ pub fn process_message_event(json: &Value) { match (message_type, sub_type) { ("private", "friend") => process_private_friend_message(json), ("group", "normal") => process_group_normal_message(json), - _ => println!("Unknown message_type or sub_type: {} - {}", message_type, sub_type), + _ => println!( + "Unknown message_type or sub_type: {} - {}", + message_type, sub_type + ), } } -pub fn process_message_sent_event(json: &Value) { +pub async fn process_message_send_event(json: &Value, request: &crate::postrequest::Request) { // 处理 message_sent 类型的逻辑 // 提取消息内容 - let message_content = json["message"][0]["data"]["text"].as_str().unwrap_or_default(); + let message_content = json["message"][0]["data"]["text"] + .as_str() + .unwrap_or_default(); // 提取发送者昵称 let sender_nickname = json["sender"]["nickname"].as_str().unwrap_or("未知用户"); @@ -27,7 +33,9 @@ pub fn process_message_sent_event(json: &Value) { fn process_private_friend_message(json: &Value) { // 提取私聊消息的发送者昵称和消息内容 let sender_nickname = json["sender"]["nickname"].as_str().unwrap_or("未知用户"); - let message_content = json["message"][0]["data"]["text"].as_str().unwrap_or("未知消息内容"); + let message_content = json["message"][0]["data"]["text"] + .as_str() + .unwrap_or("未知消息内容"); // 打印私聊消息信息 println!("{}发送了消息:{}", sender_nickname, message_content); @@ -36,8 +44,13 @@ fn process_private_friend_message(json: &Value) { fn process_group_normal_message(json: &Value) { // 提取群消息的发送者群名片、昵称和消息内容 let sender_nickname = json["sender"]["nickname"].as_str().unwrap_or("未知用户"); - let message_content = json["message"][0]["data"]["text"].as_str().unwrap_or("未知消息内容"); + let message_content = json["message"][0]["data"]["text"] + .as_str() + .unwrap_or("未知消息内容"); // 打印群消息信息 - println!("来自{}的{}发送了消息:{}", json["group_id"], sender_nickname, message_content); -} \ No newline at end of file + println!( + "来自{}的{}发送了消息:{}", + json["group_id"], sender_nickname, message_content + ); +} diff --git a/src/event/meta_event.rs b/src/event/meta_event.rs index 6a5f487..7e4e0c4 100644 --- a/src/event/meta_event.rs +++ b/src/event/meta_event.rs @@ -1,14 +1,25 @@ use serde_json::Value; -pub fn process_meta_event(json: &Value) { + +pub async fn process_meta_event(json: &Value, request: &crate::postrequest::Request) { // 处理 meta_event 类型的逻辑 // 获取 meta_event_type 值 if let Some(meta_event_type) = json["meta_event_type"].as_str() { match meta_event_type { - "lifecycle" => println!("生活周期"), + "lifecycle" => { + println!("生活周期"); + match request.send_private_msg_api(&2977926714, "Bot启动").await { + Ok(text) => { + println!("post 返回{}", text); + } + Err(err) => { + eprintln!("Error sending HTTP request: {:?}", err); + } + } + } "heartbeat" => println!("心跳一次"), _ => println!("Unknown meta_event_type: {:?}", meta_event_type), } } else { println!("Missing meta_event_type field in meta_event"); } -} \ No newline at end of file +} diff --git a/src/event.rs b/src/event/mod.rs similarity index 50% rename from src/event.rs rename to src/event/mod.rs index b2fa15d..a2408f3 100644 --- a/src/event.rs +++ b/src/event/mod.rs @@ -1,11 +1,11 @@ mod message; +mod meta_event; mod notice; mod request; -mod meta_event; use serde_json::Value; -pub fn process_json(json_str: &str) { +pub async fn process_message(json_str: &str, request: &crate::postrequest::Request) { // 使用 serde_json 解析 JSON 字符串 let json: Value = serde_json::from_str(json_str).expect("Failed to parse JSON"); @@ -13,11 +13,11 @@ pub fn process_json(json_str: &str) { let post_type = json["post_type"].as_str(); // 根据 post_type 值进行分类处理 match post_type { - Some("message") => message::process_message_event(&json), - Some("message_sent") => message::process_message_sent_event(&json), - Some("notice") => notice::process_notice_event(&json), - Some("request") => request::process_request_event(&json), - Some("meta_event") => meta_event::process_meta_event(&json), + Some("message") => message::process_message_event(&json, &&request).await, + Some("message_sent") => message::process_message_send_event(&json, &&request).await, + Some("notice") => notice::process_notice_event(&json, &&request).await, + Some("request") => request::process_request_event(&json, &&request).await, + Some("meta_event") => meta_event::process_meta_event(&json, &&request).await, _ => println!("未知 post_type: {:?}", post_type), } -} \ No newline at end of file +} diff --git a/src/event/notice.rs b/src/event/notice.rs index 3537d72..4f00a6f 100644 --- a/src/event/notice.rs +++ b/src/event/notice.rs @@ -1,7 +1,6 @@ use serde_json::Value; -use crate::postrequest; -pub fn process_notice_event(json: &Value) { +pub async fn process_notice_event(json: &Value, request: &crate::postrequest::Request) { // 处理 notice 类型的逻辑 // 提取 notice_type 值 if let Some(notice_type) = json["notice_type"].as_str() { @@ -98,12 +97,20 @@ fn group_upload(json: &Value) { ); } - fn private_upload(json: &Value) { - if let (Some(user_id), Some(sender), Some(private_file)) = - (json["user_id"].as_i64(), json["sender"].as_i64(), json["private_file"].as_object()) - { - if let (Some(file_id), Some(file_name), Some(file_size), Some(file_url), Some(sub_id), Some(expire)) = ( + if let (Some(user_id), Some(sender), Some(private_file)) = ( + json["user_id"].as_i64(), + json["sender"].as_i64(), + json["private_file"].as_object(), + ) { + if let ( + Some(file_id), + Some(file_name), + Some(file_size), + Some(file_url), + Some(sub_id), + Some(expire), + ) = ( private_file["id"].as_str(), private_file["name"].as_str(), private_file["size"].as_i64(), @@ -253,4 +260,4 @@ fn process_title(json: &Value) { } fn print_error(json: &Value, message: &str) { println!("事件处理失败,{}:\n{}", message, json); -} \ No newline at end of file +} diff --git a/src/event/request.rs b/src/event/request.rs index aafa3e7..15be95b 100644 --- a/src/event/request.rs +++ b/src/event/request.rs @@ -1,5 +1,6 @@ use serde_json::Value; -pub fn process_request_event(json: &Value) { + +pub async fn process_request_event(json: &Value, request: &crate::postrequest::Request) { if let Some(request_type) = json["request_type"].as_str() { match request_type { "friend" => process_friend_request(json), @@ -42,4 +43,4 @@ fn process_group_request(json: &Value) { } else { println!("群请求字段缺失或类型不匹配"); } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..68e0a00 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod bot; +pub mod event; +pub mod postrequest; diff --git a/src/main.rs b/src/main.rs index 2c8b91c..20784b8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,29 +1,32 @@ -mod bot; -mod event; -mod postrequest; - -use postrequest::Request; -use bot::Bot; +use q_bot::bot::Bot; +use q_bot::event::process_message; +use q_bot::postrequest::Request; use tokio::signal::ctrl_c; use tokio_tungstenite::tungstenite::Message; -use event::process_json; + #[tokio::main] async fn main() { - let server_url = "192.168.1.8"; let request = Request::new(server_url, 5700).await; - let mut bot = Bot::new(server_url, 5800,).await; - + let mut bot = Bot::new(server_url, 5800).await; + // match request.send_private_msg_api(&2977926714, "hello").await { + // Ok(text) => { + // println!("post 返回{}", text); + // } + // Err(err) => { + // eprintln!("Error sending HTTP request: {:?}", err); + // } + // } - match request.send_private_msg_api(&2977926714u32,"hello").await{ - Ok(text) => { - println!("post 返回{}", text); - } - Err(err) => { - eprintln!("Error sending HTTP request: {:?}", err); - } - } + // match request.send_group_msg_api(&758145931, "hello").await { + // Ok(text) => { + // println!("post 返回{}", text); + // } + // Err(err) => { + // eprintln!("Error sending HTTP request: {:?}", err); + // } + // } let mut exit_flag = false; @@ -40,7 +43,7 @@ async fn main() { Some(Ok(message)) => { if let Message::Text(text) = message { let json = text; - process_json(&json); + process_message(&json,&&request).await; } } Some(Err(err)) => { @@ -51,7 +54,7 @@ async fn main() { } } } => {}, - + }; if exit_flag { diff --git a/src/postrequest.rs b/src/postrequest.rs deleted file mode 100644 index 90bca7b..0000000 --- a/src/postrequest.rs +++ /dev/null @@ -1,85 +0,0 @@ -use serde_json::{Map, Value, json}; -pub struct Request { - http_server_url: String, - client: reqwest::Client, -} -impl Request { - //post请求 - async fn send_post_request(&self, api: &str,json_data: &str) ->Result { - // 发送 HTTP POST 请求 - match self.client.post(format!("{}{}", self.http_server_url, api)) - .header("Content-Type", "application/json") - .body(json_data.to_owned()) - .send() - .await - { - Ok(response) => { - if response.status().is_success() { - // 成功获取响应 - match response.text().await { - Ok(text) => { - Ok(text) - } - Err(err) => { - eprintln!("Error reading response text: {:?}", err); - Err(err) - } - } - } else { - eprintln!("HTTP request failed with status code: {}", response.status()); - Err(response.error_for_status().unwrap_err()) - } - } - Err(err) => { - eprintln!("Error sending HTTP request: {:?}", err); - Err(err) - } - } - } - pub async fn new(server_url: &str,httpport:i32) -> Self { - let http_server_url = format!("http://{}:{}/", server_url, httpport); - Request { - http_server_url, - client: reqwest::Client::new(), - } - } -} - -impl Request {//高级封装 - pub async fn send_private_msg_api(&self,user_id:&u32,message:&str) -> Result { - // 构建 API 路径 - let api_path = "send_private_msg"; - let json_data = synthesis_json(&[ - json!("user_id"), - json!(user_id), - json!("message"), - json!(message), - ]); - self.send_post_request(api_path, json_data.to_string().as_str()).await - } - // pub async fn send_group_msg_api(&self) -> Result { - // // 构建 API 路径 - // let api_path = "send_group_msg"; - // let json_data = r#" - // { - // "user_id": 2977926714, - // "message": "Bot启动" - // }"#; - // self.send_post_request(api_path, json_data).await - // } -} - - -fn synthesis_json(args: &[Value]) -> Value { - let mut json_map = Map::new(); - let mut iter = args.iter().peekable(); - - while let Some(key) = iter.next() { - if let Some(value) = iter.next() { - if let Some(key_str) = key.as_str() { - json_map.insert(key_str.to_string(), value.clone()); - } - } - } - json!(json_map) -} \ No newline at end of file diff --git a/src/postrequest/mod.rs b/src/postrequest/mod.rs new file mode 100644 index 0000000..0fc2db5 --- /dev/null +++ b/src/postrequest/mod.rs @@ -0,0 +1,108 @@ +use serde_json::{Map, Value}; + +// 请求结构体 +pub struct Request { + http_server_url: String, // HTTP服务器URL + client: reqwest::Client, // HTTP客户端 +} + +// 请求类方法 +impl Request { + // 发送POST请求 + async fn send_post_request( + &self, + api: &str, // API路径 + json_data: &str, // JSON格式的数据 + ) -> Result { + // 发送 HTTP POST 请求 + match self + .client + .post(format!("{}{}", self.http_server_url, api)) + .header("Content-Type", "application/json") + .body(json_data.to_owned()) + .send() + .await + { + Ok(response) => { + if response.status().is_success() { + // 成功获取响应 + match response.text().await { + Ok(text) => Ok(text), + Err(err) => { + eprintln!("Error reading response text: {:?}", err); + Err(err) + } + } + } else { + eprintln!( + "HTTP request failed with status code: {}", + response.status() + ); + Err(response.error_for_status().unwrap_err()) + } + } + Err(err) => { + eprintln!("Error sending HTTP request: {:?}", err); + Err(err) + } + } + } + + // 创建新的Request实例 + pub async fn new(server_url: &str, httpport: i32) -> Self { + let http_server_url = format!("http://{}:{}/", server_url, httpport); + Request { + http_server_url, + client: reqwest::Client::new(), + } + } +} + +// Request类高级封装 +impl Request { + // 发送私聊消息API请求 + pub async fn send_private_msg_api( + &self, + user_id: &i64, // 用户ID + message: &str, // 消息内容 + ) -> Result { + // 构建 API 路径 + let api_path = "send_private_msg"; + let json = synthesis_json(&[ + ("user_id", Value::Number(serde_json::Number::from(*user_id))), + ("message", Value::String(message.to_string())), + ]); + self.send_post_request(api_path, &json.to_string().as_str()) + .await + } + + // 发送群消息API请求 + pub async fn send_group_msg_api( + &self, + group_id: &i64, // 群ID + message: &str, // 消息内容 + ) -> Result { + // 构建 API 路径 + let api_path = "send_group_msg"; + let json = synthesis_json(&[ + ( + "group_id", + Value::Number(serde_json::Number::from(*group_id)), + ), + ("message", Value::String(message.to_string())), + ("auto_escape", Value::Bool(true)), + ]); + self.send_post_request(api_path, &json.to_string().as_str()) + .await + } +} +// 合成JSON数据 +fn synthesis_json(args: &[(&str, Value)]) -> Value { + let mut json_map = Map::new(); + + for (key, value) in args { + json_map.insert(key.to_string(), value.clone()); + } + + Value::Object(json_map) +}