Merge pull request #2 from Posthuman-Community/bugfix
Fixed: handle invalid timezone input to prevent crash
This commit is contained in:
commit
0c357bcec0
7 changed files with 92 additions and 35 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -12,6 +12,7 @@ dependencies = [
|
|||
"log",
|
||||
"pretty_env_logger",
|
||||
"rand",
|
||||
"regex",
|
||||
"teloxide",
|
||||
"tokio",
|
||||
]
|
||||
|
|
|
@ -12,6 +12,7 @@ diesel = { version = "2.2.4", features = ["sqlite"] }
|
|||
chrono = "0.4.38"
|
||||
dotenvy = "0.15.7"
|
||||
rand = "0.8.5"
|
||||
regex = "1.11.1"
|
||||
|
||||
[profile.release]
|
||||
debug = false
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::{
|
|||
bot::commands::Command,
|
||||
db::action::{clear_reminder_time, set_reminder_time, set_user_timezone},
|
||||
};
|
||||
use regex::Regex;
|
||||
use teloxide::{adaptors::DefaultParseMode, prelude::*, utils::html};
|
||||
|
||||
use chrono::naive::NaiveTime;
|
||||
|
@ -54,14 +55,28 @@ pub async fn reply(bot: Bot, msg: Message, command: Command) -> ResponseResult<(
|
|||
}
|
||||
}
|
||||
Command::SetTimezone(timezone) => {
|
||||
set_user_timezone(conn, user_id, msg.chat.id, timezone.as_str());
|
||||
bot.send_message(
|
||||
msg.chat.id,
|
||||
format!(
|
||||
"Hi, {mentioned_user}, your timezone is set to <code>UTC{timezone}</code>."
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
let tz_pattern =
|
||||
Regex::new(r"^(\+|-)\d{2}:\d{2}$").expect("Failed to initialize regex pattern");
|
||||
|
||||
match tz_pattern.is_match(&timezone) {
|
||||
true => {
|
||||
set_user_timezone(conn, user_id, msg.chat.id, &username, timezone.as_str());
|
||||
bot.send_message(
|
||||
msg.chat.id,
|
||||
format!(
|
||||
"Hi, {mentioned_user}, your timezone is set to <code>UTC{timezone}</code>."
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
false => {
|
||||
bot.send_message(
|
||||
msg.chat.id,
|
||||
"Invalid timezone format. Please use the format <code>±HH:MM</code>.",
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::Stop => {
|
||||
clear_reminder_time(conn, msg.chat.id, user_id);
|
||||
|
|
|
@ -12,6 +12,10 @@ pub fn set_reminder_time(
|
|||
_username: &str,
|
||||
time: &str,
|
||||
) {
|
||||
println!(
|
||||
"set_reminder_time -> UserId: {}, ChatId: {}, Username: {} , time: {}",
|
||||
_user_id.0, _chat_id.0, _username, time
|
||||
);
|
||||
diesel::insert_into(users)
|
||||
.values((
|
||||
chat_id.eq(_chat_id.0),
|
||||
|
@ -30,22 +34,46 @@ pub fn set_user_timezone(
|
|||
conn: &mut SqliteConnection,
|
||||
_user_id: UserId,
|
||||
_chat_id: ChatId,
|
||||
_username: &str,
|
||||
_user_timezone: &str,
|
||||
) {
|
||||
println!(
|
||||
"UserId: {}, ChatId: {}, UserTimezone: {}",
|
||||
_user_id.0, _chat_id.0, _user_timezone
|
||||
"set_user_timezone -> UserId: {}, ChatId: {}, Username: {} ,UserTimezone: {}",
|
||||
_user_id.0, _chat_id.0, _username, _user_timezone
|
||||
);
|
||||
diesel::update(
|
||||
users.filter(
|
||||
let user_exists = users
|
||||
.filter(
|
||||
chat_id
|
||||
.eq(_chat_id.0)
|
||||
.and(user_id.eq(i64::try_from(_user_id.0).unwrap())),
|
||||
),
|
||||
)
|
||||
.set(tz_offset.eq(_user_timezone))
|
||||
.execute(conn)
|
||||
.expect("Error update user timezone");
|
||||
)
|
||||
.select((chat_id, user_id))
|
||||
.first::<(i64, i64)>(conn)
|
||||
.optional()
|
||||
.expect("Error checking if user exists");
|
||||
|
||||
if user_exists.is_some() {
|
||||
diesel::update(
|
||||
users.filter(
|
||||
chat_id
|
||||
.eq(_chat_id.0)
|
||||
.and(user_id.eq(i64::try_from(_user_id.0).unwrap())),
|
||||
),
|
||||
)
|
||||
.set(tz_offset.eq(_user_timezone))
|
||||
.execute(conn)
|
||||
.expect("Error updating user timezone");
|
||||
} else {
|
||||
diesel::insert_into(users)
|
||||
.values((
|
||||
chat_id.eq(_chat_id.0),
|
||||
user_id.eq(i64::try_from(_user_id.0).unwrap()),
|
||||
username.eq(_username),
|
||||
tz_offset.eq(_user_timezone),
|
||||
))
|
||||
.execute(conn)
|
||||
.expect("Error inserting new user with timezone");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_reminder_time(conn: &mut SqliteConnection, _chat_id: ChatId, _user_id: UserId) {
|
||||
|
@ -63,6 +91,7 @@ pub fn clear_reminder_time(conn: &mut SqliteConnection, _chat_id: ChatId, _user_
|
|||
pub fn get_user_reminders(conn: &mut SqliteConnection) -> Vec<Users> {
|
||||
// Only work for group members
|
||||
users
|
||||
.select((chat_id, user_id, username, reminder_time, tz_offset))
|
||||
.filter(chat_id.ne(user_id))
|
||||
.load::<Users>(conn)
|
||||
.expect("Error loading user")
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::db::schema::{quotes, users};
|
||||
use diesel::prelude::*;
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[derive(Debug, Queryable, Selectable)]
|
||||
#[diesel(table_name = users)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct Users {
|
||||
pub chat_id: i64,
|
||||
pub user_id: i64,
|
||||
pub username: String,
|
||||
pub reminder_time: String,
|
||||
pub reminder_time: Option<String>,
|
||||
pub tz_offset: Option<String>,
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ diesel::table! {
|
|||
chat_id -> BigInt,
|
||||
user_id -> BigInt,
|
||||
username -> Text,
|
||||
reminder_time -> Text,
|
||||
tz_offset -> Nullable<Text>,
|
||||
reminder_time -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,23 +22,34 @@ pub async fn schedule_reminders(bot: &Arc<Bot>) {
|
|||
|
||||
for user in users_to_remind {
|
||||
if let Some(tzoffset) = user.tz_offset.as_ref() {
|
||||
let user_timezone: TimezoneOffest = tzoffset.parse().unwrap();
|
||||
if let Ok(user_timezone) = tzoffset.parse::<TimezoneOffest>() {
|
||||
let duration_secs = user_timezone.to_duration();
|
||||
let user_utc_time = Utc::now()
|
||||
.with_timezone(&FixedOffset::east_opt(duration_secs).unwrap())
|
||||
.format("%H:%M")
|
||||
.to_string();
|
||||
|
||||
let duration_secs = user_timezone.to_duration();
|
||||
let user_utc_time = Utc::now()
|
||||
.with_timezone(&FixedOffset::east_opt(duration_secs).unwrap())
|
||||
.format("%H:%M")
|
||||
.to_string();
|
||||
|
||||
if user_utc_time == user.reminder_time {
|
||||
let _user_id = UserId(u64::try_from(user.user_id).unwrap());
|
||||
let _username = user.username;
|
||||
let mentioned_user = html::user_mention(_user_id, &_username);
|
||||
let notification = format!("{mentioned_user} {selected_quote}");
|
||||
bot.send_message(ChatId(user.chat_id), notification)
|
||||
.await
|
||||
.unwrap();
|
||||
if let Some(reminder) = &user.reminder_time {
|
||||
if user_utc_time == *reminder {
|
||||
let _user_id = UserId(u64::try_from(user.user_id).unwrap());
|
||||
let _username = user.username;
|
||||
let mentioned_user = html::user_mention(_user_id, &_username);
|
||||
let notification = format!("{mentioned_user} {selected_quote}");
|
||||
bot.send_message(ChatId(user.chat_id), notification)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
} else {
|
||||
eprintln!("Invalid reminder: {:?}", &user.reminder_time)
|
||||
}
|
||||
} else {
|
||||
eprintln!("Failed to parse timezone offset: {}", tzoffset)
|
||||
}
|
||||
} else {
|
||||
eprintln!(
|
||||
"User {} does not have a timezone offset set.",
|
||||
user.username
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue