Split up get_account_name into 2 states: get_new_name and get_existing_name

This commit is contained in:
StNicolay 2023-06-04 18:46:59 +03:00
parent cc41fbbaa4
commit 3b2633c880
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
11 changed files with 161 additions and 138 deletions

12
Cargo.lock generated
View File

@ -42,9 +42,9 @@ dependencies = [
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.0.1" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -1093,9 +1093,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.144" version = "0.2.145"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" checksum = "fc86cde3ff845662b8f4ef6cb50ea0e20c524eb3d29ae048287e06a1b3fa6a81"
[[package]] [[package]]
name = "libm" name = "libm"
@ -1268,9 +1268,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.2" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
errors::NoUserInfo, markups::deletion_markup, models::DecryptedAccount, state::NameCheckKind, errors::NoUserInfo, markups::deletion_markup, models::DecryptedAccount, Handler, MainDialogue,
Handler, MainDialogue, State, State,
}; };
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
@ -101,10 +101,7 @@ pub async fn add_account(
) -> crate::Result<()> { ) -> crate::Result<()> {
let previous = bot.send_message(msg.chat.id, "Send account name").await?; let previous = bot.send_message(msg.chat.id, "Send account name").await?;
dialogue dialogue
.update(State::GetAccountName( .update(State::GetNewName(Handler::new(get_account_name, previous)))
Handler::new(get_account_name, previous),
NameCheckKind::NewAccountName,
))
.await?; .await?;
Ok(()) Ok(())
} }

View File

@ -1,7 +1,6 @@
use crate::{ use crate::{
errors::NoUserInfo, errors::NoUserInfo,
markups::{self, deletion_markup}, markups::{self, deletion_markup},
state::NameCheckKind,
Handler, MainDialogue, State, Handler, MainDialogue, State,
}; };
use entity::prelude::*; use entity::prelude::*;
@ -60,10 +59,10 @@ pub async fn delete(
.reply_markup(markup) .reply_markup(markup)
.await?; .await?;
dialogue dialogue
.update(State::GetAccountName( .update(State::GetExistingName(Handler::new(
Handler::new(get_account_name, previous), get_account_name,
NameCheckKind::MustExist, previous,
)) )))
.await?; .await?;
Ok(()) Ok(())
} }

View File

@ -1,7 +1,6 @@
use crate::{ use crate::{
errors::NoUserInfo, errors::NoUserInfo,
markups::{self, deletion_markup}, markups::{self, deletion_markup},
state::NameCheckKind,
Handler, MainDialogue, State, Handler, MainDialogue, State,
}; };
use cryptography::prelude::*; use cryptography::prelude::*;
@ -75,10 +74,10 @@ pub async fn get_account(
.reply_markup(markup) .reply_markup(markup)
.await?; .await?;
dialogue dialogue
.update(State::GetAccountName( .update(State::GetExistingName(Handler::new(
Handler::new(get_account_name, previous), get_account_name,
NameCheckKind::MustExist, previous,
)) )))
.await?; .await?;
Ok(()) Ok(())
} }

View File

