updated serenity to latest current. interval and remind commands are now operationally identical using one regex. interval accepts an optional third parameter which is an expiration point

This commit is contained in:
jellywx 2021-01-03 14:48:18 +00:00
parent c7c3b14c2d
commit 99c4a23bf0
5 changed files with 204 additions and 196 deletions

7
Cargo.lock generated
View File

@ -1316,7 +1316,7 @@ dependencies = [
[[package]]
name = "reminder_rs"
version = "1.3.5"
version = "1.4.0"
dependencies = [
"Inflector",
"async-trait",
@ -1539,8 +1539,8 @@ dependencies = [
[[package]]
name = "serenity"
version = "0.9.0-rc.3"
source = "git+https://github.com/jellywx/serenity?branch=jellywx-member_permissions#fc0af6a865d2cfdeeefbb02d297950bc34c0d87b"
version = "0.9.3"
source = "git+https://github.com/serenity-rs/serenity?branch=current#0b1fc2737efebde01f6f3b781bcdfc83a30e908e"
dependencies = [
"async-trait",
"async-tungstenite",
@ -1550,6 +1550,7 @@ dependencies = [
"chrono",
"flate2",
"futures",
"percent-encoding",
"reqwest",
"serde",
"serde_json",

View File

@ -1,6 +1,6 @@
[package]
name = "reminder_rs"
version = "1.3.5"
version = "1.4.0"
authors = ["jellywx <judesouthworth@pm.me>"]
edition = "2018"
@ -25,8 +25,8 @@ Inflector = "0.11"
levenshtein = "1.0"
[dependencies.serenity]
git = "https://github.com/jellywx/serenity"
branch = "jellywx-member_permissions"
git = "https://github.com/serenity-rs/serenity"
branch = "current"
default-features = false
features = ["builder", "client", "framework", "cache", "gateway", "http", "model", "utils", "rustls_backend", "collector"]

View File

@ -3,7 +3,12 @@ use regex_command_attr::command;
use serenity::{
client::Context,
framework::Framework,
model::{channel::Message, channel::ReactionType, id::ChannelId, id::RoleId},
model::{
channel::ReactionType,
channel::{Channel, Message},
id::ChannelId,
id::RoleId,
},
};
use chrono_tz::{Tz, TZ_VARIANTS};
@ -312,10 +317,12 @@ async fn language(ctx: &Context, msg: &Message, args: String) {
.all_languages()
.map(|(k, _)| ReactionType::Unicode(lm.get(k, "flag").to_string()));
let can_react = if let Some(guild) = msg.guild(&ctx).await {
guild
.user_permissions_in(msg.channel_id, ctx.cache.current_user().await)
.add_reactions()
let can_react = if let Some(Channel::Guild(channel)) = msg.channel(&ctx).await {
channel
.permissions_for_user(&ctx, ctx.cache.current_user().await)
.await
.map(|p| p.add_reactions())
.unwrap_or(false)
} else {
true
};
@ -367,11 +374,14 @@ async fn language(ctx: &Context, msg: &Message, args: String) {
}
}
if let Some(guild) = msg.guild(&ctx).await {
let perms =
guild.user_permissions_in(msg.channel_id, ctx.cache.current_user().await);
if let Some(Channel::Guild(channel)) = msg.channel(&ctx).await {
let has_perms = channel
.permissions_for_user(&ctx, ctx.cache.current_user().await)
.await
.map(|p| p.manage_messages())
.unwrap_or(false);
if perms.manage_messages() {
if has_perms {
let _ = sent_msg.delete_reactions(&ctx).await;
}
}

View File

@ -19,8 +19,8 @@ use crate::{
check_subscription_on_message, command_help,
consts::{
CHARACTERS, DAY, HOUR, LOCAL_TIMEZONE, MAX_TIME, MINUTE, MIN_INTERVAL, PYTHON_LOCATION,
REGEX_CHANNEL, REGEX_CHANNEL_USER, REGEX_CONTENT_SUBSTITUTION, REGEX_INTERVAL_COMMAND,
REGEX_REMIND_COMMAND, THEME_COLOR,
REGEX_CHANNEL, REGEX_CHANNEL_USER, REGEX_CONTENT_SUBSTITUTION, REGEX_REMIND_COMMAND,
THEME_COLOR,
},
framework::SendIterator,
get_ctx_data,
@ -818,6 +818,7 @@ enum ReminderError {
InvalidTag,
NotEnoughArgs,
InvalidTime,
InvalidExpiration,
NeedSubscription,
DiscordError(String),
}
@ -846,6 +847,7 @@ impl ToResponse for ReminderError {
Self::InvalidTag => "remind/invalid_tag",
Self::NotEnoughArgs => "remind/no_argument",
Self::InvalidTime => "remind/invalid_time",
Self::InvalidExpiration => "interval/invalid_expiration",
Self::NeedSubscription => "interval/donor",
Self::DiscordError(_) => "remind/generic_error",
}
@ -1010,33 +1012,10 @@ fn parse_mention_list(mentions: &str) -> Vec<ReminderScope> {
async fn remind_command(ctx: &Context, msg: &Message, args: String, command: RemindCommand) {
let (pool, lm) = get_ctx_data(&ctx).await;
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
let timezone = UserData::timezone_of(&msg.author, &pool).await;
let language = UserData::language_of(&msg.author, &pool).await;
if command == RemindCommand::Interval {
if !check_subscription_on_message(&ctx, msg).await {
// breaker
let _ = msg
.channel_id
.say(
&ctx,
lm.get(&user_data.language, "interval/donor").replace(
"{prefix}",
&GuildData::prefix_from_id(msg.guild_id, &pool).await,
),
)
.await;
return;
}
}
let captures = match command {
RemindCommand::Remind => REGEX_REMIND_COMMAND.captures(&args),
RemindCommand::Interval => REGEX_INTERVAL_COMMAND.captures(&args),
};
match captures {
match REGEX_REMIND_COMMAND.captures(&args) {
Some(captures) => {
let parsed = parse_mention_list(captures.name("mentions").unwrap().as_str());
@ -1046,18 +1025,32 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
parsed
};
let time_parser = TimeParser::new(
captures.name("time").unwrap().as_str(),
user_data.timezone(),
);
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(), user_data.timezone()))
.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}",
&GuildData::prefix_from_id(msg.guild_id, &pool).await,
),
)
.await;
} else {
let content_res = Content::build(
captures.name("content").map(|mat| mat.as_str()).unwrap(),
msg,
@ -1078,6 +1071,7 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
msg.guild_id,
&scope,
&time_parser,
expires_parser.as_ref().clone(),
interval,
&mut content,
)
@ -1094,16 +1088,16 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
let success_part = match ok_locations.len() {
0 => "".to_string(),
1 => lm
.get(&user_data.language, "remind/success")
.get(&language, "remind/success")
.replace("{location}", &ok_locations[0].mention())
.replace(
"{offset}",
&shorthand_displacement(
time_parser.displacement().unwrap() as u64
time_parser.displacement().unwrap() as u64,
),
),
n => lm
.get(&user_data.language, "remind/success_bulk")
.get(&language, "remind/success_bulk")
.replace("{number}", &n.to_string())
.replace(
"{location}",
@ -1116,7 +1110,7 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
.replace(
"{offset}",
&shorthand_displacement(
time_parser.displacement().unwrap() as u64
time_parser.displacement().unwrap() as u64,
),
),
};
@ -1126,10 +1120,10 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
match err_locations.len() {
0 => "".to_string(),
1 => lm
.get(&user_data.language, "remind/issue")
.get(&language, "remind/issue")
.replace("{location}", &err_locations[0].mention()),
n => lm
.get(&user_data.language, "remind/issue_bulk")
.get(&language, "remind/issue_bulk")
.replace("{number}", &n.to_string())
.replace(
"{location}",
@ -1144,10 +1138,10 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
.iter()
.map(|err| match err {
ReminderError::DiscordError(s) => lm
.get(&user_data.language, err.to_response())
.get(&language, err.to_response())
.replace("{error}", &s),
_ => lm.get(&user_data.language, err.to_response()).to_string(),
_ => lm.get(&language, err.to_response()).to_string(),
})
.collect::<Vec<String>>()
.join("\n")
@ -1158,8 +1152,10 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
.send_message(&ctx, |m| {
m.embed(|e| {
e.title(
lm.get(&user_data.language, "remind/title")
.replace("{number}", &ok_locations.len().to_string()),
lm.get(&language, "remind/title").replace(
"{number}",
&ok_locations.len().to_string(),
),
)
.description(format!("{}\n\n{}", success_part, error_part))
.color(*THEME_COLOR)
@ -1174,28 +1170,24 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
.send_message(ctx, |m| {
m.embed(move |e| {
e.title(
lm.get(&user_data.language, "remind/title")
lm.get(&language, "remind/title")
.replace("{number}", "0"),
)
.description(
lm.get(&user_data.language, content_error.to_response()),
)
.description(lm.get(&language, content_error.to_response()))
.color(*THEME_COLOR)
})
})
.await;
}
}
}
} else {
let _ = msg
.channel_id
.send_message(ctx, |m| {
m.embed(move |e| {
e.title(
lm.get(&user_data.language, "remind/title")
.replace("{number}", "0"),
)
.description(lm.get(&user_data.language, "interval/invalid_interval"))
e.title(lm.get(&language, "remind/title").replace("{number}", "0"))
.description(lm.get(&language, "interval/invalid_interval"))
.color(*THEME_COLOR)
})
})
@ -1208,11 +1200,11 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
match command {
RemindCommand::Remind => {
command_help(ctx, msg, lm, &prefix, &user_data.language, "remind").await
command_help(ctx, msg, lm, &prefix, &language, "remind").await
}
RemindCommand::Interval => {
command_help(ctx, msg, lm, &prefix, &user_data.language, "interval").await
command_help(ctx, msg, lm, &prefix, &language, "interval").await
}
}
}
@ -1336,6 +1328,7 @@ async fn natural(ctx: &Context, msg: &Message, args: String) {
msg.guild_id,
&scope,
timestamp,
None,
interval,
&mut content,
)
@ -1463,6 +1456,7 @@ async fn create_reminder<'a, U: Into<u64>, T: TryInto<i64>>(
guild_id: Option<GuildId>,
scope_id: &ReminderScope,
time_parser: T,
expires_parser: Option<T>,
interval: Option<i64>,
content: &mut Content,
) -> Result<(), ReminderError> {
@ -1527,6 +1521,8 @@ async fn create_reminder<'a, U: Into<u64>, T: TryInto<i64>>(
} else {
match time_parser.try_into() {
Ok(time_pre) => {
match expires_parser.map(|t| t.try_into()).transpose() {
Ok(expires) => {
let time = time_pre + nudge as i64;
let unix_time = SystemTime::now()
@ -1553,16 +1549,17 @@ INSERT INTO messages (content, tts, attachment, attachment_name) VALUES (?, ?, ?
sqlx::query!(
"
INSERT INTO reminders (uid, message_id, channel_id, time, `interval`, method, set_by) VALUES
INSERT INTO reminders (uid, message_id, channel_id, time, expires, `interval`, method, set_by) VALUES
(?,
(SELECT id FROM messages WHERE content = ? ORDER BY id DESC LIMIT 1),
?, ?, ?, 'remind',
?, ?, ?, ?, 'remind',
(SELECT id FROM users WHERE user = ? LIMIT 1))
",
generate_uid(),
content.content,
db_channel_id,
time as u32,
expires,
interval,
user_id
)
@ -1580,6 +1577,10 @@ INSERT INTO reminders (uid, message_id, channel_id, time, `interval`, method, se
}
}
Err(_) => Err(ReminderError::InvalidExpiration),
}
}
Err(_) => Err(ReminderError::InvalidTime),
}
}

View File

@ -50,11 +50,7 @@ lazy_static! {
pub static ref REGEX_CHANNEL_USER: Regex = Regex::new(r#"\s*<(#|@)(?:!)?(\d+)>\s*"#).unwrap();
pub static ref REGEX_REMIND_COMMAND: Regex = Regex::new(
r#"(?P<mentions>(?:<@\d+>\s|<@!\d+>\s|<#\d+>\s)*)(?P<time>(?:(?:\d+)(?:s|m|h|d|:|/|-|))+|()) (?P<content>.*)"#)
.unwrap();
pub static ref REGEX_INTERVAL_COMMAND: Regex = Regex::new(
r#"(?P<mentions>(?:<@\d+>\s|<@!\d+>\s|<#\d+>\s)*)(?P<time>(?:(?:\d+)(?:s|m|h|d|:|/|-|))+) (?P<interval>(?:(?:\d+)(?:s|m|h|d|))+) (?P<content>.*)"#)
r#"(?P<mentions>(?:<@\d+>\s|<@!\d+>\s|<#\d+>\s)*)(?P<time>(?:(?:\d+)(?:s|m|h|d|:|/|-|))+)(?:\s+(?P<interval>(?:(?:\d+)(?:s|m|h|d|))+))?(?:\s+(?P<expires>(?:(?:\d+)(?:s|m|h|d|:|/|-|))+))?\s+(?P<content>.*)"#)
.unwrap();
pub static ref SUBSCRIPTION_ROLES: HashSet<u64> = HashSet::from_iter(