mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2024-11-27 06:35:06 +08:00
进行一个 clicppy
This commit is contained in:
parent
f6e760e234
commit
0843826435
|
@ -61,7 +61,7 @@ impl BotConfig {
|
||||||
// try read config from file
|
// try read config from file
|
||||||
let config = fs::read_to_string(&config_file_path).expect("Failed to read config file");
|
let config = fs::read_to_string(&config_file_path).expect("Failed to read config file");
|
||||||
let ret: Self = from_str(&config)
|
let ret: Self = from_str(&config)
|
||||||
.expect(format!("Failed to parse config file {}", &config_file_path).as_str());
|
.unwrap_or_else(|_| panic!("Failed to parse config file {}", &config_file_path));
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
pub fn new_from_cli() -> Self {
|
pub fn new_from_cli() -> Self {
|
||||||
|
@ -74,7 +74,7 @@ impl BotConfig {
|
||||||
match self.enable_ica {
|
match self.enable_ica {
|
||||||
Some(enable) => {
|
Some(enable) => {
|
||||||
if enable {
|
if enable {
|
||||||
if let None = self.ica {
|
if self.ica.is_none() {
|
||||||
warn!("enable_ica 为 true 但未填写 [ica] 配置\n将不启用 ica");
|
warn!("enable_ica 为 true 但未填写 [ica] 配置\n将不启用 ica");
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,7 +85,7 @@ impl BotConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(_) = self.ica {
|
if self.ica.is_some() {
|
||||||
warn!("未填写 enable_ica 但填写了 [ica] 配置\n将不启用 ica");
|
warn!("未填写 enable_ica 但填写了 [ica] 配置\n将不启用 ica");
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -98,7 +98,7 @@ impl BotConfig {
|
||||||
match self.enable_matrix {
|
match self.enable_matrix {
|
||||||
Some(enable) => {
|
Some(enable) => {
|
||||||
if enable {
|
if enable {
|
||||||
if let None = self.matrix {
|
if self.matrix.is_none() {
|
||||||
warn!("enable_matrix 为 true 但未填写 [matrix] 配置\n将不启用 Matrix");
|
warn!("enable_matrix 为 true 但未填写 [matrix] 配置\n将不启用 Matrix");
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,7 +109,7 @@ impl BotConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if let Some(_) = self.matrix {
|
if self.matrix.is_some() {
|
||||||
warn!("未填写 enable_matrix 但填写了 [matrix] 配置\n将不启用 Matrix");
|
warn!("未填写 enable_matrix 但填写了 [matrix] 配置\n将不启用 Matrix");
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
|
|
@ -24,7 +24,7 @@ impl IcalinguaInfo {
|
||||||
let mut load = None;
|
let mut load = None;
|
||||||
let mut server_node = None;
|
let mut server_node = None;
|
||||||
let mut client_count = None;
|
let mut client_count = None;
|
||||||
let info_list = s.split("\n").collect::<Vec<&str>>();
|
let info_list = s.split('\n').collect::<Vec<&str>>();
|
||||||
for info in info_list {
|
for info in info_list {
|
||||||
if info.starts_with("icalingua-bridge-oicq") {
|
if info.starts_with("icalingua-bridge-oicq") {
|
||||||
ica_version = Some(info.split_at(22).1.to_string());
|
ica_version = Some(info.split_at(22).1.to_string());
|
||||||
|
@ -40,9 +40,9 @@ impl IcalinguaInfo {
|
||||||
server_node = Some(info.split_at(12).1.to_string());
|
server_node = Some(info.split_at(12).1.to_string());
|
||||||
} else if info.ends_with("clients connected") {
|
} else if info.ends_with("clients connected") {
|
||||||
client_count = Some(
|
client_count = Some(
|
||||||
info.split(" ")
|
info.split(' ')
|
||||||
.collect::<Vec<&str>>()
|
.collect::<Vec<&str>>()
|
||||||
.get(0)
|
.first()
|
||||||
.unwrap_or(&"1")
|
.unwrap_or(&"1")
|
||||||
.parse::<u16>()
|
.parse::<u16>()
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
|
@ -194,7 +194,7 @@ mod tests {
|
||||||
}));
|
}));
|
||||||
assert_eq!(online_data.bkn, 123);
|
assert_eq!(online_data.bkn, 123);
|
||||||
assert_eq!(online_data.nick, "test");
|
assert_eq!(online_data.nick, "test");
|
||||||
assert_eq!(online_data.online, true);
|
assert!(online_data.online);
|
||||||
assert_eq!(online_data.qqid, 123456);
|
assert_eq!(online_data.qqid, 123456);
|
||||||
assert_eq!(online_data.icalingua_info.ica_version, "2.11.1");
|
assert_eq!(online_data.icalingua_info.ica_version, "2.11.1");
|
||||||
assert_eq!(online_data.icalingua_info.os_info, "Linux c038fad79f13 4.4.302+");
|
assert_eq!(online_data.icalingua_info.os_info, "Linux c038fad79f13 4.4.302+");
|
||||||
|
@ -210,7 +210,7 @@ mod tests {
|
||||||
let online_data = OnlineData::new_from_json(&serde_json::json!({}));
|
let online_data = OnlineData::new_from_json(&serde_json::json!({}));
|
||||||
assert_eq!(online_data.bkn, -1);
|
assert_eq!(online_data.bkn, -1);
|
||||||
assert_eq!(online_data.nick, "UNKNOWN");
|
assert_eq!(online_data.nick, "UNKNOWN");
|
||||||
assert_eq!(online_data.online, false);
|
assert!(!online_data.online);
|
||||||
assert_eq!(online_data.qqid, -1);
|
assert_eq!(online_data.qqid, -1);
|
||||||
assert_eq!(online_data.icalingua_info.ica_version, "UNKNOWN");
|
assert_eq!(online_data.icalingua_info.ica_version, "UNKNOWN");
|
||||||
assert_eq!(online_data.icalingua_info.os_info, "UNKNOWN");
|
assert_eq!(online_data.icalingua_info.os_info, "UNKNOWN");
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub async fn start_ica(config: &IcaConfig, stop_reciver: tokio::sync::oneshot::R
|
||||||
for room in config.notice_room.iter() {
|
for room in config.notice_room.iter() {
|
||||||
let startup_msg = crate::data_struct::ica::messages::SendMessage::new(
|
let startup_msg = crate::data_struct::ica::messages::SendMessage::new(
|
||||||
format!("ica-async-rs bot v{}", crate::VERSION),
|
format!("ica-async-rs bot v{}", crate::VERSION),
|
||||||
room.clone(),
|
*room,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||||
|
|
|
@ -56,6 +56,10 @@ pub struct BotStatus {
|
||||||
pub config: Option<BotConfig>,
|
pub config: Option<BotConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for BotStatus {
|
||||||
|
fn default() -> Self { Self::new() }
|
||||||
|
}
|
||||||
|
|
||||||
impl BotStatus {
|
impl BotStatus {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -139,7 +143,7 @@ pub async fn sign_callback(payload: Payload, client: Client) {
|
||||||
|
|
||||||
let (auth_key, version) = (&require_data[0], &require_data[1]);
|
let (auth_key, version) = (&require_data[0], &require_data[1]);
|
||||||
debug!("auth_key: {:?}, version: {:?}", auth_key, version);
|
debug!("auth_key: {:?}, version: {:?}", auth_key, version);
|
||||||
let auth_key = match &require_data.get(0) {
|
let auth_key = match &require_data.first() {
|
||||||
Some(Value::String(auth_key)) => Some(auth_key),
|
Some(Value::String(auth_key)) => Some(auth_key),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ pub async fn delete_message(payload: Payload, client: Client) {
|
||||||
// 消息 id
|
// 消息 id
|
||||||
if let Some(value) = values.first() {
|
if let Some(value) = values.first() {
|
||||||
if let Some(msg_id) = value.as_str() {
|
if let Some(msg_id) = value.as_str() {
|
||||||
info!("delete_message {}", format!("{}", msg_id).yellow());
|
info!("delete_message {}", msg_id.to_string().yellow());
|
||||||
|
|
||||||
py::call::delete_message_py(msg_id.to_string(), &client).await;
|
py::call::delete_message_py(msg_id.to_string(), &client).await;
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,7 @@ pub async fn update_all_room(payload: Payload, _client: Client) {
|
||||||
if let Payload::Text(values) = payload {
|
if let Payload::Text(values) = payload {
|
||||||
if let Some(value) = values.first() {
|
if let Some(value) = values.first() {
|
||||||
if let Some(raw_rooms) = value.as_array() {
|
if let Some(raw_rooms) = value.as_array() {
|
||||||
let rooms: Vec<Room> =
|
let rooms: Vec<Room> = raw_rooms.iter().map(Room::new_from_json).collect();
|
||||||
raw_rooms.iter().map(|room| Room::new_from_json(room)).collect();
|
|
||||||
BotStatus::update_rooms(rooms.clone());
|
BotStatus::update_rooms(rooms.clone());
|
||||||
info!("update_all_room {}", rooms.len());
|
info!("update_all_room {}", rooms.len());
|
||||||
}
|
}
|
||||||
|
@ -151,7 +150,7 @@ pub async fn any_event(event: Event, payload: Payload, _client: Client) {
|
||||||
Payload::Text(ref data) => {
|
Payload::Text(ref data) => {
|
||||||
print!("event: {}", event.as_str().purple());
|
print!("event: {}", event.as_str().purple());
|
||||||
for value in data {
|
for value in data {
|
||||||
println!("|{}", value.to_string());
|
println!("|{}", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod ica;
|
||||||
mod matrix;
|
mod matrix;
|
||||||
mod py;
|
mod py;
|
||||||
|
|
||||||
use config::{BotConfig, IcaConfig};
|
use config::BotConfig;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
|
|
|
@ -46,19 +46,17 @@ pub fn get_func<'py>(py_module: &'py PyAny, path: &PathBuf, name: &'py str) -> O
|
||||||
pub fn verify_plugins() {
|
pub fn verify_plugins() {
|
||||||
let mut need_reload_files: Vec<PathBuf> = Vec::new();
|
let mut need_reload_files: Vec<PathBuf> = Vec::new();
|
||||||
let plugin_path = BotStatus::get_config().py_plugin_path.as_ref();
|
let plugin_path = BotStatus::get_config().py_plugin_path.as_ref();
|
||||||
if let None = plugin_path {
|
if plugin_path.is_none() {
|
||||||
warn!("未配置 Python 插件路径");
|
warn!("未配置 Python 插件路径");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let plugin_path = plugin_path.unwrap();
|
let plugin_path = plugin_path.unwrap();
|
||||||
for entry in std::fs::read_dir(&plugin_path).unwrap() {
|
for entry in std::fs::read_dir(plugin_path).unwrap() {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if let Some(ext) = path.extension() {
|
if let Some(ext) = path.extension() {
|
||||||
if ext == "py" {
|
if ext == "py" && !PyStatus::verify_file(&path) {
|
||||||
if !PyStatus::verify_file(&path) {
|
need_reload_files.push(path);
|
||||||
need_reload_files.push(path);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +92,7 @@ pub async fn new_message_py(message: &NewMessage, client: &Client) {
|
||||||
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
if let Some(py_func) = get_func(plugin.py_module.as_ref(py), &path, "on_message") {
|
if let Some(py_func) = get_func(plugin.py_module.as_ref(py), path, "on_message") {
|
||||||
if let Err(e) = py_func.call1(args) {
|
if let Err(e) = py_func.call1(args) {
|
||||||
warn!("failed to call function<on_message>: {:?}", e);
|
warn!("failed to call function<on_message>: {:?}", e);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +113,7 @@ pub async fn delete_message_py(msg_id: MessageId, client: &Client) {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
if let Some(py_func) =
|
if let Some(py_func) =
|
||||||
get_func(plugin.py_module.as_ref(py), &path, "on_delete_message")
|
get_func(plugin.py_module.as_ref(py), path, "on_delete_message")
|
||||||
{
|
{
|
||||||
if let Err(e) = py_func.call1(args) {
|
if let Err(e) = py_func.call1(args) {
|
||||||
warn!("failed to call function<on_delete_message>: {:?}", e);
|
warn!("failed to call function<on_delete_message>: {:?}", e);
|
||||||
|
|
|
@ -53,6 +53,10 @@ impl IcaStatusPy {
|
||||||
pub fn get_load(&self) -> String { BotStatus::get_online_data().icalingua_info.load.clone() }
|
pub fn get_load(&self) -> String { BotStatus::get_online_data().icalingua_info.load.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for IcaStatusPy {
|
||||||
|
fn default() -> Self { Self::new() }
|
||||||
|
}
|
||||||
|
|
||||||
impl IcaStatusPy {
|
impl IcaStatusPy {
|
||||||
pub fn new() -> Self { Self {} }
|
pub fn new() -> Self { Self {} }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use pyo3::prelude::*;
|
||||||
use pyo3::types::PyTuple;
|
use pyo3::types::PyTuple;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::config::{BotConfig, IcaConfig};
|
use crate::config::BotConfig;
|
||||||
use crate::ica::client::BotStatus;
|
use crate::ica::client::BotStatus;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -28,7 +28,7 @@ pub struct PyPlugin {
|
||||||
|
|
||||||
impl PyPlugin {
|
impl PyPlugin {
|
||||||
pub fn new_from_path(path: &PathBuf) -> Option<Self> {
|
pub fn new_from_path(path: &PathBuf) -> Option<Self> {
|
||||||
let raw_file = load_py_file(&path);
|
let raw_file = load_py_file(path);
|
||||||
match raw_file {
|
match raw_file {
|
||||||
Ok(raw_file) => match Self::try_from(raw_file) {
|
Ok(raw_file) => match Self::try_from(raw_file) {
|
||||||
Ok(plugin) => Some(plugin),
|
Ok(plugin) => Some(plugin),
|
||||||
|
@ -122,9 +122,9 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
|
||||||
"加载 Python 插件 {:?} 的配置文件信息时失败:返回的不是 [str, str]",
|
"加载 Python 插件 {:?} 的配置文件信息时失败:返回的不是 [str, str]",
|
||||||
path
|
path
|
||||||
);
|
);
|
||||||
Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(format!(
|
Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>(
|
||||||
"返回的不是 [str, str]"
|
"返回的不是 [str, str]".to_string(),
|
||||||
)))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -186,7 +186,7 @@ impl PyStatus {
|
||||||
|
|
||||||
pub static mut PYSTATUS: PyStatus = PyStatus { files: None };
|
pub static mut PYSTATUS: PyStatus = PyStatus { files: None };
|
||||||
|
|
||||||
pub fn load_py_plugins(path: &PathBuf) -> () {
|
pub fn load_py_plugins(path: &PathBuf) {
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
info!("finding plugins in: {:?}", path);
|
info!("finding plugins in: {:?}", path);
|
||||||
// 搜索所有的 py 文件 和 文件夹单层下面的 py 文件
|
// 搜索所有的 py 文件 和 文件夹单层下面的 py 文件
|
||||||
|
@ -226,7 +226,7 @@ pub fn py_module_from_code(content: &str, path: &PathBuf) -> PyResult<Py<PyAny>>
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
||||||
let module: PyResult<Py<PyAny>> = PyModule::from_code(
|
let module: PyResult<Py<PyAny>> = PyModule::from_code(
|
||||||
py,
|
py,
|
||||||
&content,
|
content,
|
||||||
&path.to_string_lossy(),
|
&path.to_string_lossy(),
|
||||||
&path.file_name().unwrap().to_string_lossy(),
|
&path.file_name().unwrap().to_string_lossy(),
|
||||||
// !!!! 请注意, 一定要给他一个名字, cpython 会自动把后面的重名模块覆盖掉前面的
|
// !!!! 请注意, 一定要给他一个名字, cpython 会自动把后面的重名模块覆盖掉前面的
|
||||||
|
@ -239,7 +239,7 @@ pub fn py_module_from_code(content: &str, path: &PathBuf) -> PyResult<Py<PyAny>>
|
||||||
/// 传入文件路径
|
/// 传入文件路径
|
||||||
/// 返回 hash 和 文件内容
|
/// 返回 hash 和 文件内容
|
||||||
pub fn load_py_file(path: &PathBuf) -> std::io::Result<RawPyPlugin> {
|
pub fn load_py_file(path: &PathBuf) -> std::io::Result<RawPyPlugin> {
|
||||||
let changed_time = get_change_time(&path);
|
let changed_time = get_change_time(path);
|
||||||
let content = std::fs::read_to_string(path)?;
|
let content = std::fs::read_to_string(path)?;
|
||||||
Ok((path.clone(), changed_time, content))
|
Ok((path.clone(), changed_time, content))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user