@ -47,7 +47,8 @@ pub fn get_dispatcher(
let message_handler = Update::filter_message() let message_handler = Update::filter_message()
.map_async(utils::delete_message) .map_async(utils::delete_message)
.enter_dialogue::<Update, InMemStorage<State>, State>() .enter_dialogue::<Update, InMemStorage<State>, State>()
.branch(case![State::GetAccountName(next, check)].endpoint(state::get_account_name)) .branch(case![State::GetExistingName(next)].endpoint(state::get_existing_name))
.branch(case![State::GetNewName(next)].endpoint(state::get_new_name))
.branch(case![State::GetMasterPass(next)].endpoint(state::get_master_pass)) .branch(case![State::GetMasterPass(next)].endpoint(state::get_master_pass))
.branch(case![State::GetLogin(next)].endpoint(state::get_login)) .branch(case![State::GetLogin(next)].endpoint(state::get_login))
.branch(case![State::GetPassword(next)].endpoint(state::get_password)) .branch(case![State::GetPassword(next)].endpoint(state::get_password))

View File

@ -27,7 +27,8 @@ where
let text = match msg.text() { let text = match msg.text() {
Some(text) => text.trim_end(), Some(text) => text.trim_end(),
None => { None => {
bot.send_message(msg.chat.id, no_text_message).await?; let msg = bot.send_message(msg.chat.id, no_text_message).await?;
handler.previous = Some(msg);
return Ok(()); return Ok(());
} }
}; };

View File

@ -1,110 +0,0 @@
use crate::{
errors::{HandlerUsed, NoUserInfo},
markups::{account_markup, deletion_markup},
utils::{delete_optional, validate_field},
MainDialogue,
};
use entity::prelude::*;
use sea_orm::DatabaseConnection;
use teloxide::{adaptors::Throttle, prelude::*};
/// Specifies the kind of checks to be run during the account name validation
#[derive(Clone, Copy)]
pub enum NameCheckKind {
NewAccountName,
MustExist,
}
/// Validates the account name
#[inline]
async fn check_name(
bot: &Throttle<Bot>,
msg: &Message,
db: &DatabaseConnection,
name: &str,
check_kind: NameCheckKind,
user_id: u64,
) -> crate::Result<Option<Message>> {
match check_kind {
NameCheckKind::MustExist => {
if !Account::exists(user_id, name, db).await? {
let msg = bot
.send_message(msg.chat.id, "Account doesn't exists. Try again")
.reply_markup(account_markup(user_id, db).await?)
.await?;
return Ok(Some(msg));
}
}
NameCheckKind::NewAccountName => {
if Account::exists(user_id, name, db).await? {
let msg = bot
.send_message(msg.chat.id, "Account already exists")
.await?;
return Ok(Some(msg));
}
if !validate_field(name) {
let msg = bot
.send_message(msg.chat.id, "Invalid account name. Try again")
.await?;
return Ok(Some(msg));
}
}
}
Ok(None)
}
/// Function to handle GetAccountName state
pub async fn get_account_name(
bot: Throttle<Bot>,
msg: Message,
db: DatabaseConnection,
dialogue: MainDialogue,
(next, check_kind): (super::PackagedHandler<String>, NameCheckKind),
) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let mut handler = next.lock().await;
delete_optional(&bot, handler.previous.as_ref()).await;
let text = match msg.text() {
Some(text) => text.trim_end(),
None => {
let mut send = bot.send_message(
msg.chat.id,
"Couldn't get the text of the message. Send the name again",
);
if let NameCheckKind::MustExist = check_kind {
send = send.reply_markup(account_markup(user_id, &db).await?)
}
send.await?;
return Ok(());
}
};
if text == "/cancel" {
dialogue.exit().await?;
bot.send_message(msg.chat.id, "Successfully cancelled")
.reply_markup(deletion_markup())
.await?;
return Ok(());
}
if handler.func.is_none() {
let _ = dialogue.exit().await;
return Err(HandlerUsed.into());
}
if let Some(failure_message) = check_name(&bot, &msg, &db, text, check_kind, user_id).await? {
handler.previous = Some(failure_message);
return Ok(());
}
let func = handler.func.take().unwrap();
drop(handler);
let text = text.to_owned();
if let Err(err) = func(bot, msg, db, dialogue.clone(), text).await {
let _ = dialogue.exit().await;
return Err(err);
}
Ok(())
}

View File

