1use crate::notifications::{Key, ValidatedNotification};
4use crate::Error;
5use async_trait::async_trait;
6use dyn_clone::DynClone;
7use std::any::Any;
8use std::collections::{HashMap, HashSet};
9use std::fmt::Debug;
10use tokio::sync::{broadcast, watch};
11
12#[cfg(feature = "discord")]
13pub mod discord;
14#[cfg(feature = "email")]
15pub mod email;
16#[cfg(feature = "file")]
17pub mod file;
18#[cfg(feature = "matrix")]
19pub mod matrix;
20
21#[typetag::deserialize(tag = "type")]
23pub trait EndpointConfig: Debug {
24 fn to_endpoint(&self) -> Result<Box<dyn Endpoint + Send>, Error>;
26}
27
28#[async_trait]
30pub trait Endpoint: DynClone + Send + Debug {
31 async fn notify(
33 &self,
34 endpoint_rx: broadcast::Receiver<ValidatedNotification>,
35 shutdown: watch::Receiver<bool>,
36 ) -> Result<(), Error>;
37
38 fn generate_keys(&self, hash_key: &Key) -> HashMap<String, HashSet<Key>>;
44
45 fn as_any(&self) -> &dyn Any;
47}
48
49dyn_clone::clone_trait_object!(Endpoint);
50
51#[derive(Clone)]
52pub(crate) struct EndpointChannel {
53 endpoint: Box<dyn Endpoint + Send>,
54 channel: broadcast::Sender<ValidatedNotification>,
55 keys: HashMap<String, HashSet<Key>>,
56}
57
58impl EndpointChannel {
59 pub fn from(
60 endpoint: Box<dyn Endpoint + Send>,
61 channel: broadcast::Sender<ValidatedNotification>,
62 keys: HashMap<String, HashSet<Key>>,
63 ) -> Self {
64 EndpointChannel { endpoint, channel, keys }
65 }
66
67 pub fn endpoint(&self) -> &Box<dyn Endpoint + Send> {
68 &self.endpoint
69 }
70
71 pub fn channel_receiver(&self) -> broadcast::Receiver<ValidatedNotification> {
72 self.channel.subscribe()
73 }
74
75 pub fn channel_sender(&self) -> broadcast::Sender<ValidatedNotification> {
76 self.channel.clone()
77 }
78
79 pub fn keys(&self) -> &HashMap<String, HashSet<Key>> {
80 &self.keys
81 }
82}
83
84pub(crate) async fn setup_endpoints(
85 endpoints: Vec<EndpointChannel>,
86 shutdown: watch::Receiver<bool>,
87) -> Result<(), Error> {
88 for channel in endpoints {
89 channel.endpoint().notify(channel.channel_receiver(), shutdown.clone()).await?
90 }
91 Ok(())
92}