1use std::{io::Error as IoError, net::SocketAddr, sync::Arc};
2
3use axum::Router;
4use tokio::net::TcpListener;
5
6use crate::{handler::UpdateHandler, types::Update};
7
8#[cfg_attr(nightly, doc(cfg(feature = "webhook")))]
10pub struct WebhookServer {
11 router: Router,
12}
13
14impl WebhookServer {
15 pub fn new<A, B>(path: A, handler: B) -> Self
22 where
23 A: AsRef<str>,
24 B: UpdateHandler + Send + Sync + 'static,
25 {
26 let router = Router::new()
27 .route(path.as_ref(), axum::routing::post(handle_update::<B>))
28 .layer(axum::Extension(Arc::new(handler)));
29 Self { router }
30 }
31
32 pub async fn run<T>(self, address: T) -> Result<SocketAddr, IoError>
40 where
41 T: Into<SocketAddr>,
42 {
43 let listener = TcpListener::bind(address.into()).await?;
44 let result = listener.local_addr();
45 axum::serve(listener, self.router).await?;
46 result
47 }
48}
49
50impl From<WebhookServer> for Router {
51 fn from(value: WebhookServer) -> Self {
52 value.router
53 }
54}
55
56async fn handle_update<H>(handler: axum::Extension<Arc<H>>, axum::extract::Json(update): axum::extract::Json<Update>)
57where
58 H: UpdateHandler,
59{
60 handler.handle(update).await
61}