2024-03-13 01:17:50 +08:00
|
|
|
pub mod client;
|
2024-03-12 00:47:00 +08:00
|
|
|
pub mod events;
|
|
|
|
|
2024-11-22 00:01:17 +08:00
|
|
|
use std::sync::OnceLock;
|
|
|
|
|
2024-03-12 00:47:00 +08:00
|
|
|
use rust_socketio::asynchronous::{Client, ClientBuilder};
|
2024-06-14 00:04:51 +08:00
|
|
|
use rust_socketio::{async_any_callback, async_callback};
|
2024-03-12 00:47:00 +08:00
|
|
|
use rust_socketio::{Event, Payload, TransportType};
|
2024-03-16 14:04:30 +08:00
|
|
|
use tracing::{event, span, Level};
|
2024-03-12 00:47:00 +08:00
|
|
|
|
|
|
|
use crate::config::IcaConfig;
|
2024-03-16 14:04:30 +08:00
|
|
|
use crate::error::{ClientResult, IcaError};
|
2024-08-18 02:38:15 +08:00
|
|
|
use crate::{version_str, StopGetter};
|
2024-03-12 00:47:00 +08:00
|
|
|
|
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
|
|
|
|
2024-03-16 14:04:30 +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())
|
2024-03-12 00:47:00 +08:00
|
|
|
.transport_type(TransportType::Websocket)
|
2024-06-14 00:04:51 +08:00
|
|
|
.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))
|
2024-06-14 00:04:51 +08:00
|
|
|
.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))
|
2024-03-12 00:47:00 +08:00
|
|
|
.connect()
|
|
|
|
.await
|
2024-03-16 14:04:30 +08:00
|
|
|
{
|
|
|
|
Ok(client) => {
|
|
|
|
event!(Level::INFO, "socketio connected");
|
|
|
|
client
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
event!(Level::ERROR, "socketio connect failed: {}", e);
|
|
|
|
return Err(IcaError::SocketIoError(e));
|
|
|
|
}
|
|
|
|
};
|
2024-03-12 00:47:00 +08:00
|
|
|
|
|
|
|
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,
|
2024-03-12 00:47:00 +08:00
|
|
|
None,
|
|
|
|
);
|
2024-08-02 21:34:28 +08:00
|
|
|
// 这可是 qq, 要保命
|
2024-03-12 00:47:00 +08:00
|
|
|
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
2024-03-16 14:04:30 +08:00
|
|
|
|
|
|
|
event!(Level::INFO, "发送启动消息到房间: {}", room);
|
|
|
|
|
2024-03-12 00:47:00 +08:00
|
|
|
if let Err(e) =
|
|
|
|
socket.emit("sendMessage", serde_json::to_value(startup_msg).unwrap()).await
|
|
|
|
{
|
2024-03-16 14:04:30 +08:00
|
|
|
event!(Level::INFO, "启动信息发送失败 房间:{}|e:{}", room, e);
|
2024-03-12 00:47:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// 等待停止信号
|
|
|
|
stop_reciver.await.ok();
|
2024-03-16 14:04:30 +08:00
|
|
|
event!(Level::INFO, "socketio client stopping");
|
2024-03-16 16:58:18 +08:00
|
|
|
match socket.disconnect().await {
|
2024-03-16 14:04:30 +08:00
|
|
|
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))
|
|
|
|
}
|
|
|
|
}
|
2024-03-16 14:04:30 +08:00
|
|
|
}
|
|
|
|
}
|
2024-03-12 00:47:00 +08:00
|
|
|
}
|