nirc-rs/src/core/message.rs

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
}
}