context: adapt handlers

pull/341/head
Demian 4 years ago
parent 5a1a187e87
commit 5f6792d860

222
bot.go

@ -32,15 +32,16 @@ func NewBot(pref Settings) (*Bot, error) {
bot := &Bot{
Token: pref.Token,
URL: pref.URL,
Updates: make(chan Update, pref.Updates),
Poller: pref.Poller,
OnError: pref.OnError,
Updates: make(chan Update, pref.Updates),
handlers: make(map[string]HandlerFunc),
stop: make(chan struct{}),
handlers: make(map[string]interface{}),
synchronous: pref.Synchronous,
verbose: pref.Verbose,
parseMode: pref.ParseMode,
stop: make(chan struct{}),
reporter: pref.Reporter,
client: client,
}
@ -64,12 +65,12 @@ type Bot struct {
URL string
Updates chan Update
Poller Poller
OnError func(error)
handlers map[string]interface{}
handlers map[string]HandlerFunc
synchronous bool
verbose bool
parseMode ParseMode
reporter func(error)
stop chan struct{}
client *http.Client
}
@ -77,14 +78,11 @@ type Bot struct {
// Settings represents a utility struct for passing certain
// properties of a bot around and is required to make bots.
type Settings struct {
// Telegram API Url
URL string
// Telegram token
URL string
Token string
// Updates channel capacity
Updates int // Default: 100
// Updates channel capacity, defaulted to 100.
Updates int
// Poller is the provider of Updates.
Poller Poller
@ -102,9 +100,10 @@ type Settings struct {
// will be able to override the default mode by passing a new one.
ParseMode ParseMode
// Reporter is a callback function that will get called
// on any panics recovered from endpoint handlers.
Reporter func(error)
// OnError is a callback function that will get called
// on errors resulted from the handler. It is used as
// post-middleware function.
OnError func(error)
// HTTP Client used to make requests to telegram api
Client *http.Client
@ -145,14 +144,14 @@ type Command struct {
//
// Example:
//
// b.Handle("/help", func (m *tb.Message) {})
// b.Handle(tb.OnText, func (m *tb.Message) {})
// b.Handle(tb.OnQuery, func (q *tb.Query) {})
// b.Handle("/help", func (c tb.Context) {})
// b.Handle(tb.OnText, func (c tb.Context) {})
// b.Handle(tb.OnQuery, func (c tb.Context) {})
//
// // make a hook for one of your preserved inline buttons.
// b.Handle(&inlineButton, func (c *tb.Callback) {})
// b.Handle(&inlineButton, func (c tb.Context) {})
//
func (b *Bot) Handle(endpoint interface{}, handler interface{}) {
func (b *Bot) Handle(endpoint interface{}, handler HandlerFunc) {
switch end := endpoint.(type) {
case string:
b.handlers[end] = handler
@ -199,11 +198,23 @@ func (b *Bot) Stop() {
// ProcessUpdate processes a single incoming update.
// A started bot calls this function automatically.
func (b *Bot) ProcessUpdate(upd Update) {
c := &nativeContext{
b: b,
message: upd.Message,
callback: upd.Callback,
query: upd.Query,
chosenInlineResult: upd.ChosenInlineResult,
shippingQuery: upd.ShippingQuery,
preCheckoutQuery: upd.PreCheckoutQuery,
poll: upd.Poll,
pollAnswer: upd.PollAnswer,
}
if upd.Message != nil {
m := upd.Message
if m.PinnedMessage != nil {
b.handle(OnPinned, m)
b.handle(OnPinned, c)
return
}
@ -224,91 +235,84 @@ func (b *Bot) ProcessUpdate(upd Update) {
}
m.Payload = match[0][5]
if b.handle(command, m) {
if b.handle(command, c) {
return
}
}
// 1:1 satisfaction
if b.handle(m.Text, m) {
if b.handle(m.Text, c) {
return
}
b.handle(OnText, m)
b.handle(OnText, c)
return
}
if b.handleMedia(m) {
if b.handleMedia(c) {
return
}
if m.Invoice != nil {
b.handle(OnInvoice, m)
b.handle(OnInvoice, c)
return
}
if m.Payment != nil {
b.handle(OnPayment, m)
b.handle(OnPayment, c)
return
}
wasAdded := (m.UserJoined != nil && m.UserJoined.ID == b.Me.ID) ||
(m.UsersJoined != nil && isUserInList(b.Me, m.UsersJoined))
if m.GroupCreated || m.SuperGroupCreated || wasAdded {
b.handle(OnAddedToGroup, m)
b.handle(OnAddedToGroup, c)
return
}
if m.UserJoined != nil {
b.handle(OnUserJoined, m)
b.handle(OnUserJoined, c)
return
}
if m.UsersJoined != nil {
for _, user := range m.UsersJoined {
m.UserJoined = &user
b.handle(OnUserJoined, m)
b.handle(OnUserJoined, c)
}
return
}
if m.UserLeft != nil {
b.handle(OnUserLeft, m)
b.handle(OnUserLeft, c)
return
}
if m.NewGroupTitle != "" {
b.handle(OnNewGroupTitle, m)
b.handle(OnNewGroupTitle, c)
return
}
if m.NewGroupPhoto != nil {
b.handle(OnNewGroupPhoto, m)
b.handle(OnNewGroupPhoto, c)
return
}
if m.GroupPhotoDeleted {
b.handle(OnGroupPhotoDeleted, m)
b.handle(OnGroupPhotoDeleted, c)
return
}
if m.MigrateTo != 0 {
if handler, ok := b.handlers[OnMigration]; ok {
handler, ok := handler.(func(int64, int64))
if !ok {
panic("telebot: migration handler is bad")
}
b.runHandler(func() { handler(m.Chat.ID, m.MigrateTo) })
}
m.MigrateFrom = m.Chat.ID
b.handle(OnMigration, c)
return
}
}
if upd.EditedMessage != nil {
b.handle(OnEdited, upd.EditedMessage)
c.message = upd.EditedMessage
b.handle(OnEdited, c)
return
}
@ -316,16 +320,19 @@ func (b *Bot) ProcessUpdate(upd Update) {
m := upd.ChannelPost
if m.PinnedMessage != nil {
b.handle(OnPinned, m)
c.message = m.PinnedMessage
b.handle(OnPinned, c)
return
}
b.handle(OnChannelPost, upd.ChannelPost)
c.message = upd.ChannelPost
b.handle(OnChannelPost, c)
return
}
if upd.EditedChannelPost != nil {
b.handle(OnEditedChannelPost, upd.EditedChannelPost)
c.message = upd.EditedChannelPost
b.handle(OnEditedChannelPost, c)
return
}
@ -334,7 +341,7 @@ func (b *Bot) ProcessUpdate(upd Update) {
if upd.Callback.MessageID != "" {
upd.Callback.Message = &Message{
// InlineID indicates that message
// is inline so we have only its id
// is inline, so we have only its id
InlineID: upd.Callback.MessageID,
}
}
@ -346,152 +353,85 @@ func (b *Bot) ProcessUpdate(upd Update) {
unique, payload := match[0][1], match[0][3]
if handler, ok := b.handlers["\f"+unique]; ok {
handler, ok := handler.(func(*Callback))
if !ok {
panic(fmt.Errorf("telebot: %s callback handler is bad", unique))
}
upd.Callback.Data = payload
b.runHandler(func() { handler(upd.Callback) })
b.runHandler(handler, c)
return
}
}
}
}
if handler, ok := b.handlers[OnCallback]; ok {
handler, ok := handler.(func(*Callback))
if !ok {
panic("telebot: callback handler is bad")
}
b.runHandler(func() { handler(upd.Callback) })
}
b.handle(OnCallback, c)
return
}
if upd.Query != nil {
if handler, ok := b.handlers[OnQuery]; ok {
handler, ok := handler.(func(*Query))
if !ok {
panic("telebot: query handler is bad")
}
b.runHandler(func() { handler(upd.Query) })
}
b.handle(OnQuery, c)
return
}
if upd.ChosenInlineResult != nil {
if handler, ok := b.handlers[OnChosenInlineResult]; ok {
handler, ok := handler.(func(*ChosenInlineResult))
if !ok {
panic("telebot: chosen inline result handler is bad")
}
b.runHandler(func() { handler(upd.ChosenInlineResult) })
}
b.handle(OnChosenInlineResult, c)
return
}
if upd.ShippingQuery != nil {
if handler, ok := b.handlers[OnShipping]; ok {
handler, ok := handler.(func(*ShippingQuery))
if !ok {
panic("telebot: shipping query handler is bad")
}
b.runHandler(func() { handler(upd.ShippingQuery) })
}
b.handle(OnShipping, c)
return
}
if upd.PreCheckoutQuery != nil {
if handler, ok := b.handlers[OnCheckout]; ok {
handler, ok := handler.(func(*PreCheckoutQuery))
if !ok {
panic("telebot: pre checkout query handler is bad")
}
b.runHandler(func() { handler(upd.PreCheckoutQuery) })
}
b.handle(OnCheckout, c)
return
}
if upd.Poll != nil {
if handler, ok := b.handlers[OnPoll]; ok {
handler, ok := handler.(func(*Poll))
if !ok {
panic("telebot: poll handler is bad")
}
b.runHandler(func() { handler(upd.Poll) })
}
b.handle(OnPoll, c)
return
}
if upd.PollAnswer != nil {
if handler, ok := b.handlers[OnPollAnswer]; ok {
handler, ok := handler.(func(*PollAnswer))
if !ok {
panic("telebot: poll answer handler is bad")
}
b.runHandler(func() { handler(upd.PollAnswer) })
}
b.handle(OnPollAnswer, c)
return
}
}
func (b *Bot) handle(end string, m *Message) bool {
func (b *Bot) handle(end string, c Context) bool {
if handler, ok := b.handlers[end]; ok {
handler, ok := handler.(func(*Message))
if !ok {
panic(fmt.Errorf("telebot: %s handler is bad", end))
}
b.runHandler(func() { handler(m) })
b.runHandler(handler, c)
return true
}
return false
}
func (b *Bot) handleMedia(m *Message) bool {
func (b *Bot) handleMedia(c Context) bool {
m := c.Message()
switch {
case m.Photo != nil:
b.handle(OnPhoto, m)
b.handle(OnPhoto, c)
case m.Voice != nil:
b.handle(OnVoice, m)
b.handle(OnVoice, c)
case m.Audio != nil:
b.handle(OnAudio, m)
b.handle(OnAudio, c)
case m.Animation != nil:
b.handle(OnAnimation, m)
b.handle(OnAnimation, c)
case m.Document != nil:
b.handle(OnDocument, m)
b.handle(OnDocument, c)
case m.Sticker != nil:
b.handle(OnSticker, m)
b.handle(OnSticker, c)
case m.Video != nil:
b.handle(OnVideo, m)
b.handle(OnVideo, c)
case m.VideoNote != nil:
b.handle(OnVideoNote, m)
b.handle(OnVideoNote, c)
case m.Contact != nil:
b.handle(OnContact, m)
b.handle(OnContact, c)
case m.Location != nil:
b.handle(OnLocation, m)
b.handle(OnLocation, c)
case m.Venue != nil:
b.handle(OnVenue, m)
b.handle(OnVenue, c)
case m.Dice != nil:
b.handle(OnDice, m)
b.handle(OnDice, c)
default:
return false
}

@ -80,27 +80,25 @@ func TestBotHandle(t *testing.T) {
t.Skip("Cached bot instance is bad (probably wrong or empty TELEBOT_SECRET)")
}
b.Handle("/start", func(m *Message) {})
b.Handle("/start", func(c Context) error { return nil })
assert.Contains(t, b.handlers, "/start")
reply := ReplyButton{Text: "reply"}
b.Handle(&reply, func(m *Message) {})
b.Handle(&reply, func(c Context) error { return nil })
inline := InlineButton{Unique: "inline"}
b.Handle(&inline, func(c *Callback) {})
b.Handle(&inline, func(c Context) error { return nil })
btnReply := (&ReplyMarkup{}).Text("btnReply")
b.Handle(&btnReply, func(m *Message) {})
b.Handle(&btnReply, func(c Context) error { return nil })
btnInline := (&ReplyMarkup{}).Data("", "btnInline")
b.Handle(&btnInline, func(c *Callback) {})
b.Handle(&btnInline, func(c Context) error { return nil })
assert.Contains(t, b.handlers, btnReply.CallbackUnique())
assert.Contains(t, b.handlers, btnInline.CallbackUnique())
assert.Contains(t, b.handlers, reply.CallbackUnique())
assert.Contains(t, b.handlers, inline.CallbackUnique())
assert.Panics(t, func() { b.Handle(1, func() {}) })
}
func TestBotStart(t *testing.T) {
@ -135,10 +133,11 @@ func TestBotStart(t *testing.T) {
b.Poller = tp
var ok bool
b.Handle("/start", func(m *Message) {
assert.Equal(t, m.Text, "/start")
b.Handle("/start", func(c Context) error {
assert.Equal(t, c.Text(), "/start")
tp.done <- struct{}{}
ok = true
return nil
})
go b.Start()
@ -154,104 +153,137 @@ func TestBotProcessUpdate(t *testing.T) {
t.Fatal(err)
}
b.Handle("/start", func(m *Message) {
assert.Equal(t, "/start", m.Text)
b.Handle("/start", func(c Context) error {
assert.Equal(t, "/start", c.Text())
return nil
})
b.Handle("hello", func(m *Message) {
assert.Equal(t, "hello", m.Text)
b.Handle("hello", func(c Context) error {
assert.Equal(t, "hello", c.Text())
return nil
})
b.Handle(OnText, func(m *Message) {
assert.Equal(t, "text", m.Text)
b.Handle(OnText, func(c Context) error {
assert.Equal(t, "text", c.Text())
return nil
})
b.Handle(OnPinned, func(m *Message) {
assert.NotNil(t, m.PinnedMessage)
b.Handle(OnPinned, func(c Context) error {
assert.NotNil(t, c.Message())
return nil
})
b.Handle(OnPhoto, func(m *Message) {
assert.NotNil(t, m.Photo)
b.Handle(OnPhoto, func(c Context) error {
assert.NotNil(t, c.Message().Photo)
return nil
})
b.Handle(OnVoice, func(m *Message) {
assert.NotNil(t, m.Voice)
b.Handle(OnVoice, func(c Context) error {
assert.NotNil(t, c.Message().Voice)
return nil
})
b.Handle(OnAudio, func(m *Message) {
assert.NotNil(t, m.Audio)
b.Handle(OnAudio, func(c Context) error {
assert.NotNil(t, c.Message().Audio)
return nil
})
b.Handle(OnAnimation, func(m *Message) {
assert.NotNil(t, m.Animation)
b.Handle(OnAnimation, func(c Context) error {
assert.NotNil(t, c.Message().Animation)
return nil
})
b.Handle(OnDocument, func(m *Message) {
assert.NotNil(t, m.Document)
b.Handle(OnDocument, func(c Context) error {
assert.NotNil(t, c.Message().Document)
return nil
})
b.Handle(OnSticker, func(m *Message) {
assert.NotNil(t, m.Sticker)
b.Handle(OnSticker, func(c Context) error {
assert.NotNil(t, c.Message().Sticker)
return nil
})
b.Handle(OnVideo, func(m *Message) {
assert.NotNil(t, m.Video)
b.Handle(OnVideo, func(c Context) error {
assert.NotNil(t, c.Message().Video)
return nil
})
b.Handle(OnVideoNote, func(m *Message) {
assert.NotNil(t, m.VideoNote)
b.Handle(OnVideoNote, func(c Context) error {
assert.NotNil(t, c.Message().VideoNote)
return nil
})
b.Handle(OnContact, func(m *Message) {
assert.NotNil(t, m.Contact)
b.Handle(OnContact, func(c Context) error {
assert.NotNil(t, c.Message().Contact)
return nil
})
b.Handle(OnLocation, func(m *Message) {
assert.NotNil(t, m.Location)
b.Handle(OnLocation, func(c Context) error {
assert.NotNil(t, c.Message().Location)
return nil
})
b.Handle(OnVenue, func(m *Message) {
assert.NotNil(t, m.Venue)
b.Handle(OnVenue, func(c Context) error {
assert.NotNil(t, c.Message().Venue)
return nil
})
b.Handle(OnAddedToGroup, func(m *Message) {
assert.NotNil(t, m.GroupCreated)
b.Handle(OnAddedToGroup, func(c Context) error {
assert.NotNil(t, c.Message().GroupCreated)
return nil
})
b.Handle(OnUserJoined, func(m *Message) {
assert.NotNil(t, m.UserJoined)
b.Handle(OnUserJoined, func(c Context) error {
assert.NotNil(t, c.Message().UserJoined)
return nil
})
b.Handle(OnUserLeft, func(m *Message) {
assert.NotNil(t, m.UserLeft)
b.Handle(OnUserLeft, func(c Context) error {
assert.NotNil(t, c.Message().UserLeft)
return nil
})
b.Handle(OnNewGroupTitle, func(m *Message) {
assert.Equal(t, "title", m.NewGroupTitle)
b.Handle(OnNewGroupTitle, func(c Context) error {
assert.Equal(t, "title", c.Message().NewGroupTitle)
return nil
})
b.Handle(OnNewGroupPhoto, func(m *Message) {
assert.NotNil(t, m.NewGroupPhoto)
b.Handle(OnNewGroupPhoto, func(c Context) error {
assert.NotNil(t, c.Message().NewGroupPhoto)
return nil
})
b.Handle(OnGroupPhotoDeleted, func(m *Message) {
assert.True(t, m.GroupPhotoDeleted)
b.Handle(OnGroupPhotoDeleted, func(c Context) error {
assert.True(t, c.Message().GroupPhotoDeleted)
return nil
})
b.Handle(OnMigration, func(from, to int64) {
b.Handle(OnMigration, func(c Context) error {
from, to := c.Migration()
assert.Equal(t, int64(1), from)
assert.Equal(t, int64(2), to)
return nil
})
b.Handle(OnEdited, func(m *Message) {
assert.Equal(t, "edited", m.Text)
b.Handle(OnEdited, func(c Context) error {
assert.Equal(t, "edited", c.Message().Text)
return nil
})
b.Handle(OnChannelPost, func(m *Message) {
assert.Equal(t, "post", m.Text)
b.Handle(OnChannelPost, func(c Context) error {
assert.Equal(t, "post", c.Message().Text)
return nil
})
b.Handle(OnEditedChannelPost, func(m *Message) {
assert.Equal(t, "edited post", m.Text)
b.Handle(OnEditedChannelPost, func(c Context) error {
assert.Equal(t, "edited post", c.Message().Text)
return nil
})
b.Handle(OnCallback, func(c *Callback) {
if c.Data[0] != '\f' {
assert.Equal(t, "callback", c.Data)
b.Handle(OnCallback, func(c Context) error {
if data := c.Callback().Data; data[0] != '\f' {
assert.Equal(t, "callback", data)
}
return nil
})
b.Handle("\funique", func(c *Callback) {
assert.Equal(t, "callback", c.Data)
b.Handle("\funique", func(c Context) error {
assert.Equal(t, "callback", c.Callback().Data)
return nil
})
b.Handle(OnQuery, func(q *Query) {
assert.Equal(t, "query", q.Text)
b.Handle(OnQuery, func(c Context) error {
assert.Equal(t, "query", c.Text())
return nil
})
b.Handle(OnChosenInlineResult, func(r *ChosenInlineResult) {
assert.Equal(t, "result", r.ResultID)
b.Handle(OnChosenInlineResult, func(c Context) error {
assert.Equal(t, "result", c.ChosenInlineResult().ResultID)
return nil
})
b.Handle(OnCheckout, func(pre *PreCheckoutQuery) {
assert.Equal(t, "checkout", pre.ID)
b.Handle(OnCheckout, func(c Context) error {
assert.Equal(t, "checkout", c.PreCheckoutQuery().ID)
return nil
})
b.Handle(OnPoll, func(p *Poll) {
assert.Equal(t, "poll", p.ID)
b.Handle(OnPoll, func(c Context) error {
assert.Equal(t, "poll", c.Poll().ID)
return nil
})
b.Handle(OnPollAnswer, func(pa *PollAnswer) {
assert.Equal(t, "poll", pa.PollID)
b.Handle(OnPollAnswer, func(c Context) error {
assert.Equal(t, "poll", c.PollAnswer().PollID)
return nil
})
b.ProcessUpdate(Update{Message: &Message{Text: "/start"}})

@ -2,14 +2,45 @@ package telebot
import "github.com/pkg/errors"
// Сontext represents a context of the current event. It stores data
// depending on its type, whether it is a message, callback or whatever.
// HandlerFunc represents a handler function type
// which is used to handle endpoints.
type HandlerFunc func(Context) error
// Context represents a context of the current event. It stores data
// depending on its type, whether it's a message, callback or whatever.
type Context interface {
// Sender returns the current recipient, depending on the context type.
// Message returns stored message if such presented.
Message() *Message
// Callback returns stored callback if such presented.
Callback() *Callback
// Query returns stored query if such presented.
Query() *Query
// ChosenInlineResult returns stored inline result if such presented.
ChosenInlineResult() *ChosenInlineResult
// ShippingQuery returns stored shipping query if such presented.
ShippingQuery() *ShippingQuery
// PreCheckoutQuery returns stored pre checkout query if such presented.
PreCheckoutQuery() *PreCheckoutQuery
// Poll returns stored poll if such presented.
Poll() *Poll
// PollAnswer returns stored poll answer if such presented.
PollAnswer() *PollAnswer
// Migration returns both migration from and to chat IDs.
Migration() (int64, int64)
// Sender returns a current recipient, depending on the context type.
// Returns nil if user is not presented.
Sender() Recipient
// Text returns the current text, depending on the context type.
// Text returns a current text, depending on the context type.
// If the context contains payment, returns its payload.
// In the case when no related data presented, returns an empty string.
Text() string
@ -26,15 +57,15 @@ type Context interface {
// See Reply from bot.go.
Reply(what interface{}, opts ...interface{}) error
// Forward forwards given message to the current recipient.
// Forward forwards a given message to the current recipient.
// See Forward from bot.go.
Forward(msg Editable, opts ...interface{}) error
// Edit edits the current message.
// Edit edits a current message.
// See Edit from bot.go.
Edit(what interface{}, opts ...interface{}) error
// EditCaption edits the caption of the current message.
// EditCaption edits a caption of the current message.
// See EditCaption from bot.go.
EditCaption(caption string, opts ...interface{}) error
@ -68,32 +99,75 @@ type Context interface {
type nativeContext struct {
b *Bot
*Message
*Callback
*Query
*ChosenInlineResult
*ShippingQuery
*PreCheckoutQuery
*Poll
*PollAnswer
message *Message
callback *Callback
query *Query
chosenInlineResult *ChosenInlineResult
shippingQuery *ShippingQuery
preCheckoutQuery *PreCheckoutQuery
poll *Poll
pollAnswer *PollAnswer
}
func (c *nativeContext) Message() *Message {
switch {
case c.message != nil:
return c.message
case c.callback != nil:
return c.callback.Message
default:
return nil
}
}
func (c *nativeContext) Callback() *Callback {
return c.callback
}
func (c *nativeContext) Query() *Query {
return c.query
}
func (c *nativeContext) ChosenInlineResult() *ChosenInlineResult {
return c.chosenInlineResult
}
func (c *nativeContext) ShippingQuery() *ShippingQuery {
return c.shippingQuery
}
func (c *nativeContext) PreCheckoutQuery() *PreCheckoutQuery {
return c.preCheckoutQuery
}
func (c *nativeContext) Poll() *Poll {
return c.poll
}
func (c *nativeContext) PollAnswer() *PollAnswer {
return c.pollAnswer
}
func (c *nativeContext) Migration() (int64, int64) {
return c.message.MigrateFrom, c.message.MigrateTo
}
func (c *nativeContext) Sender() Recipient {
switch {
case c.Message != nil:
return c.Message.Sender
case c.Callback != nil:
return c.Callback.Sender
case c.Query != nil:
return c.Query.Sender
case c.ChosenInlineResult != nil:
return c.ChosenInlineResult.Sender
case c.ShippingQuery != nil:
return c.ShippingQuery.Sender
case c.PreCheckoutQuery != nil:
return c.PreCheckoutQuery.Sender
case c.PollAnswer != nil:
return c.PollAnswer.Sender
case c.message != nil:
return c.message.Sender
case c.callback != nil:
return c.callback.Sender
case c.query != nil:
return c.query.Sender
case c.chosenInlineResult != nil:
return c.chosenInlineResult.Sender
case c.shippingQuery != nil:
return c.shippingQuery.Sender
case c.preCheckoutQuery != nil:
return c.preCheckoutQuery.Sender
case c.pollAnswer != nil:
return c.pollAnswer.Sender
default:
return nil
}
@ -101,18 +175,18 @@ func (c *nativeContext) Sender() Recipient {
func (c *nativeContext) Text() string {
switch {
case c.Message != nil:
return c.Message.Text
case c.Callback != nil:
return c.Callback.Message.Text
case c.Query != nil:
return c.Query.Text
case c.ChosenInlineResult != nil:
return c.ChosenInlineResult.Query
case c.ShippingQuery != nil:
return c.ShippingQuery.Payload
case c.PreCheckoutQuery != nil:
return c.PreCheckoutQuery.Payload
case c.message != nil:
return c.message.Text
case c.callback != nil:
return c.callback.Message.Text
case c.query != nil:
return c.query.Text
case c.chosenInlineResult != nil:
return c.chosenInlineResult.Query
case c.shippingQuery != nil:
return c.shippingQuery.Payload
case c.preCheckoutQuery != nil:
return c.preCheckoutQuery.Payload
default:
return ""
}
@ -129,10 +203,10 @@ func (c *nativeContext) SendAlbum(a Album, opts ...interface{}) error {
}
func (c *nativeContext) Reply(what interface{}, opts ...interface{}) error {
if c.Message == nil {
if c.message == nil {
return ErrBadContext
}
_, err := c.b.Reply(c.Message, what, opts...)
_, err := c.b.Reply(c.message, what, opts...)
return err
}
@ -142,26 +216,26 @@ func (c *nativeContext) Forward(msg Editable, opts ...interface{}) error {
}
func (c *nativeContext) Edit(what interface{}, opts ...interface{}) error {
if c.Message == nil {
if c.message == nil {
return ErrBadContext
}
_, err := c.b.Edit(c.Message, what, opts...)
_, err := c.b.Edit(c.message, what, opts...)
return err
}
func (c *nativeContext) EditCaption(caption string, opts ...interface{}) error {
if c.Message == nil {
if c.message == nil {
return ErrBadContext
}
_, err := c.b.EditCaption(c.Message, caption, opts...)
_, err := c.b.EditCaption(c.message, caption, opts...)
return err
}
func (c *nativeContext) Delete() error {
if c.Message == nil {
if c.message == nil {
return ErrBadContext
}
return c.b.Delete(c.Message)
return c.b.Delete(c.message)
}
func (c *nativeContext) Notify(action ChatAction) error {
@ -169,29 +243,29 @@ func (c *nativeContext) Notify(action ChatAction) error {
}
func (c *nativeContext) Ship(what ...interface{}) error {
if c.ShippingQuery == nil {
if c.shippingQuery == nil {
return errors.New("telebot: context shipping query is nil")
}
return c.b.Ship(c.ShippingQuery, what...)
return c.b.Ship(c.shippingQuery, what...)
}
func (c *nativeContext) Accept(errorMessage ...string) error {
if c.PreCheckoutQuery == nil {
if c.preCheckoutQuery == nil {
return errors.New("telebot: context pre checkout query is nil")
}
return c.b.Accept(c.PreCheckoutQuery, errorMessage...)
return c.b.Accept(c.preCheckoutQuery, errorMessage...)
}
func (c *nativeContext) Answer(resp *QueryResponse) error {
if c.Query == nil {
if c.query == nil {
return errors.New("telebot: context inline query is nil")
}
return c.b.Answer(c.Query, resp)
return c.b.Answer(c.query, resp)
}
func (c *nativeContext) Respond(resp ...*CallbackResponse) error {
if c.Callback == nil {
if c.callback == nil {
return errors.New("telebot: context callback is nil")
}
return c.b.Respond(c.Callback, resp...)
return c.b.Respond(c.callback, resp...)
}

@ -10,8 +10,8 @@ import (
func (b *Bot) debug(err error) {
err = errors.WithStack(err)
if b.reporter != nil {
b.reporter(err)
if b.OnError != nil {
b.OnError(err)
} else {
log.Printf("%+v\n", err)
}
@ -27,10 +27,12 @@ func (b *Bot) deferDebug() {
}
}
func (b *Bot) runHandler(handler func()) {
func (b *Bot) runHandler(handler HandlerFunc, c Context) {
f := func() {
defer b.deferDebug()
handler()
if err := handler(c); err != nil {
b.OnError(err)
}
}
if b.synchronous {
f()

Loading…
Cancel
Save