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}
31
32#[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#[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}