asterisk_ari/
client.rs

1use crate::{apis, ws};
2use futures_util::StreamExt;
3use std::collections::HashMap;
4use std::future::Future;
5use std::ops::Deref;
6use std::pin::Pin;
7use std::sync::Arc;
8use tracing::debug;
9
10type Handler = Arc<
11    dyn Fn(Arc<apis::client::Client>, ws::models::Event) -> Pin<Box<dyn Future<Output = ()> + Send>>
12        + Send
13        + Sync,
14>;
15
16/// `AriClient` is a client for interacting with the Asterisk REST Interface (ARI).
17/// It manages the connection to the ARI and handles events.
18#[derive(Clone)]
19pub struct AriClient {
20    client: Arc<apis::client::Client>,
21    ws: Arc<ws::client::Client>,
22    event_handlers: HashMap<String, Handler>,
23}
24
25impl AriClient {
26    /// Creates a new `AriClient` with the given configuration.
27    ///
28    /// # Arguments
29    ///
30    /// * `config` - A configuration object for the ARI client.
31    ///
32    /// # Returns
33    ///
34    /// A new instance of `AriClient`.
35    pub fn with_config(config: crate::config::Config) -> Self {
36        AriClient {
37            client: Arc::new(apis::client::Client::with_config(config.clone())),
38            ws: Arc::new(ws::client::Client::with_config(config)),
39            event_handlers: HashMap::new(),
40        }
41    }
42
43    /// Registers a handler for unknown events.
44    ///
45    /// # Arguments
46    ///
47    /// * `handler` - A function that handles unknown events.
48    ///
49    /// # Returns
50    ///
51    /// A mutable reference to the `AriClient`.
52    pub fn on_unknown_event<F, Fut>(&mut self, handler: F) -> &mut Self
53    where
54        F: Fn(Arc<apis::client::Client>, ws::models::Event) -> Fut + Send + Sync + 'static,
55        Fut: Future<Output = ()> + Send + 'static,
56    {
57        self.event_handlers.insert(
58            "Unknown".to_string(),
59            Arc::new(move |client, event| Box::pin(handler(client, event))),
60        );
61        self
62    }
63
64    /// Registers a handler for a specific event.
65    ///
66    /// # Arguments
67    ///
68    /// * `key` - The event type as a string.
69    /// * `handler` - A function that handles the event.
70    ///
71    /// # Returns
72    ///
73    /// A mutable reference to the `AriClient`.
74    pub fn on_event<F, Fut>(&mut self, key: String, handler: F) -> &mut Self
75    where
76        F: Fn(Arc<apis::client::Client>, ws::models::Event) -> Fut + Send + Sync + 'static,
77        Fut: Future<Output = ()> + Send + 'static,
78    {
79        self.event_handlers.insert(
80            key,
81            Arc::new(move |client, event| Box::pin(handler(client, event))),
82        );
83        self
84    }
85
86    /// Starts the ARI client and begins listening for events.
87    ///
88    /// # Arguments
89    ///
90    /// * `application_name` - The name of the ARI application.
91    ///
92    /// # Returns
93    ///
94    /// A `Result` indicating success or failure.
95    pub async fn start(&self, application_name: String) -> crate::errors::Result<()> {
96        let mut stream = self
97            .ws
98            .connect(ws::params::ListenRequest::new(application_name))
99            .await?;
100
101        while let Some(event) = stream.next().await {
102            if let Some(handler) = self.event_handlers.get(&event.to_string()) {
103                handler(self.client.clone(), event).await;
104            } else {
105                // Log or handle unmatched events if necessary
106                debug!(
107                    "No handler registered for event type: {}",
108                    event.to_string()
109                );
110            }
111        }
112
113        Ok(())
114    }
115
116    /// Stops the ARI client.
117    pub fn stop(&self) {
118        self.ws.disconnect();
119    }
120
121    /// Returns a reference to the WebSocket client.
122    ///
123    /// # Returns
124    ///
125    /// A reference to the WebSocket client.
126    pub fn ws(&self) -> &ws::client::Client {
127        &self.ws
128    }
129
130    /// Returns a reference to the API client.
131    ///
132    /// # Returns
133    ///
134    /// A reference to the API client.
135    pub fn client(&self) -> &apis::client::Client {
136        &self.client
137    }
138}
139
140impl Deref for AriClient {
141    type Target = apis::client::Client;
142
143    /// Dereferences the `AriClient` to the underlying API client.
144    ///
145    /// # Returns
146    ///
147    /// A reference to the API client.
148    fn deref(&self) -> &Self::Target {
149        &self.client
150    }
151}
152
153/// Macro to create event handler methods for specific events.
154macro_rules! create_event_handler {
155    ($($event_name:ident => $event_variant:ident),*) => {
156        impl AriClient {
157            $(
158                /// Registers a handler for the `$event_variant` event.
159                ///
160                /// # Arguments
161                ///
162                /// * `handler` - A function that handles the event.
163                ///
164                /// # Returns
165                ///
166                /// A mutable reference to the `AriClient`.
167                pub fn $event_name<F, Fut>(&mut self, handler: F) -> &mut Self
168                where
169                    F: Fn(Arc<apis::client::Client>, ws::models::BaseEvent<ws::models::$event_variant>) -> Fut
170                        + Send
171                        + Sync
172                        + 'static,
173                    Fut: Future<Output = ()> + Send + 'static,
174                {
175                    let handler = Arc::new(handler); // Wrap handler in Arc for shared ownership
176
177                    self.on_event(stringify!($event_variant).to_string(), move |client, event| {
178                        let handler = handler.clone(); // Clone Arc for use in the async block
179                        async move {
180                            if let ws::models::Event::$event_variant(e) = event {
181                                handler(client, e).await;
182                            } else {
183                                unreachable!(); // Ensure safety for mismatched events
184                            }
185                        }
186                    });
187
188                    self
189                }
190            )*
191        }
192    };
193}
194
195create_event_handler!(
196    on_application_move_failed => ApplicationMoveFailed,
197    on_application_replaced => ApplicationReplaced,
198    on_bridge_attended_transfer => BridgeAttendedTransfer,
199    on_bridge_blind_transfer => BridgeBlindTransfer,
200    on_bridge_created => BridgeCreated,
201    on_bridge_destroyed => BridgeDestroyed,
202    on_bridge_merged => BridgeMerged,
203    on_bridge_video_source_changed => BridgeVideoSourceChanged,
204    on_channel_caller_id => ChannelCallerId,
205    on_channel_connected_line => ChannelConnectedLine,
206    on_channel_created => ChannelCreated,
207    on_channel_destroyed => ChannelDestroyed,
208    on_channel_dialplan => ChannelDialplan,
209    on_channel_dtmf_received => ChannelDtmfReceived,
210    on_channel_entered_bridge => ChannelEnteredBridge,
211    on_channel_hangup_request => ChannelHangupRequest,
212    on_channel_hold => ChannelHold,
213    on_channel_left_bridge => ChannelLeftBridge,
214    on_channel_state_change => ChannelStateChange,
215    on_channel_talking_finished => ChannelTalkingFinished,
216    on_channel_talking_started => ChannelTalkingStarted,
217    on_channel_tone_detected => ChannelToneDetected,
218    on_channel_unhold => ChannelUnhold,
219    on_channel_user_event => ChannelUserEvent,
220    on_channel_var_set => ChannelVarSet,
221    on_contact_info => ContactInfo,
222    on_contact_status_change => ContactStatusChange,
223    on_device_state_changed => DeviceStateChanged,
224    on_dial => Dial,
225    on_endpoint_state_change => EndpointStateChange,
226    on_missing_params => MissingParams,
227    on_peer => Peer,
228    on_peer_status_change => PeerStatusChange,
229    on_playback_continuing => PlaybackContinuing,
230    on_playback_finished => PlaybackFinished,
231    on_playback_started => PlaybackStarted,
232    on_recording_failed => RecordingFailed,
233    on_recording_finished => RecordingFinished,
234    on_recording_started => RecordingStarted,
235    on_stasis_end => StasisEnd,
236    on_stasis_start => StasisStart,
237    on_text_message_received => TextMessageReceived
238);