json-rules-engine 0.9.4

json rules engine
Documentation
use crate::{event::EventTrait, Error};

use async_trait::async_trait;
use erased_serde::Serialize;
use futures_util::TryFutureExt;
use sendgrid::v3::{
    Content, Email as SendGridEmail, Message, Personalization, Sender,
};
use serde_json::Value;

use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct EmailNotification {
    ty: String,
}

#[async_trait]
impl EventTrait for EmailNotification {
    fn new() -> Self {
        Self {
            ty: "email_notification".to_string(),
        }
    }

    fn get_type(&self) -> &str {
        &self.ty
    }

    fn validate(&self, params: &HashMap<String, Value>) -> Result<(), String> {
        if !(params.contains_key("to")
            && params.contains_key("from")
            && params.contains_key("title")
            && params.contains_key("message"))
        {
            return Err(
                "At least one of 'to', 'from', 'title', 'message' is missing."
                    .to_string(),
            );
        }

        Ok(())
    }

    async fn trigger(
        &mut self,
        params: &HashMap<String, Value>,
        facts: &(dyn Serialize + Sync),
    ) -> Result<(), Error> {
        let api_key = ::std::env::var("SENDGRID_API_KEY")
            .expect("You must set 'SENDGRID_API_KEY' environment variable");

        let sender = Sender::new(api_key);

        let tos = params.get("to").unwrap().as_array().unwrap();
        let from = params.get("from").unwrap().to_string();
        let mut title = params.get("title").unwrap().to_string();
        let mut message = params.get("message").unwrap().to_string();

        let value = serde_json::from_str::<Value>(
            &serde_json::to_string(facts).unwrap(),
        )
        .unwrap();
        if let Ok(tmpl) = mustache::compile_str(&message)
            .and_then(|template| template.render_to_string(&value))
        {
            message = tmpl;
        }

        if let Ok(tmpl) = mustache::compile_str(&title)
            .and_then(|template| template.render_to_string(&value))
        {
            title = tmpl;
        }

        let personalization = {
            let mut p =
                Personalization::new(SendGridEmail::new(&tos[0].to_string()));
            for to in tos.iter().skip(1) {
                p = p.add_to(SendGridEmail::new(to.to_string()));
            }
            p
        };

        let m = Message::new(SendGridEmail::new(from))
            .set_subject(&title)
            .add_content(
                Content::new()
                    .set_content_type("text/plain")
                    .set_value(message),
            )
            .add_personalization(personalization);

        sender.send(&m).map_err(Error::from).await?;

        Ok(())
    }
}