use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "cmd", rename_all = "snake_case")]
pub enum Request {
Ping,
Sessions {
#[serde(default = "default_limit_20")]
limit: usize,
},
History {
chat: String,
#[serde(default = "default_limit_50")]
limit: usize,
#[serde(default)]
offset: usize,
#[serde(skip_serializing_if = "Option::is_none")]
since: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
until: Option<i64>,
},
Search {
keyword: String,
#[serde(skip_serializing_if = "Option::is_none")]
chats: Option<Vec<String>>,
#[serde(default = "default_limit_20")]
limit: usize,
#[serde(skip_serializing_if = "Option::is_none")]
since: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
until: Option<i64>,
},
Contacts {
#[serde(skip_serializing_if = "Option::is_none")]
query: Option<String>,
#[serde(default = "default_limit_50")]
limit: usize,
},
Watch,
}
impl Request {
pub fn to_json_line(&self) -> anyhow::Result<String> {
let s = serde_json::to_string(self)?;
Ok(s + "\n")
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Response {
pub ok: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(flatten)]
pub data: Value,
}
impl Response {
pub fn ok(data: Value) -> Self {
Self { ok: true, error: None, data }
}
pub fn err(msg: impl Into<String>) -> Self {
Self { ok: false, error: Some(msg.into()), data: Value::Null }
}
pub fn to_json_line(&self) -> anyhow::Result<String> {
let s = serde_json::to_string(self)?;
Ok(s + "\n")
}
}
fn default_limit_20() -> usize { 20 }
fn default_limit_50() -> usize { 50 }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WatchEvent {
pub event: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub time: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub chat: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub username: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_group: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sender: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub msg_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<i64>,
}
impl WatchEvent {
pub fn connected() -> Self {
Self {
event: "connected".into(),
time: None, chat: None, username: None, is_group: None,
sender: None, content: None, msg_type: None, timestamp: None,
}
}
pub fn heartbeat() -> Self {
Self {
event: "heartbeat".into(),
time: None, chat: None, username: None, is_group: None,
sender: None, content: None, msg_type: None, timestamp: None,
}
}
pub fn to_json_line(&self) -> anyhow::Result<String> {
let s = serde_json::to_string(self)?;
Ok(s + "\n")
}
}