diff --git a/.gitignore b/.gitignore index eb7a23b2..d3083e5f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ coverage.out tmp/ book/ +.vscode/ diff --git a/configs.go b/configs.go index 1831337b..5ca9e43e 100644 --- a/configs.go +++ b/configs.go @@ -265,6 +265,7 @@ func (CloseConfig) params() (Params, error) { // BaseChat is base type for all chat config types. type BaseChat struct { ChatID int64 // required + MessageThreadID int ChannelUsername string ProtectContent bool ReplyToMessageID int @@ -277,6 +278,7 @@ 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) @@ -321,6 +323,21 @@ func (edit BaseEdit) params() (Params, error) { 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 @@ -405,6 +422,7 @@ func (config CopyMessageConfig) method() string { // PhotoConfig contains information about a SendPhoto request. type PhotoConfig struct { BaseFile + BaseSpoiler Thumb RequestFileData Caption string ParseMode string @@ -420,6 +438,15 @@ func (config PhotoConfig) params() (Params, error) { params.AddNonEmpty("caption", config.Caption) params.AddNonEmpty("parse_mode", config.ParseMode) err = params.AddInterface("caption_entities", config.CaptionEntities) + if err != nil { + return params, err + } + + p1, err := config.BaseSpoiler.params() + if err != nil { + return params, err + } + params.Merge(p1) return params, err } @@ -436,7 +463,7 @@ func (config PhotoConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -484,7 +511,7 @@ func (config AudioConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -524,7 +551,7 @@ func (config DocumentConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -534,11 +561,18 @@ func (config DocumentConfig) files() []RequestFile { // StickerConfig contains information about a SendSticker request. type StickerConfig struct { + //Emoji associated with the sticker; only for just uploaded stickers + Emoji string BaseFile } func (config StickerConfig) params() (Params, error) { - return config.BaseChat.params() + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + params.AddNonEmpty("emoji", config.Emoji) + return params, err } func (config StickerConfig) method() string { @@ -555,6 +589,7 @@ func (config StickerConfig) files() []RequestFile { // VideoConfig contains information about a SendVideo request. type VideoConfig struct { BaseFile + BaseSpoiler Thumb RequestFileData Duration int Caption string @@ -574,6 +609,15 @@ func (config VideoConfig) params() (Params, error) { params.AddNonEmpty("parse_mode", config.ParseMode) params.AddBool("supports_streaming", config.SupportsStreaming) err = params.AddInterface("caption_entities", config.CaptionEntities) + if err != nil { + return params, err + } + + p1, err := config.BaseSpoiler.params() + if err != nil { + return params, err + } + params.Merge(p1) return params, err } @@ -590,7 +634,7 @@ func (config VideoConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -601,6 +645,7 @@ func (config VideoConfig) files() []RequestFile { // AnimationConfig contains information about a SendAnimation request. type AnimationConfig struct { BaseFile + BaseSpoiler Duration int Thumb RequestFileData Caption string @@ -618,6 +663,15 @@ func (config AnimationConfig) params() (Params, error) { params.AddNonEmpty("caption", config.Caption) params.AddNonEmpty("parse_mode", config.ParseMode) err = params.AddInterface("caption_entities", config.CaptionEntities) + if err != nil { + return params, err + } + + p1, err := config.BaseSpoiler.params() + if err != nil { + return params, err + } + params.Merge(p1) return params, err } @@ -634,7 +688,7 @@ func (config AnimationConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -671,7 +725,7 @@ func (config VideoNoteConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -715,7 +769,7 @@ func (config VoiceConfig) files() []RequestFile { if config.Thumb != nil { files = append(files, RequestFile{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }) } @@ -974,13 +1028,15 @@ func (config GetGameHighScoresConfig) method() string { // ChatActionConfig contains information about a SendChatAction request. type ChatActionConfig struct { BaseChat - Action string // required + MessageThreadID int + Action string // required } func (config ChatActionConfig) params() (Params, error) { params, err := config.BaseChat.params() params["action"] = config.Action + params.AddNonZero("message_thread_id", config.MessageThreadID) return params, err } @@ -1164,6 +1220,7 @@ type WebhookConfig struct { MaxConnections int AllowedUpdates []string DropPendingUpdates bool + SecretToken string } func (config WebhookConfig) method() string { @@ -1181,6 +1238,7 @@ func (config WebhookConfig) params() (Params, error) { params.AddNonZero("max_connections", config.MaxConnections) err := params.AddInterface("allowed_updates", config.AllowedUpdates) params.AddBool("drop_pending_updates", config.DropPendingUpdates) + params.AddNonEmpty("secret_token", config.SecretToken) return params, err } @@ -1349,8 +1407,9 @@ type KickChatMemberConfig = BanChatMemberConfig // RestrictChatMemberConfig contains fields to restrict members of chat type RestrictChatMemberConfig struct { ChatMemberConfig - UntilDate int64 - Permissions *ChatPermissions + UntilDate int64 + UseIndependentChatPermissions bool + Permissions *ChatPermissions } func (config RestrictChatMemberConfig) method() string { @@ -1362,6 +1421,7 @@ func (config RestrictChatMemberConfig) params() (Params, error) { 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) @@ -1383,6 +1443,7 @@ type PromoteChatMemberConfig struct { CanRestrictMembers bool CanPinMessages bool CanPromoteMembers bool + CanManageTopics bool } func (config PromoteChatMemberConfig) method() string { @@ -1406,6 +1467,7 @@ func (config PromoteChatMemberConfig) params() (Params, error) { params.AddBool("can_restrict_members", config.CanRestrictMembers) params.AddBool("can_pin_messages", config.CanPinMessages) params.AddBool("can_promote_members", config.CanPromoteMembers) + params.AddBool("can_manage_topics", config.CanManageTopics) return params, nil } @@ -1525,7 +1587,8 @@ func (ChatAdministratorsConfig) method() string { // restrict members. type SetChatPermissionsConfig struct { ChatConfig - Permissions *ChatPermissions + UseIndependentChatPermissions bool + Permissions *ChatPermissions } func (SetChatPermissionsConfig) method() string { @@ -1536,6 +1599,7 @@ func (config SetChatPermissionsConfig) params() (Params, error) { params := make(Params) params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions) err := params.AddInterface("permissions", config.Permissions) return params, err @@ -1784,6 +1848,64 @@ func (config InvoiceConfig) method() string { return "sendInvoice" } +// InvoiceLinkConfig contains information for createInvoiceLink method +type InvoiceLinkConfig struct { + Title string //Required + Description string //Required + Payload string //Required + ProviderToken string //Required + Currency string //Required + Prices []LabeledPrice //Required + MaxTipAmount int + SuggestedTipAmounts []int + ProviderData string + PhotoURL string + PhotoSize int + PhotoWidth int + PhotoHeight int + NeedName bool + NeedPhoneNumber bool + NeedEmail bool + NeedShippingAddress bool + SendPhoneNumberToProvider bool + SendEmailToProvider bool + IsFlexible bool +} + +func (config InvoiceLinkConfig) params() (Params, error) { + params := make(Params) + + params["title"] = config.Title + params["description"] = config.Description + params["payload"] = config.Payload + params["provider_token"] = config.ProviderToken + params["currency"] = config.Currency + if err := params.AddInterface("prices", config.Prices); err != nil { + return params, err + } + + params.AddNonZero("max_tip_amount", config.MaxTipAmount) + err := params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts) + params.AddNonEmpty("provider_data", config.ProviderData) + params.AddNonEmpty("photo_url", config.PhotoURL) + params.AddNonZero("photo_size", config.PhotoSize) + params.AddNonZero("photo_width", config.PhotoWidth) + params.AddNonZero("photo_height", config.PhotoHeight) + params.AddBool("need_name", config.NeedName) + params.AddBool("need_phone_number", config.NeedPhoneNumber) + params.AddBool("need_email", config.NeedEmail) + params.AddBool("need_shipping_address", config.NeedShippingAddress) + params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider) + params.AddBool("send_email_to_provider", config.SendEmailToProvider) + params.AddBool("is_flexible", config.IsFlexible) + + return params, err +} + +func (config InvoiceLinkConfig) method() string { + return "createInvoiceLink" +} + // ShippingConfig contains information for answerShippingQuery request. type ShippingConfig struct { ShippingQueryID string // required @@ -2004,10 +2126,29 @@ func (config GetStickerSetConfig) params() (Params, error) { return params, nil } +// GetCustomEmojiStickersConfig get information about +// custom emoji stickers by their identifiers. +type GetCustomEmojiStickersConfig struct { + CustomEmojiIDs []string +} + +func (config GetCustomEmojiStickersConfig) params() (Params, error) { + params := make(Params) + + params.AddInterface("custom_emoji_ids", config.CustomEmojiIDs) + + return params, nil +} + +func (config GetCustomEmojiStickersConfig) method() string { + return "getCustomEmojiStickers" +} + // UploadStickerConfig allows you to upload a sticker for use in a set later. type UploadStickerConfig struct { - UserID int64 - PNGSticker RequestFileData + UserID int64 + Sticker RequestFile + StickerFormat string } func (config UploadStickerConfig) method() string { @@ -2018,29 +2159,24 @@ func (config UploadStickerConfig) params() (Params, error) { params := make(Params) params.AddNonZero64("user_id", config.UserID) + params["sticker_format"] = config.StickerFormat return params, nil } func (config UploadStickerConfig) files() []RequestFile { - return []RequestFile{{ - Name: "png_sticker", - Data: config.PNGSticker, - }} + return []RequestFile{config.Sticker} } // NewStickerSetConfig allows creating a new sticker set. -// -// You must set either PNGSticker or TGSSticker. type NewStickerSetConfig struct { - UserID int64 - Name string - Title string - PNGSticker RequestFileData - TGSSticker RequestFileData - Emojis string - ContainsMasks bool - MaskPosition *MaskPosition + UserID int64 + Name string + Title string + Stickers []InputSticker + StickerFormat string + StickerType string + NeedsRepainting bool //optional; Pass True if stickers in the sticker set must be repainted to the color of text when used in messages, the accent color if used as emoji status, white on chat photos, or another appropriate color based on context; for custom emoji sticker sets only } func (config NewStickerSetConfig) method() string { @@ -2053,38 +2189,28 @@ func (config NewStickerSetConfig) params() (Params, error) { params.AddNonZero64("user_id", config.UserID) params["name"] = config.Name params["title"] = config.Title + params["sticker_format"] = config.StickerFormat - params["emojis"] = config.Emojis - - params.AddBool("contains_masks", config.ContainsMasks) - - err := params.AddInterface("mask_position", config.MaskPosition) + params.AddBool("needs_repainting", config.NeedsRepainting) + params.AddNonEmpty("sticker_type", string(config.StickerType)) + err := params.AddInterface("stickers", config.Stickers) return params, err } func (config NewStickerSetConfig) files() []RequestFile { - if config.PNGSticker != nil { - return []RequestFile{{ - Name: "png_sticker", - Data: config.PNGSticker, - }} + requestFiles := []RequestFile{} + for _, v := range config.Stickers { + requestFiles = append(requestFiles, v.Sticker) } - - return []RequestFile{{ - Name: "tgs_sticker", - Data: config.TGSSticker, - }} + return requestFiles } // AddStickerConfig allows you to add a sticker to a set. type AddStickerConfig struct { - UserID int64 - Name string - PNGSticker RequestFileData - TGSSticker RequestFileData - Emojis string - MaskPosition *MaskPosition + UserID int64 + Name string + Sticker InputSticker } func (config AddStickerConfig) method() string { @@ -2096,26 +2222,12 @@ func (config AddStickerConfig) params() (Params, error) { params.AddNonZero64("user_id", config.UserID) params["name"] = config.Name - params["emojis"] = config.Emojis - - err := params.AddInterface("mask_position", config.MaskPosition) - + err := params.AddInterface("sticker", config.Sticker) return params, err } func (config AddStickerConfig) files() []RequestFile { - if config.PNGSticker != nil { - return []RequestFile{{ - Name: "png_sticker", - Data: config.PNGSticker, - }} - } - - return []RequestFile{{ - Name: "tgs_sticker", - Data: config.TGSSticker, - }} - + return []RequestFile{config.Sticker.Sticker} } // SetStickerPositionConfig allows you to change the position of a sticker in a set. @@ -2137,6 +2249,61 @@ func (config SetStickerPositionConfig) params() (Params, error) { return params, nil } +// SetCustomEmojiStickerSetThumbnalConfig allows you to set the thumbnail of a custom emoji sticker set +type SetCustomEmojiStickerSetThumbnalConfig struct { + Name string + CustomEmojiID string +} + +func (config SetCustomEmojiStickerSetThumbnalConfig) method() string { + return "setCustomEmojiStickerSetThumbnail" +} + +func (config SetCustomEmojiStickerSetThumbnalConfig) params() (Params, error) { + params := make(Params) + + params["name"] = config.Name + params.AddNonEmpty("position", config.CustomEmojiID) + + return params, nil +} + +// SetStickerSetTitle allows you to set the title of a created sticker set +type SetStickerSetTitleConfig struct { + Name string + Title string +} + +func (config SetStickerSetTitleConfig) method() string { + return "setStickerSetTitle" +} + +func (config SetStickerSetTitleConfig) params() (Params, error) { + params := make(Params) + + params["name"] = config.Name + params["title"] = config.Title + + return params, nil +} + +// DeleteStickerSetConfig allows you to delete a sticker set that was created by the bot. +type DeleteStickerSetConfig struct { + Name string +} + +func (config DeleteStickerSetConfig) method() string { + return "deleteStickerSet" +} + +func (config DeleteStickerSetConfig) params() (Params, error) { + params := make(Params) + + params["name"] = config.Name + + return params, nil +} + // DeleteStickerConfig allows you to delete a sticker from a set. type DeleteStickerConfig struct { Sticker string @@ -2154,6 +2321,63 @@ func (config DeleteStickerConfig) params() (Params, error) { return params, nil } +// SetStickerEmojiListConfig allows you to change the list of emoji assigned to a regular or custom emoji sticker. The sticker must belong to a sticker set created by the bot +type SetStickerEmojiListConfig struct { + Sticker string + EmojiList []string +} + +func (config SetStickerEmojiListConfig) method() string { + return "setStickerEmojiList" +} + +func (config SetStickerEmojiListConfig) params() (Params, error) { + params := make(Params) + + params["sticker"] = config.Sticker + err := params.AddInterface("emoji_list", config.EmojiList) + + return params, err +} + +// SetStickerKeywordsConfig allows you to change search keywords assigned to a regular or custom emoji sticker. The sticker must belong to a sticker set created by the bot. +type SetStickerKeywordsConfig struct { + Sticker string + Keywords []string +} + +func (config SetStickerKeywordsConfig) method() string { + return "setStickerKeywords" +} + +func (config SetStickerKeywordsConfig) params() (Params, error) { + params := make(Params) + + params["sticker"] = config.Sticker + err := params.AddInterface("keywords", config.Keywords) + + return params, err +} + +// SetStickerMaskPositionConfig allows you to change the mask position of a mask sticker. The sticker must belong to a sticker set that was created by the bot +type SetStickerMaskPositionConfig struct { + Sticker string + MaskPosition *MaskPosition +} + +func (config SetStickerMaskPositionConfig) method() string { + return "setStickerMaskPosition" +} + +func (config SetStickerMaskPositionConfig) params() (Params, error) { + params := make(Params) + + params["sticker"] = config.Sticker + err := params.AddInterface("keywords", config.MaskPosition) + + return params, err +} + // SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set. type SetStickerSetThumbConfig struct { Name string @@ -2162,7 +2386,7 @@ type SetStickerSetThumbConfig struct { } func (config SetStickerSetThumbConfig) method() string { - return "setStickerSetThumb" + return "setStickerSetThumbnail" } func (config SetStickerSetThumbConfig) params() (Params, error) { @@ -2176,7 +2400,7 @@ func (config SetStickerSetThumbConfig) params() (Params, error) { func (config SetStickerSetThumbConfig) files() []RequestFile { return []RequestFile{{ - Name: "thumb", + Name: "thumbnail", Data: config.Thumb, }} } @@ -2220,16 +2444,246 @@ func (config DeleteChatStickerSetConfig) params() (Params, error) { return params, nil } +// GetForumTopicIconStickersConfig allows you to get custom emoji stickers, +// which can be used as a forum topic icon by any user. +type GetForumTopicIconStickersConfig struct{} + +func (config GetForumTopicIconStickersConfig) method() string { + return "getForumTopicIconStickers" +} + +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 + Name string + IconColor int + IconCustomEmojiID string +} + +func (config CreateForumTopicConfig) method() string { + return "createForumTopic" +} + +func (config CreateForumTopicConfig) params() (Params, error) { + params := make(Params) + + 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 +} + +// 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 +} + +func (config EditForumTopicConfig) method() string { + return "editForumTopic" +} + +func (config EditForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero("message_thread_id", config.MessageThreadID) + 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 +} + +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 +} + +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 +} + +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 +} + +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 +// and must have can_manage_topics administrator rights. Returns True on success. +type EditGeneralForumTopicConfig struct { + BaseForum + Name string +} + +func (config EditGeneralForumTopicConfig) method() string { + return "editGeneralForumTopic" +} + +func (config EditGeneralForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("name", config.Name) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// CloseGeneralForumTopicConfig allows you to to close an open 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// Returns True on success. +type CloseGeneralForumTopicConfig struct{ BaseForum } + +func (config CloseGeneralForumTopicConfig) method() string { + return "closeGeneralForumTopic" +} + +// CloseGeneralForumTopicConfig allows you to reopen a closed 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// The topic will be automatically unhidden if it was hidden. +// Returns True on success. +type ReopenGeneralForumTopicConfig struct{ BaseForum } + +func (config ReopenGeneralForumTopicConfig) method() string { + return "reopenGeneralForumTopic" +} + +// HideGeneralForumTopicConfig allows you to hide the 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// The topic will be automatically closed if it was open. +// Returns True on success. +type HideGeneralForumTopicConfig struct{ BaseForum } + +func (config HideGeneralForumTopicConfig) method() string { + return "hideGeneralForumTopic" +} + +// UnhideGeneralForumTopicConfig allows you to unhide the 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// Returns True on success. +type UnhideGeneralForumTopicConfig struct{ BaseForum } + +func (config UnhideGeneralForumTopicConfig) method() string { + return "unhideGeneralForumTopic" +} + // MediaGroupConfig allows you to send a group of media. // // Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo). type MediaGroupConfig struct { - ChatID int64 - ChannelUsername string - - Media []interface{} - DisableNotification bool - ReplyToMessageID int + BaseChat + Media []interface{} } func (config MediaGroupConfig) method() string { @@ -2237,13 +2691,16 @@ func (config MediaGroupConfig) method() string { } func (config MediaGroupConfig) params() (Params, error) { - params := make(Params) + params, err := config.BaseChat.params() + 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)) + err = params.AddInterface("media", prepareInputMediaForParams(config.Media)) return params, err } @@ -2338,6 +2795,86 @@ func (config DeleteMyCommandsConfig) params() (Params, error) { return params, err } +// GetMyDescriptionConfig get the current bot description for the given user language +type GetMyDescriptionConfig struct { + LanguageCode string +} + +func (config GetMyDescriptionConfig) method() string { + return "getMyDescription" +} + +func (config GetMyDescriptionConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, nil +} + +// SetMyDescroptionConfig sets the bot's description, which is shown in the chat with the bot if the chat is empty +type SetMyDescriptionConfig struct { + // Pass an empty string to remove the dedicated description for the given language. + Description string + //If empty, the description will be applied to all users for whose language there is no dedicated description. + LanguageCode string +} + +func (config SetMyDescriptionConfig) method() string { + return "setMyDescription" +} + +func (config SetMyDescriptionConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("description", config.Description) + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, nil +} + +// GetMyShortDescriptionConfig get the current bot short description for the given user language +type GetMyShortDescriptionConfig struct { + LanguageCode string +} + +func (config GetMyShortDescriptionConfig) method() string { + return "getMyShortDescription" +} + +func (config GetMyShortDescriptionConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, nil +} + +// SetMyDescroptionConfig sets the bot's short description, which is shown on the bot's profile page and is sent together with the link when users share the bot. +type SetMyShortDescriptionConfig struct { + // New short description for the bot; 0-120 characters. + // + //Pass an empty string to remove the dedicated short description for the given language. + ShortDescription string + //A two-letter ISO 639-1 language code. + // + //If empty, the short description will be applied to all users for whose language there is no dedicated short description. + LanguageCode string +} + +func (config SetMyShortDescriptionConfig) method() string { + return "setMyDescription" +} + +func (config SetMyShortDescriptionConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("short_description", config.ShortDescription) + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, nil +} + // SetChatMenuButtonConfig changes the bot's menu button in a private chat, // or the default menu button. type SetChatMenuButtonConfig struct { diff --git a/helpers.go b/helpers.go index 3a0e8187..79028392 100644 --- a/helpers.go +++ b/helpers.go @@ -130,6 +130,29 @@ func NewSticker(chatID int64, file RequestFileData) StickerConfig { } } +// NewCustomEmojiStickerSetThumbnal creates a new setCustomEmojiStickerSetThumbnal request +func NewCustomEmojiStickerSetThumbnal(name, customEmojiID string) SetCustomEmojiStickerSetThumbnalConfig { + return SetCustomEmojiStickerSetThumbnalConfig{ + Name: name, + CustomEmojiID: customEmojiID, + } +} + +// NewStickerSetTitle creates a new setStickerSetTitle request +func NewStickerSetTitle(name, title string) SetStickerSetTitleConfig { + return SetStickerSetTitleConfig{ + Name: name, + Title: title, + } +} + +// NewDeleteStickerSet creates a new deleteStickerSet request +func NewDeleteStickerSet(name, title string) DeleteStickerSetConfig { + return DeleteStickerSetConfig{ + Name: name, + } +} + // NewVideo creates a new sendVideo request. func NewVideo(chatID int64, file RequestFileData) VideoConfig { return VideoConfig{ @@ -178,8 +201,10 @@ func NewVoice(chatID int64, file RequestFileData) VoiceConfig { // two to ten InputMediaPhoto or InputMediaVideo. func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig { return MediaGroupConfig{ - ChatID: chatID, - Media: files, + BaseChat: BaseChat{ + ChatID: chatID, + }, + Media: files, } } @@ -906,6 +931,36 @@ func NewBotCommandScopeChatMember(chatID, userID int64) BotCommandScope { } } +// NewSetMyDescription allows you to change the bot's description, which is shown in the chat with the bot if the chat is empty. +func NewSetMyDescription(description, languageCode string) SetMyDescriptionConfig { + return SetMyDescriptionConfig{ + Description: description, + LanguageCode: languageCode, + } +} + +// NewGetMyDescription returns the current bot description for the given user language +func NewGetMyDescription(languageCode string) GetMyDescriptionConfig { + return GetMyDescriptionConfig{ + LanguageCode: languageCode, + } +} + +// NewSetMyShortDescription allows you change the bot's short description, which is shown on the bot's profile page and is sent together with the link when users share the bot. +func NewSetMyShortDescription(shortDescription, languageCode string) SetMyShortDescriptionConfig { + return SetMyShortDescriptionConfig{ + ShortDescription: shortDescription, + LanguageCode: languageCode, + } +} + +// NewGetMyShortDescription returns the current bot short description for the given user language. +func NewGetMyShortDescription(languageCode string) GetMyShortDescriptionConfig { + return GetMyShortDescriptionConfig{ + LanguageCode: languageCode, + } +} + // NewGetMyCommandsWithScope allows you to set the registered commands for a // given scope. func NewGetMyCommandsWithScope(scope BotCommandScope) GetMyCommandsConfig { diff --git a/params.go b/params.go index 134f85e4..118af364 100644 --- a/params.go +++ b/params.go @@ -95,3 +95,10 @@ func (p Params) AddFirstValid(key string, args ...interface{}) error { return nil } + +// Merge merges two sets of parameters. Overwrites old fields if present +func (p *Params) Merge(p1 Params) { + for k, v := range p1 { + (*p)[k] = v + } +} \ No newline at end of file diff --git a/types.go b/types.go index 36c174b8..780fd6ef 100644 --- a/types.go +++ b/types.go @@ -187,6 +187,10 @@ type User struct { // // optional IsPremium bool `json:"is_premium,omitempty"` + // AddedToAttachmentMenu true, if this user added the bot to the attachment menu + // + // optional + AddedToAttachmentMenu bool `json:"added_to_attachment_menu,omitempty"` // FirstName user's or bot's first name FirstName string `json:"first_name"` // LastName user's or bot's last name @@ -261,8 +265,22 @@ type Chat struct { // // optional LastName string `json:"last_name,omitempty"` + // IsForum is true if the supergroup chat is a forum (has topics enabled) + // + // optional + IsForum bool `json:"is_forum,omitempty"` // Photo is a chat photo Photo *ChatPhoto `json:"photo"` + // If non-empty, the list of all active chat usernames; + // for private chats, supergroups and channels. Returned only in getChat. + // + // optional + ActiveUsernames []string `json:"active_usernames,omitempty"` + // Custom emoji identifier of emoji status of the other party + // in a private chat. Returned only in getChat. + // + // optional + EmojiStatusCustomEmojiID string `json:"emoji_status_custom_emoji_id,omitempty"` // Bio is the bio of the other party in a private chat. Returned only in // getChat // @@ -274,6 +292,24 @@ type Chat struct { // // optional HasPrivateForwards bool `json:"has_private_forwards,omitempty"` + // HasRestrictedVoiceAndVideoMessages if the privacy settings of the other party + // restrict sending voice and video note messages + // in the private chat. Returned only in getChat. + // + // optional + HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages,omitempty"` + // JoinToSendMessages is true, if users need to join the supergroup + // before they can send messages. + // Returned only in getChat + // + // optional + JoinToSendMessages bool `json:"join_to_send_messages,omitempty"` + // JoinByRequest is true, if all users directly joining the supergroup + // need to be approved by supergroup administrators. + // Returned only in getChat. + // + // optional + JoinByRequest bool `json:"join_by_request,omitempty"` // Description for groups, supergroups and channel chats // // optional @@ -304,6 +340,17 @@ type Chat struct { // // optional MessageAutoDeleteTime int `json:"message_auto_delete_time,omitempty"` + // HasAggressiveAntiSpamEnabled is true if aggressive anti-spam checks are enabled + // in the supergroup. The field is only available to chat administrators. + // Returned only in getChat. + // + // optional + HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled,omitempty"` + // HasHiddenMembers is true if non-administrators can only get + // the list of bots and administrators in the chat. + // + // optional + HasHiddenMembers bool `json:"has_hidden_members,omitempty"` // HasProtectedContent is true if messages from the chat can't be forwarded // to other chats. Returned only in getChat. // @@ -361,6 +408,11 @@ func (c Chat) ChatConfig() ChatConfig { type Message struct { // MessageID is a unique message identifier inside this chat MessageID int `json:"message_id"` + // Unique identifier of a message thread to which the message belongs; + // for supergroups only + // + // optional + MessageThreadID int `json:"message_thread_id,omitempty"` // From is a sender, empty for messages sent to channels; // // optional @@ -404,6 +456,10 @@ type Message struct { // // optional ForwardDate int `json:"forward_date,omitempty"` + // IsTopicMessage true if the message is sent to a forum topic + // + // optional + IsTopicMessage bool `json:"is_topic_message,omitempty"` // IsAutomaticForward is true if the message is a channel post that was // automatically forwarded to the connected discussion group. // @@ -490,6 +546,10 @@ type Message struct { // // optional CaptionEntities []MessageEntity `json:"caption_entities,omitempty"` + // HasSpoiler 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 @@ -594,11 +654,24 @@ type Message struct { // // optional SuccessfulPayment *SuccessfulPayment `json:"successful_payment,omitempty"` + // UserShared is a service message: a user was shared with the bot + // + // optional + UserShared *UserShared `json:"user_shared,omitempty"` + // ChatShared is a service message: a chat was shared with the bot + // + // optional + ChatShared *ChatShared `json:"chat_shared,omitempty"` // ConnectedWebsite is the domain name of the website on which the user has // logged in; // // optional ConnectedWebsite string `json:"connected_website,omitempty"` + // WriteAccessAllowed is a service message: the user allowed the bot + // added to the attachment menu to write messages + // + // optional + WriteAccessAllowed *WriteAccessAllowed `json:"write_access_allowed,omitempty"` // PassportData is a Telegram Passport data; // // optional @@ -608,6 +681,30 @@ type Message struct { // // optional ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered,omitempty"` + // ForumTopicCreated is a service message: forum topic created + // + // optional + ForumTopicCreated *ForumTopicCreated `json:"forum_topic_created,omitempty"` + // ForumTopicClosed is a service message: forum topic edited + // + // optional + ForumTopicEdited *ForumTopicEdited `json:"forum_topic_edited,omitempty"` + // ForumTopicClosed is a service message: forum topic closed + // + // optional + ForumTopicClosed *ForumTopicClosed `json:"forum_topic_closed,omitempty"` + // ForumTopicReopened is a service message: forum topic reopened + // + // optional + ForumTopicReopened *ForumTopicReopened `json:"forum_topic_reopened,omitempty"` + // GeneralForumTopicHidden is a service message: the 'General' forum topic hidden + // + // optional + GeneralForumTopicHidden *GeneralForumTopicHidden `json:"general_forum_topic_hidden,omitempty"` + // GeneralForumTopicUnhidden is a service message: the 'General' forum topic unhidden + // + // optional + GeneralForumTopicUnhidden *GeneralForumTopicUnhidden `json:"general_forum_topic_unhidden,omitempty"` // VideoChatScheduled is a service message: video chat scheduled. // // optional @@ -730,6 +827,7 @@ type MessageEntity struct { // “pre” (monowidth block), // “text_link” (for clickable text URLs), // “text_mention” (for users without usernames) + // “text_mention” (for inline custom emoji stickers) Type string `json:"type"` // Offset in UTF-16 code units to the start of the entity Offset int `json:"offset"` @@ -747,6 +845,10 @@ type MessageEntity struct { // // optional Language string `json:"language,omitempty"` + // CustomEmojiID for “custom_emoji” only, unique identifier of the custom emoji + // + // optional + CustomEmojiID string `json:"custom_emoji_id"` } // ParseURL attempts to parse a URL contained within a MessageEntity. @@ -851,7 +953,7 @@ type Animation struct { // Thumbnail animation thumbnail as defined by sender // // optional - Thumbnail *PhotoSize `json:"thumb,omitempty"` + Thumbnail *PhotoSize `json:"thumbnail,omitempty"` // FileName original animation filename as defined by sender // // optional @@ -863,7 +965,7 @@ type Animation struct { // FileSize file size // // optional - FileSize int `json:"file_size,omitempty"` + FileSize int64 `json:"file_size,omitempty"` } // Audio represents an audio file to be treated as music by the Telegram clients. @@ -896,11 +998,11 @@ type Audio struct { // FileSize file size // // optional - FileSize int `json:"file_size,omitempty"` + FileSize int64 `json:"file_size,omitempty"` // Thumbnail is the album cover to which the music file belongs // // optional - Thumbnail *PhotoSize `json:"thumb,omitempty"` + Thumbnail *PhotoSize `json:"thumbnail,omitempty"` } // Document represents a general file. @@ -915,7 +1017,7 @@ type Document struct { // Thumbnail document thumbnail as defined by sender // // optional - Thumbnail *PhotoSize `json:"thumb,omitempty"` + Thumbnail *PhotoSize `json:"thumbnail,omitempty"` // FileName original filename as defined by sender // // optional @@ -927,7 +1029,7 @@ type Document struct { // FileSize file size // // optional - FileSize int `json:"file_size,omitempty"` + FileSize int64 `json:"file_size,omitempty"` } // Video represents a video file. @@ -948,7 +1050,7 @@ type Video struct { // Thumbnail video thumbnail // // optional - Thumbnail *PhotoSize `json:"thumb,omitempty"` + Thumbnail *PhotoSize `json:"thumbnail,omitempty"` // FileName is the original filename as defined by sender // // optional @@ -960,7 +1062,7 @@ type Video struct { // FileSize file size // // optional - FileSize int `json:"file_size,omitempty"` + FileSize int64 `json:"file_size,omitempty"` } // VideoNote object represents a video message. @@ -978,7 +1080,7 @@ type VideoNote struct { // Thumbnail video thumbnail // // optional - Thumbnail *PhotoSize `json:"thumb,omitempty"` + Thumbnail *PhotoSize `json:"thumbnail,omitempty"` // FileSize file size // // optional @@ -1002,7 +1104,7 @@ type Voice struct { // FileSize file size // // optional - FileSize int `json:"file_size,omitempty"` + FileSize int64 `json:"file_size,omitempty"` } // Contact represents a phone contact. @@ -1181,6 +1283,78 @@ type MessageAutoDeleteTimerChanged struct { MessageAutoDeleteTime int `json:"message_auto_delete_time"` } +// ForumTopicCreated represents a service message about a new forum topic +// created in the chat. +type ForumTopicCreated struct { + // Name is the name of topic + Name string `json:"name"` + // IconColor is the color of the topic icon in RGB format + IconColor int `json:"icon_color"` + // IconCustomEmojiID is the unique identifier of the custom emoji + // shown as the topic icon + // + // optional + IconCustomEmojiID string `json:"icon_custom_emoji_id,omitempty"` +} + +// ForumTopicClosed represents a service message about a forum topic +// closed in the chat. Currently holds no information. +type ForumTopicClosed struct { +} + +// ForumTopicEdited object represents a service message about an edited forum topic. +type ForumTopicEdited struct { + // Name is the new name of the topic, if it was edited + // + // optional + Name string `json:"name,omitempty"` + // IconCustomEmojiID is the new identifier of the custom emoji + // shown as the topic icon, if it was edited; + // an empty string if the icon was removed + // + // optional + IconCustomEmojiID *string `json:"icon_custom_emoji_id,omitempty"` +} + +// ForumTopicReopened represents a service message about a forum topic +// reopened in the chat. Currently holds no information. +type ForumTopicReopened struct { +} + +// GeneralForumTopicHidden represents a service message about General forum topic +// hidden in the chat. Currently holds no information. +type GeneralForumTopicHidden struct { +} + +// GeneralForumTopicUnhidden represents a service message about General forum topic +// unhidden in the chat. Currently holds no information. +type GeneralForumTopicUnhidden struct { +} + +// UserShared object contains information about the user whose identifier +// was shared with the bot using a KeyboardButtonRequestUser button. +type UserShared 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"` +} + +// ChatShared contains information about the chat whose identifier +// was shared with the bot using a KeyboardButtonRequestChat button. +type ChatShared struct { + // RequestID is an indentifier of the request. + RequestID int `json:"request_id"` + // ChatID is an identifier of the shared chat. + ChatID int64 `json:"chat_id"` +} + +// WriteAccessAllowed represents a service message about a user +// allowing a bot added to the attachment menu to write messages. +// Currently holds no information. +type WriteAccessAllowed struct { +} + // VideoChatScheduled represents a service message about a voice chat scheduled // in the chat. type VideoChatScheduled struct { @@ -1234,7 +1408,7 @@ type File struct { // FileSize file size, if known // // optional - FileSize int `json:"file_size,omitempty"` + FileSize int64 `json:"file_size,omitempty"` // FilePath file path // // optional @@ -1259,6 +1433,13 @@ type WebAppInfo struct { type ReplyKeyboardMarkup struct { // Keyboard is an array of button rows, each represented by an Array of KeyboardButton objects Keyboard [][]KeyboardButton `json:"keyboard"` + // IsPersistent requests clients to always show the keyboard + // when the regular keyboard is hidden. + // Defaults to false, in which case the custom keyboard can be hidden + // and opened with a keyboard icon. + // + // optional + IsPersistent bool `json:"is_persistent"` // ResizeKeyboard requests clients to resize the keyboard vertically for optimal fit // (e.g., make the keyboard smaller if there are just two rows of buttons). // Defaults to false, in which case the custom keyboard @@ -1300,6 +1481,20 @@ 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 + // 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"` + // 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. + // Available in private chats only. + // + // optional + RequestChat *KeyboardButtonRequestChat `json:"request_chat,omitempty"` // RequestContact if True, the user's phone number will be sent // as a contact when the button is pressed. // Available in private chats only. @@ -1325,6 +1520,72 @@ type KeyboardButton struct { WebApp *WebAppInfo `json:"web_app,omitempty"` } +// KeyboardButtonRequestUser 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 { + // RequestID is a signed 32-bit identifier of the request. + RequestID int `json:"request_id"` + // UserIsBot pass True to request a bot, + // pass False to request a regular user. + // If not specified, no additional restrictions are applied. + // + // optional + UserIsBot bool `json:"user_is_bot,omitempty"` + // UserIsPremium pass True to request a premium user, + // pass False to request a non-premium user. + // If not specified, no additional restrictions are applied. + // + // optional + UserIsPremium bool `json:"user_is_premium,omitempty"` +} + +// KeyboardButtonRequestChat defines the criteria used to request +// a suitable chat. The identifier of the selected chat will be shared +// with the bot when the corresponding button is pressed. +type KeyboardButtonRequestChat struct { + // RequestID is a signed 32-bit identifier of the request. + RequestID int `json:"request_id"` + // ChatIsChannel pass True to request a channel chat, + // pass False to request a group or a supergroup chat. + ChatIsChannel bool `json:"chat_is_channel"` + // ChatIsForum pass True to request a forum supergroup, + // pass False to request a non-forum chat. + // If not specified, no additional restrictions are applied. + // + // optional + ChatIsForum bool `json:"chat_is_forum,omitempty"` + // ChatHasUsername pass True to request a supergroup or a channel with a username, + // pass False to request a chat without a username. + // If not specified, no additional restrictions are applied. + // + // optional + ChatHasUsername bool `json:"chat_has_username,omitempty"` + // ChatIsCreated pass True to request a chat owned by the user. + // Otherwise, no additional restrictions are applied. + // + // optional + ChatIsCreated bool `json:"chat_is_created,omitempty"` + // UserAdministratorRights is a JSON-serialized object listing + // the required administrator rights of the user in the chat. + // If not specified, no additional restrictions are applied. + // + // optional + UserAdministratorRights *ChatAdministratorRights `json:"user_administrator_rights,omitempty"` + // BotAdministratorRights is a JSON-serialized object listing + // the required administrator rights of the bot in the chat. + // The rights must be a subset of user_administrator_rights. + // If not specified, no additional restrictions are applied. + // + // optional + BotAdministratorRights *ChatAdministratorRights `json:"bot_administrator_rights,omitempty"` + // BotIsMember pass True to request a chat with the bot as a member. + // Otherwise, no additional restrictions are applied. + // + // optional + BotIsMember bool `json:"bot_is_member,omitempty"` +} + // KeyboardButtonPollType represents type of poll, which is allowed to // be created and sent when the corresponding button is pressed. type KeyboardButtonPollType struct { @@ -1591,6 +1852,7 @@ type ChatAdministratorRights struct { CanPostMessages bool `json:"can_post_messages"` CanEditMessages bool `json:"can_edit_messages"` CanPinMessages bool `json:"can_pin_messages"` + CanManageTopics bool `json:"can_manage_topics"` } // ChatMember contains information about one member of a chat. @@ -1683,6 +1945,12 @@ type ChatMember struct { // // optional CanPinMessages bool `json:"can_pin_messages,omitempty"` + // CanManageTopics administrators and restricted only. + // True, if the user is allowed to create, rename, + // close, and reopen forum topics; supergroups only + // + // optional + CanManageTopics bool `json:"can_manage_topics,omitempty"` // IsMember is true, if the user is a member of the chat at the moment of // the request IsMember bool `json:"is_member"` @@ -1690,11 +1958,36 @@ type ChatMember struct { // // optional CanSendMessages bool `json:"can_send_messages,omitempty"` - // CanSendMediaMessages restricted only. - // True, if the user is allowed to send text messages, contacts, locations and venues + // CanSendAudios restricted only. + // True, if the user is allowed to send audios + // + // optional + CanSendAudios bool + // CanSendDocuments restricted only. + // True, if the user is allowed to send documents + // + // optional + CanSendDocuments bool + // CanSendPhotos is restricted only. + // True, if the user is allowed to send photos // // optional - CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"` + CanSendPhotos bool + // CanSendVideos restricted only. + // True, if the user is allowed to send videos + // + // optional + CanSendVideos bool + // CanSendVideoNotes restricted only. + // True, if the user is allowed to send video notes + // + // optional + CanSendVideoNotes bool + // CanSendVoiceNotes restricted only. + // True, if the user is allowed to send voice notes + // + // optional + CanSendVoiceNotes bool // CanSendPolls restricted only. // True, if the user is allowed to send polls // @@ -1725,6 +2018,27 @@ func (chat ChatMember) HasLeft() bool { return chat.Status == "left" } // WasKicked returns if the ChatMember was kicked from the chat. func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" } +// SetCanSendMediaMessages is a method to replace field "can_send_media_messages". +// It sets CanSendAudio, CanSendDocuments, CanSendPhotos, CanSendVideos, +// CanSendVideoNotes, CanSendVoiceNotes to passed value. +func (chat *ChatMember) SetCanSendMediaMessages(b bool) { + chat.CanSendAudios = b + chat.CanSendDocuments = b + chat.CanSendPhotos = b + chat.CanSendVideos = b + chat.CanSendVideoNotes = b + chat.CanSendVoiceNotes = b +} + +// CanSendMediaMessages method to replace field "can_send_media_messages". +// It returns true if CanSendAudio and CanSendDocuments and CanSendPhotos and CanSendVideos and +// CanSendVideoNotes and CanSendVoiceNotes are true. +func (chat *ChatMember) CanSendMediaMessages() bool { + return chat.CanSendAudios && chat.CanSendDocuments && + chat.CanSendPhotos && chat.CanSendVideos && + chat.CanSendVideoNotes && chat.CanSendVoiceNotes +} + // ChatMemberUpdated represents changes in the status of a chat member. type ChatMemberUpdated struct { // Chat the user belongs to. @@ -1750,6 +2064,8 @@ type ChatJoinRequest struct { Chat Chat `json:"chat"` // User that sent the join request. From User `json:"from"` + // UserChatID identifier of a private chat with the user who sent the join request. + UserChatID int64 `json:"user_chat_id"` // Date the request was sent in Unix time. Date int `json:"date"` // Bio of the user. @@ -1770,12 +2086,30 @@ type ChatPermissions struct { // // optional CanSendMessages bool `json:"can_send_messages,omitempty"` - // CanSendMediaMessages is true, if the user is allowed to send audios, - // documents, photos, videos, video notes and voice notes, implies - // can_send_messages + // CanSendAudios is true, if the user is allowed to send audios // // optional - CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"` + CanSendAudios bool + // CanSendDocuments is true, if the user is allowed to send documents + // + // optional + CanSendDocuments bool + // CanSendPhotos is true, if the user is allowed to send photos + // + // optional + CanSendPhotos bool + // CanSendVideos is true, if the user is allowed to send videos + // + // optional + CanSendVideos bool + // CanSendVideoNotes is true, if the user is allowed to send video notes + // + // optional + CanSendVideoNotes bool + // CanSendVoiceNotes is true, if the user is allowed to send voice notes + // + // optional + CanSendVoiceNotes bool // CanSendPolls is true, if the user is allowed to send polls, implies // can_send_messages // @@ -1806,6 +2140,32 @@ type ChatPermissions struct { // // optional CanPinMessages bool `json:"can_pin_messages,omitempty"` + // CanManageTopics is true, if the user is allowed to create forum topics. + // If omitted defaults to the value of can_pin_messages + // + // optional + CanManageTopics bool `json:"can_manage_topics,omitempty"` +} + +// SetCanSendMediaMessages is a method to replace field "can_send_media_messages". +// It sets CanSendAudio, CanSendDocuments, CanSendPhotos, CanSendVideos, +// CanSendVideoNotes, CanSendVoiceNotes to passed value. +func (c *ChatPermissions) SetCanSendMediaMessages(b bool) { + c.CanSendAudios = b + c.CanSendDocuments = b + c.CanSendPhotos = b + c.CanSendVideos = b + c.CanSendVideoNotes = b + c.CanSendVoiceNotes = b +} + +// CanSendMediaMessages method to replace field "can_send_media_messages". +// It returns true if CanSendAudio and CanSendDocuments and CanSendPhotos and CanSendVideos and +// CanSendVideoNotes and CanSendVoiceNotes are true. +func (c *ChatPermissions) CanSendMediaMessages() bool { + return c.CanSendAudios && c.CanSendDocuments && + c.CanSendPhotos && c.CanSendVideos && + c.CanSendVideoNotes && c.CanSendVoiceNotes } // ChatLocation represents a location to which a chat is connected. @@ -1818,6 +2178,21 @@ type ChatLocation struct { Address string `json:"address"` } +// ForumTopic represents a forum topic. +type ForumTopic struct { + // MessageThreadID is the unique identifier of the forum topic + MessageThreadID int `json:"message_thread_id"` + // Name is the name of the topic + Name string `json:"name"` + // IconColor is the color of the topic icon in RGB format + IconColor int `json:"icon_color"` + // IconCustomEmojiID is the unique identifier of the custom emoji + // shown as the topic icon + // + // optional + IconCustomEmojiID string `json:"icon_custom_emoji_id,omitempty"` +} + // BotCommand represents a bot command. type BotCommand struct { // Command text of the command, 1-32 characters. @@ -1837,6 +2212,16 @@ type BotCommandScope struct { UserID int64 `json:"user_id,omitempty"` } +// BotDescription represents the bot's description. +type BotDescription struct { + Description string `json:"description"` +} + +// BotShortDescription represents the bot's short description +type BotShortDescription struct { + ShortDescription string `json:"short_description"` +} + // 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: @@ -1891,6 +2276,10 @@ type BaseInputMedia struct { // // optional CaptionEntities []MessageEntity `json:"caption_entities,omitempty"` + // HasSpoiler pass True, if the photo needs to be covered with a spoiler animation + // + // optional + HasSpoiler bool `json:"has_spoiler,omitempty"` } // InputMediaPhoto is a photo to send as part of a media group. @@ -1905,7 +2294,7 @@ type InputMediaVideo struct { // the file is supported server-side. // // optional - Thumb RequestFileData `json:"thumb,omitempty"` + Thumb RequestFileData `json:"thumbnail,omitempty"` // Width video width // // optional @@ -1922,6 +2311,10 @@ type InputMediaVideo struct { // // optional SupportsStreaming bool `json:"supports_streaming,omitempty"` + // HasSpoiler pass True, if the video needs to be covered with a spoiler animation + // + // optional + HasSpoiler bool `json:"has_spoiler,omitempty"` } // InputMediaAnimation is an animation to send as part of a media group. @@ -1931,7 +2324,7 @@ type InputMediaAnimation struct { // the file is supported server-side. // // optional - Thumb RequestFileData `json:"thumb,omitempty"` + Thumb RequestFileData `json:"thumbnail,omitempty"` // Width video width // // optional @@ -1944,6 +2337,10 @@ type InputMediaAnimation struct { // // optional Duration int `json:"duration,omitempty"` + // HasSpoiler pass True, if the photo needs to be covered with a spoiler animation + // + // optional + HasSpoiler bool `json:"has_spoiler,omitempty"` } // InputMediaAudio is an audio to send as part of a media group. @@ -1953,7 +2350,7 @@ type InputMediaAudio struct { // the file is supported server-side. // // optional - Thumb RequestFileData `json:"thumb,omitempty"` + Thumb RequestFileData `json:"thumbnail,omitempty"` // Duration of the audio in seconds // // optional @@ -1975,7 +2372,7 @@ type InputMediaDocument struct { // the file is supported server-side. // // optional - Thumb RequestFileData `json:"thumb,omitempty"` + Thumb RequestFileData `json:"thumbnail,omitempty"` // DisableContentTypeDetection disables automatic server-side content type // detection for files uploaded using multipart/form-data. Always true, if // the document is sent as part of an album @@ -1984,6 +2381,13 @@ type InputMediaDocument struct { DisableContentTypeDetection bool `json:"disable_content_type_detection,omitempty"` } +// Constant values for sticker types +const ( + StickerTypeRegular = "regular" + StickerTypeMask = "mask" + StickerTypeCustomEmoji = "custom_emoji" +) + // Sticker represents a sticker. type Sticker struct { // FileID is an identifier for this file, which can be used to download or @@ -1993,6 +2397,10 @@ type Sticker struct { // which is supposed to be the same over time and for different bots. // Can't be used to download or reuse the file. FileUniqueID string `json:"file_unique_id"` + // Type is a type of the sticker, currently one of “regular”, + // “mask”, “custom_emoji”. The type of the sticker is independent + // from its format, which is determined by the fields is_animated and is_video. + Type string `json:"type"` // Width sticker width Width int `json:"width"` // Height sticker height @@ -2008,7 +2416,7 @@ type Sticker struct { // Thumbnail sticker thumbnail in the .WEBP or .JPG format // // optional - Thumbnail *PhotoSize `json:"thumb,omitempty"` + Thumbnail *PhotoSize `json:"thumbnail,omitempty"` // Emoji associated with the sticker // // optional @@ -2030,12 +2438,31 @@ type Sticker struct { // // optional CustomEmojiID string `json:"custom_emoji_id,omitempty"` + // NeedsRepainting True, if the sticker must be repainted to a text color in messages, the color of the Telegram Premium badge in emoji status, white color on chat photos, or another appropriate color in other places + // + //optional + NeedsRepainting bool `json:"needs_reainting,omitempty"` // FileSize // // optional FileSize int `json:"file_size,omitempty"` } +// IsRegular returns if the Sticker is regular +func (s Sticker) IsRegular() bool { + return s.Type == StickerTypeRegular +} + +// IsMask returns if the Sticker is mask +func (s Sticker) IsMask() bool { + return s.Type == StickerTypeMask +} + +// IsCustomEmoji returns if the Sticker is custom emoji +func (s Sticker) IsCustomEmoji() bool { + return s.Type == StickerTypeCustomEmoji +} + // StickerSet represents a sticker set. type StickerSet struct { // Name sticker set name @@ -2049,11 +2476,28 @@ type StickerSet struct { // IsVideo true, if the sticker set contains video stickers IsVideo bool `json:"is_video"` // ContainsMasks true, if the sticker set contains masks + // + // deprecated. Use sticker_type instead ContainsMasks bool `json:"contains_masks"` // Stickers list of all set stickers Stickers []Sticker `json:"stickers"` // Thumb is the sticker set thumbnail in the .WEBP or .TGS format - Thumbnail *PhotoSize `json:"thumb"` + Thumbnail *PhotoSize `json:"thumbnail"` +} + +// IsRegular returns if the StickerSet is regular +func (s StickerSet) IsRegular() bool { + return s.StickerType == StickerTypeRegular +} + +// IsMask returns if the StickerSet is mask +func (s StickerSet) IsMask() bool { + return s.StickerType == StickerTypeMask +} + +// IsCustomEmoji returns if the StickerSet is custom emoji +func (s StickerSet) IsCustomEmoji() bool { + return s.StickerType == StickerTypeCustomEmoji } // MaskPosition describes the position on faces where a mask should be placed @@ -2074,6 +2518,22 @@ type MaskPosition struct { Scale float64 `json:"scale"` } +// InputSticker describes a sticker to be added to a sticker set. +type InputSticker struct { + // The added sticker. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, upload a new one using multipart/form-data, or pass “attach://” to upload a new one using multipart/form-data under name. Animated and video stickers can't be uploaded via HTTP URL. + Sticker RequestFile `json:"sticker"` + // List of 1-20 emoji associated with the sticker + EmojiList []string `json:"emoji_list"` + // Position where the mask should be placed on faces. For “mask” stickers only. + // + // optional + MaskPosition *MaskPosition `json:"mask_position"` + // List of 0-20 search keywords for the sticker with total length of up to 64 characters. For “regular” and “custom_emoji” stickers only. + // + // optional + Keywords []string `json:"keywords"` +} + // Game represents a game. Use BotFather to create and edit games, their short // names will act as unique identifiers. type Game struct { @@ -2493,15 +2953,15 @@ type InlineQueryResultArticle struct { // ThumbURL url of the thumbnail for the result // // optional - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // ThumbWidth thumbnail width // // optional - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // ThumbHeight thumbnail height // // optional - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // InlineQueryResultAudio is an inline query response audio. @@ -2557,9 +3017,9 @@ type InlineQueryResultContact struct { VCard string `json:"vcard"` ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` InputMessageContent interface{} `json:"input_message_content,omitempty"` - ThumbURL string `json:"thumb_url"` - ThumbWidth int `json:"thumb_width"` - ThumbHeight int `json:"thumb_height"` + ThumbURL string `json:"thumbnail_url"` + ThumbWidth int `json:"thumbnail_width"` + ThumbHeight int `json:"thumbnail_height"` } // InlineQueryResultGame is an inline query response game. @@ -2607,15 +3067,15 @@ type InlineQueryResultDocument struct { // ThumbURL url of the thumbnail (jpeg only) for the file // // optional - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // ThumbWidth thumbnail width // // optional - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // ThumbHeight thumbnail height // // optional - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // InlineQueryResultGIF is an inline query response GIF. @@ -2627,7 +3087,9 @@ type InlineQueryResultGIF struct { // URL a valid URL for the GIF file. File size must not exceed 1MB. URL string `json:"gif_url"` // ThumbURL url of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result. - ThumbURL string `json:"thumb_url"` + ThumbURL string `json:"thumbnail_url"` + // MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or “video/mp4”. Defaults to “image/jpeg” + ThumbMimeType string `json:"thumbnail_mime_type,omitempty"` // Width of the GIF // // optional @@ -2713,15 +3175,15 @@ type InlineQueryResultLocation struct { // ThumbURL url of the thumbnail for the result // // optional - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // ThumbWidth thumbnail width // // optional - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // ThumbHeight thumbnail height // // optional - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF. @@ -2745,7 +3207,9 @@ type InlineQueryResultMPEG4GIF struct { // optional Duration int `json:"mpeg4_duration,omitempty"` // ThumbURL url of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result. - ThumbURL string `json:"thumb_url"` + ThumbURL string `json:"thumbnail_url"` + // MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or “video/mp4”. Defaults to “image/jpeg” + ThumbMimeType string `json:"thumbnail_mime_type,omitempty"` // Title for the result // // optional @@ -2797,7 +3261,7 @@ type InlineQueryResultPhoto struct { // ThumbURL url of the thumbnail for the photo. // // optional - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Title for the result // // optional @@ -2873,15 +3337,15 @@ type InlineQueryResultVenue struct { // ThumbURL url of the thumbnail for the result // // optional - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // ThumbWidth thumbnail width // // optional - ThumbWidth int `json:"thumb_width,omitempty"` + ThumbWidth int `json:"thumbnail_width,omitempty"` // ThumbHeight thumbnail height // // optional - ThumbHeight int `json:"thumb_height,omitempty"` + ThumbHeight int `json:"thumbnail_height,omitempty"` } // InlineQueryResultVideo is an inline query response video. @@ -2897,7 +3361,7 @@ type InlineQueryResultVideo struct { // // ThumbURL url of the thumbnail (jpeg only) for the video // optional - ThumbURL string `json:"thumb_url,omitempty"` + ThumbURL string `json:"thumbnail_url,omitempty"` // Title for the result Title string `json:"title"` // Caption of the video to be sent, 0-1024 characters after entities parsing diff --git a/types_test.go b/types_test.go index 0c6ba4ab..e4e3da16 100644 --- a/types_test.go +++ b/types_test.go @@ -347,6 +347,28 @@ var ( _ Chattable = VideoNoteConfig{} _ Chattable = VoiceConfig{} _ Chattable = WebhookConfig{} + _ Chattable = CreateForumTopicConfig{} + _ Chattable = EditForumTopicConfig{} + _ Chattable = CloseForumTopicConfig{} + _ Chattable = ReopenForumTopicConfig{} + _ Chattable = DeleteForumTopicConfig{} + _ Chattable = UnpinAllForumTopicMessagesConfig{} + _ Chattable = GetForumTopicIconStickersConfig{} + _ Chattable = EditGeneralForumTopicConfig{} + _ Chattable = CloseGeneralForumTopicConfig{} + _ Chattable = ReopenGeneralForumTopicConfig{} + _ Chattable = HideGeneralForumTopicConfig{} + _ Chattable = UnhideGeneralForumTopicConfig{} + _ Chattable = SetCustomEmojiStickerSetThumbnalConfig{} + _ Chattable = SetStickerSetTitleConfig{} + _ Chattable = DeleteStickerSetConfig{} + _ Chattable = SetStickerEmojiListConfig{} + _ Chattable = SetStickerKeywordsConfig{} + _ Chattable = SetStickerMaskPositionConfig{} + _ Chattable = GetMyDescriptionConfig{} + _ Chattable = SetMyDescriptionConfig{} + _ Chattable = GetMyShortDescriptionConfig{} + _ Chattable = SetMyShortDescriptionConfig{} ) // Ensure all Fileable types are correct.