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 {
match q.data.as_deref() {
Some("delete_message") => true,
_ => false,
}
matches!(q.data.as_deref(), Some("delete_message"))
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,23 +16,25 @@ use teloxide::{
use tokio::sync::Mutex;
type MainDialogue = Dialogue<State, InMemStorage<State>>;
type PackagedHandler<T> = Arc<
Mutex<
Option<
Box<
dyn FnOnce(
Throttle<Bot>,
Message,
DatabaseConnection,
MainDialogue,
T,
) -> crate::PinnedFuture<'static, crate::Result<()>>
+ Send
+ Sync,
>,
>,
#[allow(clippy::type_complexity)]
pub struct Handler<T> {
pub handler: Box<
dyn FnOnce(
Throttle<Bot>,
Message,
DatabaseConnection,
MainDialogue,
T,
) -> crate::PinnedFuture<'static, crate::Result<()>>
+ Send
+ Sync,
>,
>;
pub previous: Option<Message>,
}
type PackagedHandler<T> = Arc<Mutex<Option<Handler<T>>>>;
#[derive(BotCommands, Clone, Copy)]
#[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 teloxide::{adaptors::Throttle, prelude::*};
@ -19,13 +23,17 @@ where
&'a str,
) -> PinnedFuture<'a, crate::Result<bool>>,
{
let handler = next.lock().await.take();
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")
.reply_markup(deletion_markup())
.await?;
return Ok(());
}
let handler = handler.ok_or(HandlerUsed)?;
delete_optional(&bot, &handler.previous).await;
match check(&bot, &msg, &db, &text).await {
Ok(true) => (),
Ok(false) => {
@ -37,5 +45,5 @@ where
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::{
errors::HandlerUsed,
handlers::{MainDialogue, PackagedHandler},
handlers::{utils::delete_optional, MainDialogue, PackagedHandler},
};
use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*};
@ -12,5 +12,7 @@ pub async fn get_document(
dialogue: MainDialogue,
next: PackagedHandler<()>,
) -> 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?;
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 std::{future::Future, sync::Arc};
use teloxide::{adaptors::Throttle, prelude::*};
use tokio::sync::Mutex;
#[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
H: FnOnce(Throttle<Bot>, Message, DatabaseConnection, MainDialogue, T) -> F
+ Send
@ -13,11 +13,21 @@ where
+ 'static,
F: Future<Output = crate::Result<()>> + Send + 'static,
{
Arc::new(Mutex::new(Some(Box::new(
move |bot, msg, db, dialogue, val| Box::pin(f(bot, msg, db, dialogue, val)),
))))
Arc::new(Mutex::new(Some(Handler {
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) {
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;
}
}