plexus_comms/activations/sms/
activation.rs1use super::providers::{create_provider, SmsProvider};
2use super::types::*;
3use crate::config::SmsConfig;
4use async_stream::stream;
5use futures::Stream;
6use std::sync::Arc;
7
8use 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}