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