fix(telegram): allow inline_query through the getUpdates filter

The alias module registers an inline-query handler, but pollingAllowedUpdates
listed only message and callback_query. Telegram filters getUpdates on its
side, so inline queries were dropped before reaching the bot — the handler
never ran, and the omission left no log line or error to debug from.

Adds a test tying the list to the kinds actually handled, since nothing else
would catch the next such gap.
This commit is contained in:
tiennm99 committed 2026-09-04 11:46:59 +07:00
1 parent b903d14fc2
commit eafeebb69c
3 files changed
+50 -7

No files matched your search

+9 -3
View File
@@ -68,9 +68,15 @@ is the payoff for storing a `file_id` rather than bytes.
`InlineQueryResultCachedVideoNote`, and substituting a plain video would change
what was saved. They stay reachable through `/insert` and `/<name>`.
**Inline mode must be enabled in BotFather** (`/setinline`) or Telegram never
delivers these updates and the handler is never called. This is a one-time
operational step that cannot be done from code.
**Two things gate inline mode, and both fail silently.**
1. `inline_query` must be in `pollingAllowedUpdates`
(`internal/telegram/client.go`). Telegram filters getUpdates server-side, so
a missing kind means the handler is never called — no log line, no error.
2. Inline mode must be enabled for the bot in BotFather (`/setinline`). Until
it is, Telegram does not offer the bot for inline use at all, so typing
`@botname` shows nothing. This is a one-time operational step that cannot be
done from code.
## Names
+9 -4
View File
@@ -5,10 +5,15 @@ import (
)
// pollingAllowedUpdates restricts getUpdates to the update kinds the modules
// actually handle (text commands + inline-keyboard callbacks), matching the
// allowed_updates the old webhook registration set. Anything else (channel
// posts, edited messages, etc.) is dropped server-side by Telegram.
var pollingAllowedUpdates = bot.AllowedUpdates{"message", "callback_query"}
// actually handle: text commands, inline-keyboard callbacks, and inline-mode
// queries. Anything else (channel posts, edited messages, etc.) is dropped
// server-side by Telegram.
//
// This list is a hard gate, not an optimisation. Telegram filters on its side,
// so a handler for a kind missing here is never called and leaves no trace —
// no log line, no error, nothing to debug from. Any module that starts handling
// a new update kind must add it here in the same change.
var pollingAllowedUpdates = bot.AllowedUpdates{"message", "callback_query", "inline_query"}
// NewBot constructs a Telegram bot for long-polling mode (the sole transport
// on self-host — b.Start runs the getUpdates loop in cmd/server):
+32
View File
@@ -0,0 +1,32 @@
package telegram
import (
"slices"
"testing"
)
// pollingAllowedUpdates is a silent gate: Telegram filters getUpdates on its
// side, so a handler for a kind missing from this list is never called and
// leaves no log line, no error, and nothing to debug from. Inline queries were
// dropped exactly this way once — the handler was registered and the list was
// not updated.
//
// This test is the tripwire. A module that starts handling a new update kind
// belongs in both places, and removing a kind here must be deliberate enough to
// require editing this list too.
func TestPollingAllowedUpdates_CoversEveryHandledKind(t *testing.T) {
// message — every /command, and the alias fallback
// callback_query — inline-keyboard buttons (stock dividends, loldle)
// inline_query — "@botname <prefix>" alias lookups
want := []string{"message", "callback_query", "inline_query"}
for _, kind := range want {
if !slices.Contains(pollingAllowedUpdates, kind) {
t.Errorf("%q missing from pollingAllowedUpdates; its handlers will never fire", kind)
}
}
if len(pollingAllowedUpdates) != len(want) {
t.Errorf("pollingAllowedUpdates = %v, want exactly %v — an unhandled kind costs bandwidth for nothing",
pollingAllowedUpdates, want)
}
}