chasm_cli/integrations/
communication.rs

1// Copyright (c) 2024-2026 Nervosys LLC
2// SPDX-License-Identifier: Apache-2.0
3//! Communication Integrations
4//!
5//! Slack, Discord, Teams, Telegram, SMS, Email
6
7use super::IntegrationResult;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11// =============================================================================
12// Common Types
13// =============================================================================
14
15/// Chat message
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct ChatMessage {
18    pub id: String,
19    pub channel_id: String,
20    pub author: ChatUser,
21    pub content: String,
22    pub timestamp: String,
23    pub thread_id: Option<String>,
24    pub attachments: Vec<ChatAttachment>,
25    pub reactions: Vec<Reaction>,
26    pub edited: bool,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct ChatUser {
31    pub id: String,
32    pub username: String,
33    pub display_name: Option<String>,
34    pub avatar_url: Option<String>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct ChatAttachment {
39    pub id: String,
40    pub filename: String,
41    pub url: String,
42    pub mime_type: Option<String>,
43    pub size: Option<u64>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct Reaction {
48    pub emoji: String,
49    pub count: u32,
50    pub users: Vec<String>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct Channel {
55    pub id: String,
56    pub name: String,
57    pub topic: Option<String>,
58    pub is_private: bool,
59    pub is_archived: bool,
60    pub member_count: Option<u32>,
61}
62
63// =============================================================================
64// Slack
65// =============================================================================
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct SlackConfig {
69    pub workspace: String,
70    pub bot_token: String,
71    pub user_token: Option<String>,
72}
73
74/// Slack provider trait
75#[async_trait::async_trait]
76pub trait SlackProvider: Send + Sync {
77    async fn send_message(
78        &self,
79        channel: &str,
80        text: &str,
81        thread_ts: Option<&str>,
82    ) -> IntegrationResult;
83    async fn list_channels(&self) -> IntegrationResult;
84    async fn list_messages(&self, channel: &str, limit: u32) -> IntegrationResult;
85    async fn upload_file(
86        &self,
87        channel: &str,
88        file_path: &str,
89        comment: Option<&str>,
90    ) -> IntegrationResult;
91    async fn set_status(&self, status_text: &str, status_emoji: &str) -> IntegrationResult;
92    async fn search_messages(&self, query: &str) -> IntegrationResult;
93    async fn add_reaction(&self, channel: &str, timestamp: &str, emoji: &str) -> IntegrationResult;
94    async fn get_user(&self, user_id: &str) -> IntegrationResult;
95}
96
97// =============================================================================
98// Discord
99// =============================================================================
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct DiscordConfig {
103    pub bot_token: String,
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct DiscordGuild {
108    pub id: String,
109    pub name: String,
110    pub icon: Option<String>,
111    pub owner_id: String,
112    pub member_count: Option<u32>,
113}
114
115/// Discord provider trait
116#[async_trait::async_trait]
117pub trait DiscordProvider: Send + Sync {
118    async fn send_message(&self, channel_id: &str, content: &str) -> IntegrationResult;
119    async fn list_guilds(&self) -> IntegrationResult;
120    async fn list_channels(&self, guild_id: &str) -> IntegrationResult;
121    async fn list_messages(&self, channel_id: &str, limit: u32) -> IntegrationResult;
122    async fn add_reaction(
123        &self,
124        channel_id: &str,
125        message_id: &str,
126        emoji: &str,
127    ) -> IntegrationResult;
128    async fn create_thread(
129        &self,
130        channel_id: &str,
131        name: &str,
132        message_id: Option<&str>,
133    ) -> IntegrationResult;
134}
135
136// =============================================================================
137// Microsoft Teams
138// =============================================================================
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct TeamsConfig {
142    pub tenant_id: String,
143    pub client_id: String,
144    pub client_secret: String,
145}
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct TeamsTeam {
149    pub id: String,
150    pub display_name: String,
151    pub description: Option<String>,
152}
153
154/// Teams provider trait
155#[async_trait::async_trait]
156pub trait TeamsProvider: Send + Sync {
157    async fn send_message(
158        &self,
159        team_id: &str,
160        channel_id: &str,
161        content: &str,
162    ) -> IntegrationResult;
163    async fn list_teams(&self) -> IntegrationResult;
164    async fn list_channels(&self, team_id: &str) -> IntegrationResult;
165    async fn create_meeting(
166        &self,
167        subject: &str,
168        start: &str,
169        end: &str,
170        attendees: &[String],
171    ) -> IntegrationResult;
172    async fn get_presence(&self, user_id: &str) -> IntegrationResult;
173    async fn set_presence(&self, availability: &str, activity: &str) -> IntegrationResult;
174}
175
176// =============================================================================
177// Telegram
178// =============================================================================
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct TelegramConfig {
182    pub bot_token: String,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct TelegramChat {
187    pub id: i64,
188    pub chat_type: String,
189    pub title: Option<String>,
190    pub username: Option<String>,
191}
192
193/// Telegram provider trait
194#[async_trait::async_trait]
195pub trait TelegramProvider: Send + Sync {
196    async fn send_message(&self, chat_id: &str, text: &str) -> IntegrationResult;
197    async fn send_photo(
198        &self,
199        chat_id: &str,
200        photo_path: &str,
201        caption: Option<&str>,
202    ) -> IntegrationResult;
203    async fn send_document(
204        &self,
205        chat_id: &str,
206        file_path: &str,
207        caption: Option<&str>,
208    ) -> IntegrationResult;
209    async fn get_updates(&self, offset: Option<i64>) -> IntegrationResult;
210    async fn set_webhook(&self, url: &str) -> IntegrationResult;
211}
212
213// =============================================================================
214// SMS
215// =============================================================================
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct SmsConfig {
219    pub provider: SmsProvider,
220    pub account_sid: String,
221    pub auth_token: String,
222    pub from_number: String,
223}
224
225#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
226#[serde(rename_all = "lowercase")]
227pub enum SmsProvider {
228    Twilio,
229    Vonage,
230    MessageBird,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct SmsMessage {
235    pub id: String,
236    pub from: String,
237    pub to: String,
238    pub body: String,
239    pub status: SmsStatus,
240    pub timestamp: String,
241}
242
243#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
244#[serde(rename_all = "lowercase")]
245pub enum SmsStatus {
246    Queued,
247    Sent,
248    Delivered,
249    Failed,
250}
251
252/// SMS provider trait
253#[async_trait::async_trait]
254pub trait SmsProviderTrait: Send + Sync {
255    async fn send_sms(&self, to: &str, body: &str) -> IntegrationResult;
256    async fn get_messages(&self, limit: u32) -> IntegrationResult;
257}
258
259// =============================================================================
260// Voice (Alexa, Google Assistant, Siri)
261// =============================================================================
262
263#[derive(Debug, Clone, Serialize, Deserialize)]
264pub struct VoiceCommand {
265    pub text: String,
266    pub intent: Option<String>,
267    pub slots: HashMap<String, String>,
268    pub confidence: f32,
269}
270
271/// Voice assistant provider trait
272#[async_trait::async_trait]
273pub trait VoiceProvider: Send + Sync {
274    async fn speak(&self, text: &str) -> IntegrationResult;
275    async fn listen(&self) -> IntegrationResult;
276    async fn process_command(&self, command: &VoiceCommand) -> IntegrationResult;
277}
278
279// =============================================================================
280// Notifications
281// =============================================================================
282
283#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct Notification {
285    pub title: String,
286    pub body: String,
287    pub icon: Option<String>,
288    pub sound: Option<String>,
289    pub badge: Option<u32>,
290    pub actions: Vec<NotificationAction>,
291    pub data: Option<HashMap<String, String>>,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct NotificationAction {
296    pub id: String,
297    pub title: String,
298    pub destructive: bool,
299}
300
301/// Notifications provider trait
302#[async_trait::async_trait]
303pub trait NotificationsProvider: Send + Sync {
304    async fn send(&self, notification: &Notification) -> IntegrationResult;
305    async fn schedule(&self, notification: &Notification, at: &str) -> IntegrationResult;
306    async fn cancel(&self, notification_id: &str) -> IntegrationResult;
307}