mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-31 16:40:37 +01:00
Provide a webhook example instead of a library function
This commit is contained in:
parent
8ea460e04f
commit
51129f5d0f
4 changed files with 103 additions and 49 deletions
|
@ -25,9 +25,6 @@ maintenance = { status = "actively-developed" }
|
|||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
webhooks = ["warp"]
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0.44"
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
|
@ -47,12 +44,9 @@ async-trait = "0.1.22"
|
|||
futures = "0.3.1"
|
||||
pin-project = "0.4.6"
|
||||
serde_with_macros = "1.0.1"
|
||||
either = "1.5.3"
|
||||
|
||||
teloxide-macros = "0.2.1"
|
||||
|
||||
warp = { version = "0.2.2", features = ["tls"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
smart-default = "0.6.0"
|
||||
rand = "0.7.3"
|
||||
|
|
18
examples/webhook_ping_pong_bot/Cargo.toml
Normal file
18
examples/webhook_ping_pong_bot/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "webhook_ping_pong_bot"
|
||||
version = "0.1.0"
|
||||
authors = ["Temirkhan Myrzamadi <hirrolot@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
futures = "0.3.4"
|
||||
tokio = "0.2.9"
|
||||
pretty_env_logger = "0.4.0"
|
||||
|
||||
teloxide = { path = "../../" }
|
||||
|
||||
# Used to setup a webhook
|
||||
warp = "0.2.2"
|
85
examples/webhook_ping_pong_bot/src/main.rs
Normal file
85
examples/webhook_ping_pong_bot/src/main.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
// The version of ping-pong-bot, which uses a webhook to receive updates from
|
||||
// Telegram, instead of long polling.
|
||||
|
||||
use teloxide::{dispatching::update_listeners, prelude::*};
|
||||
|
||||
use std::{convert::Infallible, net::SocketAddr, sync::Arc};
|
||||
use tokio::sync::mpsc;
|
||||
use warp::Filter;
|
||||
|
||||
use reqwest::StatusCode;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
run().await;
|
||||
}
|
||||
|
||||
async fn handle_rejection(
|
||||
error: warp::Rejection,
|
||||
) -> Result<impl warp::Reply, Infallible> {
|
||||
log::error!("Cannot process the request due to: {:?}", error);
|
||||
Ok(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
|
||||
pub async fn webhook<'a>(
|
||||
bot: Arc<Bot>,
|
||||
) -> impl update_listeners::UpdateListener<Infallible> {
|
||||
// You might want to specify a self-signed certificate via .certificate
|
||||
// method on SetWebhook.
|
||||
bot.set_webhook("Your HTTPS ngrok URL here. Get it by 'ngrok http 80'")
|
||||
.send()
|
||||
.await
|
||||
.expect("Cannot setup a webhook");
|
||||
|
||||
let (tx, rx) = mpsc::unbounded_channel();
|
||||
|
||||
let server = warp::post()
|
||||
.and(warp::body::json())
|
||||
.map(move |json: serde_json::Value| {
|
||||
match serde_json::from_str::<Update>(&json.to_string()) {
|
||||
Ok(update) => tx
|
||||
.send(Ok(update))
|
||||
.expect("Cannot send an incoming update from the webhook"),
|
||||
Err(error) => {
|
||||
// In this case, please report a bug at https://github.com/teloxide/teloxide/issues !!!
|
||||
log::error!(
|
||||
"Cannot parse Update: {}\nError: {}",
|
||||
json,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
StatusCode::OK
|
||||
})
|
||||
.recover(handle_rejection);
|
||||
|
||||
let serve = warp::serve(server);
|
||||
|
||||
// You might want to use serve.key_path/serve.cert_path methods here to
|
||||
// setup a self-signed TLS certificate.
|
||||
|
||||
tokio::spawn(serve.run("127.0.0.1:80".parse::<SocketAddr>().unwrap()));
|
||||
rx
|
||||
}
|
||||
|
||||
async fn run() {
|
||||
teloxide::enable_logging!();
|
||||
log::info!("Starting ping_pong_bot!");
|
||||
|
||||
let bot = Bot::from_env();
|
||||
|
||||
Dispatcher::new(Arc::clone(&bot))
|
||||
.messages_handler(|rx: DispatcherHandlerRx<Message>| {
|
||||
rx.for_each(|message| async move {
|
||||
message.answer("pong").send().await.log_on_error().await;
|
||||
})
|
||||
})
|
||||
.dispatch_with_listener(
|
||||
webhook(bot).await,
|
||||
LoggingErrorHandler::with_custom_text(
|
||||
"An error from the update listener",
|
||||
),
|
||||
)
|
||||
.await;
|
||||
}
|
|
@ -198,46 +198,3 @@ pub fn polling(
|
|||
)
|
||||
.flatten()
|
||||
}
|
||||
|
||||
#[cfg(feature = "webhooks")]
|
||||
pub async fn webhook<KP, KB, CP, CB>(
|
||||
url: reqwest::Url,
|
||||
addr: std::net::SocketAddr,
|
||||
key: either::Either<KP, KB>,
|
||||
cert: either::Either<CP, CB>,
|
||||
) -> crate::prelude::ResponseResult<impl UpdateListener<std::convert::Infallible>>
|
||||
where
|
||||
KP: AsRef<std::path::Path>,
|
||||
KB: AsRef<[u8]>,
|
||||
CP: AsRef<std::path::Path>,
|
||||
CB: AsRef<[u8]>,
|
||||
{
|
||||
use either::Either;
|
||||
use tokio::sync::mpsc;
|
||||
use warp::Filter;
|
||||
|
||||
let (tx, rx) = mpsc::unbounded_channel();
|
||||
|
||||
let server = warp::post().and(warp::path(url)).and(warp::body::json()).map(
|
||||
move |update: Update| {
|
||||
tx.send(Ok(update)).expect("Cannot send an update from webhook");
|
||||
""
|
||||
},
|
||||
);
|
||||
|
||||
let serve = warp::serve(server).tls();
|
||||
|
||||
let serve = match key {
|
||||
Either::Left(path) => serve.key_path(path),
|
||||
Either::Right(bytes) => serve.key(bytes),
|
||||
};
|
||||
|
||||
let serve = match cert {
|
||||
Either::Left(path) => serve.cert_path(path),
|
||||
Either::Right(bytes) => serve.cert(bytes),
|
||||
};
|
||||
|
||||
tokio::spawn(serve.run(addr));
|
||||
|
||||
Ok(rx)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue