1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-10-16 14:37:27 +00:00

Add /reminder command

This commit is contained in:
Steffo 2024-07-11 07:53:51 +02:00
parent 7a4be66a41
commit cd4214cb4b
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
7 changed files with 128 additions and 1 deletions

30
Cargo.lock generated
View file

@ -772,6 +772,12 @@ dependencies = [
"unicase",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.4"
@ -815,6 +821,16 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@ -893,6 +909,17 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "parse_datetime"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8720474e3dd4af20cea8716703498b9f3b690f318fa9d9d9e2e38eaf44b96d0"
dependencies = [
"chrono",
"nom",
"regex",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@ -1124,8 +1151,11 @@ dependencies = [
"diesel",
"log",
"micronfig",
"once_cell",
"parse_datetime",
"pretty_env_logger",
"rand",
"regex",
"teloxide",
"tokio",
]

View file

@ -12,4 +12,7 @@ micronfig = "0.3.0"
pretty_env_logger = "0.5.0"
rand = { version = "0.8.5", features = ["small_rng"] }
teloxide = { version = "0.12.2", features = ["ctrlc_handler", "native-tls", "macros"], default-features = false }
tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] }
tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread", "time"] }
parse_datetime = "0.6.0"
regex = "1.10.5"
once_cell = "1.19.0"

View file

@ -2,6 +2,7 @@ use anyhow::Result;
use crate::telegram::DispatchWithResult;
pub(crate) mod database;
pub(crate) mod utils;
mod telegram;
#[tokio::main]

View file

@ -16,6 +16,7 @@ mod echo;
mod help;
mod whoami;
mod answer;
mod reminder;
#[derive(Debug, Clone, PartialEq, Eq, BotCommands)]
#[command(rename_rule = "lowercase")]
@ -32,6 +33,8 @@ enum Command {
WhoAmI,
#[command(description = "Rispondi ad una domanda.")]
Answer(String),
#[command(description = "Ricorda la chat di qualcosa che avverrà in futuro.")]
Reminder(reminder::ReminderArgs),
}
async fn handle_command(bot: Bot, command: Command, message: Message) -> CommandResult {
@ -47,6 +50,7 @@ async fn handle_command(bot: Bot, command: Command, message: Message) -> Command
Command::Echo(text) => echo::handler(&bot, &message, &text).await,
Command::WhoAmI => whoami::handler(&bot, &message).await,
Command::Answer(_) => answer::handler(&bot, &message).await,
Command::Reminder(args) => reminder::handler(&bot, &message, args).await,
};
if result.is_ok() {

View file

@ -0,0 +1,88 @@
use std::str::FromStr;
use anyhow::Context;
use teloxide::Bot;
use teloxide::payloads::SendMessageSetters;
use teloxide::requests::Requester;
use teloxide::types::{Message};
use parse_datetime::parse_datetime_at_date;
use once_cell::sync::Lazy;
use regex::Regex;
use super::{CommandResult};
fn determine_wait(target_chrono: chrono::DateTime<chrono::Local>) -> tokio::time::Duration {
let now_chrono = chrono::Local::now();
let duration_chrono = target_chrono.signed_duration_since(now_chrono);
let seconds = duration_chrono.num_seconds();
tokio::time::Duration::from_secs(seconds as u64)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReminderArgs {
target: chrono::DateTime<chrono::Local>,
reminder: String,
}
impl FromStr for ReminderArgs {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
static REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\[(?<target>.*)]\s*(?<reminder>.+)$").unwrap());
let captures = REGEX.captures(s)
.context("Sintassi del comando incorretta.")?;
let target = captures.name("target")
.unwrap()
.as_str();
let reminder = captures.name("reminder")
.unwrap()
.as_str()
.to_string();
let target = parse_datetime_at_date(chrono::Local::now(), target)
.context("Impossibile determinare la data in cui l'attesa avrà termine.")?
.with_timezone(&chrono::Local);
Ok(
ReminderArgs { target, reminder }
)
}
}
pub async fn handler(bot: &Bot, message: &Message, ReminderArgs { target, reminder}: ReminderArgs) -> CommandResult {
let text = format!(
"🕒 Promemoria per {} impostato\n\
{}",
target.format("%c"),
reminder
);
let _reply = bot
.send_message(message.chat.id, text)
.reply_to_message_id(message.id)
.await
.context("Non è stato possibile inviare la conferma.")?;
let wait_duration = determine_wait(target);
tokio::time::sleep(wait_duration).await;
let text = format!(
"🕒 Promemoria per {} attivato\n\
{}",
target.format("%c"),
reminder
);
let _reply = bot
.send_message(message.chat.id, text)
.reply_to_message_id(message.id)
.await
.context("Non è stato possibile inviare il promemoria.")?;
Ok(())
}

1
src/utils/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod time;

0
src/utils/time.rs Normal file
View file