diff --git a/api/methods.gen.go b/api/methods.gen.go index 070576b..df48c20 100644 --- a/api/methods.gen.go +++ b/api/methods.gen.go @@ -1875,7 +1875,7 @@ type SendPollParams struct { // A JSON-serialized list of special entities that appear in the poll explanation. It can be specified instead of explanation_parse_mode ExplanationEntities []MessageEntity `json:"explanation_entities,omitempty"` // Media added to the quiz explanation - ExplanationMedia *InputPollMedia `json:"explanation_media,omitempty"` + ExplanationMedia InputPollMedia `json:"explanation_media,omitempty"` // Amount of time in seconds the poll will be active after creation, 5-2628000. Can't be used together with close_date. OpenPeriod *int64 `json:"open_period,omitempty"` // Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 2628000 seconds in the future. Can't be used together with open_period. @@ -1889,7 +1889,7 @@ type SendPollParams struct { // A JSON-serialized list of special entities that appear in the poll description, which can be specified instead of description_parse_mode DescriptionEntities []MessageEntity `json:"description_entities,omitempty"` // Media added to the poll description - Media *InputPollMedia `json:"media,omitempty"` + Media InputPollMedia `json:"media,omitempty"` // Sends the message silently. Users will receive a notification with no sound. DisableNotification *bool `json:"disable_notification,omitempty"` // Protects the contents of the sent message from forwarding and saving @@ -3140,7 +3140,7 @@ type SetMyCommandsParams struct { // A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified. Commands []BotCommand `json:"commands"` // A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. - Scope *BotCommandScope `json:"scope,omitempty"` + Scope BotCommandScope `json:"scope,omitempty"` // A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands LanguageCode string `json:"language_code,omitempty"` } @@ -3157,7 +3157,7 @@ func SetMyCommands(ctx context.Context, b *client.Bot, p *SetMyCommandsParams) ( // Use this method to delete the list of the bot's commands for the given scope and user language. After deletion, higher level commands will be shown to affected users. Returns True on success. type DeleteMyCommandsParams struct { // A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. - Scope *BotCommandScope `json:"scope,omitempty"` + Scope BotCommandScope `json:"scope,omitempty"` // A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands LanguageCode string `json:"language_code,omitempty"` } @@ -3174,7 +3174,7 @@ func DeleteMyCommands(ctx context.Context, b *client.Bot, p *DeleteMyCommandsPar // Use this method to get the current list of the bot's commands for the given scope and user language. Returns an Array of BotCommand objects. If commands aren't set, an empty list is returned. type GetMyCommandsParams struct { // A JSON-serialized object, describing scope of users. Defaults to BotCommandScopeDefault. - Scope *BotCommandScope `json:"scope,omitempty"` + Scope BotCommandScope `json:"scope,omitempty"` // A two-letter ISO 639-1 language code or an empty string LanguageCode string `json:"language_code,omitempty"` } diff --git a/api/types.gen.go b/api/types.gen.go index 84a30da..71efc08 100644 --- a/api/types.gen.go +++ b/api/types.gen.go @@ -1288,7 +1288,7 @@ type InputPollOption struct { // 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"` // Optional. Media added to the poll option - Media *InputPollOptionMedia `json:"media,omitempty"` + Media InputPollOptionMedia `json:"media,omitempty"` } // This object represents an answer of a user in a non-anonymous poll. @@ -4550,7 +4550,7 @@ type InlineQueryResultPhoto struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the photo - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to an animated GIF file. By default, this animated GIF file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4584,7 +4584,7 @@ type InlineQueryResultGif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the GIF animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a video animation (H.264/MPEG-4 AVC video without sound). By default, this animated MPEG-4 file will be sent by the user with optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4618,7 +4618,7 @@ type InlineQueryResultMpeg4Gif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a page containing an embedded video player or a video file. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video. @@ -4655,7 +4655,7 @@ type InlineQueryResultVideo struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video. This field is required if InlineQueryResultVideo is used to send an HTML-page as a result (e.g., a YouTube video). - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to an MP3 audio file. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio. @@ -4681,7 +4681,7 @@ type InlineQueryResultAudio struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the audio - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a voice recording in an .OGG container encoded with OPUS. By default, this voice recording will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the the voice message. @@ -4705,7 +4705,7 @@ type InlineQueryResultVoice struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the voice recording - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a file. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. Currently, only .PDF and .ZIP files can be sent using this method. @@ -4731,7 +4731,7 @@ type InlineQueryResultDocument struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the file - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. URL of the thumbnail (JPEG only) for the file ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -4763,7 +4763,7 @@ type InlineQueryResultLocation struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the location - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. Url of the thumbnail for the result ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -4797,7 +4797,7 @@ type InlineQueryResultVenue struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the venue - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. Url of the thumbnail for the result ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -4823,7 +4823,7 @@ type InlineQueryResultContact struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the contact - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. Url of the thumbnail for the result ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -4867,7 +4867,7 @@ type InlineQueryResultCachedPhoto struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the photo - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to an animated GIF file stored on the Telegram servers. By default, this animated GIF file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with specified content instead of the animation. @@ -4891,7 +4891,7 @@ type InlineQueryResultCachedGif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the GIF animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a video animation (H.264/MPEG-4 AVC video without sound) stored on the Telegram servers. By default, this animated MPEG-4 file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the animation. @@ -4915,7 +4915,7 @@ type InlineQueryResultCachedMpeg4Gif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a sticker stored on the Telegram servers. By default, this sticker will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the sticker. @@ -4929,7 +4929,7 @@ type InlineQueryResultCachedSticker struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the sticker - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a file stored on the Telegram servers. By default, this file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the file. @@ -4953,7 +4953,7 @@ type InlineQueryResultCachedDocument struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the file - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a video file stored on the Telegram servers. By default, this video file will be sent by the user with an optional caption. Alternatively, you can use input_message_content to send a message with the specified content instead of the video. @@ -4979,7 +4979,7 @@ type InlineQueryResultCachedVideo struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to a voice message stored on the Telegram servers. By default, this voice message will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the voice message. @@ -5001,7 +5001,7 @@ type InlineQueryResultCachedVoice struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the voice message - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // Represents a link to an MP3 audio file stored on the Telegram servers. By default, this audio file will be sent by the user. Alternatively, you can use input_message_content to send a message with the specified content instead of the audio. @@ -5021,7 +5021,7 @@ type InlineQueryResultCachedAudio struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the audio - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } // InputMessageContent is a union type. The following concrete variants implement diff --git a/api/unionparam_test.go b/api/unionparam_test.go new file mode 100644 index 0000000..72df034 --- /dev/null +++ b/api/unionparam_test.go @@ -0,0 +1,77 @@ +package api + +import ( + "context" + "io" + "net/http" + "strings" + "testing" + + "github.com/lukaszraczylo/go-telegram/client" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +// TestSetMyCommands_BotCommandScope_NoPointerToInterface is a regression +// test for the bug where sealed-interface union types without an +// auto-decode discriminator (BotCommandScope, InputMedia, etc.) were +// emitted as `*` (pointer-to-interface) when used as optional +// fields. Pointer-to-interface is a Go anti-pattern: the interface is +// already nil-able, and callers were forced to write +// `Scope: &someConcreteScope` instead of `Scope: someConcreteScope`. +// +// This test confirms the field is now bare-interface-typed: a concrete +// variant assigns directly, and a nil scope omits the field via +// omitempty. +func TestSetMyCommands_BotCommandScope_NoPointerToInterface(t *testing.T) { + var captured string + m := &mockDoer{} + m.On("Do", mock.MatchedBy(func(r *http.Request) bool { + if r.Body != nil { + b, _ := io.ReadAll(r.Body) + captured = string(b) + } + return true + })).Return(&http.Response{ + StatusCode: 200, + Body: io.NopCloser(strings.NewReader(`{"ok":true,"result":true}`)), + Header: http.Header{"Content-Type": []string{"application/json"}}, + }, nil) + + bot := client.New("test:token", client.WithHTTPClient(m)) + + // Direct assignment of a concrete variant — only possible when Scope + // is `BotCommandScope` (interface), not `*BotCommandScope`. + ok, err := SetMyCommands(context.Background(), bot, &SetMyCommandsParams{ + Commands: []BotCommand{{Command: "start", Description: "begin"}}, + Scope: &BotCommandScopeAllPrivateChats{Type: "all_private_chats"}, + }) + require.NoError(t, err) + require.True(t, ok) + require.Contains(t, captured, `"scope":{"type":"all_private_chats"}`) +} + +// TestSetMyCommands_NilScope_OmitsField confirms omitempty works on the +// bare-interface field when the caller doesn't supply a scope. +func TestSetMyCommands_NilScope_OmitsField(t *testing.T) { + var captured string + m := &mockDoer{} + m.On("Do", mock.MatchedBy(func(r *http.Request) bool { + if r.Body != nil { + b, _ := io.ReadAll(r.Body) + captured = string(b) + } + return true + })).Return(&http.Response{ + StatusCode: 200, + Body: io.NopCloser(strings.NewReader(`{"ok":true,"result":true}`)), + Header: http.Header{"Content-Type": []string{"application/json"}}, + }, nil) + + bot := client.New("test:token", client.WithHTTPClient(m)) + _, err := SetMyCommands(context.Background(), bot, &SetMyCommandsParams{ + Commands: []BotCommand{{Command: "start", Description: "begin"}}, + }) + require.NoError(t, err) + require.NotContains(t, captured, `"scope"`, "nil scope must be omitted from JSON") +} diff --git a/cmd/genapi/emitter.go b/cmd/genapi/emitter.go index 6e3fae6..d1a15be 100644 --- a/cmd/genapi/emitter.go +++ b/cmd/genapi/emitter.go @@ -168,9 +168,18 @@ type emitter struct { } func newEmitter(api *spec.API, outDir string) *emitter { + knownInterfaceTypes = buildUnionTypeSet(api) return &emitter{api: api, outDir: outDir, enums: planEnums(api)} } +// knownInterfaceTypes is the full set of sealed-interface union type names +// (both auto-decoded ones in knownDiscriminators and marker-only ones from +// types with OneOf). Populated at emitter construction. goType and +// unionTypeFor consult this so optional fields of any union type stay +// bare interface, never *Interface (which is meaningless in Go and trips +// users at every call site). +var knownInterfaceTypes = map[string]bool{} + // emitTypes renders types.gen.go. func (e *emitter) emitTypes() error { t, err := template.New("types").Funcs(funcs(e.enums)).Parse(typesTmpl) @@ -477,7 +486,7 @@ func goType(tr spec.TypeRef, optional bool) string { // multipart helpers (fileCheck, multipartFileEntry) call // f.IsLocalUpload() and dereference Reader, both of which // expect a pointer receiver. - if _, isUnion := knownDiscriminators[tr.Name]; isUnion { + if knownInterfaceTypes[tr.Name] { // Interface type — never add *. return tr.Name } diff --git a/docs/reference/api.md b/docs/reference/api.md index 854a581..95e9a98 100644 --- a/docs/reference/api.md +++ b/docs/reference/api.md @@ -4690,7 +4690,7 @@ Use this method to delete the list of the bot's commands for the given scope and ```go type DeleteMyCommandsParams struct { // A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. - Scope *BotCommandScope `json:"scope,omitempty"` + Scope BotCommandScope `json:"scope,omitempty"` // A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands LanguageCode string `json:"language_code,omitempty"` } @@ -5860,7 +5860,7 @@ Use this method to get the current list of the bot's commands for the given scop ```go type GetMyCommandsParams struct { // A JSON-serialized object, describing scope of users. Defaults to BotCommandScopeDefault. - Scope *BotCommandScope `json:"scope,omitempty"` + Scope BotCommandScope `json:"scope,omitempty"` // A two-letter ISO 639-1 language code or an empty string LanguageCode string `json:"language_code,omitempty"` } @@ -6528,7 +6528,7 @@ type InlineQueryResultAudio struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the audio - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6554,7 +6554,7 @@ type InlineQueryResultCachedAudio struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the audio - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6584,7 +6584,7 @@ type InlineQueryResultCachedDocument struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the file - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6614,7 +6614,7 @@ type InlineQueryResultCachedGif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the GIF animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6644,7 +6644,7 @@ type InlineQueryResultCachedMpeg4Gif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6676,7 +6676,7 @@ type InlineQueryResultCachedPhoto struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the photo - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6696,7 +6696,7 @@ type InlineQueryResultCachedSticker struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the sticker - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6728,7 +6728,7 @@ type InlineQueryResultCachedVideo struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6756,7 +6756,7 @@ type InlineQueryResultCachedVoice struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the voice message - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6782,7 +6782,7 @@ type InlineQueryResultContact struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the contact - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. Url of the thumbnail for the result ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -6820,7 +6820,7 @@ type InlineQueryResultDocument struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the file - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. URL of the thumbnail (JPEG only) for the file ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -6902,7 +6902,7 @@ type InlineQueryResultGif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the GIF animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -6953,7 +6953,7 @@ type InlineQueryResultLocation struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the location - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. Url of the thumbnail for the result ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -6999,7 +6999,7 @@ type InlineQueryResultMpeg4Gif struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video animation - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -7037,7 +7037,7 @@ type InlineQueryResultPhoto struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the photo - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -7071,7 +7071,7 @@ type InlineQueryResultVenue struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the venue - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` // Optional. Url of the thumbnail for the result ThumbnailURL string `json:"thumbnail_url,omitempty"` // Optional. Thumbnail width @@ -7119,7 +7119,7 @@ type InlineQueryResultVideo struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the video. This field is required if InlineQueryResultVideo is used to send an HTML-page as a result (e.g., a YouTube video). - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -7149,7 +7149,7 @@ type InlineQueryResultVoice struct { // Optional. Inline keyboard attached to the message ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` // Optional. Content of the message to be sent instead of the voice recording - InputMessageContent *InputMessageContent `json:"input_message_content,omitempty"` + InputMessageContent InputMessageContent `json:"input_message_content,omitempty"` } ``` @@ -7710,7 +7710,7 @@ type InputPollOption struct { // 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"` // Optional. Media added to the poll option - Media *InputPollOptionMedia `json:"media,omitempty"` + Media InputPollOptionMedia `json:"media,omitempty"` } ``` @@ -12102,7 +12102,7 @@ type SendPollParams struct { // A JSON-serialized list of special entities that appear in the poll explanation. It can be specified instead of explanation_parse_mode ExplanationEntities []MessageEntity `json:"explanation_entities,omitempty"` // Media added to the quiz explanation - ExplanationMedia *InputPollMedia `json:"explanation_media,omitempty"` + ExplanationMedia InputPollMedia `json:"explanation_media,omitempty"` // Amount of time in seconds the poll will be active after creation, 5-2628000. Can't be used together with close_date. OpenPeriod *int64 `json:"open_period,omitempty"` // Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 2628000 seconds in the future. Can't be used together with open_period. @@ -12116,7 +12116,7 @@ type SendPollParams struct { // A JSON-serialized list of special entities that appear in the poll description, which can be specified instead of description_parse_mode DescriptionEntities []MessageEntity `json:"description_entities,omitempty"` // Media added to the poll description - Media *InputPollMedia `json:"media,omitempty"` + Media InputPollMedia `json:"media,omitempty"` // Sends the message silently. Users will receive a notification with no sound. DisableNotification *bool `json:"disable_notification,omitempty"` // Protects the contents of the sent message from forwarding and saving @@ -12911,7 +12911,7 @@ type SetMyCommandsParams struct { // A JSON-serialized list of bot commands to be set as the list of the bot's commands. At most 100 commands can be specified. Commands []BotCommand `json:"commands"` // A JSON-serialized object, describing scope of users for which the commands are relevant. Defaults to BotCommandScopeDefault. - Scope *BotCommandScope `json:"scope,omitempty"` + Scope BotCommandScope `json:"scope,omitempty"` // A two-letter ISO 639-1 language code. If empty, commands will be applied to all users from the given scope, for whose language there are no dedicated commands LanguageCode string `json:"language_code,omitempty"` }