mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-20 15:39:53 +08:00
Compare commits
No commits in common. "6dfbc4e87992861bda2ffa73abafd9b9d5a7eb4a" and "aa20b7f1c343c0ffd60bb2160a48b319e1100f8d" have entirely different histories.
6dfbc4e879
...
aa20b7f1c3
1164
Cargo.lock
generated
1164
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
@ -1,39 +1,38 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ica-rs"
|
name = "ica-rs"
|
||||||
version = "0.6.0-dev"
|
version = "0.5.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ica", "tailchat"]
|
default = ["ica", "matrix"]
|
||||||
ica = ["dep:ed25519", "dep:ed25519-dalek", "dep:hex", "dep:rust_socketio"]
|
ica = ["dep:ed25519", "dep:ed25519-dalek", "dep:hex", "dep:rust_socketio"]
|
||||||
tailchat = ["dep:rust_socketio", "dep:md-5"]
|
matrix = ["dep:matrix-sdk", "dep:url"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
# matrix
|
||||||
|
url = { version = "2.5.0", optional = true }
|
||||||
|
matrix-sdk = { version = "0.7.1", optional = true, default-features = false, features = ["rustls-tls"] }
|
||||||
|
|
||||||
# ica
|
# ica
|
||||||
ed25519 = { version = "2.2", optional = true }
|
ed25519 = { version = "2.2.3", optional = true }
|
||||||
ed25519-dalek = { version = "2.1", optional = true }
|
ed25519-dalek = { version = "2.1.1", optional = true }
|
||||||
hex = { version = "0.4", optional = true }
|
hex = { version = "0.4.3", optional = true }
|
||||||
|
|
||||||
# tailchat
|
|
||||||
md-5 = { version = "0.10.6", optional = true }
|
|
||||||
|
|
||||||
# ica & tailchat (socketio)
|
|
||||||
rust_socketio = { version = "0.4.4", features = ["async"], optional = true }
|
rust_socketio = { version = "0.4.4", features = ["async"], optional = true }
|
||||||
|
|
||||||
# data
|
# data
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
chrono = "0.4.37"
|
chrono = "0.4.35"
|
||||||
toml = "0.8.12"
|
toml = "0.8.11"
|
||||||
colored = "2.1.0"
|
colored = "2.1.0"
|
||||||
|
|
||||||
# runtime
|
# runtime
|
||||||
tokio = { version = "1.37", features = ["full"] }
|
tokio = { version = "1.36", features = ["full"] }
|
||||||
futures-util = "0.3.30"
|
futures-util = "0.3.30"
|
||||||
pyo3 = { version = "0.21.0", features = ["experimental-async"] }
|
pyo3 = "0.20.3"
|
||||||
anyhow = { version = "1.0.81", features = ["backtrace"] }
|
anyhow = { version = "1.0.81", features = ["backtrace"] }
|
||||||
# async 这玩意以后在搞
|
# async 这玩意以后在搞
|
||||||
# pyo3-async = "0.3.2"
|
# pyo3-async = "0.3.2"
|
||||||
|
|
|
@ -139,6 +139,9 @@ class IcaClient:
|
||||||
@property
|
@property
|
||||||
def ica_version() -> str:
|
def ica_version() -> str:
|
||||||
"""shenbot ica 的版本号"""
|
"""shenbot ica 的版本号"""
|
||||||
|
@property
|
||||||
|
def matrix_version() -> str:
|
||||||
|
"""shenbot matrix 的版本号"""
|
||||||
|
|
||||||
def debug(self, message: str) -> None:
|
def debug(self, message: str) -> None:
|
||||||
"""向日志中输出调试信息"""
|
"""向日志中输出调试信息"""
|
||||||
|
|
|
@ -24,6 +24,20 @@ pub struct IcaConfig {
|
||||||
pub filter_list: Vec<i64>,
|
pub filter_list: Vec<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Matrix 配置
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct MatrixConfig {
|
||||||
|
/// home server
|
||||||
|
pub home_server: String,
|
||||||
|
/// bot_id
|
||||||
|
pub bot_id: String,
|
||||||
|
/// bot password
|
||||||
|
pub bot_password: String,
|
||||||
|
/// 提醒的房间
|
||||||
|
pub notice_room: Vec<String>,
|
||||||
|
/// 是否提醒
|
||||||
|
pub notice_start: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct PyConfig {
|
pub struct PyConfig {
|
||||||
|
@ -40,7 +54,10 @@ pub struct BotConfig {
|
||||||
pub enable_ica: Option<bool>,
|
pub enable_ica: Option<bool>,
|
||||||
/// Ica 配置
|
/// Ica 配置
|
||||||
pub ica: Option<IcaConfig>,
|
pub ica: Option<IcaConfig>,
|
||||||
|
/// 是否启用 Matrix
|
||||||
|
pub enable_matrix: Option<bool>,
|
||||||
|
/// Matrix 配置
|
||||||
|
pub matrix: Option<MatrixConfig>,
|
||||||
/// 是否启用 Python 插件
|
/// 是否启用 Python 插件
|
||||||
pub enable_py: Option<bool>,
|
pub enable_py: Option<bool>,
|
||||||
/// Python 插件配置
|
/// Python 插件配置
|
||||||
|
@ -89,6 +106,26 @@ impl BotConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 检查是否启用 Matrix
|
||||||
|
pub fn check_matrix(&self) -> bool {
|
||||||
|
match self.enable_matrix {
|
||||||
|
Some(enable) => {
|
||||||
|
if enable && self.matrix.is_none() {
|
||||||
|
warn!("enable_matrix 为 true 但未填写 [matrix] 配置\n将不启用 Matrix");
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if self.matrix.is_some() {
|
||||||
|
warn!("未填写 enable_matrix 但填写了 [matrix] 配置\n将不启用 Matrix");
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 检查是否启用 Python 插件
|
/// 检查是否启用 Python 插件
|
||||||
pub fn check_py(&self) -> bool {
|
pub fn check_py(&self) -> bool {
|
||||||
match self.enable_py {
|
match self.enable_py {
|
||||||
|
@ -110,5 +147,6 @@ impl BotConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ica(&self) -> IcaConfig { self.ica.clone().expect("No ica config found") }
|
pub fn ica(&self) -> IcaConfig { self.ica.clone().expect("No ica config found") }
|
||||||
|
pub fn matrix(&self) -> MatrixConfig { self.matrix.clone().expect("No matrix config found") }
|
||||||
pub fn py(&self) -> PyConfig { self.py.clone().expect("No py config found") }
|
pub fn py(&self) -> PyConfig { self.py.clone().expect("No py config found") }
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ pub type RoomId = i64;
|
||||||
pub type UserId = i64;
|
pub type UserId = i64;
|
||||||
pub type MessageId = String;
|
pub type MessageId = String;
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub trait RoomIdTrait {
|
pub trait RoomIdTrait {
|
||||||
fn is_room(&self) -> bool;
|
fn is_room(&self) -> bool;
|
||||||
fn is_chat(&self) -> bool { !self.is_room() }
|
fn is_chat(&self) -> bool { !self.is_room() }
|
||||||
|
|
|
@ -31,7 +31,6 @@ impl<'de> Deserialize<'de> for At {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub trait MessageTrait {
|
pub trait MessageTrait {
|
||||||
fn is_reply(&self) -> bool;
|
fn is_reply(&self) -> bool;
|
||||||
fn is_from_self(&self) -> bool {
|
fn is_from_self(&self) -> bool {
|
||||||
|
|
|
@ -6,10 +6,24 @@ pub enum IcaError {
|
||||||
SocketIoError(rust_socketio::error::Error),
|
SocketIoError(rust_socketio::error::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum MatrixError {
|
||||||
|
/// Homeserver Url 错误
|
||||||
|
HomeserverUrlError(url::ParseError),
|
||||||
|
/// Http 请求错误
|
||||||
|
HttpError(matrix_sdk::HttpError),
|
||||||
|
/// Matrix Error
|
||||||
|
MatrixError(matrix_sdk::Error),
|
||||||
|
}
|
||||||
|
|
||||||
impl From<rust_socketio::Error> for IcaError {
|
impl From<rust_socketio::Error> for IcaError {
|
||||||
fn from(e: rust_socketio::Error) -> Self { IcaError::SocketIoError(e) }
|
fn from(e: rust_socketio::Error) -> Self { IcaError::SocketIoError(e) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<matrix_sdk::Error> for MatrixError {
|
||||||
|
fn from(e: matrix_sdk::Error) -> Self { MatrixError::MatrixError(e) }
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for IcaError {
|
impl std::fmt::Display for IcaError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
@ -25,3 +39,23 @@ impl std::error::Error for IcaError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for MatrixError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
MatrixError::HomeserverUrlError(e) => write!(f, "Homeserver Url 错误: {}", e),
|
||||||
|
MatrixError::HttpError(e) => write!(f, "Http 请求错误: {}", e),
|
||||||
|
MatrixError::MatrixError(e) => write!(f, "Matrix Error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for MatrixError {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
MatrixError::HomeserverUrlError(e) => Some(e),
|
||||||
|
MatrixError::HttpError(e) => Some(e),
|
||||||
|
MatrixError::MatrixError(e) => Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::data_struct::ica::all_rooms::Room;
|
||||||
use crate::data_struct::ica::messages::{Message, MessageTrait, NewMessage};
|
use crate::data_struct::ica::messages::{Message, MessageTrait, NewMessage};
|
||||||
use crate::data_struct::ica::online_data::OnlineData;
|
use crate::data_struct::ica::online_data::OnlineData;
|
||||||
use crate::ica::client::send_message;
|
use crate::ica::client::send_message;
|
||||||
use crate::{py, MainStatus, ICA_VERSION, VERSION};
|
use crate::{py, MainStatus, ICA_VERSION, MATRIX_VERSION, VERSION};
|
||||||
|
|
||||||
/// 获取在线数据
|
/// 获取在线数据
|
||||||
pub async fn get_online_data(payload: Payload, _client: Client) {
|
pub async fn get_online_data(payload: Payload, _client: Client) {
|
||||||
|
@ -35,8 +35,8 @@ pub async fn add_message(payload: Payload, client: Client) {
|
||||||
// 之后的处理交给插件
|
// 之后的处理交给插件
|
||||||
if message.content().eq("/bot-rs") && !message.is_from_self() && !message.is_reply() {
|
if message.content().eq("/bot-rs") && !message.is_from_self() && !message.is_reply() {
|
||||||
let reply = message.reply_with(&format!(
|
let reply = message.reply_with(&format!(
|
||||||
"shenbot v{}\nica-async-rs pong v{}",
|
"shenbot v{}\nica-async-rs pong v{}\nmatrix v{}",
|
||||||
VERSION, ICA_VERSION
|
VERSION, ICA_VERSION, MATRIX_VERSION
|
||||||
));
|
));
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ pub async fn connect_callback(payload: Payload, _client: Client) {
|
||||||
event!(Level::INFO, "{}", "需要登录到 icalingua!".yellow())
|
event!(Level::INFO, "{}", "需要登录到 icalingua!".yellow())
|
||||||
}
|
}
|
||||||
Some(msg) => {
|
Some(msg) => {
|
||||||
event!(Level::INFO, "{}{}", "未知消息".yellow(), msg);
|
event!(Level::INFO, "{}", "未知消息".yellow());
|
||||||
}
|
}
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ mod data_struct;
|
||||||
mod error;
|
mod error;
|
||||||
#[cfg(feature = "ica")]
|
#[cfg(feature = "ica")]
|
||||||
mod ica;
|
mod ica;
|
||||||
// #[cfg(feature = "tailchat")]
|
#[cfg(feature = "matrix")]
|
||||||
// mod tailchat;
|
mod matrix;
|
||||||
mod py;
|
mod py;
|
||||||
mod status;
|
mod status;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ use tracing::{event, info, span, Level};
|
||||||
pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus {
|
pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus {
|
||||||
config: None,
|
config: None,
|
||||||
ica_status: None,
|
ica_status: None,
|
||||||
|
matrix_status: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type MainStatus = status::BotStatus;
|
pub type MainStatus = status::BotStatus;
|
||||||
|
@ -24,7 +25,7 @@ pub type StopGetter = tokio::sync::oneshot::Receiver<()>;
|
||||||
|
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
pub const ICA_VERSION: &str = "1.4.0";
|
pub const ICA_VERSION: &str = "1.4.0";
|
||||||
pub const TAILCHAT_VERSION: &str = "0.1.0";
|
pub const MATRIX_VERSION: &str = "0.1.0";
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! wrap_callback {
|
macro_rules! wrap_callback {
|
||||||
|
@ -79,6 +80,19 @@ async fn main() {
|
||||||
event!(Level::INFO, "未启用 ica");
|
event!(Level::INFO, "未启用 ica");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event!(Level::INFO, "启动 Matrix");
|
||||||
|
let (matrix_send, matrix_recv) = tokio::sync::oneshot::channel::<()>();
|
||||||
|
|
||||||
|
if bot_config.check_matrix() {
|
||||||
|
event!(Level::INFO, "启动 Matrix");
|
||||||
|
let config = bot_config.matrix();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
matrix::start_matrix(&config, matrix_recv).await.unwrap();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
event!(Level::INFO, "未启用 Matrix");
|
||||||
|
}
|
||||||
|
|
||||||
tokio::time::sleep(Duration::from_secs(2)).await;
|
tokio::time::sleep(Duration::from_secs(2)).await;
|
||||||
// 等待一个输入
|
// 等待一个输入
|
||||||
info!("Press any key to exit");
|
info!("Press any key to exit");
|
||||||
|
@ -86,6 +100,7 @@ async fn main() {
|
||||||
std::io::stdin().read_line(&mut input).unwrap();
|
std::io::stdin().read_line(&mut input).unwrap();
|
||||||
|
|
||||||
ica_send.send(()).ok();
|
ica_send.send(()).ok();
|
||||||
|
matrix_send.send(()).ok();
|
||||||
|
|
||||||
info!("Disconnected");
|
info!("Disconnected");
|
||||||
}
|
}
|
||||||
|
|
140
ica-rs/src/matrix.rs
Normal file
140
ica-rs/src/matrix.rs
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
pub mod events;
|
||||||
|
|
||||||
|
use std::{str::FromStr, time::Duration};
|
||||||
|
|
||||||
|
use futures_util::StreamExt;
|
||||||
|
use matrix_sdk::{
|
||||||
|
config::SyncSettings,
|
||||||
|
ruma::{
|
||||||
|
api::client::message::send_message_event, events::room::message::RoomMessageEventContent,
|
||||||
|
OwnedRoomId, TransactionId,
|
||||||
|
},
|
||||||
|
Client,
|
||||||
|
};
|
||||||
|
use tracing::{event, span, Level};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::config::MatrixConfig;
|
||||||
|
use crate::error::{ClientResult, MatrixError};
|
||||||
|
use crate::StopGetter;
|
||||||
|
|
||||||
|
pub async fn start_matrix(
|
||||||
|
config: &MatrixConfig,
|
||||||
|
mut stop_reciver: StopGetter,
|
||||||
|
) -> ClientResult<(), MatrixError> {
|
||||||
|
let span = span!(Level::INFO, "Matrix Client");
|
||||||
|
let _enter = span.enter();
|
||||||
|
|
||||||
|
let homeserver_url = match Url::parse(&config.home_server) {
|
||||||
|
Ok(url) => url,
|
||||||
|
Err(e) => {
|
||||||
|
event!(Level::ERROR, "Homeserver Url 错误: {}", e);
|
||||||
|
return Err(MatrixError::HomeserverUrlError(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let password = &config.bot_password;
|
||||||
|
let username = &config.bot_id;
|
||||||
|
|
||||||
|
let client = match Client::new(homeserver_url).await {
|
||||||
|
Ok(client) => {
|
||||||
|
event!(Level::INFO, "Logged in as {}", username);
|
||||||
|
client
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
event!(Level::ERROR, "Failed to log in as {}: {}", username, error);
|
||||||
|
return Err(MatrixError::HttpError(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let display_name = format!("shenbot-matrix v{}", crate::MATRIX_VERSION);
|
||||||
|
|
||||||
|
match client
|
||||||
|
.matrix_auth()
|
||||||
|
.login_username(&username, &password)
|
||||||
|
.initial_device_display_name(&display_name)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {
|
||||||
|
event!(Level::INFO, "Logged in as {}", username);
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
event!(Level::ERROR, "Failed to log in as {}: {}", username, error);
|
||||||
|
return Err(MatrixError::MatrixError(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送启动消息
|
||||||
|
if config.notice_start {
|
||||||
|
for room in config.notice_room.iter() {
|
||||||
|
let startup_msg = RoomMessageEventContent::text_plain(format!(
|
||||||
|
"shenbot v {}\nmatrix-rs v{} started!",
|
||||||
|
crate::VERSION,
|
||||||
|
crate::MATRIX_VERSION
|
||||||
|
));
|
||||||
|
let startup_req: send_message_event::v3::Request =
|
||||||
|
send_message_event::v3::Request::new(
|
||||||
|
OwnedRoomId::from_str(&room).unwrap(),
|
||||||
|
TransactionId::new(),
|
||||||
|
&startup_msg,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
event!(Level::INFO, "发送启动消息到房间: {}", room);
|
||||||
|
|
||||||
|
if let Err(e) = client.send::<send_message_event::v3::Request>(startup_req, None).await
|
||||||
|
{
|
||||||
|
event!(Level::INFO, "启动信息发送失败 房间:{}|e:{}", room, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event!(Level::INFO, "未启用启动消息");
|
||||||
|
}
|
||||||
|
|
||||||
|
client.add_event_handler(events::on_room_message);
|
||||||
|
|
||||||
|
let init_sync_setting = SyncSettings::new().timeout(Duration::from_mins(10));
|
||||||
|
|
||||||
|
match client.sync_once(init_sync_setting).await {
|
||||||
|
Ok(_) => {
|
||||||
|
event!(Level::INFO, "Synced");
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
event!(Level::ERROR, "Failed to sync: {}", error);
|
||||||
|
return Err(MatrixError::MatrixError(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stream_sync =
|
||||||
|
Box::pin(client.sync_stream(SyncSettings::new().timeout(Duration::from_mins(10))).await);
|
||||||
|
|
||||||
|
while let Some(Ok(response)) = stream_sync.next().await {
|
||||||
|
for room in response.rooms.join.values() {
|
||||||
|
for e in &room.timeline.events {
|
||||||
|
if let Ok(event) = e.event.deserialize() {
|
||||||
|
println!("Received event {:?}", event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if stop_reciver.try_recv().is_ok() {
|
||||||
|
event!(Level::INFO, "Matrix client stopping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// loop {
|
||||||
|
// match stop_reciver.try_recv() {
|
||||||
|
// Ok(_) => {
|
||||||
|
// event!(Level::INFO, "Matrix client stopping");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// Err(tokio::sync::oneshot::error::TryRecvError::Empty) => {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// Err(tokio::sync::oneshot::error::TryRecvError::Closed) => {
|
||||||
|
// event!(Level::INFO, "Matrix client stopping");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
42
ica-rs/src/matrix/events.rs
Normal file
42
ica-rs/src/matrix/events.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
use matrix_sdk::{
|
||||||
|
ruma::events::room::message::{
|
||||||
|
AddMentions, ForwardThread, MessageType, OriginalSyncRoomMessageEvent,
|
||||||
|
RoomMessageEventContent,
|
||||||
|
},
|
||||||
|
Room, RoomState,
|
||||||
|
};
|
||||||
|
use tracing::{event, span, Level};
|
||||||
|
|
||||||
|
use crate::py::call::matrix_new_message_py;
|
||||||
|
|
||||||
|
pub async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
|
||||||
|
// We only want to listen to joined rooms.
|
||||||
|
if room.state() != RoomState::Joined {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only want to log text messages.
|
||||||
|
let MessageType::Text(msgtype) = &event.content.msgtype else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 匹配消息
|
||||||
|
|
||||||
|
// /bot
|
||||||
|
if msgtype.body == "/bot" {
|
||||||
|
let pong = format!("shenbot v {}\nmatrix-rs v{}", crate::VERSION, crate::MATRIX_VERSION);
|
||||||
|
|
||||||
|
let reply = RoomMessageEventContent::text_plain(pong);
|
||||||
|
let reply = reply.make_reply_to(
|
||||||
|
&event.into_full_event(room.room_id().to_owned()),
|
||||||
|
ForwardThread::Yes,
|
||||||
|
AddMentions::No,
|
||||||
|
);
|
||||||
|
|
||||||
|
room.send(reply).await.expect("Failed to send message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发给 Python 处理剩下的
|
||||||
|
matrix_new_message_py().await;
|
||||||
|
}
|
|
@ -76,7 +76,7 @@ pub fn verify_plugins() {
|
||||||
pub const ICA_NEW_MESSAGE_FUNC: &str = "on_ica_message";
|
pub const ICA_NEW_MESSAGE_FUNC: &str = "on_ica_message";
|
||||||
pub const ICA_DELETE_MESSAGE_FUNC: &str = "on_ica_delete_message";
|
pub const ICA_DELETE_MESSAGE_FUNC: &str = "on_ica_delete_message";
|
||||||
|
|
||||||
pub const TAILCHAT_NEW_MESSAGE_FUNC: &str = "on_tailchat_message";
|
pub const MATRIX_NEW_MESSAGE_FUNC: &str = "on_matrix_message";
|
||||||
|
|
||||||
/// 执行 new message 的 python 插件
|
/// 执行 new message 的 python 插件
|
||||||
pub async fn ica_new_message_py(message: &NewMessage, client: &Client) {
|
pub async fn ica_new_message_py(message: &NewMessage, client: &Client) {
|
||||||
|
@ -124,3 +124,22 @@ pub async fn ica_delete_message_py(msg_id: MessageId, client: &Client) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn matrix_new_message_py() {
|
||||||
|
verify_plugins();
|
||||||
|
|
||||||
|
let plugins = PyStatus::get_files();
|
||||||
|
for (path, plugin) in plugins.iter() {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
if let Some(py_func) =
|
||||||
|
get_func(plugin.py_module.as_ref(py), path, MATRIX_NEW_MESSAGE_FUNC)
|
||||||
|
{
|
||||||
|
if let Err(e) = py_func.call0() {
|
||||||
|
warn!("failed to call function<{}>: {:?}", MATRIX_NEW_MESSAGE_FUNC, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
pub mod ica;
|
pub mod ica;
|
||||||
|
pub mod matrix;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use toml::Value as TomlValue;
|
use toml::Value as TomlValue;
|
||||||
|
|
|
@ -214,6 +214,8 @@ impl IcaClientPy {
|
||||||
pub fn get_version(&self) -> String { crate::VERSION.to_string() }
|
pub fn get_version(&self) -> String { crate::VERSION.to_string() }
|
||||||
#[getter]
|
#[getter]
|
||||||
pub fn get_ica_version(&self) -> String { crate::ICA_VERSION.to_string() }
|
pub fn get_ica_version(&self) -> String { crate::ICA_VERSION.to_string() }
|
||||||
|
#[getter]
|
||||||
|
pub fn get_matrix_version(&self) -> String { crate::MATRIX_VERSION.to_string() }
|
||||||
|
|
||||||
pub fn debug(&self, content: String) {
|
pub fn debug(&self, content: String) {
|
||||||
debug!("{}", content);
|
debug!("{}", content);
|
||||||
|
|
1
ica-rs/src/py/class/matrix.rs
Normal file
1
ica-rs/src/py/class/matrix.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::MAIN_STATUS;
|
||||||
pub struct BotStatus {
|
pub struct BotStatus {
|
||||||
pub config: Option<BotConfig>,
|
pub config: Option<BotConfig>,
|
||||||
pub ica_status: Option<ica::MainStatus>,
|
pub ica_status: Option<ica::MainStatus>,
|
||||||
|
pub matrix_status: Option<matrix::MainStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BotStatus {
|
impl BotStatus {
|
||||||
|
@ -18,6 +19,11 @@ impl BotStatus {
|
||||||
MAIN_STATUS.ica_status = Some(status);
|
MAIN_STATUS.ica_status = Some(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn update_matrix_status(status: matrix::MainStatus) {
|
||||||
|
unsafe {
|
||||||
|
MAIN_STATUS.matrix_status = Some(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn static_init(config: BotConfig) {
|
pub fn static_init(config: BotConfig) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -28,6 +34,9 @@ impl BotStatus {
|
||||||
rooms: Vec::new(),
|
rooms: Vec::new(),
|
||||||
online_status: ica::OnlineData::default(),
|
online_status: ica::OnlineData::default(),
|
||||||
});
|
});
|
||||||
|
MAIN_STATUS.matrix_status = Some(matrix::MainStatus {
|
||||||
|
enable: config.check_matrix(),
|
||||||
|
});
|
||||||
MAIN_STATUS.config = Some(config);
|
MAIN_STATUS.config = Some(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,10 +45,16 @@ impl BotStatus {
|
||||||
pub fn global_ica_status() -> &'static ica::MainStatus {
|
pub fn global_ica_status() -> &'static ica::MainStatus {
|
||||||
unsafe { MAIN_STATUS.ica_status.as_ref().unwrap() }
|
unsafe { MAIN_STATUS.ica_status.as_ref().unwrap() }
|
||||||
}
|
}
|
||||||
|
pub fn global_matrix_status() -> &'static matrix::MainStatus {
|
||||||
|
unsafe { MAIN_STATUS.matrix_status.as_ref().unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn global_ica_status_mut() -> &'static mut ica::MainStatus {
|
pub fn global_ica_status_mut() -> &'static mut ica::MainStatus {
|
||||||
unsafe { MAIN_STATUS.ica_status.as_mut().unwrap() }
|
unsafe { MAIN_STATUS.ica_status.as_mut().unwrap() }
|
||||||
}
|
}
|
||||||
|
pub fn global_matrix_status_mut() -> &'static mut matrix::MainStatus {
|
||||||
|
unsafe { MAIN_STATUS.matrix_status.as_mut().unwrap() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod ica {
|
pub mod ica {
|
||||||
|
@ -65,3 +80,12 @@ pub mod ica {
|
||||||
pub fn update_online_status(&mut self, status: OnlineData) { self.online_status = status; }
|
pub fn update_online_status(&mut self, status: OnlineData) { self.online_status = status; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod matrix {
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MainStatus {
|
||||||
|
/// 是否启用 matrix
|
||||||
|
pub enable: bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user