telebot/context.go

472 lines
12 KiB
Go
Raw Normal View History

2020-06-19 19:48:05 +00:00
package telebot
2020-07-25 20:08:51 +00:00
import (
"errors"
2020-07-25 20:08:51 +00:00
"strings"
2021-03-12 08:03:27 +00:00
"sync"
"time"
2020-07-25 20:08:51 +00:00
)
2020-06-19 19:48:05 +00:00
// HandlerFunc represents a handler function, which is
// used to handle actual endpoints.
2020-07-25 19:44:50 +00:00
type HandlerFunc func(Context) error
2021-08-19 10:46:04 +00:00
// Context wraps an update and represents the context of current event.
2020-06-19 19:48:05 +00:00
type Context interface {
2021-08-15 17:55:12 +00:00
// Bot returns the bot instance.
Bot() *Bot
// Update returns the original update.
Update() Update
2020-07-25 19:44:50 +00:00
// 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
// InlineResult returns stored inline result if such presented.
InlineResult() *InlineResult
2020-07-25 19:44:50 +00:00
// 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
// ChatMember returns chat member changes.
2021-08-19 14:40:36 +00:00
ChatMember() *ChatMemberUpdate
2021-07-26 14:37:48 +00:00
2021-11-05 20:31:32 +00:00
// ChatJoinRequest returns cha
ChatJoinRequest() *ChatJoinRequest
2020-07-25 19:44:50 +00:00
// Migration returns both migration from and to chat IDs.
Migration() (int64, int64)
// Sender returns the current recipient, depending on the context type.
2020-06-19 19:48:05 +00:00
// Returns nil if user is not presented.
Sender() *User
2020-06-19 19:48:05 +00:00
2020-10-10 10:44:39 +00:00
// Chat returns the current chat, depending on the context type.
// Returns nil if chat is not presented.
Chat() *Chat
// Recipient combines both Sender and Chat functions. If there is no user
2020-10-22 16:29:12 +00:00
// the chat will be returned. The native context cannot be without sender,
// but it is useful in the case when the context created intentionally
// by the NewContext constructor and have only Chat field inside.
Recipient() Recipient
2020-10-22 16:29:12 +00:00
2020-10-12 15:46:45 +00:00
// Text returns the message text, depending on the context type.
2020-06-19 19:48:05 +00:00
// In the case when no related data presented, returns an empty string.
Text() string
2020-10-12 15:46:45 +00:00
// Data returns the current data, depending on the context type.
// If the context contains command, returns its arguments string.
2020-10-12 15:46:45 +00:00
// If the context contains payment, returns its payload.
// In the case when no related data presented, returns an empty string.
Data() string
2020-07-25 20:08:51 +00:00
// Args returns a raw slice of command or callback arguments as strings.
// The message arguments split by space, while the callback's ones by a "|" symbol.
Args() []string
2020-06-19 19:48:05 +00:00
// Send sends a message to the current recipient.
// See Send from bot.go.
Send(what interface{}, opts ...interface{}) error
// SendAlbum sends an album to the current recipient.
// See SendAlbum from bot.go.
SendAlbum(a Album, opts ...interface{}) error
// Reply replies to the current message.
// See Reply from bot.go.
Reply(what interface{}, opts ...interface{}) error
// Forward forwards the given message to the current recipient.
2020-06-19 19:48:05 +00:00
// See Forward from bot.go.
Forward(msg Editable, opts ...interface{}) error
// ForwardTo forwards the current message to the given recipient.
// See Forward from bot.go
ForwardTo(to Recipient, opts ...interface{}) error
// Edit edits the current message.
2020-06-19 19:48:05 +00:00
// See Edit from bot.go.
Edit(what interface{}, opts ...interface{}) error
2020-06-19 19:48:05 +00:00
// EditCaption edits the caption of the current message.
2020-06-19 19:48:05 +00:00
// See EditCaption from bot.go.
EditCaption(caption string, opts ...interface{}) error
2020-06-19 19:48:05 +00:00
// EditOrSend edits the current message if the update is callback,
// otherwise the content is sent to the chat as a separate message.
EditOrSend(what interface{}, opts ...interface{}) error
// EditOrReply edits the current message if the update is callback,
// otherwise the content is replied as a separate message.
EditOrReply(what interface{}, opts ...interface{}) error
2020-06-19 19:48:05 +00:00
// Delete removes the current message.
// See Delete from bot.go.
Delete() error
// DeleteAfter waits for the duration to elapse and then removes the
// message. It handles an error automatically using b.OnError callback.
// It returns a Timer that can be used to cancel the call using its Stop method.
DeleteAfter(d time.Duration) *time.Timer
2020-06-19 19:48:05 +00:00
// Notify updates the chat action for the current recipient.
// See Notify from bot.go.
Notify(action ChatAction) error
// Ship replies to the current shipping query.
// See Ship from bot.go.
Ship(what ...interface{}) error
// Accept finalizes the current deal.
// See Accept from bot.go.
Accept(errorMessage ...string) error
// Answer sends a response to the current inline query.
// See Answer from bot.go.
Answer(resp *QueryResponse) error
// Respond sends a response for the current callback query.
// See Respond from bot.go.
Respond(resp ...*CallbackResponse) error
2021-03-12 08:03:27 +00:00
// Get retrieves data from the context.
Get(key string) interface{}
// Set saves data in the context.
Set(key string, val interface{})
2020-06-19 19:48:05 +00:00
}
// nativeContext is a native implementation of the Context interface.
// "context" is taken by context package, maybe there is a better name.
type nativeContext struct {
2022-01-21 12:47:11 +00:00
b *Bot
u Update
2021-03-12 08:03:27 +00:00
lock sync.RWMutex
store map[string]interface{}
2020-07-25 19:44:50 +00:00
}
2021-08-15 17:55:12 +00:00
func (c *nativeContext) Bot() *Bot {
return c.b
}
func (c *nativeContext) Update() Update {
2022-01-21 12:47:11 +00:00
return c.u
}
2020-07-25 19:44:50 +00:00
func (c *nativeContext) Message() *Message {
switch {
2022-01-21 12:47:11 +00:00
case c.u.Message != nil:
return c.u.Message
case c.u.Callback != nil:
return c.u.Callback.Message
case c.u.EditedMessage != nil:
return c.u.EditedMessage
case c.u.ChannelPost != nil:
if c.u.ChannelPost.PinnedMessage != nil {
return c.u.ChannelPost.PinnedMessage
}
return c.u.ChannelPost
case c.u.EditedChannelPost != nil:
return c.u.EditedChannelPost
2020-07-25 19:44:50 +00:00
default:
return nil
}
}
func (c *nativeContext) Callback() *Callback {
2022-01-21 12:47:11 +00:00
return c.u.Callback
2020-07-25 19:44:50 +00:00
}
func (c *nativeContext) Query() *Query {
2022-01-21 12:47:11 +00:00
return c.u.Query
2020-07-25 19:44:50 +00:00
}
func (c *nativeContext) InlineResult() *InlineResult {
2022-01-21 12:47:11 +00:00
return c.u.InlineResult
2020-07-25 19:44:50 +00:00
}
func (c *nativeContext) ShippingQuery() *ShippingQuery {
2022-01-21 12:47:11 +00:00
return c.u.ShippingQuery
2020-07-25 19:44:50 +00:00
}
func (c *nativeContext) PreCheckoutQuery() *PreCheckoutQuery {
2022-01-21 12:47:11 +00:00
return c.u.PreCheckoutQuery
2020-07-25 19:44:50 +00:00
}
2021-08-19 14:40:36 +00:00
func (c *nativeContext) ChatMember() *ChatMemberUpdate {
switch {
2022-01-21 12:47:11 +00:00
case c.u.ChatMember != nil:
return c.u.ChatMember
case c.u.MyChatMember != nil:
return c.u.MyChatMember
default:
return nil
}
}
2021-11-05 20:31:32 +00:00
func (c *nativeContext) ChatJoinRequest() *ChatJoinRequest {
2022-01-21 12:47:11 +00:00
return c.u.ChatJoinRequest
2021-11-05 20:31:32 +00:00
}
2020-07-25 19:44:50 +00:00
func (c *nativeContext) Poll() *Poll {
2022-01-21 12:47:11 +00:00
return c.u.Poll
2020-07-25 19:44:50 +00:00
}
func (c *nativeContext) PollAnswer() *PollAnswer {
2022-01-21 12:47:11 +00:00
return c.u.PollAnswer
2020-07-25 19:44:50 +00:00
}
func (c *nativeContext) Migration() (int64, int64) {
2022-01-21 12:47:11 +00:00
return c.u.Message.MigrateFrom, c.u.Message.MigrateTo
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) Sender() *User {
2020-06-19 19:48:05 +00:00
switch {
2022-01-21 12:47:11 +00:00
case c.u.Callback != nil:
return c.u.Callback.Sender
2022-01-22 16:32:04 +00:00
case c.Message() != nil:
return c.Message().Sender
2022-01-21 12:47:11 +00:00
case c.u.Query != nil:
return c.u.Query.Sender
case c.u.InlineResult != nil:
return c.u.InlineResult.Sender
case c.u.ShippingQuery != nil:
return c.u.ShippingQuery.Sender
case c.u.PreCheckoutQuery != nil:
return c.u.PreCheckoutQuery.Sender
case c.u.PollAnswer != nil:
return c.u.PollAnswer.Sender
case c.u.MyChatMember != nil:
return c.u.MyChatMember.Sender
case c.u.ChatMember != nil:
return c.u.ChatMember.Sender
case c.u.ChatJoinRequest != nil:
return c.u.ChatJoinRequest.Sender
2020-06-19 19:48:05 +00:00
default:
return nil
}
}
2020-10-10 10:44:39 +00:00
func (c *nativeContext) Chat() *Chat {
switch {
2022-01-22 16:32:04 +00:00
case c.Message() != nil:
return c.Message().Chat
2022-01-21 12:47:11 +00:00
case c.u.MyChatMember != nil:
return c.u.MyChatMember.Chat
case c.u.ChatMember != nil:
return c.u.ChatMember.Chat
case c.u.ChatJoinRequest != nil:
return c.u.ChatJoinRequest.Chat
2020-10-10 10:44:39 +00:00
default:
return nil
}
}
func (c *nativeContext) Recipient() Recipient {
chat := c.Chat()
if chat != nil {
return chat
}
return c.Sender()
}
2020-06-19 19:48:05 +00:00
func (c *nativeContext) Text() string {
2022-01-22 16:32:04 +00:00
m := c.Message()
if m == nil {
2020-10-12 15:46:45 +00:00
return ""
}
if m.Caption != "" {
return m.Caption
}
return m.Text
2020-10-12 15:46:45 +00:00
}
func (c *nativeContext) Data() string {
switch {
2022-01-21 12:47:11 +00:00
case c.u.Message != nil:
return c.u.Message.Payload
case c.u.Callback != nil:
return c.u.Callback.Data
case c.u.Query != nil:
return c.u.Query.Text
case c.u.InlineResult != nil:
return c.u.InlineResult.Query
case c.u.ShippingQuery != nil:
return c.u.ShippingQuery.Payload
case c.u.PreCheckoutQuery != nil:
return c.u.PreCheckoutQuery.Payload
2020-06-19 19:48:05 +00:00
default:
return ""
}
}
2020-07-25 20:08:51 +00:00
func (c *nativeContext) Args() []string {
2021-07-28 07:30:52 +00:00
switch {
2022-01-21 12:47:11 +00:00
case c.u.Message != nil:
payload := strings.Trim(c.u.Message.Payload, " ")
2021-07-28 07:30:52 +00:00
if payload != "" {
return strings.Split(payload, " ")
}
2022-01-21 12:47:11 +00:00
case c.u.Callback != nil:
return strings.Split(c.u.Callback.Data, "|")
case c.u.Query != nil:
return strings.Split(c.u.Query.Text, " ")
case c.u.InlineResult != nil:
return strings.Split(c.u.InlineResult.Query, " ")
2020-07-25 20:08:51 +00:00
}
return nil
}
2020-06-19 19:48:05 +00:00
func (c *nativeContext) Send(what interface{}, opts ...interface{}) error {
_, err := c.b.Send(c.Recipient(), what, opts...)
2020-06-19 19:48:05 +00:00
return err
}
func (c *nativeContext) SendAlbum(a Album, opts ...interface{}) error {
_, err := c.b.SendAlbum(c.Recipient(), a, opts...)
2020-06-19 19:48:05 +00:00
return err
}
func (c *nativeContext) Reply(what interface{}, opts ...interface{}) error {
msg := c.Message()
if msg == nil {
2020-06-19 19:48:05 +00:00
return ErrBadContext
}
_, err := c.b.Reply(msg, what, opts...)
2020-06-19 19:48:05 +00:00
return err
}
func (c *nativeContext) Forward(msg Editable, opts ...interface{}) error {
_, err := c.b.Forward(c.Recipient(), msg, opts...)
2020-06-19 19:48:05 +00:00
return err
}
func (c *nativeContext) ForwardTo(to Recipient, opts ...interface{}) error {
msg := c.Message()
if msg == nil {
return ErrBadContext
}
_, err := c.b.Forward(to, msg, opts...)
return err
}
func (c *nativeContext) Edit(what interface{}, opts ...interface{}) error {
2022-01-21 12:47:11 +00:00
if c.u.InlineResult != nil {
_, err := c.b.Edit(c.u.InlineResult, what, opts...)
return err
}
2022-01-21 12:47:11 +00:00
if c.u.Callback != nil {
_, err := c.b.Edit(c.u.Callback, what, opts...)
return err
}
return ErrBadContext
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) EditCaption(caption string, opts ...interface{}) error {
2022-01-21 12:47:11 +00:00
if c.u.InlineResult != nil {
_, err := c.b.EditCaption(c.u.InlineResult, caption, opts...)
2021-08-31 11:08:51 +00:00
return err
}
2022-01-21 12:47:11 +00:00
if c.u.Callback != nil {
_, err := c.b.EditCaption(c.u.Callback, caption, opts...)
2021-08-31 11:08:51 +00:00
return err
}
return ErrBadContext
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) EditOrSend(what interface{}, opts ...interface{}) error {
2021-08-31 11:08:51 +00:00
err := c.Edit(what, opts...)
if err == ErrBadContext {
return c.Send(what, opts...)
}
2021-08-31 11:08:51 +00:00
return err
}
func (c *nativeContext) EditOrReply(what interface{}, opts ...interface{}) error {
2021-08-31 11:08:51 +00:00
err := c.Edit(what, opts...)
if err == ErrBadContext {
return c.Reply(what, opts...)
}
2021-08-31 11:08:51 +00:00
return err
}
2020-06-19 19:48:05 +00:00
func (c *nativeContext) Delete() error {
msg := c.Message()
if msg == nil {
2020-06-19 19:48:05 +00:00
return ErrBadContext
}
return c.b.Delete(msg)
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) DeleteAfter(d time.Duration) *time.Timer {
return time.AfterFunc(d, func() {
if err := c.Delete(); err != nil {
c.b.OnError(err, c)
}
})
}
2020-06-19 19:48:05 +00:00
func (c *nativeContext) Notify(action ChatAction) error {
return c.b.Notify(c.Recipient(), action)
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) Ship(what ...interface{}) error {
2022-01-21 12:47:11 +00:00
if c.u.ShippingQuery == nil {
2020-06-19 19:48:05 +00:00
return errors.New("telebot: context shipping query is nil")
}
2022-01-21 12:47:11 +00:00
return c.b.Ship(c.u.ShippingQuery, what...)
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) Accept(errorMessage ...string) error {
2022-01-21 12:47:11 +00:00
if c.u.PreCheckoutQuery == nil {
2020-06-19 19:48:05 +00:00
return errors.New("telebot: context pre checkout query is nil")
}
2022-01-21 12:47:11 +00:00
return c.b.Accept(c.u.PreCheckoutQuery, errorMessage...)
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) Answer(resp *QueryResponse) error {
2022-01-21 12:47:11 +00:00
if c.u.Query == nil {
2020-06-19 19:48:05 +00:00
return errors.New("telebot: context inline query is nil")
}
2022-01-21 12:47:11 +00:00
return c.b.Answer(c.u.Query, resp)
2020-06-19 19:48:05 +00:00
}
func (c *nativeContext) Respond(resp ...*CallbackResponse) error {
2022-01-21 12:47:11 +00:00
if c.u.Callback == nil {
2020-06-19 19:48:05 +00:00
return errors.New("telebot: context callback is nil")
}
2022-01-21 12:47:11 +00:00
return c.b.Respond(c.u.Callback, resp...)
2020-06-19 19:48:05 +00:00
}
2021-03-12 08:03:27 +00:00
func (c *nativeContext) Set(key string, value interface{}) {
c.lock.Lock()
defer c.lock.Unlock()
if c.store == nil {
c.store = make(map[string]interface{})
}
c.store[key] = value
}
func (c *nativeContext) Get(key string) interface{} {
c.lock.RLock()
defer c.lock.RUnlock()
return c.store[key]
}