use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct WireSegment {
#[serde(rename = "type")]
pub kind: String,
#[serde(default)]
pub data: Map<String, Value>,
}
pub(crate) fn value_as_string(v: &Value) -> Option<String> {
match v {
Value::String(s) => Some(s.clone()),
Value::Number(n) => Some(n.to_string()),
Value::Bool(b) => Some(b.to_string()),
_ => None,
}
}
impl WireSegment {
pub fn new(kind: impl Into<String>, data: Map<String, Value>) -> Self {
WireSegment { kind: kind.into(), data }
}
pub fn str_field(&self, key: &str) -> Option<String> {
self.data.get(key).and_then(value_as_string)
}
pub fn i64_field(&self, key: &str) -> Option<i64> {
match self.data.get(key)? {
Value::Number(n) => n.as_i64(),
Value::String(s) => s.parse().ok(),
_ => None,
}
}
pub fn bool_field(&self, key: &str) -> Option<bool> {
match self.data.get(key)? {
Value::Bool(b) => Some(*b),
Value::String(s) => match s.as_str() {
"true" | "yes" | "1" => Some(true),
"false" | "no" | "0" => Some(false),
_ => None,
},
Value::Number(n) => n.as_i64().map(|v| v != 0),
_ => None,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum WireMessage {
Array(Vec<WireSegment>),
Cq(String),
}
impl Default for WireMessage {
fn default() -> Self {
WireMessage::Array(Vec::new())
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WireSender {
#[serde(default)]
pub user_id: Option<i64>,
#[serde(default)]
pub nickname: Option<String>,
#[serde(default)]
pub card: Option<String>,
#[serde(default)]
pub sex: Option<String>,
#[serde(default)]
pub age: Option<i32>,
#[serde(default)]
pub area: Option<String>,
#[serde(default)]
pub level: Option<String>,
#[serde(default)]
pub role: Option<String>,
#[serde(default)]
pub title: Option<String>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WireMessageStyle {
#[serde(default)]
pub bubble_id: Option<i64>,
#[serde(default)]
pub pendant_id: Option<i64>,
#[serde(default)]
pub pal_type: Option<i64>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WireAnonymous {
#[serde(default)]
pub id: i64,
#[serde(default)]
pub name: String,
#[serde(default)]
pub flag: String,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WireFile {
#[serde(default)]
pub id: Option<String>,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub size: Option<u64>,
#[serde(default)]
pub busid: Option<i64>,
#[serde(default)]
pub url: Option<String>,
#[serde(default)]
pub hash: Option<String>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct RawEventJson {
#[serde(default)]
pub time: i64,
#[serde(default)]
pub self_id: i64,
#[serde(default)]
pub post_type: Option<String>,
#[serde(default)]
pub message_type: Option<String>,
#[serde(default)]
pub sub_type: Option<String>,
#[serde(default)]
pub message_id: Option<i32>,
#[serde(default)]
pub group_id: Option<i64>,
#[serde(default)]
pub user_id: Option<i64>,
#[serde(default)]
pub message: Option<WireMessage>,
#[serde(default)]
pub raw_message: Option<String>,
#[serde(default)]
pub sender: Option<WireSender>,
#[serde(default)]
pub anonymous: Option<WireAnonymous>,
#[serde(default)]
pub font: Option<i32>,
#[serde(default)]
pub message_seq: Option<i64>,
#[serde(default)]
pub message_style: Option<WireMessageStyle>,
#[serde(default)]
pub notice_type: Option<String>,
#[serde(default)]
pub operator_id: Option<i64>,
#[serde(default)]
pub target_id: Option<i64>,
#[serde(default)]
pub sender_id: Option<i64>,
#[serde(default)]
pub duration: Option<i64>,
#[serde(default)]
pub file: Option<WireFile>,
#[serde(default)]
pub honor_type: Option<String>,
#[serde(default)]
pub action: Option<String>,
#[serde(default)]
pub suffix: Option<String>,
#[serde(default)]
pub action_img_url: Option<String>,
#[serde(default)]
pub code: Option<String>,
#[serde(default)]
pub count: Option<i64>,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub message_offline: Option<String>,
#[serde(default)]
pub tag: Option<String>,
#[serde(default)]
pub reason: Option<String>,
#[serde(default)]
pub request_type: Option<String>,
#[serde(default)]
pub comment: Option<String>,
#[serde(default)]
pub flag: Option<String>,
#[serde(default)]
pub invitor_id: Option<i64>,
#[serde(default)]
pub meta_event_type: Option<String>,
#[serde(default)]
pub interval: Option<i64>,
#[serde(default)]
pub status: Option<Value>,
#[serde(flatten)]
pub extra: Map<String, Value>,
}
#[derive(Clone, Debug, Default, Deserialize)]
pub struct RespJson {
#[serde(default)]
pub status: String,
#[serde(default)]
pub retcode: i64,
#[serde(default)]
pub data: Value,
#[serde(default)]
pub echo: Value,
#[serde(default, alias = "msg", alias = "wording")]
pub message: Option<String>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Inbound {
Resp(EchoEnvelope),
Event(Box<RawEventJson>),
}
#[derive(Clone, Debug, Deserialize)]
pub struct EchoEnvelope {
pub echo: Value,
#[serde(default)]
pub status: Value,
#[serde(default)]
pub retcode: Value,
#[serde(flatten)]
pub rest: Map<String, Value>,
}