mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-20 15:09:54 +08:00
239 lines
6.8 KiB
Rust
239 lines
6.8 KiB
Rust
use std::fmt::Display;
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
use serde_json::{json, Value as JsonValue};
|
||
|
||
use crate::data_struct::tailchat::{ConverseId, GroupId, MessageId, UserId};
|
||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||
pub struct ReceiveMessage {
|
||
/// 消息ID
|
||
#[serde(rename = "_id")]
|
||
pub msg_id: MessageId,
|
||
/// 消息内容
|
||
pub content: String,
|
||
/// 发送者ID
|
||
#[serde(rename = "author")]
|
||
pub sender_id: UserId,
|
||
/// 服务器ID
|
||
/// 在私聊中不存在
|
||
#[serde(rename = "groupId")]
|
||
pub group_id: Option<GroupId>,
|
||
/// 会话ID
|
||
#[serde(rename = "converseId")]
|
||
pub converse_id: ConverseId,
|
||
/// 是否有回复?
|
||
#[serde(rename = "hasRecall")]
|
||
pub has_recall: bool,
|
||
/// 暂时懒得解析这玩意
|
||
/// 准确来说是不确定内容, 毕竟没细看 API
|
||
pub meta: Option<JsonValue>,
|
||
/// 也懒得解析这玩意
|
||
pub reactions: Vec<JsonValue>,
|
||
/// 创建时间
|
||
#[serde(rename = "createdAt")]
|
||
pub created_at: String,
|
||
/// 更新时间
|
||
#[serde(rename = "updatedAt")]
|
||
pub updated_at: String,
|
||
}
|
||
|
||
impl ReceiveMessage {
|
||
pub fn is_reply(&self) -> bool {
|
||
if let Some(meta) = &self.meta {
|
||
meta.get("reply").is_some()
|
||
} else {
|
||
false
|
||
}
|
||
}
|
||
|
||
pub fn is_from_self(&self) -> bool {
|
||
crate::MainStatus::global_tailchat_status().user_id == self.sender_id
|
||
}
|
||
|
||
/// 创建一个对这条消息的回复
|
||
pub fn as_reply(&self) -> SendingMessage {
|
||
SendingMessage::new(
|
||
"".to_string(),
|
||
self.converse_id.clone(),
|
||
self.group_id.clone(),
|
||
Some(ReplyMeta::from_receive_message(self)),
|
||
)
|
||
}
|
||
|
||
/// 回复这条消息
|
||
pub fn reply_with(&self, content: &str) -> SendingMessage {
|
||
SendingMessage::new(
|
||
content.to_string(),
|
||
self.converse_id.clone(),
|
||
self.group_id.clone(),
|
||
Some(ReplyMeta::from_receive_message(self)),
|
||
)
|
||
}
|
||
}
|
||
|
||
impl Display for ReceiveMessage {
|
||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||
// msgid|groupid-converseid|senderid|content
|
||
write!(
|
||
f,
|
||
"{}|{:?}-{}|{}|{}",
|
||
self.msg_id, self.group_id, self.converse_id, self.sender_id, self.content
|
||
)
|
||
}
|
||
}
|
||
|
||
#[derive(Debug, Clone, Default)]
|
||
pub enum SendingFile {
|
||
#[default]
|
||
None,
|
||
/// 需要生成
|
||
/// [img height=1329 width=1918]{BACKEND}/static/files/6602e20d7b8d10675758e36b/8db505b87bdf9fb309467abcec4d8e2a.png[/img]
|
||
Image { file: Vec<u8>, name: String },
|
||
/// [card type=file url={BACKEND}/static/files/6602e20d7b8d10675758e36b/9df28943d17b9713cb0ea9625f37d015.wav]Engine.wav[/card]
|
||
File { file: Vec<u8>, name: String },
|
||
}
|
||
|
||
impl SendingFile {
|
||
pub fn is_some(&self) -> bool { !matches!(self, Self::None) }
|
||
pub fn is_image(&self) -> bool { matches!(self, Self::Image { .. }) }
|
||
pub fn is_file(&self) -> bool { matches!(self, Self::File { .. }) }
|
||
|
||
pub fn file_data(&self) -> Vec<u8> {
|
||
match self {
|
||
Self::Image { file, .. } => file.clone(),
|
||
Self::File { file, .. } => file.clone(),
|
||
_ => vec![],
|
||
}
|
||
}
|
||
|
||
pub fn file_name(&self) -> String {
|
||
match self {
|
||
Self::Image { name, .. } => name.clone(),
|
||
Self::File { name, .. } => name.clone(),
|
||
_ => "".to_string(),
|
||
}
|
||
}
|
||
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)]
|
||
/// 将要发送的消息
|
||
///
|
||
/// 发送时:
|
||
/// - `content`: 回复的消息内容
|
||
/// - `converseId`: 会话ID
|
||
/// - `groupId`: 服务器ID
|
||
/// - `meta`: 回复的消息的元数据 ( 可能为空 )
|
||
/// - `mentions`: 被回复的人的ID (可以是多个)
|
||
/// - `reply`: 被回复的消息
|
||
/// - `_id`: 被回复的消息ID
|
||
/// - `author`: 被回复的消息的发送者ID
|
||
/// - `content`: 被回复的消息内容
|
||
pub struct SendingMessage {
|
||
/// 消息内容
|
||
///
|
||
/// 其实还有个 plain, 就是不知道干啥的
|
||
pub content: String,
|
||
/// 会话ID
|
||
#[serde(rename = "converseId")]
|
||
pub converse_id: ConverseId,
|
||
/// 服务器ID
|
||
#[serde(rename = "groupId")]
|
||
pub group_id: Option<GroupId>,
|
||
/// 消息的元数据
|
||
pub meta: Option<ReplyMeta>,
|
||
/// 额外携带的文件
|
||
#[serde(skip)]
|
||
pub file: SendingFile,
|
||
}
|
||
|
||
impl SendingMessage {
|
||
pub fn new(
|
||
content: String,
|
||
converse_id: ConverseId,
|
||
group_id: Option<GroupId>,
|
||
meta: Option<ReplyMeta>,
|
||
) -> Self {
|
||
Self {
|
||
content,
|
||
converse_id,
|
||
group_id,
|
||
meta,
|
||
file: SendingFile::None,
|
||
}
|
||
}
|
||
pub fn new_without_meta(
|
||
content: String,
|
||
converse_id: ConverseId,
|
||
group_id: Option<GroupId>,
|
||
) -> Self {
|
||
Self {
|
||
content,
|
||
converse_id,
|
||
group_id,
|
||
meta: None,
|
||
file: SendingFile::None,
|
||
}
|
||
}
|
||
pub fn contain_file(&self) -> bool { self.file.is_some() }
|
||
|
||
pub fn add_img(&mut self, file: SendingFile) { self.file = file; }
|
||
|
||
pub fn as_value(&self) -> JsonValue { serde_json::to_value(self).unwrap() }
|
||
}
|
||
|
||
#[derive(Debug, Clone)]
|
||
pub struct ReplyMeta {
|
||
/// 被回复的人的ID (可以是多个)
|
||
pub mentions: Vec<UserId>,
|
||
/// 被回复的消息ID
|
||
pub reply_id: MessageId,
|
||
/// 被回复的消息的发送者ID
|
||
pub reply_author: UserId,
|
||
/// 被回复的消息内容
|
||
pub reply_content: String,
|
||
}
|
||
|
||
impl ReplyMeta {
|
||
pub fn from_receive_message(msg: &ReceiveMessage) -> Self {
|
||
Self {
|
||
mentions: vec![msg.sender_id.clone()],
|
||
reply_id: msg.msg_id.clone(),
|
||
reply_author: msg.sender_id.clone(),
|
||
reply_content: msg.content.clone(),
|
||
}
|
||
}
|
||
pub fn add_mention(&mut self, user_id: UserId) { self.mentions.push(user_id); }
|
||
pub fn replace_content(&mut self, content: String) { self.reply_content = content; }
|
||
}
|
||
|
||
impl Serialize for ReplyMeta {
|
||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||
where
|
||
S: serde::ser::Serializer,
|
||
{
|
||
let reply = json! {
|
||
{
|
||
"_id": self.reply_id,
|
||
"author": self.reply_author,
|
||
"content": self.reply_content,
|
||
}
|
||
};
|
||
let mut map = serde_json::Map::new();
|
||
map.insert("mentions".to_string(), serde_json::to_value(&self.mentions).unwrap());
|
||
map.insert("reply".to_string(), reply);
|
||
map.serialize(serializer)
|
||
}
|
||
}
|