Sibling to kei-notify-telegram (outbound only). This crate is the inbound
half of the Telegram Bot API integration — receives POST /webhook from
Telegram, verifies secret token, parses Update, emits typed WebhookEvent.
Architecture: handler-only. The crate exposes `handle_webhook` and the
parsed types; the consumer owns the axum::Router and the HTTP server.
This keeps kei-telegram-webhook composable into kei-buddy, kei-gateway,
or any other consumer without forcing a server topology.
Files (9 new, 484 LOC total, all under 200/file):
* src/update.rs — lean Telegram Update / Message / User / Chat /
CallbackQuery structs (only fields KeiBuddy needs: chat_id, from,
text, message_id, date, callback_data; #[serde(default)] on optionals)
* src/event.rs — WebhookEvent enum (Text / Callback / Other) +
classify(update) -> WebhookEvent
* src/handler.rs — axum handler with X-Telegram-Bot-Api-Secret-Token
header verification (mismatch → 401)
* src/context.rs — WebhookContext trait (consumer provides
secret_token() + on_event())
* src/error.rs — WebhookError via thiserror
* src/lib.rs — module declarations + re-exports
* Cargo.toml — workspace member, maturity = "alpha"
* README.md — usage example (axum Router mount, 10-line snippet)
Tests (5 in src/event.rs + src/handler.rs, all pass):
* classify_text_message — text Update → WebhookEvent::Text
* classify_callback_query — callback Update → WebhookEvent::Callback
* classify_other_returns_other — edited_message-only Update → Other
* bad_secret_token_returns_401 — wrong header → 401 UNAUTHORIZED
* good_secret_token_returns_200 — matching header → 200 OK
Verify-before-commit (RULE 0.13 §):
* cargo check --offline -p kei-telegram-webhook: PASS
* cargo test --offline -p kei-telegram-webhook --lib: 5 passed / 0 failed
* cargo check --workspace --offline: PASS (no new warnings)
STATUS-TRUTH from agent: shipped=functional, stubs=0, behaviour-verified=yes.
Follow-up (deferred, not blocking):
* axum is direct dep "0.7" in this crate + kei-cortex + kei-forge —
workspace should adopt axum in [workspace.dependencies] for version
unification (separate consolidation wave)
* Unmodelled Telegram fields (edited_message, inline_query, photo,
document, reply_markup) — extend when KeiBuddy needs them
24 lines
935 B
Rust
24 lines
935 B
Rust
// SPDX-License-Identifier: Apache-2.0
|
|
//! kei-telegram-webhook — inbound Telegram Bot API webhook handler.
|
|
//!
|
|
//! Consumers mount [`handler::handle_webhook`] inside their own [`axum::Router`].
|
|
//! This crate does NOT own an `axum::Server`.
|
|
//!
|
|
//! Module layout (Constructor Pattern — one file, one responsibility):
|
|
//! * `update` — lean `Update` / `Message` / `User` / `Chat` / `CallbackQuery` structs
|
|
//! * `event` — `WebhookEvent` enum + `classify` function
|
|
//! * `context` — `WebhookContext` trait (secret_token + on_event)
|
|
//! * `handler` — axum handler `handle_webhook<S>`
|
|
//! * `error` — `WebhookError` via thiserror
|
|
|
|
pub mod context;
|
|
pub mod error;
|
|
pub mod event;
|
|
pub mod handler;
|
|
pub mod update;
|
|
|
|
pub use context::WebhookContext;
|
|
pub use error::WebhookError;
|
|
pub use event::{classify, WebhookEvent};
|
|
pub use handler::handle_webhook;
|
|
pub use update::{CallbackQuery, Chat, Message, Update, User};
|