use crate::database::models::Event; use crate::hypebot_config::HypeBotConfig; use chrono::{Duration, NaiveDateTime, Utc}; use serenity::prelude::TypeMapKey; /// Event Reminder #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub struct Reminder { pub event_id: i32, pub time: NaiveDateTime, pub reminder_id: usize, } /// Set of reminders for currently active events #[derive(Debug, Clone, Default)] pub struct Reminders { reminders: Vec, } impl TypeMapKey for Reminders { type Value = Reminders; } impl Reminders { /// Add all the reminders for an event pub fn add_reminders(&mut self, event: &Event, config: &HypeBotConfig) { if let Some(event_reminders) = &config.reminders { for (reminder_id, event_reminder) in event_reminders.iter().enumerate() { let reminder_time = event.event_time - chrono::Duration::minutes(event_reminder.reminder_time as i64); if reminder_time > Utc::now().naive_utc() { self.reminders.push(Reminder { event_id: event.id, time: reminder_time, reminder_id, }); } } } } /// Get reminders that need to be sent pub fn get_reminders(&mut self) -> Vec { let reminders: Vec = self .reminders .iter() .filter(|r| { let time_diff = r.time - Utc::now().naive_utc(); time_diff > Duration::seconds(-5) && time_diff < Duration::seconds(5) }) .copied() .collect(); self.reminders.retain(|r| !reminders.contains(r)); reminders } /// Removes reminders for an event pub fn remove_reminders(&mut self, event: &Event) { self.reminders.retain(|e| e.event_id != event.id) } /// Update reminders for an event #[allow(dead_code)] pub fn update_reminders(&mut self, event: &Event, config: &HypeBotConfig) { self.remove_reminders(event); self.add_reminders(event, config); } } #[cfg(test)] mod tests { use crate::hypebot_config::{EventReminder, HypeBotConfig}; use crate::models::Event; use crate::reminder::Reminders; use chrono::{Duration, Utc}; fn setup() -> (Reminders, HypeBotConfig, Event) { let r = Reminders::default(); let c = HypeBotConfig { db_url: "".to_string(), default_thumbnail_link: "".to_string(), discord_key: "".to_string(), prefix: "".to_string(), event_channel: 0, event_roles: vec![], ping_roles: vec![], event_timezone: chrono_tz::UTC, log_path: "".to_string(), reminders: Some( [EventReminder { msg: "".to_string(), reminder_time: 5, }, EventReminder { msg: "".to_string(), reminder_time: 1, }] .to_vec(), ), }; let e = Event { id: 0, event_name: "".to_string(), event_desc: "".to_string(), event_loc: "".to_string(), organizer: "".to_string(), event_time: Utc::now().naive_utc() + Duration::minutes(5) + Duration::seconds(5), message_id: "".to_string(), thumbnail_link: "".to_string(), reminder_sent: 0, }; (r, c, e) } #[test] fn test_add_reminders() { let (mut r, c, e) = setup(); r.add_reminders(&e, &c); assert_eq!(r.reminders.len(), c.reminders.unwrap().len()); } #[test] fn test_get_reminders() { let (mut r, c, e) = setup(); r.add_reminders(&e, &c); assert_eq!(r.get_reminders().len(), 1); assert_eq!(r.reminders.len(), c.reminders.unwrap().len()-1); } #[test] fn test_remove_reminders() { let (mut r, c, e) = setup(); r.add_reminders(&e, &c); r.remove_reminders(&e); assert_eq!(r.reminders.len(), 0); } #[test] fn test_update_reminders() { let (mut r, c, e) = setup(); r.add_reminders(&e, &c); r.update_reminders(&e, &c); assert_eq!(r.get_reminders().len(), 1); } }