telebot/update.go

347 lines
6.4 KiB
Go
Raw Permalink Normal View History

2023-02-01 12:08:20 +03:00
package telebot
import "strings"
// Update object represents an incoming update.
type Update struct {
ID int `json:"update_id"`
Message *Message `json:"message,omitempty"`
EditedMessage *Message `json:"edited_message,omitempty"`
ChannelPost *Message `json:"channel_post,omitempty"`
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
Callback *Callback `json:"callback_query,omitempty"`
Query *Query `json:"inline_query,omitempty"`
InlineResult *InlineResult `json:"chosen_inline_result,omitempty"`
ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"`
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
Poll *Poll `json:"poll,omitempty"`
PollAnswer *PollAnswer `json:"poll_answer,omitempty"`
MyChatMember *ChatMemberUpdate `json:"my_chat_member,omitempty"`
ChatMember *ChatMemberUpdate `json:"chat_member,omitempty"`
ChatJoinRequest *ChatJoinRequest `json:"chat_join_request,omitempty"`
}
// ProcessUpdate processes a single incoming update.
// A started bot calls this function automatically.
func (b *Bot) ProcessUpdate(u Update) {
c := b.NewContext(u)
if u.Message != nil {
m := u.Message
if m.PinnedMessage != nil {
b.handle(OnPinned, c)
return
}
// Commands
if m.Text != "" {
// Filtering malicious messages
if m.Text[0] == '\a' {
return
}
match := cmdRx.FindAllStringSubmatch(m.Text, -1)
if match != nil {
// Syntax: "</command>@<bot> <payload>"
command, botName := match[0][1], match[0][3]
if botName != "" && !strings.EqualFold(b.Me.Username, botName) {
return
}
m.Payload = match[0][5]
if b.handle(command, c) {
return
}
}
// 1:1 satisfaction
if b.handle(m.Text, c) {
return
}
b.handle(OnText, c)
return
}
if b.handleMedia(c) {
return
}
if m.Contact != nil {
b.handle(OnContact, c)
return
}
if m.Location != nil {
b.handle(OnLocation, c)
return
}
if m.Venue != nil {
b.handle(OnVenue, c)
return
}
if m.Game != nil {
b.handle(OnGame, c)
return
}
if m.Dice != nil {
b.handle(OnDice, c)
return
}
if m.Invoice != nil {
b.handle(OnInvoice, c)
return
}
if m.Payment != nil {
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, c)
return
}
if m.UserJoined != nil {
b.handle(OnUserJoined, c)
return
}
if m.UsersJoined != nil {
for _, user := range m.UsersJoined {
m.UserJoined = &user
b.handle(OnUserJoined, c)
}
return
}
if m.UserLeft != nil {
b.handle(OnUserLeft, c)
return
}
if m.NewGroupTitle != "" {
b.handle(OnNewGroupTitle, c)
return
}
if m.NewGroupPhoto != nil {
b.handle(OnNewGroupPhoto, c)
return
}
if m.GroupPhotoDeleted {
b.handle(OnGroupPhotoDeleted, c)
return
}
if m.GroupCreated {
b.handle(OnGroupCreated, c)
return
}
if m.SuperGroupCreated {
b.handle(OnSuperGroupCreated, c)
return
}
if m.ChannelCreated {
b.handle(OnChannelCreated, c)
return
}
if m.MigrateTo != 0 {
m.MigrateFrom = m.Chat.ID
b.handle(OnMigration, c)
return
}
if m.VideoChatStarted != nil {
b.handle(OnVideoChatStarted, c)
return
}
if m.VideoChatEnded != nil {
b.handle(OnVideoChatEnded, c)
return
}
if m.VideoChatParticipants != nil {
b.handle(OnVideoChatParticipants, c)
return
}
if m.VideoChatScheduled != nil {
b.handle(OnVideoChatScheduled, c)
return
}
if m.WebAppData != nil {
b.handle(OnWebApp, c)
}
if m.ProximityAlert != nil {
b.handle(OnProximityAlert, c)
return
}
if m.AutoDeleteTimer != nil {
b.handle(OnAutoDeleteTimer, c)
return
}
}
if u.EditedMessage != nil {
b.handle(OnEdited, c)
return
}
if u.ChannelPost != nil {
m := u.ChannelPost
if m.PinnedMessage != nil {
b.handle(OnPinned, c)
return
}
b.handle(OnChannelPost, c)
return
}
if u.EditedChannelPost != nil {
b.handle(OnEditedChannelPost, c)
return
}
if u.Callback != nil {
if data := u.Callback.Data; data != "" && data[0] == '\f' {
match := cbackRx.FindAllStringSubmatch(data, -1)
if match != nil {
unique, payload := match[0][1], match[0][3]
if handler, ok := b.handlers["\f"+unique]; ok {
u.Callback.Unique = unique
u.Callback.Data = payload
b.runHandler(handler, c)
return
}
}
}
b.handle(OnCallback, c)
return
}
if u.Query != nil {
b.handle(OnQuery, c)
return
}
if u.InlineResult != nil {
b.handle(OnInlineResult, c)
return
}
if u.ShippingQuery != nil {
b.handle(OnShipping, c)
return
}
if u.PreCheckoutQuery != nil {
b.handle(OnCheckout, c)
return
}
if u.Poll != nil {
b.handle(OnPoll, c)
return
}
if u.PollAnswer != nil {
b.handle(OnPollAnswer, c)
return
}
if u.MyChatMember != nil {
b.handle(OnMyChatMember, c)
return
}
if u.ChatMember != nil {
b.handle(OnChatMember, c)
return
}
if u.ChatJoinRequest != nil {
b.handle(OnChatJoinRequest, c)
return
}
}
func (b *Bot) handle(end string, c Context) bool {
if handler, ok := b.handlers[end]; ok {
b.runHandler(handler, c)
return true
}
return false
}
func (b *Bot) handleMedia(c Context) bool {
var (
m = c.Message()
fired = true
)
switch {
case m.Photo != nil:
fired = b.handle(OnPhoto, c)
case m.Voice != nil:
fired = b.handle(OnVoice, c)
case m.Audio != nil:
fired = b.handle(OnAudio, c)
case m.Animation != nil:
fired = b.handle(OnAnimation, c)
case m.Document != nil:
fired = b.handle(OnDocument, c)
case m.Sticker != nil:
fired = b.handle(OnSticker, c)
case m.Video != nil:
fired = b.handle(OnVideo, c)
case m.VideoNote != nil:
fired = b.handle(OnVideoNote, c)
default:
return false
}
if !fired {
return b.handle(OnMedia, c)
}
return true
}
func (b *Bot) runHandler(h HandlerFunc, c Context) {
f := func() {
if err := h(c); err != nil {
b.OnError(err, c)
}
}
if b.synchronous {
f()
} else {
go f()
}
}
func isUserInList(user *User, list []User) bool {
for _, user2 := range list {
if user.ID == user2.ID {
return true
}
}
return false
}