pass_manager/src/state/generic.rs

64 lines
1.8 KiB
Rust

use crate::{errors::HandlerUsed, markups::deletion_markup, utils::delete_optional, PinnedFuture};
use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*};
/// A generic state handler. It checks for "/cancel" messages and runs the provided validation function
#[inline]
pub async fn generic<F>(
bot: Throttle<Bot>,
msg: Message,
db: DatabaseConnection,
dialogue: crate::MainDialogue,
check: F,
no_text_message: impl Into<String>,
next: super::PackagedHandler<String>,
) -> crate::Result<()>
where
for<'a> F: FnOnce(
&'a Throttle<Bot>,
&'a Message,
&'a DatabaseConnection,
&'a str,
) -> PinnedFuture<'a, crate::Result<Option<Message>>>,
{
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, no_text_message).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(&bot, &msg, &db, text).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(())
}