diff options
-rw-r--r-- | src/main.rs | 56 | ||||
-rw-r--r-- | src/mattermost.rs | 72 |
2 files changed, 116 insertions, 12 deletions
diff --git a/src/main.rs b/src/main.rs index e2a9028..36dfbb8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,57 @@ mod mattermost; +use anyhow::anyhow; use tokio::{self}; use tracing::{debug, info}; -struct Vav{ - -} +struct Vav {} #[async_trait::async_trait] -impl mattermost::Handler for Vav{ - async fn handle(&self,message:serde_json::Value,client: & mattermost::Client) { - debug!("{message:?}"); +impl mattermost::Handler for Vav { + async fn handle( + &self, + value: serde_json::Value, + client: &mattermost::Client, + ) -> Result<(), anyhow::Error> { + debug!("{value:?}"); + let object = value + .as_object() + .ok_or(anyhow!("Response from mattermost should be object"))?; + if object + .get("event") + .ok_or(anyhow!("missing event type"))? + .as_str() + .ok_or(anyhow!("event type should be a string"))? + != "posted" + { + return Ok(()); + } + let post: serde_json::Value = serde_json::from_str( + object + .get("data") + .unwrap() + .get("post") + .ok_or(anyhow!("missing post field"))? + .as_str() + .ok_or(anyhow!("post should be string"))?, + )?; + debug!("Post field {post:?}"); + let object = post + .as_object() + .ok_or(anyhow!("Post field should represent legit object"))?; + let message = object + .get("message") + .ok_or(anyhow!("missing message"))? + .as_str() + .ok_or(anyhow!("message should be string"))?; + if !message.starts_with('!') { + return Ok(()); + } + let message = message.strip_prefix('!').unwrap(); + match message{ + "adres" => client.reply_to(&post, "Uniwersytet Wrocławski Instytut Informatyki; pl. Frederyka Joliot-Curie 15; 50-383 Wrocław".to_owned()).await?, + _ => return Err(anyhow!("Unrecognized command {message}")), + } + Ok(()) } } @@ -21,6 +63,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let auth = mattermost::AuthData { login, password }; let mut client = mattermost::Client::new(auth, "https://mattermost.continuum.ii.uni.wroc.pl"); client.update_bearer_token().await?; - client.handle_websocket_stream(Vav{}).await?; + client.handle_websocket_stream(Vav {}).await?; Ok(()) } diff --git a/src/mattermost.rs b/src/mattermost.rs index 9b811d1..c8759c3 100644 --- a/src/mattermost.rs +++ b/src/mattermost.rs @@ -16,7 +16,11 @@ pub struct Client { #[async_trait::async_trait] pub trait Handler { - async fn handle(&self, message:serde_json::Value,client: &Client); + async fn handle( + &self, + message: serde_json::Value, + client: &Client, + ) -> Result<(), anyhow::Error>; } impl Client { @@ -48,7 +52,10 @@ impl Client { debug!("Successfully updated bearer token"); Ok(()) } - pub(crate) async fn handle_websocket_stream<T:Handler>(&mut self, handler: T) -> Result<(), anyhow::Error> { + pub(crate) async fn handle_websocket_stream<T: Handler>( + &mut self, + handler: T, + ) -> 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 @@ -67,13 +74,18 @@ impl Client { Message::Text(text) => { let json: Result<serde_json::Value, _> = serde_json::from_str(&text); match json { - Ok(json) => {debug!("Got json {json}");handler.handle(json,&self).await;}, - Err(err) => warn!("Error while deserializing {err}"), + Ok(json) => { + // debug!("Got json: {json}"); + if let Err(err) = handler.handle(json, &self).await { + warn!("Handler returned error: {err}"); + }; + } + Err(err) => warn!("Error while deserializing: {err}"), } } Message::Close(_) => break, _ => { - debug!("Message {message:?}"); + debug!("Message: {message:?}"); } }, Err(err) => warn!("Error {err} while reading message"), @@ -81,4 +93,54 @@ impl Client { } Ok(()) } + pub(crate) async fn reply_to( + &self, + post: &serde_json::Value, + reply: String, + ) -> Result<(), anyhow::Error> { + let token = self + .bearer_token + .clone() + .ok_or(anyhow!("Missing bearer token"))?; + let object = post + .as_object() + .ok_or(anyhow!("Response from mattermost should be object"))?; + let id = object + .get("id") + .ok_or(anyhow!("missing id"))? + .as_str() + .ok_or(anyhow!("id should be a string"))?; + let root_id = object + .get("root_id") + .ok_or(anyhow!("missing root_id"))? + .as_str() + .ok_or(anyhow!("root_id should be a string"))?; + let post_id = if root_id == "" { id } else { root_id }; + let channel_id = object + .get("channel_id") + .ok_or(anyhow!("missing channel_id"))? + .as_str() + .ok_or(anyhow!("channel_id should be a string"))?; + + debug!("Sending response"); + let response = self + .client + .post(format!("{}/api/v4/posts", self.url)) + .json(&json!({ + "channel_id":channel_id, + "root_id":post_id, + "message":&reply, + })) + .header("Authorization", format!("Bearer {token}")) + .send() + .await?; + let status = response.status(); + let resp = response.text().await; + if !status.is_success() { + warn!("{:?}", resp); + return Err(anyhow!("Error {}", status)); + } + debug!("Sent response"); + Ok(()) + } } |