81 lines
3.5 KiB
Rust
Executable File
81 lines
3.5 KiB
Rust
Executable File
/// Normalised chat message — protocol-agnostic representation.
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub enum MessageKind {
|
|
Text,
|
|
Action,
|
|
Notice,
|
|
Private,
|
|
FileTransfer { filename: String, size_bytes: u64, source: String },
|
|
Error,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ChatMessage {
|
|
pub id: String,
|
|
pub protocol: crate::core::protocol::ProtocolType,
|
|
pub kind: MessageKind,
|
|
pub source: String,
|
|
pub sender: String,
|
|
pub body: String,
|
|
pub timestamp: DateTime<Utc>,
|
|
pub is_own: bool,
|
|
/// `true` if the timestamp was provided by the remote server (e.g. IRCv3
|
|
/// `server-time`, Matrix `origin_server_ts`) rather than the local clock.
|
|
/// The TUI uses this to render the timestamp in a distinct style so the
|
|
/// user can see which messages have server-confirmed times.
|
|
#[serde(default)]
|
|
pub remote_ts: bool,
|
|
}
|
|
|
|
impl ChatMessage {
|
|
pub fn new_id() -> String {
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_nanos();
|
|
format!("{nanos:x}")
|
|
}
|
|
|
|
pub fn text(protocol: crate::core::protocol::ProtocolType, source: &str, sender: &str, body: &str, is_own: bool) -> Self {
|
|
Self { id: Self::new_id(), protocol, kind: MessageKind::Text, source: source.to_owned(), sender: sender.to_owned(), body: body.to_owned(), timestamp: Utc::now(), is_own, remote_ts: false }
|
|
}
|
|
|
|
pub fn action(protocol: crate::core::protocol::ProtocolType, source: &str, sender: &str, body: &str, is_own: bool) -> Self {
|
|
Self { id: Self::new_id(), protocol, kind: MessageKind::Action, source: source.to_owned(), sender: sender.to_owned(), body: body.to_owned(), timestamp: Utc::now(), is_own, remote_ts: false }
|
|
}
|
|
|
|
pub fn notice(protocol: crate::core::protocol::ProtocolType, source: &str, body: &str) -> Self {
|
|
Self { id: Self::new_id(), protocol, kind: MessageKind::Notice, source: source.to_owned(), sender: String::new(), body: body.to_owned(), timestamp: Utc::now(), is_own: false, remote_ts: false }
|
|
}
|
|
|
|
pub fn error(protocol: crate::core::protocol::ProtocolType, source: &str, body: &str) -> Self {
|
|
Self { id: Self::new_id(), protocol, kind: MessageKind::Error, source: source.to_owned(), sender: String::new(), body: body.to_owned(), timestamp: Utc::now(), is_own: false, remote_ts: false }
|
|
}
|
|
|
|
/// Private / direct message.
|
|
pub fn private(protocol: crate::core::protocol::ProtocolType, source: &str, sender: &str, body: &str, is_own: bool) -> Self {
|
|
Self { id: Self::new_id(), protocol, kind: MessageKind::Private, source: source.to_owned(), sender: sender.to_owned(), body: body.to_owned(), timestamp: Utc::now(), is_own, remote_ts: false }
|
|
}
|
|
|
|
/// Override the timestamp (used by IRCv3 server-time, Matrix event
|
|
/// origin_server_ts, etc.). Returns `self` for chaining.
|
|
pub fn with_timestamp(mut self, ts: DateTime<Utc>) -> Self {
|
|
self.timestamp = ts;
|
|
self
|
|
}
|
|
|
|
/// Mark that this message's timestamp came from the remote server rather
|
|
/// than the local clock. The TUI renders these with a distinct style.
|
|
pub fn with_remote_ts(mut self) -> Self {
|
|
self.remote_ts = true;
|
|
self
|
|
}
|
|
|
|
/// Conditionally mark the message as having a remote timestamp.
|
|
pub fn with_remote_ts_if(mut self, flag: bool) -> Self {
|
|
self.remote_ts = flag;
|
|
self
|
|
}
|
|
} |