mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-20 11:59:53 +08:00
Compare commits
No commits in common. "84ced3b30a447e929bd562a9e4e7e5b84a8ba193" and "2f535cc960159dcbf20456f04c60ca4977d7e554" have entirely different histories.
84ced3b30a
...
2f535cc960
|
@ -2,30 +2,16 @@
|
|||
|
||||
from typing import Callable, Tuple
|
||||
|
||||
|
||||
"""
|
||||
ica.rs
|
||||
pub type RoomId = i64;
|
||||
pub type UserId = i64;
|
||||
pub type MessageId = String;
|
||||
"""
|
||||
class IcaType:
|
||||
RoomId = int
|
||||
UserId = int
|
||||
MessageId = str
|
||||
|
||||
"""
|
||||
tailchat.rs
|
||||
pub type GroupId = String;
|
||||
pub type ConverseId = String;
|
||||
pub type UserId = String;
|
||||
pub type MessageId = String;
|
||||
"""
|
||||
class TailchatType:
|
||||
GroupId = str
|
||||
ConverseId = str
|
||||
UserId = str
|
||||
MessageId = str
|
||||
RoomId = int
|
||||
UserId = int
|
||||
MessageId = str
|
||||
|
||||
|
||||
class IcaStatus:
|
||||
"""
|
||||
|
@ -39,7 +25,7 @@ class IcaStatus:
|
|||
def online(self) -> bool:
|
||||
...
|
||||
@property
|
||||
def self_id(self) -> IcaType.UserId:
|
||||
def self_id(self) -> UserId:
|
||||
...
|
||||
@property
|
||||
def nick_name(self) -> str:
|
||||
|
@ -96,13 +82,13 @@ class IcaNewMessage:
|
|||
def __str__(self) -> str:
|
||||
...
|
||||
@property
|
||||
def id(self) -> IcaType.MessageId:
|
||||
def id(self) -> MessageId:
|
||||
...
|
||||
@property
|
||||
def content(self) -> str:
|
||||
...
|
||||
@property
|
||||
def sender_id(self) -> IcaType.UserId:
|
||||
def sender_id(self) -> UserId:
|
||||
...
|
||||
@property
|
||||
def is_from_self(self) -> bool:
|
||||
|
@ -117,7 +103,7 @@ class IcaNewMessage:
|
|||
def is_chat_msg(self) -> bool:
|
||||
"""是否是私聊消息"""
|
||||
@property
|
||||
def room_id(self) -> IcaType.RoomId:
|
||||
def room_id(self) -> RoomId:
|
||||
"""
|
||||
如果是群聊消息, 返回 (-群号)
|
||||
如果是私聊消息, 返回 对面qq
|
||||
|
@ -162,45 +148,10 @@ class IcaClient:
|
|||
"""向日志中输出警告信息"""
|
||||
|
||||
|
||||
class TailchatReciveMessage:
|
||||
class MatrixClient:
|
||||
"""
|
||||
Tailchat 接收到的新消息
|
||||
Matrix 的客户端
|
||||
"""
|
||||
@property
|
||||
def id(self) -> TailchatType.MessageId:
|
||||
...
|
||||
@property
|
||||
def content(self) -> str:
|
||||
...
|
||||
@property
|
||||
def sender_id(self) -> TailchatType.UserId:
|
||||
...
|
||||
@property
|
||||
def is_from_self(self) -> bool:
|
||||
...
|
||||
@property
|
||||
def is_reply(self) -> bool:
|
||||
...
|
||||
@property
|
||||
def group_id(self) -> TailchatType.GroupId:
|
||||
...
|
||||
@property
|
||||
def converse_id(self) -> TailchatType.ConverseId:
|
||||
...
|
||||
|
||||
|
||||
|
||||
class TailchatClient:
|
||||
"""
|
||||
Tailchat 的客户端
|
||||
"""
|
||||
|
||||
def debug(self, message: str) -> None:
|
||||
"""向日志中输出调试信息"""
|
||||
def info(self, message: str) -> None:
|
||||
"""向日志中输出信息"""
|
||||
def warn(self, message: str) -> None:
|
||||
"""向日志中输出警告信息"""
|
||||
|
||||
|
||||
class ConfigData:
|
||||
|
@ -218,12 +169,12 @@ on_ica_message = Callable[[IcaNewMessage, IcaClient], None]
|
|||
# def on_message(msg: NewMessage, client: IcaClient) -> None:
|
||||
# ...
|
||||
|
||||
on_ica_delete_message = Callable[[IcaType.MessageId, IcaClient], None]
|
||||
on_ica_delete_message = Callable[[MessageId, IcaClient], None]
|
||||
# def on_delete_message(msg_id: MessageId, client: IcaClient) -> None:
|
||||
# ...
|
||||
|
||||
# TODO: Tailchat adapter
|
||||
on_tailchat_message = Callable[[], None]
|
||||
# TODO: Matrix adapter
|
||||
on_matrix_message = Callable[[], None]
|
||||
|
||||
on_config = Callable[[None], Tuple[str, str]]
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ use serde::Deserialize;
|
|||
use toml::from_str;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::data_struct::{ica, tailchat};
|
||||
|
||||
/// Icalingua bot 的配置
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct IcaConfig {
|
||||
|
@ -15,33 +13,15 @@ pub struct IcaConfig {
|
|||
/// icalingua 服务器地址
|
||||
pub host: String,
|
||||
/// bot 的 qq
|
||||
pub self_id: ica::UserId,
|
||||
pub self_id: u64,
|
||||
/// 提醒的房间
|
||||
pub notice_room: Vec<ica::RoomId>,
|
||||
pub notice_room: Vec<i64>,
|
||||
/// 是否提醒
|
||||
pub notice_start: bool,
|
||||
/// 管理员列表
|
||||
pub admin_list: Vec<ica::UserId>,
|
||||
pub admin_list: Vec<i64>,
|
||||
/// 过滤列表
|
||||
pub filter_list: Vec<ica::UserId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct TailchatConfig {
|
||||
/// 服务器地址
|
||||
pub host: String,
|
||||
/// 机器人 App ID
|
||||
pub app_id: String,
|
||||
/// 机器人 App Secret
|
||||
pub app_secret: String,
|
||||
/// 提醒的房间
|
||||
pub notice_room: Vec<(tailchat::GroupId, tailchat::ConverseId)>,
|
||||
/// 是否提醒
|
||||
pub notice_start: bool,
|
||||
/// 管理员列表
|
||||
pub admin_list: Vec<tailchat::UserId>,
|
||||
/// 过滤列表
|
||||
pub filter_list: Vec<tailchat::UserId>,
|
||||
pub filter_list: Vec<i64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
|
@ -60,11 +40,6 @@ pub struct BotConfig {
|
|||
/// Ica 配置
|
||||
pub ica: Option<IcaConfig>,
|
||||
|
||||
/// 是否启用 Tailchat
|
||||
pub enable_tailchat: Option<bool>,
|
||||
/// Tailchat 配置
|
||||
pub tailchat: Option<TailchatConfig>,
|
||||
|
||||
/// 是否启用 Python 插件
|
||||
pub enable_py: Option<bool>,
|
||||
/// Python 插件配置
|
||||
|
@ -113,26 +88,6 @@ impl BotConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// 检查是否启用 Tailchat
|
||||
pub fn check_tailchat(&self) -> bool {
|
||||
match self.enable_tailchat {
|
||||
Some(enable) => {
|
||||
if enable && self.tailchat.is_none() {
|
||||
warn!("enable_tailchat 为 true 但未填写 [tailchat] 配置\n将不启用 Tailchat");
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if self.tailchat.is_some() {
|
||||
warn!("未填写 enable_tailchat 但填写了 [tailchat] 配置\n将不启用 Tailchat");
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 检查是否启用 Python 插件
|
||||
pub fn check_py(&self) -> bool {
|
||||
match self.enable_py {
|
||||
|
@ -154,8 +109,5 @@ impl BotConfig {
|
|||
}
|
||||
|
||||
pub fn ica(&self) -> IcaConfig { self.ica.clone().expect("No ica config found") }
|
||||
pub fn tailchat(&self) -> TailchatConfig {
|
||||
self.tailchat.clone().expect("No tailchat config found")
|
||||
}
|
||||
pub fn py(&self) -> PyConfig { self.py.clone().expect("No py config found") }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
pub mod messages;
|
||||
pub mod status;
|
||||
|
||||
pub type GroupId = String;
|
||||
pub type ConverseId = String;
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::data_struct::tailchat::UserId;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct LoginData {
|
||||
pub jwt: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: UserId,
|
||||
pub email: String,
|
||||
pub nickname: String,
|
||||
pub avatar: String,
|
||||
}
|
|
@ -12,8 +12,6 @@ pub enum IcaError {
|
|||
pub enum TailchatError {
|
||||
/// Socket IO 链接错误
|
||||
SocketIoError(rust_socketio::error::Error),
|
||||
/// reqwest 相关错误
|
||||
ReqwestError(reqwest::Error),
|
||||
/// 登录失败
|
||||
LoginFailed(String),
|
||||
}
|
||||
|
@ -37,14 +35,6 @@ impl From<rust_socketio::Error> for IcaError {
|
|||
fn from(e: rust_socketio::Error) -> Self { IcaError::SocketIoError(e) }
|
||||
}
|
||||
|
||||
impl From<rust_socketio::Error> for TailchatError {
|
||||
fn from(e: rust_socketio::Error) -> Self { TailchatError::SocketIoError(e) }
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for TailchatError {
|
||||
fn from(e: reqwest::Error) -> Self { TailchatError::ReqwestError(e) }
|
||||
}
|
||||
|
||||
impl std::fmt::Display for IcaError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
@ -58,7 +48,6 @@ impl std::fmt::Display for TailchatError {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
TailchatError::SocketIoError(e) => write!(f, "Socket IO 链接错误: {}", e),
|
||||
TailchatError::ReqwestError(e) => write!(f, "Reqwest 错误: {}", e),
|
||||
TailchatError::LoginFailed(e) => write!(f, "登录失败: {}", e),
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +85,6 @@ impl std::error::Error for TailchatError {
|
|||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
TailchatError::SocketIoError(e) => Some(e),
|
||||
TailchatError::ReqwestError(e) => Some(e),
|
||||
TailchatError::LoginFailed(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ async fn inner_sign(payload: Payload, client: Client) -> ClientResult<(), IcaErr
|
|||
let (auth_key, version) = (&require_data[0], &require_data[1]);
|
||||
|
||||
debug!("auth_key: {:?}, server_version: {:?}", auth_key, 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())),
|
||||
|
|
|
@ -17,7 +17,6 @@ use tracing::{event, info, span, Level};
|
|||
pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus {
|
||||
config: None,
|
||||
ica_status: None,
|
||||
tailchat_status: None,
|
||||
};
|
||||
|
||||
pub type MainStatus = status::BotStatus;
|
||||
|
@ -81,18 +80,6 @@ async fn main() {
|
|||
event!(Level::INFO, "未启用 ica");
|
||||
}
|
||||
|
||||
let (tailchat_send, tailchat_recv) = tokio::sync::oneshot::channel::<()>();
|
||||
|
||||
if bot_config.check_tailchat() {
|
||||
event!(Level::INFO, "启动 Tailchat");
|
||||
let config = bot_config.tailchat();
|
||||
tokio::spawn(async move {
|
||||
tailchat::start_tailchat(config, tailchat_recv).await.unwrap();
|
||||
});
|
||||
} else {
|
||||
event!(Level::INFO, "未启用 Tailchat");
|
||||
}
|
||||
|
||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||
// 等待一个输入
|
||||
info!("Press any key to exit");
|
||||
|
@ -100,7 +87,6 @@ async fn main() {
|
|||
std::io::stdin().read_line(&mut input).unwrap();
|
||||
|
||||
ica_send.send(()).ok();
|
||||
tailchat_send.send(()).ok();
|
||||
|
||||
info!("Disconnected");
|
||||
}
|
||||
|
|
|
@ -96,21 +96,8 @@ pub const ICA_DELETE_MESSAGE_FUNC: &str = "on_ica_delete_message";
|
|||
pub const TAILCHAT_NEW_MESSAGE_FUNC: &str = "on_tailchat_message";
|
||||
|
||||
macro_rules! call_py_func {
|
||||
($args:expr, $plugin:expr, $plugin_path:expr, $func_name:expr, $client:expr) => {
|
||||
tokio::spawn(async move {
|
||||
Python::with_gil(|py| {
|
||||
if let Ok(py_func) = get_func($plugin.py_module.bind(py), $func_name) {
|
||||
if let Err(e) = py_func.call1($args) {
|
||||
let e = PyPluginError::FuncCallError(
|
||||
e,
|
||||
$func_name.to_string(),
|
||||
$plugin_path.to_string_lossy().to_string(),
|
||||
);
|
||||
warn!("failed to call function<{}>: {:?}", $func_name, e);
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
($args:expr, $func_name:expr, $client:expr) => {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -125,21 +112,20 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl
|
|||
let client = class::ica::IcaClientPy::new(client);
|
||||
let args = (msg, client);
|
||||
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
||||
call_py_func!(args, plugin, path, ICA_NEW_MESSAGE_FUNC, client);
|
||||
// tokio::spawn(async move {
|
||||
// Python::with_gil(|py| {
|
||||
// if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) {
|
||||
// if let Err(e) = py_func.call1(args) {
|
||||
// let e = PyPluginError::FuncCallError(
|
||||
// e,
|
||||
// ICA_NEW_MESSAGE_FUNC.to_string(),
|
||||
// path.to_string_lossy().to_string(),
|
||||
// );
|
||||
// warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
tokio::spawn(async move {
|
||||
Python::with_gil(|py| {
|
||||
if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) {
|
||||
if let Err(e) = py_func.call1(args) {
|
||||
let e = PyPluginError::FuncCallError(
|
||||
e,
|
||||
ICA_NEW_MESSAGE_FUNC.to_string(),
|
||||
path.to_string_lossy().to_string(),
|
||||
);
|
||||
warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,31 +137,23 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
|
|||
let msg_id = msg_id.clone();
|
||||
let client = class::ica::IcaClientPy::new(client);
|
||||
let args = (msg_id.clone(), client);
|
||||
call_py_func!(args, plugin, path, ICA_DELETE_MESSAGE_FUNC, client);
|
||||
// tokio::spawn(async move {
|
||||
// Python::with_gil(|py| {
|
||||
// if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) {
|
||||
// if let Err(e) = py_func.call1(args) {
|
||||
// let e = PyPluginError::FuncCallError(
|
||||
// e,
|
||||
// ICA_DELETE_MESSAGE_FUNC.to_string(),
|
||||
// path.to_string_lossy().to_string(),
|
||||
// );
|
||||
// warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e);
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
tokio::spawn(async move {
|
||||
Python::with_gil(|py| {
|
||||
if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) {
|
||||
if let Err(e) = py_func.call1(args) {
|
||||
let e = PyPluginError::FuncCallError(
|
||||
e,
|
||||
ICA_DELETE_MESSAGE_FUNC.to_string(),
|
||||
path.to_string_lossy().to_string(),
|
||||
);
|
||||
warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn tailchat_new_message_py(message: &tailchat::messages::ReciveMessage, client: &Client) {
|
||||
verify_plugins();
|
||||
pub async fn tailchat_new_message_py(message: tailchat::messages::ReciveMessage, client: &Client) {
|
||||
|
||||
let plugins = PyStatus::get_files();
|
||||
for (path, plugin) in plugins.iter() {
|
||||
// let msg = class::tailchat::
|
||||
let args = ();
|
||||
call_py_func!(args, plugin, path, TAILCHAT_NEW_MESSAGE_FUNC, client);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,7 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
|
|||
};
|
||||
match config_value {
|
||||
Ok(config) => {
|
||||
let py_config =
|
||||
Bound::new(py, class::ConfigDataPy::new(config)).unwrap();
|
||||
let py_config = Bound::new(py, class::ConfigDataPy::new(config)).unwrap();
|
||||
module.setattr("CONFIG_DATA", py_config).unwrap();
|
||||
Ok(PyPlugin {
|
||||
file_path: path,
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::MAIN_STATUS;
|
|||
pub struct BotStatus {
|
||||
pub config: Option<BotConfig>,
|
||||
pub ica_status: Option<ica::MainStatus>,
|
||||
pub tailchat_status: Option<tailchat::MainStatus>,
|
||||
}
|
||||
|
||||
impl BotStatus {
|
||||
|
@ -19,11 +18,6 @@ impl BotStatus {
|
|||
MAIN_STATUS.ica_status = Some(status);
|
||||
}
|
||||
}
|
||||
pub fn update_tailchat_status(status: tailchat::MainStatus) {
|
||||
unsafe {
|
||||
MAIN_STATUS.tailchat_status = Some(status);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn static_init(config: BotConfig) {
|
||||
unsafe {
|
||||
|
@ -39,20 +33,13 @@ impl BotStatus {
|
|||
}
|
||||
|
||||
pub fn global_config() -> &'static BotConfig { unsafe { MAIN_STATUS.config.as_ref().unwrap() } }
|
||||
|
||||
pub fn global_ica_status() -> &'static ica::MainStatus {
|
||||
unsafe { MAIN_STATUS.ica_status.as_ref().unwrap() }
|
||||
}
|
||||
pub fn global_tailchat_status() -> &'static tailchat::MainStatus {
|
||||
unsafe { MAIN_STATUS.tailchat_status.as_ref().unwrap() }
|
||||
}
|
||||
|
||||
pub fn global_ica_status_mut() -> &'static mut ica::MainStatus {
|
||||
unsafe { MAIN_STATUS.ica_status.as_mut().unwrap() }
|
||||
}
|
||||
pub fn global_tailchat_status_mut() -> &'static mut tailchat::MainStatus {
|
||||
unsafe { MAIN_STATUS.tailchat_status.as_mut().unwrap() }
|
||||
}
|
||||
}
|
||||
|
||||
pub mod ica {
|
||||
|
@ -78,33 +65,3 @@ pub mod ica {
|
|||
pub fn update_online_status(&mut self, status: OnlineData) { self.online_status = status; }
|
||||
}
|
||||
}
|
||||
|
||||
pub mod tailchat {
|
||||
use crate::data_struct::tailchat::UserId;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MainStatus {
|
||||
/// 是否启用 tailchat
|
||||
pub enable: bool,
|
||||
/// 是否登录
|
||||
pub login: bool,
|
||||
/// 用户 ID
|
||||
pub user_id: UserId,
|
||||
/// 昵称
|
||||
pub nick_name: String,
|
||||
/// 邮箱
|
||||
pub email: String,
|
||||
/// JWT Token
|
||||
pub jwt_token: String,
|
||||
/// avatar
|
||||
pub avatar: String,
|
||||
}
|
||||
|
||||
impl MainStatus {
|
||||
pub fn update_user_id(&mut self, user_id: UserId) { self.user_id = user_id; }
|
||||
pub fn update_nick_name(&mut self, nick_name: String) { self.nick_name = nick_name; }
|
||||
pub fn update_email(&mut self, email: String) { self.email = email; }
|
||||
pub fn update_jwt_token(&mut self, jwt_token: String) { self.jwt_token = jwt_token; }
|
||||
pub fn update_avatar(&mut self, avatar: String) { self.avatar = avatar; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,104 +1,23 @@
|
|||
pub mod client;
|
||||
pub mod events;
|
||||
|
||||
use futures_util::FutureExt;
|
||||
use md5::{Digest, Md5};
|
||||
use reqwest::{Body, ClientBuilder as reqwest_ClientBuilder};
|
||||
use rust_socketio::asynchronous::{Client, ClientBuilder};
|
||||
use rust_socketio::{Event, Payload, TransportType};
|
||||
use serde_json::{from_str, from_value, json, Value};
|
||||
use tracing::{event, span, Level};
|
||||
|
||||
use crate::config::TailchatConfig;
|
||||
use crate::data_struct::tailchat::status::LoginData;
|
||||
// use crate::config::IcaConfig;
|
||||
use crate::error::{ClientResult, TailchatError};
|
||||
use crate::{wrap_any_callback, wrap_callback, StopGetter};
|
||||
|
||||
pub async fn start_tailchat(
|
||||
config: TailchatConfig,
|
||||
stop_reciver: StopGetter,
|
||||
) -> ClientResult<(), TailchatError> {
|
||||
pub async fn start_tailchat() -> ClientResult<(), TailchatError> {
|
||||
let span = span!(Level::INFO, "Tailchat Client");
|
||||
let _enter = span.enter();
|
||||
|
||||
event!(Level::INFO, "tailchat-async-rs v{} initing", crate::TAILCHAT_VERSION);
|
||||
|
||||
let mut hasher = Md5::new();
|
||||
hasher.update(config.app_id.as_bytes());
|
||||
hasher.update(config.app_secret.as_bytes());
|
||||
|
||||
let token = format!("{:x}", hasher.finalize());
|
||||
|
||||
let mut header_map = reqwest::header::HeaderMap::new();
|
||||
header_map.append("Content-Type", "application/json".parse().unwrap());
|
||||
|
||||
let client = reqwest_ClientBuilder::new().default_headers(header_map.clone()).build()?;
|
||||
let status = match client
|
||||
.post(&format!("{}/api/openapi/bot/login", config.host))
|
||||
.body(json! {{"appId": config.app_id, "token": token}}.to_string())
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(resp) => {
|
||||
if resp.status().is_success() {
|
||||
let raw_data = resp.text().await?;
|
||||
let json_data = serde_json::from_str::<Value>(&raw_data).unwrap();
|
||||
let login_data = serde_json::from_value::<LoginData>(json_data["data"].clone());
|
||||
match login_data {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
event!(Level::ERROR, "login failed: {}|{}", e, raw_data);
|
||||
return Err(TailchatError::LoginFailed(e.to_string()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(TailchatError::LoginFailed(resp.text().await?));
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(TailchatError::LoginFailed(e.to_string())),
|
||||
};
|
||||
|
||||
header_map.append("X-Token", status.jwt.clone().parse().unwrap());
|
||||
|
||||
let client = reqwest_ClientBuilder::new().default_headers(header_map).build()?;
|
||||
|
||||
let socket = ClientBuilder::new(config.host)
|
||||
.auth(json!({"token": status.jwt.clone()}))
|
||||
.transport_type(TransportType::Websocket)
|
||||
.on_any(wrap_any_callback!(events::any_event))
|
||||
.on("chat.message.sendMessage", wrap_callback!(events::on_message))
|
||||
.connect()
|
||||
.await?;
|
||||
|
||||
// notify:chat.message.delete
|
||||
// notify:chat.message.add
|
||||
|
||||
stop_reciver.await.ok();
|
||||
event!(Level::INFO, "socketio client stopping");
|
||||
match socket.disconnect().await {
|
||||
Ok(_) => {
|
||||
event!(Level::INFO, "socketio client stopped");
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
// 单独处理 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");
|
||||
return Ok(());
|
||||
} else {
|
||||
event!(Level::ERROR, "socketio client stopped with error: {:?}", inner_e);
|
||||
Err(TailchatError::SocketIoError(
|
||||
rust_socketio::Error::IncompleteResponseFromEngineIo(inner_e),
|
||||
))
|
||||
}
|
||||
}
|
||||
e => {
|
||||
event!(Level::ERROR, "socketio client stopped with error: {}", e);
|
||||
Err(TailchatError::SocketIoError(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// let socket = match ClientBuilder::new() {
|
||||
|
||||
// };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
use colored::Colorize;
|
||||
use rust_socketio::asynchronous::Client;
|
||||
use rust_socketio::{Event, Payload};
|
||||
use tracing::info;
|
||||
|
||||
/// 所有
|
||||
pub async fn any_event(event: Event, payload: Payload, _client: Client) {
|
||||
let handled = vec![
|
||||
// 真正处理过的
|
||||
"chat.message.sendMessage", // 也许以后会用到
|
||||
|
||||
// 忽略的
|
||||
];
|
||||
match &event {
|
||||
Event::Custom(event_name) => {
|
||||
if handled.contains(&event_name.as_str()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Event::Message => {
|
||||
match payload {
|
||||
Payload::Text(values) => {
|
||||
if let Some(value) = values.first() {
|
||||
if handled.contains(&value.as_str().unwrap()) {
|
||||
return;
|
||||
}
|
||||
info!("收到消息 {}", value.to_string().yellow());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
match payload {
|
||||
Payload::Binary(ref data) => {
|
||||
println!("event: {} |{:?}", event, data)
|
||||
}
|
||||
Payload::Text(ref data) => {
|
||||
print!("event: {}", event.as_str().purple());
|
||||
for value in data {
|
||||
println!("|{}", value);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn on_message(payload: Payload, client: Client) {
|
||||
match payload {
|
||||
Payload::Text(values) => {
|
||||
if let Some(value) = values.first() {
|
||||
info!("收到消息 {}", value.to_string().yellow());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user