use super::{Anonymous, Sender};
use crate::event::{MsgEvent, PostType, RepliableEvent, UniversalMessage};
use crate::message_trait::MessageRegistrar as _;
use crate::onebot_message::OneBotMessage;
use kovi::bot::runtimebot::{CanSendApi, send_api_request_with_forget};
use kovi::bot::{BotInformation, SendApi};
use kovi::error::EventBuildError;
use kovi::event::id::ref_id::RefID;
use kovi::event::{Event, InternalEvent};
use kovi::message::Message as KoviMessage;
use kovi::types::ApiAndOptOneshot;
use log::info;
use serde::Serialize;
use serde_json::value::Index;
use serde_json::{self, Value, json};
use tokio::sync::mpsc;
#[derive(Debug, Clone)]
pub struct AdminMsgEvent {
pub time: i64,
pub self_id: i64,
pub post_type: PostType,
pub message_type: String,
pub sub_type: String,
pub message: KoviMessage,
pub message_id: i32,
pub group_id: Option<i64>,
pub user_id: i64,
pub anonymous: Option<Anonymous>,
pub raw_message: String,
pub font: i32,
pub sender: Sender,
pub text: Option<String>,
pub human_text: String,
pub original_json: Value,
pub api_tx: mpsc::Sender<ApiAndOptOneshot>,
}
impl Event for AdminMsgEvent {
fn de(
event: &InternalEvent,
bot_info: &BotInformation,
api_tx: &mpsc::Sender<ApiAndOptOneshot>,
) -> Option<Self> {
let InternalEvent::DriverEvent(json) = event else {
return None;
};
let event = Self::new(api_tx.clone(), json.clone()).ok()?;
if !bot_info.any_admins_contains(RefID::new(&event.sender.user_id)) {
return None;
}
Some(event)
}
}
impl AdminMsgEvent {
fn new(
api_tx: mpsc::Sender<ApiAndOptOneshot>,
json: Value,
) -> Result<AdminMsgEvent, EventBuildError> {
let msg_event = MsgEvent::new(api_tx, json)?;
Ok(AdminMsgEvent {
time: msg_event.time,
self_id: msg_event.self_id,
post_type: msg_event.post_type,
message_type: msg_event.message_type,
sub_type: msg_event.sub_type,
message: msg_event.message,
message_id: msg_event.message_id,
group_id: msg_event.group_id,
user_id: msg_event.user_id,
anonymous: msg_event.anonymous,
raw_message: msg_event.raw_message,
font: msg_event.font,
sender: msg_event.sender,
text: msg_event.text,
human_text: msg_event.human_text,
original_json: msg_event.original_json,
api_tx: msg_event.api_tx,
})
}
}
impl AdminMsgEvent {
pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
self.original_json.get(index)
}
}
impl<I> std::ops::Index<I> for AdminMsgEvent
where
I: Index,
{
type Output = Value;
fn index(&self, index: I) -> &Self::Output {
&self.original_json[index]
}
}
impl AdminMsgEvent {
fn reply_builder<M>(&self, msg: M, auto_escape: bool) -> SendApi
where
M: Into<OneBotMessage>,
{
RepliableEvent::reply_builder(self, msg, auto_escape)
}
#[cfg(not(feature = "cqstring"))]
pub fn reply<T>(&self, msg: T)
where
KoviMessage: From<T>,
T: Serialize,
{
RepliableEvent::reply(self, msg)
}
#[cfg(feature = "cqstring")]
pub fn reply<T>(&self, msg: T)
where
CQMessage: From<T>,
T: Serialize,
{
RepliableEvent::reply(self, msg)
}
#[cfg(not(feature = "cqstring"))]
pub fn reply_and_quote<T>(&self, msg: T)
where
KoviMessage: From<T>,
T: Serialize,
{
RepliableEvent::reply_and_quote(self, msg);
}
#[cfg(feature = "cqstring")]
fn reply_and_quote<T>(&self, msg: T)
where
CQMessage: From<T>,
T: Serialize,
{
RepliableEvent::reply_and_quote(self, msg);
}
#[cfg(feature = "cqstring")]
fn reply_text<T>(&self, msg: T)
where
String: From<T>,
T: Serialize,
{
RepliableEvent::reply_text(self, msg)
}
pub fn get_text(&self) -> String {
RepliableEvent::get_text(self)
}
pub fn get_sender_nickname(&self) -> String {
RepliableEvent::get_sender_nickname(self)
}
pub fn borrow_text(&self) -> Option<&str> {
RepliableEvent::borrow_text(self)
}
pub fn is_group(&self) -> bool {
UniversalMessage::is_group(self)
}
pub fn is_private(&self) -> bool {
UniversalMessage::is_private(self)
}
}
impl UniversalMessage for AdminMsgEvent {
fn is_group(&self) -> bool {
self.group_id.is_some()
}
fn is_private(&self) -> bool {
self.group_id.is_none()
}
}
impl RepliableEvent for AdminMsgEvent {
fn reply_builder<M>(&self, msg: M, auto_escape: bool) -> SendApi
where
M: Into<OneBotMessage>,
{
let msg = msg.into();
if self.is_private() {
SendApi::new(
"send_msg",
json!({
"message_type":"private",
"user_id":self.user_id,
"message":msg,
"auto_escape":auto_escape,
}),
)
} else {
SendApi::new(
"send_msg",
json!({
"message_type":"group",
"group_id":self.group_id.expect("unreachable"),
"message":msg,
"auto_escape":auto_escape,
}),
)
}
}
#[cfg(not(feature = "cqstring"))]
fn reply<T>(&self, msg: T)
where
KoviMessage: From<T>,
T: Serialize,
{
let msg = KoviMessage::from(msg);
let mut nickname = self.get_sender_nickname();
nickname.insert(0, ' ');
let id = &self.sender.user_id;
let message_type = &self.message_type;
let group_id = match &self.group_id {
Some(v) => format!(" {v}"),
None => "".to_string(),
};
let human_msg = msg.to_human_string();
info!("[reply] [to {message_type}{group_id}{nickname} {id}]: {human_msg}");
let send_msg = self.reply_builder(msg, false);
send_api_request_with_forget(&self.api_tx, send_msg)
}
#[cfg(feature = "cqstring")]
fn reply<T>(&self, msg: T)
where
CQMessage: From<T>,
T: Serialize,
{
let msg = CQMessage::from(msg);
let send_msg = self.reply_builder(&msg, false);
let mut nickname = self.get_sender_nickname();
nickname.insert(0, ' ');
let id = &self.sender.user_id;
let message_type = &self.message_type;
let group_id = match &self.group_id {
Some(v) => format!(" {v}"),
None => "".to_string(),
};
let human_msg = Message::from(msg).to_human_string();
info!("[reply] [to {message_type}{group_id}{nickname} {id}]: {human_msg}");
send_api_request_with_forget(&self.api_tx, send_msg);
}
#[cfg(not(feature = "cqstring"))]
fn reply_and_quote<T>(&self, msg: T)
where
KoviMessage: From<T>,
T: Serialize,
{
let msg = KoviMessage::from(msg).add_reply(self.message_id);
let mut nickname = self.get_sender_nickname();
nickname.insert(0, ' ');
let id = &self.sender.user_id;
let message_type = &self.message_type;
let group_id = match &self.group_id {
Some(v) => format!(" {v}"),
None => "".to_string(),
};
let human_msg = msg.to_human_string();
info!("[reply] [to {message_type}{group_id}{nickname} {id}]: {human_msg}");
let send_msg = self.reply_builder(msg, false);
send_api_request_with_forget(&self.api_tx, send_msg);
}
#[cfg(feature = "cqstring")]
fn reply_and_quote<T>(&self, msg: T)
where
CQMessage: From<T>,
T: Serialize,
{
let msg = CQMessage::from(msg).add_reply(self.message_id);
let send_msg = self.reply_builder(&msg, false);
let mut nickname = self.get_sender_nickname();
nickname.insert(0, ' ');
let id = &self.sender.user_id;
let message_type = &self.message_type;
let group_id = match &self.group_id {
Some(v) => format!(" {v}"),
None => "".to_string(),
};
let human_msg = Message::from(msg).to_human_string();
info!("[reply] [to {message_type}{group_id}{nickname} {id}]: {human_msg}");
send_api_request_with_forget(&self.api_tx, send_msg);
}
#[cfg(feature = "cqstring")]
fn reply_text<T>(&self, msg: T)
where
String: From<T>,
T: Serialize,
{
let send_msg = self.reply_builder(&msg, true);
let mut nickname = self.get_sender_nickname();
nickname.insert(0, ' ');
let id = &self.sender.user_id;
let message_type = &self.message_type;
let group_id = match &self.group_id {
Some(v) => format!(" {v}"),
None => "".to_string(),
};
let msg = String::from(msg);
info!("[reply] [to {message_type}{group_id} {nickname} {id}]: {msg}");
send_api_request_with_forget(&self.api_tx, send_msg);
}
fn get_text(&self) -> String {
match self.text.clone() {
Some(v) => v,
None => "".to_string(),
}
}
fn get_sender_nickname(&self) -> String {
if let Some(v) = &self.sender.nickname {
v.clone()
} else {
"".to_string()
}
}
fn borrow_text(&self) -> Option<&str> {
self.text.as_deref()
}
}
impl CanSendApi for AdminMsgEvent {
fn __get_api_tx(&self) -> &tokio::sync::mpsc::Sender<kovi::types::ApiAndOptOneshot> {
&self.api_tx
}
}