Global, group, and per-handler middleware with the MiddlewareFunc type, b.Use(), Group.Use(), and built-in middleware.
Middleware in Telebot wraps HandlerFunc values, letting you intercept every request before (and after) your handler runs. This is the standard place for cross-cutting concerns: logging, authentication, rate-limiting, panic recovery, and more.
// MiddlewareFunc represents a middleware processing function,// which get called before the endpoint group or specific handler.type MiddlewareFunc func(HandlerFunc) HandlerFunc
A middleware receives next HandlerFunc and returns a new HandlerFunc. Call next(c) to proceed to the next middleware or final handler, or return early to short-circuit.Minimal example:
// Group is a separated group of handlers, united by the general middleware.type Group struct { ... }// Use adds middleware to the chain.func (g *Group) Use(middleware ...MiddlewareFunc)// Handle adds endpoint handler to the bot, combining group's middleware// with the optional given middleware.func (g *Group) Handle(endpoint interface{}, h HandlerFunc, m ...MiddlewareFunc)
Group middleware only wraps the handlers registered through that specific *Group:
adminGroup := b.Group()adminGroup.Use(requireAdmin)adminGroup.Handle("/ban", onBan)adminGroup.Handle("/kick", onKick)adminGroup.Handle("/promote", onPromote)// /start is NOT affected by requireAdminb.Handle("/start", onStart)
// Logger returns a middleware that logs incoming updates.// If no custom logger provided, log.Default() will be used.func Logger(logger ...*log.Logger) tele.MiddlewareFunc
Logs the full JSON representation of each incoming Update.
// Whitelist returns a middleware that skips the update for users// NOT specified in the chats field.func Whitelist(chats ...int64) tele.MiddlewareFunc
Allows only the listed user/chat IDs through. All others are silently ignored.
A generalised version of Whitelist/Blacklist that lets you provide custom handlers for matched and unmatched chats:
// RestrictConfig defines config for Restrict middleware.type RestrictConfig struct { Chats []int64 In tele.HandlerFunc // called when chat is in Chats Out tele.HandlerFunc // called when chat is NOT in Chats}func Restrict(v RestrictConfig) tele.MiddlewareFunc
b.Use(middleware.Restrict(middleware.RestrictConfig{ Chats: allowedGroupIDs, In: tele.DefaultHandlerFunc, // proceed normally Out: func(c tele.Context) error { return c.Send("This bot is not available in this chat.") },}))
Middleware is applied in the order it was registered. The first middleware registered runs outermost (first before, last after). Each call to next(c) descends one level deeper.
b.Use(A, B)b.Handle("/cmd", handler, C)// Execution order:// A → B → C → handler → C (return) → B (return) → A (return)
This means errors propagate back up through the same chain, and deferred logic in outer middleware runs after inner middleware and the handler have completed.