1#![deny(missing_docs)]
5#![deny(unsafe_code)]
6#![warn(clippy::all, clippy::pedantic)]
7
8use crate::error::*;
9
10pub mod config;
11pub mod error;
12pub mod types;
13
14#[cfg(feature = "http")]
15pub mod http;
16
17#[cfg(feature = "websocket")]
18pub mod ws;
19
20#[derive(Clone, Debug)]
22pub struct Client {
23
24 #[cfg(feature = "http")]
25 http: Option<std::sync::Arc<http::HttpClient>>,
26
27 #[cfg(feature = "websocket")]
28 ws_client: std::sync::Arc<tokio::sync::RwLock<Option<ws::WebsocketClient>>>,
29
30 #[cfg(feature = "websocket")]
31 ws_config: Option<config::WebsocketConfig>
32}
33impl Client {
34
35 pub fn new(config: config::ClientConfig) -> ClientResult<Self> {
37 Ok(Self {
38
39 #[cfg(feature = "http")]
40 http: config.http.map(|config| http::HttpClient::new(config).map(std::sync::Arc::new)).transpose()?,
41
42 #[cfg(feature = "websocket")]
43 ws_client: std::sync::Arc::new(tokio::sync::RwLock::new(None)),
44
45 #[cfg(feature = "websocket")]
46 ws_config: config.websocket
47 })
48 }
49
50 #[cfg(feature = "http")]
52 pub fn http(&self) -> ClientResult<&http::HttpClient> {
53 match &self.http {
54 Some(http) => Ok(http),
55 None => Err(ClientError::MissingConfiguration("HttpClient"))
56 }
57 }
58
59 #[cfg(feature = "http")]
61 pub fn http_arc(&self) -> ClientResult<std::sync::Arc<http::HttpClient>> {
62 match &self.http {
63 Some(http) => Ok(http.clone()),
64 None => Err(ClientError::MissingConfiguration("HttpClient"))
65 }
66 }
67
68 #[cfg(feature = "websocket")]
94 pub async fn on_message<F>(&self, callback: F) -> ClientResult<()>
95 where
96 F: Fn(ws::types::WebsocketMessage, std::sync::Arc<Self>) + Send + Sync + 'static,
97 {
98 let mut ws_guard = self.create_or_get_ws_client().await?;
99 if let Some(ws_client) = ws_guard.as_mut() {
100 let client = std::sync::Arc::new(self.clone());
101 ws_client.on_message(move |msg| {
102 callback(msg, std::sync::Arc::clone(&client));
103 });
104 }
105 Ok(())
106 }
107
108 #[cfg(feature = "websocket")]
130 pub async fn on_message_simple<F>(&self, callback: F) -> ClientResult<()>
131 where
132 F: Fn(ws::types::WebsocketMessage) + Send + Sync + 'static,
133 {
134 let mut ws_guard = self.create_or_get_ws_client().await?;
135 if let Some(ws_client) = ws_guard.as_mut() {
136 ws_client.on_message(callback);
137 }
138 Ok(())
139 }
140
141 #[cfg(feature = "websocket")]
143 pub async fn start_background_websocket(&self) -> ClientResult<()> {
144 let mut ws_guard = self.create_or_get_ws_client().await?;
145 if let Some(ws_client) = ws_guard.as_mut() {
146 ws_client.start_background().await?;
147 }
148 Ok(())
149 }
150
151 #[cfg(feature = "websocket")]
153 pub async fn start_blocking_websocket(&self) -> ClientResult<()> {
154 let mut ws_guard = self.create_or_get_ws_client().await?;
155 if let Some(ws_client) = ws_guard.as_mut() {
156 ws_client.start_blocking().await?;
157 }
158 Ok(())
159 }
160
161 #[cfg(feature = "websocket")]
163 pub async fn stop_background_websocket(&self) -> ClientResult<()> {
164 let mut ws_guard = self.ws_client.write().await;
165
166 if let Some(ws_client) = ws_guard.as_mut() {
167 ws_client.stop_background().await?;
168 }
169
170 Ok(())
171 }
172
173 #[cfg(feature = "websocket")]
175 pub async fn is_websocket_connected(&self) -> bool {
176 let ws_guard = self.ws_client.read().await;
177
178 if let Some(ws_client) = ws_guard.as_ref() {
179 ws_client.is_connected().await
180 } else {
181 false
182 }
183 }
184
185 #[cfg(feature = "websocket")]
187 pub async fn reconnect_websocket(&self) -> ClientResult<()> {
188 let ws_guard = self.ws_client.read().await;
189
190 if let Some(ws_client) = ws_guard.as_ref() {
191 ws_client.reconnect().await?;
192 Ok(())
193 } else {
194 Err(ClientError::NoWebsocketClient)
195 }
196 }
197
198 #[cfg(feature = "websocket")]
200 async fn create_or_get_ws_client(&self) -> ClientResult<tokio::sync::RwLockWriteGuard<'_, Option<ws::WebsocketClient>>> {
201 let mut ws_guard = self.ws_client.write().await;
202 if ws_guard.is_none() {
203 let config = match self.ws_config.clone() {
204 Some(config) => config,
205 None => return Err(ClientError::MissingConfiguration("WebsocketConfig"))
206 };
207
208 let ws_client = ws::WebsocketClient::new(config);
209 *ws_guard = Some(ws_client);
210 }
211
212 Ok(ws_guard)
213 }
214}
215impl Drop for Client {
216 fn drop(&mut self) {
217 }
220}