if only setting one reminder with natural, show errors in messages. more refactor

This commit is contained in:
jude 2020-10-03 17:31:23 +01:00
parent 2b74adadeb
commit 836b77d14e
2 changed files with 88 additions and 32 deletions

View File

@ -3,6 +3,7 @@ use custom_error::custom_error;
use regex_command_attr::command; use regex_command_attr::command;
use serenity::{ use serenity::{
cache::Cache,
http::CacheHttp, http::CacheHttp,
client::Context, client::Context,
model::{ model::{
@ -29,10 +30,10 @@ use crate::{
Reminder, Reminder,
Timer, Timer,
}, },
check_subscription,
SQLPool, SQLPool,
time_parser::TimeParser, time_parser::TimeParser,
framework::SendIterator, framework::SendIterator,
check_subscription_on_message,
}; };
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
@ -69,7 +70,6 @@ use std::{
use regex::Regex; use regex::Regex;
use serde_json::json; use serde_json::json;
use serenity::cache::Cache;
lazy_static! { lazy_static! {
static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap(); static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap();
@ -570,7 +570,13 @@ custom_error!{ReminderError
DiscordError = "Bad response received from Discord" DiscordError = "Bad response received from Discord"
} }
impl ReminderError { trait ToResponse {
fn to_response(&self) -> String;
fn to_response_natural(&self) -> String;
}
impl ToResponse for ReminderError {
fn to_response(&self) -> String { fn to_response(&self) -> String {
match self { match self {
Self::LongTime => "remind/long_time", Self::LongTime => "remind/long_time",
@ -583,6 +589,31 @@ impl ReminderError {
Self::DiscordError => "remind/no_webhook", Self::DiscordError => "remind/no_webhook",
}.to_string() }.to_string()
} }
fn to_response_natural(&self) -> String {
match self {
Self::LongTime => "natural/long_time".to_string(),
_ => self.to_response(),
}
}
}
impl<T> ToResponse for Result<T, ReminderError> {
fn to_response(&self) -> String {
match self {
Ok(_) => "remind/success".to_string(),
Err(reminder_error) => reminder_error.to_response(),
}
}
fn to_response_natural(&self) -> String {
match self {
Ok(_) => "remind/success".to_string(),
Err(reminder_error) => reminder_error.to_response_natural(),
}
}
} }
fn generate_uid() -> String { fn generate_uid() -> String {
@ -623,10 +654,7 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
pool: &MySqlPool) pool: &MySqlPool)
-> Result<(), ReminderError> { -> Result<(), ReminderError> {
let subscribed = check_subscription(&ctx, &msg.author).await || if command == RemindCommand::Interval && check_subscription_on_message(&ctx, &msg).await {
if let Some(guild) = msg.guild(&ctx).await { check_subscription(&ctx, guild.owner_id).await } else { false };
if command == RemindCommand::Interval && subscribed {
if let Some(interval_arg) = args_iter.next() { if let Some(interval_arg) = args_iter.next() {
let interval = TimeParser::new(interval_arg.to_string(), UTC); let interval = TimeParser::new(interval_arg.to_string(), UTC);
@ -708,11 +736,7 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
Err(ReminderError::NotEnoughArgs) Err(ReminderError::NotEnoughArgs)
}; };
let str_response = match response { let str_response = response.to_response()
Ok(_) => user_data.response(&pool, "remind/success").await,
Err(reminder_error) => user_data.response(&pool, &reminder_error.to_response()).await,
}
.replacen("{location}", &scope_id.mention(), 1) .replacen("{location}", &scope_id.mention(), 1)
.replacen("{offset}", &time_parser.map(|tp| tp.displacement().ok()).flatten().unwrap_or(-1).to_string(), 1) .replacen("{offset}", &time_parser.map(|tp| tp.displacement().ok()).flatten().unwrap_or(-1).to_string(), 1)
.replacen("{min_interval}", &MIN_INTERVAL.to_string(), 1) .replacen("{min_interval}", &MIN_INTERVAL.to_string(), 1)
@ -726,6 +750,11 @@ async fn natural(ctx: &Context, msg: &Message, args: String) -> CommandResult {
let pool = ctx.data.read().await let pool = ctx.data.read().await
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data"); .get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
let now = SystemTime::now();
let since_epoch = now
.duration_since(UNIX_EPOCH)
.expect("Time calculated as going backwards. Very bad");
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap(); let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
let send_str = user_data.response(&pool, "natural/send").await; let send_str = user_data.response(&pool, "natural/send").await;
@ -740,7 +769,7 @@ async fn natural(ctx: &Context, msg: &Message, args: String) -> CommandResult {
let python_call = Command::new("venv/bin/python3") let python_call = Command::new("venv/bin/python3")
.arg("dp.py") .arg("dp.py")
.arg(time_crop) .arg(time_crop)
.arg(user_data.timezone) .arg(&user_data.timezone)
.arg(&env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string())) .arg(&env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string()))
.output() .output()
.await; .await;
@ -782,10 +811,7 @@ async fn natural(ctx: &Context, msg: &Message, args: String) -> CommandResult {
} }
} }
let subscribed = check_subscription(&ctx, &msg.author).await || if check_subscription_on_message(&ctx, &msg).await {
if let Some(guild) = msg.guild(&ctx).await { check_subscription(&ctx, guild.owner_id).await } else { false };
if subscribed {
let re_match = Regex::new(&format!(r#"(?P<msg>.*) {} (?P<interval>.*)$"#, every_str)) let re_match = Regex::new(&format!(r#"(?P<msg>.*) {} (?P<interval>.*)$"#, every_str))
.unwrap() .unwrap()
.captures(content); .captures(content);
@ -803,11 +829,6 @@ async fn natural(ctx: &Context, msg: &Message, args: String) -> CommandResult {
.output() .output()
.await; .await;
let now = SystemTime::now();
let since_epoch = now
.duration_since(UNIX_EPOCH)
.expect("Time calculated as going backwards. Very bad");
interval = python_call.ok().map(|inner| interval = python_call.ok().map(|inner|
if inner.status.success() { if inner.status.success() {
Some(from_utf8(&*inner.stdout).unwrap().parse::<i64>().unwrap() - since_epoch.as_secs() as i64) Some(from_utf8(&*inner.stdout).unwrap().parse::<i64>().unwrap() - since_epoch.as_secs() as i64)
@ -819,25 +840,51 @@ async fn natural(ctx: &Context, msg: &Message, args: String) -> CommandResult {
} }
let mut issue_count = 0; if location_ids.len() == 1 {
let location_id = location_ids.get(0).unwrap();
for location in location_ids {
let res = create_reminder( let res = create_reminder(
&ctx, &ctx,
&pool, &pool,
msg.author.id.as_u64().to_owned(), msg.author.id.as_u64().to_owned(),
msg.guild_id, msg.guild_id,
&location, &location_id,
timestamp, timestamp,
interval, interval,
&content).await; &content).await;
if res.is_ok() {
issue_count += 1;
}
}
let _ = msg.channel_id.say(&ctx, format!("successfully set {} reminders", issue_count)).await; let str_response = res.to_response_natural()
.replacen("{location}", &location_id.mention(), 1)
.replacen("{offset}", &(timestamp as u64 - since_epoch.as_secs()).to_string(), 1)
.replacen("{min_interval}", &MIN_INTERVAL.to_string(), 1)
.replacen("{max_time}", &MAX_TIME.to_string(), 1);
let _ = msg.channel_id.say(&ctx, &str_response).await;
}
else {
let mut issue_count = 0_u8;
for location in location_ids {
let res = create_reminder(
&ctx,
&pool,
msg.author.id.as_u64().to_owned(),
msg.guild_id,
&location,
timestamp,
interval,
&content).await;
if res.is_ok() {
issue_count += 1;
}
}
let content = user_data.response(&pool, "natural/bulk_set").await.replace("{count}", &issue_count.to_string());
let _ = msg.channel_id.say(&ctx, content).await;
}
} }
else { else {
let _ = msg.channel_id.say(&ctx, "DEV ERROR: Failed to invoke Python").await; let _ = msg.channel_id.say(&ctx, "DEV ERROR: Failed to invoke Python").await;

View File

@ -8,13 +8,17 @@ mod time_parser;
mod consts; mod consts;
use serenity::{ use serenity::{
cache::Cache,
http::CacheHttp, http::CacheHttp,
client::{ client::{
bridge::gateway::GatewayIntents, bridge::gateway::GatewayIntents,
Client, Client,
}, },
model::id::{ model::{
GuildId, UserId, id::{
GuildId, UserId,
},
channel::Message,
}, },
framework::Framework, framework::Framework,
prelude::TypeMapKey, prelude::TypeMapKey,
@ -164,3 +168,8 @@ pub async fn check_subscription(cache_http: impl CacheHttp, user_id: impl Into<U
true true
} }
} }
pub async fn check_subscription_on_message(cache_http: impl CacheHttp + AsRef<Cache>, msg: &Message) -> bool {
check_subscription(&cache_http, &msg.author).await ||
if let Some(guild) = msg.guild(&cache_http).await { check_subscription(&cache_http, guild.owner_id).await } else { false }
}