From b5718e12131697841768321167366ec50e97285a Mon Sep 17 00:00:00 2001 From: comerc Date: Fri, 14 May 2021 07:01:25 +0300 Subject: [PATCH 01/31] Add copyMessage --- bot.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/bot.go b/bot.go index ddbf350..8152d98 100644 --- a/bot.go +++ b/bot.go @@ -741,6 +741,32 @@ func (b *Bot) Forward(to Recipient, msg Editable, options ...interface{}) (*Mess return extractMessage(data) } +// Copy behaves just like Forward() but the copied message doesn't have a link to the original message (see Bots API). +// +// This function will panic upon nil Editable. +func (b *Bot) Copy(to Recipient, msg Editable, options ...interface{}) (*Message, error) { + if to == nil { + return nil, ErrBadRecipient + } + msgID, chatID := msg.MessageSig() + + params := map[string]string{ + "chat_id": to.Recipient(), + "from_chat_id": strconv.FormatInt(chatID, 10), + "message_id": msgID, + } + + sendOpts := extractOptions(options) + b.embedSendOptions(params, sendOpts) + + data, err := b.Raw("copyMessage", params) + if err != nil { + return nil, err + } + + return extractMessage(data) +} + // Edit is magic, it lets you change already sent message. // // If edited message is sent by the bot, returns it, From eb09eb2ca75a4f3a161d1cb439aad990c4656d84 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 15:05:37 +0300 Subject: [PATCH 02/31] bot: add log out and close api server --- bot.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/bot.go b/bot.go index ddbf350..4936e08 100644 --- a/bot.go +++ b/bot.go @@ -1526,3 +1526,37 @@ func (b *Bot) SetCommands(cmds []Command) error { func (b *Bot) NewMarkup() *ReplyMarkup { return &ReplyMarkup{} } + +// Logout log out from the cloud Bot API server before launching the bot locally, +func (b *Bot) Logout() (bool, error) { + data, err := b.Raw("logOut", nil) + if err != nil { + return false, err + } + + var resp struct { + Result bool `json:"result"` + } + if err := json.Unmarshal(data, &resp); err != nil { + return false, wrapError(err) + } + + return resp.Result, nil +} + +// Close closes the bot instance before moving it from one local server to another, +func (b *Bot) Close() (bool, error) { + data, err := b.Raw("close", nil) + if err != nil { + return false, err + } + + var resp struct { + Result bool `json:"result"` + } + if err := json.Unmarshal(data, &resp); err != nil { + return false, wrapError(err) + } + + return resp.Result, nil +} From cfe18bbec558a52999dee32067aeb9bc60b7bc28 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 15:16:48 +0300 Subject: [PATCH 03/31] bot: typo fix --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index 4936e08..8e285fc 100644 --- a/bot.go +++ b/bot.go @@ -1527,7 +1527,7 @@ func (b *Bot) NewMarkup() *ReplyMarkup { return &ReplyMarkup{} } -// Logout log out from the cloud Bot API server before launching the bot locally, +// Logout logs out from the cloud Bot API server before launching the bot locally, func (b *Bot) Logout() (bool, error) { data, err := b.Raw("logOut", nil) if err != nil { From b7575fce7041b962bf43d13ff5a5129ee1f22a57 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 15:17:03 +0300 Subject: [PATCH 04/31] webhooks: add ip_address and drop_pending_updates fields --- webhook.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/webhook.go b/webhook.go index e3f953a..22970c1 100644 --- a/webhook.go +++ b/webhook.go @@ -49,6 +49,9 @@ type Webhook struct { ErrorUnixtime int64 `json:"last_error_date"` ErrorMessage string `json:"last_error_message"` + IpAddress string `json:"ip_address"` + DropPendingUpdates bool `json:"drop_pending_updates"` + TLS *WebhookTLS Endpoint *WebhookEndpoint @@ -88,6 +91,12 @@ func (h *Webhook) getParams() map[string]string { data, _ := json.Marshal(h.AllowedUpdates) params["allowed_updates"] = string(data) } + if h.IpAddress != "" { + params["ip_address"] = h.IpAddress + } + if h.DropPendingUpdates { + params["drop_pending_updates"] = strconv.FormatBool(h.DropPendingUpdates) + } if h.TLS != nil { params["url"] = "https://" + h.Listen @@ -178,7 +187,13 @@ func (b *Bot) SetWebhook(w *Webhook) error { } // RemoveWebhook removes webhook integration. -func (b *Bot) RemoveWebhook() error { - _, err := b.Raw("deleteWebhook", nil) +func (b *Bot) RemoveWebhook(dropPending ...bool) error { + drop := false + if len(dropPending) > 0 { + drop = dropPending[0] + } + _, err := b.Raw("deleteWebhook", map[string]bool{ + "drop_pending_updates": drop, + }) return err } From 072f7ef63b55cbfa2a7ba2237c0601ba0c4acbd6 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 15:34:29 +0300 Subject: [PATCH 05/31] groups: add fields of get chat request --- admin.go | 6 +++++- chat.go | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/admin.go b/admin.go index 64a4df1..b4ff014 100644 --- a/admin.go +++ b/admin.go @@ -148,12 +148,16 @@ func (b *Bot) Ban(chat *Chat, member *ChatMember) error { } // Unban will unban user from chat, who would have thought eh? -func (b *Bot) Unban(chat *Chat, user *User) error { +func (b *Bot) Unban(chat *Chat, user *User, isBanned ...bool) error { params := map[string]string{ "chat_id": chat.Recipient(), "user_id": user.Recipient(), } + if len(isBanned) > 0 { + params["only_if_banned"] = strconv.FormatBool(isBanned[0]) + } + _, err := b.Raw("unbanChatMember", params) return err } diff --git a/chat.go b/chat.go index a57934c..af00327 100644 --- a/chat.go +++ b/chat.go @@ -42,6 +42,7 @@ type Chat struct { Still bool `json:"is_member,omitempty"` // Returns only in getChat + Bio string `json:"bio,omitempty"` Photo *ChatPhoto `json:"photo,omitempty"` Description string `json:"description,omitempty"` InviteLink string `json:"invite_link,omitempty"` @@ -50,6 +51,11 @@ type Chat struct { SlowMode int `json:"slow_mode_delay,omitempty"` StickerSet string `json:"sticker_set_name,omitempty"` CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` + LinkedChatID int64 `json:"linked_chat_id,omitempty"` + ChatLocation *struct { + Location Location `json:"location,omitempty"` + Address string `json:"address,omitempty"` + } `json:"location,omitempty"` } // ChatPhoto object represents a chat photo. From 277c1eedbd6628260b0d41c300b014352dbb0abe Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 15:38:32 +0300 Subject: [PATCH 06/31] files: add file_name and disable content type detection fields --- file.go | 1 + options.go | 3 +++ util.go | 8 ++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/file.go b/file.go index 2025e77..9d61d17 100644 --- a/file.go +++ b/file.go @@ -9,6 +9,7 @@ import ( type File struct { FileID string `json:"file_id"` UniqueID string `json:"file_unique_id"` + FileName string `json:"file_name"` FileSize int `json:"file_size"` // file on telegram server https://core.telegram.org/bots/api#file diff --git a/options.go b/options.go index 9329e70..09c30d0 100644 --- a/options.go +++ b/options.go @@ -50,6 +50,9 @@ type SendOptions struct { // ParseMode controls how client apps render your message. ParseMode ParseMode + + // DisableContentDetection abilities to disable server-side file content type detection. + DisableContentDetection bool } func (og *SendOptions) copy() *SendOptions { diff --git a/util.go b/util.go index a07020a..030da62 100644 --- a/util.go +++ b/util.go @@ -1,13 +1,13 @@ package telebot import ( + "bytes" "encoding/json" "fmt" + "github.com/pkg/errors" "log" "net/http" "strconv" - "bytes" - "github.com/pkg/errors" ) func (b *Bot) debug(err error) { @@ -195,6 +195,10 @@ func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) { params["parse_mode"] = opt.ParseMode } + if opt.DisableContentDetection { + params["disable_content_type_detection"] = "true" + } + if opt.ReplyMarkup != nil { processButtons(opt.ReplyMarkup.InlineKeyboard) replyMarkup, _ := json.Marshal(opt.ReplyMarkup) From e8cbd53914cb2b9467d116023108db4830e9e690 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 15:56:02 +0300 Subject: [PATCH 07/31] messages: add message_id field and unpin all messages method --- bot.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/bot.go b/bot.go index 8e285fc..6296cf1 100644 --- a/bot.go +++ b/bot.go @@ -1395,15 +1395,32 @@ func (b *Bot) Pin(msg Editable, options ...interface{}) error { // Unpin unpins a message in a supergroup or a channel. // // It supports tb.Silent option. -func (b *Bot) Unpin(chat *Chat) error { +// MessageID is a specific pinned message +func (b *Bot) Unpin(chat *Chat, messageID ...int) error { params := map[string]string{ "chat_id": chat.Recipient(), } + if len(messageID) > 0 { + params["message_id"] = strconv.Itoa(messageID[0]) + } _, err := b.Raw("unpinChatMessage", params) return err } +// Unpin unpins all messages in a supergroup or a channel. +// +// It supports tb.Silent option. +// MessageID is a specific pinned message +func (b *Bot) UnpinAll(chat *Chat) error { + params := map[string]string{ + "chat_id": chat.Recipient(), + } + + _, err := b.Raw("unpinAllChatMessages", params) + return err +} + // ChatByID fetches chat info of its ID. // // Including current name of the user for one-on-one conversations, From 0ba7aefa6932ea03dcc89d5fb527fc4fd2ce3593 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 16:17:38 +0300 Subject: [PATCH 08/31] live location: add support live_period, heading, proximity_alert_radius fields and add proximity alert trigger --- bot.go | 22 ++++++++++++++++++++++ media.go | 15 +++++++++++++++ message.go | 4 ++++ sendable.go | 9 +++++++++ telebot.go | 5 +++++ 5 files changed, 55 insertions(+) diff --git a/bot.go b/bot.go index 6296cf1..33982d1 100644 --- a/bot.go +++ b/bot.go @@ -348,6 +348,19 @@ func (b *Bot) ProcessUpdate(upd Update) { return } + + if m.ProximityAlertTriggered != nil { + if handler, ok := b.handlers[OnProximityAlertTriggered]; ok { + handler, ok := handler.(func(*Message)) + if !ok { + panic("telebot: proximity alert triggered handler is bad") + } + + b.runHandler(func() { handler(m) }) + } + + return + } } if upd.EditedMessage != nil { @@ -773,6 +786,15 @@ func (b *Bot) Edit(msg Editable, what interface{}, options ...interface{}) (*Mes method = "editMessageLiveLocation" params["latitude"] = fmt.Sprintf("%f", v.Lat) params["longitude"] = fmt.Sprintf("%f", v.Lng) + if v.HA != nil { + params["horizontal_accuracy"] = fmt.Sprintf("%f", *v.HA) + } + if v.Heading != 0 { + params["heading"] = strconv.Itoa(v.Heading) + } + if v.ProximityAlertRadius != 0 { + params["proximity_alert_radius"] = strconv.Itoa(v.Heading) + } default: return nil, ErrUnsupportedWhat } diff --git a/media.go b/media.go index 13b7134..77c6f5e 100644 --- a/media.go +++ b/media.go @@ -195,9 +195,24 @@ type Location struct { // Longitude Lng float32 `json:"longitude"` + // Horizontal Accuracy + HA *float32 `json:"horizontal_accuracy,omitempty"` + + Heading int `json:"heading,omitempty"` + // Period in seconds for which the location will be updated // (see Live Locations, should be between 60 and 86400.) LivePeriod int `json:"live_period,omitempty"` + + ProximityAlertRadius int `json:"proximity_alert_radius,omitempty"` +} + +// ProximityAlertTriggered object represents sent whenever +// a user in the chat triggers a proximity alert set by another user. +type ProximityAlertTriggered struct { + Traveler *User `json:"traveler,omitempty"` + Watcher *User `json:"watcher,omitempty"` + Distance int `json:"distance"` } // Venue object represents a venue location with name, address and diff --git a/message.go b/message.go index 47cbdcb..6db077f 100644 --- a/message.go +++ b/message.go @@ -226,6 +226,10 @@ type Message struct { // For a service message, some users were invited in the voice chat. VoiceChatPartecipantsInvited *VoiceChatPartecipantsInvited `json:"voice_chat_partecipants_invited,omitempty"` + + // For a service message, represents the content of a service message, + // sent whenever a user in the chat triggers a proximity alert set by another user. + ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered,omitempty"` } // MessageEntity object represents "special" parts of text messages, diff --git a/sendable.go b/sendable.go index 7036de8..86c123d 100644 --- a/sendable.go +++ b/sendable.go @@ -265,6 +265,15 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error "longitude": fmt.Sprintf("%f", x.Lng), "live_period": strconv.Itoa(x.LivePeriod), } + if x.HA != nil { + params["horizontal_accuracy"] = fmt.Sprintf("%f", *x.HA) + } + if x.Heading != 0 { + params["heading"] = strconv.Itoa(x.Heading) + } + if x.ProximityAlertRadius != 0 { + params["proximity_alert_radius"] = strconv.Itoa(x.Heading) + } b.embedSendOptions(params, opt) data, err := b.Raw("sendLocation", params) diff --git a/telebot.go b/telebot.go index 5cb25fb..e2f3b4d 100644 --- a/telebot.go +++ b/telebot.go @@ -144,6 +144,11 @@ const ( // // Handler: func(*Message) OnVoiceChatPartecipantsInvited = "\avoice_chat_partecipants_invited" + + // Will fire on ProximityAlertTriggered + // + // Handler: func(*Message) + OnProximityAlertTriggered = "\aproximity_alert_triggered" ) // ChatAction is a client-side status indicating bot activity. From 24f37119636e1ec5b7a48b560c203ae6c6bb14b0 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 16:27:40 +0300 Subject: [PATCH 09/31] venue: add google place fields --- media.go | 6 ++++-- sendable.go | 16 +++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/media.go b/media.go index 77c6f5e..e5e1acf 100644 --- a/media.go +++ b/media.go @@ -223,8 +223,10 @@ type Venue struct { Address string `json:"address"` // (Optional) - FoursquareID string `json:"foursquare_id,omitempty"` - FoursquareType string `json:"foursquare_type,omitempty"` + FoursquareID string `json:"foursquare_id,omitempty"` + FoursquareType string `json:"foursquare_type,omitempty"` + GooglePlaceID string `json:"google_place_id,omitempty"` + GooglePlaceType string `json:"google_place_type,omitempty"` } // Dice object represents a dice with a random value diff --git a/sendable.go b/sendable.go index 86c123d..56d5e53 100644 --- a/sendable.go +++ b/sendable.go @@ -287,13 +287,15 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error // Send delivers media through bot b to recipient. func (v *Venue) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) { params := map[string]string{ - "chat_id": to.Recipient(), - "latitude": fmt.Sprintf("%f", v.Location.Lat), - "longitude": fmt.Sprintf("%f", v.Location.Lng), - "title": v.Title, - "address": v.Address, - "foursquare_id": v.FoursquareID, - "foursquare_type": v.FoursquareType, + "chat_id": to.Recipient(), + "latitude": fmt.Sprintf("%f", v.Location.Lat), + "longitude": fmt.Sprintf("%f", v.Location.Lng), + "title": v.Title, + "address": v.Address, + "foursquare_id": v.FoursquareID, + "foursquare_type": v.FoursquareType, + "google_place_id": v.GooglePlaceID, + "google_place_type": v.GooglePlaceType, } b.embedSendOptions(params, opt) From bd1acf22f110f823c56cef5041855ba4411d6a06 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 16:28:02 +0300 Subject: [PATCH 10/31] message: add sender_chat field --- message.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/message.go b/message.go index 6db077f..3d4dc6d 100644 --- a/message.go +++ b/message.go @@ -20,6 +20,9 @@ type Message struct { // Conversation the message belongs to. Chat *Chat `json:"chat"` + // Sender of the message, sent on behalf of a chat. + SenderChat *Chat `json:"sender_chat"` + // For forwarded messages, sender of the original message. OriginalSender *User `json:"forward_from"` From 44945b170354a8c87702ff6f0d2f9da7a129fc65 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 16:28:29 +0300 Subject: [PATCH 11/31] chat: add is_anonymous field --- admin.go | 5 +++-- chat.go | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/admin.go b/admin.go index b4ff014..4845921 100644 --- a/admin.go +++ b/admin.go @@ -199,8 +199,9 @@ func (b *Bot) Promote(chat *Chat, member *ChatMember) error { prv := member.Rights params := map[string]interface{}{ - "chat_id": chat.Recipient(), - "user_id": member.User.Recipient(), + "chat_id": chat.Recipient(), + "user_id": member.User.Recipient(), + "is_anonymous": member.IsAnonymous, } embedRights(params, prv) diff --git a/chat.go b/chat.go index af00327..7815bab 100644 --- a/chat.go +++ b/chat.go @@ -78,9 +78,10 @@ func (c *Chat) Recipient() string { type ChatMember struct { Rights - User *User `json:"user"` - Role MemberStatus `json:"status"` - Title string `json:"custom_title"` + User *User `json:"user"` + Role MemberStatus `json:"status"` + Title string `json:"custom_title"` + IsAnonymous bool `json:"is_anonymous"` // Date when restrictions will be lifted for the user, unix time. // From f136c77a4aaf3b755bfcc4921f1c09f68db974d8 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 16:28:59 +0300 Subject: [PATCH 12/31] sendable: add sending without reply field --- options.go | 3 +++ util.go | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/options.go b/options.go index 09c30d0..8ad30d7 100644 --- a/options.go +++ b/options.go @@ -53,6 +53,9 @@ type SendOptions struct { // DisableContentDetection abilities to disable server-side file content type detection. DisableContentDetection bool + + // AllowWithoutReply allows sending messages not a as reply if the replied-to message has already been deleted. + AllowWithoutReply bool } func (og *SendOptions) copy() *SendOptions { diff --git a/util.go b/util.go index 030da62..5856d15 100644 --- a/util.go +++ b/util.go @@ -199,6 +199,10 @@ func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) { params["disable_content_type_detection"] = "true" } + if opt.AllowWithoutReply { + params["allow_sending_without_reply"] = "true" + } + if opt.ReplyMarkup != nil { processButtons(opt.ReplyMarkup.InlineKeyboard) replyMarkup, _ := json.Marshal(opt.ReplyMarkup) From 0816adc16eb09dfe1dbf9a4012ccf672e7eea878 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 16:42:07 +0300 Subject: [PATCH 13/31] bot: typo fix --- bot.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.go b/bot.go index 33982d1..37da15e 100644 --- a/bot.go +++ b/bot.go @@ -1566,7 +1566,7 @@ func (b *Bot) NewMarkup() *ReplyMarkup { return &ReplyMarkup{} } -// Logout logs out from the cloud Bot API server before launching the bot locally, +// Logout logs out from the cloud Bot API server before launching the bot locally. func (b *Bot) Logout() (bool, error) { data, err := b.Raw("logOut", nil) if err != nil { @@ -1583,7 +1583,7 @@ func (b *Bot) Logout() (bool, error) { return resp.Result, nil } -// Close closes the bot instance before moving it from one local server to another, +// Close closes the bot instance before moving it from one local server to another. func (b *Bot) Close() (bool, error) { data, err := b.Raw("close", nil) if err != nil { From 5d1d57964275ea658d12f4afe04f4c2b9b98cd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=23=D0=BA=D0=BE=D0=B4=D0=B5=D1=80=D0=BE=D1=82=D0=B1=D0=BE?= =?UTF-8?q?=D0=B3=D0=B0?= Date: Sun, 23 May 2021 18:07:40 +0300 Subject: [PATCH 14/31] Add CreateChatInviteLink() --- bot.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/bot.go b/bot.go index 8152d98..4c0b179 100644 --- a/bot.go +++ b/bot.go @@ -1295,6 +1295,33 @@ func (b *Bot) StopPoll(msg Editable, options ...interface{}) (*Poll, error) { return resp.Result, nil } +// CreateChatInviteLink should be used to create an additional invite link for a chat. +func (b *Bot) CreateChatInviteLink(chat *Chat, expireDate int64, memberLimit int) (*ChatInviteLink, error) { + params := map[string]string{ + "chat_id": chat.Recipient(), + } + if expireDate > 0 { + params["expire_date"] = fmt.Sprintf("%d", expireDate) + } + if memberLimit > 0 { + params["member_limit"] = fmt.Sprintf("%d", memberLimit) + } + + data, err := b.Raw("createChatInviteLink", params) + if err != nil { + return nil, err + } + + var resp struct { + Result *ChatInviteLink + } + + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result, nil +} + // GetInviteLink should be used to export chat's invite link. func (b *Bot) GetInviteLink(chat *Chat) (string, error) { params := map[string]string{ From 965cd03621edfafb63420424c91fbc0b015adf45 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 19:43:58 +0300 Subject: [PATCH 15/31] telebot: fix all miscalculations --- admin.go | 9 +++++---- bot.go | 11 +++++------ chat.go | 38 ++++++++++++++++++++------------------ media.go | 4 ++-- sendable.go | 4 ++-- telebot.go | 4 ++-- webhook.go | 12 ++++++------ 7 files changed, 42 insertions(+), 40 deletions(-) diff --git a/admin.go b/admin.go index 4845921..2a6d5b4 100644 --- a/admin.go +++ b/admin.go @@ -148,14 +148,15 @@ func (b *Bot) Ban(chat *Chat, member *ChatMember) error { } // Unban will unban user from chat, who would have thought eh? -func (b *Bot) Unban(chat *Chat, user *User, isBanned ...bool) error { +// forBanned does nothing if the user is not banned. +func (b *Bot) Unban(chat *Chat, user *User, forBanned ...bool) error { params := map[string]string{ "chat_id": chat.Recipient(), "user_id": user.Recipient(), } - if len(isBanned) > 0 { - params["only_if_banned"] = strconv.FormatBool(isBanned[0]) + if len(forBanned) > 0 { + params["only_if_banned"] = strconv.FormatBool(forBanned[0]) } _, err := b.Raw("unbanChatMember", params) @@ -201,7 +202,7 @@ func (b *Bot) Promote(chat *Chat, member *ChatMember) error { params := map[string]interface{}{ "chat_id": chat.Recipient(), "user_id": member.User.Recipient(), - "is_anonymous": member.IsAnonymous, + "is_anonymous": member.Anonymous, } embedRights(params, prv) diff --git a/bot.go b/bot.go index 37da15e..4c578a5 100644 --- a/bot.go +++ b/bot.go @@ -350,10 +350,10 @@ func (b *Bot) ProcessUpdate(upd Update) { } if m.ProximityAlertTriggered != nil { - if handler, ok := b.handlers[OnProximityAlertTriggered]; ok { + if handler, ok := b.handlers[OnProximityAlert]; ok { handler, ok := handler.(func(*Message)) if !ok { - panic("telebot: proximity alert triggered handler is bad") + panic("telebot: proximity alert handler is bad") } b.runHandler(func() { handler(m) }) @@ -786,8 +786,8 @@ func (b *Bot) Edit(msg Editable, what interface{}, options ...interface{}) (*Mes method = "editMessageLiveLocation" params["latitude"] = fmt.Sprintf("%f", v.Lat) params["longitude"] = fmt.Sprintf("%f", v.Lng) - if v.HA != nil { - params["horizontal_accuracy"] = fmt.Sprintf("%f", *v.HA) + if v.HorizontalAccuracy != nil { + params["horizontal_accuracy"] = fmt.Sprintf("%f", *v.HorizontalAccuracy) } if v.Heading != 0 { params["heading"] = strconv.Itoa(v.Heading) @@ -1430,10 +1430,9 @@ func (b *Bot) Unpin(chat *Chat, messageID ...int) error { return err } -// Unpin unpins all messages in a supergroup or a channel. +// UnpinAll unpins all messages in a supergroup or a channel. // // It supports tb.Silent option. -// MessageID is a specific pinned message func (b *Bot) UnpinAll(chat *Chat) error { params := map[string]string{ "chat_id": chat.Recipient(), diff --git a/chat.go b/chat.go index 7815bab..b2c3bfb 100644 --- a/chat.go +++ b/chat.go @@ -42,20 +42,22 @@ type Chat struct { Still bool `json:"is_member,omitempty"` // Returns only in getChat - Bio string `json:"bio,omitempty"` - Photo *ChatPhoto `json:"photo,omitempty"` - Description string `json:"description,omitempty"` - InviteLink string `json:"invite_link,omitempty"` - PinnedMessage *Message `json:"pinned_message,omitempty"` - Permissions *Rights `json:"permissions,omitempty"` - SlowMode int `json:"slow_mode_delay,omitempty"` - StickerSet string `json:"sticker_set_name,omitempty"` - CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` - LinkedChatID int64 `json:"linked_chat_id,omitempty"` - ChatLocation *struct { - Location Location `json:"location,omitempty"` - Address string `json:"address,omitempty"` - } `json:"location,omitempty"` + Bio string `json:"bio,omitempty"` + Photo *ChatPhoto `json:"photo,omitempty"` + Description string `json:"description,omitempty"` + InviteLink string `json:"invite_link,omitempty"` + PinnedMessage *Message `json:"pinned_message,omitempty"` + Permissions *Rights `json:"permissions,omitempty"` + SlowMode int `json:"slow_mode_delay,omitempty"` + StickerSet string `json:"sticker_set_name,omitempty"` + CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` + LinkedChatID int64 `json:"linked_chat_id,omitempty"` + ChatLocation *ChatLocation `json:"location,omitempty"` +} + +type ChatLocation struct { + Location Location `json:"location,omitempty"` + Address string `json:"address,omitempty"` } // ChatPhoto object represents a chat photo. @@ -78,10 +80,10 @@ func (c *Chat) Recipient() string { type ChatMember struct { Rights - User *User `json:"user"` - Role MemberStatus `json:"status"` - Title string `json:"custom_title"` - IsAnonymous bool `json:"is_anonymous"` + User *User `json:"user"` + Role MemberStatus `json:"status"` + Title string `json:"custom_title"` + Anonymous bool `json:"is_anonymous"` // Date when restrictions will be lifted for the user, unix time. // diff --git a/media.go b/media.go index e5e1acf..bcce24b 100644 --- a/media.go +++ b/media.go @@ -196,7 +196,7 @@ type Location struct { Lng float32 `json:"longitude"` // Horizontal Accuracy - HA *float32 `json:"horizontal_accuracy,omitempty"` + HorizontalAccuracy *float32 `json:"horizontal_accuracy,omitempty"` Heading int `json:"heading,omitempty"` @@ -207,7 +207,7 @@ type Location struct { ProximityAlertRadius int `json:"proximity_alert_radius,omitempty"` } -// ProximityAlertTriggered object represents sent whenever +// ProximityAlertTriggered sent whenever // a user in the chat triggers a proximity alert set by another user. type ProximityAlertTriggered struct { Traveler *User `json:"traveler,omitempty"` diff --git a/sendable.go b/sendable.go index 56d5e53..ba80763 100644 --- a/sendable.go +++ b/sendable.go @@ -265,8 +265,8 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error "longitude": fmt.Sprintf("%f", x.Lng), "live_period": strconv.Itoa(x.LivePeriod), } - if x.HA != nil { - params["horizontal_accuracy"] = fmt.Sprintf("%f", *x.HA) + if x.HorizontalAccuracy != nil { + params["horizontal_accuracy"] = fmt.Sprintf("%f", *x.HorizontalAccuracy) } if x.Heading != 0 { params["heading"] = strconv.Itoa(x.Heading) diff --git a/telebot.go b/telebot.go index e2f3b4d..7a09d45 100644 --- a/telebot.go +++ b/telebot.go @@ -145,10 +145,10 @@ const ( // Handler: func(*Message) OnVoiceChatPartecipantsInvited = "\avoice_chat_partecipants_invited" - // Will fire on ProximityAlertTriggered + // Will fire on ProximityAlert // // Handler: func(*Message) - OnProximityAlertTriggered = "\aproximity_alert_triggered" + OnProximityAlert = "\aproximity_alert" ) // ChatAction is a client-side status indicating bot activity. diff --git a/webhook.go b/webhook.go index 22970c1..17e283a 100644 --- a/webhook.go +++ b/webhook.go @@ -49,8 +49,8 @@ type Webhook struct { ErrorUnixtime int64 `json:"last_error_date"` ErrorMessage string `json:"last_error_message"` - IpAddress string `json:"ip_address"` - DropPendingUpdates bool `json:"drop_pending_updates"` + Ip string `json:"ip_address"` + DropUpdates bool `json:"drop_pending_updates"` TLS *WebhookTLS Endpoint *WebhookEndpoint @@ -91,11 +91,11 @@ func (h *Webhook) getParams() map[string]string { data, _ := json.Marshal(h.AllowedUpdates) params["allowed_updates"] = string(data) } - if h.IpAddress != "" { - params["ip_address"] = h.IpAddress + if h.Ip != "" { + params["ip_address"] = h.Ip } - if h.DropPendingUpdates { - params["drop_pending_updates"] = strconv.FormatBool(h.DropPendingUpdates) + if h.DropUpdates { + params["drop_pending_updates"] = strconv.FormatBool(h.DropUpdates) } if h.TLS != nil { From 7f6dcd3f8be12fd2180542ed93cfc4b401fd69e2 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 19:51:39 +0300 Subject: [PATCH 16/31] telebot: typo fix --- telebot.go | 2 +- webhook.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telebot.go b/telebot.go index 7a09d45..5276ba7 100644 --- a/telebot.go +++ b/telebot.go @@ -148,7 +148,7 @@ const ( // Will fire on ProximityAlert // // Handler: func(*Message) - OnProximityAlert = "\aproximity_alert" + OnProximityAlert = "\aproximity_alert_triggered" ) // ChatAction is a client-side status indicating bot activity. diff --git a/webhook.go b/webhook.go index 17e283a..c4acfd5 100644 --- a/webhook.go +++ b/webhook.go @@ -49,7 +49,7 @@ type Webhook struct { ErrorUnixtime int64 `json:"last_error_date"` ErrorMessage string `json:"last_error_message"` - Ip string `json:"ip_address"` + IP string `json:"ip_address"` DropUpdates bool `json:"drop_pending_updates"` TLS *WebhookTLS @@ -91,8 +91,8 @@ func (h *Webhook) getParams() map[string]string { data, _ := json.Marshal(h.AllowedUpdates) params["allowed_updates"] = string(data) } - if h.Ip != "" { - params["ip_address"] = h.Ip + if h.IP != "" { + params["ip_address"] = h.IP } if h.DropUpdates { params["drop_pending_updates"] = strconv.FormatBool(h.DropUpdates) From d632ff5c20fba542938e185e8d37ff1ea69dcacf Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 20:46:27 +0300 Subject: [PATCH 17/31] links: add chat invite link support --- admin.go | 8 +++---- bot.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/admin.go b/admin.go index 2a6d5b4..734af06 100644 --- a/admin.go +++ b/admin.go @@ -22,7 +22,7 @@ type ChatInviteLink struct { // (Optional) Point in time when the link will expire, use // ChatInviteLink.ExpireTime() to get time.Time - Unixtime int64 `json:"expire_date,omitempty"` + ExpireDate int64 `json:"expire_date,omitempty"` // (Optional) Maximum number of users that can be members of // the chat simultaneously. @@ -31,7 +31,7 @@ type ChatInviteLink struct { // ExpireTime returns the moment of the link expiration in local time. func (c *ChatInviteLink) ExpireTime() time.Time { - return time.Unix(c.Unixtime, 0) + return time.Unix(c.ExpireDate, 0) } // ChatMemberUpdated object represents changes in the status of a chat member. @@ -53,7 +53,7 @@ type ChatMemberUpdated struct { // (Optional) ChatInviteLink which was used by the user to // join the chat; for joining by invite link events only. - ChatInviteLink *ChatInviteLink `json:"chat_invite_link"` + ChatInviteLink *ChatInviteLink `json:"invite_link"` } // Time returns the moment of the change in local time. @@ -130,7 +130,7 @@ func AdminRights() Rights { } } -// Forever is a Unixtime of "forever" banning. +// Forever is a ExpireDate of "forever" banning. func Forever() int64 { return time.Now().Add(367 * 24 * time.Hour).Unix() } diff --git a/bot.go b/bot.go index 4c578a5..724c483 100644 --- a/bot.go +++ b/bot.go @@ -1598,3 +1598,69 @@ func (b *Bot) Close() (bool, error) { return resp.Result, nil } + +// CreateInviteLink creates an additional invite link for a chat. +func (b *Bot) CreateInviteLink(chat *Chat, link *ChatInviteLink) (*ChatInviteLink, error) { + params := map[string]string{ + "chat_id": chat.Recipient(), + } + if link != nil { + params["expire_date"] = strconv.FormatInt(link.ExpireDate, 10) + params["member_limit"] = strconv.Itoa(link.MemberLimit) + } + + data, err := b.Raw("createChatInviteLink", params) + if err != nil { + return nil, err + } + + var resp ChatInviteLink + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + + return &resp, nil +} + +// EditInviteLink edits a non-primary invite link created by the bot. +func (b *Bot) EditInviteLink(chat *Chat, link *ChatInviteLink) (*ChatInviteLink, error) { + params := map[string]string{ + "chat_id": chat.Recipient(), + } + if link != nil { + params["expire_date"] = strconv.FormatInt(link.ExpireDate, 10) + params["member_limit"] = strconv.Itoa(link.MemberLimit) + } + + data, err := b.Raw("editChatInviteLink", params) + if err != nil { + return nil, err + } + + var resp ChatInviteLink + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + + return &resp, nil +} + +// RevokeInviteLink revokes an invite link created by the bot. +func (b *Bot) RevokeInviteLink(chat *Chat, link string) (*ChatInviteLink, error) { + params := map[string]string{ + "chat_id": chat.Recipient(), + "link": link, + } + + data, err := b.Raw("revokeChatInviteLink", params) + if err != nil { + return nil, err + } + + var resp ChatInviteLink + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + + return &resp, nil +} From 101ce90a5680ac9c6376eba9c0301c13a0ebacad Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 21:17:05 +0300 Subject: [PATCH 18/31] links: field fix --- bot.go | 1 + bot_test.go | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/bot.go b/bot.go index 724c483..5c6f361 100644 --- a/bot.go +++ b/bot.go @@ -1628,6 +1628,7 @@ func (b *Bot) EditInviteLink(chat *Chat, link *ChatInviteLink) (*ChatInviteLink, "chat_id": chat.Recipient(), } if link != nil { + params["invite_link"] = link.InviteLink params["expire_date"] = strconv.FormatInt(link.ExpireDate, 10) params["member_limit"] = strconv.Itoa(link.MemberLimit) } diff --git a/bot_test.go b/bot_test.go index f5f15da..45c1ed9 100644 --- a/bot_test.go +++ b/bot_test.go @@ -318,6 +318,19 @@ func TestBot(t *testing.T) { } var msg *Message + t.Run("Link", func(t *testing.T) { + b.Send(to, "test") + + l, err := b.CreateInviteLink(to, &ChatInviteLink{ + InviteLink: "test1", + MemberLimit: 0, + }) + assert.Nil(t, err) + t.Log(l) + }) + + return + t.Run("Send(what=Sendable)", func(t *testing.T) { msg, err = b.Send(to, photo) require.NoError(t, err) From 306f4545afc00e3e7c7b7a3de77f1128e4c42e21 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 21:40:40 +0300 Subject: [PATCH 19/31] message: add auto delete timer changed handler --- bot.go | 13 +++++++++++++ message.go | 8 ++++++++ telebot.go | 5 +++++ 3 files changed, 26 insertions(+) diff --git a/bot.go b/bot.go index 5c6f361..488685e 100644 --- a/bot.go +++ b/bot.go @@ -361,6 +361,19 @@ func (b *Bot) ProcessUpdate(upd Update) { return } + + if m.AutoDeleteTimerChanged != nil { + if handler, ok := b.handlers[OnAutoDeleteTimer]; ok { + handler, ok := handler.(func(*Message)) + if !ok { + panic("telebot: auto delete timer handler is bad") + } + + b.runHandler(func() { handler(m) }) + } + + return + } } if upd.EditedMessage != nil { diff --git a/message.go b/message.go index 3d4dc6d..fe6bd76 100644 --- a/message.go +++ b/message.go @@ -233,6 +233,14 @@ type Message struct { // For a service message, represents the content of a service message, // sent whenever a user in the chat triggers a proximity alert set by another user. ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered,omitempty"` + + // For a service message, represents about a change in auto-delete timer settings. + AutoDeleteTimerChanged *MessageAutoDeleteTimerChanged `json:"message_auto_delete_timer_changed,omitempty"` +} + +// MessageAutoDeleteTimerChanged represents a service message about a change in auto-delete timer settings. +type MessageAutoDeleteTimerChanged struct { + DeleteTime int `json:"message_auto_delete_time"` } // MessageEntity object represents "special" parts of text messages, diff --git a/telebot.go b/telebot.go index 5276ba7..b45a416 100644 --- a/telebot.go +++ b/telebot.go @@ -149,6 +149,11 @@ const ( // // Handler: func(*Message) OnProximityAlert = "\aproximity_alert_triggered" + + // Will fire on AudoDeleteTimer + // + // Handler: func(*Message) + OnAutoDeleteTimer = "\amessage_auto_delete_timer_changed" ) // ChatAction is a client-side status indicating bot activity. From 2322d77bcd04ea2139ae07c9186cf54dbb78668e Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 21:45:37 +0300 Subject: [PATCH 20/31] admin: add can manage chat right --- admin.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/admin.go b/admin.go index 734af06..63a1d0b 100644 --- a/admin.go +++ b/admin.go @@ -78,6 +78,7 @@ type Rights struct { CanSendOther bool `json:"can_send_other_messages"` CanAddPreviews bool `json:"can_add_web_page_previews"` CanManageVoiceChats bool `json:"can_manage_voice_chats"` + CanManageChat bool `json:"can_manage_chat"` } // NoRights is the default Rights{}. @@ -106,6 +107,7 @@ func NoRestrictions() Rights { CanSendOther: true, CanAddPreviews: true, CanManageVoiceChats: false, + CanManageChat: false, } } @@ -127,6 +129,7 @@ func AdminRights() Rights { CanSendOther: true, CanAddPreviews: true, CanManageVoiceChats: true, + CanManageChat: true, } } @@ -138,9 +141,10 @@ func Forever() int64 { // Ban will ban user from chat until `member.RestrictedUntil`. func (b *Bot) Ban(chat *Chat, member *ChatMember) error { params := map[string]string{ - "chat_id": chat.Recipient(), - "user_id": member.User.Recipient(), - "until_date": strconv.FormatInt(member.RestrictedUntil, 10), + "chat_id": chat.Recipient(), + "user_id": member.User.Recipient(), + "until_date": strconv.FormatInt(member.RestrictedUntil, 10), + "revoke_messages": strconv.FormatBool(member.RevokeMessages), } _, err := b.Raw("kickChatMember", params) From 50ae1bb6b2bb4925affbd09dee8450cce3ea814b Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 21:45:57 +0300 Subject: [PATCH 21/31] chat: add revoke message field --- chat.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/chat.go b/chat.go index b2c3bfb..1eb0c87 100644 --- a/chat.go +++ b/chat.go @@ -80,10 +80,11 @@ func (c *Chat) Recipient() string { type ChatMember struct { Rights - User *User `json:"user"` - Role MemberStatus `json:"status"` - Title string `json:"custom_title"` - Anonymous bool `json:"is_anonymous"` + User *User `json:"user"` + Role MemberStatus `json:"status"` + Title string `json:"custom_title"` + Anonymous bool `json:"is_anonymous"` + RevokeMessages bool `json:"revoke_messages"` // Date when restrictions will be lifted for the user, unix time. // From b98cfa23a6cd435127a46b84ede60b6e40147850 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 22:07:26 +0300 Subject: [PATCH 22/31] telebot: some fixes --- admin.go | 16 ++++++++-------- bot.go | 8 ++++---- bot_test.go | 13 ------------- message.go | 4 ++-- util_test.go | 1 + 5 files changed, 15 insertions(+), 27 deletions(-) diff --git a/admin.go b/admin.go index 63a1d0b..efd674d 100644 --- a/admin.go +++ b/admin.go @@ -21,17 +21,17 @@ type ChatInviteLink struct { IsRevoked bool `json:"is_revoked"` // (Optional) Point in time when the link will expire, use - // ChatInviteLink.ExpireTime() to get time.Time - ExpireDate int64 `json:"expire_date,omitempty"` + // ChatInviteLink.ExpireDate() to get time.Time + ExpireUnixtime int64 `json:"expire_date,omitempty"` // (Optional) Maximum number of users that can be members of // the chat simultaneously. MemberLimit int `json:"member_limit,omitempty"` } -// ExpireTime returns the moment of the link expiration in local time. -func (c *ChatInviteLink) ExpireTime() time.Time { - return time.Unix(c.ExpireDate, 0) +// ExpireDate returns the moment of the link expiration in local time. +func (c *ChatInviteLink) ExpireDate() time.Time { + return time.Unix(c.ExpireUnixtime, 0) } // ChatMemberUpdated object represents changes in the status of a chat member. @@ -51,9 +51,9 @@ type ChatMemberUpdated struct { // New information about the chat member. NewChatMember *ChatMember `json:"new_chat_member"` - // (Optional) ChatInviteLink which was used by the user to + // (Optional) InviteLink which was used by the user to // join the chat; for joining by invite link events only. - ChatInviteLink *ChatInviteLink `json:"invite_link"` + InviteLink *ChatInviteLink `json:"invite_link"` } // Time returns the moment of the change in local time. @@ -133,7 +133,7 @@ func AdminRights() Rights { } } -// Forever is a ExpireDate of "forever" banning. +// Forever is a ExpireUnixtime of "forever" banning. func Forever() int64 { return time.Now().Add(367 * 24 * time.Hour).Unix() } diff --git a/bot.go b/bot.go index 488685e..6dcf339 100644 --- a/bot.go +++ b/bot.go @@ -349,7 +349,7 @@ func (b *Bot) ProcessUpdate(upd Update) { return } - if m.ProximityAlertTriggered != nil { + if m.ProximityAlert != nil { if handler, ok := b.handlers[OnProximityAlert]; ok { handler, ok := handler.(func(*Message)) if !ok { @@ -362,7 +362,7 @@ func (b *Bot) ProcessUpdate(upd Update) { return } - if m.AutoDeleteTimerChanged != nil { + if m.AutoDeleteTimer != nil { if handler, ok := b.handlers[OnAutoDeleteTimer]; ok { handler, ok := handler.(func(*Message)) if !ok { @@ -1618,7 +1618,7 @@ func (b *Bot) CreateInviteLink(chat *Chat, link *ChatInviteLink) (*ChatInviteLin "chat_id": chat.Recipient(), } if link != nil { - params["expire_date"] = strconv.FormatInt(link.ExpireDate, 10) + params["expire_date"] = strconv.FormatInt(link.ExpireUnixtime, 10) params["member_limit"] = strconv.Itoa(link.MemberLimit) } @@ -1642,7 +1642,7 @@ func (b *Bot) EditInviteLink(chat *Chat, link *ChatInviteLink) (*ChatInviteLink, } if link != nil { params["invite_link"] = link.InviteLink - params["expire_date"] = strconv.FormatInt(link.ExpireDate, 10) + params["expire_date"] = strconv.FormatInt(link.ExpireUnixtime, 10) params["member_limit"] = strconv.Itoa(link.MemberLimit) } diff --git a/bot_test.go b/bot_test.go index 45c1ed9..f5f15da 100644 --- a/bot_test.go +++ b/bot_test.go @@ -318,19 +318,6 @@ func TestBot(t *testing.T) { } var msg *Message - t.Run("Link", func(t *testing.T) { - b.Send(to, "test") - - l, err := b.CreateInviteLink(to, &ChatInviteLink{ - InviteLink: "test1", - MemberLimit: 0, - }) - assert.Nil(t, err) - t.Log(l) - }) - - return - t.Run("Send(what=Sendable)", func(t *testing.T) { msg, err = b.Send(to, photo) require.NoError(t, err) diff --git a/message.go b/message.go index fe6bd76..ff07464 100644 --- a/message.go +++ b/message.go @@ -232,10 +232,10 @@ type Message struct { // For a service message, represents the content of a service message, // sent whenever a user in the chat triggers a proximity alert set by another user. - ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered,omitempty"` + ProximityAlert *ProximityAlertTriggered `json:"proximity_alert_triggered,omitempty"` // For a service message, represents about a change in auto-delete timer settings. - AutoDeleteTimerChanged *MessageAutoDeleteTimerChanged `json:"message_auto_delete_timer_changed,omitempty"` + AutoDeleteTimer *MessageAutoDeleteTimerChanged `json:"message_auto_delete_timer_changed,omitempty"` } // MessageAutoDeleteTimerChanged represents a service message about a change in auto-delete timer settings. diff --git a/util_test.go b/util_test.go index b06e88f..b62d429 100644 --- a/util_test.go +++ b/util_test.go @@ -60,6 +60,7 @@ func TestEmbedRights(t *testing.T) { "can_pin_messages": false, "can_promote_members": false, "can_manage_voice_chats": false, + "can_manage_chat": false, } assert.Equal(t, expected, params) } From 123e689049a08337062aff44b401edc20d67eac3 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 22:11:01 +0300 Subject: [PATCH 23/31] admin: move revoke message field in separate argument --- admin.go | 12 +++++++----- chat.go | 9 ++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/admin.go b/admin.go index efd674d..84ed1a0 100644 --- a/admin.go +++ b/admin.go @@ -139,12 +139,14 @@ func Forever() int64 { } // Ban will ban user from chat until `member.RestrictedUntil`. -func (b *Bot) Ban(chat *Chat, member *ChatMember) error { +func (b *Bot) Ban(chat *Chat, member *ChatMember, revokeMessages ...bool) error { params := map[string]string{ - "chat_id": chat.Recipient(), - "user_id": member.User.Recipient(), - "until_date": strconv.FormatInt(member.RestrictedUntil, 10), - "revoke_messages": strconv.FormatBool(member.RevokeMessages), + "chat_id": chat.Recipient(), + "user_id": member.User.Recipient(), + "until_date": strconv.FormatInt(member.RestrictedUntil, 10), + } + if len(revokeMessages) > 0 { + params["revoke_messages"] = strconv.FormatBool(revokeMessages[0]) } _, err := b.Raw("kickChatMember", params) diff --git a/chat.go b/chat.go index 1eb0c87..b2c3bfb 100644 --- a/chat.go +++ b/chat.go @@ -80,11 +80,10 @@ func (c *Chat) Recipient() string { type ChatMember struct { Rights - User *User `json:"user"` - Role MemberStatus `json:"status"` - Title string `json:"custom_title"` - Anonymous bool `json:"is_anonymous"` - RevokeMessages bool `json:"revoke_messages"` + User *User `json:"user"` + Role MemberStatus `json:"status"` + Title string `json:"custom_title"` + Anonymous bool `json:"is_anonymous"` // Date when restrictions will be lifted for the user, unix time. // From 0f7e5b74dd6e343ff6022fe3c081b0e110696a4e Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 23:38:47 +0300 Subject: [PATCH 24/31] chat: add voice schedule support --- bot.go | 13 +++++++++++++ message.go | 2 ++ sendable.go | 4 ++++ telebot.go | 5 +++++ util.go | 8 ++++++++ voicechat.go | 12 ++++++++++++ 6 files changed, 44 insertions(+) diff --git a/bot.go b/bot.go index 6dcf339..f25a46a 100644 --- a/bot.go +++ b/bot.go @@ -374,6 +374,19 @@ func (b *Bot) ProcessUpdate(upd Update) { return } + + if m.VoiceChatSchedule != nil { + if handler, ok := b.handlers[OnVoiceChatScheduled]; ok { + handler, ok := handler.(func(*Message)) + if !ok { + panic("telebot: voice chat scheduled is bad") + } + + b.runHandler(func() { handler(m) }) + } + + return + } } if upd.EditedMessage != nil { diff --git a/message.go b/message.go index ff07464..ec82969 100644 --- a/message.go +++ b/message.go @@ -221,6 +221,8 @@ type Message struct { // Inline keyboard attached to the message. ReplyMarkup InlineKeyboardMarkup `json:"reply_markup"` + VoiceChatSchedule *VoiceChatSchedule `json:"voice_chat_scheduled,omitempty"` + // For a service message, a voice chat started in the chat. VoiceChatStarted *VoiceChatStarted `json:"voice_chat_started,omitempty"` diff --git a/sendable.go b/sendable.go index ba80763..c843896 100644 --- a/sendable.go +++ b/sendable.go @@ -317,6 +317,7 @@ func (i *Invoice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) "payload": i.Payload, "provider_token": i.Token, "currency": i.Currency, + "max_tip_amount": strconv.Itoa(i.MaxTipAmount), "need_name": strconv.FormatBool(i.NeedName), "need_phone_number": strconv.FormatBool(i.NeedPhoneNumber), "need_email": strconv.FormatBool(i.NeedEmail), @@ -343,6 +344,9 @@ func (i *Invoice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) data, _ := json.Marshal(i.Prices) params["prices"] = string(data) } + if len(i.SuggestedTipAmounts) > 0 { + params["suggested_tip_amounts"] = sliceIntToString(i.SuggestedTipAmounts) + } b.embedSendOptions(params, opt) data, err := b.Raw("sendInvoice", params) diff --git a/telebot.go b/telebot.go index b45a416..74cddc7 100644 --- a/telebot.go +++ b/telebot.go @@ -154,6 +154,11 @@ const ( // // Handler: func(*Message) OnAutoDeleteTimer = "\amessage_auto_delete_timer_changed" + + // Will fire on OnVoiceChatScheduled + // + // Handler: func(*Message) + OnVoiceChatScheduled = "\avoice_chat_scheduled" ) // ChatAction is a client-side status indicating bot activity. diff --git a/util.go b/util.go index 5856d15..4c95b24 100644 --- a/util.go +++ b/util.go @@ -251,3 +251,11 @@ func isUserInList(user *User, list []User) bool { } return false } + +func sliceIntToString(ns []int) (s string) { + for _, n := range ns { + s += strconv.Itoa(n) + "," + } + s = s[:len(s)-1] + return +} diff --git a/voicechat.go b/voicechat.go index f2ff990..7ac01d6 100644 --- a/voicechat.go +++ b/voicechat.go @@ -1,5 +1,7 @@ package telebot +import "time" + // VoiceChatStarted represents a service message about a voice chat // started in the chat. type VoiceChatStarted struct{} @@ -15,3 +17,13 @@ type VoiceChatEnded struct { type VoiceChatPartecipantsInvited struct { Users []User `json:"users"` } + +// VoiceChatSchedule represents a service message about a voice chat scheduled in the chat. +type VoiceChatSchedule struct { + StartUnixTime int64 `json:"start_date"` +} + +// ExpireDate returns the point when the voice chat is supposed to be started by a chat administrator. +func (v *VoiceChatSchedule) ExpireDate() time.Time { + return time.Unix(v.StartUnixTime, 0) +} From 98e591688badf7a0395b00f70e557356ad42370e Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 23:39:11 +0300 Subject: [PATCH 25/31] payments: update --- inline.go | 3 +++ payments.go | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/inline.go b/inline.go index 5023b0c..fee643a 100644 --- a/inline.go +++ b/inline.go @@ -33,6 +33,9 @@ type Query struct { // Offset of the results to be returned, can be controlled by the bot. Offset string `json:"offset"` + + // ChatType of the type of the chat, from which the inline query was sent. + ChatType string `json:"chat_type"` } // QueryResponse builds a response to an inline Query. diff --git a/payments.go b/payments.go index bd6330f..0fa7e7f 100644 --- a/payments.go +++ b/payments.go @@ -74,13 +74,16 @@ type Invoice struct { PhotoSize int `json:"photo_size"` // Unique deep-linking parameter that can be used to - // generate this invoice when used as a start parameter. + // generate this invoice when used as a start parameter (0). Start string `json:"start_parameter"` // Shows the total price in the smallest units of the currency. // For example, for a price of US$ 1.45 pass amount = 145. Total int `json:"total_amount"` + MaxTipAmount int `json:"max_tip_amount"` + SuggestedTipAmounts []int `json:"suggested_tip_amounts"` + NeedName bool `json:"need_name"` NeedPhoneNumber bool `json:"need_phone_number"` NeedEmail bool `json:"need_email"` From c4aba0399242a10e3f6c071b752e07bb18b0ae14 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 23:43:51 +0300 Subject: [PATCH 26/31] telebot: some fixes --- bot.go | 4 ++-- message.go | 2 +- telebot.go | 4 ++-- voicechat.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bot.go b/bot.go index f25a46a..27a97bb 100644 --- a/bot.go +++ b/bot.go @@ -336,11 +336,11 @@ func (b *Bot) ProcessUpdate(upd Update) { return } - if m.VoiceChatPartecipantsInvited != nil { + if m.VoiceChatParticipantsInvited != nil { if handler, ok := b.handlers[OnVoiceChatPartecipantsInvited]; ok { handler, ok := handler.(func(*Message)) if !ok { - panic("telebot: voice chat partecipants invited handler is bad") + panic("telebot: voice chat participants invited handler is bad") } b.runHandler(func() { handler(m) }) diff --git a/message.go b/message.go index ec82969..2ab2ee6 100644 --- a/message.go +++ b/message.go @@ -230,7 +230,7 @@ type Message struct { VoiceChatEnded *VoiceChatEnded `json:"voice_chat_ended,omitempty"` // For a service message, some users were invited in the voice chat. - VoiceChatPartecipantsInvited *VoiceChatPartecipantsInvited `json:"voice_chat_partecipants_invited,omitempty"` + VoiceChatParticipantsInvited *VoiceChatParticipantsInvited `json:"voice_chat_participants_invited,omitempty"` // For a service message, represents the content of a service message, // sent whenever a user in the chat triggers a proximity alert set by another user. diff --git a/telebot.go b/telebot.go index 74cddc7..41a0643 100644 --- a/telebot.go +++ b/telebot.go @@ -140,10 +140,10 @@ const ( // Handler: func(*Message) OnVoiceChatEnded = "\avoice_chat_ended" - // Will fire on VoiceChatPartecipantsInvited + // Will fire on VoiceChatParticipantsInvited // // Handler: func(*Message) - OnVoiceChatPartecipantsInvited = "\avoice_chat_partecipants_invited" + OnVoiceChatParticipantsInvited = "\avoice_chat_participants_invited" // Will fire on ProximityAlert // diff --git a/voicechat.go b/voicechat.go index 7ac01d6..549b37d 100644 --- a/voicechat.go +++ b/voicechat.go @@ -12,9 +12,9 @@ type VoiceChatEnded struct { Duration int `json:"duration"` } -// VoiceChatPartecipantsInvited represents a service message about new +// VoiceChatParticipantsInvited represents a service message about new // members invited to a voice chat -type VoiceChatPartecipantsInvited struct { +type VoiceChatParticipantsInvited struct { Users []User `json:"users"` } From 6684383594d413503e41c438a32ab1a10d694408 Mon Sep 17 00:00:00 2001 From: Nikita Date: Sun, 23 May 2021 23:48:13 +0300 Subject: [PATCH 27/31] telebot: typo fix --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index 27a97bb..1f244c6 100644 --- a/bot.go +++ b/bot.go @@ -337,7 +337,7 @@ func (b *Bot) ProcessUpdate(upd Update) { } if m.VoiceChatParticipantsInvited != nil { - if handler, ok := b.handlers[OnVoiceChatPartecipantsInvited]; ok { + if handler, ok := b.handlers[OnVoiceChatParticipantsInvited]; ok { handler, ok := handler.(func(*Message)) if !ok { panic("telebot: voice chat participants invited handler is bad") From 6145c866cafe01bd122ee5572208b60f1657c155 Mon Sep 17 00:00:00 2001 From: comerc Date: Mon, 24 May 2021 09:42:04 +0300 Subject: [PATCH 28/31] Revert "Add CreateChatInviteLink()" This reverts commit 5d1d57964275ea658d12f4afe04f4c2b9b98cd96. --- bot.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/bot.go b/bot.go index 4c0b179..8152d98 100644 --- a/bot.go +++ b/bot.go @@ -1295,33 +1295,6 @@ func (b *Bot) StopPoll(msg Editable, options ...interface{}) (*Poll, error) { return resp.Result, nil } -// CreateChatInviteLink should be used to create an additional invite link for a chat. -func (b *Bot) CreateChatInviteLink(chat *Chat, expireDate int64, memberLimit int) (*ChatInviteLink, error) { - params := map[string]string{ - "chat_id": chat.Recipient(), - } - if expireDate > 0 { - params["expire_date"] = fmt.Sprintf("%d", expireDate) - } - if memberLimit > 0 { - params["member_limit"] = fmt.Sprintf("%d", memberLimit) - } - - data, err := b.Raw("createChatInviteLink", params) - if err != nil { - return nil, err - } - - var resp struct { - Result *ChatInviteLink - } - - if err := json.Unmarshal(data, &resp); err != nil { - return nil, wrapError(err) - } - return resp.Result, nil -} - // GetInviteLink should be used to export chat's invite link. func (b *Bot) GetInviteLink(chat *Chat) (string, error) { params := map[string]string{ From 2d4921e1ea89d159e07fe3786fd056f65292c819 Mon Sep 17 00:00:00 2001 From: Nikita Date: Mon, 24 May 2021 13:04:06 +0300 Subject: [PATCH 29/31] telebot: some fixes --- message.go | 2 +- sendable.go | 3 ++- util.go | 5 ++--- voicechat.go => voice.go | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) rename voicechat.go => voice.go (69%) diff --git a/message.go b/message.go index 2ab2ee6..b14efbc 100644 --- a/message.go +++ b/message.go @@ -221,7 +221,7 @@ type Message struct { // Inline keyboard attached to the message. ReplyMarkup InlineKeyboardMarkup `json:"reply_markup"` - VoiceChatSchedule *VoiceChatSchedule `json:"voice_chat_scheduled,omitempty"` + VoiceChatSchedule *VoiceChatScheduled `json:"voice_chat_scheduled,omitempty"` // For a service message, a voice chat started in the chat. VoiceChatStarted *VoiceChatStarted `json:"voice_chat_started,omitempty"` diff --git a/sendable.go b/sendable.go index c843896..7047494 100644 --- a/sendable.go +++ b/sendable.go @@ -5,6 +5,7 @@ import ( "fmt" "path/filepath" "strconv" + "strings" ) // Recipient is any possible endpoint you can send @@ -345,7 +346,7 @@ func (i *Invoice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) params["prices"] = string(data) } if len(i.SuggestedTipAmounts) > 0 { - params["suggested_tip_amounts"] = sliceIntToString(i.SuggestedTipAmounts) + params["suggested_tip_amounts"] = "[" + strings.Join(intsToStrs(i.SuggestedTipAmounts), ",") + "]" } b.embedSendOptions(params, opt) diff --git a/util.go b/util.go index 4c95b24..f316f12 100644 --- a/util.go +++ b/util.go @@ -252,10 +252,9 @@ func isUserInList(user *User, list []User) bool { return false } -func sliceIntToString(ns []int) (s string) { +func intsToStrs(ns []int) (s []string) { for _, n := range ns { - s += strconv.Itoa(n) + "," + s = append(s, strconv.Itoa(n)) } - s = s[:len(s)-1] return } diff --git a/voicechat.go b/voice.go similarity index 69% rename from voicechat.go rename to voice.go index 549b37d..7e8f967 100644 --- a/voicechat.go +++ b/voice.go @@ -18,12 +18,12 @@ type VoiceChatParticipantsInvited struct { Users []User `json:"users"` } -// VoiceChatSchedule represents a service message about a voice chat scheduled in the chat. -type VoiceChatSchedule struct { - StartUnixTime int64 `json:"start_date"` +// VoiceChatScheduled represents a service message about a voice chat scheduled in the chat. +type VoiceChatScheduled struct { + Unixtime int64 `json:"start_date"` } // ExpireDate returns the point when the voice chat is supposed to be started by a chat administrator. -func (v *VoiceChatSchedule) ExpireDate() time.Time { - return time.Unix(v.StartUnixTime, 0) +func (v *VoiceChatScheduled) ExpireDate() time.Time { + return time.Unix(v.Unixtime, 0) } From 17c3c99c8e5e963b7800150d715bee312a5027f5 Mon Sep 17 00:00:00 2001 From: jasonkhew96 <29531167+JasonKhew96@users.noreply.github.com> Date: Tue, 25 May 2021 13:18:20 +0800 Subject: [PATCH 30/31] Fix chat member handler --- bot.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot.go b/bot.go index 67e423e..d1da881 100644 --- a/bot.go +++ b/bot.go @@ -549,10 +549,10 @@ func (b *Bot) ProcessUpdate(upd Update) { if handler, ok := b.handlers[OnChatMember]; ok { handler, ok := handler.(func(*ChatMemberUpdated)) if !ok { - panic("telebot: my chat member handler is bad") + panic("telebot: chat member handler is bad") } - b.runHandler(func() { handler(upd.MyChatMember) }) + b.runHandler(func() { handler(upd.ChatMember) }) } return From 2b1a95f3ed32a2f8442545dc1a805febad569df4 Mon Sep 17 00:00:00 2001 From: jasonkhew96 <29531167+JasonKhew96@users.noreply.github.com> Date: Sat, 29 May 2021 16:26:06 +0800 Subject: [PATCH 31/31] Fix ChatMemberUpdated --- admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin.go b/admin.go index 84ed1a0..21faed6 100644 --- a/admin.go +++ b/admin.go @@ -40,7 +40,7 @@ type ChatMemberUpdated struct { Chat Chat `json:"chat"` // From which user the action was triggered. - From User `json:"user"` + From User `json:"from"` // Unixtime, use ChatMemberUpdated.Time() to get time.Time Unixtime int64 `json:"date"`