109 lines
3.1 KiB
Rust
109 lines
3.1 KiB
Rust
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<Bot>) -> 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<Bot>,
|
|
text: impl Into<String> + Send,
|
|
markup: impl Into<Option<InlineKeyboardMarkup>> + Send,
|
|
parse_mode: impl Into<Option<ParseMode>> + 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<T> = Box<
|
|
dyn FnOnce(
|
|
Throttle<Bot>,
|
|
Message,
|
|
Pool,
|
|
MainDialogue,
|
|
MessageIds,
|
|
LocaleRef,
|
|
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,
|
|
LocaleRef,
|
|
T,
|
|
) -> BoxFuture<'static, crate::Result<()>>
|
|
+ Send
|
|
+ 'static,
|
|
{
|
|
let handler = Self {
|
|
func: Some(Box::new(f)),
|
|
previous: previous.into(),
|
|
};
|
|
Arc::new(Mutex::new(handler))
|
|
}
|
|
}
|