working on improvements to reminder command still

This commit is contained in:
jellywx 2020-11-29 12:49:50 +00:00
parent 3879c83085
commit d8aaf92335

View File

@ -1,5 +1,3 @@
use custom_error::custom_error;
use regex_command_attr::command; use regex_command_attr::command;
use serenity::{ use serenity::{
@ -22,9 +20,10 @@ use crate::{
consts::{ consts::{
CHARACTERS, DAY, HOUR, LOCAL_TIMEZONE, MAX_TIME, MINUTE, MIN_INTERVAL, PYTHON_LOCATION, CHARACTERS, DAY, HOUR, LOCAL_TIMEZONE, MAX_TIME, MINUTE, MIN_INTERVAL, PYTHON_LOCATION,
REGEX_CHANNEL, REGEX_CHANNEL_USER, REGEX_CONTENT_SUBSTITUTION, REGEX_INTERVAL_COMMAND, REGEX_CHANNEL, REGEX_CHANNEL_USER, REGEX_CONTENT_SUBSTITUTION, REGEX_INTERVAL_COMMAND,
REGEX_REMIND_COMMAND, REGEX_REMIND_COMMAND, THEME_COLOR,
}, },
framework::SendIterator, framework::SendIterator,
language_manager::LanguageManager,
models::{ChannelData, GuildData, Timer, UserData}, models::{ChannelData, GuildData, Timer, UserData},
time_parser::TimeParser, time_parser::TimeParser,
SQLPool, SQLPool,
@ -41,6 +40,7 @@ use std::str::from_utf8;
use num_integer::Integer; use num_integer::Integer;
use std::{ use std::{
collections::HashSet,
convert::TryInto, convert::TryInto,
default::Default, default::Default,
fmt::Display, fmt::Display,
@ -48,7 +48,6 @@ use std::{
time::{SystemTime, UNIX_EPOCH}, time::{SystemTime, UNIX_EPOCH},
}; };
use crate::language_manager::LanguageManager;
use regex::RegexBuilder; use regex::RegexBuilder;
fn shorthand_displacement(seconds: u64) -> String { fn shorthand_displacement(seconds: u64) -> String {
@ -919,26 +918,35 @@ impl Mentionable for ReminderScope {
} }
} }
custom_error! {ReminderError #[derive(PartialEq, Eq, Hash, Debug)]
LongTime = "Time too long", enum ReminderError {
LongInterval = "Interval too long", LongTime,
PastTime = "Time has already passed", LongInterval,
ShortInterval = "Interval too short", PastTime,
InvalidTag = "Invalid reminder scope", ShortInterval,
NotEnoughArgs = "Not enough args", InvalidTag,
InvalidTime = "Invalid time provided", NotEnoughArgs,
NeedSubscription = "Subscription required and not found", InvalidTime,
DiscordError = "Bad response received from Discord" NeedSubscription,
DiscordError,
} }
trait ToResponse { impl std::fmt::Display for ReminderError {
fn to_response(&self) -> String; fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_response())
}
}
fn to_response_natural(&self) -> String; impl std::error::Error for ReminderError {}
trait ToResponse {
fn to_response(&self) -> &'static str;
fn to_response_natural(&self) -> &'static str;
} }
impl ToResponse for ReminderError { impl ToResponse for ReminderError {
fn to_response(&self) -> String { fn to_response(&self) -> &'static str {
match self { match self {
Self::LongTime => "remind/long_time", Self::LongTime => "remind/long_time",
Self::LongInterval => "interval/long_interval", Self::LongInterval => "interval/long_interval",
@ -950,30 +958,29 @@ impl ToResponse for ReminderError {
Self::NeedSubscription => "interval/donor", Self::NeedSubscription => "interval/donor",
Self::DiscordError => "remind/no_webhook", Self::DiscordError => "remind/no_webhook",
} }
.to_string()
} }
fn to_response_natural(&self) -> String { fn to_response_natural(&self) -> &'static str {
match self { match self {
Self::LongTime => "natural/long_time".to_string(), Self::LongTime => "natural/long_time",
Self::InvalidTime => "natural/invalid_time".to_string(), Self::InvalidTime => "natural/invalid_time",
_ => self.to_response(), _ => self.to_response(),
} }
} }
} }
impl<T> ToResponse for Result<T, ReminderError> { impl<T> ToResponse for Result<T, ReminderError> {
fn to_response(&self) -> String { fn to_response(&self) -> &'static str {
match self { match self {
Ok(_) => "remind/success".to_string(), Ok(_) => "remind/success",
Err(reminder_error) => reminder_error.to_response(), Err(reminder_error) => reminder_error.to_response(),
} }
} }
fn to_response_natural(&self) -> String { fn to_response_natural(&self) -> &'static str {
match self { match self {
Ok(_) => "remind/success".to_string(), Ok(_) => "remind/success",
Err(reminder_error) => reminder_error.to_response_natural(), Err(reminder_error) => reminder_error.to_response_natural(),
} }
@ -1053,10 +1060,12 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
match captures { match captures {
Some(captures) => { Some(captures) => {
let scopes = if let Some(mentions) = captures.name("mentions") { let parsed = parse_mention_list(captures.name("mentions").unwrap().as_str());
parse_mention_list(mentions.as_str())
} else { let scopes = if parsed.len() == 0 {
vec![ReminderScope::Channel(msg.channel_id.into())] vec![ReminderScope::Channel(msg.channel_id.into())]
} else {
parsed
}; };
let time_parser = TimeParser::new( let time_parser = TimeParser::new(
@ -1072,8 +1081,12 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
let content = captures.name("content").map(|mat| mat.as_str()).unwrap(); let content = captures.name("content").map(|mat| mat.as_str()).unwrap();
let mut ok_locations = vec![];
let mut err_locations = vec![];
let mut err_types = HashSet::new();
for scope in scopes { for scope in scopes {
create_reminder( let res = create_reminder(
&ctx, &ctx,
&pool, &pool,
msg.author.id, msg.author.id,
@ -1084,13 +1097,86 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
content, content,
) )
.await; .await;
if let Err(e) = res {
err_locations.push(scope);
err_types.insert(e);
} else {
ok_locations.push(scope);
} }
} }
let success_part = match ok_locations.len() {
0 => "".to_string(),
1 => lm
.get(&user_data.language, "remind/success")
.replace("{location}", &ok_locations[0].mention())
.replace(
"{offset}",
&shorthand_displacement(time_parser.displacement().unwrap() as u64),
),
n => lm
.get(&user_data.language, "remind/success_bulk")
.replace("{number}", &n.to_string())
.replace(
"{location}",
&ok_locations
.iter()
.map(|l| l.mention())
.collect::<Vec<String>>()
.join(", "),
)
.replace(
"{offset}",
&shorthand_displacement(time_parser.displacement().unwrap() as u64),
),
};
let error_part = format!(
"{}\n{}",
match err_locations.len() {
0 => "".to_string(),
1 => lm
.get(&user_data.language, "remind/issue")
.replace("{location}", &err_locations[0].mention()),
n => lm
.get(&user_data.language, "remind/issue_bulk")
.replace("{number}", &n.to_string())
.replace(
"{location}",
&err_locations
.iter()
.map(|l| l.mention())
.collect::<Vec<String>>()
.join(", "),
),
},
err_types
.iter()
.map(|err| lm.get(&user_data.language, err.to_response()))
.collect::<Vec<&str>>()
.join("\n")
);
let _ = msg
.channel_id
.send_message(&ctx, |m| {
m.embed(|e| {
e.title(
lm.get(&user_data.language, "remind/title")
.replace("{number}", &ok_locations.len().to_string()),
)
.description(format!("{}\n\n{}", success_part, error_part))
.color(*THEME_COLOR)
})
})
.await;
}
None => { None => {
let _ = msg let _ = msg
.channel_id .channel_id
.say(&ctx, lm.get(&user_data.language, "remind/invalid")) .say(&ctx, lm.get(&user_data.language, "remind/no_argument"))
.await; .await;
} }
} }