rework of remind command. updated a dep. fixed an issue in parsing absolute times
This commit is contained in:
parent
55437b76eb
commit
3879c83085
@ -9,7 +9,7 @@ dotenv = "0.15"
|
|||||||
tokio = { version = "0.2", features = ["process"] }
|
tokio = { version = "0.2", features = ["process"] }
|
||||||
reqwest = { version = "0.10", features = ["rustls-tls"] }
|
reqwest = { version = "0.10", features = ["rustls-tls"] }
|
||||||
sqlx = { version = "0.4", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal", "chrono"] }
|
sqlx = { version = "0.4", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal", "chrono"] }
|
||||||
regex = "1.3"
|
regex = "1.4"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
|
@ -49,7 +49,7 @@ async fn help(ctx: &Context, msg: &Message, _args: String) {
|
|||||||
.channel_id
|
.channel_id
|
||||||
.send_message(ctx, |m| {
|
.send_message(ctx, |m| {
|
||||||
m.embed(move |e| {
|
m.embed(move |e| {
|
||||||
e.title("Help")
|
e.title("Help Menu")
|
||||||
.description(desc)
|
.description(desc)
|
||||||
.footer(|f| {
|
.footer(|f| {
|
||||||
f.text(concat!(
|
f.text(concat!(
|
||||||
|
@ -3,7 +3,6 @@ use custom_error::custom_error;
|
|||||||
use regex_command_attr::command;
|
use regex_command_attr::command;
|
||||||
|
|
||||||
use serenity::{
|
use serenity::{
|
||||||
cache::Cache,
|
|
||||||
client::Context,
|
client::Context,
|
||||||
http::CacheHttp,
|
http::CacheHttp,
|
||||||
model::{
|
model::{
|
||||||
@ -22,7 +21,8 @@ use crate::{
|
|||||||
check_subscription_on_message,
|
check_subscription_on_message,
|
||||||
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_CHANNEL, REGEX_CHANNEL_USER, REGEX_CONTENT_SUBSTITUTION, REGEX_INTERVAL_COMMAND,
|
||||||
|
REGEX_REMIND_COMMAND,
|
||||||
},
|
},
|
||||||
framework::SendIterator,
|
framework::SendIterator,
|
||||||
models::{ChannelData, GuildData, Timer, UserData},
|
models::{ChannelData, GuildData, Timer, UserData},
|
||||||
@ -32,8 +32,6 @@ use crate::{
|
|||||||
|
|
||||||
use chrono::{offset::TimeZone, NaiveDateTime};
|
use chrono::{offset::TimeZone, NaiveDateTime};
|
||||||
|
|
||||||
use chrono_tz::Etc::UTC;
|
|
||||||
|
|
||||||
use rand::{rngs::OsRng, seq::IteratorRandom};
|
use rand::{rngs::OsRng, seq::IteratorRandom};
|
||||||
|
|
||||||
use sqlx::{encode::Encode, MySql, MySqlPool, Type};
|
use sqlx::{encode::Encode, MySql, MySqlPool, Type};
|
||||||
@ -153,7 +151,7 @@ async fn pause(ctx: &Context, msg: &Message, args: String) {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let parser = TimeParser::new(args, timezone);
|
let parser = TimeParser::new(&args, timezone);
|
||||||
let pause_until = parser.timestamp();
|
let pause_until = parser.timestamp();
|
||||||
|
|
||||||
match pause_until {
|
match pause_until {
|
||||||
@ -211,7 +209,7 @@ async fn offset(ctx: &Context, msg: &Message, args: String) {
|
|||||||
.say(&ctx, lm.get(&user_data.language, "offset/help"))
|
.say(&ctx, lm.get(&user_data.language, "offset/help"))
|
||||||
.await;
|
.await;
|
||||||
} else {
|
} else {
|
||||||
let parser = TimeParser::new(args, user_data.timezone());
|
let parser = TimeParser::new(&args, user_data.timezone());
|
||||||
|
|
||||||
if let Ok(displacement) = parser.displacement() {
|
if let Ok(displacement) = parser.displacement() {
|
||||||
if let Some(guild) = msg.guild(&ctx).await {
|
if let Some(guild) = msg.guild(&ctx).await {
|
||||||
@ -292,7 +290,7 @@ async fn nudge(ctx: &Context, msg: &Message, args: String) {
|
|||||||
|
|
||||||
let _ = msg.channel_id.say(&ctx, content).await;
|
let _ = msg.channel_id.say(&ctx, content).await;
|
||||||
} else {
|
} else {
|
||||||
let parser = TimeParser::new(args, timezone);
|
let parser = TimeParser::new(&args, timezone);
|
||||||
let nudge_time = parser.displacement();
|
let nudge_time = parser.displacement();
|
||||||
|
|
||||||
match nudge_time {
|
match nudge_time {
|
||||||
@ -811,16 +809,20 @@ async fn timer(ctx: &Context, msg: &Message, args: String) {
|
|||||||
Some("list") => {
|
Some("list") => {
|
||||||
let timers = Timer::from_owner(owner, &pool).await;
|
let timers = Timer::from_owner(owner, &pool).await;
|
||||||
|
|
||||||
let _ =
|
let _ = msg
|
||||||
msg.channel_id
|
.channel_id
|
||||||
.send_message(&ctx, |m| {
|
.send_message(&ctx, |m| {
|
||||||
m.embed(|e| {
|
m.embed(|e| {
|
||||||
e.fields(timers.iter().map(|timer| {
|
e.fields(timers.iter().map(|timer| {
|
||||||
(&timer.name, time_difference(timer.start_time), false)
|
(
|
||||||
}))
|
&timer.name,
|
||||||
})
|
format!("⏳ `{}`", time_difference(timer.start_time)),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
.await;
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some("start") => {
|
Some("start") => {
|
||||||
@ -1003,60 +1005,28 @@ async fn remind(ctx: &Context, msg: &Message, args: String) {
|
|||||||
#[command("interval")]
|
#[command("interval")]
|
||||||
#[permission_level(Managed)]
|
#[permission_level(Managed)]
|
||||||
async fn interval(ctx: &Context, msg: &Message, args: String) {
|
async fn interval(ctx: &Context, msg: &Message, args: String) {
|
||||||
remind_command(ctx, msg, args, RemindCommand::Interval).await;
|
if check_subscription_on_message(&ctx, msg).await {
|
||||||
|
remind_command(ctx, msg, args, RemindCommand::Interval).await;
|
||||||
|
} else {
|
||||||
|
let _ = msg.channel_id.say(&ctx, "interval/donor").await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn remind_command(ctx: &Context, msg: &Message, args: String, command: RemindCommand) {
|
async fn remind_command(ctx: &Context, msg: &Message, args: String, command: RemindCommand) {
|
||||||
async fn check_interval(
|
fn parse_mention_list(mentions: &str) -> Vec<ReminderScope> {
|
||||||
ctx: impl CacheHttp + AsRef<Cache>,
|
REGEX_CHANNEL_USER
|
||||||
msg: &Message,
|
.captures_iter(mentions)
|
||||||
mut args_iter: impl Iterator<Item = &str>,
|
.map(|i| {
|
||||||
scope_id: &ReminderScope,
|
let pref = i.get(1).unwrap().as_str();
|
||||||
time_parser: &TimeParser,
|
let id = i.get(2).unwrap().as_str().parse::<u64>().unwrap();
|
||||||
command: RemindCommand,
|
|
||||||
pool: &MySqlPool,
|
|
||||||
) -> Result<(), ReminderError> {
|
|
||||||
if command == RemindCommand::Interval && check_subscription_on_message(&ctx, &msg).await {
|
|
||||||
if let Some(interval_arg) = args_iter.next() {
|
|
||||||
let interval = TimeParser::new(interval_arg.to_string(), UTC);
|
|
||||||
|
|
||||||
if let Ok(interval_seconds) = interval.displacement() {
|
if pref == "#" {
|
||||||
let content = args_iter.collect::<Vec<&str>>().join(" ");
|
ReminderScope::Channel(id)
|
||||||
|
|
||||||
create_reminder(
|
|
||||||
ctx,
|
|
||||||
pool,
|
|
||||||
msg.author.id.as_u64().to_owned(),
|
|
||||||
msg.guild_id,
|
|
||||||
scope_id,
|
|
||||||
time_parser,
|
|
||||||
Some(interval_seconds),
|
|
||||||
content,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
} else {
|
} else {
|
||||||
Err(ReminderError::InvalidTime)
|
ReminderScope::User(id)
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
Err(ReminderError::NotEnoughArgs)
|
.collect::<Vec<ReminderScope>>()
|
||||||
}
|
|
||||||
} else if command == RemindCommand::Interval {
|
|
||||||
Err(ReminderError::NeedSubscription)
|
|
||||||
} else {
|
|
||||||
let content = args_iter.collect::<Vec<&str>>().join(" ");
|
|
||||||
|
|
||||||
create_reminder(
|
|
||||||
ctx,
|
|
||||||
pool,
|
|
||||||
msg.author.id.as_u64().to_owned(),
|
|
||||||
msg.guild_id,
|
|
||||||
scope_id,
|
|
||||||
time_parser,
|
|
||||||
None,
|
|
||||||
content,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let pool;
|
let pool;
|
||||||
@ -1075,74 +1045,55 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
|
|||||||
|
|
||||||
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 mut args_iter = args.split(' ').filter(|s| !s.is_empty());
|
let captures = match command {
|
||||||
|
RemindCommand::Remind => REGEX_REMIND_COMMAND.captures(&args),
|
||||||
|
|
||||||
let mut time_parser = None;
|
RemindCommand::Interval => REGEX_INTERVAL_COMMAND.captures(&args),
|
||||||
let mut scope_id = ReminderScope::Channel(msg.channel_id.as_u64().to_owned());
|
|
||||||
|
|
||||||
// todo reimplement using next_if and Peekable
|
|
||||||
let response = if let Some(first_arg) = args_iter.next().map(|s| s.to_string()) {
|
|
||||||
if let Some((Some(scope_match), Some(id_match))) = REGEX_CHANNEL_USER
|
|
||||||
.captures(&first_arg)
|
|
||||||
.map(|cap| (cap.get(1), cap.get(2)))
|
|
||||||
{
|
|
||||||
if scope_match.as_str() == "@" {
|
|
||||||
scope_id = ReminderScope::User(id_match.as_str().parse::<u64>().unwrap());
|
|
||||||
} else {
|
|
||||||
scope_id = ReminderScope::Channel(id_match.as_str().parse::<u64>().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(next) = args_iter.next().map(|inner| inner.to_string()) {
|
|
||||||
time_parser = Some(TimeParser::new(next, user_data.timezone.parse().unwrap()));
|
|
||||||
|
|
||||||
check_interval(
|
|
||||||
&ctx,
|
|
||||||
msg,
|
|
||||||
args_iter,
|
|
||||||
&scope_id,
|
|
||||||
&time_parser.as_ref().unwrap(),
|
|
||||||
command,
|
|
||||||
&pool,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
} else {
|
|
||||||
Err(ReminderError::NotEnoughArgs)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
time_parser = Some(TimeParser::new(first_arg, user_data.timezone()));
|
|
||||||
|
|
||||||
check_interval(
|
|
||||||
&ctx,
|
|
||||||
msg,
|
|
||||||
args_iter,
|
|
||||||
&scope_id,
|
|
||||||
&time_parser.as_ref().unwrap(),
|
|
||||||
command,
|
|
||||||
&pool,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(ReminderError::NotEnoughArgs)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = time_parser
|
match captures {
|
||||||
.map(|tp| tp.displacement().ok())
|
Some(captures) => {
|
||||||
.flatten()
|
let scopes = if let Some(mentions) = captures.name("mentions") {
|
||||||
.unwrap_or(0) as u64;
|
parse_mention_list(mentions.as_str())
|
||||||
|
} else {
|
||||||
|
vec![ReminderScope::Channel(msg.channel_id.into())]
|
||||||
|
};
|
||||||
|
|
||||||
let str_response = lm
|
let time_parser = TimeParser::new(
|
||||||
.get(&user_data.language, &response.to_response())
|
captures.name("time").unwrap().as_str(),
|
||||||
.replace(
|
user_data.timezone(),
|
||||||
"{prefix}",
|
);
|
||||||
&GuildData::prefix_from_id(msg.guild_id, &pool).await,
|
|
||||||
)
|
|
||||||
.replacen("{location}", &scope_id.mention(), 1)
|
|
||||||
.replacen("{offset}", &shorthand_displacement(offset), 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;
|
let interval_parser = captures
|
||||||
|
.name("interval")
|
||||||
|
.map(|mat| TimeParser::new(mat.as_str(), user_data.timezone()))
|
||||||
|
// todo remove unwrap below
|
||||||
|
.map(|parser| parser.displacement().unwrap());
|
||||||
|
|
||||||
|
let content = captures.name("content").map(|mat| mat.as_str()).unwrap();
|
||||||
|
|
||||||
|
for scope in scopes {
|
||||||
|
create_reminder(
|
||||||
|
&ctx,
|
||||||
|
&pool,
|
||||||
|
msg.author.id,
|
||||||
|
msg.guild_id,
|
||||||
|
&scope,
|
||||||
|
&time_parser,
|
||||||
|
interval_parser,
|
||||||
|
content,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None => {
|
||||||
|
let _ = msg
|
||||||
|
.channel_id
|
||||||
|
.say(&ctx, lm.get(&user_data.language, "remind/invalid"))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command("natural")]
|
#[command("natural")]
|
||||||
@ -1274,7 +1225,7 @@ async fn natural(ctx: &Context, msg: &Message, args: String) {
|
|||||||
let res = create_reminder(
|
let res = create_reminder(
|
||||||
&ctx,
|
&ctx,
|
||||||
&pool,
|
&pool,
|
||||||
msg.author.id.as_u64().to_owned(),
|
msg.author.id,
|
||||||
msg.guild_id,
|
msg.guild_id,
|
||||||
&location_id,
|
&location_id,
|
||||||
timestamp,
|
timestamp,
|
||||||
@ -1304,7 +1255,7 @@ async fn natural(ctx: &Context, msg: &Message, args: String) {
|
|||||||
let res = create_reminder(
|
let res = create_reminder(
|
||||||
&ctx,
|
&ctx,
|
||||||
&pool,
|
&pool,
|
||||||
msg.author.id.as_u64().to_owned(),
|
msg.author.id,
|
||||||
msg.guild_id,
|
msg.guild_id,
|
||||||
&location,
|
&location,
|
||||||
timestamp,
|
timestamp,
|
||||||
@ -1344,16 +1295,23 @@ async fn natural(ctx: &Context, msg: &Message, args: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_reminder<'a, T: TryInto<i64>, S: ToString + Type<MySql> + Encode<'a, MySql>>(
|
async fn create_reminder<
|
||||||
|
'a,
|
||||||
|
U: Into<u64>,
|
||||||
|
T: TryInto<i64>,
|
||||||
|
S: ToString + Type<MySql> + Encode<'a, MySql>,
|
||||||
|
>(
|
||||||
ctx: impl CacheHttp,
|
ctx: impl CacheHttp,
|
||||||
pool: &MySqlPool,
|
pool: &MySqlPool,
|
||||||
user_id: u64,
|
user_id: U,
|
||||||
guild_id: Option<GuildId>,
|
guild_id: Option<GuildId>,
|
||||||
scope_id: &ReminderScope,
|
scope_id: &ReminderScope,
|
||||||
time_parser: T,
|
time_parser: T,
|
||||||
interval: Option<i64>,
|
interval: Option<i64>,
|
||||||
content: S,
|
content: S,
|
||||||
) -> Result<(), ReminderError> {
|
) -> Result<(), ReminderError> {
|
||||||
|
let user_id = user_id.into();
|
||||||
|
|
||||||
let mut content_string = content.to_string();
|
let mut content_string = content.to_string();
|
||||||
|
|
||||||
// substitution filters
|
// substitution filters
|
||||||
|
@ -11,6 +11,27 @@ use std::{collections::HashSet, env, iter::FromIterator};
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
pub static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap();
|
||||||
|
|
||||||
|
pub static ref REGEX_ROLE: Regex = Regex::new(r#"<@&(\d+)>"#).unwrap();
|
||||||
|
|
||||||
|
pub static ref REGEX_COMMANDS: Regex = Regex::new(r#"([a-z]+)"#).unwrap();
|
||||||
|
|
||||||
|
pub static ref REGEX_ALIAS: Regex =
|
||||||
|
Regex::new(r#"(?P<name>[\S]{1,12})(?:(?: (?P<cmd>.*)$)|$)"#).unwrap();
|
||||||
|
|
||||||
|
pub static ref REGEX_CONTENT_SUBSTITUTION: Regex = Regex::new(r#"<<(\d+)>>"#).unwrap();
|
||||||
|
|
||||||
|
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>.*)"#)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
pub static ref SUBSCRIPTION_ROLES: HashSet<u64> = HashSet::from_iter(
|
pub static ref SUBSCRIPTION_ROLES: HashSet<u64> = HashSet::from_iter(
|
||||||
env::var("SUBSCRIPTION_ROLES")
|
env::var("SUBSCRIPTION_ROLES")
|
||||||
.map(|var| var
|
.map(|var| var
|
||||||
@ -23,31 +44,31 @@ lazy_static! {
|
|||||||
.map(|var| var.parse::<u64>().ok())
|
.map(|var| var.parse::<u64>().ok())
|
||||||
.ok()
|
.ok()
|
||||||
.flatten();
|
.flatten();
|
||||||
pub static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap();
|
|
||||||
pub static ref REGEX_ROLE: Regex = Regex::new(r#"<@&([0-9]+)>"#).unwrap();
|
|
||||||
pub static ref REGEX_COMMANDS: Regex = Regex::new(r#"([a-z]+)"#).unwrap();
|
|
||||||
pub static ref REGEX_ALIAS: Regex =
|
|
||||||
Regex::new(r#"(?P<name>[\S]{1,12})(?:(?: (?P<cmd>.*)$)|$)"#).unwrap();
|
|
||||||
pub static ref REGEX_CONTENT_SUBSTITUTION: Regex = Regex::new(r#"<<(\d+)>>"#).unwrap();
|
|
||||||
pub static ref REGEX_CHANNEL_USER: Regex = Regex::new(r#"\s*<(#|@)(?:!)?(\d+)>\s*"#).unwrap();
|
|
||||||
pub static ref MIN_INTERVAL: i64 = env::var("MIN_INTERVAL")
|
pub static ref MIN_INTERVAL: i64 = env::var("MIN_INTERVAL")
|
||||||
.ok()
|
.ok()
|
||||||
.map(|inner| inner.parse::<i64>().ok())
|
.map(|inner| inner.parse::<i64>().ok())
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or(600);
|
.unwrap_or(600);
|
||||||
|
|
||||||
pub static ref MAX_TIME: i64 = env::var("MAX_TIME")
|
pub static ref MAX_TIME: i64 = env::var("MAX_TIME")
|
||||||
.ok()
|
.ok()
|
||||||
.map(|inner| inner.parse::<i64>().ok())
|
.map(|inner| inner.parse::<i64>().ok())
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or(60 * 60 * 24 * 365 * 50);
|
.unwrap_or(60 * 60 * 24 * 365 * 50);
|
||||||
|
|
||||||
pub static ref LOCAL_TIMEZONE: String =
|
pub static ref LOCAL_TIMEZONE: String =
|
||||||
env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string());
|
env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string());
|
||||||
|
|
||||||
pub static ref LOCAL_LANGUAGE: String =
|
pub static ref LOCAL_LANGUAGE: String =
|
||||||
env::var("LOCAL_LANGUAGE").unwrap_or_else(|_| "EN".to_string());
|
env::var("LOCAL_LANGUAGE").unwrap_or_else(|_| "EN".to_string());
|
||||||
|
|
||||||
pub static ref PYTHON_LOCATION: String =
|
pub static ref PYTHON_LOCATION: String =
|
||||||
env::var("PYTHON_LOCATION").unwrap_or_else(|_| "venv/bin/python3".to_string());
|
env::var("PYTHON_LOCATION").unwrap_or_else(|_| "venv/bin/python3".to_string());
|
||||||
|
|
||||||
pub static ref DEFAULT_PREFIX: String =
|
pub static ref DEFAULT_PREFIX: String =
|
||||||
env::var("DEFAULT_PREFIX").unwrap_or_else(|_| "$".to_string());
|
env::var("DEFAULT_PREFIX").unwrap_or_else(|_| "$".to_string());
|
||||||
|
|
||||||
pub static ref THEME_COLOR: u32 = env::var("THEME_COLOR").map_or(
|
pub static ref THEME_COLOR: u32 = env::var("THEME_COLOR").map_or(
|
||||||
THEME_COLOR_FALLBACK,
|
THEME_COLOR_FALLBACK,
|
||||||
|inner| u32::from_str_radix(&inner, 16).unwrap_or(THEME_COLOR_FALLBACK)
|
|inner| u32::from_str_radix(&inner, 16).unwrap_or(THEME_COLOR_FALLBACK)
|
||||||
|
@ -43,7 +43,7 @@ impl TryFrom<&TimeParser> for i64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TimeParser {
|
impl TimeParser {
|
||||||
pub fn new(input: String, timezone: Tz) -> Self {
|
pub fn new(input: &str, timezone: Tz) -> Self {
|
||||||
let inverted = input.starts_with('-');
|
let inverted = input.starts_with('-');
|
||||||
|
|
||||||
let parse_type = if input.contains('/') || input.contains(':') {
|
let parse_type = if input.contains('/') || input.contains(':') {
|
||||||
@ -104,7 +104,7 @@ impl TimeParser {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok("".to_string())
|
Ok("".to_string())
|
||||||
}? + if segments == 1 {
|
}? + {
|
||||||
let colons = self.time_string.matches(':').count();
|
let colons = self.time_string.matches(':').count();
|
||||||
|
|
||||||
match colons {
|
match colons {
|
||||||
@ -112,8 +112,6 @@ impl TimeParser {
|
|||||||
2 => Ok("%H:%M:%S"),
|
2 => Ok("%H:%M:%S"),
|
||||||
_ => Err(InvalidTime::ParseErrorHMS),
|
_ => Err(InvalidTime::ParseErrorHMS),
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Ok("")
|
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let dt = self
|
let dt = self
|
||||||
|
Loading…
Reference in New Issue
Block a user