use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use async_trait::async_trait;
use crate::context::Context;
use crate::error::BotResult;
pub type HandlerFuture = Pin<Box<dyn Future<Output = BotResult<()>> + Send>>;
#[async_trait]
pub trait Handler: Send + Sync + 'static {
async fn handle(&self, ctx: Context) -> BotResult<()>;
}
pub type BoxHandler = Arc<dyn Handler>;
pub struct HandlerFn<F> {
f: F,
}
impl<F, Fut> HandlerFn<F>
where
F: Fn(Context) -> Fut + Send + Sync + 'static,
Fut: Future<Output = BotResult<()>> + Send + 'static,
{
pub fn new(f: F) -> Self {
Self { f }
}
}
#[async_trait]
impl<F, Fut> Handler for HandlerFn<F>
where
F: Fn(Context) -> Fut + Send + Sync + 'static,
Fut: Future<Output = BotResult<()>> + Send + 'static,
{
async fn handle(&self, ctx: Context) -> BotResult<()> {
(self.f)(ctx).await
}
}
pub fn handler_fn<F, Fut>(f: F) -> BoxHandler
where
F: Fn(Context) -> Fut + Send + Sync + 'static,
Fut: Future<Output = BotResult<()>> + Send + 'static,
{
Arc::new(HandlerFn::new(f))
}
pub struct LoggingHandler {
inner: BoxHandler,
}
impl LoggingHandler {
pub fn wrap(inner: BoxHandler) -> BoxHandler {
Arc::new(Self { inner })
}
}
#[async_trait]
impl Handler for LoggingHandler {
async fn handle(&self, ctx: Context) -> BotResult<()> {
let update_id = ctx.update_id();
if let Err(e) = self.inner.handle(ctx).await {
tracing::error!("Handler error on update {}: {}", update_id, e);
}
Ok(())
}
}
#[async_trait]
impl Handler for std::sync::Arc<dyn Handler> {
async fn handle(&self, ctx: Context) -> BotResult<()> {
(**self).handle(ctx).await
}
}