Wiki
猫Table of Contents
- Update Routing Model
- Top-level routing
- What prepareUpdateCtx(...) does
- Command flow contract
- Payload flow contract
- Generic update handler contract
- Normalized MessageContext fields by update kind
- Message-backed update kinds
- User-backed but not message-backed update kinds
- Callback-specific update kind
- Update kinds without normalized user/message guarantees
- What is already stable enough to rely on
- What is still intentionally open
- Related pages
Update Routing Model
Russian version: Update-Routing-Model-RU
This page defines the current update-routing contract in Laniakea: which Telegram update kinds go through command routing, which go through payload routing, which go through generic update handlers, and what MessageContext guarantees exist in each path.
This is a model of current framework behavior, not a second API surface. The goal is to make the existing routing and MessageContext normalization explicit and testable.
Top-level routing
Laniakea currently routes updates like this:
| Update type | Routing path |
|---|---|
message |
command flow |
channel_post |
command flow |
callback_query |
payload flow |
| everything else | AddUpdateHandler(...) |
Important:
message,channel_post, andcallback_queryare reserved fromAddUpdateHandler(...).- scenes are checked before normal routing, but the current scene model is still fundamentally message-driven.
What prepareUpdateCtx(...) does
Before handler routing, Laniakea normalizes a MessageContext from the incoming Telegram update.
That normalization is intentionally broader than command and payload routing:
- some update kinds populate
ctx.Msg - some populate
ctx.Fromandctx.FromID - callback queries may populate callback-target fields
ctx.Text,ctx.Args, andctx.Prefixare not populated by this stage
This is an important distinction:
prepareUpdateCtx(...)defines the raw normalized context shape- routing then decides which handler path receives that context
Command flow contract
Command flow applies only to:
messagechannel_post
When a command matches, these guarantees apply:
ctx.Updateis always presentctx.Msgis presentctx.Prefixcontains the matched command prefixctx.Textcontains the parsed tail after the command namectx.Argscontainsstrings.Fields(ctx.Text)ctx.Loggerswitches to the matched plugin logger when one exists
Not guaranteed:
ctx.Fromctx.FromID
Example edge case:
- a
channel_postsent viasender_chatstill hasctx.Msg - but
ctx.Frommay benil - and
ctx.FromIDmay stay0
Payload flow contract
Payload flow applies only to:
callback_query
Base guarantees:
ctx.Updateis always presentctx.CallbackQueryIDis populatedctx.Fromandctx.FromIDare populated when Telegram includes a userctx.Argsis populated from decoded payload argsctx.Loggerswitches to the matched plugin logger when one exists
Not guaranteed:
ctx.Textctx.Prefix
There are two payload target shapes.
Callback query targeting a chat message
Guarantees:
ctx.Msgis presentctx.CallbackMsgIDis populatedctx.InlineMsgID == ""
Callback query targeting an inline message
Guarantees:
ctx.Msg == nilctx.CallbackMsgID == 0ctx.InlineMsgIDis populated
Generic update handler contract
Generic update handlers are registered through Plugin.AddUpdateHandler(...).
They apply to all update kinds outside the reserved command/payload flow.
General guarantees:
ctx.Updateis always presentctx.Textis not normalizedctx.Argsis not normalizedctx.Prefixis not normalized- each plugin update handler receives its own copied
MessageContextstruct
Important limitation:
- the copied context is an isolated struct copy, not a deep copy of all nested Telegram payload objects
Normalized MessageContext fields by update kind
Message-backed update kinds
| Update type | ctx.Msg |
ctx.From / ctx.FromID |
|---|---|---|
message |
yes | yes, when Msg.From exists |
edited_message |
yes | yes, when Msg.From exists |
channel_post |
yes | only when Msg.From exists |
edited_channel_post |
yes | only when Msg.From exists |
business_message |
yes | yes, when Msg.From exists |
edited_business_message |
yes | yes, when Msg.From exists |
Important:
- message-backed does not mean command-routed
edited_message,edited_channel_post,business_message, andedited_business_messagecurrently do not enter command flow automatically
User-backed but not message-backed update kinds
| Update type | ctx.Msg |
ctx.From / ctx.FromID |
|---|---|---|
inline_query |
no | yes |
chosen_inline_result |
no | yes |
shipping_query |
no | yes |
pre_checkout_query |
no | yes |
purchased_paid_media |
no | yes |
my_chat_member |
no | yes |
chat_member |
no | yes |
chat_join_request |
no | yes |
business_connection |
no | yes |
poll_answer |
no | yes |
message_reaction |
no | yes, when Telegram includes User |
chat_boost |
no | yes |
removed_chat_boost |
no | yes |
Callback-specific update kind
| Update type | ctx.Msg |
ctx.From / ctx.FromID |
Special fields |
|---|---|---|---|
callback_query with Message |
yes | yes | CallbackQueryID, CallbackMsgID |
callback_query with InlineMessageID |
no | yes | CallbackQueryID, InlineMsgID |
Update kinds without normalized user/message guarantees
| Update type | ctx.Msg |
ctx.From / ctx.FromID |
|---|---|---|
poll |
no | no |
message_reaction_count |
no | no |
deleted_business_messages |
no | no |
unknown |
no | no |
What is already stable enough to rely on
messageandchannel_poststay on command flowcallback_querystays on payload flowprepareUpdateCtx(...)itself does not populateText,Args, orPrefix- command parsing populates
Text,Args, andPrefix - payload decoding populates
Args, notText - callback target shape is split between chat-message callbacks and inline-message callbacks
edited_messageandedited_channel_poststay out of command routing
What is still intentionally open
- whether scenes should remain message-driven only or grow a broader update model
- whether message-backed edited/business updates should ever gain command-style routing
- whether “message-backed update” should become an explicit documented framework concept
Related pages
Navigation
Start here
Runtime and Architecture
- Bot-Lifecycle
- Webhook-Runtime
- Middleware
- Runners
- Error-Handling
- Logging
- Update-Routing-Model
- Policies
- Scenes
Interaction and Telegram API
- Inline-Keyboards-and-Payloads
- Auto-Generated-Commands
- Drafts
- Rich-Messages
- Localization
- Rate-Limiting
- tgapi-Overview