1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use async_trait::async_trait;
6
7use crate::context::Context;
8use crate::error::BotResult;
9
10pub type HandlerFuture = Pin<Box<dyn Future<Output = BotResult<()>> + Send>>;
12
13#[async_trait]
23pub trait Handler: Send + Sync + 'static {
24 async fn handle(&self, ctx: Context) -> BotResult<()>;
26}
27
28pub type BoxHandler = Arc<dyn Handler>;
30
31pub struct HandlerFn<F> {
33 f: F,
34}
35
36impl<F, Fut> HandlerFn<F>
37where
38 F: Fn(Context) -> Fut + Send + Sync + 'static,
39 Fut: Future<Output = BotResult<()>> + Send + 'static,
40{
41 pub fn new(f: F) -> Self {
43 Self { f }
44 }
45}
46
47#[async_trait]
48impl<F, Fut> Handler for HandlerFn<F>
49where
50 F: Fn(Context) -> Fut + Send + Sync + 'static,
51 Fut: Future<Output = BotResult<()>> + Send + 'static,
52{
53 async fn handle(&self, ctx: Context) -> BotResult<()> {
54 (self.f)(ctx).await
55 }
56}
57
58pub fn handler_fn<F, Fut>(f: F) -> BoxHandler
71where
72 F: Fn(Context) -> Fut + Send + Sync + 'static,
73 Fut: Future<Output = BotResult<()>> + Send + 'static,
74{
75 Arc::new(HandlerFn::new(f))
76}
77
78pub struct LoggingHandler {
80 inner: BoxHandler,
81}
82
83impl LoggingHandler {
84 pub fn wrap(inner: BoxHandler) -> BoxHandler {
87 Arc::new(Self { inner })
88 }
89}
90
91#[async_trait]
92impl Handler for LoggingHandler {
93 async fn handle(&self, ctx: Context) -> BotResult<()> {
94 let update_id = ctx.update_id();
95 if let Err(e) = self.inner.handle(ctx).await {
96 tracing::error!("Handler error on update {}: {}", update_id, e);
97 }
98 Ok(())
99 }
100}
101
102#[async_trait]
105impl Handler for std::sync::Arc<dyn Handler> {
106 async fn handle(&self, ctx: Context) -> BotResult<()> {
107 (**self).handle(ctx).await
108 }
109}