use actix::Message as ActixMessage;
use bytestring::ByteString;
use serde_json::{json, Value};
#[derive(
serde::Serialize,
serde::Deserialize,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Debug,
Hash,
strum_macros::EnumString,
)]
#[strum(ascii_case_insensitive)]
pub enum Level {
Msg,
Err,
Info,
Warn,
}
#[derive(
serde::Serialize,
serde::Deserialize,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Debug,
Hash,
strum_macros::EnumString,
)]
#[strum(ascii_case_insensitive)]
pub enum OutputMessageType {
ServerTime,
Connected,
Disconnect,
Accept,
Success,
Failed,
Notification,
}
#[derive(serde::Serialize)]
pub enum TypedMessage {
TextMessage(String),
JsonMessage(Value),
}
#[derive(serde::Serialize, ActixMessage)]
#[rtype(result = "()")]
pub struct OutputMessage {
pub id: Option<String>,
pub level: Level,
pub ty: OutputMessageType,
pub msg: TypedMessage,
}
impl From<OutputMessage> for ByteString {
fn from(val: OutputMessage) -> Self {
let json_string = serde_json::to_string(&val).unwrap();
let byte_string: ByteString = ByteString::from(json_string);
byte_string
}
}
impl OutputMessage {
pub fn err(ty: OutputMessageType, msg: &str, id: Option<String>) -> Self {
OutputMessage {
id,
level: Level::Err,
ty,
msg: TypedMessage::TextMessage(msg.to_string()),
}
}
pub fn output(&self) -> Option<String> {
let mut vl = json! ({"level": self.level, "ty": self.ty});
if let Some(id) = &self.id {
vl["id"] = json!(id)
}
match &self.msg {
TypedMessage::TextMessage(msg) => vl["data"] = json!(msg),
TypedMessage::JsonMessage(val) => vl["data"] = val.clone(),
}
vl["@ts"] = json!(Self::ts());
Some(serde_json::to_string(&vl).unwrap())
}
pub fn ts() -> String {
chrono::Utc::now()
.format("%Y-%m-%dT%H:%M:%S.%3f")
.to_string()
+ "Z"
}
}