diff --git a/Cargo.lock b/Cargo.lock index d0809ea..8d3e2d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -685,7 +685,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", - "humantime 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime", "log", "regex", "termcolor", @@ -1069,11 +1069,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "humantime" -version = "2.1.0" -source = "git+https://github.com/reminder-bot/humantime#12ce6f50894a56a410b390e5608ac9db8afe2407" - [[package]] name = "hyper" version = "0.14.23" @@ -2145,7 +2140,6 @@ dependencies = [ "chrono-tz 0.8.1", "dotenv", "env_logger", - "humantime 2.1.0 (git+https://github.com/reminder-bot/humantime)", "lazy-regex", "lazy_static", "levenshtein", diff --git a/src/main.rs b/src/main.rs index 011692e..c0e4760 100644 --- a/src/main.rs +++ b/src/main.rs @@ -75,7 +75,7 @@ impl Display for Ended { impl StdError for Ended {} -#[tokio::main] +#[tokio::main(flavor = "multi_thread")] async fn main() -> Result<(), Box> { let (tx, mut rx) = broadcast::channel(16); diff --git a/web/src/routes/dashboard/export.rs b/web/src/routes/dashboard/export.rs index 6dd530b..f71b071 100644 --- a/web/src/routes/dashboard/export.rs +++ b/web/src/routes/dashboard/export.rs @@ -58,6 +58,7 @@ pub async fn export_reminders( reminders.enabled, reminders.expires, reminders.interval_seconds, + reminders.interval_days, reminders.interval_months, reminders.name, reminders.restartable, @@ -159,6 +160,7 @@ pub async fn import_reminders( enabled: record.enabled, expires: record.expires, interval_seconds: record.interval_seconds, + interval_days: record.interval_days, interval_months: record.interval_months, name: record.name, restartable: record.restartable, diff --git a/web/src/routes/dashboard/guild.rs b/web/src/routes/dashboard/guild.rs index 83db5f8..c8c6660 100644 --- a/web/src/routes/dashboard/guild.rs +++ b/web/src/routes/dashboard/guild.rs @@ -339,6 +339,7 @@ pub async fn get_reminders(id: u64, ctx: &State, pool: &State, interval_seconds: Option, + interval_days: Option, interval_months: Option, #[serde(default = "name_default")] name: String, @@ -164,6 +165,7 @@ pub struct ReminderCsv { enabled: bool, expires: Option, interval_seconds: Option, + interval_days: Option, interval_months: Option, #[serde(default = "name_default")] name: String, @@ -214,6 +216,8 @@ pub struct PatchReminder { #[serde(default)] interval_seconds: Unset>, #[serde(default)] + interval_days: Unset>, + #[serde(default)] interval_months: Unset>, #[serde(default)] name: Unset, @@ -370,8 +374,12 @@ pub async fn create_reminder( if reminder.utc_time < Utc::now().naive_utc() { return Err(json!({"error": "Time must be in the future"})); } - if reminder.interval_seconds.is_some() || reminder.interval_months.is_some() { + if reminder.interval_seconds.is_some() + || reminder.interval_days.is_some() + || reminder.interval_months.is_some() + { if reminder.interval_months.unwrap_or(0) * 30 * DAY as u32 + + reminder.interval_days.unwrap_or(0) * DAY as u32 + reminder.interval_seconds.unwrap_or(0) < *MIN_INTERVAL { @@ -380,7 +388,10 @@ pub async fn create_reminder( } // check patreon if necessary - if reminder.interval_seconds.is_some() || reminder.interval_months.is_some() { + if reminder.interval_seconds.is_some() + || reminder.interval_days.is_some() + || reminder.interval_months.is_some() + { if !check_guild_subscription(&ctx, guild_id).await && !check_subscription(&ctx, user_id).await { @@ -416,13 +427,14 @@ pub async fn create_reminder( enabled, expires, interval_seconds, + interval_days, interval_months, name, restartable, tts, username, `utc_time` - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", new_uid, attachment_data, reminder.attachment_name, @@ -442,6 +454,7 @@ pub async fn create_reminder( reminder.enabled, reminder.expires, reminder.interval_seconds, + reminder.interval_days, reminder.interval_months, name, reminder.restartable, @@ -473,6 +486,7 @@ pub async fn create_reminder( reminders.enabled, reminders.expires, reminders.interval_seconds, + reminders.interval_days, reminders.interval_months, reminders.name, reminders.restartable, diff --git a/web/src/routes/login.rs b/web/src/routes/login.rs index d5894c9..1fd4196 100644 --- a/web/src/routes/login.rs +++ b/web/src/routes/login.rs @@ -135,14 +135,14 @@ pub async fn discord_callback( Err(Flash::new( Redirect::to(uri!(super::return_to_same_site(""))), "warning", - "Your login request was rejected", + "Your login request was rejected. The server may be misconfigured. Please retry or alert us in Discord.", )) } } } else { - Err(Flash::new(Redirect::to(uri!(super::return_to_same_site(""))), "danger", "Your request failed to validate, and so has been rejected (error: CSRF Validation Failure)")) + Err(Flash::new(Redirect::to(uri!(super::return_to_same_site(""))), "danger", "Your request failed to validate, and so has been rejected (CSRF Validation Failure)")) } } else { - Err(Flash::new(Redirect::to(uri!(super::return_to_same_site(""))), "warning", "Your request was missing information, and so has been rejected (error: CSRF Validation Tokens Missing)")) + Err(Flash::new(Redirect::to(uri!(super::return_to_same_site(""))), "warning", "Your request was missing information, and so has been rejected (CSRF Validation Tokens Missing)")) } } diff --git a/web/static/js/interval.js b/web/static/js/interval.js index a28d75a..7909afe 100644 --- a/web/static/js/interval.js +++ b/web/static/js/interval.js @@ -7,9 +7,9 @@ function get_interval(element) { return { months: parseInt(months) || null, + days: parseInt(days) || null, seconds: - (parseInt(days) || 0) * 86400 + - (parseInt(hours) || 0) * 3600 + + (parseInt(hours) || 0) * 3600 + (parseInt(minutes) || 0) * 60 + (parseInt(seconds) || 0) || null, }; @@ -42,13 +42,6 @@ function update_interval(element) { minutes.value = String(remainder).padStart(2, "0"); hours.value = String(Number(hours.value) + Number(quotient)).padStart(2, "0"); } - if (hours.value >= 24) { - let quotient = Math.floor(hours.value / 24); - let remainder = hours.value % 24; - - hours.value = String(remainder).padStart(2, "0"); - days.value = Number(days.value) + Number(quotient); - } } const $intervalGroup = document.querySelector(".interval-group"); diff --git a/web/static/js/main.js b/web/static/js/main.js index 5fafcf5..c403ccd 100644 --- a/web/static/js/main.js +++ b/web/static/js/main.js @@ -319,6 +319,7 @@ async function serialize_reminder(node, mode) { embed_fields: fields, expires: expiration_time, interval_seconds: mode !== "template" ? interval.seconds : null, + interval_days: mode !== "template" ? interval.days : null, interval_months: mode !== "template" ? interval.months : null, name: node.querySelector('input[name="name"]').value, tts: node.querySelector('input[name="tts"]').checked, diff --git a/web/templates/support/intervals.html.tera b/web/templates/support/intervals.html.tera index fc8889e..7d61e27 100644 --- a/web/templates/support/intervals.html.tera +++ b/web/templates/support/intervals.html.tera @@ -49,7 +49,7 @@

Monthly or yearly intervals are configured the same as fixed intervals. Instead of a fixed time interval, these reminders repeat on a certain day each month or each year. This makes them ideal - for marking certain dates. + for marking calendar events.

@@ -61,7 +61,8 @@

Interval expiration

An expiration time can also be specified, both via commands and dashboard, for repeating reminders. - This is optional, and if omitted, the reminder will repeat indefinitely. + This is optional, and if omitted, the reminder will repeat indefinitely. Otherwise, the reminder + will be deleted once the expiration date is reached.