1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Webhook-бот на Actix-web.
//! Если указано, регистрирует подписку на обновления.
//!
//! Слушает входящие события, отвечает текстом из пришедших сообщений.
//!
//! # Запуск
//! ```bash
//! export MAXBOT_TOKEN="ваш_токен"
//! export WEBHOOK_URL="https://my-russian-company.ru/webhook"
//! cargo run --example webhook-bot --features webhook
//! ```
//!
//! Если не указан WEBHOOK_URL, после запуска необходимо зарегистрировать webhook в MAX (однократно):
//! ```rust,no_run
//! # use maxbot::MaxClient;
//! # async fn reg() {
//! let client = MaxClient::from_env().unwrap();
//! client.create_subscription("https://my-russian-company.ru/webhook", vec![], Some("my_secret_123")).await.unwrap();
//! # }
//! ```
//!
//! MAX будет присылать обновления на `POST /webhook`.
//! Убедитесь, что ваш сервер доступен по HTTPS (порт 443), например, через nginx.
use maxbot::{InlineKeyboardButton, InlineKeyboardBuilder};
use maxbot::webhook::WebhookServer;
use maxbot::{Dispatcher, MaxClient};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let bot = MaxClient::from_env().expect("MAXBOT_TOKEN not set");
let secret = std::env::var("WEBHOOK_SECRET").unwrap_or_else(|_| "my_secret_123".to_string());
if let Ok(webhook_url) = std::env::var("WEBHOOK_URL") {
// Регистрируем webhook в MAX
match bot.create_subscription(&webhook_url, vec![], Some(&secret)).await {
Ok(()) => println!("Webhook registered successfully"),
Err(e) => eprintln!("Failed to register webhook: {}", e),
}
}
let mut dp = Dispatcher::new(bot);
// Стартовый обработчик (выполнится один раз)
dp.on_start(|_ctx| async move {
println!("Webhook bot started");
Ok(())
});
// Обработчик всех текстовых сообщений
dp.on_message(|ctx| async move {
if let Some(text) = ctx.text() {
if text.trim().eq_ignore_ascii_case("ping") {
ctx.reply_text("pong").await?;
} else {
ctx.reply_text(&format!("echo: {}", text)).await?;
}
}
Ok(())
});
// Обработчик callback с заменой клавиатуры
dp.on_callback_payload("stand", |ctx| async move {
let new_keyboard = InlineKeyboardBuilder::new()
.button(InlineKeyboardButton::callback("Начать заново", "stand"))
.build()?;
ctx.answer_callback_edit_keyboard(new_keyboard).await?;
Ok(())
});
// Обработчик callback с заменой текста
dp.on_callback_payload("change_text", |ctx| async move {
ctx.answer_callback_edit_text("Новый текст").await?;
Ok(())
});
// Запускаем actix-web сервер
WebhookServer::new(dp)
.secret(secret) // должен совпадать с тем, что передан в create_subscription
.path("/webhook")
.serve("0.0.0.0:8443") // порт 8443 за прокси, который реализует HTTPS
.await
}