use anyhow::anyhow; use async_tungstenite::{tokio::connect_async, tungstenite::Message}; use futures_util::{SinkExt, StreamExt}; use serde_json::json; use tracing::debug; pub struct AuthData { pub(crate) login: String, pub(crate) password: String, } pub struct Client { pub(crate) auth: AuthData, pub(crate) url: String, bearer_token: Option, client: reqwest::Client, } impl Client { pub(crate) fn new(auth: AuthData, url: &str) -> Self { Self { auth, url: url.to_owned(), bearer_token: None, client: reqwest::Client::new(), } } pub(crate) async fn update_bearer_token(&mut self) -> Result<(), anyhow::Error> { debug!("Fetching bearer token from api"); let response = self .client .post(format!("{}/api/v4/users/login", self.url)) .json(&json!({ "login_id":self.auth.login, "password":self.auth.password, })) .send() .await?; let token = response .headers() .get("token") .ok_or(anyhow!("Haven't received bearer token in headers"))? .to_str()?; self.bearer_token = Some(token.to_owned()); debug!("Successfully updated bearer token"); Ok(()) } pub(crate) async fn handle_websocket_stream(&self) -> Result<(), anyhow::Error> { let url = format!("{}/api/v4/websocket", self.url.replacen("http", "ws", 1)); let (mut ws_stream, _) = connect_async(url).await?; let token = self .bearer_token .clone() .ok_or(anyhow!("Missing bearer token"))?; ws_stream .send(Message::Text( json!({"seq":1,"action":"authentication_challenge","data":{"token":token}}) .to_string(), )) .await?; while let Some(message) = ws_stream.next().await { debug!("{:?}", message); } Ok(()) } }