Skip to main content

chat_system/
channel_type.rs

1//! Channel/platform type definitions and capabilities.
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6
7/// Supported inbound message delivery modes.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum InboundMode {
10    None,
11    Polling,
12    GatewayLoop,
13    SocketMode,
14    Webhook,
15}
16
17/// Capabilities of a particular channel type.
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub struct ChannelCapabilities {
20    pub inbound_mode: InboundMode,
21    pub supports_outbound: bool,
22    pub supports_streaming: bool,
23    pub supports_interactive: bool,
24    pub supports_threads: bool,
25    pub supports_voice_ingest: bool,
26    pub supports_pairing: bool,
27    pub supports_otp: bool,
28    pub supports_reactions: bool,
29    pub supports_location: bool,
30}
31
32/// Descriptor combining a channel type with its display name and capabilities.
33#[derive(Debug, Clone, Copy)]
34pub struct ChannelDescriptor {
35    pub channel_type: ChannelType,
36    pub display_name: &'static str,
37    pub capabilities: ChannelCapabilities,
38}
39
40/// All supported chat platform / channel types.
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
42#[serde(rename_all = "lowercase")]
43pub enum ChannelType {
44    Telegram,
45    Whatsapp,
46    #[serde(rename = "msteams")]
47    MsTeams,
48    Discord,
49    Slack,
50    Irc,
51    Matrix,
52    Signal,
53    GoogleChat,
54    IMessage,
55    Console,
56    Webhook,
57}
58
59impl ChannelType {
60    pub const ALL: &'static [ChannelType] = &[
61        ChannelType::Telegram,
62        ChannelType::Whatsapp,
63        ChannelType::MsTeams,
64        ChannelType::Discord,
65        ChannelType::Slack,
66        ChannelType::Irc,
67        ChannelType::Matrix,
68        ChannelType::Signal,
69        ChannelType::GoogleChat,
70        ChannelType::IMessage,
71        ChannelType::Console,
72        ChannelType::Webhook,
73    ];
74
75    pub fn as_str(&self) -> &'static str {
76        match self {
77            ChannelType::Telegram => "telegram",
78            ChannelType::Whatsapp => "whatsapp",
79            ChannelType::MsTeams => "msteams",
80            ChannelType::Discord => "discord",
81            ChannelType::Slack => "slack",
82            ChannelType::Irc => "irc",
83            ChannelType::Matrix => "matrix",
84            ChannelType::Signal => "signal",
85            ChannelType::GoogleChat => "googlechat",
86            ChannelType::IMessage => "imessage",
87            ChannelType::Console => "console",
88            ChannelType::Webhook => "webhook",
89        }
90    }
91
92    pub fn display_name(&self) -> &'static str {
93        match self {
94            ChannelType::Telegram => "Telegram",
95            ChannelType::Whatsapp => "WhatsApp",
96            ChannelType::MsTeams => "Microsoft Teams",
97            ChannelType::Discord => "Discord",
98            ChannelType::Slack => "Slack",
99            ChannelType::Irc => "IRC",
100            ChannelType::Matrix => "Matrix",
101            ChannelType::Signal => "Signal",
102            ChannelType::GoogleChat => "Google Chat",
103            ChannelType::IMessage => "iMessage",
104            ChannelType::Console => "Console",
105            ChannelType::Webhook => "Webhook",
106        }
107    }
108
109    pub fn descriptor(&self) -> ChannelDescriptor {
110        let caps = match self {
111            ChannelType::Telegram => ChannelCapabilities {
112                inbound_mode: InboundMode::Polling,
113                supports_outbound: true,
114                supports_streaming: true,
115                supports_interactive: false,
116                supports_threads: false,
117                supports_voice_ingest: true,
118                supports_pairing: false,
119                supports_otp: true,
120                supports_reactions: false,
121                supports_location: true,
122            },
123            ChannelType::Whatsapp => ChannelCapabilities {
124                inbound_mode: InboundMode::GatewayLoop,
125                supports_outbound: true,
126                supports_streaming: true,
127                supports_interactive: false,
128                supports_threads: false,
129                supports_voice_ingest: true,
130                supports_pairing: true,
131                supports_otp: true,
132                supports_reactions: false,
133                supports_location: false,
134            },
135            ChannelType::MsTeams => ChannelCapabilities {
136                inbound_mode: InboundMode::Webhook,
137                supports_outbound: true,
138                supports_streaming: true,
139                supports_interactive: false,
140                supports_threads: false,
141                supports_voice_ingest: false,
142                supports_pairing: false,
143                supports_otp: false,
144                supports_reactions: false,
145                supports_location: true,
146            },
147            ChannelType::Discord => ChannelCapabilities {
148                inbound_mode: InboundMode::GatewayLoop,
149                supports_outbound: true,
150                supports_streaming: true,
151                supports_interactive: true,
152                supports_threads: true,
153                supports_voice_ingest: false,
154                supports_pairing: false,
155                supports_otp: false,
156                supports_reactions: false,
157                supports_location: true,
158            },
159            ChannelType::Slack => ChannelCapabilities {
160                inbound_mode: InboundMode::SocketMode,
161                supports_outbound: true,
162                supports_streaming: true,
163                supports_interactive: true,
164                supports_threads: true,
165                supports_voice_ingest: false,
166                supports_pairing: false,
167                supports_otp: false,
168                supports_reactions: true,
169                supports_location: false,
170            },
171            ChannelType::Irc => ChannelCapabilities {
172                inbound_mode: InboundMode::GatewayLoop,
173                supports_outbound: true,
174                supports_streaming: false,
175                supports_interactive: false,
176                supports_threads: false,
177                supports_voice_ingest: false,
178                supports_pairing: false,
179                supports_otp: false,
180                supports_reactions: false,
181                supports_location: false,
182            },
183            ChannelType::Matrix => ChannelCapabilities {
184                inbound_mode: InboundMode::GatewayLoop,
185                supports_outbound: true,
186                supports_streaming: true,
187                supports_interactive: false,
188                supports_threads: true,
189                supports_voice_ingest: false,
190                supports_pairing: false,
191                supports_otp: false,
192                supports_reactions: true,
193                supports_location: false,
194            },
195            ChannelType::Signal => ChannelCapabilities {
196                inbound_mode: InboundMode::GatewayLoop,
197                supports_outbound: true,
198                supports_streaming: false,
199                supports_interactive: false,
200                supports_threads: false,
201                supports_voice_ingest: true,
202                supports_pairing: false,
203                supports_otp: false,
204                supports_reactions: false,
205                supports_location: false,
206            },
207            ChannelType::GoogleChat => ChannelCapabilities {
208                inbound_mode: InboundMode::Webhook,
209                supports_outbound: true,
210                supports_streaming: false,
211                supports_interactive: false,
212                supports_threads: false,
213                supports_voice_ingest: false,
214                supports_pairing: false,
215                supports_otp: false,
216                supports_reactions: false,
217                supports_location: false,
218            },
219            ChannelType::IMessage => ChannelCapabilities {
220                inbound_mode: InboundMode::Polling,
221                supports_outbound: true,
222                supports_streaming: false,
223                supports_interactive: false,
224                supports_threads: false,
225                supports_voice_ingest: false,
226                supports_pairing: false,
227                supports_otp: false,
228                supports_reactions: false,
229                supports_location: false,
230            },
231            ChannelType::Console => ChannelCapabilities {
232                inbound_mode: InboundMode::None,
233                supports_outbound: true,
234                supports_streaming: false,
235                supports_interactive: false,
236                supports_threads: false,
237                supports_voice_ingest: false,
238                supports_pairing: false,
239                supports_otp: false,
240                supports_reactions: false,
241                supports_location: false,
242            },
243            ChannelType::Webhook => ChannelCapabilities {
244                inbound_mode: InboundMode::None,
245                supports_outbound: true,
246                supports_streaming: false,
247                supports_interactive: false,
248                supports_threads: false,
249                supports_voice_ingest: false,
250                supports_pairing: false,
251                supports_otp: false,
252                supports_reactions: false,
253                supports_location: false,
254            },
255        };
256        ChannelDescriptor {
257            channel_type: *self,
258            display_name: self.display_name(),
259            capabilities: caps,
260        }
261    }
262}
263
264impl fmt::Display for ChannelType {
265    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266        f.write_str(self.as_str())
267    }
268}
269
270impl FromStr for ChannelType {
271    type Err = anyhow::Error;
272
273    fn from_str(s: &str) -> Result<Self, Self::Err> {
274        match s.to_lowercase().as_str() {
275            "telegram" => Ok(ChannelType::Telegram),
276            "whatsapp" => Ok(ChannelType::Whatsapp),
277            "msteams" | "teams" | "microsoft teams" => Ok(ChannelType::MsTeams),
278            "discord" => Ok(ChannelType::Discord),
279            "slack" => Ok(ChannelType::Slack),
280            "irc" => Ok(ChannelType::Irc),
281            "matrix" => Ok(ChannelType::Matrix),
282            "signal" => Ok(ChannelType::Signal),
283            "googlechat" | "google chat" => Ok(ChannelType::GoogleChat),
284            "imessage" => Ok(ChannelType::IMessage),
285            "console" => Ok(ChannelType::Console),
286            "webhook" => Ok(ChannelType::Webhook),
287            other => Err(anyhow::anyhow!("unknown channel type: {}", other)),
288        }
289    }
290}