From 10a9f2650f0deb282d5f163612a08ee67e864e23 Mon Sep 17 00:00:00 2001 From: Syfaro Date: Sat, 16 Apr 2022 12:36:59 -0400 Subject: [PATCH] Implement Bot API 6.0 changes. --- bot.go | 34 ++++++++++++--- configs.go | 102 ++++++++++++++++++++++++++++++++++++++++++- types.go | 117 ++++++++++++++++++++++++++++++++++++++++---------- types_test.go | 5 +++ 4 files changed, 228 insertions(+), 30 deletions(-) diff --git a/bot.go b/bot.go index c58afec..3c7f953 100644 --- a/bot.go +++ b/bot.go @@ -681,12 +681,7 @@ func (bot *BotAPI) GetMyCommandsWithConfig(config GetMyCommandsConfig) ([]BotCom // forwardMessage, but the copied message doesn't have a link to the original // message. Returns the MessageID of the sent message on success. func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) { - params, err := config.params() - if err != nil { - return MessageID{}, err - } - - resp, err := bot.MakeRequest(config.method(), params) + resp, err := bot.Request(config) if err != nil { return MessageID{}, err } @@ -697,6 +692,33 @@ func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) { return messageID, err } +// AnswerWebAppQuery sets the result of an interaction with a Web App and send a +// corresponding message on behalf of the user to the chat from which the query originated. +func (bot *BotAPI) AnswerWebAppQuery(config AnswerWebAppQueryConfig) (SentWebAppMessage, error) { + var sentWebAppMessage SentWebAppMessage + + resp, err := bot.Request(config) + if err != nil { + return sentWebAppMessage, err + } + + err = json.Unmarshal(resp.Result, &sentWebAppMessage) + return sentWebAppMessage, err +} + +// GetMyDefaultAdministratorRights gets the current default administrator rights of the bot. +func (bot *BotAPI) GetMyDefaultAdministratorRights(config GetMyDefaultAdministratorRightsConfig) (ChatAdministratorRights, error) { + var rights ChatAdministratorRights + + resp, err := bot.Request(config) + if err != nil { + return rights, err + } + + err = json.Unmarshal(resp.Result, &rights) + return rights, err +} + // EscapeText takes an input text and escape Telegram markup symbols. // In this way we can send a text without being afraid of having to escape the characters manually. // Note that you don't have to include the formatting style in the input text, or it will be escaped too. diff --git a/configs.go b/configs.go index 2023548..fef0328 100644 --- a/configs.go +++ b/configs.go @@ -1242,6 +1242,29 @@ func (config InlineConfig) params() (Params, error) { return params, err } +// AnswerWebAppQueryConfig is used to set the result of an interaction with a +// Web App and send a corresponding message on behalf of the user to the chat +// from which the query originated. +type AnswerWebAppQueryConfig struct { + // WebAppQueryID is the unique identifier for the query to be answered. + WebAppQueryID string `json:"web_app_query_id"` + // Result is an InlineQueryResult object describing the message to be sent. + Result interface{} `json:"result"` +} + +func (config AnswerWebAppQueryConfig) method() string { + return "answerWebAppQuery" +} + +func (config AnswerWebAppQueryConfig) params() (Params, error) { + params := make(Params) + + params["web_app_query_id"] = config.WebAppQueryID + err := params.AddInterface("result", config.Result) + + return params, err +} + // CallbackConfig contains information on making a CallbackQuery response. type CallbackConfig struct { CallbackQueryID string `json:"callback_query_id"` @@ -1355,7 +1378,7 @@ type PromoteChatMemberConfig struct { CanPostMessages bool CanEditMessages bool CanDeleteMessages bool - CanManageVoiceChats bool + CanManageVideoChats bool CanInviteUsers bool CanRestrictMembers bool CanPinMessages bool @@ -1378,7 +1401,7 @@ func (config PromoteChatMemberConfig) params() (Params, error) { params.AddBool("can_post_messages", config.CanPostMessages) params.AddBool("can_edit_messages", config.CanEditMessages) params.AddBool("can_delete_messages", config.CanDeleteMessages) - params.AddBool("can_manage_voice_chats", config.CanManageVoiceChats) + params.AddBool("can_manage_video_chats", config.CanManageVideoChats) params.AddBool("can_invite_users", config.CanInviteUsers) params.AddBool("can_restrict_members", config.CanRestrictMembers) params.AddBool("can_pin_messages", config.CanPinMessages) @@ -2315,6 +2338,81 @@ func (config DeleteMyCommandsConfig) params() (Params, error) { return params, err } +// SetChatMenuButtonConfig changes the bot's menu button in a private chat, +// or the default menu button. +type SetChatMenuButtonConfig struct { + ChatID int64 + ChannelUsername string + + MenuButton *MenuButton +} + +func (config SetChatMenuButtonConfig) method() string { + return "setChatMenuButton" +} + +func (config SetChatMenuButtonConfig) params() (Params, error) { + params := make(Params) + + if err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername); err != nil { + return params, err + } + err := params.AddInterface("menu_button", config.MenuButton) + + return params, err +} + +type GetChatMenuButtonConfig struct { + ChatID int64 + ChannelUsername string +} + +func (config GetChatMenuButtonConfig) method() string { + return "getChatMenuButton" +} + +func (config GetChatMenuButtonConfig) params() (Params, error) { + params := make(Params) + + err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + + return params, err +} + +type SetMyDefaultAdministratorRightsConfig struct { + Rights ChatAdministratorRights + ForChannels bool +} + +func (config SetMyDefaultAdministratorRightsConfig) method() string { + return "setMyDefaultAdministratorRights" +} + +func (config SetMyDefaultAdministratorRightsConfig) params() (Params, error) { + params := make(Params) + + err := params.AddInterface("rights", config.Rights) + params.AddBool("for_channels", config.ForChannels) + + return params, err +} + +type GetMyDefaultAdministratorRightsConfig struct { + ForChannels bool +} + +func (config GetMyDefaultAdministratorRightsConfig) method() string { + return "getMyDefaultAdministratorRights" +} + +func (config GetMyDefaultAdministratorRightsConfig) params() (Params, error) { + params := make(Params) + + params.AddBool("for_channels", config.ForChannels) + + return params, nil +} + // prepareInputMediaParam evaluates a single InputMedia and determines if it // needs to be modified for a successful upload. If it returns nil, then the // value does not need to be included in the params. Otherwise, it will return diff --git a/types.go b/types.go index 5004892..cb77528 100644 --- a/types.go +++ b/types.go @@ -599,23 +599,27 @@ type Message struct { // // optional ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered"` - // VoiceChatScheduled is a service message: voice chat scheduled. + // VideoChatScheduled is a service message: video chat scheduled. // // optional - VoiceChatScheduled *VoiceChatScheduled `json:"voice_chat_scheduled"` - // VoiceChatStarted is a service message: voice chat started. + VideoChatScheduled *VideoChatScheduled `json:"video_chat_scheduled"` + // VideoChatStarted is a service message: video chat started. // // optional - VoiceChatStarted *VoiceChatStarted `json:"voice_chat_started"` - // VoiceChatEnded is a service message: voice chat ended. + VideoChatStarted *VideoChatStarted `json:"video_chat_started"` + // VideoChatEnded is a service message: video chat ended. // // optional - VoiceChatEnded *VoiceChatEnded `json:"voice_chat_ended"` - // VoiceChatParticipantsInvited is a service message: new participants - // invited to a voice chat. + VideoChatEnded *VideoChatEnded `json:"video_chat_ended"` + // VideoChatParticipantsInvited is a service message: new participants + // invited to a video chat. // // optional - VoiceChatParticipantsInvited *VoiceChatParticipantsInvited `json:"voice_chat_participants_invited"` + VideoChatParticipantsInvited *VideoChatParticipantsInvited `json:"video_chat_participants_invited"` + // WebAppData is a service message: data sent by a Web App. + // + // optional + WebAppData *WebAppData `json:"web_app_data"` // ReplyMarkup is the Inline keyboard attached to the message. // login_url buttons are represented as ordinary url buttons. // @@ -1135,6 +1139,15 @@ type Venue struct { GooglePlaceType string `json:"google_place_type,omitempty"` } +// WebAppData Contains data sent from a Web App to the bot. +type WebAppData struct { + // Data is the data. Be aware that a bad client can send arbitrary data in this field. + Data string `json:"data"` + // ButtonText is the text of the web_app keyboard button, from which the Web App + // was opened. Be aware that a bad client can send arbitrary data in this field. + ButtonText string `json:"button_text"` +} + // ProximityAlertTriggered represents a service message sent when a user in the // chat triggers a proximity alert sent by another user. type ProximityAlertTriggered struct { @@ -1153,33 +1166,33 @@ type MessageAutoDeleteTimerChanged struct { MessageAutoDeleteTime int `json:"message_auto_delete_time"` } -// VoiceChatScheduled represents a service message about a voice chat scheduled +// VideoChatScheduled represents a service message about a voice chat scheduled // in the chat. -type VoiceChatScheduled struct { +type VideoChatScheduled struct { // Point in time (Unix timestamp) when the voice chat is supposed to be // started by a chat administrator StartDate int `json:"start_date"` } // Time converts the scheduled start date into a Time. -func (m *VoiceChatScheduled) Time() time.Time { +func (m *VideoChatScheduled) Time() time.Time { return time.Unix(int64(m.StartDate), 0) } -// VoiceChatStarted represents a service message about a voice chat started in +// VideoChatStarted represents a service message about a voice chat started in // the chat. -type VoiceChatStarted struct{} +type VideoChatStarted struct{} -// VoiceChatEnded represents a service message about a voice chat ended in the +// VideoChatEnded represents a service message about a voice chat ended in the // chat. -type VoiceChatEnded struct { +type VideoChatEnded struct { // Voice chat duration; in seconds. Duration int `json:"duration"` } -// VoiceChatParticipantsInvited represents a service message about new members +// VideoChatParticipantsInvited represents a service message about new members // invited to a voice chat. -type VoiceChatParticipantsInvited struct { +type VideoChatParticipantsInvited struct { // New members that were invited to the voice chat. // // optional @@ -1220,6 +1233,13 @@ func (f *File) Link(token string) string { return fmt.Sprintf(FileEndpoint, token, f.FilePath) } +// WebAppInfo contains information about a Web App. +type WebAppInfo struct { + // URL is the HTTPS URL of a Web App to be opened with additional data as + // specified in Initializing Web Apps. + URL string `json:"url"` +} + // ReplyKeyboardMarkup represents a custom keyboard with reply options. type ReplyKeyboardMarkup struct { // Keyboard is an array of button rows, each represented by an Array of KeyboardButton objects @@ -1277,11 +1297,17 @@ type KeyboardButton struct { // // optional RequestLocation bool `json:"request_location,omitempty"` - // RequestPoll if True, the user will be asked to create a poll and send it + // RequestPoll if specified, the user will be asked to create a poll and send it // to the bot when the button is pressed. Available in private chats only // // optional RequestPoll *KeyboardButtonPollType `json:"request_poll,omitempty"` + // WebApp if specified, the described Web App will be launched when the button + // is pressed. The Web App will be able to send a “web_app_data” service + // message. Available in private chats only. + // + // optional + WebApp *WebAppInfo `json:"web_app,omitempty"` } // KeyboardButtonPollType represents type of poll, which is allowed to @@ -1348,6 +1374,12 @@ type InlineKeyboardButton struct { // // optional CallbackData *string `json:"callback_data,omitempty"` + // WebApp is the Description of the Web App that will be launched when the user presses the button. + // The Web App will be able to send an arbitrary message on behalf of the user using the method + // answerWebAppQuery. Available only in private chats between a user and the bot. + // + // optional + WebApp *WebAppInfo `json:"web_app,omitempty"` // SwitchInlineQuery if set, pressing the button will prompt the user to select one of their chats, // open that chat and insert the bot's username and the specified inline query in the input field. // Can be empty, in which case just the bot's username will be inserted. @@ -1532,6 +1564,20 @@ type ChatInviteLink struct { PendingJoinRequestCount int `json:"pending_join_request_count"` } +type ChatAdministratorRights struct { + IsAnonymous bool `json:"is_anonymous"` + CanManageChat bool `json:"can_manage_chat"` + CanDeleteMessages bool `json:"can_delete_messages"` + CanManageVideoChats bool `json:"can_manage_video_chats"` + CanRestrictMembers bool `json:"can_restrict_members"` + CanPromoteMembers bool `json:"can_promote_members"` + CanChangeInfo bool `json:"can_change_info"` + CanInviteUsers bool `json:"can_invite_users"` + CanPostMessages bool `json:"can_post_messages"` + CanEditMessages bool `json:"can_edit_messages"` + CanPinMessages bool `json:"can_pin_messages"` +} + // ChatMember contains information about one member of a chat. type ChatMember struct { // User information about the user @@ -1590,11 +1636,11 @@ type ChatMember struct { // // optional CanDeleteMessages bool `json:"can_delete_messages,omitempty"` - // CanManageVoiceChats administrators only. - // True, if the administrator can manage voice chats. + // CanManageVideoChats administrators only. + // True, if the administrator can manage video chats. // // optional - CanManageVoiceChats bool `json:"can_manage_voice_chats"` + CanManageVideoChats bool `json:"can_manage_video_chats"` // CanRestrictMembers administrators only. // True, if the administrator can restrict, ban or unban chat members. // @@ -1776,6 +1822,20 @@ type BotCommandScope struct { UserID int64 `json:"user_id,omitempty"` } +// MenuButton describes the bot's menu button in a private chat. +type MenuButton struct { + // Type is the type of menu button, must be one of: + // - `commands` + // - `web_app` + // - `default` + Type string `json:"type"` + // Text is the text on the button, for `web_app` type. + Text string `json:"text,omitempty"` + // WebApp is the description of the Web App that will be launched when the + // user presses the button for the `web_app` type. + WebApp *WebAppInfo `json:"web_app,omitempty"` +} + // ResponseParameters are various errors that can be returned in APIResponse. type ResponseParameters struct { // The group has been migrated to a supergroup with the specified identifier. @@ -2044,6 +2104,9 @@ type WebhookInfo struct { // // optional LastErrorMessage string `json:"last_error_message,omitempty"` + // LastSynchronizationErrorDate is the unix time of the most recent error that + // happened when trying to synchronize available updates with Telegram datacenters. + LastSynchronizationErrorDate int `json:"last_synchronization_error_date,omitempty"` // MaxConnections maximum allowed number of simultaneous // HTTPS connections to the webhook for update delivery. // @@ -2897,6 +2960,16 @@ type ChosenInlineResult struct { Query string `json:"query"` } +// SentWebAppMessage contains information about an inline message sent by a Web App +// on behalf of a user. +type SentWebAppMessage struct { + // Identifier of the sent inline message. Available only if there is an inline + // keyboard attached to the message. + // + // optional + InlineMessageID string `json:"inline_message_id"` +} + // InputTextMessageContent contains text for displaying // as an inline query result. type InputTextMessageContent struct { diff --git a/types_test.go b/types_test.go index 9ba9bb5..0c6ba4a 100644 --- a/types_test.go +++ b/types_test.go @@ -280,6 +280,7 @@ func TestFileLink(t *testing.T) { // Ensure all configs are sendable var ( _ Chattable = AnimationConfig{} + _ Chattable = AnswerWebAppQueryConfig{} _ Chattable = AudioConfig{} _ Chattable = BanChatMemberConfig{} _ Chattable = BanChatSenderChatConfig{} @@ -308,7 +309,9 @@ var ( _ Chattable = ForwardConfig{} _ Chattable = GameConfig{} _ Chattable = GetChatMemberConfig{} + _ Chattable = GetChatMenuButtonConfig{} _ Chattable = GetGameHighScoresConfig{} + _ Chattable = GetMyDefaultAdministratorRightsConfig{} _ Chattable = InlineConfig{} _ Chattable = InvoiceConfig{} _ Chattable = KickChatMemberConfig{} @@ -325,9 +328,11 @@ var ( _ Chattable = RevokeChatInviteLinkConfig{} _ Chattable = SendPollConfig{} _ Chattable = SetChatDescriptionConfig{} + _ Chattable = SetChatMenuButtonConfig{} _ Chattable = SetChatPhotoConfig{} _ Chattable = SetChatTitleConfig{} _ Chattable = SetGameScoreConfig{} + _ Chattable = SetMyDefaultAdministratorRightsConfig{} _ Chattable = ShippingConfig{} _ Chattable = StickerConfig{} _ Chattable = StopMessageLiveLocationConfig{}