middleware: basic implementation and groups

pull/341/head
Demian 4 years ago
parent a69dd5aa62
commit f1015d1754

@ -67,7 +67,9 @@ type Bot struct {
Poller Poller
OnError func(error)
handlers map[string]HandlerFunc
handlers map[string]HandlerFunc
middleware map[string][]MiddlewareFunc
synchronous bool
verbose bool
parseMode ParseMode
@ -139,24 +141,42 @@ type Command struct {
Description string `json:"description"`
}
// Group returns a new group.
func (b *Bot) Group() *Group {
return &Group{b: b}
}
// Handle lets you set the handler for some command name or
// one of the supported endpoints.
// one of the supported endpoints. It also applies middleware
// if such passed to the function.
//
// Example:
//
// b.Handle("/help", func (c tb.Context) {})
// b.Handle(tb.OnText, func (c tb.Context) {})
// b.Handle(tb.OnQuery, func (c tb.Context) {})
// b.Handle("/start", func (c tele.Context) error {
// return c.Reply("Hello!")
// })
//
// b.Handle(&inlineButton, func (c tele.Context) error {
// return c.Respond(&tb.CallbackResponse{Text: "Hello!"})
// })
//
// // make a hook for one of your preserved inline buttons.
// b.Handle(&inlineButton, func (c tb.Context) {})
// Middleware usage:
//
func (b *Bot) Handle(endpoint interface{}, handler HandlerFunc) {
// protected := telemw.Whitelist(ids...)
// b.Handle("/ban", onBan, protected)
//
func (b *Bot) Handle(endpoint interface{}, h HandlerFunc, m ...MiddlewareFunc) {
if m != nil {
h = func(c Context) error {
return applyMiddleware(h, m...)(c)
}
}
switch end := endpoint.(type) {
case string:
b.handlers[end] = handler
b.handlers[end] = h
case CallbackEndpoint:
b.handlers[end.CallbackUnique()] = handler
b.handlers[end.CallbackUnique()] = h
default:
panic("telebot: unsupported endpoint")
}

@ -6,8 +6,8 @@ import (
"github.com/pkg/errors"
)
// HandlerFunc represents a handler function type
// which is used to handle endpoints.
// HandlerFunc represents a handler function, which is
// used to handle actual endpoints.
type HandlerFunc func(Context) error
// Context represents a context of the current event. It stores data

@ -0,0 +1,22 @@
package telebot
// MiddlewareFunc represents a middleware processing function,
// which get called before the endpoint group or specific handler.
type MiddlewareFunc func(HandlerFunc) HandlerFunc
// Group is a separated group of handlers, united by the general middleware.
type Group struct {
b *Bot
middleware []MiddlewareFunc
}
// Use adds middleware to the chain.
func (g *Group) Use(middleware ...MiddlewareFunc) {
g.middleware = append(g.middleware, middleware...)
}
// 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) {
g.b.Handle(endpoint, h, append(g.middleware, m...)...)
}

@ -31,6 +31,7 @@ package telebot
import "github.com/pkg/errors"
var (
ErrSkip = errors.New("telebot: skip")
ErrBadRecipient = errors.New("telebot: recipient is nil")
ErrUnsupportedWhat = errors.New("telebot: unsupported what argument")
ErrCouldNotUpdate = errors.New("telebot: could not fetch new updates")

@ -27,10 +27,10 @@ func (b *Bot) deferDebug() {
}
}
func (b *Bot) runHandler(handler HandlerFunc, c Context) {
func (b *Bot) runHandler(h HandlerFunc, c Context) {
f := func() {
defer b.deferDebug()
if err := handler(c); err != nil {
if err := h(c); err != nil && err != ErrSkip {
b.OnError(err)
}
}
@ -41,6 +41,13 @@ func (b *Bot) runHandler(handler HandlerFunc, c Context) {
}
}
func applyMiddleware(h HandlerFunc, middleware ...MiddlewareFunc) HandlerFunc {
for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i](h)
}
return h
}
// wrapError returns new wrapped telebot-related error.
func wrapError(err error) error {
return errors.Wrap(err, "telebot")

Loading…
Cancel
Save