/* * Copyright (C) 2025 Jonni Liljamo * * This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for * more information. */ use async_trait::async_trait; use pastey::paste; use crate::{MessageForm, config::ServiceConfig}; pub mod email; pub mod gotify; pub mod matrix; #[async_trait] pub trait Service { async fn send(&self, form: &MessageForm) -> Result<(), Box>; } macro_rules! make_service_match { ($client:expr, $service_config:expr, $service:expr) => { paste! { Box::new($service::[<$service:upper_camel Service>]::new( $client, $service_config .as_any() .downcast_ref::<$service::[<$service:upper_camel Config>]>() .ok_or("no such service")?.clone(), )?) } }; ($client:expr, $service_config:expr, $($service:expr),+) => { match $service_config.typetag_name() { $(stringify!($service) => make_service_match!($client, $service_config, $service)),+, _ => unreachable!(), } }; } pub fn build( client: reqwest::Client, service_config: &dyn ServiceConfig, ) -> Result, Box> { let config: Box = make_service_match!(client, service_config, email, gotify, matrix); Ok(config) }