1use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6
7#[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#[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 pub supports_editing: bool,
32 pub supports_deletion: bool,
34 pub supports_file_upload: bool,
36 pub max_message_length: usize,
38}
39
40#[derive(Debug, Clone, Copy)]
42pub struct ChannelDescriptor {
43 pub channel_type: ChannelType,
44 pub display_name: &'static str,
45 pub capabilities: ChannelCapabilities,
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
50#[serde(rename_all = "lowercase")]
51pub enum ChannelType {
52 Telegram,
53 Whatsapp,
54 #[serde(rename = "msteams")]
55 MsTeams,
56 Discord,
57 Slack,
58 Irc,
59 Matrix,
60 Signal,
61 GoogleChat,
62 IMessage,
63 Console,
64 Webhook,
65}
66
67impl ChannelType {
68 pub const ALL: &'static [ChannelType] = &[
69 ChannelType::Telegram,
70 ChannelType::Whatsapp,
71 ChannelType::MsTeams,
72 ChannelType::Discord,
73 ChannelType::Slack,
74 ChannelType::Irc,
75 ChannelType::Matrix,
76 ChannelType::Signal,
77 ChannelType::GoogleChat,
78 ChannelType::IMessage,
79 ChannelType::Console,
80 ChannelType::Webhook,
81 ];
82
83 pub fn as_str(&self) -> &'static str {
84 match self {
85 ChannelType::Telegram => "telegram",
86 ChannelType::Whatsapp => "whatsapp",
87 ChannelType::MsTeams => "msteams",
88 ChannelType::Discord => "discord",
89 ChannelType::Slack => "slack",
90 ChannelType::Irc => "irc",
91 ChannelType::Matrix => "matrix",
92 ChannelType::Signal => "signal",
93 ChannelType::GoogleChat => "googlechat",
94 ChannelType::IMessage => "imessage",
95 ChannelType::Console => "console",
96 ChannelType::Webhook => "webhook",
97 }
98 }
99
100 pub fn display_name(&self) -> &'static str {
101 match self {
102 ChannelType::Telegram => "Telegram",
103 ChannelType::Whatsapp => "WhatsApp",
104 ChannelType::MsTeams => "Microsoft Teams",
105 ChannelType::Discord => "Discord",
106 ChannelType::Slack => "Slack",
107 ChannelType::Irc => "IRC",
108 ChannelType::Matrix => "Matrix",
109 ChannelType::Signal => "Signal",
110 ChannelType::GoogleChat => "Google Chat",
111 ChannelType::IMessage => "iMessage",
112 ChannelType::Console => "Console",
113 ChannelType::Webhook => "Webhook",
114 }
115 }
116
117 pub fn descriptor(&self) -> ChannelDescriptor {
118 let caps = match self {
119 ChannelType::Telegram => ChannelCapabilities {
120 inbound_mode: InboundMode::Polling,
121 supports_outbound: true,
122 supports_streaming: true,
123 supports_interactive: false,
124 supports_threads: false,
125 supports_voice_ingest: true,
126 supports_pairing: false,
127 supports_otp: true,
128 supports_reactions: true,
129 supports_location: true,
130 supports_editing: true,
131 supports_deletion: true,
132 supports_file_upload: true,
133 max_message_length: 4096,
134 },
135 ChannelType::Whatsapp => ChannelCapabilities {
136 inbound_mode: InboundMode::GatewayLoop,
137 supports_outbound: true,
138 supports_streaming: true,
139 supports_interactive: false,
140 supports_threads: false,
141 supports_voice_ingest: true,
142 supports_pairing: true,
143 supports_otp: true,
144 supports_reactions: true,
145 supports_location: false,
146 supports_editing: true,
147 supports_deletion: true,
148 supports_file_upload: true,
149 max_message_length: 65536,
150 },
151 ChannelType::MsTeams => ChannelCapabilities {
152 inbound_mode: InboundMode::Webhook,
153 supports_outbound: true,
154 supports_streaming: true,
155 supports_interactive: false,
156 supports_threads: false,
157 supports_voice_ingest: false,
158 supports_pairing: false,
159 supports_otp: false,
160 supports_reactions: true,
161 supports_location: true,
162 supports_editing: true,
163 supports_deletion: true,
164 supports_file_upload: true,
165 max_message_length: 28000,
166 },
167 ChannelType::Discord => ChannelCapabilities {
168 inbound_mode: InboundMode::GatewayLoop,
169 supports_outbound: true,
170 supports_streaming: true,
171 supports_interactive: true,
172 supports_threads: true,
173 supports_voice_ingest: false,
174 supports_pairing: false,
175 supports_otp: false,
176 supports_reactions: true,
177 supports_location: true,
178 supports_editing: true,
179 supports_deletion: true,
180 supports_file_upload: true,
181 max_message_length: 2000,
182 },
183 ChannelType::Slack => ChannelCapabilities {
184 inbound_mode: InboundMode::SocketMode,
185 supports_outbound: true,
186 supports_streaming: true,
187 supports_interactive: true,
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 supports_editing: true,
195 supports_deletion: true,
196 supports_file_upload: true,
197 max_message_length: 40000,
198 },
199 ChannelType::Irc => ChannelCapabilities {
200 inbound_mode: InboundMode::GatewayLoop,
201 supports_outbound: true,
202 supports_streaming: false,
203 supports_interactive: false,
204 supports_threads: false,
205 supports_voice_ingest: false,
206 supports_pairing: false,
207 supports_otp: false,
208 supports_reactions: false,
209 supports_location: false,
210 supports_editing: false,
211 supports_deletion: false,
212 supports_file_upload: false,
213 max_message_length: 512,
214 },
215 ChannelType::Matrix => ChannelCapabilities {
216 inbound_mode: InboundMode::GatewayLoop,
217 supports_outbound: true,
218 supports_streaming: true,
219 supports_interactive: false,
220 supports_threads: true,
221 supports_voice_ingest: false,
222 supports_pairing: false,
223 supports_otp: false,
224 supports_reactions: true,
225 supports_location: false,
226 supports_editing: true,
227 supports_deletion: true,
228 supports_file_upload: true,
229 max_message_length: 65536,
230 },
231 ChannelType::Signal => ChannelCapabilities {
232 inbound_mode: InboundMode::GatewayLoop,
233 supports_outbound: true,
234 supports_streaming: false,
235 supports_interactive: false,
236 supports_threads: false,
237 supports_voice_ingest: true,
238 supports_pairing: false,
239 supports_otp: false,
240 supports_reactions: true,
241 supports_location: false,
242 supports_editing: false,
243 supports_deletion: true,
244 supports_file_upload: true,
245 max_message_length: 0,
246 },
247 ChannelType::GoogleChat => ChannelCapabilities {
248 inbound_mode: InboundMode::Webhook,
249 supports_outbound: true,
250 supports_streaming: false,
251 supports_interactive: false,
252 supports_threads: false,
253 supports_voice_ingest: false,
254 supports_pairing: false,
255 supports_otp: false,
256 supports_reactions: true,
257 supports_location: false,
258 supports_editing: true,
259 supports_deletion: true,
260 supports_file_upload: true,
261 max_message_length: 4096,
262 },
263 ChannelType::IMessage => ChannelCapabilities {
264 inbound_mode: InboundMode::Polling,
265 supports_outbound: true,
266 supports_streaming: false,
267 supports_interactive: false,
268 supports_threads: false,
269 supports_voice_ingest: false,
270 supports_pairing: false,
271 supports_otp: false,
272 supports_reactions: true,
273 supports_location: false,
274 supports_editing: false,
275 supports_deletion: false,
276 supports_file_upload: true,
277 max_message_length: 0,
278 },
279 ChannelType::Console => ChannelCapabilities {
280 inbound_mode: InboundMode::None,
281 supports_outbound: true,
282 supports_streaming: false,
283 supports_interactive: false,
284 supports_threads: false,
285 supports_voice_ingest: false,
286 supports_pairing: false,
287 supports_otp: false,
288 supports_reactions: false,
289 supports_location: false,
290 supports_editing: false,
291 supports_deletion: false,
292 supports_file_upload: false,
293 max_message_length: 0,
294 },
295 ChannelType::Webhook => ChannelCapabilities {
296 inbound_mode: InboundMode::None,
297 supports_outbound: true,
298 supports_streaming: false,
299 supports_interactive: false,
300 supports_threads: false,
301 supports_voice_ingest: false,
302 supports_pairing: false,
303 supports_otp: false,
304 supports_reactions: false,
305 supports_location: false,
306 supports_editing: false,
307 supports_deletion: false,
308 supports_file_upload: false,
309 max_message_length: 0,
310 },
311 };
312 ChannelDescriptor {
313 channel_type: *self,
314 display_name: self.display_name(),
315 capabilities: caps,
316 }
317 }
318}
319
320impl fmt::Display for ChannelType {
321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
322 f.write_str(self.as_str())
323 }
324}
325
326impl FromStr for ChannelType {
327 type Err = anyhow::Error;
328
329 fn from_str(s: &str) -> Result<Self, Self::Err> {
330 match s.to_lowercase().as_str() {
331 "telegram" => Ok(ChannelType::Telegram),
332 "whatsapp" => Ok(ChannelType::Whatsapp),
333 "msteams" | "teams" | "microsoft teams" => Ok(ChannelType::MsTeams),
334 "discord" => Ok(ChannelType::Discord),
335 "slack" => Ok(ChannelType::Slack),
336 "irc" => Ok(ChannelType::Irc),
337 "matrix" => Ok(ChannelType::Matrix),
338 "signal" => Ok(ChannelType::Signal),
339 "googlechat" | "google chat" => Ok(ChannelType::GoogleChat),
340 "imessage" => Ok(ChannelType::IMessage),
341 "console" => Ok(ChannelType::Console),
342 "webhook" => Ok(ChannelType::Webhook),
343 other => Err(anyhow::anyhow!("unknown channel type: {}", other)),
344 }
345 }
346}