This commit is contained in:
shenjack 2024-06-15 23:31:10 +08:00
parent 1e81db998f
commit a02bb089a5
Signed by: shenjack
GPG Key ID: 7B1134A979775551
7 changed files with 116 additions and 35 deletions

20
Cargo.lock generated
View File

@ -802,6 +802,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.3" version = "0.7.3"
@ -1183,6 +1193,7 @@ dependencies = [
"js-sys", "js-sys",
"log", "log",
"mime", "mime",
"mime_guess",
"native-tls", "native-tls",
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
@ -1838,6 +1849,15 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.15" version = "0.3.15"

View File

@ -25,7 +25,7 @@ ed25519-dalek = { version = "2.1", optional = true }
hex = { version = "0.4", optional = true } hex = { version = "0.4", optional = true }
# tailchat # tailchat
reqwest = { version = "0.12.4", optional = true } reqwest = { version = "0.12.4", optional = true, features = ["multipart"] }
md-5 = { version = "0.10.6", optional = true } md-5 = { version = "0.10.6", optional = true }
# ica & tailchat (socketio) # ica & tailchat (socketio)

View File

@ -91,6 +91,7 @@ pub enum SendingFile {
/// [img height=1329 width=1918]{BACKEND}/static/files/6602e20d7b8d10675758e36b/8db505b87bdf9fb309467abcec4d8e2a.png[/img] /// [img height=1329 width=1918]{BACKEND}/static/files/6602e20d7b8d10675758e36b/8db505b87bdf9fb309467abcec4d8e2a.png[/img]
Image { Image {
file: Vec<u8>, file: Vec<u8>,
name: String,
width: u32, width: u32,
height: u32, height: u32,
}, },
@ -102,26 +103,23 @@ impl SendingFile {
pub fn is_some(&self) -> bool { !matches!(self, Self::None) } pub fn is_some(&self) -> bool { !matches!(self, Self::None) }
pub fn is_image(&self) -> bool { matches!(self, Self::Image { .. }) } pub fn is_image(&self) -> bool { matches!(self, Self::Image { .. }) }
pub fn is_file(&self) -> bool { matches!(self, Self::File { .. }) } pub fn is_file(&self) -> bool { matches!(self, Self::File { .. }) }
// pub fn gen_msg(&self, file_path: &str) -> String {
// match self { pub fn file_data(&self) -> Vec<u8> {
// Self::Image { _file, width, height } => { match self {
// format!( Self::Image { file, .. } => file.clone(),
// "[img height={} width={}]{{BACKEND}}/static/files/{}[/img]", Self::File { file, .. } => file.clone(),
// height, _ => vec![],
// width, }
// file_path }
// )
// } pub fn file_name(&self) -> String {
// Self::File { _file, name } => { match self {
// format!( Self::Image { name, .. } => name.clone(),
// "[file name={}]{{BACKEND}}/static/files/{}[/file]", Self::File { name, .. } => name.clone(),
// name, _ => "".to_string(),
// file_path }
// ) }
// } pub fn gen_markdown(&self, response_data: JsonValue) {}
// _ => "".to_string(),
// }
// }
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]

View File

@ -61,8 +61,3 @@ impl BotStatus {
pub fn get_user_id(&self) -> UserId { self.user_id.clone() } pub fn get_user_id(&self) -> UserId { self.user_id.clone() }
} }
#[derive(Debug, Clone)]
pub struct BotStatusSnapshot {
user_id: UserId,
}

View File

@ -25,7 +25,7 @@ pub async fn get_online_data(payload: Payload, _client: Client) {
pub async fn add_message(payload: Payload, client: Client) { pub async fn add_message(payload: Payload, client: Client) {
if let Payload::Text(values) = payload { if let Payload::Text(values) = payload {
if let Some(value) = values.first() { if let Some(value) = values.first() {
let span = span!(Level::INFO, "ica add_message"); let span = span!(Level::INFO, "ica new_msg");
let _enter = span.enter(); let _enter = span.enter();
let message: NewMessage = serde_json::from_value(value.clone()).unwrap(); let message: NewMessage = serde_json::from_value(value.clone()).unwrap();
// 检测是否在过滤列表内 // 检测是否在过滤列表内
@ -33,7 +33,7 @@ pub async fn add_message(payload: Payload, client: Client) {
return; return;
} }
event!(Level::INFO, "add_message {}", message.to_string().cyan()); event!(Level::INFO, "new_msg {}", message.to_string().cyan());
// 就在这里处理掉最基本的消息 // 就在这里处理掉最基本的消息
// 之后的处理交给插件 // 之后的处理交给插件
if !message.is_from_self() && !message.is_reply() { if !message.is_from_self() && !message.is_reply() {

View File

@ -124,4 +124,7 @@ impl TailchatSendingMessagePy {
self.message.content = content; self.message.content = content;
self.clone() self.clone()
} }
// pub fn set_img(&mut self, file: Vec<u8>, file_type: String) {
// self.message.add_img(file, file_type, as_sticker);
// }
} }

View File

@ -1,37 +1,102 @@
use crate::data_struct::tailchat::messages::SendingMessage; use crate::data_struct::tailchat::messages::SendingMessage;
// use crate::data_struct::tailchat::{ConverseId, GroupId, MessageId, UserId}; // use crate::data_struct::tailchat::{ConverseId, GroupId, MessageId, UserId};
use rust_socketio::asynchronous::Client;
use colored::Colorize; use colored::Colorize;
use reqwest::multipart;
use rust_socketio::asynchronous::Client;
use serde_json::{json, Value}; use serde_json::{json, Value};
use tracing::{debug, info, warn}; use tracing::{event, span, Level};
pub async fn send_message(client: &Client, message: &SendingMessage) -> bool { pub async fn send_message(client: &Client, message: &SendingMessage) -> bool {
let span = span!(Level::INFO, "tailchat send message");
let _enter = span.enter();
if message.contain_file() { if message.contain_file() {
// 处理文件 // 处理文件
let mut header = reqwest::header::HeaderMap::new();
header
.insert(
"X-Token",
crate::MainStatus::global_tailchat_status().jwt_token.clone().parse().unwrap(),
)
.unwrap();
let file_client = match reqwest::ClientBuilder::new().default_headers(header).build() {
Ok(client) => client,
Err(e) => {
event!(Level::ERROR, "file_client build failed:{}", format!("{:#?}", e).red());
return false;
}
};
// 感谢 https://stackoverflow.com/questions/65814450/how-to-post-a-file-using-reqwest
let upload_url =
format!("{}/upload", crate::MainStatus::global_config().tailchat().host.clone());
let file_body =
multipart::Part::stream(message.file.file_data()).file_name(message.file.file_name());
let form_data = multipart::Form::new().part("file", file_body);
event!(Level::INFO, "sending file message");
let data = match file_client.post(&upload_url).multipart(form_data).send().await {
Ok(resp) => {
if resp.status().is_success() {
match resp.text().await {
Ok(text) => match serde_json::from_str::<Value>(&text) {
Ok(json) => json,
Err(e) => {
event!(
Level::ERROR,
"file uploaded, but response parse failed:{}",
format!("{:#?}", e).red()
);
return false;
}
},
Err(e) => {
event!(
Level::ERROR,
"file uploaded, but failed to get response:{}",
format!("{:#?}", e).red()
);
return false;
}
}
} else {
event!(Level::ERROR, "file upload faild:{}", format!("{:#?}", resp).red());
return false;
}
}
Err(e) => {
event!(
Level::ERROR,
"file upload failed while posting data:{}",
format!("{:#?}", e).red()
);
return false;
}
};
event!(Level::INFO, "file upload success with data:{}", format!("{:#?}", data).cyan());
} }
let value: Value = message.as_value(); let value: Value = message.as_value();
match client.emit("chat.message.sendMessage", value).await { match client.emit("chat.message.sendMessage", value).await {
Ok(_) => { Ok(_) => {
debug!("send_message {}", format!("{:#?}", message).cyan()); event!(Level::DEBUG, "send message {}", format!("{:#?}", message).cyan());
true true
} }
Err(e) => { Err(e) => {
warn!("send_message failed:{}", format!("{:#?}", e).red()); event!(Level::WARN, "send message failed:{}", format!("{:#?}", e).red());
false false
} }
} }
} }
pub async fn emit_join_room(client: &Client) -> bool { pub async fn emit_join_room(client: &Client) -> bool {
let span = span!(Level::INFO, "tailchat findAndJoinRoom");
let _enter = span.enter();
match client.emit("chat.converse.findAndJoinRoom", json!([])).await { match client.emit("chat.converse.findAndJoinRoom", json!([])).await {
Ok(_) => { Ok(_) => {
info!("emiting join room"); event!(Level::INFO, "emiting join room");
true true
} }
Err(e) => { Err(e) => {
warn!("emit_join_room faild:{}", format!("{:#?}", e).red()); event!(Level::WARN, "emit_join_room faild:{}", format!("{:#?}", e).red());
false false
} }
} }