use crate::config::MessageConfig; use crate::game::player_data::PlayerData; use crate::GlobalData; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serenity::model::guild::Member; use serenity::prelude::Mentionable; use std::collections::HashMap; use tera::{Tera, Value}; type TeraFnRet = Box) -> tera::Result + Send + Sync>; fn time_to_discord_time(time_flag: &str) -> TeraFnRet { let time_flag = time_flag.to_string(); Box::new( move |args: &HashMap| -> tera::Result { match args.get("time") { Some(val) => match tera::from_value::(val.clone()) { Ok(v) => { let time = v.parse::>().unwrap(); Ok( tera::to_value(format!("", time.timestamp(), time_flag)) .unwrap(), ) } Err(_) => Err("Failed to parse value as time".into()), }, None => Err("Missing parameter".into()), } }, ) } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DiscordUser { pub(crate) display_name: String, pub(crate) mention: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Tally { target: String, votes: u64, } impl From<&Member> for DiscordUser { fn from(m: &Member) -> Self { Self { display_name: m.display_name().to_string(), mention: m.mention().to_string(), } } } #[derive(Debug, Clone)] pub struct MessageTemplates { templates: Tera, } impl MessageTemplates { pub fn build_welcome_message( &self, global_data: &GlobalData, discord_user: &DiscordUser, player_data: &PlayerData, ) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("game_state", global_data.game_state().unwrap()); context.insert("discord_user", discord_user); context.insert("player_data", player_data); let mut msg = self.templates.render("welcome_message", &context)?; msg.push_str(&self.templates.render("status_message", &context)?); Ok(msg) } pub fn build_satus_message(&self, global_data: &GlobalData) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("game_state", global_data.game_state().unwrap()); self.templates.render("status_message", &context) } pub fn build_announcement( &self, global_data: &GlobalData, message: &str, ) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("game_state", global_data.game_state().unwrap()); context.insert("message", message); self.templates.render("announcement", &context) } pub fn build_vote_tally(&self, global_data: &GlobalData) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("game_state", global_data.game_state().unwrap()); context.insert( "tallies", &global_data.game_state().unwrap().get_vote_tallies(), ); self.templates.render("tally_message", &context) } pub fn build_vote_message( &self, global_data: &GlobalData, player: &PlayerData, target: &PlayerData, ) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("game_state", global_data.game_state().unwrap()); context.insert("player_data", player); context.insert("target_data", target); self.templates.render("vote_message", &context) } pub fn build_phase_extend_message( &self, global_data: &GlobalData, ) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("game_state", global_data.game_state().unwrap()); self.templates.render("phase_extend_message", &context) } pub fn build_name( &self, global_data: &GlobalData, first_name: Option, last_name: Option, ) -> Result { let mut context = tera::Context::new(); context.insert("game_cfg", global_data.game_cfg().unwrap()); context.insert("first_name", &first_name); context.insert("last_name", &last_name); self.templates.render("name_format", &context) } } impl TryFrom for MessageTemplates { type Error = tera::Error; fn try_from(config: MessageConfig) -> Result { let mut templates = Tera::default(); templates.register_function("to_countdown", time_to_discord_time("R")); templates.register_function("to_local_time", time_to_discord_time("f")); templates.add_raw_template("welcome_message", &config.welcome_message)?; templates.add_raw_template("status_message", &config.status_message)?; templates.add_raw_template("announcement", &config.announcement_format)?; templates.add_raw_template("tally_message", &config.tally_message)?; templates.add_raw_template("vote_message", &config.vote_message)?; templates.add_raw_template("phase_extend_message", &config.phase_extend_message)?; templates.add_raw_template("name_format", &config.name_format)?; Ok(Self { templates }) } }