time parser struct
This commit is contained in:
parent
c1a4092e3c
commit
74617d50a5
@ -72,7 +72,12 @@ async fn clock(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|||||||
|
|
||||||
let now = Utc::now().with_timezone(&tz);
|
let now = Utc::now().with_timezone(&tz);
|
||||||
|
|
||||||
let _ = msg.channel_id.say(&ctx, format!("Current time: **{}**", now.format("%H:%M:%S"))).await;
|
if args == "12".to_string() {
|
||||||
|
let _ = msg.channel_id.say(&ctx, format!("Current time: **{}**", now.format("%I:%M:%S %p"))).await;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let _ = msg.channel_id.say(&ctx, format!("Current time: **{}**", now.format("%H:%M:%S"))).await;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
SQLPool,
|
SQLPool,
|
||||||
framework::SendFromDb,
|
framework::SendFromDb,
|
||||||
|
time_parser::TimeParser,
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -143,15 +144,3 @@ async fn prefix(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
|
||||||
async fn pause(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|
||||||
let pool = ctx.data.read().await
|
|
||||||
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
||||||
|
|
||||||
let channel = ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), pool.clone()).await.unwrap();
|
|
||||||
|
|
||||||
channel.commit_changes(pool).await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
use regex_command_attr::command;
|
||||||
|
|
||||||
|
use serenity::{
|
||||||
|
client::Context,
|
||||||
|
model::{
|
||||||
|
channel::{
|
||||||
|
Message,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
framework::standard::CommandResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
use chrono_tz::{
|
||||||
|
Tz,
|
||||||
|
Etc::UTC,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
models::{
|
||||||
|
ChannelData,
|
||||||
|
UserData,
|
||||||
|
},
|
||||||
|
SQLPool,
|
||||||
|
framework::SendFromDb,
|
||||||
|
time_parser::TimeParser,
|
||||||
|
};
|
||||||
|
|
||||||
|
use chrono::NaiveDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
async fn pause(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
||||||
|
let pool = ctx.data.read().await
|
||||||
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
||||||
|
|
||||||
|
let user_data = UserData::from_id(&msg.author, &ctx, pool.clone()).await.unwrap();
|
||||||
|
let mut channel = ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), pool.clone()).await.unwrap();
|
||||||
|
|
||||||
|
if args.len() == 0 {
|
||||||
|
channel.paused = !channel.paused;
|
||||||
|
channel.paused_until = None;
|
||||||
|
|
||||||
|
channel.commit_changes(pool).await;
|
||||||
|
|
||||||
|
if channel.paused {
|
||||||
|
let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/paused_indefinite").await;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/unpaused").await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let parser = TimeParser::new(args, user_data.timezone.parse().unwrap());
|
||||||
|
let pause_until = parser.timestamp();
|
||||||
|
|
||||||
|
match pause_until {
|
||||||
|
Ok(timestamp) => {
|
||||||
|
channel.paused = true;
|
||||||
|
channel.paused_until = Some(NaiveDateTime::from_timestamp(timestamp, 0));
|
||||||
|
|
||||||
|
channel.commit_changes(pool).await;
|
||||||
|
|
||||||
|
let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/paused_until").await;
|
||||||
|
},
|
||||||
|
|
||||||
|
Err(_) => {
|
||||||
|
let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/invalid_time").await;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -65,7 +65,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
.add_command("todo", &todo_cmds::TODO_PARSE_COMMAND)
|
.add_command("todo", &todo_cmds::TODO_PARSE_COMMAND)
|
||||||
.add_command("blacklist", &moderation_cmds::BLACKLIST_COMMAND)
|
.add_command("blacklist", &moderation_cmds::BLACKLIST_COMMAND)
|
||||||
.add_command("timezone", &moderation_cmds::TIMEZONE_COMMAND)
|
.add_command("timezone", &moderation_cmds::TIMEZONE_COMMAND)
|
||||||
.add_command("language", &moderation_cmds::LANGUAGE_COMMAND)
|
.add_command("lang", &moderation_cmds::LANGUAGE_COMMAND)
|
||||||
|
.add_command("pause", &reminder_cmds::PAUSE_COMMAND)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment"))
|
let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment"))
|
||||||
|
@ -3,16 +3,38 @@ use std::time::{
|
|||||||
UNIX_EPOCH,
|
UNIX_EPOCH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::fmt::{
|
||||||
|
Formatter,
|
||||||
|
Display,
|
||||||
|
Result as FmtResult,
|
||||||
|
};
|
||||||
|
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use chrono::offset::Utc;
|
use chrono::offset::Utc;
|
||||||
use chrono::{Timelike, Datelike, TimeZone};
|
use chrono::{Timelike, Datelike, TimeZone};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InvalidTime {
|
||||||
|
ParseErrorDMY,
|
||||||
|
ParseErrorHMS,
|
||||||
|
ParseErrorDisplacement,
|
||||||
|
ParseErrorChrono,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for InvalidTime {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
write!(f, "InvalidTime: {:?}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for InvalidTime {}
|
||||||
|
|
||||||
enum ParseType {
|
enum ParseType {
|
||||||
Explicit,
|
Explicit,
|
||||||
Displacement,
|
Displacement,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TimeParser {
|
pub struct TimeParser {
|
||||||
timezone: Tz,
|
timezone: Tz,
|
||||||
inverted: bool,
|
inverted: bool,
|
||||||
time_string: String,
|
time_string: String,
|
||||||
@ -43,19 +65,10 @@ impl TimeParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timestamp(&self) -> i32 {
|
pub fn timestamp(&self) -> Result<i64, InvalidTime> {
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn displacement(&self) -> i32 {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process(&self) -> i32 {
|
|
||||||
match self.parse_type {
|
match self.parse_type {
|
||||||
ParseType::Explicit => {
|
ParseType::Explicit => {
|
||||||
// TODO remove unwrap from here
|
Ok(self.process_explicit()?)
|
||||||
self.process_explicit().unwrap()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
ParseType::Displacement => {
|
ParseType::Displacement => {
|
||||||
@ -64,45 +77,88 @@ impl TimeParser {
|
|||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.expect("Time calculated as going backwards. Very bad");
|
.expect("Time calculated as going backwards. Very bad");
|
||||||
|
|
||||||
since_epoch.as_secs() as i32 + self.process_displacement()
|
Ok(since_epoch.as_secs() as i64 + self.process_displacement()?)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_explicit(&self) -> Result<i32, Box<dyn std::error::Error>> {
|
pub fn displacement(&self) -> Result<i64, InvalidTime> {
|
||||||
let dt = self.timezone.datetime_from_str(self.time_string.as_str(), "%d/%m/%Y-%H:%M:%S")?;
|
match self.parse_type {
|
||||||
|
ParseType::Explicit => {
|
||||||
|
let now = SystemTime::now();
|
||||||
|
let since_epoch = now
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.expect("Time calculated as going backwards. Very bad");
|
||||||
|
|
||||||
Ok(dt.timestamp() as i32)
|
Ok(self.process_explicit()? - since_epoch.as_secs() as i64)
|
||||||
|
},
|
||||||
|
|
||||||
|
ParseType::Displacement => {
|
||||||
|
Ok(self.process_displacement()?)
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_displacement(&self) -> i32 {
|
|
||||||
|
fn process_explicit(&self) -> Result<i64, InvalidTime> {
|
||||||
|
let segments = self.time_string.matches("-").count();
|
||||||
|
|
||||||
|
let parse_string = if segments == 1 {
|
||||||
|
let slashes = self.time_string.matches("/").count();
|
||||||
|
|
||||||
|
match slashes {
|
||||||
|
0 => Ok("%d-".to_string()),
|
||||||
|
1 => Ok("%d/%m-".to_string()),
|
||||||
|
2 => Ok("%d/%m/%Y-".to_string()),
|
||||||
|
_ => Err(InvalidTime::ParseErrorDMY)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok("".to_string())
|
||||||
|
}? + if segments == 1 {
|
||||||
|
let colons = self.time_string.matches(":").count();
|
||||||
|
|
||||||
|
match colons {
|
||||||
|
1 => Ok("%H:%M"),
|
||||||
|
2 => Ok("%H:%M:%S"),
|
||||||
|
_ => Err(InvalidTime::ParseErrorHMS)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok("")
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let dt = self.timezone.datetime_from_str(self.time_string.as_str(), &parse_string).map_err(|_| InvalidTime::ParseErrorChrono)?;
|
||||||
|
|
||||||
|
Ok(dt.timestamp() as i64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_displacement(&self) -> Result<i64, InvalidTime> {
|
||||||
let mut current_buffer = "0".to_string();
|
let mut current_buffer = "0".to_string();
|
||||||
|
|
||||||
let mut seconds = 0 as i32;
|
let mut seconds = 0 as i64;
|
||||||
let mut minutes = 0 as i32;
|
let mut minutes = 0 as i64;
|
||||||
let mut hours = 0 as i32;
|
let mut hours = 0 as i64;
|
||||||
let mut days = 0 as i32;
|
let mut days = 0 as i64;
|
||||||
|
|
||||||
for character in self.time_string.chars() {
|
for character in self.time_string.chars() {
|
||||||
match character {
|
match character {
|
||||||
|
|
||||||
's' => {
|
's' => {
|
||||||
seconds = current_buffer.parse::<i32>().unwrap();
|
seconds = current_buffer.parse::<i64>().unwrap();
|
||||||
current_buffer = String::from("0");
|
current_buffer = String::from("0");
|
||||||
},
|
},
|
||||||
|
|
||||||
'm' => {
|
'm' => {
|
||||||
minutes = current_buffer.parse::<i32>().unwrap();
|
minutes = current_buffer.parse::<i64>().unwrap();
|
||||||
current_buffer = String::from("0");
|
current_buffer = String::from("0");
|
||||||
},
|
},
|
||||||
|
|
||||||
'h' => {
|
'h' => {
|
||||||
hours = current_buffer.parse::<i32>().unwrap();
|
hours = current_buffer.parse::<i64>().unwrap();
|
||||||
current_buffer = String::from("0");
|
current_buffer = String::from("0");
|
||||||
},
|
},
|
||||||
|
|
||||||
'd' => {
|
'd' => {
|
||||||
days = current_buffer.parse::<i32>().unwrap();
|
days = current_buffer.parse::<i64>().unwrap();
|
||||||
current_buffer = String::from("0");
|
current_buffer = String::from("0");
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -111,15 +167,15 @@ impl TimeParser {
|
|||||||
current_buffer += &c.to_string();
|
current_buffer += &c.to_string();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// raise exception
|
return Err(InvalidTime::ParseErrorDisplacement)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let full = seconds + (minutes * 60) + (hours * 3600) + (days * 86400) + current_buffer.parse::<i32>().unwrap() *
|
let full = seconds + (minutes * 60) + (hours * 3600) + (days * 86400) + current_buffer.parse::<i64>().unwrap() *
|
||||||
if self.inverted { -1 } else { 1 };
|
if self.inverted { -1 } else { 1 };
|
||||||
|
|
||||||
full
|
Ok(full)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user