pass_manager/src/state/handler.rs

107 lines
2.9 KiB
Rust

use crate::prelude::*;
use futures::{future::BoxFuture, TryFutureExt};
use std::{mem, sync::Arc};
use teloxide::{
requests::HasPayload,
types::{InlineKeyboardMarkup, MessageId, ParseMode},
RequestError,
};
use tokio::{sync::Mutex, try_join};
#[derive(Clone, Copy)]
pub struct MessageIds(pub ChatId, pub MessageId);
impl MessageIds {
// Tries to delete the message while ignoring API errors
#[inline]
pub async fn delete(self, bot: &Throttle<Bot>) -> crate::Result<()> {
match bot.delete_message(self.0, self.1).await {
Ok(_) | Err(RequestError::Api(_)) => Ok(()),
Err(err) => Err(err.into()),
}
}
/// Tries to alter the message or sends a new one
#[inline]
pub async fn alter_message(
&mut self,
bot: &Throttle<Bot>,
text: impl Into<String> + Send,
markup: impl Into<Option<InlineKeyboardMarkup>> + Send,
parse_mode: impl Into<Option<ParseMode>> + Send,
) -> crate::Result<()> {
let mut edit = bot.edit_message_text(self.0, self.1, text);
edit.parse_mode = parse_mode.into();
edit.reply_markup = markup.into();
match edit.send_ref().await {
Ok(_) => return Ok(()),
Err(RequestError::Api(_)) => (),
Err(err) => return Err(err.into()),
};
let send = {
let mut send_request = bot.send_message(self.0, mem::take(&mut edit.text));
let payload = send_request.payload_mut();
payload.parse_mode = edit.parse_mode;
payload.reply_markup = edit.reply_markup.take().map(Into::into);
send_request.send().map_err(Into::into)
};
let msg = try_join!(self.delete(bot), send)?.1;
*self = Self::from(&msg);
Ok(())
}
}
impl From<&Message> for MessageIds {
#[inline]
fn from(value: &Message) -> Self {
Self(value.chat.id, value.id)
}
}
type DynHanlder<T> = Box<
dyn FnOnce(
Throttle<Bot>,
Message,
Pool,
MainDialogue,
MessageIds,
T,
) -> BoxFuture<'static, crate::Result<()>>
+ Send,
>;
pub struct Handler<T> {
pub func: Option<DynHanlder<T>>,
pub previous: MessageIds,
}
pub type Packaged<T> = Arc<Mutex<Handler<T>>>;
impl<T> Handler<T> {
/// Convinience method to convert a simple async function and a previous message into `PackagedHandler`
#[inline]
pub fn new<H>(f: H, previous: impl Into<MessageIds>) -> PackagedHandler<T>
where
H: FnOnce(
Throttle<Bot>,
Message,
Pool,
MainDialogue,
MessageIds,
T,
) -> BoxFuture<'static, crate::Result<()>>
+ Send
+ 'static,
{
let handler = Self {
func: Some(Box::new(f)),
previous: previous.into(),
};
Arc::new(Mutex::new(handler))
}
}