mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-20 10:29:55 +08:00
Compare commits
10 Commits
4b1ed03b9a
...
18df7d1a89
Author | SHA1 | Date | |
---|---|---|---|
18df7d1a89 | |||
127f0f0ab4 | |||
e2e5142688 | |||
3b67d58ae2 | |||
d8e40bfb4d | |||
047cc110a4 | |||
2f00a3f29a | |||
0ee8091e0d | |||
13995d2915 | |||
17f3a36540 |
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -659,7 +659,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ica-rs"
|
name = "ica-rs"
|
||||||
version = "0.6.8"
|
version = "0.6.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
|
BIN
SMILEYSANS-OBLIQUE.TTF
Normal file
BIN
SMILEYSANS-OBLIQUE.TTF
Normal file
Binary file not shown.
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ica-rs"
|
name = "ica-rs"
|
||||||
version = "0.6.8"
|
version = "0.6.9"
|
||||||
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
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Python 兼容版本 3.8+
|
# Python 兼容版本 3.8+
|
||||||
|
|
||||||
from typing import Callable, Tuple, NewType, TYPE_CHECKING, TypeVar, Optional, Union
|
from typing import Callable, Tuple, NewType, Optional, Union
|
||||||
|
|
||||||
"""
|
"""
|
||||||
ica.rs
|
ica.rs
|
||||||
|
@ -236,13 +236,12 @@ class TailchatSendingMessage:
|
||||||
"""
|
"""
|
||||||
self.content = content
|
self.content = content
|
||||||
return self
|
return self
|
||||||
# def set_img(self, file: bytes, file_type: str, as_sticker: bool):
|
def set_img(self, file: bytes, file_name: str):
|
||||||
# """
|
"""
|
||||||
# 设置消息的图片
|
设置消息的图片
|
||||||
# @param file: 图片文件 (实际上是 vec<u8>)
|
@param file: 图片文件 (实际上是 vec<u8>)
|
||||||
# @param file_type: 图片类型 (MIME) (image/png; image/jpeg)
|
@param file_name: 图片名称 (just_img.png)
|
||||||
# @param as_sticker: 是否作为贴纸发送
|
"""
|
||||||
# """
|
|
||||||
|
|
||||||
|
|
||||||
class TailchatClient:
|
class TailchatClient:
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
import io
|
||||||
|
import psutil
|
||||||
|
import platform
|
||||||
from typing import TYPE_CHECKING, TypeVar
|
from typing import TYPE_CHECKING, TypeVar
|
||||||
|
from PIL import (Image, ImageDraw, ImageFont)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ica_typing import IcaNewMessage, IcaClient
|
from ica_typing import IcaNewMessage, IcaClient
|
||||||
|
@ -9,16 +13,59 @@ else:
|
||||||
TailchatReciveMessage = TypeVar("TailchatReciveMessage")
|
TailchatReciveMessage = TypeVar("TailchatReciveMessage")
|
||||||
TailchatClient = TypeVar("TailchatClient")
|
TailchatClient = TypeVar("TailchatClient")
|
||||||
|
|
||||||
|
|
||||||
|
# 生成一张本地信息图
|
||||||
|
def local_env_info() -> str:
|
||||||
|
cache = io.StringIO()
|
||||||
|
# 参考 DR 的 (crash report)
|
||||||
|
cache.write(f"系统: {platform.platform()}\n")
|
||||||
|
# 处理器
|
||||||
|
try:
|
||||||
|
cache.write("|".join([f"{x}%" for x in psutil.cpu_percent(interval=1, percpu=True)]))
|
||||||
|
cache.write("\n")
|
||||||
|
except OSError:
|
||||||
|
cache.write("CPU: 未知\n")
|
||||||
|
# Python 版本信息
|
||||||
|
cache.write(f"{platform.python_implementation()}: {platform.python_version()}-{platform.python_branch()}({platform.python_compiler()})\n")
|
||||||
|
# 内存信息
|
||||||
|
try:
|
||||||
|
memory = psutil.virtual_memory()
|
||||||
|
cache.write(f"内存: {memory.free / 1024 / 1024 / 1024:.3f}GB/{memory.total / 1024 / 1024 / 1024:.3f}GB\n")
|
||||||
|
except OSError:
|
||||||
|
cache.write("内存: 未知\n")
|
||||||
|
return cache.getvalue()
|
||||||
|
|
||||||
|
def local_env_image() -> bytes:
|
||||||
|
img = Image.new("RGB", (800, 140), (255, 255, 255))
|
||||||
|
# 往图片上写入一些信息
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
font = ImageFont.truetype("./SMILEYSANS-OBLIQUE.TTF", size=25)
|
||||||
|
draw.text((10, 10), local_env_info(), fill=(0, 0, 0), font=font)
|
||||||
|
img_cache = io.BytesIO()
|
||||||
|
img.save(img_cache, format="PNG")
|
||||||
|
raw_img = img_cache.getvalue()
|
||||||
|
img_cache.close()
|
||||||
|
return raw_img
|
||||||
|
|
||||||
def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
|
def on_ica_message(msg: IcaNewMessage, client: IcaClient) -> None:
|
||||||
if not (msg.is_from_self or msg.is_reply):
|
if not (msg.is_from_self or msg.is_reply):
|
||||||
if msg.content == "/bot":
|
if msg.content == "/bot":
|
||||||
reply = msg.reply_with(f"ica-async-rs({client.version})-sync-py {client.ica_version}")
|
reply = msg.reply_with(f"ica-async-rs({client.version})-sync-py {client.ica_version}")
|
||||||
client.send_message(reply)
|
client.send_message(reply)
|
||||||
|
elif msg.content == "/bot-sys":
|
||||||
|
datas = local_env_info()
|
||||||
|
reply = msg.reply_with(datas)
|
||||||
|
reply.set_img(local_env_image(), "image/png", False)
|
||||||
|
client.send_message(reply)
|
||||||
|
|
||||||
|
|
||||||
def on_tailchat_message(msg: TailchatReciveMessage, client: TailchatClient) -> None:
|
def on_tailchat_message(msg: TailchatReciveMessage, client: TailchatClient) -> None:
|
||||||
# if not (msg.is_from_self or msg.is_reply):
|
if not (msg.is_reply or msg.is_from_self):
|
||||||
if not (msg.is_reply):
|
|
||||||
if msg.content == "/bot":
|
if msg.content == "/bot":
|
||||||
reply = msg.reply_with(f"tailchat-async-rs({client.version})-sync-py {client.tailchat_version}")
|
reply = msg.reply_with(f"tailchat-async-rs({client.version})-sync-py {client.tailchat_version}")
|
||||||
client.send_message(reply)
|
client.send_message(reply)
|
||||||
|
elif msg.content == "/bot-sys":
|
||||||
|
datas = local_env_info()
|
||||||
|
reply = msg.reply_with(datas)
|
||||||
|
reply.set_img(local_env_image(), "just_img.png")
|
||||||
|
client.send_message(reply)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod api;
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
|
||||||
|
|
8
ica-rs/src/data_struct/tailchat/api.rs
Normal file
8
ica-rs/src/data_struct/tailchat/api.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct FileUpload {
|
||||||
|
pub etag: String,
|
||||||
|
pub path: String,
|
||||||
|
pub url: String,
|
||||||
|
}
|
|
@ -114,7 +114,17 @@ impl SendingFile {
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn gen_markdown(&self, response_data: JsonValue) {}
|
pub fn gen_markdown(&self, backend_path: &str) -> String {
|
||||||
|
match self {
|
||||||
|
Self::Image { .. } => {
|
||||||
|
format!("[img]{}[/img]", backend_path)
|
||||||
|
}
|
||||||
|
Self::File { name, .. } => {
|
||||||
|
format!("[card type=file url={}]{}[/card]", backend_path, name)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
|
|
@ -100,13 +100,29 @@ macro_rules! call_py_func {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
if let Ok(py_func) = get_func($plugin.py_module.bind(py), $func_name) {
|
if let Ok(py_func) = get_func($plugin.py_module.bind(py), $func_name) {
|
||||||
if let Err(e) = py_func.call1($args) {
|
if let Err(py_err) = py_func.call1($args) {
|
||||||
let e = PyPluginError::FuncCallError(
|
let e = PyPluginError::FuncCallError(
|
||||||
e,
|
py_err,
|
||||||
$func_name.to_string(),
|
$func_name.to_string(),
|
||||||
$plugin_path.to_string_lossy().to_string(),
|
$plugin_path.to_string_lossy().to_string(),
|
||||||
);
|
);
|
||||||
event!(Level::WARN, "failed to call function<{}>: {:?}", $func_name, e);
|
event!(
|
||||||
|
Level::WARN,
|
||||||
|
"failed to call function<{}>: {}\ntraceback: {}",
|
||||||
|
$func_name,
|
||||||
|
e,
|
||||||
|
// 获取 traceback
|
||||||
|
match &e {
|
||||||
|
PyPluginError::FuncCallError(py_err, _, _) => match py_err.traceback_bound(py) {
|
||||||
|
Some(traceback) => match traceback.format() {
|
||||||
|
Ok(trace) => trace,
|
||||||
|
Err(trace_e) => format!("failed to format traceback: {:?}", trace_e),
|
||||||
|
},
|
||||||
|
None => "no traceback".to_string(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,15 +10,14 @@ use tracing::{event, span, Level};
|
||||||
pub async fn send_message(client: &Client, message: &SendingMessage) -> bool {
|
pub async fn send_message(client: &Client, message: &SendingMessage) -> bool {
|
||||||
let span = span!(Level::INFO, "tailchat send message");
|
let span = span!(Level::INFO, "tailchat send message");
|
||||||
let _enter = span.enter();
|
let _enter = span.enter();
|
||||||
|
let mut value: Value = message.as_value();
|
||||||
if message.contain_file() {
|
if message.contain_file() {
|
||||||
// 处理文件
|
// 处理文件
|
||||||
let mut header = reqwest::header::HeaderMap::new();
|
let mut header = reqwest::header::HeaderMap::new();
|
||||||
header
|
header.append(
|
||||||
.insert(
|
"X-Token",
|
||||||
"X-Token",
|
crate::MainStatus::global_tailchat_status().jwt_token.clone().parse().unwrap(),
|
||||||
crate::MainStatus::global_tailchat_status().jwt_token.clone().parse().unwrap(),
|
);
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let file_client = match reqwest::ClientBuilder::new().default_headers(header).build() {
|
let file_client = match reqwest::ClientBuilder::new().default_headers(header).build() {
|
||||||
Ok(client) => client,
|
Ok(client) => client,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -72,9 +71,13 @@ pub async fn send_message(client: &Client, message: &SendingMessage) -> bool {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
event!(Level::INFO, "file upload success with data:{}", format!("{:#?}", data).cyan());
|
let content = format!(
|
||||||
|
"{}{}",
|
||||||
|
message.content,
|
||||||
|
message.file.gen_markdown(data["url"].as_str().unwrap())
|
||||||
|
);
|
||||||
|
value["content"] = json!(content);
|
||||||
}
|
}
|
||||||
let value: Value = message.as_value();
|
|
||||||
match client.emit("chat.message.sendMessage", value).await {
|
match client.emit("chat.message.sendMessage", value).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
event!(Level::DEBUG, "send message {}", format!("{:#?}", message).cyan());
|
event!(Level::DEBUG, "send message {}", format!("{:#?}", message).cyan());
|
||||||
|
|
Loading…
Reference in New Issue
Block a user