/*
* 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 std::{collections::HashMap, sync::Arc};
use crate::{
config::{Config, NotifierConfig},
routes::message::MessageForm,
service::{self, Service},
};
static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
#[derive(Clone)]
pub struct State {
_client: reqwest::Client,
pub services: Arc<HashMap<String, Box<dyn Service + Send + Sync>>>,
pub notifiers: HashMap<String, NotifierConfig>,
}
impl State {
pub fn from_config(config: &Config) -> Result<Self, Box<dyn std::error::Error>> {
let client: reqwest::Client = reqwest::ClientBuilder::new()
.user_agent(USER_AGENT)
.build()?;
let mut services: HashMap<String, Box<dyn Service + Send + Sync>> = HashMap::new();
for (id, service_config) in &config.services {
let service: Box<dyn Service + Send + Sync> =
service::build(client.clone(), &*(*service_config))?;
services.insert(id.clone(), service);
}
Ok(Self {
_client: client,
services: Arc::new(services),
notifiers: config.notifiers.clone(),
})
}
pub fn find_notifier(&self, token: &str) -> Option<(&String, &NotifierConfig)> {
self.notifiers.iter().find(|(_k, v)| v.token == token)
}
pub async fn send_message(
&self,
notifier: (&String, &NotifierConfig),
form: &MessageForm,
) -> Result<(), Vec<Box<dyn std::error::Error + Send + Sync>>> {
let mut errs = vec![];
for (_k, v) in self
.services
.iter()
.filter(|(k, _v)| notifier.1.services.contains(k))
{
if let Err(err) = v.send(form).await {
errs.push(err);
};
}
if !errs.is_empty() { Err(errs) } else { Ok(()) }
}
}