DEVELOPMENT ENVIRONMENT

~liljamo/canwa

ref: 48cdec8c4b46ff488355395941e0e428635a24ef canwa/src/service/mod.rs -rw-r--r-- 1.5 KiB
48cdec8cJonni Liljamo feat(nix): hydraJobs 3 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
 * Copyright (C) 2025 Jonni Liljamo <jonni@liljamo.com>
 *
 * 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::{config::ServiceConfig, routes::message::MessageForm};

pub mod email;
pub mod gotify;
pub mod matrix;

#[async_trait]
pub trait Service {
    async fn send(
        &self,
        form: &MessageForm,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
}

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<dyn Service + Send + Sync>, Box<dyn std::error::Error>> {
    let config: Box<dyn Service + Send + Sync> =
        make_service_match!(client, service_config, email, gotify, matrix);
    Ok(config)
}