From 17344a80d13e92272888e1f3a82c3f48b1f1e698 Mon Sep 17 00:00:00 2001 From: Paul Larsen Date: Mon, 6 May 2024 16:52:49 +0200 Subject: [PATCH 1/5] Regenerate for Bot API 7.3 --- gen_helpers.go | 2 +- gen_methods.go | 67 +-- gen_types.go | 1064 +++++++++++++++++++++++++++++++++++++----------- spec_commit | 2 +- 4 files changed, 881 insertions(+), 254 deletions(-) diff --git a/gen_helpers.go b/gen_helpers.go index d3623ca..1c1bcd3 100755 --- a/gen_helpers.go +++ b/gen_helpers.go @@ -59,7 +59,7 @@ func (c Chat) ExportInviteLink(b *Bot, opts *ExportChatInviteLinkOpts) (string, } // Get Helper method for Bot.GetChat. -func (c Chat) Get(b *Bot, opts *GetChatOpts) (*Chat, error) { +func (c Chat) Get(b *Bot, opts *GetChatOpts) (*ChatFullInfo, error) { return b.GetChat(c.Id, opts) } diff --git a/gen_methods.go b/gen_methods.go index 555c4da..d414e3d 100755 --- a/gen_methods.go +++ b/gen_methods.go @@ -476,7 +476,7 @@ type CopyMessageOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -1373,6 +1373,8 @@ type EditMessageLiveLocationOpts struct { MessageId int64 // Required if chat_id and message_id are not specified. Identifier of the inline message InlineMessageId string + // New period in seconds during which the location can be updated, starting from the message send date. If 0x7FFFFFFF is specified, then the location can be updated forever. Otherwise, the new value must not exceed the current live_period by more than a day, and the live location expiration date must remain within the next 90 days. If not specified, then live_period remains unchanged + LivePeriod *int64 // The radius of uncertainty for the location, measured in meters; 0-1500 HorizontalAccuracy float64 // Direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. @@ -1403,6 +1405,9 @@ func (bot *Bot) EditMessageLiveLocation(latitude float64, longitude float64, opt v["message_id"] = strconv.FormatInt(opts.MessageId, 10) } v["inline_message_id"] = opts.InlineMessageId + if opts.LivePeriod != nil { + v["live_period"] = strconv.FormatInt(*opts.LivePeriod, 10) + } if opts.HorizontalAccuracy != 0.0 { v["horizontal_accuracy"] = strconv.FormatFloat(opts.HorizontalAccuracy, 'f', -1, 64) } @@ -1806,10 +1811,10 @@ type GetChatOpts struct { // GetChat (https://core.telegram.org/bots/api#getchat) // -// Use this method to get up to date information about the chat. Returns a Chat object on success. +// Use this method to get up-to-date information about the chat. Returns a ChatFullInfo object on success. // - chatId (type int64): Unique identifier for the target chat or username of the target supergroup or channel (in the format @channelusername) // - opts (type GetChatOpts): All optional parameters. -func (bot *Bot) GetChat(chatId int64, opts *GetChatOpts) (*Chat, error) { +func (bot *Bot) GetChat(chatId int64, opts *GetChatOpts) (*ChatFullInfo, error) { v := map[string]string{} v["chat_id"] = strconv.FormatInt(chatId, 10) @@ -1823,7 +1828,7 @@ func (bot *Bot) GetChat(chatId int64, opts *GetChatOpts) (*Chat, error) { return nil, err } - var c Chat + var c ChatFullInfo return &c, json.Unmarshal(r, &c) } @@ -2599,7 +2604,7 @@ type PromoteChatMemberOpts struct { CanInviteUsers bool // Pass True if the administrator can post stories to the chat CanPostStories bool - // Pass True if the administrator can edit stories posted by other users + // Pass True if the administrator can edit stories posted by other users, post stories to the chat page, pin chat stories, and access the chat's story archive CanEditStories bool // Pass True if the administrator can delete stories posted by other users CanDeleteStories bool @@ -2863,7 +2868,7 @@ type SendAnimationOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3003,7 +3008,7 @@ type SendAudioOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3171,7 +3176,7 @@ type SendContactOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3242,7 +3247,7 @@ type SendDiceOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3316,7 +3321,7 @@ type SendDocumentOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3433,7 +3438,7 @@ type SendGameOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. Not supported for messages sent on behalf of a business account. + // A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. ReplyMarkup InlineKeyboardMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3627,7 +3632,7 @@ type SendLocationOpts struct { MessageThreadId int64 // The radius of uncertainty for the location, measured in meters; 0-1500 HorizontalAccuracy float64 - // Period in seconds for which the location will be updated (see Live Locations, should be between 60 and 86400. + // Period in seconds during which the location will be updated (see Live Locations, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. LivePeriod int64 // For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. Heading int64 @@ -3639,7 +3644,7 @@ type SendLocationOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3795,7 +3800,7 @@ type SendMessageOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3883,7 +3888,7 @@ type SendPhotoOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -3973,6 +3978,10 @@ type SendPollOpts struct { BusinessConnectionId string // Unique identifier for the target message thread (topic) of the forum; for forum supergroups only MessageThreadId int64 + // Mode for parsing entities in the question. See formatting options for more details. Currently, only custom emoji entities are allowed + QuestionParseMode string + // A JSON-serialized list of special entities that appear in the poll question. It can be specified instead of question_parse_mode + QuestionEntities []MessageEntity // True, if the poll needs to be anonymous, defaults to True IsAnonymous bool // Poll type, "quiz" or "regular", defaults to "regular" @@ -3985,7 +3994,7 @@ type SendPollOpts struct { Explanation string // Mode for parsing entities in the explanation. See formatting options for more details. ExplanationParseMode string - // A JSON-serialized list of special entities that appear in the poll explanation, which can be specified instead of parse_mode + // A JSON-serialized list of special entities that appear in the poll explanation. It can be specified instead of explanation_parse_mode ExplanationEntities []MessageEntity // Amount of time in seconds the poll will be active after creation, 5-600. Can't be used together with close_date. OpenPeriod int64 @@ -3999,7 +4008,7 @@ type SendPollOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -4010,9 +4019,9 @@ type SendPollOpts struct { // Use this method to send a native poll. On success, the sent Message is returned. // - chatId (type int64): Unique identifier for the target chat or username of the target channel (in the format @channelusername) // - question (type string): Poll question, 1-300 characters -// - options (type []string): A JSON-serialized list of answer options, 2-10 strings 1-100 characters each +// - options (type []InputPollOption): A JSON-serialized list of 2-10 answer options // - opts (type SendPollOpts): All optional parameters. -func (bot *Bot) SendPoll(chatId int64, question string, options []string, opts *SendPollOpts) (*Message, error) { +func (bot *Bot) SendPoll(chatId int64, question string, options []InputPollOption, opts *SendPollOpts) (*Message, error) { v := map[string]string{} v["chat_id"] = strconv.FormatInt(chatId, 10) v["question"] = question @@ -4028,6 +4037,14 @@ func (bot *Bot) SendPoll(chatId int64, question string, options []string, opts * if opts.MessageThreadId != 0 { v["message_thread_id"] = strconv.FormatInt(opts.MessageThreadId, 10) } + v["question_parse_mode"] = opts.QuestionParseMode + if opts.QuestionEntities != nil { + bs, err := json.Marshal(opts.QuestionEntities) + if err != nil { + return nil, fmt.Errorf("failed to marshal field question_entities: %w", err) + } + v["question_entities"] = string(bs) + } v["is_anonymous"] = strconv.FormatBool(opts.IsAnonymous) v["type"] = opts.Type v["allows_multiple_answers"] = strconv.FormatBool(opts.AllowsMultipleAnswers) @@ -4097,7 +4114,7 @@ type SendStickerOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -4192,7 +4209,7 @@ type SendVenueOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -4285,7 +4302,7 @@ type SendVideoOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -4418,7 +4435,7 @@ type SendVideoNoteOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -4539,7 +4556,7 @@ type SendVoiceOpts struct { ProtectContent bool // Description of the message to reply to ReplyParameters *ReplyParameters - // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. + // Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user ReplyMarkup ReplyMarkup // RequestOpts are an additional optional field to configure timeouts for individual requests RequestOpts *RequestOpts @@ -4547,7 +4564,7 @@ type SendVoiceOpts struct { // SendVoice (https://core.telegram.org/bots/api#sendvoice) // -// Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. +// Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .OGG file encoded with OPUS, or in .MP3 format, or in .M4A format (other formats may be sent as Audio or Document). On success, the sent Message is returned. Bots can currently send voice messages of up to 50 MB in size, this limit may be changed in the future. // - chatId (type int64): Unique identifier for the target chat or username of the target channel (in the format @channelusername) // - voice (type InputFile): Audio file to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More information on Sending Files: https://core.telegram.org/bots/api#sending-files // - opts (type SendVoiceOpts): All optional parameters. diff --git a/gen_types.go b/gen_types.go index db6004b..864b525 100755 --- a/gen_types.go +++ b/gen_types.go @@ -70,7 +70,533 @@ type Audio struct { Thumbnail *PhotoSize `json:"thumbnail,omitempty"` } +// BackgroundFill (https://core.telegram.org/bots/api#backgroundfill) +// +// This object describes the way a background is filled based on the selected colors. Currently, it can be one of +// - BackgroundFillSolid +// - BackgroundFillGradient +// - BackgroundFillFreeformGradient +type BackgroundFill interface { + GetType() string + // MergeBackgroundFill returns a MergedBackgroundFill struct to simplify working with complex telegram types in a non-generic world. + MergeBackgroundFill() MergedBackgroundFill + // backgroundFill exists to avoid external types implementing this interface. + backgroundFill() +} + +// Ensure that all subtypes correctly implement the parent interface. +var ( + _ BackgroundFill = BackgroundFillSolid{} + _ BackgroundFill = BackgroundFillGradient{} + _ BackgroundFill = BackgroundFillFreeformGradient{} +) + +// MergedBackgroundFill is a helper type to simplify interactions with the various BackgroundFill subtypes. +type MergedBackgroundFill struct { + // Type of the background fill + Type string `json:"type"` + // Optional. The color of the background fill in the RGB24 format (Only for solid) + Color int64 `json:"color,omitempty"` + // Optional. Top color of the gradient in the RGB24 format (Only for gradient) + TopColor int64 `json:"top_color,omitempty"` + // Optional. Bottom color of the gradient in the RGB24 format (Only for gradient) + BottomColor int64 `json:"bottom_color,omitempty"` + // Optional. Clockwise rotation angle of the background fill in degrees; 0-359 (Only for gradient) + RotationAngle int64 `json:"rotation_angle,omitempty"` + // Optional. A list of the 3 or 4 base colors that are used to generate the freeform gradient in the RGB24 format (Only for freeform_gradient) + Colors []int64 `json:"colors,omitempty"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v MergedBackgroundFill) GetType() string { + return v.Type +} + +// MergedBackgroundFill.backgroundFill is a dummy method to avoid interface implementation. +func (v MergedBackgroundFill) backgroundFill() {} + +// MergeBackgroundFill returns a MergedBackgroundFill struct to simplify working with types in a non-generic world. +func (v MergedBackgroundFill) MergeBackgroundFill() MergedBackgroundFill { + return v +} + +// BackgroundFillFreeformGradient (https://core.telegram.org/bots/api#backgroundfillfreeformgradient) +// +// The background is a freeform gradient that rotates after every message in the chat. +type BackgroundFillFreeformGradient struct { + // A list of the 3 or 4 base colors that are used to generate the freeform gradient in the RGB24 format + Colors []int64 `json:"colors,omitempty"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundFillFreeformGradient) GetType() string { + return "freeform_gradient" +} + +// MergeBackgroundFill returns a MergedBackgroundFill struct to simplify working with types in a non-generic world. +func (v BackgroundFillFreeformGradient) MergeBackgroundFill() MergedBackgroundFill { + return MergedBackgroundFill{ + Type: "freeform_gradient", + Colors: v.Colors, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundFillFreeformGradient) MarshalJSON() ([]byte, error) { + type alias BackgroundFillFreeformGradient + a := struct { + Type string `json:"type"` + alias + }{ + Type: "freeform_gradient", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundFillFreeformGradient.backgroundFill is a dummy method to avoid interface implementation. +func (v BackgroundFillFreeformGradient) backgroundFill() {} + +// BackgroundFillGradient (https://core.telegram.org/bots/api#backgroundfillgradient) +// +// The background is a gradient fill. +type BackgroundFillGradient struct { + // Top color of the gradient in the RGB24 format + TopColor int64 `json:"top_color"` + // Bottom color of the gradient in the RGB24 format + BottomColor int64 `json:"bottom_color"` + // Clockwise rotation angle of the background fill in degrees; 0-359 + RotationAngle int64 `json:"rotation_angle"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundFillGradient) GetType() string { + return "gradient" +} + +// MergeBackgroundFill returns a MergedBackgroundFill struct to simplify working with types in a non-generic world. +func (v BackgroundFillGradient) MergeBackgroundFill() MergedBackgroundFill { + return MergedBackgroundFill{ + Type: "gradient", + TopColor: v.TopColor, + BottomColor: v.BottomColor, + RotationAngle: v.RotationAngle, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundFillGradient) MarshalJSON() ([]byte, error) { + type alias BackgroundFillGradient + a := struct { + Type string `json:"type"` + alias + }{ + Type: "gradient", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundFillGradient.backgroundFill is a dummy method to avoid interface implementation. +func (v BackgroundFillGradient) backgroundFill() {} + +// BackgroundFillSolid (https://core.telegram.org/bots/api#backgroundfillsolid) +// +// The background is filled using the selected color. +type BackgroundFillSolid struct { + // The color of the background fill in the RGB24 format + Color int64 `json:"color"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundFillSolid) GetType() string { + return "solid" +} + +// MergeBackgroundFill returns a MergedBackgroundFill struct to simplify working with types in a non-generic world. +func (v BackgroundFillSolid) MergeBackgroundFill() MergedBackgroundFill { + return MergedBackgroundFill{ + Type: "solid", + Color: v.Color, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundFillSolid) MarshalJSON() ([]byte, error) { + type alias BackgroundFillSolid + a := struct { + Type string `json:"type"` + alias + }{ + Type: "solid", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundFillSolid.backgroundFill is a dummy method to avoid interface implementation. +func (v BackgroundFillSolid) backgroundFill() {} + +// BackgroundType (https://core.telegram.org/bots/api#backgroundtype) +// +// This object describes the type of a background. Currently, it can be one of +// - BackgroundTypeFill +// - BackgroundTypeWallpaper +// - BackgroundTypePattern +// - BackgroundTypeChatTheme +type BackgroundType interface { + GetType() string + // MergeBackgroundType returns a MergedBackgroundType struct to simplify working with complex telegram types in a non-generic world. + MergeBackgroundType() MergedBackgroundType + // backgroundType exists to avoid external types implementing this interface. + backgroundType() +} + +// Ensure that all subtypes correctly implement the parent interface. +var ( + _ BackgroundType = BackgroundTypeFill{} + _ BackgroundType = BackgroundTypeWallpaper{} + _ BackgroundType = BackgroundTypePattern{} + _ BackgroundType = BackgroundTypeChatTheme{} +) + +// MergedBackgroundType is a helper type to simplify interactions with the various BackgroundType subtypes. +type MergedBackgroundType struct { + // Type of the background + Type string `json:"type"` + // Optional. The background fill (Only for fill, pattern) + Fill BackgroundFill `json:"fill,omitempty"` + // Optional. Dimming of the background in dark themes, as a percentage; 0-100 (Only for fill, wallpaper) + DarkThemeDimming int64 `json:"dark_theme_dimming,omitempty"` + // Optional. Document with the wallpaper (Only for wallpaper, pattern) + Document *Document `json:"document,omitempty"` + // Optional. True, if the wallpaper is downscaled to fit in a 450x450 square and then box-blurred with radius 12 (Only for wallpaper) + IsBlurred bool `json:"is_blurred,omitempty"` + // Optional. True, if the background moves slightly when the device is tilted (Only for wallpaper, pattern) + IsMoving bool `json:"is_moving,omitempty"` + // Optional. Intensity of the pattern when it is shown above the filled background; 0-100 (Only for pattern) + Intensity int64 `json:"intensity,omitempty"` + // Optional. True, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only (Only for pattern) + IsInverted bool `json:"is_inverted,omitempty"` + // Optional. Name of the chat theme, which is usually an emoji (Only for chat_theme) + ThemeName string `json:"theme_name,omitempty"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v MergedBackgroundType) GetType() string { + return v.Type +} + +// MergedBackgroundType.backgroundType is a dummy method to avoid interface implementation. +func (v MergedBackgroundType) backgroundType() {} + +// MergeBackgroundType returns a MergedBackgroundType struct to simplify working with types in a non-generic world. +func (v MergedBackgroundType) MergeBackgroundType() MergedBackgroundType { + return v +} + +// unmarshalBackgroundTypeArray is a JSON unmarshalling helper which allows unmarshalling an array of interfaces +// using unmarshalBackgroundType. +func unmarshalBackgroundTypeArray(d json.RawMessage) ([]BackgroundType, error) { + if len(d) == 0 { + return nil, nil + } + + var ds []json.RawMessage + err := json.Unmarshal(d, &ds) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal initial BackgroundType JSON into an array: %w", err) + } + + var vs []BackgroundType + for idx, d := range ds { + v, err := unmarshalBackgroundType(d) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundType on array item %d: %w", idx, err) + } + vs = append(vs, v) + } + + return vs, nil +} + +// unmarshalBackgroundType is a JSON unmarshal helper to marshal the right structs into a BackgroundType interface +// based on the Type field. +func unmarshalBackgroundType(d json.RawMessage) (BackgroundType, error) { + if len(d) == 0 { + return nil, nil + } + + t := struct { + Type string + }{} + err := json.Unmarshal(d, &t) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundType for constant field 'Type': %w", err) + } + + switch t.Type { + case "fill": + s := BackgroundTypeFill{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundType for value 'fill': %w", err) + } + return s, nil + + case "wallpaper": + s := BackgroundTypeWallpaper{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundType for value 'wallpaper': %w", err) + } + return s, nil + + case "pattern": + s := BackgroundTypePattern{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundType for value 'pattern': %w", err) + } + return s, nil + + case "chat_theme": + s := BackgroundTypeChatTheme{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundType for value 'chat_theme': %w", err) + } + return s, nil + + } + return nil, fmt.Errorf("unknown interface for BackgroundType with Type %v", t.Type) +} + +// BackgroundTypeChatTheme (https://core.telegram.org/bots/api#backgroundtypechattheme) +// +// The background is taken directly from a built-in chat theme. +type BackgroundTypeChatTheme struct { + // Name of the chat theme, which is usually an emoji + ThemeName string `json:"theme_name"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundTypeChatTheme) GetType() string { + return "chat_theme" +} + +// MergeBackgroundType returns a MergedBackgroundType struct to simplify working with types in a non-generic world. +func (v BackgroundTypeChatTheme) MergeBackgroundType() MergedBackgroundType { + return MergedBackgroundType{ + Type: "chat_theme", + ThemeName: v.ThemeName, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundTypeChatTheme) MarshalJSON() ([]byte, error) { + type alias BackgroundTypeChatTheme + a := struct { + Type string `json:"type"` + alias + }{ + Type: "chat_theme", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundTypeChatTheme.backgroundType is a dummy method to avoid interface implementation. +func (v BackgroundTypeChatTheme) backgroundType() {} + +// BackgroundTypeFill (https://core.telegram.org/bots/api#backgroundtypefill) +// +// The background is automatically filled based on the selected colors. +type BackgroundTypeFill struct { + // The background fill + Fill BackgroundFill `json:"fill"` + // Dimming of the background in dark themes, as a percentage; 0-100 + DarkThemeDimming int64 `json:"dark_theme_dimming"` +} + +// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. +func (v *BackgroundTypeFill) UnmarshalJSON(b []byte) error { + // All fields in BackgroundTypeFill, with interface fields as json.RawMessage + type tmp struct { + Fill json.RawMessage `json:"fill"` + DarkThemeDimming int64 `json:"dark_theme_dimming"` + } + t := tmp{} + err := json.Unmarshal(b, &t) + if err != nil { + return fmt.Errorf("failed to unmarshal BackgroundTypeFill JSON into tmp struct: %w", err) + } + + v.Fill, err = unmarshalBackgroundFill(t.Fill) + if err != nil { + return fmt.Errorf("failed to unmarshal custom JSON field Fill: %w", err) + } + v.DarkThemeDimming = t.DarkThemeDimming + + return nil +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundTypeFill) GetType() string { + return "fill" +} + +// MergeBackgroundType returns a MergedBackgroundType struct to simplify working with types in a non-generic world. +func (v BackgroundTypeFill) MergeBackgroundType() MergedBackgroundType { + return MergedBackgroundType{ + Type: "fill", + Fill: v.Fill, + DarkThemeDimming: v.DarkThemeDimming, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundTypeFill) MarshalJSON() ([]byte, error) { + type alias BackgroundTypeFill + a := struct { + Type string `json:"type"` + alias + }{ + Type: "fill", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundTypeFill.backgroundType is a dummy method to avoid interface implementation. +func (v BackgroundTypeFill) backgroundType() {} + +// BackgroundTypePattern (https://core.telegram.org/bots/api#backgroundtypepattern) +// +// The background is a PNG or TGV (gzipped subset of SVG with MIME type "application/x-tgwallpattern") pattern to be combined with the background fill chosen by the user. +type BackgroundTypePattern struct { + // Document with the pattern + Document Document `json:"document"` + // The background fill that is combined with the pattern + Fill BackgroundFill `json:"fill"` + // Intensity of the pattern when it is shown above the filled background; 0-100 + Intensity int64 `json:"intensity"` + // Optional. True, if the background fill must be applied only to the pattern itself. All other pixels are black in this case. For dark themes only + IsInverted bool `json:"is_inverted,omitempty"` + // Optional. True, if the background moves slightly when the device is tilted + IsMoving bool `json:"is_moving,omitempty"` +} + +// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. +func (v *BackgroundTypePattern) UnmarshalJSON(b []byte) error { + // All fields in BackgroundTypePattern, with interface fields as json.RawMessage + type tmp struct { + Document Document `json:"document"` + Fill json.RawMessage `json:"fill"` + Intensity int64 `json:"intensity"` + IsInverted bool `json:"is_inverted"` + IsMoving bool `json:"is_moving"` + } + t := tmp{} + err := json.Unmarshal(b, &t) + if err != nil { + return fmt.Errorf("failed to unmarshal BackgroundTypePattern JSON into tmp struct: %w", err) + } + + v.Document = t.Document + v.Fill, err = unmarshalBackgroundFill(t.Fill) + if err != nil { + return fmt.Errorf("failed to unmarshal custom JSON field Fill: %w", err) + } + v.Intensity = t.Intensity + v.IsInverted = t.IsInverted + v.IsMoving = t.IsMoving + + return nil +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundTypePattern) GetType() string { + return "pattern" +} + +// MergeBackgroundType returns a MergedBackgroundType struct to simplify working with types in a non-generic world. +func (v BackgroundTypePattern) MergeBackgroundType() MergedBackgroundType { + return MergedBackgroundType{ + Type: "pattern", + Document: &v.Document, + Fill: v.Fill, + Intensity: v.Intensity, + IsInverted: v.IsInverted, + IsMoving: v.IsMoving, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundTypePattern) MarshalJSON() ([]byte, error) { + type alias BackgroundTypePattern + a := struct { + Type string `json:"type"` + alias + }{ + Type: "pattern", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundTypePattern.backgroundType is a dummy method to avoid interface implementation. +func (v BackgroundTypePattern) backgroundType() {} + +// BackgroundTypeWallpaper (https://core.telegram.org/bots/api#backgroundtypewallpaper) +// +// The background is a wallpaper in the JPEG format. +type BackgroundTypeWallpaper struct { + // Document with the wallpaper + Document Document `json:"document"` + // Dimming of the background in dark themes, as a percentage; 0-100 + DarkThemeDimming int64 `json:"dark_theme_dimming"` + // Optional. True, if the wallpaper is downscaled to fit in a 450x450 square and then box-blurred with radius 12 + IsBlurred bool `json:"is_blurred,omitempty"` + // Optional. True, if the background moves slightly when the device is tilted + IsMoving bool `json:"is_moving,omitempty"` +} + +// GetType is a helper method to easily access the common fields of an interface. +func (v BackgroundTypeWallpaper) GetType() string { + return "wallpaper" +} + +// MergeBackgroundType returns a MergedBackgroundType struct to simplify working with types in a non-generic world. +func (v BackgroundTypeWallpaper) MergeBackgroundType() MergedBackgroundType { + return MergedBackgroundType{ + Type: "wallpaper", + Document: &v.Document, + DarkThemeDimming: v.DarkThemeDimming, + IsBlurred: v.IsBlurred, + IsMoving: v.IsMoving, + } +} + +// MarshalJSON is a custom JSON marshaller to allow for enforcing the Type value. +func (v BackgroundTypeWallpaper) MarshalJSON() ([]byte, error) { + type alias BackgroundTypeWallpaper + a := struct { + Type string `json:"type"` + alias + }{ + Type: "wallpaper", + alias: (alias)(v), + } + return json.Marshal(a) +} + +// BackgroundTypeWallpaper.backgroundType is a dummy method to avoid interface implementation. +func (v BackgroundTypeWallpaper) backgroundType() {} + // Birthdate (https://core.telegram.org/bots/api#birthdate) +// +// Describes the birthdate of a user. type Birthdate struct { // Day of the user's birth; 1-31 Day int64 `json:"day"` @@ -431,6 +957,8 @@ type BusinessConnection struct { } // BusinessIntro (https://core.telegram.org/bots/api#businessintro) +// +// Contains information about the start page settings of a Telegram Business account. type BusinessIntro struct { // Optional. Title text of the business intro Title string `json:"title,omitempty"` @@ -441,6 +969,8 @@ type BusinessIntro struct { } // BusinessLocation (https://core.telegram.org/bots/api#businesslocation) +// +// Contains information about the location of a Telegram Business account. type BusinessLocation struct { // Address of the business Address string `json:"address"` @@ -461,6 +991,8 @@ type BusinessMessagesDeleted struct { } // BusinessOpeningHours (https://core.telegram.org/bots/api#businessopeninghours) +// +// Describes the opening hours of a business. type BusinessOpeningHours struct { // Unique name of the time zone for which the opening hours are defined TimeZoneName string `json:"time_zone_name"` @@ -469,6 +1001,8 @@ type BusinessOpeningHours struct { } // BusinessOpeningHoursInterval (https://core.telegram.org/bots/api#businessopeninghoursinterval) +// +// Describes an interval of time during which a business is open. type BusinessOpeningHoursInterval struct { // The minute's sequence number in a week, starting on Monday, marking the start of the time interval during which the business is open; 0 - 7 * 24 * 60 OpeningMinute int64 `json:"opening_minute"` @@ -499,232 +1033,60 @@ type CallbackQuery struct { Data string `json:"data,omitempty"` // Optional. Short name of a Game to be returned, serves as the unique identifier for the game GameShortName string `json:"game_short_name,omitempty"` -} - -// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. -func (v *CallbackQuery) UnmarshalJSON(b []byte) error { - // All fields in CallbackQuery, with interface fields as json.RawMessage - type tmp struct { - Id string `json:"id"` - From User `json:"from"` - Message json.RawMessage `json:"message"` - InlineMessageId string `json:"inline_message_id"` - ChatInstance string `json:"chat_instance"` - Data string `json:"data"` - GameShortName string `json:"game_short_name"` - } - t := tmp{} - err := json.Unmarshal(b, &t) - if err != nil { - return fmt.Errorf("failed to unmarshal CallbackQuery JSON into tmp struct: %w", err) - } - - v.Id = t.Id - v.From = t.From - v.Message, err = unmarshalMaybeInaccessibleMessage(t.Message) - if err != nil { - return fmt.Errorf("failed to unmarshal custom JSON field Message: %w", err) - } - v.InlineMessageId = t.InlineMessageId - v.ChatInstance = t.ChatInstance - v.Data = t.Data - v.GameShortName = t.GameShortName - - return nil -} - -// Chat (https://core.telegram.org/bots/api#chat) -// -// This object represents a chat. -type Chat struct { - // Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. - Id int64 `json:"id"` - // Type of chat, can be either "private", "group", "supergroup" or "channel" - Type string `json:"type"` - // Optional. Title, for supergroups, channels and group chats - Title string `json:"title,omitempty"` - // Optional. Username, for private chats, supergroups and channels if available - Username string `json:"username,omitempty"` - // Optional. First name of the other party in a private chat - FirstName string `json:"first_name,omitempty"` - // Optional. Last name of the other party in a private chat - LastName string `json:"last_name,omitempty"` - // Optional. True, if the supergroup chat is a forum (has topics enabled) - IsForum bool `json:"is_forum,omitempty"` - // Optional. Chat photo. Returned only in getChat. - Photo *ChatPhoto `json:"photo,omitempty"` - // Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. Returned only in getChat. - ActiveUsernames []string `json:"active_usernames,omitempty"` - // Optional. For private chats, the date of birth of the user. Returned only in getChat. - Birthdate *Birthdate `json:"birthdate,omitempty"` - // Optional. For private chats with business accounts, the intro of the business. Returned only in getChat. - BusinessIntro *BusinessIntro `json:"business_intro,omitempty"` - // Optional. For private chats with business accounts, the location of the business. Returned only in getChat. - BusinessLocation *BusinessLocation `json:"business_location,omitempty"` - // Optional. For private chats with business accounts, the opening hours of the business. Returned only in getChat. - BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours,omitempty"` - // Optional. For private chats, the personal channel of the user. Returned only in getChat. - PersonalChat *Chat `json:"personal_chat,omitempty"` - // Optional. List of available reactions allowed in the chat. If omitted, then all emoji reactions are allowed. Returned only in getChat. - AvailableReactions []ReactionType `json:"available_reactions,omitempty"` - // Optional. Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See accent colors for more details. Returned only in getChat. Always returned in getChat. - AccentColorId int64 `json:"accent_color_id,omitempty"` - // Optional. Custom emoji identifier of emoji chosen by the chat for the reply header and link preview background. Returned only in getChat. - BackgroundCustomEmojiId string `json:"background_custom_emoji_id,omitempty"` - // Optional. Identifier of the accent color for the chat's profile background. See profile accent colors for more details. Returned only in getChat. - ProfileAccentColorId int64 `json:"profile_accent_color_id,omitempty"` - // Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background. Returned only in getChat. - ProfileBackgroundCustomEmojiId string `json:"profile_background_custom_emoji_id,omitempty"` - // Optional. Custom emoji identifier of the emoji status of the chat or the other party in a private chat. Returned only in getChat. - EmojiStatusCustomEmojiId string `json:"emoji_status_custom_emoji_id,omitempty"` - // Optional. Expiration date of the emoji status of the chat or the other party in a private chat, in Unix time, if any. Returned only in getChat. - EmojiStatusExpirationDate int64 `json:"emoji_status_expiration_date,omitempty"` - // Optional. Bio of the other party in a private chat. Returned only in getChat. - Bio string `json:"bio,omitempty"` - // Optional. True, if privacy settings of the other party in the private chat allows to use tg://user?id= links only in chats with the user. Returned only in getChat. - HasPrivateForwards bool `json:"has_private_forwards,omitempty"` - // Optional. True, if the privacy settings of the other party restrict sending voice and video note messages in the private chat. Returned only in getChat. - HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages,omitempty"` - // Optional. True, if users need to join the supergroup before they can send messages. Returned only in getChat. - JoinToSendMessages bool `json:"join_to_send_messages,omitempty"` - // Optional. True, if all users directly joining the supergroup need to be approved by supergroup administrators. Returned only in getChat. - JoinByRequest bool `json:"join_by_request,omitempty"` - // Optional. Description, for groups, supergroups and channel chats. Returned only in getChat. - Description string `json:"description,omitempty"` - // Optional. Primary invite link, for groups, supergroups and channel chats. Returned only in getChat. - InviteLink string `json:"invite_link,omitempty"` - // Optional. The most recent pinned message (by sending date). Returned only in getChat. - PinnedMessage *Message `json:"pinned_message,omitempty"` - // Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat. - Permissions *ChatPermissions `json:"permissions,omitempty"` - // Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unprivileged user; in seconds. Returned only in getChat. - SlowModeDelay int64 `json:"slow_mode_delay,omitempty"` - // Optional. For supergroups, the minimum number of boosts that a non-administrator user needs to add in order to ignore slow mode and chat permissions. Returned only in getChat. - UnrestrictBoostCount int64 `json:"unrestrict_boost_count,omitempty"` - // Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds. Returned only in getChat. - MessageAutoDeleteTime int64 `json:"message_auto_delete_time,omitempty"` - // Optional. True, if aggressive anti-spam checks are enabled in the supergroup. The field is only available to chat administrators. Returned only in getChat. - HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled,omitempty"` - // Optional. True, if non-administrators can only get the list of bots and administrators in the chat. Returned only in getChat. - HasHiddenMembers bool `json:"has_hidden_members,omitempty"` - // Optional. True, if messages from the chat can't be forwarded to other chats. Returned only in getChat. - HasProtectedContent bool `json:"has_protected_content,omitempty"` - // Optional. True, if new chat members will have access to old messages; available only to chat administrators. Returned only in getChat. - HasVisibleHistory bool `json:"has_visible_history,omitempty"` - // Optional. For supergroups, name of group sticker set. Returned only in getChat. - StickerSetName string `json:"sticker_set_name,omitempty"` - // Optional. True, if the bot can change the group sticker set. Returned only in getChat. - CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` - // Optional. For supergroups, the name of the group's custom emoji sticker set. Custom emoji from this set can be used by all users and bots in the group. Returned only in getChat. - CustomEmojiStickerSetName string `json:"custom_emoji_sticker_set_name,omitempty"` - // Optional. Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; for supergroups and channel chats. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. Returned only in getChat. - LinkedChatId int64 `json:"linked_chat_id,omitempty"` - // Optional. For supergroups, the location to which the supergroup is connected. Returned only in getChat. - Location *ChatLocation `json:"location,omitempty"` -} - -// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. -func (v *Chat) UnmarshalJSON(b []byte) error { - // All fields in Chat, with interface fields as json.RawMessage - type tmp struct { - Id int64 `json:"id"` - Type string `json:"type"` - Title string `json:"title"` - Username string `json:"username"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - IsForum bool `json:"is_forum"` - Photo *ChatPhoto `json:"photo"` - ActiveUsernames []string `json:"active_usernames"` - Birthdate *Birthdate `json:"birthdate"` - BusinessIntro *BusinessIntro `json:"business_intro"` - BusinessLocation *BusinessLocation `json:"business_location"` - BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours"` - PersonalChat *Chat `json:"personal_chat"` - AvailableReactions json.RawMessage `json:"available_reactions"` - AccentColorId int64 `json:"accent_color_id"` - BackgroundCustomEmojiId string `json:"background_custom_emoji_id"` - ProfileAccentColorId int64 `json:"profile_accent_color_id"` - ProfileBackgroundCustomEmojiId string `json:"profile_background_custom_emoji_id"` - EmojiStatusCustomEmojiId string `json:"emoji_status_custom_emoji_id"` - EmojiStatusExpirationDate int64 `json:"emoji_status_expiration_date"` - Bio string `json:"bio"` - HasPrivateForwards bool `json:"has_private_forwards"` - HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages"` - JoinToSendMessages bool `json:"join_to_send_messages"` - JoinByRequest bool `json:"join_by_request"` - Description string `json:"description"` - InviteLink string `json:"invite_link"` - PinnedMessage *Message `json:"pinned_message"` - Permissions *ChatPermissions `json:"permissions"` - SlowModeDelay int64 `json:"slow_mode_delay"` - UnrestrictBoostCount int64 `json:"unrestrict_boost_count"` - MessageAutoDeleteTime int64 `json:"message_auto_delete_time"` - HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled"` - HasHiddenMembers bool `json:"has_hidden_members"` - HasProtectedContent bool `json:"has_protected_content"` - HasVisibleHistory bool `json:"has_visible_history"` - StickerSetName string `json:"sticker_set_name"` - CanSetStickerSet bool `json:"can_set_sticker_set"` - CustomEmojiStickerSetName string `json:"custom_emoji_sticker_set_name"` - LinkedChatId int64 `json:"linked_chat_id"` - Location *ChatLocation `json:"location"` +} + +// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. +func (v *CallbackQuery) UnmarshalJSON(b []byte) error { + // All fields in CallbackQuery, with interface fields as json.RawMessage + type tmp struct { + Id string `json:"id"` + From User `json:"from"` + Message json.RawMessage `json:"message"` + InlineMessageId string `json:"inline_message_id"` + ChatInstance string `json:"chat_instance"` + Data string `json:"data"` + GameShortName string `json:"game_short_name"` } t := tmp{} err := json.Unmarshal(b, &t) if err != nil { - return fmt.Errorf("failed to unmarshal Chat JSON into tmp struct: %w", err) + return fmt.Errorf("failed to unmarshal CallbackQuery JSON into tmp struct: %w", err) } v.Id = t.Id - v.Type = t.Type - v.Title = t.Title - v.Username = t.Username - v.FirstName = t.FirstName - v.LastName = t.LastName - v.IsForum = t.IsForum - v.Photo = t.Photo - v.ActiveUsernames = t.ActiveUsernames - v.Birthdate = t.Birthdate - v.BusinessIntro = t.BusinessIntro - v.BusinessLocation = t.BusinessLocation - v.BusinessOpeningHours = t.BusinessOpeningHours - v.PersonalChat = t.PersonalChat - v.AvailableReactions, err = unmarshalReactionTypeArray(t.AvailableReactions) + v.From = t.From + v.Message, err = unmarshalMaybeInaccessibleMessage(t.Message) if err != nil { - return fmt.Errorf("failed to unmarshal custom JSON field AvailableReactions: %w", err) + return fmt.Errorf("failed to unmarshal custom JSON field Message: %w", err) } - v.AccentColorId = t.AccentColorId - v.BackgroundCustomEmojiId = t.BackgroundCustomEmojiId - v.ProfileAccentColorId = t.ProfileAccentColorId - v.ProfileBackgroundCustomEmojiId = t.ProfileBackgroundCustomEmojiId - v.EmojiStatusCustomEmojiId = t.EmojiStatusCustomEmojiId - v.EmojiStatusExpirationDate = t.EmojiStatusExpirationDate - v.Bio = t.Bio - v.HasPrivateForwards = t.HasPrivateForwards - v.HasRestrictedVoiceAndVideoMessages = t.HasRestrictedVoiceAndVideoMessages - v.JoinToSendMessages = t.JoinToSendMessages - v.JoinByRequest = t.JoinByRequest - v.Description = t.Description - v.InviteLink = t.InviteLink - v.PinnedMessage = t.PinnedMessage - v.Permissions = t.Permissions - v.SlowModeDelay = t.SlowModeDelay - v.UnrestrictBoostCount = t.UnrestrictBoostCount - v.MessageAutoDeleteTime = t.MessageAutoDeleteTime - v.HasAggressiveAntiSpamEnabled = t.HasAggressiveAntiSpamEnabled - v.HasHiddenMembers = t.HasHiddenMembers - v.HasProtectedContent = t.HasProtectedContent - v.HasVisibleHistory = t.HasVisibleHistory - v.StickerSetName = t.StickerSetName - v.CanSetStickerSet = t.CanSetStickerSet - v.CustomEmojiStickerSetName = t.CustomEmojiStickerSetName - v.LinkedChatId = t.LinkedChatId - v.Location = t.Location + v.InlineMessageId = t.InlineMessageId + v.ChatInstance = t.ChatInstance + v.Data = t.Data + v.GameShortName = t.GameShortName return nil } +// Chat (https://core.telegram.org/bots/api#chat) +// +// This object represents a chat. +type Chat struct { + // Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. + Id int64 `json:"id"` + // Type of the chat, can be either "private", "group", "supergroup" or "channel" + Type string `json:"type"` + // Optional. Title, for supergroups, channels and group chats + Title string `json:"title,omitempty"` + // Optional. Username, for private chats, supergroups and channels if available + Username string `json:"username,omitempty"` + // Optional. First name of the other party in a private chat + FirstName string `json:"first_name,omitempty"` + // Optional. Last name of the other party in a private chat + LastName string `json:"last_name,omitempty"` + // Optional. True, if the supergroup chat is a forum (has topics enabled) + IsForum bool `json:"is_forum,omitempty"` +} + // ChatAdministratorRights (https://core.telegram.org/bots/api#chatadministratorrights) // // Represents the rights of an administrator in a chat. @@ -747,7 +1109,7 @@ type ChatAdministratorRights struct { CanInviteUsers bool `json:"can_invite_users"` // True, if the administrator can post stories to the chat CanPostStories bool `json:"can_post_stories"` - // True, if the administrator can edit stories posted by other users + // True, if the administrator can edit stories posted by other users, post stories to the chat page, pin chat stories, and access the chat's story archive CanEditStories bool `json:"can_edit_stories"` // True, if the administrator can delete stories posted by other users CanDeleteStories bool `json:"can_delete_stories"` @@ -761,6 +1123,34 @@ type ChatAdministratorRights struct { CanManageTopics bool `json:"can_manage_topics,omitempty"` } +// ChatBackground (https://core.telegram.org/bots/api#chatbackground) +// +// This object represents a chat background. +type ChatBackground struct { + // Type of the background + Type BackgroundType `json:"type"` +} + +// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. +func (v *ChatBackground) UnmarshalJSON(b []byte) error { + // All fields in ChatBackground, with interface fields as json.RawMessage + type tmp struct { + Type json.RawMessage `json:"type"` + } + t := tmp{} + err := json.Unmarshal(b, &t) + if err != nil { + return fmt.Errorf("failed to unmarshal ChatBackground JSON into tmp struct: %w", err) + } + + v.Type, err = unmarshalBackgroundType(t.Type) + if err != nil { + return fmt.Errorf("failed to unmarshal custom JSON field Type: %w", err) + } + + return nil +} + // ChatBoost (https://core.telegram.org/bots/api#chatboost) // // This object contains information about a chat boost. @@ -1091,6 +1481,202 @@ type ChatBoostUpdated struct { Boost ChatBoost `json:"boost"` } +// ChatFullInfo (https://core.telegram.org/bots/api#chatfullinfo) +// +// This object contains full information about a chat. +type ChatFullInfo struct { + // Unique identifier for this chat. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so a signed 64-bit integer or double-precision float type are safe for storing this identifier. + Id int64 `json:"id"` + // Type of the chat, can be either "private", "group", "supergroup" or "channel" + Type string `json:"type"` + // Optional. Title, for supergroups, channels and group chats + Title string `json:"title,omitempty"` + // Optional. Username, for private chats, supergroups and channels if available + Username string `json:"username,omitempty"` + // Optional. First name of the other party in a private chat + FirstName string `json:"first_name,omitempty"` + // Optional. Last name of the other party in a private chat + LastName string `json:"last_name,omitempty"` + // Optional. True, if the supergroup chat is a forum (has topics enabled) + IsForum bool `json:"is_forum,omitempty"` + // Identifier of the accent color for the chat name and backgrounds of the chat photo, reply header, and link preview. See accent colors for more details. + AccentColorId int64 `json:"accent_color_id"` + // The maximum number of reactions that can be set on a message in the chat + MaxReactionCount int64 `json:"max_reaction_count"` + // Optional. Chat photo + Photo *ChatPhoto `json:"photo,omitempty"` + // Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels + ActiveUsernames []string `json:"active_usernames,omitempty"` + // Optional. For private chats, the date of birth of the user + Birthdate *Birthdate `json:"birthdate,omitempty"` + // Optional. For private chats with business accounts, the intro of the business + BusinessIntro *BusinessIntro `json:"business_intro,omitempty"` + // Optional. For private chats with business accounts, the location of the business + BusinessLocation *BusinessLocation `json:"business_location,omitempty"` + // Optional. For private chats with business accounts, the opening hours of the business + BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours,omitempty"` + // Optional. For private chats, the personal channel of the user + PersonalChat *Chat `json:"personal_chat,omitempty"` + // Optional. List of available reactions allowed in the chat. If omitted, then all emoji reactions are allowed. + AvailableReactions []ReactionType `json:"available_reactions,omitempty"` + // Optional. Custom emoji identifier of the emoji chosen by the chat for the reply header and link preview background + BackgroundCustomEmojiId string `json:"background_custom_emoji_id,omitempty"` + // Optional. Identifier of the accent color for the chat's profile background. See profile accent colors for more details. + ProfileAccentColorId int64 `json:"profile_accent_color_id,omitempty"` + // Optional. Custom emoji identifier of the emoji chosen by the chat for its profile background + ProfileBackgroundCustomEmojiId string `json:"profile_background_custom_emoji_id,omitempty"` + // Optional. Custom emoji identifier of the emoji status of the chat or the other party in a private chat + EmojiStatusCustomEmojiId string `json:"emoji_status_custom_emoji_id,omitempty"` + // Optional. Expiration date of the emoji status of the chat or the other party in a private chat, in Unix time, if any + EmojiStatusExpirationDate int64 `json:"emoji_status_expiration_date,omitempty"` + // Optional. Bio of the other party in a private chat + Bio string `json:"bio,omitempty"` + // Optional. True, if privacy settings of the other party in the private chat allows to use tg://user?id= links only in chats with the user + HasPrivateForwards bool `json:"has_private_forwards,omitempty"` + // Optional. True, if the privacy settings of the other party restrict sending voice and video note messages in the private chat + HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages,omitempty"` + // Optional. True, if users need to join the supergroup before they can send messages + JoinToSendMessages bool `json:"join_to_send_messages,omitempty"` + // Optional. True, if all users directly joining the supergroup need to be approved by supergroup administrators + JoinByRequest bool `json:"join_by_request,omitempty"` + // Optional. Description, for groups, supergroups and channel chats + Description string `json:"description,omitempty"` + // Optional. Primary invite link, for groups, supergroups and channel chats + InviteLink string `json:"invite_link,omitempty"` + // Optional. The most recent pinned message (by sending date) + PinnedMessage *Message `json:"pinned_message,omitempty"` + // Optional. Default chat member permissions, for groups and supergroups + Permissions *ChatPermissions `json:"permissions,omitempty"` + // Optional. For supergroups, the minimum allowed delay between consecutive messages sent by each unprivileged user; in seconds + SlowModeDelay int64 `json:"slow_mode_delay,omitempty"` + // Optional. For supergroups, the minimum number of boosts that a non-administrator user needs to add in order to ignore slow mode and chat permissions + UnrestrictBoostCount int64 `json:"unrestrict_boost_count,omitempty"` + // Optional. The time after which all messages sent to the chat will be automatically deleted; in seconds + MessageAutoDeleteTime int64 `json:"message_auto_delete_time,omitempty"` + // Optional. True, if aggressive anti-spam checks are enabled in the supergroup. The field is only available to chat administrators. + HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled,omitempty"` + // Optional. True, if non-administrators can only get the list of bots and administrators in the chat + HasHiddenMembers bool `json:"has_hidden_members,omitempty"` + // Optional. True, if messages from the chat can't be forwarded to other chats + HasProtectedContent bool `json:"has_protected_content,omitempty"` + // Optional. True, if new chat members will have access to old messages; available only to chat administrators + HasVisibleHistory bool `json:"has_visible_history,omitempty"` + // Optional. For supergroups, name of the group sticker set + StickerSetName string `json:"sticker_set_name,omitempty"` + // Optional. True, if the bot can change the group sticker set + CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` + // Optional. For supergroups, the name of the group's custom emoji sticker set. Custom emoji from this set can be used by all users and bots in the group. + CustomEmojiStickerSetName string `json:"custom_emoji_sticker_set_name,omitempty"` + // Optional. Unique identifier for the linked chat, i.e. the discussion group identifier for a channel and vice versa; for supergroups and channel chats. This identifier may be greater than 32 bits and some programming languages may have difficulty/silent defects in interpreting it. But it is smaller than 52 bits, so a signed 64 bit integer or double-precision float type are safe for storing this identifier. + LinkedChatId int64 `json:"linked_chat_id,omitempty"` + // Optional. For supergroups, the location to which the supergroup is connected + Location *ChatLocation `json:"location,omitempty"` +} + +// UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. +func (v *ChatFullInfo) UnmarshalJSON(b []byte) error { + // All fields in ChatFullInfo, with interface fields as json.RawMessage + type tmp struct { + Id int64 `json:"id"` + Type string `json:"type"` + Title string `json:"title"` + Username string `json:"username"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + IsForum bool `json:"is_forum"` + AccentColorId int64 `json:"accent_color_id"` + MaxReactionCount int64 `json:"max_reaction_count"` + Photo *ChatPhoto `json:"photo"` + ActiveUsernames []string `json:"active_usernames"` + Birthdate *Birthdate `json:"birthdate"` + BusinessIntro *BusinessIntro `json:"business_intro"` + BusinessLocation *BusinessLocation `json:"business_location"` + BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours"` + PersonalChat *Chat `json:"personal_chat"` + AvailableReactions json.RawMessage `json:"available_reactions"` + BackgroundCustomEmojiId string `json:"background_custom_emoji_id"` + ProfileAccentColorId int64 `json:"profile_accent_color_id"` + ProfileBackgroundCustomEmojiId string `json:"profile_background_custom_emoji_id"` + EmojiStatusCustomEmojiId string `json:"emoji_status_custom_emoji_id"` + EmojiStatusExpirationDate int64 `json:"emoji_status_expiration_date"` + Bio string `json:"bio"` + HasPrivateForwards bool `json:"has_private_forwards"` + HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages"` + JoinToSendMessages bool `json:"join_to_send_messages"` + JoinByRequest bool `json:"join_by_request"` + Description string `json:"description"` + InviteLink string `json:"invite_link"` + PinnedMessage *Message `json:"pinned_message"` + Permissions *ChatPermissions `json:"permissions"` + SlowModeDelay int64 `json:"slow_mode_delay"` + UnrestrictBoostCount int64 `json:"unrestrict_boost_count"` + MessageAutoDeleteTime int64 `json:"message_auto_delete_time"` + HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled"` + HasHiddenMembers bool `json:"has_hidden_members"` + HasProtectedContent bool `json:"has_protected_content"` + HasVisibleHistory bool `json:"has_visible_history"` + StickerSetName string `json:"sticker_set_name"` + CanSetStickerSet bool `json:"can_set_sticker_set"` + CustomEmojiStickerSetName string `json:"custom_emoji_sticker_set_name"` + LinkedChatId int64 `json:"linked_chat_id"` + Location *ChatLocation `json:"location"` + } + t := tmp{} + err := json.Unmarshal(b, &t) + if err != nil { + return fmt.Errorf("failed to unmarshal ChatFullInfo JSON into tmp struct: %w", err) + } + + v.Id = t.Id + v.Type = t.Type + v.Title = t.Title + v.Username = t.Username + v.FirstName = t.FirstName + v.LastName = t.LastName + v.IsForum = t.IsForum + v.AccentColorId = t.AccentColorId + v.MaxReactionCount = t.MaxReactionCount + v.Photo = t.Photo + v.ActiveUsernames = t.ActiveUsernames + v.Birthdate = t.Birthdate + v.BusinessIntro = t.BusinessIntro + v.BusinessLocation = t.BusinessLocation + v.BusinessOpeningHours = t.BusinessOpeningHours + v.PersonalChat = t.PersonalChat + v.AvailableReactions, err = unmarshalReactionTypeArray(t.AvailableReactions) + if err != nil { + return fmt.Errorf("failed to unmarshal custom JSON field AvailableReactions: %w", err) + } + v.BackgroundCustomEmojiId = t.BackgroundCustomEmojiId + v.ProfileAccentColorId = t.ProfileAccentColorId + v.ProfileBackgroundCustomEmojiId = t.ProfileBackgroundCustomEmojiId + v.EmojiStatusCustomEmojiId = t.EmojiStatusCustomEmojiId + v.EmojiStatusExpirationDate = t.EmojiStatusExpirationDate + v.Bio = t.Bio + v.HasPrivateForwards = t.HasPrivateForwards + v.HasRestrictedVoiceAndVideoMessages = t.HasRestrictedVoiceAndVideoMessages + v.JoinToSendMessages = t.JoinToSendMessages + v.JoinByRequest = t.JoinByRequest + v.Description = t.Description + v.InviteLink = t.InviteLink + v.PinnedMessage = t.PinnedMessage + v.Permissions = t.Permissions + v.SlowModeDelay = t.SlowModeDelay + v.UnrestrictBoostCount = t.UnrestrictBoostCount + v.MessageAutoDeleteTime = t.MessageAutoDeleteTime + v.HasAggressiveAntiSpamEnabled = t.HasAggressiveAntiSpamEnabled + v.HasHiddenMembers = t.HasHiddenMembers + v.HasProtectedContent = t.HasProtectedContent + v.HasVisibleHistory = t.HasVisibleHistory + v.StickerSetName = t.StickerSetName + v.CanSetStickerSet = t.CanSetStickerSet + v.CustomEmojiStickerSetName = t.CustomEmojiStickerSetName + v.LinkedChatId = t.LinkedChatId + v.Location = t.Location + + return nil +} + // ChatInviteLink (https://core.telegram.org/bots/api#chatinvitelink) // // Represents an invite link for a chat. @@ -1199,7 +1785,7 @@ type MergedChatMember struct { CanInviteUsers bool `json:"can_invite_users,omitempty"` // Optional. True, if the administrator can post stories to the chat (Only for administrator) CanPostStories bool `json:"can_post_stories,omitempty"` - // Optional. True, if the administrator can edit stories posted by other users (Only for administrator) + // Optional. True, if the administrator can edit stories posted by other users, post stories to the chat page, pin chat stories, and access the chat's story archive (Only for administrator) CanEditStories bool `json:"can_edit_stories,omitempty"` // Optional. True, if the administrator can delete stories posted by other users (Only for administrator) CanDeleteStories bool `json:"can_delete_stories,omitempty"` @@ -1374,7 +1960,7 @@ type ChatMemberAdministrator struct { CanInviteUsers bool `json:"can_invite_users"` // True, if the administrator can post stories to the chat CanPostStories bool `json:"can_post_stories"` - // True, if the administrator can edit stories posted by other users + // True, if the administrator can edit stories posted by other users, post stories to the chat page, pin chat stories, and access the chat's story archive CanEditStories bool `json:"can_edit_stories"` // True, if the administrator can delete stories posted by other users CanDeleteStories bool `json:"can_delete_stories"` @@ -1724,6 +2310,8 @@ type ChatMemberUpdated struct { NewChatMember ChatMember `json:"new_chat_member"` // Optional. Chat invite link, which was used by the user to join the chat; for joining by invite link events only. InviteLink *ChatInviteLink `json:"invite_link,omitempty"` + // Optional. True, if the user joined the chat after sending a direct join request and being approved by an administrator + ViaJoinRequest bool `json:"via_join_request,omitempty"` // Optional. True, if the user joined the chat via a chat folder invite link ViaChatFolderInviteLink bool `json:"via_chat_folder_invite_link,omitempty"` } @@ -1738,6 +2326,7 @@ func (v *ChatMemberUpdated) UnmarshalJSON(b []byte) error { OldChatMember json.RawMessage `json:"old_chat_member"` NewChatMember json.RawMessage `json:"new_chat_member"` InviteLink *ChatInviteLink `json:"invite_link"` + ViaJoinRequest bool `json:"via_join_request"` ViaChatFolderInviteLink bool `json:"via_chat_folder_invite_link"` } t := tmp{} @@ -1758,6 +2347,7 @@ func (v *ChatMemberUpdated) UnmarshalJSON(b []byte) error { return fmt.Errorf("failed to unmarshal custom JSON field NewChatMember: %w", err) } v.InviteLink = t.InviteLink + v.ViaJoinRequest = t.ViaJoinRequest v.ViaChatFolderInviteLink = t.ViaChatFolderInviteLink return nil @@ -2058,7 +2648,7 @@ type File struct { // ForceReply (https://core.telegram.org/bots/api#forcereply) // -// Upon receiving a message with this object, Telegram clients will display a reply interface to the user (act as if the user has selected the bot's message and tapped 'Reply'). This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. +// Upon receiving a message with this object, Telegram clients will display a reply interface to the user (act as if the user has selected the bot's message and tapped 'Reply'). This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. Not supported in channels and for messages sent on behalf of a Telegram Business account. type ForceReply struct { // Shows reply interface to the user, as if they manually selected the bot's message and tapped 'Reply' ForceReply bool `json:"force_reply"` @@ -2262,17 +2852,17 @@ type InlineKeyboardButton struct { Text string `json:"text"` // Optional. HTTP or tg:// URL to be opened when the button is pressed. Links tg://user?id= can be used to mention a user by their identifier without using a username, if this is allowed by their privacy settings. Url string `json:"url,omitempty"` - // Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes + // Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes. Not supported for messages sent on behalf of a Telegram Business account. CallbackData string `json:"callback_data,omitempty"` - // Optional. Description of the Web App that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Available only in private chats between a user and the bot. + // Optional. Description of the Web App that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Available only in private chats between a user and the bot. Not supported for messages sent on behalf of a Telegram Business account. WebApp *WebAppInfo `json:"web_app,omitempty"` // Optional. An HTTPS URL used to automatically authorize the user. Can be used as a replacement for the Telegram Login Widget. LoginUrl *LoginUrl `json:"login_url,omitempty"` - // Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. May be empty, in which case just the bot's username will be inserted. + // Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. May be empty, in which case just the bot's username will be inserted. Not supported for messages sent on behalf of a Telegram Business account. SwitchInlineQuery *string `json:"switch_inline_query,omitempty"` - // Optional. If set, pressing the button will insert the bot's username and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username will be inserted. This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. + // Optional. If set, pressing the button will insert the bot's username and the specified inline query in the current chat's input field. May be empty, in which case only the bot's username will be inserted. This offers a quick way for the user to open your bot in inline mode in the same chat - good for selecting something from multiple options. Not supported in channels and for messages sent on behalf of a Telegram Business account. SwitchInlineQueryCurrentChat *string `json:"switch_inline_query_current_chat,omitempty"` - // Optional. If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field + // Optional. If set, pressing the button will prompt the user to select one of their chats of the specified type, open that chat and insert the bot's username and the specified inline query in the input field. Not supported for messages sent on behalf of a Telegram Business account. SwitchInlineQueryChosenChat *SwitchInlineQueryChosenChat `json:"switch_inline_query_chosen_chat,omitempty"` // Optional. Description of the game that will be launched when the user presses the button. NOTE: This type of button must always be the first button in the first row. CallbackGame *CallbackGame `json:"callback_game,omitempty"` @@ -2449,7 +3039,7 @@ type MergedInlineQueryResult struct { Longitude float64 `json:"longitude,omitempty"` // Optional. The radius of uncertainty for the location, measured in meters; 0-1500 (Only for location) HorizontalAccuracy float64 `json:"horizontal_accuracy,omitempty"` - // Optional. Period in seconds for which the location can be updated, should be between 60 and 86400. (Only for location) + // Optional. Period in seconds during which the location can be updated, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. (Only for location) LivePeriod int64 `json:"live_period,omitempty"` // Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. (Only for location) Heading int64 `json:"heading,omitempty"` @@ -3434,7 +4024,7 @@ type InlineQueryResultLocation struct { Title string `json:"title"` // Optional. The radius of uncertainty for the location, measured in meters; 0-1500 HorizontalAccuracy float64 `json:"horizontal_accuracy,omitempty"` - // Optional. Period in seconds for which the location can be updated, should be between 60 and 86400. + // Optional. Period in seconds during which the location can be updated, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. LivePeriod int64 `json:"live_period,omitempty"` // Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. Heading int64 `json:"heading,omitempty"` @@ -3972,7 +4562,7 @@ type InputLocationMessageContent struct { Longitude float64 `json:"longitude"` // Optional. The radius of uncertainty for the location, measured in meters; 0-1500 HorizontalAccuracy float64 `json:"horizontal_accuracy,omitempty"` - // Optional. Period in seconds for which the location can be updated, should be between 60 and 86400. + // Optional. Period in seconds during which the location can be updated, should be between 60 and 86400, or 0x7FFFFFFF for live locations that can be edited indefinitely. LivePeriod int64 `json:"live_period,omitempty"` // Optional. For live locations, a direction in which the user is moving, in degrees. Must be between 1 and 360 if specified. Heading int64 `json:"heading,omitempty"` @@ -4502,6 +5092,18 @@ var ( _ InputMessageContent = InputInvoiceMessageContent{} ) +// InputPollOption (https://core.telegram.org/bots/api#inputpolloption) +// +// This object contains information about one answer option in a poll to send. +type InputPollOption struct { + // Option text, 1-100 characters + Text string `json:"text"` + // Optional. Mode for parsing entities in the text. See formatting options for more details. Currently, only custom emoji entities are allowed + TextParseMode string `json:"text_parse_mode,omitempty"` + // Optional. A JSON-serialized list of special entities that appear in the poll option text. It can be specified instead of text_parse_mode + TextEntities []MessageEntity `json:"text_entities,omitempty"` +} + // InputSticker (https://core.telegram.org/bots/api#inputsticker) // // This object describes a sticker to be added to a sticker set. @@ -5146,6 +5748,8 @@ type Message struct { ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered,omitempty"` // Optional. Service message: user boosted the chat BoostAdded *ChatBoostAdded `json:"boost_added,omitempty"` + // Optional. Service message: chat background set + ChatBackgroundSet *ChatBackground `json:"chat_background_set,omitempty"` // Optional. Service message: forum topic created ForumTopicCreated *ForumTopicCreated `json:"forum_topic_created,omitempty"` // Optional. Service message: forum topic edited @@ -5248,6 +5852,7 @@ func (v *Message) UnmarshalJSON(b []byte) error { PassportData *PassportData `json:"passport_data"` ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered"` BoostAdded *ChatBoostAdded `json:"boost_added"` + ChatBackgroundSet *ChatBackground `json:"chat_background_set"` ForumTopicCreated *ForumTopicCreated `json:"forum_topic_created"` ForumTopicEdited *ForumTopicEdited `json:"forum_topic_edited"` ForumTopicClosed *ForumTopicClosed `json:"forum_topic_closed"` @@ -5341,6 +5946,7 @@ func (v *Message) UnmarshalJSON(b []byte) error { v.PassportData = t.PassportData v.ProximityAlertTriggered = t.ProximityAlertTriggered v.BoostAdded = t.BoostAdded + v.ChatBackgroundSet = t.ChatBackgroundSet v.ForumTopicCreated = t.ForumTopicCreated v.ForumTopicEdited = t.ForumTopicEdited v.ForumTopicClosed = t.ForumTopicClosed @@ -6432,6 +7038,8 @@ type Poll struct { Id string `json:"id"` // Poll question, 1-300 characters Question string `json:"question"` + // Optional. Special entities that appear in the question. Currently, only custom emoji entities are allowed in poll questions + QuestionEntities []MessageEntity `json:"question_entities,omitempty"` // List of poll options Options []PollOption `json:"options,omitempty"` // Total number of users that voted in the poll @@ -6476,6 +7084,8 @@ type PollAnswer struct { type PollOption struct { // Option text, 1-100 characters Text string `json:"text"` + // Optional. Special entities that appear in the option text. Currently, only custom emoji entities are allowed in poll option texts + TextEntities []MessageEntity `json:"text_entities,omitempty"` // Number of users that voted for this option VoterCount int64 `json:"voter_count"` } @@ -6723,7 +7333,7 @@ func (v ReactionTypeEmoji) reactionType() {} // ReplyKeyboardMarkup (https://core.telegram.org/bots/api#replykeyboardmarkup) // -// This object represents a custom keyboard with reply options (see Introduction to bots for details and examples). +// This object represents a custom keyboard with reply options (see Introduction to bots for details and examples). Not supported in channels and for messages sent on behalf of a Telegram Business account. type ReplyKeyboardMarkup struct { // Array of button rows, each represented by an Array of KeyboardButton objects Keyboard [][]KeyboardButton `json:"keyboard,omitempty"` @@ -6744,7 +7354,7 @@ func (v ReplyKeyboardMarkup) replyMarkup() {} // ReplyKeyboardRemove (https://core.telegram.org/bots/api#replykeyboardremove) // -// Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see ReplyKeyboardMarkup). +// Upon receiving a message with this object, Telegram clients will remove the current custom keyboard and display the default letter-keyboard. By default, custom keyboards are displayed until a new keyboard is sent by a bot. An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see ReplyKeyboardMarkup). Not supported in channels and for messages sent on behalf of a Telegram Business account. type ReplyKeyboardRemove struct { // Requests clients to remove the custom keyboard (user will not be able to summon this keyboard; if you want to hide the keyboard from sight but keep it accessible, use one_time_keyboard in ReplyKeyboardMarkup) RemoveKeyboard bool `json:"remove_keyboard"` diff --git a/spec_commit b/spec_commit index 9d4b8be..e319820 100644 --- a/spec_commit +++ b/spec_commit @@ -1 +1 @@ -93db1105f667e10ee0c699248aae12f30d310cc9 \ No newline at end of file +9fd3d85f0b93e1cb905f6ae11327d77e2167e7cf \ No newline at end of file From 6e83d72d798c7964e414afc1c805767fe92e4c40 Mon Sep 17 00:00:00 2001 From: Paul Larsen Date: Mon, 6 May 2024 17:26:05 +0200 Subject: [PATCH 2/5] Fix up unmarshalFunc generation for interface types --- gen_types.go | 69 +++++++++++++++++++++++++++++++++++++++++ scripts/generate/gen.go | 37 +++++++++++++++------- 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/gen_types.go b/gen_types.go index 864b525..6067255 100755 --- a/gen_types.go +++ b/gen_types.go @@ -120,6 +120,75 @@ func (v MergedBackgroundFill) MergeBackgroundFill() MergedBackgroundFill { return v } +// unmarshalBackgroundFillArray is a JSON unmarshalling helper which allows unmarshalling an array of interfaces +// using unmarshalBackgroundFill. +func unmarshalBackgroundFillArray(d json.RawMessage) ([]BackgroundFill, error) { + if len(d) == 0 { + return nil, nil + } + + var ds []json.RawMessage + err := json.Unmarshal(d, &ds) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal initial BackgroundFill JSON into an array: %w", err) + } + + var vs []BackgroundFill + for idx, d := range ds { + v, err := unmarshalBackgroundFill(d) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundFill on array item %d: %w", idx, err) + } + vs = append(vs, v) + } + + return vs, nil +} + +// unmarshalBackgroundFill is a JSON unmarshal helper to marshal the right structs into a BackgroundFill interface +// based on the Type field. +func unmarshalBackgroundFill(d json.RawMessage) (BackgroundFill, error) { + if len(d) == 0 { + return nil, nil + } + + t := struct { + Type string + }{} + err := json.Unmarshal(d, &t) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundFill for constant field 'Type': %w", err) + } + + switch t.Type { + case "solid": + s := BackgroundFillSolid{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundFill for value 'solid': %w", err) + } + return s, nil + + case "gradient": + s := BackgroundFillGradient{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundFill for value 'gradient': %w", err) + } + return s, nil + + case "freeform_gradient": + s := BackgroundFillFreeformGradient{} + err := json.Unmarshal(d, &s) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BackgroundFill for value 'freeform_gradient': %w", err) + } + return s, nil + + } + return nil, fmt.Errorf("unknown interface for BackgroundFill with Type %v", t.Type) +} + // BackgroundFillFreeformGradient (https://core.telegram.org/bots/api#backgroundfillfreeformgradient) // // The background is a freeform gradient that rotates after every message in the chat. diff --git a/scripts/generate/gen.go b/scripts/generate/gen.go index 1afdd39..307e5ad 100644 --- a/scripts/generate/gen.go +++ b/scripts/generate/gen.go @@ -56,7 +56,7 @@ func (td TypeDescription) sentByAPI(d APIDescription) bool { continue } - if usesChildType(d, child, td.Name, []string{td.Name}) { + if child.usesChildType(d, td.Name, []string{td.Name}) { return true } checked[r] = true @@ -65,26 +65,39 @@ func (td TypeDescription) sentByAPI(d APIDescription) bool { return false } -func usesChildType(d APIDescription, tgType TypeDescription, typeName string, skip []string) bool { - for _, f := range tgType.Fields { +func (td TypeDescription) usesChildType(d APIDescription, typeName string, skip []string) bool { + for _, f := range td.Fields { for _, t := range f.Types { if isTgArray(t) { t = strings.TrimPrefix(t, "Array of ") } - if t == typeName { + if td.isChildType(d, t, typeName, skip) { return true } + } + } - if contains(t, skip) { - continue - } + for _, t := range td.Subtypes { + if td.isChildType(d, t, typeName, skip) { + return true + } + } + return false +} - if child, ok := d.Types[t]; ok && t != tgType.Name { - if usesChildType(d, child, typeName, append(skip, tgType.Name)) { - return true - } - } +func (td TypeDescription) isChildType(d APIDescription, t string, typeName string, skip []string) bool { + if t == typeName { + return true + } + + if contains(t, skip) { + return false + } + + if child, ok := d.Types[t]; ok && t != td.Name { + if child.usesChildType(d, typeName, append(skip, td.Name)) { + return true } } return false From a564ebbfe309972d278148af0776cc3d49116399 Mon Sep 17 00:00:00 2001 From: Paul Larsen Date: Mon, 6 May 2024 19:50:15 +0200 Subject: [PATCH 3/5] add tochat method --- custom_helpers.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/custom_helpers.go b/custom_helpers.go index 4067622..f49dabb 100644 --- a/custom_helpers.go +++ b/custom_helpers.go @@ -78,6 +78,19 @@ func (im InaccessibleMessage) ToMessage() *Message { } } +// ToChat is a helper function to turn a ChatFullInfo struct into a Chat. +func (c ChatFullInfo) ToChat() Chat { + return Chat{ + Id: c.Id, + Type: c.Type, + Title: c.Title, + Username: c.Username, + FirstName: c.FirstName, + LastName: c.LastName, + IsForum: c.IsForum, + } +} + // SendMessage is a helper function to easily call Bot.SendMessage in a chat. func (c Chat) SendMessage(b *Bot, text string, opts *SendMessageOpts) (*Message, error) { return b.SendMessage(c.Id, text, opts) From cd5d15f080621d213bf29e2de937d5f85e6771fc Mon Sep 17 00:00:00 2001 From: Paul Larsen Date: Thu, 9 May 2024 08:19:27 +0100 Subject: [PATCH 4/5] Add joinrequest helper function --- custom_helpers.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/custom_helpers.go b/custom_helpers.go index f49dabb..9eb1f3e 100644 --- a/custom_helpers.go +++ b/custom_helpers.go @@ -111,6 +111,11 @@ func (f File) URL(b *Bot, opts *RequestOpts) string { return b.FileURL(b.Token, f.FilePath, opts) } +// IsJoinRequest returns true if ChatMemberUpdated originated from a join request; either from a direct join, or from an invitelink. +func (cm ChatMemberUpdated) IsJoinRequest() bool { + return cm.ViaJoinRequest || (cm.InviteLink != nil && cm.InviteLink.CreatesJoinRequest) +} + // unmarshalMaybeInaccessibleMessage is a JSON unmarshal helper to marshal the right structs into a // MaybeInaccessibleMessage interface based on the Date field. // This method is manually maintained due to special-case handling on the Date field rather than a specific type field. From 6138f301344c56b5eda192734b05a2cc5327a3b8 Mon Sep 17 00:00:00 2001 From: Paul Larsen Date: Thu, 9 May 2024 08:19:45 +0100 Subject: [PATCH 5/5] Merge in latest docs changes --- gen_types.go | 6 +++--- spec_commit | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gen_types.go b/gen_types.go index 6067255..4954a29 100755 --- a/gen_types.go +++ b/gen_types.go @@ -1606,7 +1606,7 @@ type ChatFullInfo struct { HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages,omitempty"` // Optional. True, if users need to join the supergroup before they can send messages JoinToSendMessages bool `json:"join_to_send_messages,omitempty"` - // Optional. True, if all users directly joining the supergroup need to be approved by supergroup administrators + // Optional. True, if all users directly joining the supergroup without using an invite link need to be approved by supergroup administrators JoinByRequest bool `json:"join_by_request,omitempty"` // Optional. Description, for groups, supergroups and channel chats Description string `json:"description,omitempty"` @@ -2379,7 +2379,7 @@ type ChatMemberUpdated struct { NewChatMember ChatMember `json:"new_chat_member"` // Optional. Chat invite link, which was used by the user to join the chat; for joining by invite link events only. InviteLink *ChatInviteLink `json:"invite_link,omitempty"` - // Optional. True, if the user joined the chat after sending a direct join request and being approved by an administrator + // Optional. True, if the user joined the chat after sending a direct join request without using an invite link and being approved by an administrator ViaJoinRequest bool `json:"via_join_request,omitempty"` // Optional. True, if the user joined the chat via a chat folder invite link ViaChatFolderInviteLink bool `json:"via_chat_folder_invite_link,omitempty"` @@ -7661,7 +7661,7 @@ type Update struct { EditedChannelPost *Message `json:"edited_channel_post,omitempty"` // Optional. The bot was connected to or disconnected from a business account, or a user edited an existing connection with the bot BusinessConnection *BusinessConnection `json:"business_connection,omitempty"` - // Optional. New non-service message from a connected business account + // Optional. New message from a connected business account BusinessMessage *Message `json:"business_message,omitempty"` // Optional. New version of a message from a connected business account EditedBusinessMessage *Message `json:"edited_business_message,omitempty"` diff --git a/spec_commit b/spec_commit index e319820..1b7715e 100644 --- a/spec_commit +++ b/spec_commit @@ -1 +1 @@ -9fd3d85f0b93e1cb905f6ae11327d77e2167e7cf \ No newline at end of file +68843d1ae456b90a494bfee92253f30a8204b2a7 \ No newline at end of file