mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-19 14:49:55 +08:00
145 lines
4.9 KiB
Rust
145 lines
4.9 KiB
Rust
use crate::MainStatus;
|
|
use crate::data_struct::ica::messages::{DeleteMessage, SendMessage};
|
|
use crate::data_struct::ica::{RoomId, RoomIdTrait, UserId};
|
|
use crate::error::{ClientResult, IcaError};
|
|
|
|
use colored::Colorize;
|
|
use ed25519_dalek::{Signature, Signer, SigningKey};
|
|
use rust_socketio::Payload;
|
|
use rust_socketio::asynchronous::Client;
|
|
use serde_json::{Value, json};
|
|
use tracing::{Level, event, span};
|
|
|
|
/// "安全" 的 发送一条消息
|
|
pub async fn send_message(client: &Client, message: &SendMessage) -> bool {
|
|
let value = message.as_value();
|
|
match client.emit("sendMessage", value).await {
|
|
Ok(_) => {
|
|
event!(Level::INFO, "send_message {}", format!("{:#?}", message).cyan());
|
|
true
|
|
}
|
|
Err(e) => {
|
|
event!(Level::WARN, "send_message faild:{}", format!("{:#?}", e).red());
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
/// "安全" 的 删除一条消息
|
|
pub async fn delete_message(client: &Client, message: &DeleteMessage) -> bool {
|
|
let value = message.as_value();
|
|
match client.emit("deleteMessage", value).await {
|
|
Ok(_) => {
|
|
event!(Level::DEBUG, "delete_message {}", format!("{:#?}", message).yellow());
|
|
true
|
|
}
|
|
Err(e) => {
|
|
event!(Level::WARN, "delete_message faild:{}", format!("{:#?}", e).red());
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
/// "安全" 的 获取历史消息
|
|
/// ```typescript
|
|
/// async fetchHistory(messageId: string, roomId: number, currentLoadedMessagesCount: number)
|
|
/// ```
|
|
// #[allow(dead_code)]
|
|
// pub async fn fetch_history(client: &Client, roomd_id: RoomId) -> bool { false }
|
|
async fn inner_sign(payload: Payload, client: &Client) -> ClientResult<(), IcaError> {
|
|
let span = span!(Level::INFO, "signing icalingua");
|
|
let _guard = span.enter();
|
|
|
|
// 获取数据
|
|
let require_data = match payload {
|
|
Payload::Text(json_value) => Ok(json_value),
|
|
_ => Err(IcaError::LoginFailed("Got a invalid payload".to_string())),
|
|
}?;
|
|
|
|
let (auth_key, version) = (&require_data[0], &require_data[1]);
|
|
|
|
event!(
|
|
Level::INFO,
|
|
"服务器发过来的待签名key: {:?}, 服务端版本号: {:?}",
|
|
auth_key,
|
|
version
|
|
);
|
|
// 判定和自己的兼容版本号是否 一致
|
|
let server_protocol_version = version
|
|
.get("protocolVersion")
|
|
.unwrap_or(&Value::Null)
|
|
.as_str()
|
|
.unwrap_or("unknow");
|
|
if server_protocol_version != crate::ica::ICA_PROTOCOL_VERSION {
|
|
event!(
|
|
Level::WARN,
|
|
"服务器版本与兼容版本不一致\n服务器协议版本:{:?}\n兼容版本:{}",
|
|
version.get("protocolVersion"),
|
|
crate::ica::ICA_PROTOCOL_VERSION
|
|
);
|
|
}
|
|
|
|
let auth_key = match &require_data.first() {
|
|
Some(Value::String(auth_key)) => Ok(auth_key),
|
|
_ => Err(IcaError::LoginFailed("Got a invalid auth_key".to_string())),
|
|
}?;
|
|
|
|
let salt = hex::decode(auth_key).expect("Got an invalid salt from the server");
|
|
// 签名
|
|
let private_key = MainStatus::global_config().ica().private_key.clone();
|
|
|
|
let array_key: [u8; 32] = hex::decode(private_key)
|
|
.expect("配置文件设置的私钥不是一个有效的私钥, 无法使用hex解析")
|
|
.try_into()
|
|
.expect("配置文件设置的私钥不是一个有效的私钥, 无法转换为[u8; 32]数组");
|
|
let signing_key: SigningKey = SigningKey::from_bytes(&array_key);
|
|
let signature: Signature = signing_key.sign(salt.as_slice());
|
|
|
|
// 发送签名
|
|
let sign = signature.to_bytes().to_vec();
|
|
client.emit("auth", sign).await.expect("发送签名信息失败");
|
|
Ok(())
|
|
}
|
|
|
|
/// 签名回调
|
|
/// 失败的时候得 panic
|
|
pub async fn sign_callback(payload: Payload, client: Client) {
|
|
inner_sign(payload, &client).await.expect("Faild to sign");
|
|
}
|
|
|
|
/// 向指定群发送签到信息
|
|
///
|
|
/// 只能是群啊, 不能是私聊
|
|
pub async fn send_room_sign_in(client: &Client, room_id: RoomId) -> bool {
|
|
if room_id.is_chat() {
|
|
event!(Level::WARN, "不能向私聊发送签到信息");
|
|
return false;
|
|
}
|
|
let data = json!(room_id.abs());
|
|
match client.emit("sendGroupSign", data).await {
|
|
Ok(_) => {
|
|
event!(Level::INFO, "已向群 {} 发送签到信息", room_id);
|
|
true
|
|
}
|
|
Err(e) => {
|
|
event!(Level::ERROR, "向群 {} 发送签到信息失败: {}", room_id, e);
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 向某个群/私聊的某个人发送戳一戳
|
|
pub async fn send_poke(client: &Client, room_id: RoomId, target: UserId) -> bool {
|
|
let data = vec![json!(room_id), json!(target)];
|
|
match client.emit("sendGroupPoke", data).await {
|
|
Ok(_) => {
|
|
event!(Level::INFO, "已向 {} 的 {} 发送戳一戳", room_id, target);
|
|
true
|
|
}
|
|
Err(e) => {
|
|
event!(Level::ERROR, "向 {} 的 {} 发送戳一戳失败: {}", room_id, target, e);
|
|
false
|
|
}
|
|
}
|
|
}
|