Skip to main content

cortexfs_channels/
message.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{ChannelError, ChannelId, ConversationId};
6
7/// Sender identity supplied by the platform adapter.
8#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
9pub struct Participant {
10    pub id: String,
11    pub display_name: Option<String>,
12    pub handle: Option<String>,
13}
14
15/// Text plus optional platform-neutral attachment references.
16#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
17pub struct MessageBody {
18    pub text: String,
19    #[serde(default, skip_serializing_if = "Vec::is_empty")]
20    pub attachments: Vec<Attachment>,
21}
22
23impl MessageBody {
24    pub fn text(value: impl Into<String>) -> Result<Self, ChannelError> {
25        let body = Self {
26            text: value.into(),
27            attachments: Vec::new(),
28        };
29        body.validate()?;
30        Ok(body)
31    }
32
33    pub fn validate(&self) -> Result<(), ChannelError> {
34        if self.text.is_empty() && self.attachments.is_empty() {
35            return Err(ChannelError::InvalidMessage(
36                "message body is empty".to_owned(),
37            ));
38        }
39        if self.text.contains('\0') {
40            return Err(ChannelError::InvalidMessage(
41                "message text contains NUL".to_owned(),
42            ));
43        }
44        Ok(())
45    }
46}
47
48/// A remote attachment represented by a retrievable URL.
49#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
50pub struct Attachment {
51    pub url: String,
52    pub name: Option<String>,
53    pub mime: Option<String>,
54}
55
56/// Stable destination identity used by both inbound and outbound messages.
57#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
58pub struct MessageTarget {
59    pub channel: ChannelId,
60    pub conversation: ConversationId,
61    pub thread: Option<String>,
62    pub reply_to: Option<String>,
63}
64
65/// A message delivered by a channel adapter.
66#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
67pub struct InboundMessage {
68    pub id: String,
69    pub target: MessageTarget,
70    pub sender: Participant,
71    pub body: MessageBody,
72    pub timestamp_ms: Option<u64>,
73    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
74    pub metadata: BTreeMap<String, String>,
75}
76
77/// A message sent through a channel adapter.
78#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
79pub struct OutboundMessage {
80    pub target: MessageTarget,
81    pub body: MessageBody,
82    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
83    pub metadata: BTreeMap<String, String>,
84}