Skip to main content

plexus_comms/activations/sms/
activation.rs

1use super::providers::{create_provider, SmsProvider};
2use super::types::*;
3use crate::config::SmsConfig;
4use async_stream::stream;
5use futures::Stream;
6use std::sync::Arc;
7
8// Required for macro-generated code
9use plexus_core::plexus;
10use plexus_core::serde_helpers;
11
12#[derive(Clone)]
13pub struct Sms {
14    provider: Arc<Box<dyn SmsProvider>>,
15}
16
17impl Sms {
18    pub async fn new(config: SmsConfig) -> Result<Self, String> {
19        let provider = create_provider(&config)?;
20
21        Ok(Self {
22            provider: Arc::new(provider),
23        })
24    }
25}
26
27#[plexus_macros::hub_methods(
28    namespace = "sms",
29    version = "1.0.0",
30    description = "Send SMS messages via multiple providers (Twilio, SNS, Vonage, MessageBird)"
31)]
32impl Sms {
33    #[plexus_macros::hub_method(
34        description = "Send an SMS message",
35        params(
36            to = "Recipient phone number (E.164 format)",
37            message = "Message content",
38            from = "Sender phone number (optional, uses default if not provided)"
39        )
40    )]
41    async fn send(
42        &self,
43        to: String,
44        message: String,
45        from: Option<String>,
46    ) -> impl Stream<Item = SendSmsEvent> + Send + 'static {
47        let provider = self.provider.clone();
48        let params = SendSmsParams { to, message, from };
49
50        stream! {
51            match provider.send(params).await {
52                Ok(event) => yield event,
53                Err(e) => yield SendSmsEvent::Error {
54                    message: e,
55                    code: None,
56                },
57            }
58        }
59    }
60
61    #[plexus_macros::hub_method(
62        streaming,
63        description = "Send multiple SMS messages with progress tracking",
64        params(messages = "List of SMS messages to send")
65    )]
66    async fn send_batch(
67        &self,
68        messages: Vec<SendSmsParams>,
69    ) -> impl Stream<Item = BatchSendEvent> + Send + 'static {
70        let provider = self.provider.clone();
71        let total = messages.len();
72
73        stream! {
74            let mut sent = 0;
75            let mut failed = 0;
76
77            for (index, sms) in messages.into_iter().enumerate() {
78                let to = sms.to.clone();
79                match provider.send(sms).await {
80                    Ok(SendSmsEvent::Queued { message_id, .. }) |
81                    Ok(SendSmsEvent::Sent { message_id, .. }) => {
82                        sent += 1;
83                        yield BatchSendEvent::SmsSent { index, message_id, to };
84                    }
85                    Ok(SendSmsEvent::Error { message, .. }) | Err(message) => {
86                        failed += 1;
87                        yield BatchSendEvent::SmsFailed { index, to, error: message };
88                    }
89                }
90
91                if (index + 1) % 10 == 0 || index + 1 == total {
92                    yield BatchSendEvent::Progress {
93                        sent,
94                        total,
95                        percentage: ((sent + failed) as f32 / total as f32) * 100.0,
96                    };
97                }
98            }
99
100            yield BatchSendEvent::Complete {
101                total_sent: sent,
102                total_failed: failed,
103            };
104        }
105    }
106
107    #[plexus_macros::hub_method(
108        description = "Check delivery status of an SMS message",
109        params(message_id = "Message ID returned from send")
110    )]
111    async fn check_status(
112        &self,
113        message_id: String,
114    ) -> impl Stream<Item = StatusEvent> + Send + 'static {
115        let provider = self.provider.clone();
116
117        stream! {
118            match provider.check_status(&message_id).await {
119                Ok(status) => yield StatusEvent::Status { message_id, status },
120                Err(e) => yield StatusEvent::Error { message: e },
121            }
122        }
123    }
124}