socket-bot/ica-rs/src/ica.rs

126 lines
4.6 KiB
Rust
Raw Normal View History

2024-03-13 01:17:50 +08:00
pub mod client;
pub mod events;
2024-11-22 00:01:17 +08:00
use std::sync::OnceLock;
use rust_socketio::asynchronous::{Client, ClientBuilder};
use rust_socketio::{async_any_callback, async_callback};
use rust_socketio::{Event, Payload, TransportType};
use tracing::{event, span, Level};
use crate::config::IcaConfig;
use crate::error::{ClientResult, IcaError};
2024-08-18 02:38:15 +08:00
use crate::{version_str, StopGetter};
2024-08-17 21:49:16 +08:00
/// icalingua 客户端的兼容版本号
2024-11-22 00:01:17 +08:00
pub const ICA_PROTOCOL_VERSION: &str = "2.12.24";
mod status {
use crate::data_struct::ica::all_rooms::Room;
pub use crate::data_struct::ica::online_data::OnlineData;
#[derive(Debug, Clone)]
pub struct MainStatus {
/// 是否启用 ica
pub enable: bool,
/// qq 是否登录
pub qq_login: bool,
/// 当前已加载的消息数量
pub current_loaded_messages_count: u64,
/// 房间数据
pub rooms: Vec<Room>,
/// 在线数据 (Icalingua 信息)
pub online_status: OnlineData,
}
impl MainStatus {
pub fn update_rooms(&mut self, room: Vec<Room>) { self.rooms = room; }
pub fn update_online_status(&mut self, status: OnlineData) { self.online_status = status; }
}
}
static ICA_STATUS: OnceLock<status::MainStatus> = OnceLock::new();
2024-05-04 13:37:54 +08:00
pub async fn start_ica(config: &IcaConfig, stop_reciver: StopGetter) -> ClientResult<(), IcaError> {
let span = span!(Level::INFO, "Icalingua Client");
let _enter = span.enter();
event!(Level::INFO, "ica-async-rs v{} initing", crate::ICA_VERSION);
let socket = match ClientBuilder::new(config.host.clone())
.transport_type(TransportType::Websocket)
.on_any(async_any_callback!(events::any_event))
.on("requireAuth", async_callback!(client::sign_callback))
.on("message", async_callback!(events::connect_callback))
.on("authSucceed", async_callback!(events::connect_callback))
.on("authFailed", async_callback!(events::connect_callback))
2024-06-15 01:34:03 +08:00
.on("messageSuccess", async_callback!(events::success_message))
.on("messageFailed", async_callback!(events::failed_message))
.on("onlineData", async_callback!(events::get_online_data))
.on("setAllRooms", async_callback!(events::update_all_room))
.on("setMessages", async_callback!(events::set_messages))
.on("addMessage", async_callback!(events::add_message))
.on("deleteMessage", async_callback!(events::delete_message))
.connect()
.await
{
Ok(client) => {
event!(Level::INFO, "socketio connected");
client
}
Err(e) => {
event!(Level::ERROR, "socketio connect failed: {}", e);
return Err(IcaError::SocketIoError(e));
}
};
if config.notice_start {
for room in config.notice_room.iter() {
2024-03-13 01:17:50 +08:00
let startup_msg = crate::data_struct::ica::messages::SendMessage::new(
2024-08-18 02:38:15 +08:00
format!("{}\n启动成功", version_str()),
2024-03-13 01:20:41 +08:00
*room,
None,
);
2024-08-02 21:34:28 +08:00
// 这可是 qq, 要保命
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
event!(Level::INFO, "发送启动消息到房间: {}", room);
if let Err(e) =
socket.emit("sendMessage", serde_json::to_value(startup_msg).unwrap()).await
{
event!(Level::INFO, "启动信息发送失败 房间:{}|e:{}", room, e);
}
}
}
// 等待停止信号
stop_reciver.await.ok();
event!(Level::INFO, "socketio client stopping");
2024-03-16 16:58:18 +08:00
match socket.disconnect().await {
Ok(_) => {
event!(Level::INFO, "socketio client stopped");
Ok(())
}
Err(e) => {
2024-03-16 16:58:18 +08:00
// 单独处理 SocketIoError(IncompleteResponseFromEngineIo(WebsocketError(AlreadyClosed)))
match e {
rust_socketio::Error::IncompleteResponseFromEngineIo(inner_e) => {
if inner_e.to_string().contains("AlreadyClosed") {
event!(Level::INFO, "socketio client stopped");
2024-06-05 00:09:08 +08:00
Ok(())
2024-03-16 16:58:18 +08:00
} else {
2024-08-17 21:49:16 +08:00
event!(Level::ERROR, "socketio 客户端出现了 Error: {:?}", inner_e);
2024-03-16 16:58:18 +08:00
Err(IcaError::SocketIoError(
rust_socketio::Error::IncompleteResponseFromEngineIo(inner_e),
))
}
}
e => {
event!(Level::ERROR, "socketio client stopped with error: {}", e);
Err(IcaError::SocketIoError(e))
}
}
}
}
}