Added Handler struct to hold the boxed next step handler and the previous message to be able to delete the previous message to allways delete it

This commit is contained in:
StNicolay 2023-05-07 13:20:11 +03:00
parent c264623510
commit ab6e4d9233
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
14 changed files with 87 additions and 103 deletions

View File

@ -11,8 +11,5 @@ pub async fn run(bot: Throttle<Bot>, q: CallbackQuery) -> crate::Result<()> {
} }
pub fn filter(q: CallbackQuery) -> bool { pub fn filter(q: CallbackQuery) -> bool {
match q.data.as_deref() { matches!(q.data.as_deref(), Some("delete_message"))
Some("delete_message") => true,
_ => false,
}
} }

View File

@ -1,7 +1,8 @@
use crate::{ use crate::{
entity::{account, prelude::Account}, entity::prelude::Account,
errors::NoUserInfo, errors::NoUserInfo,
handlers::{markups::deletion_markup, utils::package_handler, MainDialogue, State}, handlers::{markups::deletion_markup, utils::package_handler, MainDialogue, State},
models::DecryptedAccount,
}; };
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
@ -12,19 +13,12 @@ async fn get_master_pass(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message, account: DecryptedAccount,
name: String,
login: String,
password: String,
master_pass: String, master_pass: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
dialogue.exit().await?; dialogue.exit().await?;
let account = spawn_blocking(move || { let account = spawn_blocking(move || account.into_account(user_id, &master_pass)).await??;
account::ActiveModel::from_unencrypted(user_id, name, &login, &password, &master_pass)
})
.await??;
account.insert(&db).await?; account.insert(&db).await?;
bot.send_message(msg.chat.id, "Success") bot.send_message(msg.chat.id, "Success")
.reply_markup(deletion_markup()) .reply_markup(deletion_markup())
@ -37,30 +31,24 @@ async fn get_password(
msg: Message, msg: Message,
_: DatabaseConnection, _: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
login: String, login: String,
password: String, password: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let previous = bot let previous = bot
.send_message(msg.chat.id, "Send master password") .send_message(msg.chat.id, "Send master password")
.await?; .await?;
let account = DecryptedAccount {
name,
login,
password,
};
dialogue dialogue
.update(State::GetMasterPass(package_handler( .update(State::GetMasterPass(package_handler(
move |bot, msg, db, dialogue, master_pass| { move |bot, msg, db, dialogue, master_pass| {
get_master_pass( get_master_pass(bot, msg, db, dialogue, account, master_pass)
bot,
msg,
db,
dialogue,
previous,
name,
login,
password,
master_pass,
)
}, },
previous,
))) )))
.await?; .await?;
Ok(()) Ok(())
@ -71,17 +59,16 @@ async fn get_login(
msg: Message, msg: Message,
_: DatabaseConnection, _: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
login: String, login: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let previous = bot.send_message(msg.chat.id, "Send password").await?; let previous = bot.send_message(msg.chat.id, "Send password").await?;
dialogue dialogue
.update(State::GetPassword(package_handler( .update(State::GetPassword(package_handler(
move |bot, msg, db, dialogue, password| { move |bot, msg, db, dialogue, password| {
get_password(bot, msg, db, dialogue, previous, name, login, password) get_password(bot, msg, db, dialogue, name, login, password)
}, },
previous,
))) )))
.await?; .await?;
Ok(()) Ok(())
@ -92,10 +79,8 @@ async fn get_account_name(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
if Account::exists(user_id, &name, &db).await? { if Account::exists(user_id, &name, &db).await? {
bot.send_message(msg.chat.id, "Account alreay exists") bot.send_message(msg.chat.id, "Account alreay exists")
@ -106,9 +91,8 @@ async fn get_account_name(
let previous = bot.send_message(msg.chat.id, "Send login").await?; let previous = bot.send_message(msg.chat.id, "Send login").await?;
dialogue dialogue
.update(State::GetLogin(package_handler( .update(State::GetLogin(package_handler(
move |bot, msg, db, dialogue, login| { move |bot, msg, db, dialogue, login| get_login(bot, msg, db, dialogue, name, login),
get_login(bot, msg, db, dialogue, previous, name, login) previous,
},
))) )))
.await?; .await?;
Ok(()) Ok(())
@ -122,9 +106,8 @@ pub async fn add_account(
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(package_handler( .update(State::GetAccountName(package_handler(
move |bot, msg, db, dialogue, name| { get_account_name,
get_account_name(bot, msg, db, dialogue, previous, name) previous,
},
))) )))
.await?; .await?;
Ok(()) Ok(())

View File

@ -15,10 +15,8 @@ async fn get_master_pass(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
dialogue.exit().await?; dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
Account::delete_by_id((user_id, name)).exec(&db).await?; Account::delete_by_id((user_id, name)).exec(&db).await?;
@ -33,10 +31,8 @@ async fn get_account_name(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
if !Account::exists(user_id, &name, &db).await? { if !Account::exists(user_id, &name, &db).await? {
bot.send_message(msg.chat.id, "Account doesn't exists") bot.send_message(msg.chat.id, "Account doesn't exists")
@ -49,9 +45,8 @@ async fn get_account_name(
.await?; .await?;
dialogue dialogue
.update(State::GetMasterPass(package_handler( .update(State::GetMasterPass(package_handler(
move |bot, msg, db, dialogue, _| { move |bot, msg, db, dialogue, _| get_master_pass(bot, msg, db, dialogue, name),
get_master_pass(bot, msg, db, dialogue, previous, name) previous,
},
))) )))
.await?; .await?;
Ok(()) Ok(())
@ -71,9 +66,8 @@ pub async fn delete(
.await?; .await?;
dialogue dialogue
.update(State::GetAccountName(package_handler( .update(State::GetAccountName(package_handler(
move |bot, msg, db, dialogue, name| { get_account_name,
get_account_name(bot, msg, db, dialogue, previous, name) previous,
},
))) )))
.await?; .await?;
Ok(()) Ok(())

View File

@ -11,9 +11,8 @@ async fn get_master_pass(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message, _master_pass: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
dialogue.exit().await?; dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
Account::delete_many() Account::delete_many()
@ -40,7 +39,8 @@ pub async fn delete_all(
.await?; .await?;
dialogue dialogue
.update(State::GetMasterPass(package_handler( .update(State::GetMasterPass(package_handler(
move |bot, msg, db, dialogue, _| get_master_pass(bot, msg, db, dialogue, previous), get_master_pass,
previous,
))) )))
.await?; .await?;
Ok(()) Ok(())

View File

@ -16,10 +16,8 @@ async fn get_master_pass(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
master_pass: String, master_pass: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let master_pass: Arc<str> = master_pass.into(); let master_pass: Arc<str> = master_pass.into();
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let accounts = Arc::new(Mutex::new(Vec::new())); let accounts = Arc::new(Mutex::new(Vec::new()));
@ -59,8 +57,9 @@ pub async fn export(bot: Throttle<Bot>, msg: Message, dialogue: MainDialogue) ->
dialogue dialogue
.update(State::GetMasterPass(package_handler( .update(State::GetMasterPass(package_handler(
move |bot, msg, db, dialogue, master_pass| { move |bot, msg, db, dialogue, master_pass| {
get_master_pass(bot, msg, db, dialogue, previous, master_pass) get_master_pass(bot, msg, db, dialogue, master_pass)
}, },
previous,
))) )))
.await?; .await?;
Ok(()) Ok(())

View File

@ -16,11 +16,9 @@ async fn get_master_pass(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
master_pass: String, master_pass: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
dialogue.exit().await?; dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let account = match Account::get(user_id, &name, &db).await? { let account = match Account::get(user_id, &name, &db).await? {
@ -46,10 +44,8 @@ async fn get_account_name(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
name: String, name: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
if !Account::exists(user_id, &name, &db).await? { if !Account::exists(user_id, &name, &db).await? {
bot.send_message(msg.chat.id, "Account doesn't exists") bot.send_message(msg.chat.id, "Account doesn't exists")
@ -63,8 +59,9 @@ async fn get_account_name(
dialogue dialogue
.update(State::GetMasterPass(package_handler( .update(State::GetMasterPass(package_handler(
move |bot, msg, db, dialogue, master_pass| { move |bot, msg, db, dialogue, master_pass| {
get_master_pass(bot, msg, db, dialogue, previous, name, master_pass) get_master_pass(bot, msg, db, dialogue, name, master_pass)
}, },
previous,
))) )))
.await?; .await?;
Ok(()) Ok(())
@ -84,9 +81,8 @@ pub async fn get_account(
.await?; .await?;
dialogue dialogue
.update(State::GetAccountName(package_handler( .update(State::GetAccountName(package_handler(
move |bot, msg, db, dialogue, name| { get_account_name,
get_account_name(bot, msg, db, dialogue, previous, name) previous,
},
))) )))
.await?; .await?;
Ok(()) Ok(())

View File

@ -17,10 +17,8 @@ async fn get_master_pass(
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
master_pass: String, master_pass: String,
previous: Message,
accounts: Vec<DecryptedAccount>, accounts: Vec<DecryptedAccount>,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let master_pass: Arc<str> = master_pass.into(); let master_pass: Arc<str> = master_pass.into();
let failed = Arc::new(Mutex::new(Vec::new())); let failed = Arc::new(Mutex::new(Vec::new()));
@ -66,9 +64,8 @@ async fn get_document(
msg: Message, msg: Message,
_: DatabaseConnection, _: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message, (): (),
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
let document = match msg.document() { let document = match msg.document() {
Some(doc) => doc, Some(doc) => doc,
None => { None => {
@ -113,8 +110,9 @@ async fn get_document(
dialogue dialogue
.update(State::GetMasterPass(package_handler( .update(State::GetMasterPass(package_handler(
move |bot, msg, db, dialogue, master_pass| { move |bot, msg, db, dialogue, master_pass| {
get_master_pass(bot, msg, db, dialogue, master_pass, previous, accounts) get_master_pass(bot, msg, db, dialogue, master_pass, accounts)
}, },
previous,
))) )))
.await?; .await?;
Ok(()) Ok(())
@ -128,9 +126,7 @@ pub async fn import(bot: Throttle<Bot>, msg: Message, dialogue: MainDialogue) ->
) )
.await?; .await?;
dialogue dialogue
.update(State::GetDocument(package_handler( .update(State::GetDocument(package_handler(get_document, previous)))
move |bot, msg, db, dialogue, ()| get_document(bot, msg, db, dialogue, previous),
)))
.await?; .await?;
Ok(()) Ok(())
} }

View File

@ -12,10 +12,8 @@ async fn get_master_pass(
msg: Message, msg: Message,
db: DatabaseConnection, db: DatabaseConnection,
dialogue: MainDialogue, dialogue: MainDialogue,
previous: Message,
master_password: String, master_password: String,
) -> crate::Result<()> { ) -> crate::Result<()> {
let _ = bot.delete_message(previous.chat.id, previous.id).await;
dialogue.exit().await?; dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let model = task::spawn_blocking(move || { let model = task::spawn_blocking(move || {
@ -47,9 +45,8 @@ pub async fn set_master_pass(
.await?; .await?;
dialogue dialogue
.update(State::GetPassword(package_handler( .update(State::GetPassword(package_handler(
move |bot, msg, db, dialogue, master_pass| { get_master_pass,
get_master_pass(bot, msg, db, dialogue, previous, master_pass) previous,
},
))) )))
.await?; .await?;
Ok(()) Ok(())

View File

@ -10,7 +10,7 @@ pub async fn account_markup(
) -> crate::Result<KeyboardMarkup> { ) -> crate::Result<KeyboardMarkup> {
let account_names: Vec<Vec<KeyboardButton>> = Account::get_names(user_id, db, true) let account_names: Vec<Vec<KeyboardButton>> = Account::get_names(user_id, db, true)
.await? .await?
.map_ok(|account| KeyboardButton::new(account)) .map_ok(KeyboardButton::new)
.try_chunks(3) .try_chunks(3)
.try_collect() .try_collect()
.await?; .await?;

View File

@ -16,23 +16,25 @@ use teloxide::{
use tokio::sync::Mutex; use tokio::sync::Mutex;
type MainDialogue = Dialogue<State, InMemStorage<State>>; type MainDialogue = Dialogue<State, InMemStorage<State>>;
type PackagedHandler<T> = Arc<
Mutex< #[allow(clippy::type_complexity)]
Option< pub struct Handler<T> {
Box< pub handler: Box<
dyn FnOnce( dyn FnOnce(
Throttle<Bot>, Throttle<Bot>,
Message, Message,
DatabaseConnection, DatabaseConnection,
MainDialogue, MainDialogue,
T, T,
) -> crate::PinnedFuture<'static, crate::Result<()>> ) -> crate::PinnedFuture<'static, crate::Result<()>>
+ Send + Send
+ Sync, + Sync,
>,
>,
>, >,
>;
pub previous: Option<Message>,
}
type PackagedHandler<T> = Arc<Mutex<Option<Handler<T>>>>;
#[derive(BotCommands, Clone, Copy)] #[derive(BotCommands, Clone, Copy)]
#[command(rename_rule = "snake_case")] #[command(rename_rule = "snake_case")]

View File

@ -1,4 +1,8 @@
use crate::{errors::HandlerUsed, handlers::markups::deletion_markup, PinnedFuture}; use crate::{
errors::HandlerUsed,
handlers::{markups::deletion_markup, utils::delete_optional},
PinnedFuture,
};
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
@ -19,13 +23,17 @@ where
&'a str, &'a str,
) -> PinnedFuture<'a, crate::Result<bool>>, ) -> PinnedFuture<'a, crate::Result<bool>>,
{ {
let handler = next.lock().await.take();
if text == "/cancel" { if text == "/cancel" {
dialogue.exit().await?; let previous = handler.and_then(|handler| handler.previous);
delete_optional(&bot, &previous).await;
bot.send_message(msg.chat.id, "Successfully cancelled") bot.send_message(msg.chat.id, "Successfully cancelled")
.reply_markup(deletion_markup()) .reply_markup(deletion_markup())
.await?; .await?;
return Ok(()); return Ok(());
} }
let handler = handler.ok_or(HandlerUsed)?;
delete_optional(&bot, &handler.previous).await;
match check(&bot, &msg, &db, &text).await { match check(&bot, &msg, &db, &text).await {
Ok(true) => (), Ok(true) => (),
Ok(false) => { Ok(false) => {
@ -37,5 +45,5 @@ where
return Err(err); return Err(err);
} }
}; };
next.lock().await.take().ok_or(HandlerUsed)?(bot, msg, db, dialogue, text).await (handler.handler)(bot, msg, db, dialogue, text).await
} }

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
errors::HandlerUsed, errors::HandlerUsed,
handlers::{MainDialogue, PackagedHandler}, handlers::{utils::delete_optional, MainDialogue, PackagedHandler},
}; };
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
@ -12,5 +12,7 @@ pub async fn get_document(
dialogue: MainDialogue, dialogue: MainDialogue,
next: PackagedHandler<()>, next: PackagedHandler<()>,
) -> crate::Result<()> { ) -> crate::Result<()> {
next.lock().await.take().ok_or(HandlerUsed)?(bot, msg, db, dialogue, ()).await let handler = next.lock().await.take().ok_or(HandlerUsed)?;
delete_optional(&bot, &handler.previous).await;
(handler.handler)(bot, msg, db, dialogue, ()).await
} }

View File

@ -29,7 +29,7 @@ pub async fn check_master_pass<'a>(
.await?; .await?;
Ok(false) Ok(false)
} }
Err(err) => Err(err.into()), Err(err) => Err(err),
} }
} }

View File

@ -1,11 +1,11 @@
use super::{MainDialogue, PackagedHandler}; use super::{Handler, MainDialogue, PackagedHandler};
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
use std::{future::Future, sync::Arc}; use std::{future::Future, sync::Arc};
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
use tokio::sync::Mutex; use tokio::sync::Mutex;
#[inline] #[inline]
pub fn package_handler<H, F, T>(f: H) -> PackagedHandler<T> pub fn package_handler<H, F, T>(f: H, previous: impl Into<Option<Message>>) -> PackagedHandler<T>
where where
H: FnOnce(Throttle<Bot>, Message, DatabaseConnection, MainDialogue, T) -> F H: FnOnce(Throttle<Bot>, Message, DatabaseConnection, MainDialogue, T) -> F
+ Send + Send
@ -13,11 +13,21 @@ where
+ 'static, + 'static,
F: Future<Output = crate::Result<()>> + Send + 'static, F: Future<Output = crate::Result<()>> + Send + 'static,
{ {
Arc::new(Mutex::new(Some(Box::new( Arc::new(Mutex::new(Some(Handler {
move |bot, msg, db, dialogue, val| Box::pin(f(bot, msg, db, dialogue, val)), handler: Box::new(move |bot, msg, db, dialogue, val| {
)))) Box::pin(f(bot, msg, db, dialogue, val))
}),
previous: previous.into(),
})))
} }
pub async fn delete_message(bot: Throttle<Bot>, msg: Message) { pub async fn delete_message(bot: Throttle<Bot>, msg: Message) {
let _ = bot.delete_message(msg.chat.id, msg.id).await; let _ = bot.delete_message(msg.chat.id, msg.id).await;
} }
#[inline]
pub async fn delete_optional(bot: &Throttle<Bot>, msg: &Option<Message>) {
if let Some(msg) = msg {
let _ = bot.delete_message(msg.chat.id, msg.id).await;
}
}