use serde::{Deserialize, Serialize};
use crate::{action::UploadFile, ExtendedValue, StandardEvent};
pub type Resps = Resp<RespContent>;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Resp<T> {
pub status: String,
pub retcode: i64,
pub data: T,
pub message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum RespContent {
SendMessage(SendMessageRespContent),
LatestEvents(Vec<StandardEvent>),
SupportActions(Vec<String>),
Status(StatusContent),
Version(VersionContent),
MessageEvent(StandardEvent),
UserInfo(UserInfoContent),
FriendList(Vec<UserInfoContent>),
GroupInfo(GroupInfoContent),
GroupList(Vec<GroupInfoContent>),
FileId(FileIdContent),
PrepareFileFragmented(FileFragmentedHead),
TransferFileFragmented(Vec<u8>),
GetFile(UploadFile),
Other(ExtendedValue),
}
macro_rules! resp_content {
($t:ty, $name: tt) => {
impl From<$t> for RespContent {
fn from(t: $t) -> Self {
RespContent::$name(t)
}
}
};
}
resp_content!(SendMessageRespContent, SendMessage);
resp_content!(Vec<StandardEvent>, LatestEvents);
resp_content!(Vec<String>, SupportActions);
resp_content!(StatusContent, Status);
resp_content!(VersionContent, Version);
resp_content!(StandardEvent, MessageEvent);
resp_content!(UserInfoContent, UserInfo);
resp_content!(Vec<UserInfoContent>, FriendList);
resp_content!(GroupInfoContent, GroupInfo);
resp_content!(Vec<GroupInfoContent>, GroupList);
resp_content!(FileIdContent, FileId);
resp_content!(FileFragmentedHead, PrepareFileFragmented);
resp_content!(Vec<u8>, TransferFileFragmented);
resp_content!(UploadFile, GetFile);
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum ExtendedRespContent<T> {
Standard(RespContent),
Extended(T),
}
pub trait FromStandard {
fn from_standard(standard: RespContent) -> Self;
}
impl<T> FromStandard for ExtendedRespContent<T> {
fn from_standard(standard: RespContent) -> Self {
ExtendedRespContent::Standard(standard)
}
}
impl RespContent {
pub fn empty() -> Self {
Self::Other(ExtendedValue::empty())
}
}
impl FromStandard for RespContent {
fn from_standard(standard: RespContent) -> Self {
standard
}
}
impl<T> Resp<T> {
#[allow(dead_code)]
pub fn success(data: T) -> Self {
Resp {
status: "ok".to_owned(),
retcode: 0,
data,
message: "".to_owned(),
}
}
#[allow(dead_code)]
pub fn fail(data: T, retcode: i64, message: String) -> Self {
Resp {
status: "failed".to_owned(),
retcode,
data,
message,
}
}
#[allow(dead_code)]
pub fn tired(data: T) -> Self {
Self::fail(data, 36000, "I Am Tired!".to_owned())
}
}
macro_rules! empty_err_resp {
($fn_name: ident, $retcode: expr, $message: expr) => {
#[allow(dead_code)]
pub fn $fn_name() -> Self {
Self::empty_fail($retcode, $message.to_owned())
}
};
}
impl<T> Resp<T>
where
T: FromStandard,
{
#[allow(dead_code)]
pub fn empty_success() -> Self {
Self::success(T::from_standard(RespContent::empty()))
}
#[allow(dead_code)]
pub fn empty_fail(retcode: i64, message: String) -> Self {
Self::fail(T::from_standard(RespContent::empty()), retcode, message)
}
empty_err_resp!(bad_request, 10001, "无效的动作请求");
empty_err_resp!(unsupported_action, 10002, "不支持的动作请求");
empty_err_resp!(bad_param, 10003, "无效的动作请求参数");
empty_err_resp!(unsupported_param, 10004, "不支持的动作请求参数");
empty_err_resp!(unsupported_segment, 10005, "不支持的消息段类型");
empty_err_resp!(bad_segment_data, 10006, "无效的消息段参数");
empty_err_resp!(unsupported_segment_data, 10007, "不支持的消息段参数");
empty_err_resp!(platform_error, 34000, "机器人平台错误");
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct StatusContent {
pub good: bool,
pub online: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VersionContent {
pub r#impl: String,
pub platform: String,
pub version: String,
pub onebot_version: String,
}
impl Default for VersionContent {
fn default() -> Self {
VersionContent {
r#impl: "AbrasOneBot".to_owned(),
platform: "RustOneBot".to_owned(),
version: "0.0.1".to_owned(),
onebot_version: "12".to_owned(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SendMessageRespContent {
pub message_id: String,
pub time: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct UserInfoContent {
pub user_id: String,
pub nickname: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GroupInfoContent {
pub group_id: String,
pub group_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct FileIdContent {
pub file_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct FileContent {
pub name: String,
pub url: Option<String>,
pub headers: Option<std::collections::HashMap<String, String>>,
pub path: Option<String>,
pub data: Option<Vec<u8>>,
pub sha256: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct FileFragmentedHead {
pub name: String,
pub total_size: i64,
pub sha256: String,
}