diff --git a/src/commands/info_cmds.rs b/src/commands/info_cmds.rs index cb0a6c9..7eb4295 100644 --- a/src/commands/info_cmds.rs +++ b/src/commands/info_cmds.rs @@ -32,7 +32,7 @@ async fn info(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { let current_user = ctx.cache.current_user(); let footer = footer(ctx); - invoke + let _ = invoke .respond( ctx.http.clone(), CreateGenericResponse::new().embed(|e| { @@ -40,15 +40,13 @@ async fn info(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { .description(format!( "Default prefix: `{default_prefix}` Reset prefix: `@{user} prefix {default_prefix}` -Help: `{prefix}help`**Welcome \ - to Reminder Bot!** +Help: `{prefix}help`**Welcome to Reminder Bot!** Developer: <@203532103185465344> Icon: <@253202252821430272> -Find me on https://discord.jellywx.com \ - and on https://github.com/JellyWX :) +Find me on https://discord.jellywx.com and on https://github.com/JellyWX :) -Invite the bot: https://invite.reminder-bot.com/Use our dashboard: \ - https://reminder-bot.com/", +Invite the bot: https://invite.reminder-bot.com/ +Use our dashboard: https://reminder-bot.com/", default_prefix = *DEFAULT_PREFIX, user = current_user.name, prefix = prefix @@ -66,7 +64,7 @@ Invite the bot: https://invite.reminder-bot.com/Use our dashboard: \ async fn donate(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { let footer = footer(ctx); - invoke + let _ = invoke .respond( ctx.http.clone(), CreateGenericResponse::new().embed(|e| { @@ -99,7 +97,7 @@ Just $2 USD/month! async fn dashboard(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { let footer = footer(ctx); - invoke + let _ = invoke .respond( ctx.http.clone(), CreateGenericResponse::new().embed(|e| { @@ -119,7 +117,7 @@ async fn clock(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { let ud = ctx.user_data(&invoke.author_id()).await.unwrap(); let now = Utc::now().with_timezone(&ud.timezone()); - invoke + let _ = invoke .respond( ctx.http.clone(), CreateGenericResponse::new().content(format!("Current time: {}", now.format("%H:%M"))), diff --git a/src/commands/reminder_cmds.rs b/src/commands/reminder_cmds.rs index 13112e3..2fe8371 100644 --- a/src/commands/reminder_cmds.rs +++ b/src/commands/reminder_cmds.rs @@ -1,5 +1,5 @@ use std::{ - default::Default, + collections::HashSet, string::ToString, time::{SystemTime, UNIX_EPOCH}, }; @@ -7,7 +7,15 @@ use std::{ use chrono::NaiveDateTime; use num_integer::Integer; use regex_command_attr::command; -use serenity::{client::Context, model::channel::Channel}; +use serenity::{ + builder::CreateEmbed, + client::Context, + model::{ + channel::Channel, + id::{GuildId, UserId}, + interactions::InteractionResponseType, + }, +}; use crate::{ check_subscription_on_message, @@ -17,7 +25,7 @@ use crate::{ }, consts::{ EMBED_DESCRIPTION_MAX_LENGTH, REGEX_CHANNEL_USER, REGEX_NATURAL_COMMAND_1, - REGEX_NATURAL_COMMAND_2, REGEX_REMIND_COMMAND, THEME_COLOR, + REGEX_NATURAL_COMMAND_2, THEME_COLOR, }, framework::{CommandInvoke, CommandOptions, CreateGenericResponse, OptionValue}, models::{ @@ -26,6 +34,7 @@ use crate::{ reminder::{ builder::{MultiReminderBuilder, ReminderScope}, content::Content, + errors::ReminderError, look_flags::{LookFlags, TimeDisplayType}, Reminder, }, @@ -33,7 +42,7 @@ use crate::{ user_data::UserData, CtxData, }, - time_parser::{natural_parser, TimeParser}, + time_parser::natural_parser, SQLPool, }; @@ -444,6 +453,15 @@ async fn delete(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync)) { } } +async fn show_delete_page( + ctx: &Context, + guild_id: Option, + user_id: UserId, + page: usize, + timezone: Tz, +) { +} + #[command("timer")] #[description("Manage timers")] #[subcommand("list")] @@ -582,23 +600,168 @@ DELETE FROM timers WHERE owner = ? AND name = ? } } -/* -#[derive(PartialEq)] -enum RemindCommand { - Remind, - Interval, -} - #[command("remind")] -#[permission_level(Managed)] -async fn remind(ctx: &Context, msg: &Message, args: String) { - remind_command(ctx, msg, args, RemindCommand::Remind).await; +#[description("Create a new reminder")] +#[arg( + name = "time", + description = "A description of the time to set the reminder for", + kind = "String", + required = true +)] +#[arg( + name = "content", + description = "The message content to send", + kind = "String", + required = true +)] +#[arg( + name = "channels", + description = "Channel or user mentions to set the reminder for", + kind = "String", + required = false +)] +#[arg( + name = "repeat", + description = "(Patreon only) Time to wait before repeating the reminder. Leave blank for one-shot reminder", + kind = "String", + required = false +)] +#[arg( + name = "expires", + description = "(Patreon only) For repeating reminders, the time at which the reminder will stop sending", + kind = "String", + required = false +)] +#[arg( + name = "tts", + description = "Set the TTS flag on the reminder message (like the /tts command)", + kind = "Boolean", + required = false +)] +#[required_permissions(Managed)] +async fn remind(ctx: &Context, invoke: &(dyn CommandInvoke + Send + Sync), args: CommandOptions) { + let interaction = invoke.interaction().unwrap(); + + // defer response since processing times can take some time + interaction + .create_interaction_response(&ctx, |r| { + r.kind(InteractionResponseType::DeferredChannelMessageWithSource) + }) + .await + .unwrap(); + + let user_data = ctx.user_data(invoke.author_id()).await.unwrap(); + let timezone = user_data.timezone(); + + let time = { + let time_str = args.get("time").unwrap().to_string(); + + natural_parser(&time_str, &timezone.to_string()).await + }; + + match time { + Some(time) => { + let content = { + let content = args.get("content").unwrap().to_string(); + let tts = args.get("tts").map_or(false, |arg| arg.as_bool().unwrap_or(false)); + + Content { content, tts, attachment: None, attachment_name: None } + }; + + let scopes = { + let list = args + .get("channels") + .map(|arg| parse_mention_list(&arg.to_string())) + .unwrap_or(vec![]); + + if list.is_empty() { + vec![ReminderScope::Channel(invoke.channel_id().0)] + } else { + list + } + }; + + let interval = args + .get("repeat") + .map(|arg| { + humantime::parse_duration(&arg.to_string()) + .or_else(|_| humantime::parse_duration(&format!("1 {}", arg.to_string()))) + .map(|duration| duration.as_secs() as i64) + .ok() + }) + .flatten(); + let expires = { + if let Some(arg) = args.get("expires") { + natural_parser(&arg.to_string(), &timezone.to_string()).await + } else { + None + } + }; + + let mut builder = MultiReminderBuilder::new(ctx, invoke.guild_id()) + .author(user_data) + .content(content) + .time(time) + .expires(expires) + .interval(interval); + + builder.set_scopes(scopes); + + let (errors, successes) = builder.build().await; + + let embed = create_response(successes, errors, time); + + interaction + .edit_original_interaction_response(&ctx, |r| r.add_embed(embed)) + .await + .unwrap(); + } + None => { + let _ = interaction + .edit_original_interaction_response(&ctx, |r| { + r.content("Time could not be processed.") + }) + .await; + } + } } -#[command("interval")] -#[permission_level(Managed)] -async fn interval(ctx: &Context, msg: &Message, args: String) { - remind_command(ctx, msg, args, RemindCommand::Interval).await; +fn create_response( + successes: HashSet, + errors: HashSet, + time: i64, +) -> CreateEmbed { + let success_part = match successes.len() { + 0 => "".to_string(), + n => format!( + "Reminder{s} for {locations} set for ", + s = if n > 1 { "s" } else { "" }, + locations = successes.iter().map(|l| l.mention()).collect::>().join(", "), + offset = time + ), + }; + + let error_part = match errors.len() { + 0 => "".to_string(), + n => format!( + "{n} reminder{s} failed to set:\n{errors}", + s = if n > 1 { "s" } else { "" }, + n = n, + errors = errors.iter().map(|e| e.to_string()).collect::>().join("\n") + ), + }; + + let mut embed = CreateEmbed::default(); + embed + .title(format!( + "{n} Reminder{s} Set", + n = successes.len(), + s = if successes.len() > 1 { "s" } else { "" } + )) + .description(format!("{}\n\n{}", success_part, error_part)) + .color(*THEME_COLOR); + + embed } fn parse_mention_list(mentions: &str) -> Vec { @@ -617,158 +780,7 @@ fn parse_mention_list(mentions: &str) -> Vec { .collect::>() } -async fn remind_command(ctx: &Context, msg: &Message, args: String, command: RemindCommand) { - let (pool, lm) = get_ctx_data(&ctx).await; - - let timezone = UserData::timezone_of(&msg.author, &pool).await; - let language = UserData::language_of(&msg.author, &pool).await; - - match REGEX_REMIND_COMMAND.captures(&args) { - Some(captures) => { - let parsed = parse_mention_list(captures.name("mentions").unwrap().as_str()); - - let scopes = if parsed.is_empty() { - vec![ReminderScope::Channel(msg.channel_id.into())] - } else { - parsed - }; - - let time_parser = TimeParser::new(captures.name("time").unwrap().as_str(), timezone); - - let expires_parser = - captures.name("expires").map(|mat| TimeParser::new(mat.as_str(), timezone)); - - let interval_parser = captures - .name("interval") - .map(|mat| TimeParser::new(mat.as_str(), timezone)) - .map(|parser| parser.displacement()) - .transpose(); - - if let Ok(interval) = interval_parser { - if interval.is_some() && !check_subscription_on_message(&ctx, msg).await { - // no patreon - let _ = msg - .channel_id - .say( - &ctx, - lm.get(&language, "interval/donor") - .replace("{prefix}", &ctx.prefix(msg.guild_id).await), - ) - .await; - } else { - let content_res = Content::build( - captures.name("content").map(|mat| mat.as_str()).unwrap(), - msg, - ) - .await; - - match content_res { - Ok(mut content) => { - if let Some(guild) = msg.guild(&ctx) { - content.substitute(guild); - } - - let user_data = ctx.user_data(&msg.author).await.unwrap(); - - let mut builder = MultiReminderBuilder::new(ctx, msg.guild_id) - .author(user_data) - .content(content) - .interval(interval) - .expires_parser(expires_parser) - .time_parser(time_parser.clone()); - - builder.set_scopes(scopes); - - let (errors, successes) = builder.build().await; - - let success_part = match successes.len() { - 0 => "".to_string(), - n => format!( - "Reminder{s} for {locations} set for ", - s = if n > 1 { "s" } else { "" }, - locations = successes - .iter() - .map(|l| l.mention()) - .collect::>() - .join(", "), - offset = time_parser.timestamp().unwrap() - ), - }; - - let error_part = match errors.len() { - 0 => "".to_string(), - n => format!( - "{n} reminder{s} failed to set:\n{errors}", - s = if n > 1 { "s" } else { "" }, - n = n, - errors = errors - .iter() - .map(|e| e.display(false)) - .collect::>() - .join("\n") - ), - }; - - let _ = msg - .channel_id - .send_message(&ctx, |m| { - m.embed(|e| { - e.title(format!( - "{n} Reminder{s} Set", - n = successes.len(), - s = if successes.len() > 1 { "s" } else { "" } - )) - .description(format!("{}\n\n{}", success_part, error_part)) - .color(*THEME_COLOR) - }) - }) - .await; - } - - Err(content_error) => { - let _ = msg - .channel_id - .send_message(ctx, |m| { - m.embed(move |e| { - e.title("0 Reminders Set") - .description(content_error.to_string()) - .color(*THEME_COLOR) - }) - }) - .await; - } - } - } - } else { - let _ = msg - .channel_id - .send_message(ctx, |m| { - m.embed(move |e| { - e.title(lm.get(&language, "remind/title").replace("{number}", "0")) - .description(lm.get(&language, "interval/invalid_interval")) - .color(*THEME_COLOR) - }) - }) - .await; - } - } - - None => { - let prefix = ctx.prefix(msg.guild_id).await; - - match command { - RemindCommand::Remind => { - command_help(ctx, msg, lm, &prefix, &language, "remind").await - } - - RemindCommand::Interval => { - command_help(ctx, msg, lm, &prefix, &language, "interval").await - } - } - } - } -} - +/* #[command("natural")] #[permission_level(Managed)] async fn natural(ctx: &Context, msg: &Message, args: String) { diff --git a/src/component_models/mod.rs b/src/component_models/mod.rs index f589b5d..8adba69 100644 --- a/src/component_models/mod.rs +++ b/src/component_models/mod.rs @@ -272,6 +272,34 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let reminders = Reminder::from_guild(ctx, component.guild_id, component.user.id).await; + if reminders.is_empty() { + let mut embed = CreateEmbed::default(); + embed.title("Delete Reminders").description("No Reminders").color(*THEME_COLOR); + + component + .create_interaction_response(&ctx, |r| { + r.kind(InteractionResponseType::UpdateMessage) + .interaction_response_data(|response| { + response.embeds(vec![embed]).components(|comp| comp) + }) + }) + .await; + + return; + } + + let pages = reminders + .iter() + .enumerate() + .map(|(count, reminder)| reminder.display_del(count, &selector.timezone)) + .fold(0, |t, r| t + r.len()) + .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); + + let mut page = selector.page; + if page >= pages { + page = pages - 1; + } + let mut char_count = 0; let mut skip_char_count = 0; let mut first_num = 0; @@ -286,7 +314,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id first_num += 1; skip_char_count += p.len(); - skip_char_count < EMBED_DESCRIPTION_MAX_LENGTH * selector.page + skip_char_count < EMBED_DESCRIPTION_MAX_LENGTH * page }) .take_while(|(_, p)| { char_count += p.len(); @@ -297,17 +325,10 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let display = display_vec.join("\n"); - let pages = reminders - .iter() - .enumerate() - .map(|(count, reminder)| reminder.display_del(count, &selector.timezone)) - .fold(0, |t, r| t + r.len()) - .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); - let pager = DelPager::new(selector.timezone); let del_selector = ComponentDataModel::DelSelector(DelSelector { - page: selector.page, + page, timezone: selector.timezone, }); @@ -315,7 +336,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id embed .title("Delete Reminders") .description(display) - .footer(|f| f.text(format!("Page {} of {}", selector.page + 1, pages))) + .footer(|f| f.text(format!("Page {} of {}", page + 1, pages))) .color(*THEME_COLOR); component @@ -333,7 +354,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id shown_reminders.iter().enumerate() { opt.create_option(|o| { - o.label(count + 1) + o.label(count + first_num) .value(reminder.id) .description({ let c = diff --git a/src/component_models/pager.rs b/src/component_models/pager.rs index a78e72d..40d25a1 100644 --- a/src/component_models/pager.rs +++ b/src/component_models/pager.rs @@ -16,8 +16,9 @@ pub trait Pager { enum PageAction { First = 0, Previous = 1, - Next = 2, - Last = 3, + Refresh = 2, + Next = 3, + Last = 4, } #[derive(Serialize, Deserialize)] @@ -33,6 +34,7 @@ impl Pager for LookPager { match self.action { PageAction::First => 0, PageAction::Previous => 0.max(self.page - 1), + PageAction::Refresh => self.page, PageAction::Next => (max_pages - 1).min(self.page + 1), PageAction::Last => max_pages - 1, } @@ -41,7 +43,7 @@ impl Pager for LookPager { fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) { let next_page = self.next_page(max_pages); - let (page_first, page_prev, page_next, page_last) = + let (page_first, page_prev, page_refresh, page_next, page_last) = LookPager::buttons(self.flags, next_page, self.timezone); comp.create_action_row(|row| { @@ -57,6 +59,9 @@ impl Pager for LookPager { .custom_id(page_prev.to_custom_id()) .disabled(next_page == 0) }) + .create_button(|b| { + b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id()) + }) .create_button(|b| { b.label("▶️") .style(ButtonStyle::Secondary) @@ -82,7 +87,13 @@ impl LookPager { flags: LookFlags, page: usize, timezone: Tz, - ) -> (ComponentDataModel, ComponentDataModel, ComponentDataModel, ComponentDataModel) { + ) -> ( + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ) { ( ComponentDataModel::LookPager(LookPager { flags, @@ -96,6 +107,12 @@ impl LookPager { action: PageAction::Previous, timezone, }), + ComponentDataModel::LookPager(LookPager { + flags, + page, + action: PageAction::Refresh, + timezone, + }), ComponentDataModel::LookPager(LookPager { flags, page, @@ -124,6 +141,7 @@ impl Pager for DelPager { match self.action { PageAction::First => 0, PageAction::Previous => 0.max(self.page - 1), + PageAction::Refresh => self.page, PageAction::Next => (max_pages - 1).min(self.page + 1), PageAction::Last => max_pages - 1, } @@ -132,7 +150,7 @@ impl Pager for DelPager { fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) { let next_page = self.next_page(max_pages); - let (page_first, page_prev, page_next, page_last) = + let (page_first, page_prev, page_refresh, page_next, page_last) = DelPager::buttons(next_page, self.timezone); comp.create_action_row(|row| { @@ -148,6 +166,9 @@ impl Pager for DelPager { .custom_id(page_prev.to_custom_id()) .disabled(next_page == 0) }) + .create_button(|b| { + b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id()) + }) .create_button(|b| { b.label("▶️") .style(ButtonStyle::Secondary) @@ -172,10 +193,17 @@ impl DelPager { pub fn buttons( page: usize, timezone: Tz, - ) -> (ComponentDataModel, ComponentDataModel, ComponentDataModel, ComponentDataModel) { + ) -> ( + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ComponentDataModel, + ) { ( ComponentDataModel::DelPager(DelPager { page, action: PageAction::First, timezone }), ComponentDataModel::DelPager(DelPager { page, action: PageAction::Previous, timezone }), + ComponentDataModel::DelPager(DelPager { page, action: PageAction::Refresh, timezone }), ComponentDataModel::DelPager(DelPager { page, action: PageAction::Next, timezone }), ComponentDataModel::DelPager(DelPager { page, action: PageAction::Last, timezone }), ) diff --git a/src/main.rs b/src/main.rs index eb51567..e4999d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -296,8 +296,8 @@ async fn main() -> Result<(), Box> { .add_command(&info_cmds::CLOCK_COMMAND) // reminder commands .add_command(&reminder_cmds::TIMER_COMMAND) + .add_command(&reminder_cmds::REMIND_COMMAND) /* - .add_command("remind", &reminder_cmds::REMIND_COMMAND) .add_command("r", &reminder_cmds::REMIND_COMMAND) .add_command("interval", &reminder_cmds::INTERVAL_COMMAND) .add_command("i", &reminder_cmds::INTERVAL_COMMAND) diff --git a/src/models/mod.rs b/src/models/mod.rs index e8afa15..7801c90 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -6,6 +6,7 @@ pub mod user_data; use std::sync::Arc; +use chrono_tz::Tz; use serenity::{ async_trait, model::id::{ChannelId, GuildId, UserId}, @@ -33,6 +34,8 @@ pub trait CtxData { user_id: U, ) -> Result>; + async fn timezone + Send + Sync>(&self, user_id: U) -> Tz; + async fn channel_data + Send + Sync>( &self, channel_id: C, @@ -92,6 +95,13 @@ impl CtxData for Context { UserData::from_user(&user, &self, &pool).await } + async fn timezone + Send + Sync>(&self, user_id: U) -> Tz { + let user_id = user_id.into(); + let pool = self.data.read().await.get::().cloned().unwrap(); + + UserData::timezone_of(user_id, &pool).await + } + async fn channel_data + Send + Sync>( &self, channel_id: C, diff --git a/src/models/reminder/builder.rs b/src/models/reminder/builder.rs index 8bf9ec5..73cffb6 100644 --- a/src/models/reminder/builder.rs +++ b/src/models/reminder/builder.rs @@ -21,7 +21,6 @@ use crate::{ reminder::{content::Content, errors::ReminderError, helper::generate_uid, Reminder}, user_data::UserData, }, - time_parser::TimeParser, SQLPool, }; @@ -133,7 +132,8 @@ INSERT INTO reminders ( self.set_by ) .execute(&self.pool) - .await; + .await + .unwrap(); Ok(Reminder::from_uid(&self.pool, self.uid).await.unwrap()) } @@ -147,11 +147,9 @@ INSERT INTO reminders ( pub struct MultiReminderBuilder<'a> { scopes: Vec, utc_time: NaiveDateTime, - utc_time_parser: Option, timezone: Tz, interval: Option, expires: Option, - expires_parser: Option, content: Content, set_by: Option, ctx: &'a Context, @@ -163,11 +161,9 @@ impl<'a> MultiReminderBuilder<'a> { MultiReminderBuilder { scopes: vec![], utc_time: Utc::now().naive_utc(), - utc_time_parser: None, timezone: Tz::UTC, interval: None, expires: None, - expires_parser: None, content: Content::new(), set_by: None, ctx, @@ -187,12 +183,6 @@ impl<'a> MultiReminderBuilder<'a> { self } - pub fn time_parser(mut self, parser: TimeParser) -> Self { - self.utc_time_parser = Some(parser); - - self - } - pub fn expires>(mut self, time: Option) -> Self { if let Some(t) = time { self.expires = Some(NaiveDateTime::from_timestamp(t.into(), 0)); @@ -203,12 +193,6 @@ impl<'a> MultiReminderBuilder<'a> { self } - pub fn expires_parser(mut self, parser: Option) -> Self { - self.expires_parser = parser; - - self - } - pub fn author(mut self, user: UserData) -> Self { self.set_by = Some(user.id); self.timezone = user.timezone(); @@ -226,33 +210,13 @@ impl<'a> MultiReminderBuilder<'a> { self.scopes = scopes; } - pub async fn build(mut self) -> (HashSet, HashSet) { + pub async fn build(self) -> (HashSet, HashSet) { let pool = self.ctx.data.read().await.get::().cloned().unwrap(); let mut errors = HashSet::new(); let mut ok_locs = HashSet::new(); - if let Some(expire_parser) = self.expires_parser { - if let Ok(expires) = expire_parser.timestamp() { - self.expires = Some(NaiveDateTime::from_timestamp(expires, 0)); - } else { - errors.insert(ReminderError::InvalidExpiration); - - return (errors, ok_locs); - } - } - - if let Some(time_parser) = self.utc_time_parser { - if let Ok(time) = time_parser.timestamp() { - self.utc_time = NaiveDateTime::from_timestamp(time, 0); - } else { - errors.insert(ReminderError::InvalidTime); - - return (errors, ok_locs); - } - } - if self.interval.map_or(false, |i| (i as i64) < *MIN_INTERVAL) { errors.insert(ReminderError::ShortInterval); } else if self.interval.map_or(false, |i| (i as i64) > *MAX_TIME) { diff --git a/src/models/reminder/errors.rs b/src/models/reminder/errors.rs index d3e8ad5..e8fc0f5 100644 --- a/src/models/reminder/errors.rs +++ b/src/models/reminder/errors.rs @@ -39,8 +39,8 @@ pub enum ReminderError { DiscordError(String), } -impl ReminderError { - pub fn display(&self, is_natural: bool) -> String { +impl ToString for ReminderError { + fn to_string(&self) -> String { match self { ReminderError::LongTime => { "That time is too far in the future. Please specify a shorter time.".to_string() @@ -50,40 +50,20 @@ impl ReminderError { max_time = *MAX_TIME / 86_400 ), ReminderError::PastTime => { - "Please ensure the time provided is in the future. If the time should be in \ - the future, please be more specific with the definition." - .to_string() + "Please ensure the time provided is in the future. If the time should be in the future, please be more specific with the definition.".to_string() } ReminderError::ShortInterval => format!( "Please ensure the interval provided is longer than {min_interval} seconds", min_interval = *MIN_INTERVAL ), ReminderError::InvalidTag => { - "Couldn't find a location by your tag. Your tag must be either a channel or \ - a user (not a role)" - .to_string() + "Couldn't find a location by your tag. Your tag must be either a channel or a user (not a role)".to_string() } ReminderError::InvalidTime => { - if is_natural { - "Your time failed to process. Please make it as clear as possible, for example `\"16th of july\"` \ - or `\"in 20 minutes\"`" - .to_string() - } else { - "Make sure the time you have provided is in the format of [num][s/m/h/d][num][s/m/h/d] etc. or \ - `day/month/year-hour:minute:second`" - .to_string() - } + "Your time failed to process. Please make it as clear as possible, for example `\"16th of july\"` or `\"in 20 minutes\"`".to_string() } ReminderError::InvalidExpiration => { - if is_natural { - "Your expiration time failed to process. Please make it as clear as possible, for example `\"16th \ - of july\"` or `\"in 20 minutes\"`" - .to_string() - } else { - "Make sure the expiration time you have provided is in the format of [num][s/m/h/d][num][s/m/h/d] \ - etc. or `day/month/year-hour:minute:second`" - .to_string() - } + "Your expiration time failed to process. Please make it as clear as possible, for example `\"16th of july\"` or `\"in 20 minutes\"`".to_string() } ReminderError::DiscordError(s) => format!("A Discord error occurred: **{}**", s), }