diff options
author | Thom Dickson <td3of4@gmail.com> | 2023-03-14 18:03:04 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-14 23:03:04 +0100 |
commit | 601f48a50ea31a9631011766c680ecef931ddafc (patch) | |
tree | aa88bff487f12a05d70c7677ddc2a3e14bbd9fbf /vendor/github.com/matterbridge/telegram-bot-api/v6/configs.go | |
parent | c2b8e298d8c0a15a0e6489b658efe58030a18164 (diff) | |
download | matterbridge-msglm-601f48a50ea31a9631011766c680ecef931ddafc.tar.gz matterbridge-msglm-601f48a50ea31a9631011766c680ecef931ddafc.tar.bz2 matterbridge-msglm-601f48a50ea31a9631011766c680ecef931ddafc.zip |
Add support for Telegram topics (telegram) (#1942)
Topics are surfaced by appending /<topic-id> to the channel setting for the gateway.
An example for the topic with ID of 16 would be:
```
[[gateway.inout]]
account="telegram.mytelegram"
channel="-100xxxxxxxxxx/16"
```
Diffstat (limited to 'vendor/github.com/matterbridge/telegram-bot-api/v6/configs.go')
-rw-r--r-- | vendor/github.com/matterbridge/telegram-bot-api/v6/configs.go | 2934 |
1 files changed, 2934 insertions, 0 deletions
diff --git a/vendor/github.com/matterbridge/telegram-bot-api/v6/configs.go b/vendor/github.com/matterbridge/telegram-bot-api/v6/configs.go new file mode 100644 index 00000000..09c9c468 --- /dev/null +++ b/vendor/github.com/matterbridge/telegram-bot-api/v6/configs.go @@ -0,0 +1,2934 @@ +package tgbotapi + +import ( + "bytes" + "fmt" + "io" + "net/url" + "os" + "strconv" +) + +// Telegram constants +const ( + // APIEndpoint is the endpoint for all API methods, + // with formatting for Sprintf. + APIEndpoint = "https://api.telegram.org/bot%s/%s" + // FileEndpoint is the endpoint for downloading a file from Telegram. + FileEndpoint = "https://api.telegram.org/file/bot%s/%s" +) + +// Constant values for ChatActions +const ( + ChatTyping = "typing" + ChatUploadPhoto = "upload_photo" + ChatRecordVideo = "record_video" + ChatUploadVideo = "upload_video" + ChatRecordVoice = "record_voice" + ChatUploadVoice = "upload_voice" + ChatUploadDocument = "upload_document" + ChatChooseSticker = "choose_sticker" + ChatFindLocation = "find_location" + ChatRecordVideoNote = "record_video_note" + ChatUploadVideoNote = "upload_video_note" +) + +// API errors +const ( + // ErrAPIForbidden happens when a token is bad + ErrAPIForbidden = "forbidden" +) + +// Constant values for ParseMode in MessageConfig +const ( + ModeMarkdown = "Markdown" + ModeMarkdownV2 = "MarkdownV2" + ModeHTML = "HTML" +) + +// Constant values for update types +const ( + // UpdateTypeMessage is new incoming message of any kind — text, photo, sticker, etc. + UpdateTypeMessage = "message" + + // UpdateTypeEditedMessage is new version of a message that is known to the bot and was edited + UpdateTypeEditedMessage = "edited_message" + + // UpdateTypeChannelPost is new incoming channel post of any kind — text, photo, sticker, etc. + UpdateTypeChannelPost = "channel_post" + + // UpdateTypeEditedChannelPost is new version of a channel post that is known to the bot and was edited + UpdateTypeEditedChannelPost = "edited_channel_post" + + // UpdateTypeInlineQuery is new incoming inline query + UpdateTypeInlineQuery = "inline_query" + + // UpdateTypeChosenInlineResult i the result of an inline query that was chosen by a user and sent to their + // chat partner. Please see the documentation on the feedback collecting for + // details on how to enable these updates for your bot. + UpdateTypeChosenInlineResult = "chosen_inline_result" + + // UpdateTypeCallbackQuery is new incoming callback query + UpdateTypeCallbackQuery = "callback_query" + + // UpdateTypeShippingQuery is new incoming shipping query. Only for invoices with flexible price + UpdateTypeShippingQuery = "shipping_query" + + // UpdateTypePreCheckoutQuery is new incoming pre-checkout query. Contains full information about checkout + UpdateTypePreCheckoutQuery = "pre_checkout_query" + + // UpdateTypePoll is new poll state. Bots receive only updates about stopped polls and polls + // which are sent by the bot + UpdateTypePoll = "poll" + + // UpdateTypePollAnswer is when user changed their answer in a non-anonymous poll. Bots receive new votes + // only in polls that were sent by the bot itself. + UpdateTypePollAnswer = "poll_answer" + + // UpdateTypeMyChatMember is when the bot's chat member status was updated in a chat. For private chats, this + // update is received only when the bot is blocked or unblocked by the user. + UpdateTypeMyChatMember = "my_chat_member" + + // UpdateTypeChatMember is when the bot must be an administrator in the chat and must explicitly specify + // this update in the list of allowed_updates to receive these updates. + UpdateTypeChatMember = "chat_member" +) + +// Library errors +const ( + ErrBadURL = "bad or empty url" +) + +// Chattable is any config type that can be sent. +type Chattable interface { + params() (Params, error) + method() string +} + +// Fileable is any config type that can be sent that includes a file. +type Fileable interface { + Chattable + files() []RequestFile +} + +// RequestFile represents a file associated with a field name. +type RequestFile struct { + // The file field name. + Name string + // The file data to include. + Data RequestFileData +} + +// RequestFileData represents the data to be used for a file. +type RequestFileData interface { + // NeedsUpload shows if the file needs to be uploaded. + NeedsUpload() bool + + // UploadData gets the file name and an `io.Reader` for the file to be uploaded. This + // must only be called when the file needs to be uploaded. + UploadData() (string, io.Reader, error) + // SendData gets the file data to send when a file does not need to be uploaded. This + // must only be called when the file does not need to be uploaded. + SendData() string +} + +// FileBytes contains information about a set of bytes to upload +// as a File. +type FileBytes struct { + Name string + Bytes []byte +} + +func (fb FileBytes) NeedsUpload() bool { + return true +} + +func (fb FileBytes) UploadData() (string, io.Reader, error) { + return fb.Name, bytes.NewReader(fb.Bytes), nil +} + +func (fb FileBytes) SendData() string { + panic("FileBytes must be uploaded") +} + +// FileReader contains information about a reader to upload as a File. +type FileReader struct { + Name string + Reader io.Reader +} + +func (fr FileReader) NeedsUpload() bool { + return true +} + +func (fr FileReader) UploadData() (string, io.Reader, error) { + return fr.Name, fr.Reader, nil +} + +func (fr FileReader) SendData() string { + panic("FileReader must be uploaded") +} + +// FilePath is a path to a local file. +type FilePath string + +func (fp FilePath) NeedsUpload() bool { + return true +} + +func (fp FilePath) UploadData() (string, io.Reader, error) { + fileHandle, err := os.Open(string(fp)) + if err != nil { + return "", nil, err + } + + name := fileHandle.Name() + return name, fileHandle, err +} + +func (fp FilePath) SendData() string { + panic("FilePath must be uploaded") +} + +// FileURL is a URL to use as a file for a request. +type FileURL string + +func (fu FileURL) NeedsUpload() bool { + return false +} + +func (fu FileURL) UploadData() (string, io.Reader, error) { + panic("FileURL cannot be uploaded") +} + +func (fu FileURL) SendData() string { + return string(fu) +} + +// FileID is an ID of a file already uploaded to Telegram. +type FileID string + +func (fi FileID) NeedsUpload() bool { + return false +} + +func (fi FileID) UploadData() (string, io.Reader, error) { + panic("FileID cannot be uploaded") +} + +func (fi FileID) SendData() string { + return string(fi) +} + +// fileAttach is an internal file type used for processed media groups. +type fileAttach string + +func (fa fileAttach) NeedsUpload() bool { + return false +} + +func (fa fileAttach) UploadData() (string, io.Reader, error) { + panic("fileAttach cannot be uploaded") +} + +func (fa fileAttach) SendData() string { + return string(fa) +} + +// LogOutConfig is a request to log out of the cloud Bot API server. +// +// Note that you may not log back in for at least 10 minutes. +type LogOutConfig struct{} + +func (LogOutConfig) method() string { + return "logOut" +} + +func (LogOutConfig) params() (Params, error) { + return nil, nil +} + +// CloseConfig is a request to close the bot instance on a local server. +// +// Note that you may not close an instance for the first 10 minutes after the +// bot has started. +type CloseConfig struct{} + +func (CloseConfig) method() string { + return "close" +} + +func (CloseConfig) params() (Params, error) { + return nil, nil +} + +// BaseChat is base type for all chat config types. +type BaseChat struct { + ChatID int64 // required + MessageThreadID int + ChannelUsername string + ProtectContent bool + ReplyToMessageID int + ReplyMarkup interface{} + DisableNotification bool + AllowSendingWithoutReply bool +} + +func (chat *BaseChat) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername) + params.AddNonZero("message_thread_id", chat.MessageThreadID) + params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID) + params.AddBool("disable_notification", chat.DisableNotification) + params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply) + params.AddBool("protect_content", chat.ProtectContent) + + err := params.AddInterface("reply_markup", chat.ReplyMarkup) + + return params, err +} + +// BaseFile is a base type for all file config types. +type BaseFile struct { + BaseChat + File RequestFileData +} + +func (file BaseFile) params() (Params, error) { + return file.BaseChat.params() +} + +// BaseEdit is base type of all chat edits. +type BaseEdit struct { + ChatID int64 + ChannelUsername string + MessageID int + InlineMessageID string + ReplyMarkup *InlineKeyboardMarkup +} + +func (edit BaseEdit) params() (Params, error) { + params := make(Params) + + if edit.InlineMessageID != "" { + params["inline_message_id"] = edit.InlineMessageID + } else { + params.AddFirstValid("chat_id", edit.ChatID, edit.ChannelUsername) + params.AddNonZero("message_id", edit.MessageID) + } + + err := params.AddInterface("reply_markup", edit.ReplyMarkup) + + return params, err +} + +// BaseSpoiler is base type of structures with spoilers. +type BaseSpoiler struct { + HasSpoiler bool +} + +func (spoiler BaseSpoiler) params() (Params, error) { + params := make(Params) + + if spoiler.HasSpoiler { + params.AddBool("has_spoiler", true) + } + + return params, nil +} + +// MessageConfig contains information about a SendMessage request. +type MessageConfig struct { + BaseChat + Text string + ParseMode string + Entities []MessageEntity + DisableWebPagePreview bool +} + +func (config MessageConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonEmpty("text", config.Text) + params.AddBool("disable_web_page_preview", config.DisableWebPagePreview) + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("entities", config.Entities) + + return params, err +} + +func (config MessageConfig) method() string { + return "sendMessage" +} + +// ForwardConfig contains information about a ForwardMessage request. +type ForwardConfig struct { + BaseChat + FromChatID int64 // required + FromChannelUsername string + MessageID int // required +} + +func (config ForwardConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonZero64("from_chat_id", config.FromChatID) + params.AddNonZero("message_id", config.MessageID) + + return params, nil +} + +func (config ForwardConfig) method() string { + return "forwardMessage" +} + +// CopyMessageConfig contains information about a copyMessage request. +type CopyMessageConfig struct { + BaseChat + FromChatID int64 + FromChannelUsername string + MessageID int + Caption string + ParseMode string + CaptionEntities []MessageEntity +} + +func (config CopyMessageConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddFirstValid("from_chat_id", config.FromChatID, config.FromChannelUsername) + params.AddNonZero("message_id", config.MessageID) + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("caption_entities", config.CaptionEntities) + + return params, err +} + +func (config CopyMessageConfig) method() string { + return "copyMessage" +} + +// PhotoConfig contains information about a SendPhoto request. +type PhotoConfig struct { + BaseFile + BaseSpoiler + Thumb RequestFileData + Caption string + ParseMode string + CaptionEntities []MessageEntity +} + +func (config PhotoConfig) params() (Params, error) { + params, err := config.BaseFile.params() + if err != nil { + return params, err + } + + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("caption_entities", config.CaptionEntities) + if err != nil { + return params, err + } + + p1, err := config.BaseSpoiler.params() + if err != nil { + return params, err + } + params.Merge(p1) + + return params, err +} + +func (config PhotoConfig) method() string { + return "sendPhoto" +} + +func (config PhotoConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "photo", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// AudioConfig contains information about a SendAudio request. +type AudioConfig struct { + BaseFile + Thumb RequestFileData + Caption string + ParseMode string + CaptionEntities []MessageEntity + Duration int + Performer string + Title string +} + +func (config AudioConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonZero("duration", config.Duration) + params.AddNonEmpty("performer", config.Performer) + params.AddNonEmpty("title", config.Title) + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("caption_entities", config.CaptionEntities) + + return params, err +} + +func (config AudioConfig) method() string { + return "sendAudio" +} + +func (config AudioConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "audio", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// DocumentConfig contains information about a SendDocument request. +type DocumentConfig struct { + BaseFile + Thumb RequestFileData + Caption string + ParseMode string + CaptionEntities []MessageEntity + DisableContentTypeDetection bool +} + +func (config DocumentConfig) params() (Params, error) { + params, err := config.BaseFile.params() + + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + params.AddBool("disable_content_type_detection", config.DisableContentTypeDetection) + + return params, err +} + +func (config DocumentConfig) method() string { + return "sendDocument" +} + +func (config DocumentConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "document", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// StickerConfig contains information about a SendSticker request. +type StickerConfig struct { + BaseFile +} + +func (config StickerConfig) params() (Params, error) { + return config.BaseChat.params() +} + +func (config StickerConfig) method() string { + return "sendSticker" +} + +func (config StickerConfig) files() []RequestFile { + return []RequestFile{{ + Name: "sticker", + Data: config.File, + }} +} + +// VideoConfig contains information about a SendVideo request. +type VideoConfig struct { + BaseFile + BaseSpoiler + Thumb RequestFileData + Duration int + Caption string + ParseMode string + CaptionEntities []MessageEntity + SupportsStreaming bool +} + +func (config VideoConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonZero("duration", config.Duration) + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + params.AddBool("supports_streaming", config.SupportsStreaming) + err = params.AddInterface("caption_entities", config.CaptionEntities) + if err != nil { + return params, err + } + + p1, err := config.BaseSpoiler.params() + if err != nil { + return params, err + } + params.Merge(p1) + + return params, err +} + +func (config VideoConfig) method() string { + return "sendVideo" +} + +func (config VideoConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "video", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// AnimationConfig contains information about a SendAnimation request. +type AnimationConfig struct { + BaseFile + BaseSpoiler + Duration int + Thumb RequestFileData + Caption string + ParseMode string + CaptionEntities []MessageEntity +} + +func (config AnimationConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonZero("duration", config.Duration) + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("caption_entities", config.CaptionEntities) + if err != nil { + return params, err + } + + p1, err := config.BaseSpoiler.params() + if err != nil { + return params, err + } + params.Merge(p1) + + return params, err +} + +func (config AnimationConfig) method() string { + return "sendAnimation" +} + +func (config AnimationConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "animation", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// VideoNoteConfig contains information about a SendVideoNote request. +type VideoNoteConfig struct { + BaseFile + Thumb RequestFileData + Duration int + Length int +} + +func (config VideoNoteConfig) params() (Params, error) { + params, err := config.BaseChat.params() + + params.AddNonZero("duration", config.Duration) + params.AddNonZero("length", config.Length) + + return params, err +} + +func (config VideoNoteConfig) method() string { + return "sendVideoNote" +} + +func (config VideoNoteConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "video_note", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// VoiceConfig contains information about a SendVoice request. +type VoiceConfig struct { + BaseFile + Thumb RequestFileData + Caption string + ParseMode string + CaptionEntities []MessageEntity + Duration int +} + +func (config VoiceConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonZero("duration", config.Duration) + params.AddNonEmpty("caption", config.Caption) + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("caption_entities", config.CaptionEntities) + + return params, err +} + +func (config VoiceConfig) method() string { + return "sendVoice" +} + +func (config VoiceConfig) files() []RequestFile { + files := []RequestFile{{ + Name: "voice", + Data: config.File, + }} + + if config.Thumb != nil { + files = append(files, RequestFile{ + Name: "thumb", + Data: config.Thumb, + }) + } + + return files +} + +// LocationConfig contains information about a SendLocation request. +type LocationConfig struct { + BaseChat + Latitude float64 // required + Longitude float64 // required + HorizontalAccuracy float64 // optional + LivePeriod int // optional + Heading int // optional + ProximityAlertRadius int // optional +} + +func (config LocationConfig) params() (Params, error) { + params, err := config.BaseChat.params() + + params.AddNonZeroFloat("latitude", config.Latitude) + params.AddNonZeroFloat("longitude", config.Longitude) + params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy) + params.AddNonZero("live_period", config.LivePeriod) + params.AddNonZero("heading", config.Heading) + params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius) + + return params, err +} + +func (config LocationConfig) method() string { + return "sendLocation" +} + +// EditMessageLiveLocationConfig allows you to update a live location. +type EditMessageLiveLocationConfig struct { + BaseEdit + Latitude float64 // required + Longitude float64 // required + HorizontalAccuracy float64 // optional + Heading int // optional + ProximityAlertRadius int // optional +} + +func (config EditMessageLiveLocationConfig) params() (Params, error) { + params, err := config.BaseEdit.params() + + params.AddNonZeroFloat("latitude", config.Latitude) + params.AddNonZeroFloat("longitude", config.Longitude) + params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy) + params.AddNonZero("heading", config.Heading) + params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius) + + return params, err +} + +func (config EditMessageLiveLocationConfig) method() string { + return "editMessageLiveLocation" +} + +// StopMessageLiveLocationConfig stops updating a live location. +type StopMessageLiveLocationConfig struct { + BaseEdit +} + +func (config StopMessageLiveLocationConfig) params() (Params, error) { + return config.BaseEdit.params() +} + +func (config StopMessageLiveLocationConfig) method() string { + return "stopMessageLiveLocation" +} + +// VenueConfig contains information about a SendVenue request. +type VenueConfig struct { + BaseChat + Latitude float64 // required + Longitude float64 // required + Title string // required + Address string // required + FoursquareID string + FoursquareType string + GooglePlaceID string + GooglePlaceType string +} + +func (config VenueConfig) params() (Params, error) { + params, err := config.BaseChat.params() + + params.AddNonZeroFloat("latitude", config.Latitude) + params.AddNonZeroFloat("longitude", config.Longitude) + params["title"] = config.Title + params["address"] = config.Address + params.AddNonEmpty("foursquare_id", config.FoursquareID) + params.AddNonEmpty("foursquare_type", config.FoursquareType) + params.AddNonEmpty("google_place_id", config.GooglePlaceID) + params.AddNonEmpty("google_place_type", config.GooglePlaceType) + + return params, err +} + +func (config VenueConfig) method() string { + return "sendVenue" +} + +// ContactConfig allows you to send a contact. +type ContactConfig struct { + BaseChat + PhoneNumber string + FirstName string + LastName string + VCard string +} + +func (config ContactConfig) params() (Params, error) { + params, err := config.BaseChat.params() + + params["phone_number"] = config.PhoneNumber + params["first_name"] = config.FirstName + + params.AddNonEmpty("last_name", config.LastName) + params.AddNonEmpty("vcard", config.VCard) + + return params, err +} + +func (config ContactConfig) method() string { + return "sendContact" +} + +// SendPollConfig allows you to send a poll. +type SendPollConfig struct { + BaseChat + Question string + Options []string + IsAnonymous bool + Type string + AllowsMultipleAnswers bool + CorrectOptionID int64 + Explanation string + ExplanationParseMode string + ExplanationEntities []MessageEntity + OpenPeriod int + CloseDate int + IsClosed bool +} + +func (config SendPollConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params["question"] = config.Question + if err = params.AddInterface("options", config.Options); err != nil { + return params, err + } + params["is_anonymous"] = strconv.FormatBool(config.IsAnonymous) + params.AddNonEmpty("type", config.Type) + params["allows_multiple_answers"] = strconv.FormatBool(config.AllowsMultipleAnswers) + params["correct_option_id"] = strconv.FormatInt(config.CorrectOptionID, 10) + params.AddBool("is_closed", config.IsClosed) + params.AddNonEmpty("explanation", config.Explanation) + params.AddNonEmpty("explanation_parse_mode", config.ExplanationParseMode) + params.AddNonZero("open_period", config.OpenPeriod) + params.AddNonZero("close_date", config.CloseDate) + err = params.AddInterface("explanation_entities", config.ExplanationEntities) + + return params, err +} + +func (SendPollConfig) method() string { + return "sendPoll" +} + +// GameConfig allows you to send a game. +type GameConfig struct { + BaseChat + GameShortName string +} + +func (config GameConfig) params() (Params, error) { + params, err := config.BaseChat.params() + + params["game_short_name"] = config.GameShortName + + return params, err +} + +func (config GameConfig) method() string { + return "sendGame" +} + +// SetGameScoreConfig allows you to update the game score in a chat. +type SetGameScoreConfig struct { + UserID int64 + Score int + Force bool + DisableEditMessage bool + ChatID int64 + ChannelUsername string + MessageID int + InlineMessageID string +} + +func (config SetGameScoreConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserID) + params.AddNonZero("scrore", config.Score) + params.AddBool("disable_edit_message", config.DisableEditMessage) + + if config.InlineMessageID != "" { + params["inline_message_id"] = config.InlineMessageID + } else { + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero("message_id", config.MessageID) + } + + return params, nil +} + +func (config SetGameScoreConfig) method() string { + return "setGameScore" +} + +// GetGameHighScoresConfig allows you to fetch the high scores for a game. +type GetGameHighScoresConfig struct { + UserID int64 + ChatID int64 + ChannelUsername string + MessageID int + InlineMessageID string +} + +func (config GetGameHighScoresConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserID) + + if config.InlineMessageID != "" { + params["inline_message_id"] = config.InlineMessageID + } else { + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero("message_id", config.MessageID) + } + + return params, nil +} + +func (config GetGameHighScoresConfig) method() string { + return "getGameHighScores" +} + +// ChatActionConfig contains information about a SendChatAction request. +type ChatActionConfig struct { + BaseChat + MessageThreadID int + Action string // required +} + +func (config ChatActionConfig) params() (Params, error) { + params, err := config.BaseChat.params() + + params["action"] = config.Action + params.AddNonZero("message_thread_id", config.MessageThreadID) + + return params, err +} + +func (config ChatActionConfig) method() string { + return "sendChatAction" +} + +// EditMessageTextConfig allows you to modify the text in a message. +type EditMessageTextConfig struct { + BaseEdit + Text string + ParseMode string + Entities []MessageEntity + DisableWebPagePreview bool +} + +func (config EditMessageTextConfig) params() (Params, error) { + params, err := config.BaseEdit.params() + if err != nil { + return params, err + } + + params["text"] = config.Text + params.AddNonEmpty("parse_mode", config.ParseMode) + params.AddBool("disable_web_page_preview", config.DisableWebPagePreview) + err = params.AddInterface("entities", config.Entities) + + return params, err +} + +func (config EditMessageTextConfig) method() string { + return "editMessageText" +} + +// EditMessageCaptionConfig allows you to modify the caption of a message. +type EditMessageCaptionConfig struct { + BaseEdit + Caption string + ParseMode string + CaptionEntities []MessageEntity +} + +func (config EditMessageCaptionConfig) params() (Params, error) { + params, err := config.BaseEdit.params() + if err != nil { + return params, err + } + + params["caption"] = config.Caption + params.AddNonEmpty("parse_mode", config.ParseMode) + err = params.AddInterface("caption_entities", config.CaptionEntities) + + return params, err +} + +func (config EditMessageCaptionConfig) method() string { + return "editMessageCaption" +} + +// EditMessageMediaConfig allows you to make an editMessageMedia request. +type EditMessageMediaConfig struct { + BaseEdit + + Media interface{} +} + +func (EditMessageMediaConfig) method() string { + return "editMessageMedia" +} + +func (config EditMessageMediaConfig) params() (Params, error) { + params, err := config.BaseEdit.params() + if err != nil { + return params, err + } + + err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0)) + + return params, err +} + +func (config EditMessageMediaConfig) files() []RequestFile { + return prepareInputMediaFile(config.Media, 0) +} + +// EditMessageReplyMarkupConfig allows you to modify the reply markup +// of a message. +type EditMessageReplyMarkupConfig struct { + BaseEdit +} + +func (config EditMessageReplyMarkupConfig) params() (Params, error) { + return config.BaseEdit.params() +} + +func (config EditMessageReplyMarkupConfig) method() string { + return "editMessageReplyMarkup" +} + +// StopPollConfig allows you to stop a poll sent by the bot. +type StopPollConfig struct { + BaseEdit +} + +func (config StopPollConfig) params() (Params, error) { + return config.BaseEdit.params() +} + +func (StopPollConfig) method() string { + return "stopPoll" +} + +// UserProfilePhotosConfig contains information about a +// GetUserProfilePhotos request. +type UserProfilePhotosConfig struct { + UserID int64 + Offset int + Limit int +} + +func (UserProfilePhotosConfig) method() string { + return "getUserProfilePhotos" +} + +func (config UserProfilePhotosConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserID) + params.AddNonZero("offset", config.Offset) + params.AddNonZero("limit", config.Limit) + + return params, nil +} + +// FileConfig has information about a file hosted on Telegram. +type FileConfig struct { + FileID string +} + +func (FileConfig) method() string { + return "getFile" +} + +func (config FileConfig) params() (Params, error) { + params := make(Params) + + params["file_id"] = config.FileID + + return params, nil +} + +// UpdateConfig contains information about a GetUpdates request. +type UpdateConfig struct { + Offset int + Limit int + Timeout int + AllowedUpdates []string +} + +func (UpdateConfig) method() string { + return "getUpdates" +} + +func (config UpdateConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero("offset", config.Offset) + params.AddNonZero("limit", config.Limit) + params.AddNonZero("timeout", config.Timeout) + params.AddInterface("allowed_updates", config.AllowedUpdates) + + return params, nil +} + +// WebhookConfig contains information about a SetWebhook request. +type WebhookConfig struct { + URL *url.URL + Certificate RequestFileData + IPAddress string + MaxConnections int + AllowedUpdates []string + DropPendingUpdates bool + SecretToken string +} + +func (config WebhookConfig) method() string { + return "setWebhook" +} + +func (config WebhookConfig) params() (Params, error) { + params := make(Params) + + if config.URL != nil { + params["url"] = config.URL.String() + } + + params.AddNonEmpty("ip_address", config.IPAddress) + params.AddNonZero("max_connections", config.MaxConnections) + err := params.AddInterface("allowed_updates", config.AllowedUpdates) + params.AddBool("drop_pending_updates", config.DropPendingUpdates) + params.AddNonEmpty("secret_token", config.SecretToken) + + return params, err +} + +func (config WebhookConfig) files() []RequestFile { + if config.Certificate != nil { + return []RequestFile{{ + Name: "certificate", + Data: config.Certificate, + }} + } + + return nil +} + +// DeleteWebhookConfig is a helper to delete a webhook. +type DeleteWebhookConfig struct { + DropPendingUpdates bool +} + +func (config DeleteWebhookConfig) method() string { + return "deleteWebhook" +} + +func (config DeleteWebhookConfig) params() (Params, error) { + params := make(Params) + + params.AddBool("drop_pending_updates", config.DropPendingUpdates) + + return params, nil +} + +// InlineConfig contains information on making an InlineQuery response. +type InlineConfig struct { + InlineQueryID string `json:"inline_query_id"` + Results []interface{} `json:"results"` + CacheTime int `json:"cache_time"` + IsPersonal bool `json:"is_personal"` + NextOffset string `json:"next_offset"` + SwitchPMText string `json:"switch_pm_text"` + SwitchPMParameter string `json:"switch_pm_parameter"` +} + +func (config InlineConfig) method() string { + return "answerInlineQuery" +} + +func (config InlineConfig) params() (Params, error) { + params := make(Params) + + params["inline_query_id"] = config.InlineQueryID + params.AddNonZero("cache_time", config.CacheTime) + params.AddBool("is_personal", config.IsPersonal) + params.AddNonEmpty("next_offset", config.NextOffset) + params.AddNonEmpty("switch_pm_text", config.SwitchPMText) + params.AddNonEmpty("switch_pm_parameter", config.SwitchPMParameter) + err := params.AddInterface("results", config.Results) + + return params, err +} + +// AnswerWebAppQueryConfig is used to set the result of an interaction with a +// Web App and send a corresponding message on behalf of the user to the chat +// from which the query originated. +type AnswerWebAppQueryConfig struct { + // WebAppQueryID is the unique identifier for the query to be answered. + WebAppQueryID string `json:"web_app_query_id"` + // Result is an InlineQueryResult object describing the message to be sent. + Result interface{} `json:"result"` +} + +func (config AnswerWebAppQueryConfig) method() string { + return "answerWebAppQuery" +} + +func (config AnswerWebAppQueryConfig) params() (Params, error) { + params := make(Params) + + params["web_app_query_id"] = config.WebAppQueryID + err := params.AddInterface("result", config.Result) + + return params, err +} + +// CallbackConfig contains information on making a CallbackQuery response. +type CallbackConfig struct { + CallbackQueryID string `json:"callback_query_id"` + Text string `json:"text"` + ShowAlert bool `json:"show_alert"` + URL string `json:"url"` + CacheTime int `json:"cache_time"` +} + +func (config CallbackConfig) method() string { + return "answerCallbackQuery" +} + +func (config CallbackConfig) params() (Params, error) { + params := make(Params) + + params["callback_query_id"] = config.CallbackQueryID + params.AddNonEmpty("text", config.Text) + params.AddBool("show_alert", config.ShowAlert) + params.AddNonEmpty("url", config.URL) + params.AddNonZero("cache_time", config.CacheTime) + + return params, nil +} + +// ChatMemberConfig contains information about a user in a chat for use +// with administrative functions such as kicking or unbanning a user. +type ChatMemberConfig struct { + ChatID int64 + SuperGroupUsername string + ChannelUsername string + UserID int64 +} + +// UnbanChatMemberConfig allows you to unban a user. +type UnbanChatMemberConfig struct { + ChatMemberConfig + OnlyIfBanned bool +} + +func (config UnbanChatMemberConfig) method() string { + return "unbanChatMember" +} + +func (config UnbanChatMemberConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) + params.AddNonZero64("user_id", config.UserID) + params.AddBool("only_if_banned", config.OnlyIfBanned) + + return params, nil +} + +// BanChatMemberConfig contains extra fields to kick user. +type BanChatMemberConfig struct { + ChatMemberConfig + UntilDate int64 + RevokeMessages bool +} + +func (config BanChatMemberConfig) method() string { + return "banChatMember" +} + +func (config BanChatMemberConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero64("user_id", config.UserID) + params.AddNonZero64("until_date", config.UntilDate) + params.AddBool("revoke_messages", config.RevokeMessages) + + return params, nil +} + +// KickChatMemberConfig contains extra fields to ban user. +// +// This was renamed to BanChatMember in later versions of the Telegram Bot API. +type KickChatMemberConfig = BanChatMemberConfig + +// RestrictChatMemberConfig contains fields to restrict members of chat +type RestrictChatMemberConfig struct { + ChatMemberConfig + UntilDate int64 + UseIndependentChatPermissions bool + Permissions *ChatPermissions +} + +func (config RestrictChatMemberConfig) method() string { + return "restrictChatMember" +} + +func (config RestrictChatMemberConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) + params.AddNonZero64("user_id", config.UserID) + params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions) + + err := params.AddInterface("permissions", config.Permissions) + params.AddNonZero64("until_date", config.UntilDate) + + return params, err +} + +// PromoteChatMemberConfig contains fields to promote members of chat +type PromoteChatMemberConfig struct { + ChatMemberConfig + IsAnonymous bool + CanManageChat bool + CanChangeInfo bool + CanPostMessages bool + CanEditMessages bool + CanDeleteMessages bool + CanManageVideoChats bool + CanInviteUsers bool + CanRestrictMembers bool + CanPinMessages bool + CanPromoteMembers bool + CanManageTopics bool +} + +func (config PromoteChatMemberConfig) method() string { + return "promoteChatMember" +} + +func (config PromoteChatMemberConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) + params.AddNonZero64("user_id", config.UserID) + + params.AddBool("is_anonymous", config.IsAnonymous) + params.AddBool("can_manage_chat", config.CanManageChat) + params.AddBool("can_change_info", config.CanChangeInfo) + params.AddBool("can_post_messages", config.CanPostMessages) + params.AddBool("can_edit_messages", config.CanEditMessages) + params.AddBool("can_delete_messages", config.CanDeleteMessages) + params.AddBool("can_manage_video_chats", config.CanManageVideoChats) + params.AddBool("can_invite_users", config.CanInviteUsers) + params.AddBool("can_restrict_members", config.CanRestrictMembers) + params.AddBool("can_pin_messages", config.CanPinMessages) + params.AddBool("can_promote_members", config.CanPromoteMembers) + params.AddBool("can_manage_topics", config.CanManageTopics) + + return params, nil +} + +// SetChatAdministratorCustomTitle sets the title of an administrative user +// promoted by the bot for a chat. +type SetChatAdministratorCustomTitle struct { + ChatMemberConfig + CustomTitle string +} + +func (SetChatAdministratorCustomTitle) method() string { + return "setChatAdministratorCustomTitle" +} + +func (config SetChatAdministratorCustomTitle) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername) + params.AddNonZero64("user_id", config.UserID) + params.AddNonEmpty("custom_title", config.CustomTitle) + + return params, nil +} + +// BanChatSenderChatConfig bans a channel chat in a supergroup or a channel. The +// owner of the chat will not be able to send messages and join live streams on +// behalf of the chat, unless it is unbanned first. The bot must be an +// administrator in the supergroup or channel for this to work and must have the +// appropriate administrator rights. +type BanChatSenderChatConfig struct { + ChatID int64 + ChannelUsername string + SenderChatID int64 + UntilDate int +} + +func (config BanChatSenderChatConfig) method() string { + return "banChatSenderChat" +} + +func (config BanChatSenderChatConfig) params() (Params, error) { + params := make(Params) + + _ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero64("sender_chat_id", config.SenderChatID) + params.AddNonZero("until_date", config.UntilDate) + + return params, nil +} + +// UnbanChatSenderChatConfig unbans a previously banned channel chat in a +// supergroup or channel. The bot must be an administrator for this to work and +// must have the appropriate administrator rights. +type UnbanChatSenderChatConfig struct { + ChatID int64 + ChannelUsername string + SenderChatID int64 +} + +func (config UnbanChatSenderChatConfig) method() string { + return "unbanChatSenderChat" +} + +func (config UnbanChatSenderChatConfig) params() (Params, error) { + params := make(Params) + + _ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero64("sender_chat_id", config.SenderChatID) + + return params, nil +} + +// ChatConfig contains information about getting information on a chat. +type ChatConfig struct { + ChatID int64 + SuperGroupUsername string +} + +func (config ChatConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + + return params, nil +} + +// ChatInfoConfig contains information about getting chat information. +type ChatInfoConfig struct { + ChatConfig +} + +func (ChatInfoConfig) method() string { + return "getChat" +} + +// ChatMemberCountConfig contains information about getting the number of users in a chat. +type ChatMemberCountConfig struct { + ChatConfig +} + +func (ChatMemberCountConfig) method() string { + return "getChatMembersCount" +} + +// ChatAdministratorsConfig contains information about getting chat administrators. +type ChatAdministratorsConfig struct { + ChatConfig +} + +func (ChatAdministratorsConfig) method() string { + return "getChatAdministrators" +} + +// SetChatPermissionsConfig allows you to set default permissions for the +// members in a group. The bot must be an administrator and have rights to +// restrict members. +type SetChatPermissionsConfig struct { + ChatConfig + UseIndependentChatPermissions bool + Permissions *ChatPermissions +} + +func (SetChatPermissionsConfig) method() string { + return "setChatPermissions" +} + +func (config SetChatPermissionsConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddBool("use_independent_chat_permissions", config.UseIndependentChatPermissions) + err := params.AddInterface("permissions", config.Permissions) + + return params, err +} + +// ChatInviteLinkConfig contains information about getting a chat link. +// +// Note that generating a new link will revoke any previous links. +type ChatInviteLinkConfig struct { + ChatConfig +} + +func (ChatInviteLinkConfig) method() string { + return "exportChatInviteLink" +} + +func (config ChatInviteLinkConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + + return params, nil +} + +// CreateChatInviteLinkConfig allows you to create an additional invite link for +// a chat. The bot must be an administrator in the chat for this to work and +// must have the appropriate admin rights. The link can be revoked using the +// RevokeChatInviteLinkConfig. +type CreateChatInviteLinkConfig struct { + ChatConfig + Name string + ExpireDate int + MemberLimit int + CreatesJoinRequest bool +} + +func (CreateChatInviteLinkConfig) method() string { + return "createChatInviteLink" +} + +func (config CreateChatInviteLinkConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("name", config.Name) + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero("expire_date", config.ExpireDate) + params.AddNonZero("member_limit", config.MemberLimit) + params.AddBool("creates_join_request", config.CreatesJoinRequest) + + return params, nil +} + +// EditChatInviteLinkConfig allows you to edit a non-primary invite link created +// by the bot. The bot must be an administrator in the chat for this to work and +// must have the appropriate admin rights. +type EditChatInviteLinkConfig struct { + ChatConfig + InviteLink string + Name string + ExpireDate int + MemberLimit int + CreatesJoinRequest bool +} + +func (EditChatInviteLinkConfig) method() string { + return "editChatInviteLink" +} + +func (config EditChatInviteLinkConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonEmpty("name", config.Name) + params["invite_link"] = config.InviteLink + params.AddNonZero("expire_date", config.ExpireDate) + params.AddNonZero("member_limit", config.MemberLimit) + params.AddBool("creates_join_request", config.CreatesJoinRequest) + + return params, nil +} + +// RevokeChatInviteLinkConfig allows you to revoke an invite link created by the +// bot. If the primary link is revoked, a new link is automatically generated. +// The bot must be an administrator in the chat for this to work and must have +// the appropriate admin rights. +type RevokeChatInviteLinkConfig struct { + ChatConfig + InviteLink string +} + +func (RevokeChatInviteLinkConfig) method() string { + return "revokeChatInviteLink" +} + +func (config RevokeChatInviteLinkConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params["invite_link"] = config.InviteLink + + return params, nil +} + +// ApproveChatJoinRequestConfig allows you to approve a chat join request. +type ApproveChatJoinRequestConfig struct { + ChatConfig + UserID int64 +} + +func (ApproveChatJoinRequestConfig) method() string { + return "approveChatJoinRequest" +} + +func (config ApproveChatJoinRequestConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero("user_id", int(config.UserID)) + + return params, nil +} + +// DeclineChatJoinRequest allows you to decline a chat join request. +type DeclineChatJoinRequest struct { + ChatConfig + UserID int64 +} + +func (DeclineChatJoinRequest) method() string { + return "declineChatJoinRequest" +} + +func (config DeclineChatJoinRequest) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero("user_id", int(config.UserID)) + + return params, nil +} + +// LeaveChatConfig allows you to leave a chat. +type LeaveChatConfig struct { + ChatID int64 + ChannelUsername string +} + +func (config LeaveChatConfig) method() string { + return "leaveChat" +} + +func (config LeaveChatConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + + return params, nil +} + +// ChatConfigWithUser contains information about a chat and a user. +type ChatConfigWithUser struct { + ChatID int64 + SuperGroupUsername string + UserID int64 +} + +func (config ChatConfigWithUser) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero64("user_id", config.UserID) + + return params, nil +} + +// GetChatMemberConfig is information about getting a specific member in a chat. +type GetChatMemberConfig struct { + ChatConfigWithUser +} + +func (GetChatMemberConfig) method() string { + return "getChatMember" +} + +// InvoiceConfig contains information for sendInvoice request. +type InvoiceConfig struct { + BaseChat + Title string // required + Description string // required + Payload string // required + ProviderToken string // required + Currency string // required + Prices []LabeledPrice // required + MaxTipAmount int + SuggestedTipAmounts []int + StartParameter string + ProviderData string + PhotoURL string + PhotoSize int + PhotoWidth int + PhotoHeight int + NeedName bool + NeedPhoneNumber bool + NeedEmail bool + NeedShippingAddress bool + SendPhoneNumberToProvider bool + SendEmailToProvider bool + IsFlexible bool +} + +func (config InvoiceConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params["title"] = config.Title + params["description"] = config.Description + params["payload"] = config.Payload + params["provider_token"] = config.ProviderToken + params["currency"] = config.Currency + if err = params.AddInterface("prices", config.Prices); err != nil { + return params, err + } + + params.AddNonZero("max_tip_amount", config.MaxTipAmount) + err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts) + params.AddNonEmpty("start_parameter", config.StartParameter) + params.AddNonEmpty("provider_data", config.ProviderData) + params.AddNonEmpty("photo_url", config.PhotoURL) + params.AddNonZero("photo_size", config.PhotoSize) + params.AddNonZero("photo_width", config.PhotoWidth) + params.AddNonZero("photo_height", config.PhotoHeight) + params.AddBool("need_name", config.NeedName) + params.AddBool("need_phone_number", config.NeedPhoneNumber) + params.AddBool("need_email", config.NeedEmail) + params.AddBool("need_shipping_address", config.NeedShippingAddress) + params.AddBool("is_flexible", config.IsFlexible) + params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider) + params.AddBool("send_email_to_provider", config.SendEmailToProvider) + + return params, err +} + +func (config InvoiceConfig) method() string { + return "sendInvoice" +} + +// InvoiceLinkConfig contains information for createInvoiceLink method +type InvoiceLinkConfig struct { + Title string //Required + Description string //Required + Payload string //Required + ProviderToken string //Required + Currency string //Required + Prices []LabeledPrice //Required + MaxTipAmount int + SuggestedTipAmounts []int + ProviderData string + PhotoURL string + PhotoSize int + PhotoWidth int + PhotoHeight int + NeedName bool + NeedPhoneNumber bool + NeedEmail bool + NeedShippingAddress bool + SendPhoneNumberToProvider bool + SendEmailToProvider bool + IsFlexible bool +} + +func (config InvoiceLinkConfig) params() (Params, error) { + params := make(Params) + + params["title"] = config.Title + params["description"] = config.Description + params["payload"] = config.Payload + params["provider_token"] = config.ProviderToken + params["currency"] = config.Currency + if err := params.AddInterface("prices", config.Prices); err != nil { + return params, err + } + + params.AddNonZero("max_tip_amount", config.MaxTipAmount) + err := params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts) + params.AddNonEmpty("provider_data", config.ProviderData) + params.AddNonEmpty("photo_url", config.PhotoURL) + params.AddNonZero("photo_size", config.PhotoSize) + params.AddNonZero("photo_width", config.PhotoWidth) + params.AddNonZero("photo_height", config.PhotoHeight) + params.AddBool("need_name", config.NeedName) + params.AddBool("need_phone_number", config.NeedPhoneNumber) + params.AddBool("need_email", config.NeedEmail) + params.AddBool("need_shipping_address", config.NeedShippingAddress) + params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider) + params.AddBool("send_email_to_provider", config.SendEmailToProvider) + params.AddBool("is_flexible", config.IsFlexible) + + return params, err +} + +func (config InvoiceLinkConfig) method() string { + return "createInvoiceLink" +} + +// ShippingConfig contains information for answerShippingQuery request. +type ShippingConfig struct { + ShippingQueryID string // required + OK bool // required + ShippingOptions []ShippingOption + ErrorMessage string +} + +func (config ShippingConfig) method() string { + return "answerShippingQuery" +} + +func (config ShippingConfig) params() (Params, error) { + params := make(Params) + + params["shipping_query_id"] = config.ShippingQueryID + params.AddBool("ok", config.OK) + err := params.AddInterface("shipping_options", config.ShippingOptions) + params.AddNonEmpty("error_message", config.ErrorMessage) + + return params, err +} + +// PreCheckoutConfig contains information for answerPreCheckoutQuery request. +type PreCheckoutConfig struct { + PreCheckoutQueryID string // required + OK bool // required + ErrorMessage string +} + +func (config PreCheckoutConfig) method() string { + return "answerPreCheckoutQuery" +} + +func (config PreCheckoutConfig) params() (Params, error) { + params := make(Params) + + params["pre_checkout_query_id"] = config.PreCheckoutQueryID + params.AddBool("ok", config.OK) + params.AddNonEmpty("error_message", config.ErrorMessage) + + return params, nil +} + +// DeleteMessageConfig contains information of a message in a chat to delete. +type DeleteMessageConfig struct { + ChannelUsername string + ChatID int64 + MessageID int +} + +func (config DeleteMessageConfig) method() string { + return "deleteMessage" +} + +func (config DeleteMessageConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero("message_id", config.MessageID) + + return params, nil +} + +// PinChatMessageConfig contains information of a message in a chat to pin. +type PinChatMessageConfig struct { + ChatID int64 + ChannelUsername string + MessageID int + DisableNotification bool +} + +func (config PinChatMessageConfig) method() string { + return "pinChatMessage" +} + +func (config PinChatMessageConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero("message_id", config.MessageID) + params.AddBool("disable_notification", config.DisableNotification) + + return params, nil +} + +// UnpinChatMessageConfig contains information of a chat message to unpin. +// +// If MessageID is not specified, it will unpin the most recent pin. +type UnpinChatMessageConfig struct { + ChatID int64 + ChannelUsername string + MessageID int +} + +func (config UnpinChatMessageConfig) method() string { + return "unpinChatMessage" +} + +func (config UnpinChatMessageConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddNonZero("message_id", config.MessageID) + + return params, nil +} + +// UnpinAllChatMessagesConfig contains information of all messages to unpin in +// a chat. +type UnpinAllChatMessagesConfig struct { + ChatID int64 + ChannelUsername string +} + +func (config UnpinAllChatMessagesConfig) method() string { + return "unpinAllChatMessages" +} + +func (config UnpinAllChatMessagesConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + + return params, nil +} + +// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo. +type SetChatPhotoConfig struct { + BaseFile +} + +func (config SetChatPhotoConfig) method() string { + return "setChatPhoto" +} + +func (config SetChatPhotoConfig) files() []RequestFile { + return []RequestFile{{ + Name: "photo", + Data: config.File, + }} +} + +// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo. +type DeleteChatPhotoConfig struct { + ChatID int64 + ChannelUsername string +} + +func (config DeleteChatPhotoConfig) method() string { + return "deleteChatPhoto" +} + +func (config DeleteChatPhotoConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + + return params, nil +} + +// SetChatTitleConfig allows you to set the title of something other than a private chat. +type SetChatTitleConfig struct { + ChatID int64 + ChannelUsername string + + Title string +} + +func (config SetChatTitleConfig) method() string { + return "setChatTitle" +} + +func (config SetChatTitleConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params["title"] = config.Title + + return params, nil +} + +// SetChatDescriptionConfig allows you to set the description of a supergroup or channel. +type SetChatDescriptionConfig struct { + ChatID int64 + ChannelUsername string + + Description string +} + +func (config SetChatDescriptionConfig) method() string { + return "setChatDescription" +} + +func (config SetChatDescriptionConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params["description"] = config.Description + + return params, nil +} + +// GetStickerSetConfig allows you to get the stickers in a set. +type GetStickerSetConfig struct { + Name string +} + +func (config GetStickerSetConfig) method() string { + return "getStickerSet" +} + +func (config GetStickerSetConfig) params() (Params, error) { + params := make(Params) + + params["name"] = config.Name + + return params, nil +} + +// GetCustomEmojiStickersConfig get information about +// custom emoji stickers by their identifiers. +type GetCustomEmojiStickersConfig struct { + CustomEmojiIDs []string +} + +func (config GetCustomEmojiStickersConfig) params() (Params, error) { + params := make(Params) + + params.AddInterface("custom_emoji_ids", config.CustomEmojiIDs) + + return params, nil +} + +func (config GetCustomEmojiStickersConfig) method() string { + return "getCustomEmojiStickers" +} + +// UploadStickerConfig allows you to upload a sticker for use in a set later. +type UploadStickerConfig struct { + UserID int64 + PNGSticker RequestFileData +} + +func (config UploadStickerConfig) method() string { + return "uploadStickerFile" +} + +func (config UploadStickerConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserID) + + return params, nil +} + +func (config UploadStickerConfig) files() []RequestFile { + return []RequestFile{{ + Name: "png_sticker", + Data: config.PNGSticker, + }} +} + +// NewStickerSetConfig allows creating a new sticker set. +// +// You must set either PNGSticker or TGSSticker. +type NewStickerSetConfig struct { + UserID int64 + Name string + Title string + PNGSticker RequestFileData + TGSSticker RequestFileData + StickerType string + Emojis string + ContainsMasks bool // deprecated + MaskPosition *MaskPosition +} + +func (config NewStickerSetConfig) method() string { + return "createNewStickerSet" +} + +func (config NewStickerSetConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserID) + params["name"] = config.Name + params["title"] = config.Title + params["emojis"] = config.Emojis + + params.AddBool("contains_masks", config.ContainsMasks) + params.AddNonEmpty("sticker_type", string(config.StickerType)) + err := params.AddInterface("mask_position", config.MaskPosition) + + return params, err +} + +func (config NewStickerSetConfig) files() []RequestFile { + if config.PNGSticker != nil { + return []RequestFile{{ + Name: "png_sticker", + Data: config.PNGSticker, + }} + } + + return []RequestFile{{ + Name: "tgs_sticker", + Data: config.TGSSticker, + }} +} + +// AddStickerConfig allows you to add a sticker to a set. +type AddStickerConfig struct { + UserID int64 + Name string + PNGSticker RequestFileData + TGSSticker RequestFileData + Emojis string + MaskPosition *MaskPosition +} + +func (config AddStickerConfig) method() string { + return "addStickerToSet" +} + +func (config AddStickerConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserID) + params["name"] = config.Name + params["emojis"] = config.Emojis + + err := params.AddInterface("mask_position", config.MaskPosition) + + return params, err +} + +func (config AddStickerConfig) files() []RequestFile { + if config.PNGSticker != nil { + return []RequestFile{{ + Name: "png_sticker", + Data: config.PNGSticker, + }} + } + + return []RequestFile{{ + Name: "tgs_sticker", + Data: config.TGSSticker, + }} + +} + +// SetStickerPositionConfig allows you to change the position of a sticker in a set. +type SetStickerPositionConfig struct { + Sticker string + Position int +} + +func (config SetStickerPositionConfig) method() string { + return "setStickerPositionInSet" +} + +func (config SetStickerPositionConfig) params() (Params, error) { + params := make(Params) + + params["sticker"] = config.Sticker + params.AddNonZero("position", config.Position) + + return params, nil +} + +// DeleteStickerConfig allows you to delete a sticker from a set. +type DeleteStickerConfig struct { + Sticker string +} + +func (config DeleteStickerConfig) method() string { + return "deleteStickerFromSet" +} + +func (config DeleteStickerConfig) params() (Params, error) { + params := make(Params) + + params["sticker"] = config.Sticker + + return params, nil +} + +// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set. +type SetStickerSetThumbConfig struct { + Name string + UserID int64 + Thumb RequestFileData +} + +func (config SetStickerSetThumbConfig) method() string { + return "setStickerSetThumb" +} + +func (config SetStickerSetThumbConfig) params() (Params, error) { + params := make(Params) + + params["name"] = config.Name + params.AddNonZero64("user_id", config.UserID) + + return params, nil +} + +func (config SetStickerSetThumbConfig) files() []RequestFile { + return []RequestFile{{ + Name: "thumb", + Data: config.Thumb, + }} +} + +// SetChatStickerSetConfig allows you to set the sticker set for a supergroup. +type SetChatStickerSetConfig struct { + ChatID int64 + SuperGroupUsername string + + StickerSetName string +} + +func (config SetChatStickerSetConfig) method() string { + return "setChatStickerSet" +} + +func (config SetChatStickerSetConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params["sticker_set_name"] = config.StickerSetName + + return params, nil +} + +// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set. +type DeleteChatStickerSetConfig struct { + ChatID int64 + SuperGroupUsername string +} + +func (config DeleteChatStickerSetConfig) method() string { + return "deleteChatStickerSet" +} + +func (config DeleteChatStickerSetConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + + return params, nil +} + +// GetForumTopicIconStickersConfig allows you to get custom emoji stickers, +// which can be used as a forum topic icon by any user. +type GetForumTopicIconStickersConfig struct{} + +func (config GetForumTopicIconStickersConfig) method() string { + return "getForumTopicIconStickers" +} + +func (config GetForumTopicIconStickersConfig) params() (Params, error) { + return nil, nil +} + +// BaseForum is a base type for all forum config types. +type BaseForum struct { + ChatID int64 + SuperGroupUsername string +} + +func (config BaseForum) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + + return params, nil +} + +// CreateForumTopicConfig allows you to create a topic +// in a forum supergroup chat. +type CreateForumTopicConfig struct { + BaseForum + Name string + IconColor int + IconCustomEmojiID string +} + +func (config CreateForumTopicConfig) method() string { + return "createForumTopic" +} + +func (config CreateForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("name", config.Name) + params.AddNonZero("icon_color", config.IconColor) + params.AddNonEmpty("icon_custom_emoji_id", config.IconCustomEmojiID) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// EditForumTopicConfig allows you to edit +// name and icon of a topic in a forum supergroup chat. +type EditForumTopicConfig struct { + BaseForum + MessageThreadID int + Name string + IconCustomEmojiID string +} + +func (config EditForumTopicConfig) method() string { + return "editForumTopic" +} + +func (config EditForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero("message_thread_id", config.MessageThreadID) + params.AddNonEmpty("name", config.Name) + params.AddNonEmpty("icon_custom_emoji_id", config.IconCustomEmojiID) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// CloseForumTopicConfig allows you to close +// an open topic in a forum supergroup chat. +type CloseForumTopicConfig struct { + BaseForum + MessageThreadID int +} + +func (config CloseForumTopicConfig) method() string { + return "closeForumTopic" +} + +func (config CloseForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero("message_thread_id", config.MessageThreadID) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// ReopenForumTopicConfig allows you to reopen +// an closed topic in a forum supergroup chat. +type ReopenForumTopicConfig struct { + BaseForum + MessageThreadID int +} + +func (config ReopenForumTopicConfig) method() string { + return "reopenForumTopic" +} + +func (config ReopenForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero("message_thread_id", config.MessageThreadID) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// DeleteForumTopicConfig allows you to delete a forum topic +// along with all its messages in a forum supergroup chat. +type DeleteForumTopicConfig struct { + BaseForum + MessageThreadID int +} + +func (config DeleteForumTopicConfig) method() string { + return "deleteForumTopic" +} + +func (config DeleteForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero("message_thread_id", config.MessageThreadID) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// UnpinAllForumTopicMessagesConfig allows you to clear the list +// of pinned messages in a forum topic. +type UnpinAllForumTopicMessagesConfig struct { + BaseForum + MessageThreadID int +} + +func (config UnpinAllForumTopicMessagesConfig) method() string { + return "unpinAllForumTopicMessages" +} + +func (config UnpinAllForumTopicMessagesConfig) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername) + params.AddNonZero("message_thread_id", config.MessageThreadID) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// UnpinAllForumTopicMessagesConfig allows you to edit the name of +// the 'General' topic in a forum supergroup chat. +// The bot must be an administrator in the chat for this to work +// and must have can_manage_topics administrator rights. Returns True on success. +type EditGeneralForumTopicConfig struct { + BaseForum + Name string +} + +func (config EditGeneralForumTopicConfig) method() string { + return "editGeneralForumTopic" +} + +func (config EditGeneralForumTopicConfig) params() (Params, error) { + params := make(Params) + + params.AddNonEmpty("name", config.Name) + + p1, _ := config.BaseForum.params() + params.Merge(p1) + + return params, nil +} + +// CloseGeneralForumTopicConfig allows you to to close an open 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// Returns True on success. +type CloseGeneralForumTopicConfig struct{ BaseForum } + +func (config CloseGeneralForumTopicConfig) method() string { + return "closeGeneralForumTopic" +} + +// CloseGeneralForumTopicConfig allows you to reopen a closed 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// The topic will be automatically unhidden if it was hidden. +// Returns True on success. +type ReopenGeneralForumTopicConfig struct{ BaseForum } + +func (config ReopenGeneralForumTopicConfig) method() string { + return "reopenGeneralForumTopic" +} + +// HideGeneralForumTopicConfig allows you to hide the 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// The topic will be automatically closed if it was open. +// Returns True on success. +type HideGeneralForumTopicConfig struct{ BaseForum } + +func (config HideGeneralForumTopicConfig) method() string { + return "hideGeneralForumTopic" +} + +// UnhideGeneralForumTopicConfig allows you to unhide the 'General' topic +// in a forum supergroup chat. The bot must be an administrator in the chat +// for this to work and must have the can_manage_topics administrator rights. +// Returns True on success. +type UnhideGeneralForumTopicConfig struct{ BaseForum } + +func (config UnhideGeneralForumTopicConfig) method() string { + return "unhideGeneralForumTopic" +} + +// MediaGroupConfig allows you to send a group of media. +// +// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo). +type MediaGroupConfig struct { + BaseChat + Media []interface{} +} + +func (config MediaGroupConfig) method() string { + return "sendMediaGroup" +} + +func (config MediaGroupConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return nil, err + } + + params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + params.AddBool("disable_notification", config.DisableNotification) + params.AddNonZero("reply_to_message_id", config.ReplyToMessageID) + + err = params.AddInterface("media", prepareInputMediaForParams(config.Media)) + + return params, err +} + +func (config MediaGroupConfig) files() []RequestFile { + return prepareInputMediaForFiles(config.Media) +} + +// DiceConfig contains information about a sendDice request. +type DiceConfig struct { + BaseChat + // Emoji on which the dice throw animation is based. + // Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰. + // Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽, + // and values 1-64 for 🎰. + // Defaults to “🎲” + Emoji string +} + +func (config DiceConfig) method() string { + return "sendDice" +} + +func (config DiceConfig) params() (Params, error) { + params, err := config.BaseChat.params() + if err != nil { + return params, err + } + + params.AddNonEmpty("emoji", config.Emoji) + + return params, err +} + +// GetMyCommandsConfig gets a list of the currently registered commands. +type GetMyCommandsConfig struct { + Scope *BotCommandScope + LanguageCode string +} + +func (config GetMyCommandsConfig) method() string { + return "getMyCommands" +} + +func (config GetMyCommandsConfig) params() (Params, error) { + params := make(Params) + + err := params.AddInterface("scope", config.Scope) + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, err +} + +// SetMyCommandsConfig sets a list of commands the bot understands. +type SetMyCommandsConfig struct { + Commands []BotCommand + Scope *BotCommandScope + LanguageCode string +} + +func (config SetMyCommandsConfig) method() string { + return "setMyCommands" +} + +func (config SetMyCommandsConfig) params() (Params, error) { + params := make(Params) + + if err := params.AddInterface("commands", config.Commands); err != nil { + return params, err + } + err := params.AddInterface("scope", config.Scope) + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, err +} + +type DeleteMyCommandsConfig struct { + Scope *BotCommandScope + LanguageCode string +} + +func (config DeleteMyCommandsConfig) method() string { + return "deleteMyCommands" +} + +func (config DeleteMyCommandsConfig) params() (Params, error) { + params := make(Params) + + err := params.AddInterface("scope", config.Scope) + params.AddNonEmpty("language_code", config.LanguageCode) + + return params, err +} + +// SetChatMenuButtonConfig changes the bot's menu button in a private chat, +// or the default menu button. +type SetChatMenuButtonConfig struct { + ChatID int64 + ChannelUsername string + + MenuButton *MenuButton +} + +func (config SetChatMenuButtonConfig) method() string { + return "setChatMenuButton" +} + +func (config SetChatMenuButtonConfig) params() (Params, error) { + params := make(Params) + + if err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername); err != nil { + return params, err + } + err := params.AddInterface("menu_button", config.MenuButton) + + return params, err +} + +type GetChatMenuButtonConfig struct { + ChatID int64 + ChannelUsername string +} + +func (config GetChatMenuButtonConfig) method() string { + return "getChatMenuButton" +} + +func (config GetChatMenuButtonConfig) params() (Params, error) { + params := make(Params) + + err := params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername) + + return params, err +} + +type SetMyDefaultAdministratorRightsConfig struct { + Rights ChatAdministratorRights + ForChannels bool +} + +func (config SetMyDefaultAdministratorRightsConfig) method() string { + return "setMyDefaultAdministratorRights" +} + +func (config SetMyDefaultAdministratorRightsConfig) params() (Params, error) { + params := make(Params) + + err := params.AddInterface("rights", config.Rights) + params.AddBool("for_channels", config.ForChannels) + + return params, err +} + +type GetMyDefaultAdministratorRightsConfig struct { + ForChannels bool +} + +func (config GetMyDefaultAdministratorRightsConfig) method() string { + return "getMyDefaultAdministratorRights" +} + +func (config GetMyDefaultAdministratorRightsConfig) params() (Params, error) { + params := make(Params) + + params.AddBool("for_channels", config.ForChannels) + + return params, nil +} + +// prepareInputMediaParam evaluates a single InputMedia and determines if it +// needs to be modified for a successful upload. If it returns nil, then the +// value does not need to be included in the params. Otherwise, it will return +// the same type as was originally provided. +// +// The idx is used to calculate the file field name. If you only have a single +// file, 0 may be used. It is formatted into "attach://file-%d" for the primary +// media and "attach://file-%d-thumb" for thumbnails. +// +// It is expected to be used in conjunction with prepareInputMediaFile. +func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} { + switch m := inputMedia.(type) { + case InputMediaPhoto: + if m.Media.NeedsUpload() { + m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx)) + } + + return m + case InputMediaVideo: + if m.Media.NeedsUpload() { + m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx)) + } + + if m.Thumb != nil && m.Thumb.NeedsUpload() { + m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx)) + } + + return m + case InputMediaAudio: + if m.Media.NeedsUpload() { + m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx)) + } + + if m.Thumb != nil && m.Thumb.NeedsUpload() { + m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx)) + } + + return m + case InputMediaDocument: + if m.Media.NeedsUpload() { + m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx)) + } + + if m.Thumb != nil && m.Thumb.NeedsUpload() { + m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx)) + } + + return m + } + + return nil +} + +// prepareInputMediaFile generates an array of RequestFile to provide for +// Fileable's files method. It returns an array as a single InputMedia may have +// multiple files, for the primary media and a thumbnail. +// +// The idx parameter is used to generate file field names. It uses the names +// "file-%d" for the main file and "file-%d-thumb" for the thumbnail. +// +// It is expected to be used in conjunction with prepareInputMediaParam. +func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile { + files := []RequestFile{} + + switch m := inputMedia.(type) { + case InputMediaPhoto: + if m.Media.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Media, + }) + } + case InputMediaVideo: + if m.Media.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Media, + }) + } + + if m.Thumb != nil && m.Thumb.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Thumb, + }) + } + case InputMediaDocument: + if m.Media.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Media, + }) + } + + if m.Thumb != nil && m.Thumb.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Thumb, + }) + } + case InputMediaAudio: + if m.Media.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Media, + }) + } + + if m.Thumb != nil && m.Thumb.NeedsUpload() { + files = append(files, RequestFile{ + Name: fmt.Sprintf("file-%d", idx), + Data: m.Thumb, + }) + } + } + + return files +} + +// prepareInputMediaForParams calls prepareInputMediaParam for each item +// provided and returns a new array with the correct params for a request. +// +// It is expected that files will get data from the associated function, +// prepareInputMediaForFiles. +func prepareInputMediaForParams(inputMedia []interface{}) []interface{} { + newMedia := make([]interface{}, len(inputMedia)) + copy(newMedia, inputMedia) + + for idx, media := range inputMedia { + if param := prepareInputMediaParam(media, idx); param != nil { + newMedia[idx] = param + } + } + + return newMedia +} + +// prepareInputMediaForFiles calls prepareInputMediaFile for each item +// provided and returns a new array with the correct files for a request. +// +// It is expected that params will get data from the associated function, +// prepareInputMediaForParams. +func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile { + files := []RequestFile{} + + for idx, media := range inputMedia { + if file := prepareInputMediaFile(media, idx); file != nil { + files = append(files, file...) + } + } + + return files +} |