@ -0,0 +1,84 @@
use crate::{
errors::{HandlerUsed, NoUserInfo},
markups::{account_markup, deletion_markup},
utils::delete_optional,
MainDialogue,
};
use entity::prelude::*;
use sea_orm::DatabaseConnection;
use teloxide::{adaptors::Throttle, prelude::*};
/// Checks that the account with that name exists
#[inline]
async fn check_name(
bot: &Throttle<Bot>,
msg: &Message,
db: &DatabaseConnection,
name: &str,
user_id: u64,
) -> crate::Result<Option<Message>> {
if !Account::exists(user_id, name, db).await? {
let msg = bot
.send_message(msg.chat.id, "Account doesn't exists. Try again")
.reply_markup(account_markup(user_id, db).await?)
.await?;
return Ok(Some(msg));
}
Ok(None)
}
/// Function to handle GetExistingName state
pub async fn get_existing_name(
bot: Throttle<Bot>,
msg: Message,
db: DatabaseConnection,
dialogue: MainDialogue,
next: super::PackagedHandler<String>,
) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let mut handler = next.lock().await;
delete_optional(&bot, handler.previous.as_ref()).await;
let text = match msg.text() {
Some(text) => text.trim_end(),
None => {
let msg = bot
.send_message(
msg.chat.id,
"Couldn't get the text of the message. Send the name again",
)
.reply_markup(account_markup(user_id, &db).await?)
.await?;
handler.previous = Some(msg);
return Ok(());
}
};
if text == "/cancel" {
dialogue.exit().await?;
bot.send_message(msg.chat.id, "Successfully cancelled")
.reply_markup(deletion_markup())
.await?;
return Ok(());
}
if handler.func.is_none() {
let _ = dialogue.exit().await;
return Err(HandlerUsed.into());
}
if let Some(failure_message) = check_name(&bot, &msg, &db, text, user_id).await? {
handler.previous = Some(failure_message);
return Ok(());
}
let func = handler.func.take().unwrap();
drop(handler);
let text = text.to_owned();
if let Err(err) = func(bot, msg, db, dialogue.clone(), text).await {
let _ = dialogue.exit().await;
return Err(err);
}
Ok(())
}

49
src/state/get_new_name.rs Normal file
View File

@ -0,0 +1,49 @@
use crate::{errors::NoUserInfo, utils::validate_field, MainDialogue};
use entity::prelude::*;
use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*};
/// Validates a new account
#[inline]
async fn check_new_account_name(
bot: &Throttle<Bot>,
msg: &Message,
db: &DatabaseConnection,
name: &str,
) -> crate::Result<Option<Message>> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
if Account::exists(user_id, name, db).await? {
let msg = bot
.send_message(msg.chat.id, "Account already exists")
.await?;
return Ok(Some(msg));
}
if !validate_field(name) {
let msg = bot
.send_message(msg.chat.id, "Invalid account name. Try again")
.await?;
return Ok(Some(msg));
}
Ok(None)
}
/// Handles GetNewName state
pub async fn get_new_name(
bot: Throttle<Bot>,
msg: Message,
db: DatabaseConnection,
dialogue: MainDialogue,
next: super::PackagedHandler<String>,
) -> crate::Result<()> {
super::generic::generic(
bot,
msg,
db,
dialogue,
|bot, msg, db, name| Box::pin(check_new_account_name(bot, msg, db, name)),
"Couldn't get the text of the message. Send the name of the new account again",
next,
)
.await
}

View File

@ -28,7 +28,7 @@ pub async fn get_password(
Ok(None) Ok(None)
}) })
}, },
"Couldn't get the text of the message. Send the master password again", "Couldn't get the text of the message. Send the password again",
next, next,
) )
.await .await

View File

@ -1,16 +1,18 @@
//! This module consists of endpoints to handle the state //! This module consists of endpoints to handle the state
mod generic; mod generic;
mod get_account_name; mod get_existing_name;
mod get_login; mod get_login;
mod get_master_pass; mod get_master_pass;
mod get_new_name;
mod get_password; mod get_password;
mod get_user; mod get_user;
mod handler; mod handler;
pub use get_account_name::{get_account_name, NameCheckKind}; pub use get_existing_name::get_existing_name;
pub use get_login::get_login; pub use get_login::get_login;
pub use get_master_pass::get_master_pass; pub use get_master_pass::get_master_pass;
pub use get_new_name::get_new_name;
pub use get_password::get_password; pub use get_password::get_password;
pub use get_user::get_user; pub use get_user::get_user;
pub use handler::{Handler, PackagedHandler}; pub use handler::{Handler, PackagedHandler};
@ -22,7 +24,8 @@ use teloxide::{dispatching::dialogue::InMemStorage, prelude::*};
pub enum State { pub enum State {
#[default] #[default]
Start, Start,
GetAccountName(PackagedHandler<String>, NameCheckKind), GetExistingName(PackagedHandler<String>),
GetNewName(PackagedHandler<String>),
GetMasterPass(PackagedHandler<String>), GetMasterPass(PackagedHandler<String>),
GetLogin(PackagedHandler<String>), GetLogin(PackagedHandler<String>),
GetPassword(PackagedHandler<String>), GetPassword(PackagedHandler<String>),