Merge pull request 'Added configurable event reminders' (#10) from config_reminders into master
Reviewed-on: https://git.etztech.xyz/ZeroHD/HypeBot/pulls/10master
commit
47a1bc9a2a
15
README.md
15
README.md
|
@ -41,4 +41,19 @@ ping_roles = [0]
|
|||
event_timezone = "America/New_York"
|
||||
# Path to place logs in
|
||||
log_path = "log/"
|
||||
|
||||
# Configurable Reminders
|
||||
[[reminders]]
|
||||
# Message to send, "{EVENT_NAME}" gets replaced with the event's name
|
||||
msg = "{EVENT_NAME} is starting now!"
|
||||
# number of minutes before an event to send the reminder
|
||||
reminder_time = 0
|
||||
|
||||
[[reminders]]
|
||||
msg = "{EVENT_NAME} is starting in 1 minute!"
|
||||
reminder_time = 1
|
||||
|
||||
[[reminders]]
|
||||
msg = "{EVENT_NAME} is starting in 5 minutes!"
|
||||
reminder_time = 5
|
||||
```
|
|
@ -80,8 +80,10 @@ pub fn get_countdown_link(event_name: &String, utc: &DateTime<Utc>) -> String {
|
|||
let msg = event_name.replace(" ", "+");
|
||||
let time = utc.format("%G%m%dT%H%M").to_string();
|
||||
|
||||
format!("https://www.timeanddate.com/countdown/generic?iso={}&p0=&msg={}&font=sanserif&csz=1", time, msg)
|
||||
|
||||
format!(
|
||||
"https://www.timeanddate.com/countdown/generic?iso={}&p0=&msg={}&font=sanserif&csz=1",
|
||||
time, msg
|
||||
)
|
||||
}
|
||||
|
||||
/// Sends the event message to the event channel
|
||||
|
@ -98,9 +100,13 @@ pub fn send_event_msg(
|
|||
|
||||
let native_time = utc_time.with_timezone(&config.event_timezone);
|
||||
|
||||
let ping_roles = config.ping_roles.clone().into_iter().map(|role| {
|
||||
format!("<@&{}>", role)
|
||||
}).collect::<Vec<String>>().join(" ");
|
||||
let ping_roles = config
|
||||
.ping_roles
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|role| format!("<@&{}>", role))
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ");
|
||||
|
||||
// Send message
|
||||
let msg = channel.id().send_message(&http, |m| {
|
||||
|
@ -208,7 +214,7 @@ pub fn get_scheduler(
|
|||
let mut context = data.write();
|
||||
Ok(context
|
||||
.get_mut::<SchedulerKey>()
|
||||
.ok_or(CommandError("Unable to scheduler".to_string()))?
|
||||
.ok_or(CommandError("Unable to get scheduler".to_string()))?
|
||||
.clone())
|
||||
}
|
||||
|
||||
|
@ -248,6 +254,7 @@ pub fn permission_check(ctx: &mut Context, msg: &Message, _command_name: &str) -
|
|||
false
|
||||
}
|
||||
|
||||
/// Schedule event reminders
|
||||
pub fn schedule_event(http: &Arc<Http>, data: &Arc<RwLock<ShareMap>>, event: &Event) {
|
||||
let scheduler = {
|
||||
let mut context = data.write();
|
||||
|
@ -257,24 +264,48 @@ pub fn schedule_event(http: &Arc<Http>, data: &Arc<RwLock<ShareMap>>, event: &Ev
|
|||
.clone()
|
||||
};
|
||||
|
||||
if event.reminder_sent < 1 {
|
||||
let config = get_config(&data).unwrap();
|
||||
|
||||
if let Some(reminders) = config.reminders {
|
||||
let event_time: DateTime<Utc> = DateTime::<Utc>::from_utc(event.event_time.clone(), Utc);
|
||||
let reminder_time = event_time - chrono::Duration::minutes(10);
|
||||
let delete_time = event_time + chrono::Duration::minutes(1);
|
||||
let mut scheduler = scheduler.write();
|
||||
|
||||
for reminder in reminders {
|
||||
let reminder_time =
|
||||
event_time - chrono::Duration::minutes(reminder.reminder_time as i64);
|
||||
|
||||
if reminder_time > chrono::offset::Utc::now() {
|
||||
let reminder_msg = reminder.msg.clone();
|
||||
let http = http.clone();
|
||||
let data = data.clone();
|
||||
let event = event.clone();
|
||||
|
||||
scheduler.add_task_datetime(reminder_time, move |_| {
|
||||
send_reminders(&http, &data, &event, &reminder_msg)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let http = http.clone();
|
||||
let data = data.clone();
|
||||
let event = event.clone();
|
||||
|
||||
scheduler.add_task_datetime(reminder_time, move |_| send_reminders(&http, &data, &event));
|
||||
scheduler.add_task_datetime(delete_time, move |_| {
|
||||
delete_event(&http, &data, &event);
|
||||
DateResult::Done
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Send reminders
|
||||
pub fn send_reminders(http: &Arc<Http>, data: &Arc<RwLock<ShareMap>>, event: &Event) -> DateResult {
|
||||
pub fn send_reminders(
|
||||
http: &Arc<Http>,
|
||||
data: &Arc<RwLock<ShareMap>>,
|
||||
event: &Event,
|
||||
reminder_msg: &String,
|
||||
) -> DateResult {
|
||||
let config = get_config(&data).unwrap();
|
||||
let event_channel_id = config.event_channel;
|
||||
let event_time: DateTime<Utc> = DateTime::<Utc>::from_utc(event.event_time.clone(), Utc);
|
||||
let delete_time = event_time + chrono::Duration::minutes(60);
|
||||
|
||||
if let Ok(message_id) = event.message_id.parse::<u64>() {
|
||||
// Get message id
|
||||
|
@ -284,27 +315,13 @@ pub fn send_reminders(http: &Arc<Http>, data: &Arc<RwLock<ShareMap>>, event: &Ev
|
|||
.unwrap_or(Vec::<User>::new());
|
||||
|
||||
// Build reminder message
|
||||
let msg: String = format!("Hello! **{}** is starting soon!", &event.event_name);
|
||||
let msg: String = reminder_msg.replace("{EVENT_NAME}", event.event_name.as_str());
|
||||
|
||||
// Send reminder to each reacted user
|
||||
for user in reaction_users {
|
||||
send_dm_message(&http, user, &msg);
|
||||
}
|
||||
}
|
||||
|
||||
set_reminder(config.db_url.clone(), event.id, 1).ok();
|
||||
|
||||
let scheduler = get_scheduler(data).unwrap();
|
||||
let mut scheduler = scheduler.write();
|
||||
|
||||
let http = http.clone();
|
||||
let data = data.clone();
|
||||
let event = event.clone();
|
||||
|
||||
scheduler.add_task_datetime(delete_time, move |_| {
|
||||
delete_event(&http, &data, &event);
|
||||
DateResult::Done
|
||||
});
|
||||
}
|
||||
|
||||
DateResult::Done
|
||||
|
|
|
@ -5,6 +5,12 @@ use serde::{Deserialize, Deserializer};
|
|||
use serenity::prelude::TypeMapKey;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct EventReminder {
|
||||
pub msg: String,
|
||||
pub reminder_time: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct HypeBotConfig {
|
||||
pub db_url: String,
|
||||
|
@ -17,6 +23,7 @@ pub struct HypeBotConfig {
|
|||
#[serde(deserialize_with = "from_tz_string")]
|
||||
pub event_timezone: Tz,
|
||||
pub log_path: String,
|
||||
pub reminders: Option<Vec<EventReminder>>,
|
||||
}
|
||||
|
||||
struct ConfigValueVisitor;
|
||||
|
|
20
src/main.rs
20
src/main.rs
|
@ -10,13 +10,13 @@ extern crate log4rs;
|
|||
use chrono::{DateTime, Utc};
|
||||
use clap::{App, Arg};
|
||||
use log::LevelFilter;
|
||||
use log4rs::append::rolling_file::{RollingFileAppender};
|
||||
use log4rs::config::{Appender, Config, Root};
|
||||
use log4rs::encode::pattern::PatternEncoder;
|
||||
use log4rs::append::console::ConsoleAppender;
|
||||
use log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller;
|
||||
use log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger;
|
||||
use log4rs::append::rolling_file::policy::compound::CompoundPolicy;
|
||||
use log4rs::append::rolling_file::RollingFileAppender;
|
||||
use log4rs::config::{Appender, Config, Root};
|
||||
use log4rs::encode::pattern::PatternEncoder;
|
||||
use log4rs::filter::threshold::ThresholdFilter;
|
||||
use log4rs::init_config;
|
||||
use serenity::client::Client;
|
||||
|
@ -28,10 +28,10 @@ use serenity::model::id::UserId;
|
|||
use serenity::model::prelude::Ready;
|
||||
use serenity::prelude::{Context, EventHandler, RwLock};
|
||||
use std::collections::HashSet;
|
||||
use std::path::Path;
|
||||
use std::process::exit;
|
||||
use std::sync::Arc;
|
||||
use white_rabbit::{DateResult, Scheduler};
|
||||
use std::path::Path;
|
||||
|
||||
mod database;
|
||||
mod discord;
|
||||
|
@ -41,8 +41,8 @@ use database::models::NewEvent;
|
|||
use database::*;
|
||||
use discord::events::{CANCEL_COMMAND, CONFIRM_COMMAND, CREATE_COMMAND};
|
||||
use discord::{
|
||||
delete_event, get_config, get_scheduler, log_error, permission_check,
|
||||
send_message_to_reaction_users, schedule_event, DraftEvent, SchedulerKey,
|
||||
delete_event, get_config, get_scheduler, log_error, permission_check, schedule_event,
|
||||
send_message_to_reaction_users, DraftEvent, SchedulerKey,
|
||||
};
|
||||
use hypebot_config::HypeBotConfig;
|
||||
|
||||
|
@ -71,7 +71,9 @@ impl EventHandler for Handler {
|
|||
return;
|
||||
}
|
||||
};
|
||||
if reaction.channel_id.0 == config.event_channel && reaction.emoji.as_data() == INTERESTED_EMOJI {
|
||||
if reaction.channel_id.0 == config.event_channel
|
||||
&& reaction.emoji.as_data() == INTERESTED_EMOJI
|
||||
{
|
||||
send_message_to_reaction_users(
|
||||
&ctx,
|
||||
&reaction,
|
||||
|
@ -89,7 +91,9 @@ impl EventHandler for Handler {
|
|||
return;
|
||||
}
|
||||
};
|
||||
if reaction.channel_id.0 == config.event_channel && reaction.emoji.as_data() == INTERESTED_EMOJI {
|
||||
if reaction.channel_id.0 == config.event_channel
|
||||
&& reaction.emoji.as_data() == INTERESTED_EMOJI
|
||||
{
|
||||
send_message_to_reaction_users(
|
||||
&ctx,
|
||||
&reaction,
|
||||
|
|
Loading…
Reference in New Issue