Start implementing 7.0 Bot API changes
@@ -84,7 +84,7 @@ func TestSendWithMessageReply(t *testing.T) {
bot, _ := getBot(t) msg := NewMessage(ChatID, "A test message from the test library in telegram-bot-api") - msg.ReplyToMessageID = ReplyToMessageID + msg.ReplyParameters.MessageID = ReplyToMessageID _, err := bot.Send(msg) if err != nil {@@ -169,7 +169,7 @@ func TestSendWithNewPhotoReply(t *testing.T) {
bot, _ := getBot(t) msg := NewPhoto(ChatID, FilePath("tests/image.jpg")) - msg.ReplyToMessageID = ReplyToMessageID + msg.ReplyParameters.MessageID = ReplyToMessageID _, err := bot.Send(msg)@@ -699,7 +699,7 @@
log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) msg := NewMessage(update.Message.Chat.ID, update.Message.Text) - msg.ReplyToMessageID = update.Message.MessageID + msg.ReplyParameters.MessageID = update.Message.MessageID bot.Send(msg) }@@ -827,8 +827,12 @@ msg.ParseMode = ModeMarkdown
message, _ := bot.Send(msg) deleteMessageConfig := DeleteMessageConfig{ - ChatID: message.Chat.ID, - MessageID: message.MessageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: message.Chat.ID, + }, + MessageID: message.MessageID, + }, } _, err := bot.Request(deleteMessageConfig)@@ -845,8 +849,12 @@ msg.ParseMode = ModeMarkdown
message, _ := bot.Send(msg) pinChatMessageConfig := PinChatMessageConfig{ - ChatID: message.Chat.ID, - MessageID: message.MessageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: ChatID, + }, + MessageID: message.MessageID, + }, DisableNotification: false, } _, err := bot.Request(pinChatMessageConfig)@@ -865,8 +873,12 @@ message, _ := bot.Send(msg)
// We need pin message to unpin something pinChatMessageConfig := PinChatMessageConfig{ - ChatID: message.Chat.ID, - MessageID: message.MessageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: message.Chat.ID, + }, + MessageID: message.MessageID, + }, DisableNotification: false, }@@ -875,8 +887,12 @@ t.Error(err)
} unpinChatMessageConfig := UnpinChatMessageConfig{ - ChatID: message.Chat.ID, - MessageID: message.MessageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: message.Chat.ID, + }, + MessageID: message.MessageID, + }, } if _, err := bot.Request(unpinChatMessageConfig); err != nil {@@ -892,8 +908,12 @@ msg.ParseMode = ModeMarkdown
message, _ := bot.Send(msg) pinChatMessageConfig := PinChatMessageConfig{ - ChatID: message.Chat.ID, - MessageID: message.MessageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: message.Chat.ID, + }, + MessageID: message.MessageID, + }, DisableNotification: true, }@@ -902,7 +922,7 @@ t.Error(err)
} unpinAllChatMessagesConfig := UnpinAllChatMessagesConfig{ - ChatID: message.Chat.ID, + ChatConfig: ChatConfig{ChatID: message.Chat.ID}, } if _, err := bot.Request(unpinAllChatMessagesConfig); err != nil {
@@ -60,6 +60,12 @@
// UpdateTypeEditedChannelPost is new version of a channel post that is known to the bot and was edited UpdateTypeEditedChannelPost = "edited_channel_post" + // UpdateTypeMessageReactionis is a reaction to a message was changed by a user + UpdateTypeMessageReaction = "message_reaction" + + // UpdateTypeMessageReactionCount are reactions to a message with anonymous reactions were changed + UpdateTypeMessageReactionCount = "message_reaction_count" + // UpdateTypeInlineQuery is new incoming inline query UpdateTypeInlineQuery = "inline_query"@@ -96,6 +102,14 @@
// UpdateTypeChatJoinRequest is request to join the chat has been sent. // The bot must have the can_invite_users administrator right in the chat to receive these updates. UpdateTypeChatJoinRequest = "chat_join_request" + + // UpdateTypeChatBoost is chat boost was added or changed. + // The bot must be an administrator in the chat to receive these updates. + UpdateTypeChatBoost = "chat_boost" + + // UpdateTypeRemovedChatBoost is boost was removed from a chat. + // The bot must be an administrator in the chat to receive these updates. + UpdateTypeRemovedChatBoost = "removed_chat_boost" ) // Library errors@@ -266,89 +280,13 @@ func (CloseConfig) params() (Params, error) {
return nil, nil } -// BaseChat is base type for all chat config types. -type BaseChat struct { - ChatID int64 // required - MessageThreadID int - ChannelUsername string - ProtectContent bool - ReplyToMessageID int - ReplyMarkup interface{} - DisableNotification bool - AllowSendingWithoutReply bool -} - -func (chat *BaseChat) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername) - params.AddNonZero("message_thread_id", chat.MessageThreadID) - params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID) - params.AddBool("disable_notification", chat.DisableNotification) - params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply) - params.AddBool("protect_content", chat.ProtectContent) - - err := params.AddInterface("reply_markup", chat.ReplyMarkup) - - return params, err -} - -// BaseFile is a base type for all file config types. -type BaseFile struct { - BaseChat - File RequestFileData -} - -func (file BaseFile) params() (Params, error) { - return file.BaseChat.params() -} - -// BaseEdit is base type of all chat edits. -type BaseEdit struct { - ChatID int64 - ChannelUsername string - MessageID int - InlineMessageID string - ReplyMarkup *InlineKeyboardMarkup -} - -func (edit BaseEdit) params() (Params, error) { - params := make(Params) - - if edit.InlineMessageID != "" { - params["inline_message_id"] = edit.InlineMessageID - } else { - params.AddFirstValid("chat_id", edit.ChatID, edit.ChannelUsername) - params.AddNonZero("message_id", edit.MessageID) - } - - err := params.AddInterface("reply_markup", edit.ReplyMarkup) - - return params, err -} - -// BaseSpoiler is base type of structures with spoilers. -type BaseSpoiler struct { - HasSpoiler bool -} - -func (spoiler BaseSpoiler) params() (Params, error) { - params := make(Params) - - if spoiler.HasSpoiler { - params.AddBool("has_spoiler", true) - } - - return params, nil -} - // MessageConfig contains information about a SendMessage request. type MessageConfig struct { BaseChat - Text string - ParseMode string - Entities []MessageEntity - DisableWebPagePreview bool + Text string + ParseMode string + Entities []MessageEntity + LinkPreviewOptions LinkPreviewOptions } func (config MessageConfig) params() (Params, error) {@@ -358,9 +296,12 @@ return params, err
} params.AddNonEmpty("text", config.Text) - params.AddBool("disable_web_page_preview", config.DisableWebPagePreview) params.AddNonEmpty("parse_mode", config.ParseMode) err = params.AddInterface("entities", config.Entities) + if err != nil { + return params, err + } + err = params.AddInterface("link_preview_options", config.LinkPreviewOptions) return params, err }@@ -372,9 +313,8 @@
// ForwardConfig contains information about a ForwardMessage request. type ForwardConfig struct { BaseChat - FromChatID int64 // required - FromChannelUsername string - MessageID int // required + FromChat ChatConfig + MessageID int // required } func (config ForwardConfig) params() (Params, error) {@@ -382,8 +322,11 @@ params, err := config.BaseChat.params()
if err != nil { return params, err } - - params.AddNonZero64("from_chat_id", config.FromChatID) + p1, err := config.FromChat.paramsWithKey("from_chat_id") + if err != nil { + return params, err + } + params.Merge(p1) params.AddNonZero("message_id", config.MessageID) return params, nil@@ -393,15 +336,41 @@ func (config ForwardConfig) method() string {
return "forwardMessage" } +// ForwardMessagesConfig contains information about a ForwardMessages request. +type ForwardMessagesConfig struct { + BaseChat + FromChat ChatConfig + MessageIDs []int // required +} + +func (config ForwardMessagesConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + p1, err := config.FromChat.paramsWithKey("from_chat_id") + if err != nil { + return params, err + } + params.Merge(p1) + err = params.AddInterface("message_ids", config.MessageIDs) + + return params, err +} + +func (config ForwardMessagesConfig) method() string { + return "forwardMessages" +} + // CopyMessageConfig contains information about a copyMessage request. type CopyMessageConfig struct { BaseChat - FromChatID int64 - FromChannelUsername string - MessageID int - Caption string - ParseMode string - CaptionEntities []MessageEntity + FromChat ChatConfig + MessageID int + Caption string + ParseMode string + CaptionEntities []MessageEntity } func (config CopyMessageConfig) params() (Params, error) {@@ -410,7 +379,11 @@ if err != nil {
return params, err } - params.AddFirstValid("from_chat_id", config.FromChatID, config.FromChannelUsername) + p1, err := config.FromChat.paramsWithKey("from_chat_id") + if err != nil { + return params, err + } + params.Merge(p1) params.AddNonZero("message_id", config.MessageID) params.AddNonEmpty("caption", config.Caption) params.AddNonEmpty("parse_mode", config.ParseMode)@@ -423,6 +396,35 @@ func (config CopyMessageConfig) method() string {
return "copyMessage" } +// CopyMessagesConfig contains information about a copyMessages request. +type CopyMessagesConfig struct { + BaseChat + FromChat ChatConfig + MessageIDs []int + RemoveCaption bool +} + +func (config CopyMessagesConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + p1, err := config.FromChat.paramsWithKey("from_chat_id") + if err != nil { + return params, err + } + params.Merge(p1) + params.AddBool("remove_caption", config.RemoveCaption) + err = params.AddInterface("message_ids", config.MessageIDs) + + return params, err +} + +func (config CopyMessagesConfig) method() string { + return "copyMessages" +} + // PhotoConfig contains information about a SendPhoto request. type PhotoConfig struct { BaseFile@@ -970,13 +972,12 @@ }
// SetGameScoreConfig allows you to update the game score in a chat. type SetGameScoreConfig struct { + BaseChatMessage + UserID int64 Score int Force bool DisableEditMessage bool - ChatID int64 - ChannelUsername string - MessageID int InlineMessageID string }@@ -990,8 +991,11 @@
if config.InlineMessageID != "" { params["inline_message_id"] = config.InlineMessageID } else { - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - params.AddNonZero("message_id", config.MessageID) + p1, err := config.BaseChatMessage.params() + if err != nil { + return params, err + } + params.Merge(p1) } return params, nil@@ -1003,10 +1007,9 @@ }
// GetGameHighScoresConfig allows you to fetch the high scores for a game. type GetGameHighScoresConfig struct { + BaseChatMessage + UserID int64 - ChatID int64 - ChannelUsername string - MessageID int InlineMessageID string }@@ -1018,8 +1021,11 @@
if config.InlineMessageID != "" { params["inline_message_id"] = config.InlineMessageID } else { - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - params.AddNonZero("message_id", config.MessageID) + p1, err := config.BaseChatMessage.params() + if err != nil { + return params, err + } + params.Merge(p1) } return params, nil@@ -1052,10 +1058,10 @@
// EditMessageTextConfig allows you to modify the text in a message. type EditMessageTextConfig struct { BaseEdit - Text string - ParseMode string - Entities []MessageEntity - DisableWebPagePreview bool + Text string + ParseMode string + Entities []MessageEntity + LinkPreviewOptions LinkPreviewOptions } func (config EditMessageTextConfig) params() (Params, error) {@@ -1066,8 +1072,11 @@ }
params["text"] = config.Text params.AddNonEmpty("parse_mode", config.ParseMode) - params.AddBool("disable_web_page_preview", config.DisableWebPagePreview) err = params.AddInterface("entities", config.Entities) + if err != nil { + return params, err + } + err = params.AddInterface("link_preview_options", config.LinkPreviewOptions) return params, err }@@ -1152,6 +1161,28 @@ }
func (StopPollConfig) method() string { return "stopPoll" +} + +// SetMessageReactionConfig changes reactions on a message. Returns true on success. +type SetMessageReactionConfig struct { + BaseChatMessage + Reaction []ReactionType + IsBig bool +} + +func (config SetMessageReactionConfig) params() (Params, error) { + params, err := config.BaseChatMessage.params() + if err != nil { + return params, err + } + params.AddBool("is_big", config.IsBig) + err = params.AddInterface("reaction", config.Reaction) + + return params, err +} + +func (SetMessageReactionConfig) method() string { + return "setMessageReaction" } // UserProfilePhotosConfig contains information about a@@ -1370,10 +1401,17 @@
// ChatMemberConfig contains information about a user in a chat for use // with administrative functions such as kicking or unbanning a user. type ChatMemberConfig struct { - ChatID int64 - SuperGroupUsername string - ChannelUsername string - UserID int64 + ChatConfig + UserID int64 +} + +func (config ChatMemberConfig) params() (Params, error) { + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } + params.AddNonZero64("user_id", config.UserID) + return params, nil } // UnbanChatMemberConfig allows you to unban a user.@@ -1387,10 +1425,11 @@ return "unbanChatMember"
} func (config UnbanChatMemberConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatMemberConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) - params.AddNonZero64("user_id", config.UserID) params.AddBool("only_if_banned", config.OnlyIfBanned) return params, nil@@ -1408,10 +1447,11 @@ return "banChatMember"
} func (config BanChatMemberConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatMemberConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - params.AddNonZero64("user_id", config.UserID) params.AddNonZero64("until_date", config.UntilDate) params.AddBool("revoke_messages", config.RevokeMessages)@@ -1436,14 +1476,14 @@ return "restrictChatMember"
} func (config RestrictChatMemberConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatMemberConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) - params.AddNonZero64("user_id", config.UserID) params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions) - - err := params.AddInterface("permissions", config.Permissions) params.AddNonZero64("until_date", config.UntilDate) + err = params.AddInterface("permissions", config.Permissions) return params, err }@@ -1473,10 +1513,10 @@ return "promoteChatMember"
} func (config PromoteChatMemberConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) - params.AddNonZero64("user_id", config.UserID) + params, err := config.ChatMemberConfig.params() + if err != nil { + return params, err + } params.AddBool("is_anonymous", config.IsAnonymous) params.AddBool("can_manage_chat", config.CanManageChat)@@ -1509,10 +1549,10 @@ return "setChatAdministratorCustomTitle"
} func (config SetChatAdministratorCustomTitle) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) - params.AddNonZero64("user_id", config.UserID) + params, err := config.ChatMemberConfig.params() + if err != nil { + return params, err + } params.AddNonEmpty("custom_title", config.CustomTitle) return params, nil@@ -1524,10 +1564,9 @@ // behalf of the chat, unless it is unbanned first. The bot must be an
// administrator in the supergroup or channel for this to work and must have the // appropriate administrator rights. type BanChatSenderChatConfig struct { - ChatID int64 - ChannelUsername string - SenderChatID int64 - UntilDate int + ChatConfig + SenderChatID int64 + UntilDate int } func (config BanChatSenderChatConfig) method() string {@@ -1535,9 +1574,10 @@ return "banChatSenderChat"
} func (config BanChatSenderChatConfig) params() (Params, error) { - params := make(Params) - - _ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } params.AddNonZero64("sender_chat_id", config.SenderChatID) params.AddNonZero("until_date", config.UntilDate)@@ -1548,9 +1588,8 @@ // UnbanChatSenderChatConfig unbans a previously banned channel chat in a
// supergroup or channel. The bot must be an administrator for this to work and // must have the appropriate administrator rights. type UnbanChatSenderChatConfig struct { - ChatID int64 - ChannelUsername string - SenderChatID int64 + ChatConfig + SenderChatID int64 } func (config UnbanChatSenderChatConfig) method() string {@@ -1558,28 +1597,15 @@ return "unbanChatSenderChat"
} func (config UnbanChatSenderChatConfig) params() (Params, error) { - params := make(Params) - - _ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } params.AddNonZero64("sender_chat_id", config.SenderChatID) return params, nil } -// ChatConfig contains information about getting information on a chat. -type ChatConfig struct { - ChatID int64 - SuperGroupUsername string -} - -func (config ChatConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - - return params, nil -} - // ChatInfoConfig contains information about getting chat information. type ChatInfoConfig struct { ChatConfig@@ -1621,11 +1647,13 @@ return "setChatPermissions"
} func (config SetChatPermissionsConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions) - err := params.AddInterface("permissions", config.Permissions) + err = params.AddInterface("permissions", config.Permissions) return params, err }@@ -1642,11 +1670,7 @@ return "exportChatInviteLink"
} func (config ChatInviteLinkConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - - return params, nil + return config.ChatConfig.params() } // CreateChatInviteLinkConfig allows you to create an additional invite link for@@ -1666,10 +1690,12 @@ return "createChatInviteLink"
} func (config CreateChatInviteLinkConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } params.AddNonEmpty("name", config.Name) - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) params.AddNonZero("expire_date", config.ExpireDate) params.AddNonZero("member_limit", config.MemberLimit) params.AddBool("creates_join_request", config.CreatesJoinRequest)@@ -1694,9 +1720,11 @@ return "editChatInviteLink"
} func (config EditChatInviteLinkConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) params.AddNonEmpty("name", config.Name) params["invite_link"] = config.InviteLink params.AddNonZero("expire_date", config.ExpireDate)@@ -1720,9 +1748,11 @@ return "revokeChatInviteLink"
} func (config RevokeChatInviteLinkConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) params["invite_link"] = config.InviteLink return params, nil@@ -1739,10 +1769,12 @@ return "approveChatJoinRequest"
} func (config ApproveChatJoinRequestConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - params.AddNonZero("user_id", int(config.UserID)) + params.AddNonZero64("user_id", config.UserID) return params, nil }@@ -1758,18 +1790,18 @@ return "declineChatJoinRequest"
} func (config DeclineChatJoinRequest) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - params.AddNonZero("user_id", int(config.UserID)) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } + params.AddNonZero64("user_id", config.UserID) return params, nil } // LeaveChatConfig allows you to leave a chat. type LeaveChatConfig struct { - ChatID int64 - ChannelUsername string + ChatConfig } func (config LeaveChatConfig) method() string {@@ -1777,24 +1809,21 @@ return "leaveChat"
} func (config LeaveChatConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - - return params, nil + return config.ChatConfig.params() } // ChatConfigWithUser contains information about a chat and a user. type ChatConfigWithUser struct { - ChatID int64 - SuperGroupUsername string - UserID int64 + ChatConfig + UserID int64 } func (config ChatConfigWithUser) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) params.AddNonZero64("user_id", config.UserID) return params, nil@@ -1977,9 +2006,7 @@ }
// DeleteMessageConfig contains information of a message in a chat to delete. type DeleteMessageConfig struct { - ChannelUsername string - ChatID int64 - MessageID int + BaseChatMessage } func (config DeleteMessageConfig) method() string {@@ -1987,19 +2014,25 @@ return "deleteMessage"
} func (config DeleteMessageConfig) params() (Params, error) { - params := make(Params) + return config.BaseChatMessage.params() +} + +// DeleteMessageConfig contains information of a messages in a chat to delete. +type DeleteMessagesConfig struct { + BaseChatMessages +} - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - params.AddNonZero("message_id", config.MessageID) +func (config DeleteMessagesConfig) method() string { + return "deleteMessages" +} - return params, nil +func (config DeleteMessagesConfig) params() (Params, error) { + return config.BaseChatMessages.params() } // PinChatMessageConfig contains information of a message in a chat to pin. type PinChatMessageConfig struct { - ChatID int64 - ChannelUsername string - MessageID int + BaseChatMessage DisableNotification bool }@@ -2008,10 +2041,11 @@ return "pinChatMessage"
} func (config PinChatMessageConfig) params() (Params, error) { - params := make(Params) + params, err := config.BaseChatMessage.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - params.AddNonZero("message_id", config.MessageID) params.AddBool("disable_notification", config.DisableNotification) return params, nil@@ -2021,9 +2055,7 @@ // UnpinChatMessageConfig contains information of a chat message to unpin.
// // If MessageID is not specified, it will unpin the most recent pin. type UnpinChatMessageConfig struct { - ChatID int64 - ChannelUsername string - MessageID int + BaseChatMessage } func (config UnpinChatMessageConfig) method() string {@@ -2031,19 +2063,13 @@ return "unpinChatMessage"
} func (config UnpinChatMessageConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - params.AddNonZero("message_id", config.MessageID) - - return params, nil + return config.BaseChatMessage.params() } // UnpinAllChatMessagesConfig contains information of all messages to unpin in // a chat. type UnpinAllChatMessagesConfig struct { - ChatID int64 - ChannelUsername string + ChatConfig } func (config UnpinAllChatMessagesConfig) method() string {@@ -2051,11 +2077,7 @@ return "unpinAllChatMessages"
} func (config UnpinAllChatMessagesConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - - return params, nil + return config.ChatConfig.params() } // SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.@@ -2076,8 +2098,7 @@ }
// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo. type DeleteChatPhotoConfig struct { - ChatID int64 - ChannelUsername string + ChatConfig } func (config DeleteChatPhotoConfig) method() string {@@ -2085,18 +2106,12 @@ return "deleteChatPhoto"
} func (config DeleteChatPhotoConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - - return params, nil + return config.ChatConfig.params() } // SetChatTitleConfig allows you to set the title of something other than a private chat. type SetChatTitleConfig struct { - ChatID int64 - ChannelUsername string - + ChatConfig Title string }@@ -2105,9 +2120,11 @@ return "setChatTitle"
} func (config SetChatTitleConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) params["title"] = config.Title return params, nil@@ -2115,9 +2132,7 @@ }
// SetChatDescriptionConfig allows you to set the description of a supergroup or channel. type SetChatDescriptionConfig struct { - ChatID int64 - ChannelUsername string - + ChatConfig Description string }@@ -2126,9 +2141,11 @@ return "setChatDescription"
} func (config SetChatDescriptionConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) params["description"] = config.Description return params, nil@@ -2432,8 +2449,7 @@ }
// SetChatStickerSetConfig allows you to set the sticker set for a supergroup. type SetChatStickerSetConfig struct { - ChatID int64 - SuperGroupUsername string + ChatConfig StickerSetName string }@@ -2443,9 +2459,11 @@ return "setChatStickerSet"
} func (config SetChatStickerSetConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) params["sticker_set_name"] = config.StickerSetName return params, nil@@ -2453,8 +2471,7 @@ }
// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set. type DeleteChatStickerSetConfig struct { - ChatID int64 - SuperGroupUsername string + ChatConfig } func (config DeleteChatStickerSetConfig) method() string {@@ -2462,11 +2479,7 @@ return "deleteChatStickerSet"
} func (config DeleteChatStickerSetConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - - return params, nil + return config.ChatConfig.params() } // GetForumTopicIconStickersConfig allows you to get custom emoji stickers,@@ -2481,24 +2494,10 @@ func (config GetForumTopicIconStickersConfig) params() (Params, error) {
return nil, nil } -// BaseForum is a base type for all forum config types. -type BaseForum struct { - ChatID int64 - SuperGroupUsername string -} - -func (config BaseForum) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - - return params, nil -} - // CreateForumTopicConfig allows you to create a topic // in a forum supergroup chat. type CreateForumTopicConfig struct { - BaseForum + ChatConfig Name string IconColor int IconCustomEmojiID string@@ -2509,14 +2508,29 @@ return "createForumTopic"
} func (config CreateForumTopicConfig) params() (Params, error) { - params := make(Params) + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } params.AddNonEmpty("name", config.Name) params.AddNonZero("icon_color", config.IconColor) params.AddNonEmpty("icon_custom_emoji_id", config.IconCustomEmojiID) - p1, _ := config.BaseForum.params() - params.Merge(p1) + return params, nil +} + +type BaseForum struct { + ChatConfig + MessageThreadID int +} + +func (base BaseForum) params() (Params, error) { + params, err := base.ChatConfig.params() + if err != nil { + return params, err + } + params.AddNonZero("message_thread_id", base.MessageThreadID) return params, nil }@@ -2525,7 +2539,6 @@ // EditForumTopicConfig allows you to edit
// name and icon of a topic in a forum supergroup chat. type EditForumTopicConfig struct { BaseForum - MessageThreadID int Name string IconCustomEmojiID string }@@ -2535,108 +2548,48 @@ return "editForumTopic"
} func (config EditForumTopicConfig) params() (Params, error) { - params := make(Params) - - params.AddNonZero("message_thread_id", config.MessageThreadID) + params, err := config.BaseForum.params() + if err != nil { + return params, err + } params.AddNonEmpty("name", config.Name) params.AddNonEmpty("icon_custom_emoji_id", config.IconCustomEmojiID) - p1, _ := config.BaseForum.params() - params.Merge(p1) - return params, nil } // CloseForumTopicConfig allows you to close // an open topic in a forum supergroup chat. -type CloseForumTopicConfig struct { - BaseForum - MessageThreadID int -} +type CloseForumTopicConfig struct{ BaseForum } func (config CloseForumTopicConfig) method() string { return "closeForumTopic" } -func (config CloseForumTopicConfig) params() (Params, error) { - params := make(Params) - - params.AddNonZero("message_thread_id", config.MessageThreadID) - - p1, _ := config.BaseForum.params() - params.Merge(p1) - - return params, nil -} - // ReopenForumTopicConfig allows you to reopen // an closed topic in a forum supergroup chat. -type ReopenForumTopicConfig struct { - BaseForum - MessageThreadID int -} +type ReopenForumTopicConfig struct{ BaseForum } func (config ReopenForumTopicConfig) method() string { return "reopenForumTopic" } -func (config ReopenForumTopicConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - params.AddNonZero("message_thread_id", config.MessageThreadID) - - p1, _ := config.BaseForum.params() - params.Merge(p1) - - return params, nil -} - // DeleteForumTopicConfig allows you to delete a forum topic // along with all its messages in a forum supergroup chat. -type DeleteForumTopicConfig struct { - BaseForum - MessageThreadID int -} +type DeleteForumTopicConfig struct{ BaseForum } func (config DeleteForumTopicConfig) method() string { return "deleteForumTopic" } -func (config DeleteForumTopicConfig) params() (Params, error) { - params := make(Params) - - params.AddNonZero("message_thread_id", config.MessageThreadID) - - p1, _ := config.BaseForum.params() - params.Merge(p1) - - return params, nil -} - // UnpinAllForumTopicMessagesConfig allows you to clear the list // of pinned messages in a forum topic. -type UnpinAllForumTopicMessagesConfig struct { - BaseForum - MessageThreadID int -} +type UnpinAllForumTopicMessagesConfig struct{ BaseForum } func (config UnpinAllForumTopicMessagesConfig) method() string { return "unpinAllForumTopicMessages" } -func (config UnpinAllForumTopicMessagesConfig) params() (Params, error) { - params := make(Params) - - params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) - params.AddNonZero("message_thread_id", config.MessageThreadID) - - p1, _ := config.BaseForum.params() - params.Merge(p1) - - return params, nil -} - // UnpinAllForumTopicMessagesConfig allows you to edit the name of // the 'General' topic in a forum supergroup chat. // The bot must be an administrator in the chat for this to work@@ -2651,12 +2604,11 @@ return "editGeneralForumTopic"
} func (config EditGeneralForumTopicConfig) params() (Params, error) { - params := make(Params) - + params, err := config.BaseForum.params() + if err != nil { + return params, err + } params.AddNonEmpty("name", config.Name) - - p1, _ := config.BaseForum.params() - params.Merge(p1) return params, nil }@@ -2732,10 +2684,6 @@ if err != nil {
return nil, err } - params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - params.AddBool("disable_notification", config.DisableNotification) - params.AddNonZero("reply_to_message_id", config.ReplyToMessageID) - err = params.AddInterface("media", prepareInputMediaForParams(config.Media)) return params, err@@ -2767,6 +2715,26 @@ return params, err
} params.AddNonEmpty("emoji", config.Emoji) + + return params, err +} + +type GetUserChatBoostsConfig struct { + ChatConfig + UserID int64 +} + +func (config GetUserChatBoostsConfig) method() string { + return "getUserChatBoosts" +} + +func (config GetUserChatBoostsConfig) params() (Params, error) { + params, err := config.ChatConfig.params() + if err != nil { + return params, err + } + + params.AddNonZero64("user_id", config.UserID) return params, err }@@ -2949,8 +2917,7 @@
// SetChatMenuButtonConfig changes the bot's menu button in a private chat, // or the default menu button. type SetChatMenuButtonConfig struct { - ChatID int64 - ChannelUsername string + ChatConfig MenuButton *MenuButton }@@ -2960,19 +2927,18 @@ return "setChatMenuButton"
} func (config SetChatMenuButtonConfig) params() (Params, error) { - params := make(Params) - - if err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername); err != nil { + params, err := config.ChatConfig.params() + if err != nil { return params, err } - err := params.AddInterface("menu_button", config.MenuButton) + + err = params.AddInterface("menu_button", config.MenuButton) return params, err } type GetChatMenuButtonConfig struct { - ChatID int64 - ChannelUsername string + ChatConfig } func (config GetChatMenuButtonConfig) method() string {@@ -2980,11 +2946,7 @@ return "getChatMenuButton"
} func (config GetChatMenuButtonConfig) params() (Params, error) { - params := make(Params) - - err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) - - return params, err + return config.ChatConfig.params() } type SetMyDefaultAdministratorRightsConfig struct {
@@ -0,0 +1,127 @@
+package tgbotapi + +// ChatConfig is a base type for all chat identifiers +type ChatConfig struct { + ChatID int64 + ChannelUsername string + SuperGroupUsername string +} + +func (base ChatConfig) params() (Params, error) { + return base.paramsWithKey("chat_id") +} + +func (base ChatConfig) paramsWithKey(key string) (Params, error) { + params := make(Params) + return params, params.AddFirstValid(key, base.ChatID, base.ChannelUsername, base.SuperGroupUsername) +} + +// BaseChat is base type for all chat config types. +type BaseChat struct { + ChatConfig + MessageThreadID int + ProtectContent bool + ReplyMarkup interface{} + DisableNotification bool + ReplyParameters ReplyParameters +} + +func (chat *BaseChat) params() (Params, error) { + params, err := chat.ChatConfig.params() + if err != nil { + return params, err + } + + params.AddNonZero("message_thread_id", chat.MessageThreadID) + params.AddBool("disable_notification", chat.DisableNotification) + params.AddBool("protect_content", chat.ProtectContent) + + err = params.AddInterface("reply_markup", chat.ReplyMarkup) + if err != nil { + return params, err + } + err = params.AddInterface("reply_parameters", chat.ReplyParameters) + return params, err +} + +// BaseFile is a base type for all file config types. +type BaseFile struct { + BaseChat + File RequestFileData +} + +func (file BaseFile) params() (Params, error) { + return file.BaseChat.params() +} + +// BaseEdit is base type of all chat edits. +type BaseEdit struct { + BaseChatMessage + InlineMessageID string + ReplyMarkup *InlineKeyboardMarkup +} + +func (edit BaseEdit) params() (Params, error) { + params := make(Params) + + if edit.InlineMessageID != "" { + params["inline_message_id"] = edit.InlineMessageID + } else { + p1, err := edit.BaseChatMessage.params() + if err != nil { + return params, err + } + params.Merge(p1) + } + + err := params.AddInterface("reply_markup", edit.ReplyMarkup) + + return params, err +} + +// BaseSpoiler is base type of structures with spoilers. +type BaseSpoiler struct { + HasSpoiler bool +} + +func (spoiler BaseSpoiler) params() (Params, error) { + params := make(Params) + + if spoiler.HasSpoiler { + params.AddBool("has_spoiler", true) + } + + return params, nil +} + +// BaseChatMessage is a base type for all messages in chats. +type BaseChatMessage struct { + ChatConfig + MessageID int +} + +func (base BaseChatMessage) params() (Params, error) { + params, err := base.ChatConfig.params() + if err != nil { + return params, err + } + params.AddNonZero("message_id", base.MessageID) + + return params, nil +} + +// BaseChatMessages is a base type for all messages in chats. +type BaseChatMessages struct { + ChatConfig + MessageIDs []int +} + +func (base BaseChatMessages) params() (Params, error) { + params, err := base.ChatConfig.params() + if err != nil { + return params, err + } + err = params.AddInterface("message_ids", base.MessageIDs) + + return params, err +}
@@ -17,19 +17,26 @@ // chatID is where to send it, text is the message text.
func NewMessage(chatID int64, text string) MessageConfig { return MessageConfig{ BaseChat: BaseChat{ - ChatID: chatID, - ReplyToMessageID: 0, + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + }, + Text: text, + LinkPreviewOptions: LinkPreviewOptions{ + IsDisabled: false, }, - Text: text, - DisableWebPagePreview: false, } } // NewDeleteMessage creates a request to delete a message. func NewDeleteMessage(chatID int64, messageID int) DeleteMessageConfig { return DeleteMessageConfig{ - ChatID: chatID, - MessageID: messageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + MessageID: messageID, + }, } }@@ -41,8 +48,9 @@ // and the username should be in the form of `@username`.
func NewMessageToChannel(username string, text string) MessageConfig { return MessageConfig{ BaseChat: BaseChat{ - ChannelUsername: username, - }, + ChatConfig: ChatConfig{ + ChannelUsername: username, + }}, Text: text, } }@@ -53,9 +61,9 @@ // chatID is where to send it, fromChatID is the source chat,
// and messageID is the ID of the original message. func NewForward(chatID int64, fromChatID int64, messageID int) ForwardConfig { return ForwardConfig{ - BaseChat: BaseChat{ChatID: chatID}, - FromChatID: fromChatID, - MessageID: messageID, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, + FromChat: ChatConfig{ChatID: fromChatID}, + MessageID: messageID, } }@@ -65,9 +73,9 @@ // chatID is where to send it, fromChatID is the source chat,
// and messageID is the ID of the original message. func NewCopyMessage(chatID int64, fromChatID int64, messageID int) CopyMessageConfig { return CopyMessageConfig{ - BaseChat: BaseChat{ChatID: chatID}, - FromChatID: fromChatID, - MessageID: messageID, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, + FromChat: ChatConfig{ChatID: fromChatID}, + MessageID: messageID, } }@@ -80,7 +88,7 @@ // Note that you must send animated GIFs as a document.
func NewPhoto(chatID int64, file RequestFileData) PhotoConfig { return PhotoConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -92,10 +100,8 @@ // Note that you must send animated GIFs as a document.
func NewPhotoToChannel(username string, file RequestFileData) PhotoConfig { return PhotoConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ - ChannelUsername: username, - }, - File: file, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChannelUsername: username}}, + File: file, }, } }@@ -104,7 +110,7 @@ // NewAudio creates a new sendAudio request.
func NewAudio(chatID int64, file RequestFileData) AudioConfig { return AudioConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -114,7 +120,7 @@ // NewDocument creates a new sendDocument request.
func NewDocument(chatID int64, file RequestFileData) DocumentConfig { return DocumentConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -124,7 +130,7 @@ // NewSticker creates a new sendSticker request.
func NewSticker(chatID int64, file RequestFileData) StickerConfig { return StickerConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -157,7 +163,7 @@ // NewVideo creates a new sendVideo request.
func NewVideo(chatID int64, file RequestFileData) VideoConfig { return VideoConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -167,7 +173,7 @@ // NewAnimation creates a new sendAnimation request.
func NewAnimation(chatID int64, file RequestFileData) AnimationConfig { return AnimationConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -180,7 +186,7 @@ // FileReader, or FileBytes.
func NewVideoNote(chatID int64, length int, file RequestFileData) VideoNoteConfig { return VideoNoteConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, Length: length,@@ -191,7 +197,7 @@ // NewVoice creates a new sendVoice request.
func NewVoice(chatID int64, file RequestFileData) VoiceConfig { return VoiceConfig{ BaseFile: BaseFile{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, File: file, }, }@@ -202,7 +208,7 @@ // two to ten InputMediaPhoto or InputMediaVideo.
func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig { return MediaGroupConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, Media: files, }@@ -262,7 +268,7 @@ // NewContact allows you to send a shared contact.
func NewContact(chatID int64, phoneNumber, firstName string) ContactConfig { return ContactConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, PhoneNumber: phoneNumber, FirstName: firstName,@@ -275,7 +281,7 @@ // chatID is where to send it, latitude and longitude are coordinates.
func NewLocation(chatID int64, latitude float64, longitude float64) LocationConfig { return LocationConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, Latitude: latitude, Longitude: longitude,@@ -286,7 +292,7 @@ // NewVenue allows you to send a venue and its location.
func NewVenue(chatID int64, title, address string, latitude, longitude float64) VenueConfig { return VenueConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, Title: title, Address: address,@@ -301,7 +307,7 @@ //
// chatID is where to send it, action should be set via Chat constants. func NewChatAction(chatID int64, action string) ChatActionConfig { return ChatActionConfig{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ChatConfig: ChatConfig{ChatID: chatID}}, Action: action, } }@@ -592,8 +598,12 @@ // NewEditMessageText allows you to edit the text of a message.
func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTextConfig { return EditMessageTextConfig{ BaseEdit: BaseEdit{ - ChatID: chatID, - MessageID: messageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + MessageID: messageID, + }, }, Text: text, }@@ -603,8 +613,12 @@ // NewEditMessageTextAndMarkup allows you to edit the text and reply markup of a message.
func NewEditMessageTextAndMarkup(chatID int64, messageID int, text string, replyMarkup InlineKeyboardMarkup) EditMessageTextConfig { return EditMessageTextConfig{ BaseEdit: BaseEdit{ - ChatID: chatID, - MessageID: messageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + MessageID: messageID, + }, ReplyMarkup: &replyMarkup, }, Text: text,@@ -615,8 +629,12 @@ // NewEditMessageCaption allows you to edit the caption of a message.
func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig { return EditMessageCaptionConfig{ BaseEdit: BaseEdit{ - ChatID: chatID, - MessageID: messageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + MessageID: messageID, + }, }, Caption: caption, }@@ -627,8 +645,12 @@ // keyboard markup.
func NewEditMessageReplyMarkup(chatID int64, messageID int, replyMarkup InlineKeyboardMarkup) EditMessageReplyMarkupConfig { return EditMessageReplyMarkupConfig{ BaseEdit: BaseEdit{ - ChatID: chatID, - MessageID: messageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + MessageID: messageID, + }, ReplyMarkup: &replyMarkup, }, }@@ -801,7 +823,9 @@
// NewInvoice creates a new Invoice request to the user. func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices []LabeledPrice) InvoiceConfig { return InvoiceConfig{ - BaseChat: BaseChat{ChatID: chatID}, + BaseChat: BaseChat{ + ChatConfig: ChatConfig{ChatID: chatID}, + }, Title: title, Description: description, Payload: payload,@@ -814,15 +838,19 @@
// NewChatTitle allows you to update the title of a chat. func NewChatTitle(chatID int64, title string) SetChatTitleConfig { return SetChatTitleConfig{ - ChatID: chatID, - Title: title, + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + Title: title, } } // NewChatDescription allows you to update the description of a chat. func NewChatDescription(chatID int64, description string) SetChatDescriptionConfig { return SetChatDescriptionConfig{ - ChatID: chatID, + ChatConfig: ChatConfig{ + ChatID: chatID, + }, Description: description, } }@@ -832,7 +860,7 @@ func NewChatPhoto(chatID int64, photo RequestFileData) SetChatPhotoConfig {
return SetChatPhotoConfig{ BaseFile: BaseFile{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, File: photo, },@@ -842,7 +870,9 @@
// NewDeleteChatPhoto allows you to delete the photo for a chat. func NewDeleteChatPhoto(chatID int64) DeleteChatPhotoConfig { return DeleteChatPhotoConfig{ - ChatID: chatID, + ChatConfig: ChatConfig{ + ChatID: chatID, + }, } }@@ -850,7 +880,7 @@ // NewPoll allows you to create a new poll.
func NewPoll(chatID int64, question string, options ...string) SendPollConfig { return SendPollConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, Question: question, Options: options,@@ -862,8 +892,12 @@ // NewStopPoll allows you to stop a poll.
func NewStopPoll(chatID int64, messageID int) StopPollConfig { return StopPollConfig{ BaseEdit{ - ChatID: chatID, - MessageID: messageID, + BaseChatMessage: BaseChatMessage{ + ChatConfig: ChatConfig{ + ChatID: chatID, + }, + MessageID: messageID, + }, }, } }@@ -872,7 +906,7 @@ // NewDice allows you to send a random dice roll.
func NewDice(chatID int64) DiceConfig { return DiceConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, } }@@ -883,7 +917,7 @@ // Emoji may be 🎲 (1-6), 🎯 (1-6), or 🏀 (1-5).
func NewDiceWithEmoji(chatID int64, emoji string) DiceConfig { return DiceConfig{ BaseChat: BaseChat{ - ChatID: chatID, + ChatConfig: ChatConfig{ChatID: chatID}, }, Emoji: emoji, }
@@ -61,6 +61,14 @@ // sticker, etc.
// // optional EditedChannelPost *Message `json:"edited_channel_post,omitempty"` + // MessageReaction is a reaction to a message was changed by a user. + // + // optional + MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"` + // MessageReactionCount reactions to a message with anonymous reactions were changed. + // + // optional + MessageReactionCount *MessageReactionCountUpdated `json:"message_reaction_count,omitempty"` // InlineQuery new incoming inline query // // optional@@ -276,6 +284,11 @@ // for private chats, supergroups and channels. Returned only in getChat.
// // optional ActiveUsernames []string `json:"active_usernames,omitempty"` + // AvailableReactions is a list of available reactions allowed in the chat. + // If omitted, then all emoji reactions are allowed. Returned only in getChat. + // + // optional + AvailableReactions []ReactionType `json:"available_reactions,omitempty"` // Custom emoji identifier of emoji status of the other party // in a private chat. Returned only in getChat. //@@ -476,6 +489,15 @@ // even if it itself is a reply;
// // optional ReplyToMessage *Message `json:"reply_to_message,omitempty"` + // ExternalReply is an information about the message that is being replied to, + // which may come from another chat or forum topic. + // + // optional + ExternalReply *ExternalReplyInfo `json:"external_reply,omitempty"` + // Quote for replies that quote part of the original message, the quoted part of the message + // + // optional + Quote *TextQuote `json:"text_quote,omitempty"` // ViaBot through which the message was sent; // // optional@@ -505,6 +527,11 @@ // URLs, bot commands, etc. that appear in the text;
// // optional Entities []MessageEntity `json:"entities,omitempty"` + // LinkPreviewOptions are options used for link preview generation for the message, + // if it is a text message and link preview options were changed + // + // Optional + LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"` // Animation message is an animation, information about the animation. // For backward compatibility, when this field is set, the document field will also be set; //@@ -663,10 +690,10 @@ // information about the payment;
// // optional SuccessfulPayment *SuccessfulPayment `json:"successful_payment,omitempty"` - // UserShared is a service message: a user was shared with the bot + // UsersShared is a service message: the users were shared with the bot // // optional - UserShared *UserShared `json:"user_shared,omitempty"` + UsersShared *UsersShared `json:"users_shared,omitempty"` // ChatShared is a service message: a chat was shared with the bot // // optional@@ -832,6 +859,7 @@ // “italic” (italic text),
// “underline” (underlined text), // “strikethrough” (strikethrough text), // "spoiler" (spoiler message), + // “blockquote” (block quotation), // “code” (monowidth string), // “pre” (monowidth block), // “text_link” (for clickable text URLs),@@ -925,6 +953,214 @@ func (e MessageEntity) IsTextLink() bool {
return e.Type == "text_link" } +// TextQuote contains information about the quoted part of a message +// that is replied to by the given message +type TextQuote struct { + // Text of the quoted part of a message that is replied to by the given message + Text string `json:"text"` + // Entities special entities that appear in the quote. + // Currently, only bold, italic, underline, strikethrough, spoiler, + // and custom_emoji entities are kept in quotes. + // + // optional + Entities []MessageEntity `json:"entities,omitempty"` + // Position is approximate quote position in the original message + // in UTF-16 code units as specified by the sender + Position int `json:"position"` + // IsManual True, if the quote was chosen manually by the message sender. + // Otherwise, the quote was added automatically by the server. + // + // optional + IsManual bool `json:"is_manual,omitempty"` +} + +// ExternalReplyInfo contains information about a message that is being replied to, +// which may come from another chat or forum topic. +type ExternalReplyInfo struct { + // Origin of the message replied to by the given message + Origin MessageOrigin `json:"origin"` + // Chat is the conversation the message belongs to + Chat *Chat `json:"chat"` + // MessageID is a unique message identifier inside this chat + MessageID int `json:"message_id"` + // LinkPreviewOptions used for link preview generation for the original message, + // if it is a text message + // + // Optional + LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"` + // Animation message is an animation, information about the animation. + // For backward compatibility, when this field is set, the document field will also be set; + // + // optional + Animation *Animation `json:"animation,omitempty"` + // Audio message is an audio file, information about the file; + // + // optional + Audio *Audio `json:"audio,omitempty"` + // Document message is a general file, information about the file; + // + // optional + Document *Document `json:"document,omitempty"` + // Photo message is a photo, available sizes of the photo; + // + // optional + Photo []PhotoSize `json:"photo,omitempty"` + // Sticker message is a sticker, information about the sticker; + // + // optional + Sticker *Sticker `json:"sticker,omitempty"` + // Story message is a forwarded story; + // + // optional + Story *Story `json:"story,omitempty"` + // Video message is a video, information about the video; + // + // optional + Video *Video `json:"video,omitempty"` + // VideoNote message is a video note, information about the video message; + // + // optional + VideoNote *VideoNote `json:"video_note,omitempty"` + // Voice message is a voice message, information about the file; + // + // optional + Voice *Voice `json:"voice,omitempty"` + // HasMediaSpoiler True, if the message media is covered by a spoiler animation + // + // optional + HasMediaSpoiler bool `json:"has_media_spoiler,omitempty"` + // Contact message is a shared contact, information about the contact; + // + // optional + Contact *Contact `json:"contact,omitempty"` + // Dice is a dice with random value; + // + // optional + Dice *Dice `json:"dice,omitempty"` + // Game message is a game, information about the game; + // + // optional + Game *Game `json:"game,omitempty"` + // Giveaway is information about the giveaway + // + // optional + Giveaway *Giveaway `json:"giveaway,omitempty"` + // GiveawayWinners a giveaway with public winners was completed + // + // optional + GiveawayWinners *GiveawayWinners `json:"giveaway_winners,omitempty"` + // Invoice message is an invoice for a payment; + // + // optional + Invoice *Invoice `json:"invoice,omitempty"` + // Location message is a shared location, information about the location; + // + // optional + Location *Location `json:"location,omitempty"` + // Poll is a native poll, information about the poll; + // + // optional + Poll *Poll `json:"poll,omitempty"` + // Venue message is a venue, information about the venue. + // For backward compatibility, when this field is set, the location field + // will also be set; + // + // optional + Venue *Venue `json:"venue,omitempty"` +} + +// ReplyParameters describes reply parameters for the message that is being sent. +type ReplyParameters struct { + // MessageID identifier of the message that will be replied to in + // the current chat, or in the chat chat_id if it is specified + MessageID int `json:"message_id"` + // ChatID if the message to be replied to is from a different chat, + // unique identifier for the chat or username of the channel (in the format @channelusername) + // + // optional + ChatID interface{} `json:"chat_id,omitempty"` + // AllowSendingWithoutReply true if the message should be sent even + // if the specified message to be replied to is not found; + // can be used only for replies in the same chat and forum topic. + // + // optional + AllowSendingWithoutReply bool `json:"allow_sending_without_reply,omitempty"` + // Quote is a quoted part of the message to be replied to; + // 0-1024 characters after entities parsing. The quote must be + // an exact substring of the message to be replied to, + // including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. + // The message will fail to send if the quote isn't found in the original message. + // + // optional + Quote string `json:"quote,omitempty"` + // QuoteParseMode mode for parsing entities in the quote. + // + // optional + QuoteParseMode string `json:"quote_parse_mode,omitempty"` + // QuoteEntities a JSON-serialized list of special entities that appear in the quote. + // It can be specified instead of quote_parse_mode. + // + // optional + QuoteEntities []MessageEntity `json:"quote_entities,omitempty"` + // QuotePosition is a position of the quote in the original message in UTF-16 code units + // + // optional + QuotePosition int `json:"quote_position,omitempty"` +} + +const ( + MessageOriginUser = "user" + MessageOriginHiddenUser = "hidden_user" + MessageOriginChat = "chat" + MessageOriginChannel = "channel" +) + +// MessageOrigin describes the origin of a message. It can be one of: "user", "hidden_user", "origin_chat", "origin_channel" +type MessageOrigin struct { + // Type of the message origin. + Type string `json:"type"` + // Date the message was sent originally in Unix time + Date int64 `json:"date"` + // SenderUser "user" only. + // Is a user that sent the message originally + SenderUser *User `json:"sender_user,omitempty"` + // SenderUserName "hidden_user" only. + // Name of the user that sent the message originally + SenderUserName string `json:"sender_user_name,omitempty"` + // SenderChat "chat" and "channel". + // For "chat": Chat that sent the message originally + // For "channel": Channel chat to which the message was originally sent + SenderChat *Chat `json:"sender_chat,omitempty"` + // AuthorSignature "chat" and "channel". + // For "chat": For messages originally sent by an anonymous chat administrator, + // original message author signature. + // For "channel": Signature of the original post author + // + // Optional + AuthorSignature string `json:"author_signature,omitempty"` + // MessageID "channel" only. + // Unique message identifier inside the chat + // + // Optional + MessageID int `json:"message_id,omitempty"` +} + +func (m MessageOrigin) IsUser() bool { + return m.Type == MessageOriginUser +} + +func (m MessageOrigin) IsHiddenUser() bool { + return m.Type == MessageOriginHiddenUser +} + +func (m MessageOrigin) IsChat() bool { + return m.Type == MessageOriginChat +} + +func (m MessageOrigin) IsChannel() bool { + return m.Type == MessageOriginChannel +} + // PhotoSize represents one size of a photo or a file / sticker thumbnail. type PhotoSize struct { // FileID identifier for this file, which can be used to download or reuse@@ -1351,13 +1587,13 @@ // unhidden in the chat. Currently holds no information.
type GeneralForumTopicUnhidden struct { } -// UserShared object contains information about the user whose identifier +// UsersShared object contains information about the user whose identifier // was shared with the bot using a KeyboardButtonRequestUser button. -type UserShared struct { +type UsersShared struct { // RequestID is an indentifier of the request. RequestID int `json:"request_id"` - // UserID in an identifier of the shared user. - UserID int64 `json:"user_id"` + // UserIDs are identifiers of the shared user. + UserIDs []int64 `json:"user_ids"` } // ChatShared contains information about the chat whose identifier@@ -1423,6 +1659,115 @@ // optional
Users []User `json:"users,omitempty"` } +// Giveaway represents a message about a scheduled giveaway. +type Giveaway struct { + // Chats is the list of chats which the user must join to participate in the giveaway + Chats []Chat `json:"chats"` + // WinnersSelectionDate is point in time (Unix timestamp) when + // winners of the giveaway will be selected + WinnersSelectionDate int64 `json:"winners_selection_date"` + // WinnerCount is the number of users which are supposed + // to be selected as winners of the giveaway + WinnerCount int `json:"winner_count"` + // OnlyNewMembers True, if only users who join the chats after + // the giveaway started should be eligible to win + // + // optional + OnlyNewMembers bool `json:"only_new_members,omitempty"` + // HasPublicWinners True, if the list of giveaway winners will be visible to everyone + // + // optional + HasPublicWinners bool `json:"has_public_winners,omitempty"` + // PrizeDescription is description of additional giveaway prize + // + // optional + PrizeDescription string `json:"prize_description,omitempty"` + // CountryCodes is a list of two-letter ISO 3166-1 alpha-2 country codes + // indicating the countries from which eligible users for the giveaway must come. + // If empty, then all users can participate in the giveaway. + // + // optional + CountryCodes []string `json:"country_codes,omitempty"` + // PremiumSubscriptionMonthCount the number of months the Telegram Premium + // subscription won from the giveaway will be active for + // + // optional + PremiumSubscriptionMonthCount int `json:"premium_subscription_month_count,omitempty"` +} + +// Giveaway represents a message about a scheduled giveaway. +type GiveawayWinners struct { + // Chat that created the giveaway + Chat Chat `json:"chat"` + // GiveawayMessageID is the identifier of the messsage with the giveaway in the chat + GiveawayMessageID int `json:"giveaway_message_id"` + // WinnersSelectionDate is point in time (Unix timestamp) when + // winners of the giveaway will be selected + WinnersSelectionDate int64 `json:"winners_selection_date"` + // WinnerCount is the number of users which are supposed + // to be selected as winners of the giveaway + WinnerCount int `json:"winner_count"` + // Winners is a list of up to 100 winners of the giveaway + Winners []User `json:"winners"` + // AdditionalChatCount is the number of other chats + // the user had to join in order to be eligible for the giveaway + // + // optional + AdditionalChatCount int `json:"additional_chat_count,omitempty"` + // PremiumSubscriptionMonthCount the number of months the Telegram Premium + // subscription won from the giveaway will be active for + // + // optional + PremiumSubscriptionMonthCount int `json:"premium_subscription_month_count,omitempty"` + // UnclaimedPrizeCount is the number of undistributed prizes + // + // optional + UnclaimedPrizeCount int `json:"unclaimed_prize_count,omitempty"` + // OnlyNewMembers True, if only users who join the chats after + // the giveaway started should be eligible to win + // + // optional + OnlyNewMembers bool `json:"only_new_members,omitempty"` + // WasRefunded True, if the giveaway was canceled because the payment for it was refunded + // + // optional + WasRefunded bool `json:"was_refunded,omitempty"` + // PrizeDescription is description of additional giveaway prize + // + // optional + PrizeDescription string `json:"prize_description,omitempty"` +} + +// LinkPreviewOptions describes the options used for link preview generation. +type LinkPreviewOptions struct { + // IsDisabled True, if the link preview is disabled + // + // optional + IsDisabled bool `json:"is_disabled,omitempty"` + // URL to use for the link preview. If empty, + // then the first URL found in the message text will be used + // + // optional + URL string `json:"url,omitempty"` + // PreferSmallMedia True, if the media in the link preview is suppposed + // to be shrunk; ignored if the URL isn't explicitly specified + // or media size change isn't supported for the preview + // + // optional + PreferSmallMedia bool `json:"prefer_small_media,omitempty"` + // PreferLargeMedia True, if the media in the link preview is suppposed + // to be enlarged; ignored if the URL isn't explicitly specified + // or media size change isn't supported for the preview + // + // optional + PreferLargeMedia bool `json:"prefer_large_media,omitempty"` + // ShowAboveText True, if the link preview must be shown above the message text; + // otherwise, the link preview will be shown below the message text + // + // optional + ShowAboveText bool `json:"show_above_text,omitempty"` +} + // UserProfilePhotos contains a set of user profile photos. type UserProfilePhotos struct { // TotalCount total number of profile pictures the target user has@@ -1516,13 +1861,13 @@ type KeyboardButton struct {
// Text of the button. If none of the optional fields are used, // it will be sent as a message when the button is pressed. Text string `json:"text"` - // RequestUser if specified, pressing the button will open + // RequestUsers if specified, pressing the button will open // a list of suitable users. Tapping on any user will send // their identifier to the bot in a "user_shared" service message. // Available in private chats only. // // optional - RequestUser *KeyboardButtonRequestUser `json:"request_user,omitempty"` + RequestUsers *KeyboardButtonRequestUsers `json:"request_users,omitempty"` // RequestChat if specified, pressing the button will open // a list of suitable chats. Tapping on a chat will send // its identifier to the bot in a "chat_shared" service message.@@ -1555,10 +1900,10 @@ // optional
WebApp *WebAppInfo `json:"web_app,omitempty"` } -// KeyboardButtonRequestUser defines the criteria used to request +// KeyboardButtonRequestUsers defines the criteria used to request // a suitable user. The identifier of the selected user will be shared // with the bot when the corresponding button is pressed. -type KeyboardButtonRequestUser struct { +type KeyboardButtonRequestUsers struct { // RequestID is a signed 32-bit identifier of the request. RequestID int `json:"request_id"` // UserIsBot pass True to request a bot,@@ -1573,6 +1918,11 @@ // If not specified, no additional restrictions are applied.
// // optional UserIsPremium bool `json:"user_is_premium,omitempty"` + // MaxQuantity is the maximum number of users to be selected. + // 1-10. Defaults to 1 + // + // optional + MaxQuantity int `json:"max_quantity,omitempty"` } // KeyboardButtonRequestChat defines the criteria used to request@@ -2242,6 +2592,72 @@ // owner
Address string `json:"address"` } +const ( + ReactionTypeEmoji = "emoji" + ReactionTypeCustomEmoji = "custom_emoji" +) + +// ReactionType describes the type of a reaction. Currently, it can be one of: "emoji", "custom_emoji" +type ReactionType struct { + // Type of the reaction. Can be "emoji", "custom_emoji" + Type string `json:"type"` + // Emoji type "emoji" only. Is a reaction emoji. + Emoji string `json:"emoji"` + // CustomEmoji type "custom_emoji" only. Is a custom emoji identifier. + CustomEmoji string `json:"custom_emoji"` +} + +func (r ReactionType) IsEmoji() bool { + return r.Type == ReactionTypeEmoji +} + +func (r ReactionType) IsCustomEmoji() bool { + return r.Type == ReactionTypeCustomEmoji +} + +// ReactionCount represents a reaction added to a message along with the number of times it was added. +type ReactionCount struct { + // Type of the reaction + Type ReactionType `json:"type"` + // TotalCount number of times the reaction was added + TotalCount int `json:"total_count"` +} + +// MessageReactionUpdated represents a change of a reaction on a message performed by a user. +type MessageReactionUpdated struct { + // Chat containing the message the user reacted to. + Chat Chat `json:"chat"` + // MessageID unique identifier of the message inside the chat. + MessageID int `json:"message_id"` + // User that changed the reaction, if the user isn't anonymous. + // + // optional + User *User `json:"user"` + // ActorChat the chat on behalf of which the reaction was changed, + // if the user is anonymous. + // + // optional + ActorChat *Chat `json:"actor_chat"` + // Date of the change in Unix time. + Date int64 `json:"date"` + // OldReaction is a previous list of reaction types that were set by the user. + OldReaction []ReactionType `json:"old_reaction"` + // NewReaction is a new list of reaction types that have been set by the user. + NewReaction []ReactionType `json:"new_reaction"` +} + +// MessageReactionCountUpdated represents reaction changes on a message with anonymous reactions. +type MessageReactionCountUpdated struct { + // Chat containing the message. + Chat Chat `json:"chat"` + // MessageID unique identifier of the message inside the chat. + MessageID int `json:"message_id"` + // Date of the change in Unix time. + Date int64 `json:"date"` + // Reactions is a list of reactions that are present on the message. + Reactions []ReactionCount `json:"reactions"` +} + // ForumTopic represents a forum topic. type ForumTopic struct { // MessageThreadID is the unique identifier of the forum topic@@ -2303,6 +2719,83 @@ 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"` +} + +const ( + ChatBoostSourcePremium = "premium" + ChatBoostSourceGiftCode = "gift_code" + ChatBoostSourceGiveaway = "giveaway" +) + +// ChatBoostSource describes the source of a chat boost +type ChatBoostSource struct { + // Source of the boost, It can be one of: + // "premium", "gift_code", "giveaway" + Source string `json:"source"` + // For "premium": User that boosted the chat + // For "gift_code": User for which the gift code was created + // Optional for "giveaway": User that won the prize in the giveaway if any + User *User `json:"user,omitempty"` + // GiveawayMessageID "giveaway" only. + // Is an identifier of a message in the chat with the giveaway; + // the message could have been deleted already. May be 0 if the message isn't sent yet. + GiveawayMessageID int `json:"giveaway_message_id,omitempty"` + // IsUnclaimed "giveaway" only. + // True, if the giveaway was completed, but there was no user to win the prize + // + // optional + IsUnclaimed bool `json:"is_unclaimed,omitempty"` +} + +func (c ChatBoostSource) IsPremium() bool { + return c.Source == ChatBoostSourcePremium +} + +func (c ChatBoostSource) IsGiftCode() bool { + return c.Source == ChatBoostSourceGiftCode +} + +func (c ChatBoostSource) IsGiveaway() bool { + return c.Source == ChatBoostSourceGiveaway +} + +// ChatBoost contains information about a chat boost. +type ChatBoost struct { + // BoostID is an unique identifier of the boost + BoostID string `json:"boost_id"` + // AddDate is a point in time (Unix timestamp) when the chat was boosted + AddDate int64 `json:"add_date"` + // ExpirationDate is a point in time (Unix timestamp) when the boost will + // automatically expire, unless the booster's Telegram Premium subscription is prolonged + ExpirationDate int64 `json:"expiration_date"` + // Source of the added boost + Source ChatBoostSource `json:"source"` +} + +// ChatBoostUpdated represents a boost added to a chat or changed. +type ChatBoostUpdated struct { + // Chat which was boosted + Chat Chat `json:"chat"` + // Boost infomation about the chat boost + Boost ChatBoost `json:"boost"` +} + +// ChatBoostRemoved represents a boost removed from a chat. +type ChatBoostRemoved struct { + // Chat which was boosted + Chat Chat `json:"chat"` + // BoostID unique identifier of the boost + BoostID string `json:"boost_id"` + // RemoveDate point in time (Unix timestamp) when the boost was removed + RemoveDate int64 `json:"remove_date"` + // Source of the removed boost + Source ChatBoostSource `json:"source"` +} + +// UserChatBoosts represents a list of boosts added to a chat by a user. +type UserChatBoosts struct { + // Boosts is the list of boosts added to the chat by the user + Boosts []ChatBoost `json:"boosts"` } // ResponseParameters are various errors that can be returned in APIResponse.@@ -3576,10 +4069,10 @@ // can be specified instead of parse_mode
// // optional Entities []MessageEntity `json:"entities,omitempty"` - // DisableWebPagePreview disables link previews for links in the sent message + // LinkPreviewOptions used for link preview generation for the original message // - // optional - DisableWebPagePreview bool `json:"disable_web_page_preview,omitempty"` + // Optional + LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"` } // InputLocationMessageContent contains a location for displaying
@@ -341,6 +341,7 @@ _ Chattable = UnbanChatMemberConfig{}
_ Chattable = UnbanChatSenderChatConfig{} _ Chattable = UnpinChatMessageConfig{} _ Chattable = UpdateConfig{} + _ Chattable = SetMessageReactionConfig{} _ Chattable = UserProfilePhotosConfig{} _ Chattable = VenueConfig{} _ Chattable = VideoConfig{}@@ -359,6 +360,7 @@ _ Chattable = CloseGeneralForumTopicConfig{}
_ Chattable = ReopenGeneralForumTopicConfig{} _ Chattable = HideGeneralForumTopicConfig{} _ Chattable = UnhideGeneralForumTopicConfig{} + _ Chattable = UnpinAllGeneralForumTopicMessagesConfig{} _ Chattable = SetCustomEmojiStickerSetThumbnailConfig{} _ Chattable = SetStickerSetTitleConfig{} _ Chattable = DeleteStickerSetConfig{}