/* * Copyright (C) 2025 Jonni Liljamo * * This file is licensed under GPL-3.0-or-later, see NOTICE and LICENSE for * more information. */ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use serde_json::json; use crate::config::ServiceConfig; use super::Service; #[derive(Clone, Deserialize, Serialize)] pub struct MatrixConfig { pub instance: String, pub token: String, pub room: String, } #[typetag::serde(name = "matrix")] impl ServiceConfig for MatrixConfig { fn as_any(&self) -> &dyn std::any::Any { self } } pub struct MatrixService { client: reqwest::Client, config: MatrixConfig, } impl MatrixService { pub fn new(client: reqwest::Client, config: MatrixConfig) -> Self { Self { client, config } } fn gen_txn_id(&self) -> String { format!( "{}_{}", std::process::id(), std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap_or(std::time::Duration::new(0, 0)) .as_nanos() ) } } #[async_trait] impl Service for MatrixService { async fn send(&self, title: &str, message: &str) -> Result<(), Box> { let body = json!({ "msgtype": "m.notice", "body": format!("**{}**\n\n{}", title, message), "format": "org.matrix.custom.html", "formatted_body": format!("

{}

\n

{}

\n", title, message), }); let _ = self .client .put(format!( "{}/_matrix/client/v3/rooms/{}/send/m.room.message/{}", self.config.instance, self.config.room, self.gen_txn_id() )) .query(&[("access_token", &self.config.token)]) .body(body.to_string()) .send() .await?; Ok(()) } }