From 88e1a77b954d0018eb9b0dd673a5549f61d2c285 Mon Sep 17 00:00:00 2001 From: Mohammad Taha Date: Wed, 19 Jun 2019 08:44:38 +0430 Subject: [PATCH 01/70] Update helpers.go added a function with name `NewEditMessageTextAndMarkup` for edit text and replymarkup together --- helpers.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/helpers.go b/helpers.go index 3dabe11..7822152 100644 --- a/helpers.go +++ b/helpers.go @@ -615,6 +615,18 @@ func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTex } } +// NewEditMessageTextAndMarkup allows you to edit the text and replymarkup of a message. +func NewEditMessageTextAndMarkup(chatID int64, messageID int, text string, replyMarkup InlineKeyboardMarkup) EditMessageTextConfig { + return EditMessageTextConfig{ + BaseEdit: BaseEdit{ + ChatID: chatID, + MessageID: messageID, + ReplyMarkup: &replyMarkup, + }, + Text: text, + } +} + // NewEditMessageCaption allows you to edit the caption of a message. func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig { return EditMessageCaptionConfig{ @@ -622,7 +634,7 @@ func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMess ChatID: chatID, MessageID: messageID, }, - Caption: caption, + Caption: caption, } } From 72a0e2d8087dc11548bb29edc2403b1323d881bd Mon Sep 17 00:00:00 2001 From: unstppbl Date: Wed, 3 Jul 2019 17:59:56 -0700 Subject: [PATCH 02/70] closes #246 --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index a996790..7d8b9d1 100644 --- a/bot.go +++ b/bot.go @@ -438,7 +438,7 @@ func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) { // RemoveWebhook unsets the webhook. func (bot *BotAPI) RemoveWebhook() (APIResponse, error) { - return bot.MakeRequest("setWebhook", url.Values{}) + return bot.MakeRequest("deleteWebhook", url.Values{}) } // SetWebhook sets a webhook. From b478ff9669daca239e94cf0659e7c941a5071a6c Mon Sep 17 00:00:00 2001 From: rozha Date: Sun, 11 Aug 2019 13:20:40 +0300 Subject: [PATCH 03/70] Introduce NewOneTimeReplyKeyboard() helper function --- helpers.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/helpers.go b/helpers.go index 3dabe11..fc19313 100644 --- a/helpers.go +++ b/helpers.go @@ -704,6 +704,13 @@ func NewReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup { } } +// NewOneTimeReplyKeyboard creates a new one time keyboard using NewReplyKeyboard() +func NewOneTimeReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup { + markup := NewReplyKeyboard(rows...) + markup.OneTimeKeyboard = true + return markup +} + // NewInlineKeyboardButtonData creates an inline keyboard button with text // and data for a callback. func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton { From d4b2e3c2136aa63ffce72c297c97a9c3e0a06cc8 Mon Sep 17 00:00:00 2001 From: gropher Date: Wed, 18 Sep 2019 03:34:37 +0300 Subject: [PATCH 04/70] Added HandleUpdate method for serverless deploy --- bot.go | 19 ++++++++++++------- bot_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/bot.go b/bot.go index a996790..070e73d 100644 --- a/bot.go +++ b/bot.go @@ -533,18 +533,23 @@ func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel { ch := make(chan Update, bot.Buffer) http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { - bytes, _ := ioutil.ReadAll(r.Body) - r.Body.Close() - - var update Update - json.Unmarshal(bytes, &update) - - ch <- update + ch <- bot.HandleUpdate(w, r) }) return ch } +// HandleUpdate parses and returns update received via webhook +func (bot *BotAPI) HandleUpdate(res http.ResponseWriter, req *http.Request) Update { + bytes, _ := ioutil.ReadAll(req.Body) + req.Body.Close() + + var update Update + json.Unmarshal(bytes, &update) + + return update +} + // AnswerInlineQuery sends a response to an inline query. // // Note that you must respond to an inline query within 30 seconds. diff --git a/bot_test.go b/bot_test.go index 60f3e65..2e9d07a 100644 --- a/bot_test.go +++ b/bot_test.go @@ -593,6 +593,35 @@ func ExampleNewWebhook() { } } +func ExampleWebhookHandler() { + bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken") + if err != nil { + log.Fatal(err) + } + + bot.Debug = true + + log.Printf("Authorized on account %s", bot.Self.UserName) + + _, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem")) + if err != nil { + log.Fatal(err) + } + info, err := bot.GetWebhookInfo() + if err != nil { + log.Fatal(err) + } + if info.LastErrorDate != 0 { + log.Printf("[Telegram callback failed]%s", info.LastErrorMessage) + } + + http.HandleFunc("/" + bot.Token, func(w http.ResponseWriter, r *http.Request) { + log.Printf("%+v\n", bot.HandleUpdate(w, r)) + }) + + go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil) +} + func ExampleAnswerInlineQuery() { bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken") // create new bot if err != nil { From 37eb2cb6bec0d833b3873f7fcd0b2fec9e15e6db Mon Sep 17 00:00:00 2001 From: NemoD503 <1historicus@gmail.com> Date: Tue, 8 Oct 2019 12:25:37 +0300 Subject: [PATCH 05/70] Go mod was added --- go.mod | 5 +++++ go.sum | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7df46f4 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/go-telegram-bot-api/telegram-bot-api + +go 1.12 + +require github.com/technoweenie/multipartstreamer v1.0.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..8660600 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= +github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= From a6b4ce46a6e9a0270cbd9eb3a4d1c746886f4f05 Mon Sep 17 00:00:00 2001 From: NemoD503 <1historicus@gmail.com> Date: Sun, 20 Oct 2019 22:47:21 +0300 Subject: [PATCH 06/70] return pointer to error --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index a996790..48f6816 100644 --- a/bot.go +++ b/bot.go @@ -92,7 +92,7 @@ func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, if apiResp.Parameters != nil { parameters = *apiResp.Parameters } - return apiResp, Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters} + return apiResp, &Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters} } return apiResp, nil From 1af25a19c77837105406e0a847c36a078bb408ac Mon Sep 17 00:00:00 2001 From: NemoD503 <1historicus@gmail.com> Date: Sun, 20 Oct 2019 23:01:22 +0300 Subject: [PATCH 07/70] add new versions of golang to travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5769aa1..51865c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,4 +3,6 @@ language: go go: - '1.10' - '1.11' + - '1.12' + - '1.13' - tip From 935e204b042c70bd9ad117caaca97fb5622433dd Mon Sep 17 00:00:00 2001 From: Shao Yang Hong Date: Fri, 25 Oct 2019 11:47:24 +0800 Subject: [PATCH 08/70] README: link to godoc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf341d2..43b33ed 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GoDoc](https://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api?status.svg)](http://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api) [![Travis](https://travis-ci.org/go-telegram-bot-api/telegram-bot-api.svg)](https://travis-ci.org/go-telegram-bot-api/telegram-bot-api) -All methods are fairly self explanatory, and reading the godoc page should +All methods are fairly self explanatory, and reading the [godoc](http://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api) page should explain everything. If something isn't clear, open an issue or submit a pull request. From 7629a37f7708fa9a24c55fd490114922d026bdb3 Mon Sep 17 00:00:00 2001 From: Dmitriy Kharchenko Date: Sun, 24 Nov 2019 11:05:38 +0300 Subject: [PATCH 09/70] Added validation and error checking for incoming updates in ListenForWebhook --- bot.go | 26 ++++++++++++++++++++++++-- helpers.go | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/bot.go b/bot.go index a996790..3bdb49a 100644 --- a/bot.go +++ b/bot.go @@ -533,11 +533,33 @@ func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel { ch := make(chan Update, bot.Buffer) http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { - bytes, _ := ioutil.ReadAll(r.Body) + if r.Method != http.MethodPost { + errMsg, _ := json.Marshal(map[string]string{"error": "Wrong HTTP method, required POST"}) + w.WriteHeader(http.StatusMethodNotAllowed) + w.Header().Set("Content-Type", "application/json") + w.Write(errMsg) + return + } + + bytes, err := ioutil.ReadAll(r.Body) + if err != nil { + errMsg, _ := json.Marshal(map[string]string{"error": err.Error()}) + w.WriteHeader(http.StatusBadRequest) + w.Header().Set("Content-Type", "application/json") + w.Write(errMsg) + return + } r.Body.Close() var update Update - json.Unmarshal(bytes, &update) + err = json.Unmarshal(bytes, &update) + if err != nil { + errMsg, _ := json.Marshal(map[string]string{"error": err.Error()}) + w.WriteHeader(http.StatusBadRequest) + w.Header().Set("Content-Type", "application/json") + w.Write(errMsg) + return + } ch <- update }) diff --git a/helpers.go b/helpers.go index 3dabe11..70180bc 100644 --- a/helpers.go +++ b/helpers.go @@ -622,7 +622,7 @@ func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMess ChatID: chatID, MessageID: messageID, }, - Caption: caption, + Caption: caption, } } From d944d68fe6ebbde4aaafa592d8d0a2b935548cf8 Mon Sep 17 00:00:00 2001 From: Xing GUO Date: Tue, 31 Dec 2019 14:38:21 +0800 Subject: [PATCH 10/70] Document `NewMessageToChannel` clearer --- helpers.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helpers.go b/helpers.go index 3dabe11..294f31b 100644 --- a/helpers.go +++ b/helpers.go @@ -29,7 +29,8 @@ func NewDeleteMessage(chatID int64, messageID int) DeleteMessageConfig { // NewMessageToChannel creates a new Message that is sent to a channel // by username. // -// username is the username of the channel, text is the message text. +// username is the username of the channel, text is the message text, +// and the username should be in the form of `@username`. func NewMessageToChannel(username string, text string) MessageConfig { return MessageConfig{ BaseChat: BaseChat{ From 87891c10fe27ef36715525c25ae3d9b35babc372 Mon Sep 17 00:00:00 2001 From: Daniel Leining Date: Sun, 5 Jan 2020 00:35:15 -0500 Subject: [PATCH 11/70] add ability to respond to inline queries with stickers --- helpers.go | 12 +++++++++++- types.go | 11 +++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/helpers.go b/helpers.go index 3dabe11..04bf666 100644 --- a/helpers.go +++ b/helpers.go @@ -533,6 +533,16 @@ func NewInlineQueryResultCachedVideo(id, videoID, title string) InlineQueryResul } } +// NewInlineQueryResultCachedSticker create a new inline query with cached sticker. +func NewInlineQueryResultCachedSticker(id, stickerID, title string) InlineQueryResultCachedSticker { + return InlineQueryResultCachedSticker{ + Type: "sticker", + ID: id, + StickerID: stickerID, + Title: title, + } +} + // NewInlineQueryResultAudio creates a new inline query audio. func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio { return InlineQueryResultAudio{ @@ -622,7 +632,7 @@ func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMess ChatID: chatID, MessageID: messageID, }, - Caption: caption, + Caption: caption, } } diff --git a/types.go b/types.go index 52cb36c..9cd307a 100644 --- a/types.go +++ b/types.go @@ -736,6 +736,17 @@ type InlineQueryResultCachedVideo struct { InputMessageContent interface{} `json:"input_message_content,omitempty"` } +// InlineQueryResultCachedSticker is an inline query response with cached sticker. +type InlineQueryResultCachedSticker struct { + Type string `json:"type"` // required + ID string `json:"id"` // required + StickerID string `json:"sticker_file_id"` // required + Title string `json:"title"` // required + ParseMode string `json:"parse_mode"` + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + InputMessageContent interface{} `json:"input_message_content,omitempty"` +} + // InlineQueryResultAudio is an inline query response audio. type InlineQueryResultAudio struct { Type string `json:"type"` // required From 69bab9a28f2047c696d5c4d1c088fca6a2768bb8 Mon Sep 17 00:00:00 2001 From: Jiayu Yi Date: Mon, 13 Jan 2020 15:42:35 +0800 Subject: [PATCH 12/70] Add MaxConnections to WebhookInfo --- bot_test.go | 3 +++ types.go | 1 + 2 files changed, 4 insertions(+) diff --git a/bot_test.go b/bot_test.go index 60f3e65..b00ea41 100644 --- a/bot_test.go +++ b/bot_test.go @@ -497,6 +497,9 @@ func TestSetWebhookWithoutCert(t *testing.T) { if err != nil { t.Error(err) } + if info.MaxConnections == 0 { + t.Errorf("wanted max connections to be greater than 0") + } if info.LastErrorDate != 0 { t.Errorf("[Telegram callback failed]%s", info.LastErrorMessage) } diff --git a/types.go b/types.go index 70d66fa..b673dc6 100644 --- a/types.go +++ b/types.go @@ -571,6 +571,7 @@ type WebhookInfo struct { PendingUpdateCount int `json:"pending_update_count"` LastErrorDate int `json:"last_error_date"` // optional LastErrorMessage string `json:"last_error_message"` // optional + MaxConnections int `json:"max_connections"` } // IsSet returns true if a webhook is currently set. From e0d9306d8b80a6a5f9ac4d2aafa01bd790d6c10c Mon Sep 17 00:00:00 2001 From: Jiayu Yi Date: Mon, 13 Jan 2020 22:08:58 +0800 Subject: [PATCH 13/70] Include ResponseParameters in UploadFile error This makes UploadFile behave more similarly to MakeRequest when the response is not ok. --- bot.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bot.go b/bot.go index a996790..4a7e52e 100644 --- a/bot.go +++ b/bot.go @@ -226,7 +226,11 @@ func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldna } if !apiResp.Ok { - return APIResponse{}, errors.New(apiResp.Description) + parameters := ResponseParameters{} + if apiResp.Parameters != nil { + parameters = *apiResp.Parameters + } + return apiResp, Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters} } return apiResp, nil @@ -740,9 +744,9 @@ func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) } // RestrictChatMember to restrict a user in a supergroup. The bot must be an -//administrator in the supergroup for this to work and must have the -//appropriate admin rights. Pass True for all boolean parameters to lift -//restrictions from a user. Returns True on success. +// administrator in the supergroup for this to work and must have the +// appropriate admin rights. Pass True for all boolean parameters to lift +// restrictions from a user. Returns True on success. func (bot *BotAPI) RestrictChatMember(config RestrictChatMemberConfig) (APIResponse, error) { v := url.Values{} From fd860fdd66745e140316aa97698ba458c330c58e Mon Sep 17 00:00:00 2001 From: Daniel Leining Date: Thu, 23 Jan 2020 23:41:44 -0500 Subject: [PATCH 14/70] add file_unique_id --- types.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/types.go b/types.go index 70d66fa..2dc3beb 100644 --- a/types.go +++ b/types.go @@ -338,14 +338,15 @@ type Document struct { // Sticker contains information about a sticker. type Sticker struct { - FileID string `json:"file_id"` - Width int `json:"width"` - Height int `json:"height"` - Thumbnail *PhotoSize `json:"thumb"` // optional - Emoji string `json:"emoji"` // optional - FileSize int `json:"file_size"` // optional - SetName string `json:"set_name"` // optional - IsAnimated bool `json:"is_animated"` // optional + FileUniqueID string `json:"file_unique_id"` + FileID string `json:"file_id"` + Width int `json:"width"` + Height int `json:"height"` + Thumbnail *PhotoSize `json:"thumb"` // optional + Emoji string `json:"emoji"` // optional + FileSize int `json:"file_size"` // optional + SetName string `json:"set_name"` // optional + IsAnimated bool `json:"is_animated"` // optional } // ChatAnimation contains information about an animation. From f44d515f71f957178c4b408d94f644a267d316d6 Mon Sep 17 00:00:00 2001 From: Daniel Leining Date: Wed, 29 Jan 2020 22:58:02 -0500 Subject: [PATCH 15/70] add getStickerSet call --- bot.go | 19 +++++++++++++++++++ configs.go | 15 +++++++++++++++ types.go | 8 ++++++++ 3 files changed, 42 insertions(+) diff --git a/bot.go b/bot.go index a996790..e91e4e0 100644 --- a/bot.go +++ b/bot.go @@ -974,3 +974,22 @@ func (bot *BotAPI) DeleteChatPhoto(config DeleteChatPhotoConfig) (APIResponse, e return bot.MakeRequest(config.method(), v) } + +// GetStickerSet get a sticker set. +func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) { + v, err := config.values() + if err != nil { + return StickerSet{}, err + } + bot.debugLog(config.method(), v, nil) + res, err := bot.MakeRequest(config.method(), v) + if err != nil { + return StickerSet{}, err + } + stickerSet := StickerSet{} + err = json.Unmarshal(res.Result, &stickerSet) + if err != nil { + return StickerSet{}, err + } + return stickerSet, nil +} diff --git a/configs.go b/configs.go index 181d4e4..a7052dd 100644 --- a/configs.go +++ b/configs.go @@ -1262,3 +1262,18 @@ func (config DeleteChatPhotoConfig) values() (url.Values, error) { return v, nil } + +// GetStickerSetConfig contains information for get sticker set. +type GetStickerSetConfig struct { + Name string +} + +func (config GetStickerSetConfig) method() string { + return "getStickerSet" +} + +func (config GetStickerSetConfig) values() (url.Values, error) { + v := url.Values{} + v.Add("name", config.Name) + return v, nil +} diff --git a/types.go b/types.go index 70d66fa..810dd9b 100644 --- a/types.go +++ b/types.go @@ -348,6 +348,14 @@ type Sticker struct { IsAnimated bool `json:"is_animated"` // optional } +type StickerSet struct { + Name string `json:"name"` + Title string `json:"title"` + IsAnimated bool `json:"is_animated"` + ContainsMasks bool `json:"contains_masks"` + Stickers []Sticker `json:"stickers"` +} + // ChatAnimation contains information about an animation. type ChatAnimation struct { FileID string `json:"file_id"` From 706e70933da04f25dbf2985bc5da4b3002319760 Mon Sep 17 00:00:00 2001 From: Tarcisio Gruppi Date: Sat, 22 Feb 2020 19:13:34 -0300 Subject: [PATCH 16/70] Close updates chan on stop --- bot.go | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.go b/bot.go index a996790..019fe19 100644 --- a/bot.go +++ b/bot.go @@ -495,6 +495,7 @@ func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) (UpdatesChannel, error) { for { select { case <-bot.shutdownChannel: + close(ch) return default: } From b5d42143e7dd8968ad3794af63aeb8ccb15eacbb Mon Sep 17 00:00:00 2001 From: Adelya Date: Tue, 3 Mar 2020 17:00:42 +0300 Subject: [PATCH 17/70] Ability to create BotAPI instance directly with new API endpoint --- bot.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/bot.go b/bot.go index a996790..790f47f 100644 --- a/bot.go +++ b/bot.go @@ -36,21 +36,29 @@ type BotAPI struct { // // It requires a token, provided by @BotFather on Telegram. func NewBotAPI(token string) (*BotAPI, error) { - return NewBotAPIWithClient(token, &http.Client{}) + return NewBotAPIWithClient(token, APIEndpoint, &http.Client{}) +} + +// NewBotAPIWithAPIEndpoint creates a new BotAPI instance +// and allows you to pass API endpoint. +// +// It requires a token, provided by @BotFather on Telegram and API endpoint. +func NewBotAPIWithAPIEndpoint(token, apiEndpoint string) (*BotAPI, error) { + return NewBotAPIWithClient(token, apiEndpoint, &http.Client{}) } // NewBotAPIWithClient creates a new BotAPI instance // and allows you to pass a http.Client. // -// It requires a token, provided by @BotFather on Telegram. -func NewBotAPIWithClient(token string, client *http.Client) (*BotAPI, error) { +// It requires a token, provided by @BotFather on Telegram and API endpoint. +func NewBotAPIWithClient(token, apiEndpoint string, client *http.Client) (*BotAPI, error) { bot := &BotAPI{ Token: token, Client: client, Buffer: 100, shutdownChannel: make(chan interface{}), - apiEndpoint: APIEndpoint, + apiEndpoint: apiEndpoint, } self, err := bot.GetMe() From 303a66f022f500bac7ae8d9bdf9d0a5dbfa1e0f6 Mon Sep 17 00:00:00 2001 From: Mendel E Date: Sun, 26 Apr 2020 00:30:21 -0400 Subject: [PATCH 18/70] Add ParseMode to InlineQueryResultPhoto --- types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types.go b/types.go index 70d66fa..56a91d5 100644 --- a/types.go +++ b/types.go @@ -635,6 +635,7 @@ type InlineQueryResultPhoto struct { Title string `json:"title"` Description string `json:"description"` Caption string `json:"caption"` + ParseMode string `json:"parse_mode"` ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` InputMessageContent interface{} `json:"input_message_content,omitempty"` } From 74925cfcaf65580e42aa05296691424b181de85d Mon Sep 17 00:00:00 2001 From: "maria.bagdasarova" Date: Fri, 22 May 2020 11:42:19 +0300 Subject: [PATCH 19/70] Fix nil pointer on User String method --- types.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/types.go b/types.go index 5c1c55e..551b5c5 100644 --- a/types.go +++ b/types.go @@ -64,6 +64,9 @@ type User struct { // It is normally a user's username, but falls back to a first/last // name as available. func (u *User) String() string { + if u == nil { + return "" + } if u.UserName != "" { return u.UserName } From 6792fab6bb9bbeda26f6ef0573946e15fc4b33af Mon Sep 17 00:00:00 2001 From: Andrii Soluk Date: Sun, 24 May 2020 12:54:43 +0300 Subject: [PATCH 20/70] feat: Replaces *http.Client with an interface Signed-off-by: Andrii Soluk --- bot.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/bot.go b/bot.go index 5f25979..e6c2cc8 100644 --- a/bot.go +++ b/bot.go @@ -19,14 +19,18 @@ import ( "github.com/technoweenie/multipartstreamer" ) +type HttpClient interface { + Do(req *http.Request) (*http.Response, error) +} + // BotAPI allows you to interact with the Telegram Bot API. type BotAPI struct { Token string `json:"token"` Debug bool `json:"debug"` Buffer int `json:"buffer"` - Self User `json:"-"` - Client *http.Client `json:"-"` + Self User `json:"-"` + Client HttpClient `json:"-"` shutdownChannel chan interface{} apiEndpoint string @@ -51,7 +55,7 @@ func NewBotAPIWithAPIEndpoint(token, apiEndpoint string) (*BotAPI, error) { // and allows you to pass a http.Client. // // It requires a token, provided by @BotFather on Telegram and API endpoint. -func NewBotAPIWithClient(token, apiEndpoint string, client *http.Client) (*BotAPI, error) { +func NewBotAPIWithClient(token, apiEndpoint string, client HttpClient) (*BotAPI, error) { bot := &BotAPI{ Token: token, Client: client, @@ -79,7 +83,13 @@ func (b *BotAPI) SetAPIEndpoint(apiEndpoint string) { func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, error) { method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint) - resp, err := bot.Client.PostForm(method, params) + req, err := http.NewRequest("POST", method, strings.NewReader(params.Encode())) + if err != nil { + return APIResponse{}, err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + resp, err := bot.Client.Do(req) if err != nil { return APIResponse{}, err } From e55e8bc55aa771d1a0bcc4d05a5f135020ceba10 Mon Sep 17 00:00:00 2001 From: Dmytro Kurest Date: Sun, 28 Jun 2020 22:13:32 +0300 Subject: [PATCH 21/70] Fixes error parameter name for AnswerPreCheckoutQuery --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index e6c2cc8..0bac814 100644 --- a/bot.go +++ b/bot.go @@ -881,7 +881,7 @@ func (bot *BotAPI) AnswerPreCheckoutQuery(config PreCheckoutConfig) (APIResponse v.Add("pre_checkout_query_id", config.PreCheckoutQueryID) v.Add("ok", strconv.FormatBool(config.OK)) if config.OK != true { - v.Add("error", config.ErrorMessage) + v.Add("error_message", config.ErrorMessage) } bot.debugLog("answerPreCheckoutQuery", v, nil) From dc71b50b19cb81acc603a6ef671714d017d6b333 Mon Sep 17 00:00:00 2001 From: "an.groshev" Date: Wed, 1 Jul 2020 20:03:05 +0300 Subject: [PATCH 22/70] add MarkdownV2 --- configs.go | 5 +++-- helpers.go | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/configs.go b/configs.go index a7052dd..1c5ca75 100644 --- a/configs.go +++ b/configs.go @@ -36,8 +36,9 @@ const ( // Constant values for ParseMode in MessageConfig const ( - ModeMarkdown = "Markdown" - ModeHTML = "HTML" + ModeMarkdown = "Markdown" + ModeMarkdownV2 = "MarkdownV2" + ModeHTML = "HTML" ) // Library errors diff --git a/helpers.go b/helpers.go index d2fb165..b9afb84 100644 --- a/helpers.go +++ b/helpers.go @@ -438,6 +438,19 @@ func NewInlineQueryResultArticleMarkdown(id, title, messageText string) InlineQu } } +// NewInlineQueryResultArticleMarkdownV2 creates a new inline query article with MarkdownV2 parsing. +func NewInlineQueryResultArticleMarkdownV2(id, title, messageText string) InlineQueryResultArticle { + return InlineQueryResultArticle{ + Type: "article", + ID: id, + Title: title, + InputMessageContent: InputTextMessageContent{ + Text: messageText, + ParseMode: "MarkdownV2", + }, + } +} + // NewInlineQueryResultArticleHTML creates a new inline query article with HTML parsing. func NewInlineQueryResultArticleHTML(id, title, messageText string) InlineQueryResultArticle { return InlineQueryResultArticle{ From 86a3d94b4ba4e5318466cd56f738d18ca039fcdb Mon Sep 17 00:00:00 2001 From: ros-tel Date: Sun, 19 Jul 2020 10:11:27 +0500 Subject: [PATCH 23/70] Delete a message in a channel --- configs.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/configs.go b/configs.go index a7052dd..4bd2c33 100644 --- a/configs.go +++ b/configs.go @@ -1138,8 +1138,9 @@ type PreCheckoutConfig struct { // DeleteMessageConfig contains information of a message in a chat to delete. type DeleteMessageConfig struct { - ChatID int64 - MessageID int + ChannelUsername string + ChatID int64 + MessageID int } func (config DeleteMessageConfig) method() string { @@ -1149,7 +1150,12 @@ func (config DeleteMessageConfig) method() string { func (config DeleteMessageConfig) values() (url.Values, error) { v := url.Values{} - v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + if config.ChannelUsername == "" { + v.Add("chat_id", strconv.FormatInt(config.ChatID, 10)) + } else { + v.Add("chat_id", config.ChannelUsername) + } + v.Add("message_id", strconv.Itoa(config.MessageID)) return v, nil From f11e1caecf8aca5a417dfdccb35cae275fc3507c Mon Sep 17 00:00:00 2001 From: mehanizm Date: Tue, 31 Mar 2020 09:02:18 +0300 Subject: [PATCH 24/70] feat: add sendDice configs Add sendDice config to use in Send method as a Chattable interface. Add NewDice and NewDiceWithEmoji helpers Add tests https://core.telegram.org/bots/api#senddice --- bot.go | 5 +++-- bot_test.go | 28 +++++++++++++++++++++++++++- configs.go | 27 +++++++++++++++++++++++++++ helpers.go | 26 +++++++++++++++++++++++++- helpers_test.go | 21 ++++++++++++++++++++- types.go | 1 + 6 files changed, 103 insertions(+), 5 deletions(-) diff --git a/bot.go b/bot.go index a7647d6..c112ab4 100644 --- a/bot.go +++ b/bot.go @@ -75,8 +75,9 @@ func NewBotAPIWithClient(token, apiEndpoint string, client HttpClient) (*BotAPI, return bot, nil } -func (b *BotAPI) SetAPIEndpoint(apiEndpoint string) { - b.apiEndpoint = apiEndpoint +// SetAPIEndpoint add telegram apiEndpont to Bot +func (bot *BotAPI) SetAPIEndpoint(apiEndpoint string) { + bot.apiEndpoint = apiEndpoint } // MakeRequest makes a request to a specific endpoint with our token. diff --git a/bot_test.go b/bot_test.go index 2e9d07a..0c98ee9 100644 --- a/bot_test.go +++ b/bot_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/go-telegram-bot-api/telegram-bot-api" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" ) const ( @@ -402,6 +402,32 @@ func TestSendWithExistingStickerAndKeyboardHide(t *testing.T) { } } +func TestSendWithDice(t *testing.T) { + bot, _ := getBot(t) + + msg := tgbotapi.NewDice(ChatID) + _, err := bot.Send(msg) + + if err != nil { + t.Error(err) + t.Fail() + } + +} + +func TestSendWithDiceWithEmoji(t *testing.T) { + bot, _ := getBot(t) + + msg := tgbotapi.NewDiceWithEmoji(ChatID, "🏀") + _, err := bot.Send(msg) + + if err != nil { + t.Error(err) + t.Fail() + } + +} + func TestGetFile(t *testing.T) { bot, _ := getBot(t) diff --git a/configs.go b/configs.go index 0265ada..3989774 100644 --- a/configs.go +++ b/configs.go @@ -1284,3 +1284,30 @@ func (config GetStickerSetConfig) values() (url.Values, error) { v.Add("name", config.Name) return v, nil } + +// 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 “🎯”, and values 1-5 for “🏀”. + // Defaults to “🎲” + Emoji string +} + +// values returns a url.Values representation of DiceConfig. +func (config DiceConfig) values() (url.Values, error) { + v, err := config.BaseChat.values() + if err != nil { + return v, err + } + if config.Emoji != "" { + v.Add("emoji", config.Emoji) + } + return v, nil +} + +// method returns Telegram API method name for sending Dice. +func (config DiceConfig) method() string { + return "sendDice" +} diff --git a/helpers.go b/helpers.go index b9afb84..e8f8831 100644 --- a/helpers.go +++ b/helpers.go @@ -18,6 +18,30 @@ func NewMessage(chatID int64, text string) MessageConfig { } } +// NewDice creates a new DiceConfig. +// +// chatID is where to send it +func NewDice(chatID int64) DiceConfig { + return DiceConfig{ + BaseChat: BaseChat{ + ChatID: chatID, + }, + } +} + +// NewDiceWithEmoji creates a new DiceConfig. +// +// chatID is where to send it +// emoji is type of the Dice +func NewDiceWithEmoji(chatID int64, emoji string) DiceConfig { + return DiceConfig{ + BaseChat: BaseChat{ + ChatID: chatID, + }, + Emoji: emoji, + } +} + // NewDeleteMessage creates a request to delete a message. func NewDeleteMessage(chatID int64, messageID int) DeleteMessageConfig { return DeleteMessageConfig{ @@ -491,7 +515,7 @@ func NewInlineQueryResultMPEG4GIF(id, url string) InlineQueryResultMPEG4GIF { } } -// NewInlineQueryResultCachedPhoto create a new inline query with cached photo. +// NewInlineQueryResultCachedMPEG4GIF create a new inline query with cached MPEG4 GIF. func NewInlineQueryResultCachedMPEG4GIF(id, MPEG4GifID string) InlineQueryResultCachedMpeg4Gif { return InlineQueryResultCachedMpeg4Gif{ Type: "mpeg4_gif", diff --git a/helpers_test.go b/helpers_test.go index 9542f02..ec15a4e 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -1,8 +1,9 @@ package tgbotapi_test import ( - "github.com/go-telegram-bot-api/telegram-bot-api" "testing" + + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" ) func TestNewInlineQueryResultArticle(t *testing.T) { @@ -175,3 +176,21 @@ func TestNewEditMessageReplyMarkup(t *testing.T) { } } + +func TestNewDice(t *testing.T) { + dice := tgbotapi.NewDice(42) + + if dice.ChatID != 42 || + dice.Emoji != "" { + t.Fail() + } +} + +func TestNewDiceWithEmoji(t *testing.T) { + dice := tgbotapi.NewDiceWithEmoji(42, "🏀") + + if dice.ChatID != 42 || + dice.Emoji != "🏀" { + t.Fail() + } +} diff --git a/types.go b/types.go index 6e295ca..f2ad140 100644 --- a/types.go +++ b/types.go @@ -352,6 +352,7 @@ type Sticker struct { IsAnimated bool `json:"is_animated"` // optional } +// StickerSet contains information about an sticker set. type StickerSet struct { Name string `json:"name"` Title string `json:"title"` From 64517d16e7c54529952c535c22764e8cbbfd939c Mon Sep 17 00:00:00 2001 From: Jiayu Yi Date: Tue, 21 Jul 2020 16:33:33 +0800 Subject: [PATCH 25/70] Mark WebhookInfo.MaxConnections as optional --- types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types.go b/types.go index b673dc6..4ca2fe9 100644 --- a/types.go +++ b/types.go @@ -571,7 +571,7 @@ type WebhookInfo struct { PendingUpdateCount int `json:"pending_update_count"` LastErrorDate int `json:"last_error_date"` // optional LastErrorMessage string `json:"last_error_message"` // optional - MaxConnections int `json:"max_connections"` + MaxConnections int `json:"max_connections"` // optional } // IsSet returns true if a webhook is currently set. From ce395c2286e5532256440120e145eb551e558555 Mon Sep 17 00:00:00 2001 From: Syfaro Date: Tue, 21 Jul 2020 03:35:48 -0500 Subject: [PATCH 26/70] Update comment on NewOneTimeReplyKeyboard. --- helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helpers.go b/helpers.go index fc19313..bf256b8 100644 --- a/helpers.go +++ b/helpers.go @@ -704,7 +704,7 @@ func NewReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup { } } -// NewOneTimeReplyKeyboard creates a new one time keyboard using NewReplyKeyboard() +// NewOneTimeReplyKeyboard creates a new one time keyboard. func NewOneTimeReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup { markup := NewReplyKeyboard(rows...) markup.OneTimeKeyboard = true From 5c5e96de34ba4bcb0b1d1e9dd757559577c71e47 Mon Sep 17 00:00:00 2001 From: Jiayu Yi Date: Tue, 21 Jul 2020 16:37:08 +0800 Subject: [PATCH 27/70] Change assertion failure message --- bot_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot_test.go b/bot_test.go index b00ea41..8e5cf63 100644 --- a/bot_test.go +++ b/bot_test.go @@ -498,7 +498,7 @@ func TestSetWebhookWithoutCert(t *testing.T) { t.Error(err) } if info.MaxConnections == 0 { - t.Errorf("wanted max connections to be greater than 0") + t.Errorf("Expected maximum connections to be greater than 0") } if info.LastErrorDate != 0 { t.Errorf("[Telegram callback failed]%s", info.LastErrorMessage) From 4b372faeebe7df44f54a8495a6d3ca91b59fb6dd Mon Sep 17 00:00:00 2001 From: Syfaro Date: Tue, 21 Jul 2020 03:56:23 -0500 Subject: [PATCH 28/70] Make returned error consistent. --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index f13fa5d..f0b35a4 100644 --- a/bot.go +++ b/bot.go @@ -111,7 +111,7 @@ func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, if apiResp.Parameters != nil { parameters = *apiResp.Parameters } - return apiResp, &Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters} + return apiResp, Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters} } return apiResp, nil From dff2120d96a3baa18c2a73b5fc56fb744ad04665 Mon Sep 17 00:00:00 2001 From: Syfaro Date: Wed, 22 Jul 2020 04:33:50 -0500 Subject: [PATCH 29/70] Remove old Go versions from Travis. --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 51865c8..712ce95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: go go: - - '1.10' - - '1.11' - - '1.12' - '1.13' + - '1.14' - tip From b6575a2934b018fc5109ac4b161cc52f51210436 Mon Sep 17 00:00:00 2001 From: Dmitriy Kharchenko <43345312+dmitriy-kharchenko@users.noreply.github.com> Date: Wed, 29 Jul 2020 09:51:11 +0300 Subject: [PATCH 30/70] Added stream processing of input JSON Co-authored-by: TJ Horner --- bot.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/bot.go b/bot.go index 5a13ec7..16cdacd 100644 --- a/bot.go +++ b/bot.go @@ -579,17 +579,8 @@ func (bot *BotAPI) HandleUpdate(r *http.Request) (*Update, error) { return nil, err } - payload, err := ioutil.ReadAll(r.Body) - if err != nil { - return nil, err - } - - if err := r.Body.Close(); err != nil { - return nil, err - } - var update Update - err = json.Unmarshal(payload, &update) + err := json.NewDecoder(r.Body).Decode(&update) if err != nil { return nil, err } From 5ebb3edeffaa49f5bdf05e6f810d171714211628 Mon Sep 17 00:00:00 2001 From: TJ Horner Date: Mon, 10 Aug 2020 17:17:07 -0400 Subject: [PATCH 31/70] feat: Add CustomTitle field to ChatMember --- types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types.go b/types.go index 44f1a58..0362c51 100644 --- a/types.go +++ b/types.go @@ -517,6 +517,7 @@ type ForceReply struct { type ChatMember struct { User *User `json:"user"` Status string `json:"status"` + CustomTitle string `json:"custom_title,omitempty"` // optional UntilDate int64 `json:"until_date,omitempty"` // optional CanBeEdited bool `json:"can_be_edited,omitempty"` // optional CanChangeInfo bool `json:"can_change_info,omitempty"` // optional From dadb760cdebdb5fed4e4665d94c7eb25d4f279e5 Mon Sep 17 00:00:00 2001 From: vdimir Date: Thu, 20 Aug 2020 20:59:20 +0300 Subject: [PATCH 32/70] Add missing message fields media_group_id author_signature via_bot --- types.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/types.go b/types.go index 0362c51..5e95678 100644 --- a/types.go +++ b/types.go @@ -143,7 +143,10 @@ type Message struct { ForwardFromMessageID int `json:"forward_from_message_id"` // optional ForwardDate int `json:"forward_date"` // optional ReplyToMessage *Message `json:"reply_to_message"` // optional + ViaBot *User `json:"via_bot"` // optional EditDate int `json:"edit_date"` // optional + MediaGroupID string `json:"media_group_id"` // optional + AuthorSignature string `json:"author_signature"` // optional Text string `json:"text"` // optional Entities *[]MessageEntity `json:"entities"` // optional CaptionEntities *[]MessageEntity `json:"caption_entities"` // optional From 4a2c8c4547a868841c1ec088302b23b59443de2b Mon Sep 17 00:00:00 2001 From: bcmk <45658475+bcmk@users.noreply.github.com> Date: Sun, 27 Sep 2020 00:55:26 +0400 Subject: [PATCH 33/70] setMyCommands implemented --- bot.go | 15 +++++++++++++++ types.go | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/bot.go b/bot.go index e8e1a7c..83903d4 100644 --- a/bot.go +++ b/bot.go @@ -1036,3 +1036,18 @@ func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) } return stickerSet, nil } + +// SetMyCommands changes the list of the bot's commands. +func (bot *BotAPI) SetMyCommands(commands []BotCommand) error { + v := url.Values{} + data, err := json.Marshal(commands) + if err != nil { + return err + } + v.Add("commands", string(data)) + _, err = bot.MakeRequest("setMyCommands", v) + if err != nil { + return err + } + return nil +} diff --git a/types.go b/types.go index 5e95678..a4a9625 100644 --- a/types.go +++ b/types.go @@ -1005,3 +1005,9 @@ type Error struct { func (e Error) Error() string { return e.Message } + +// BotCommand represents a bot command. +type BotCommand struct { + Command string `json:"command"` + Description string `json:"description"` +} From e7590a0638df29ec1e28568b1195362642daf74a Mon Sep 17 00:00:00 2001 From: bcmk <45658475+bcmk@users.noreply.github.com> Date: Sun, 27 Sep 2020 01:54:11 +0400 Subject: [PATCH 34/70] getMyCommands implemented --- bot.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bot.go b/bot.go index 83903d4..cffe4c2 100644 --- a/bot.go +++ b/bot.go @@ -1037,6 +1037,20 @@ func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) return stickerSet, nil } +// GetMyCommands gets the current list of the bot's commands. +func (bot *BotAPI) GetMyCommands() ([]BotCommand, error) { + res, err := bot.MakeRequest("getMyCommands", nil) + if err != nil { + return nil, err + } + var commands []BotCommand + err = json.Unmarshal(res.Result, &commands) + if err != nil { + return nil, err + } + return commands, nil +} + // SetMyCommands changes the list of the bot's commands. func (bot *BotAPI) SetMyCommands(commands []BotCommand) error { v := url.Values{} From 152625538f56f2c9e6fe8a4b7e876aa0a9af28b2 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Mon, 19 Oct 2020 00:09:50 +0300 Subject: [PATCH 35/70] Add message documentation --- types.go | 197 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 154 insertions(+), 43 deletions(-) diff --git a/types.go b/types.go index a4a9625..8c907f0 100644 --- a/types.go +++ b/types.go @@ -134,49 +134,160 @@ func (c Chat) ChatConfig() ChatConfig { // Message is returned by almost every request, and contains data about // almost anything. type Message struct { - MessageID int `json:"message_id"` - From *User `json:"from"` // optional - Date int `json:"date"` - Chat *Chat `json:"chat"` - ForwardFrom *User `json:"forward_from"` // optional - ForwardFromChat *Chat `json:"forward_from_chat"` // optional - ForwardFromMessageID int `json:"forward_from_message_id"` // optional - ForwardDate int `json:"forward_date"` // optional - ReplyToMessage *Message `json:"reply_to_message"` // optional - ViaBot *User `json:"via_bot"` // optional - EditDate int `json:"edit_date"` // optional - MediaGroupID string `json:"media_group_id"` // optional - AuthorSignature string `json:"author_signature"` // optional - Text string `json:"text"` // optional - Entities *[]MessageEntity `json:"entities"` // optional - CaptionEntities *[]MessageEntity `json:"caption_entities"` // optional - Audio *Audio `json:"audio"` // optional - Document *Document `json:"document"` // optional - Animation *ChatAnimation `json:"animation"` // optional - Game *Game `json:"game"` // optional - Photo *[]PhotoSize `json:"photo"` // optional - Sticker *Sticker `json:"sticker"` // optional - Video *Video `json:"video"` // optional - VideoNote *VideoNote `json:"video_note"` // optional - Voice *Voice `json:"voice"` // optional - Caption string `json:"caption"` // optional - Contact *Contact `json:"contact"` // optional - Location *Location `json:"location"` // optional - Venue *Venue `json:"venue"` // optional - NewChatMembers *[]User `json:"new_chat_members"` // optional - LeftChatMember *User `json:"left_chat_member"` // optional - NewChatTitle string `json:"new_chat_title"` // optional - NewChatPhoto *[]PhotoSize `json:"new_chat_photo"` // optional - DeleteChatPhoto bool `json:"delete_chat_photo"` // optional - GroupChatCreated bool `json:"group_chat_created"` // optional - SuperGroupChatCreated bool `json:"supergroup_chat_created"` // optional - ChannelChatCreated bool `json:"channel_chat_created"` // optional - MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional - MigrateFromChatID int64 `json:"migrate_from_chat_id"` // optional - PinnedMessage *Message `json:"pinned_message"` // optional - Invoice *Invoice `json:"invoice"` // optional - SuccessfulPayment *SuccessfulPayment `json:"successful_payment"` // optional - PassportData *PassportData `json:"passport_data,omitempty"` // optional + // MessageID is a unique message identifier inside this chat + MessageID int `json:"message_id"` + // From is a sender, empty for messages sent to channels; + // optional + From *User `json:"from"` + // Date of the message was sent in Unix time + Date int `json:"date"` + // Chat is the conversation the message belongs to + Chat *Chat `json:"chat"` + // ForwardFrom for forwarded messages, sender of the original message; + // optional + ForwardFrom *User `json:"forward_from"` + // ForwardFromChat for messages forwarded from channels, + // information about the original channel; + // optional + ForwardFromChat *Chat `json:"forward_from_chat"` + // ForwardFromMessageID for messages forwarded from channels, + // identifier of the original message in the channel; + // optional + ForwardFromMessageID int `json:"forward_from_message_id"` + // ForwardDate for forwarded messages, date the original message was sent in Unix time; + // optional + ForwardDate int `json:"forward_date"` + // ReplyToMessage for replies, the original message. + // Note that the Message object in this field will not contain further ReplyToMessage fields + // even if it itself is a reply; + // optional + ReplyToMessage *Message `json:"reply_to_message"` + // ViaBot through which the message was sent; + // optional + ViaBot *User `json:"via_bot"` + // EditDate of the message was last edited in Unix time; + // optional + EditDate int `json:"edit_date"` + // MediaGroupID is the unique identifier of a media message group this message belongs to; + // optional + MediaGroupID string `json:"media_group_id"` + // AuthorSignature is the signature of the post author for messages in channels; + // optional + AuthorSignature string `json:"author_signature"` + // Text is for text messages, the actual UTF-8 text of the message, 0-4096 characters; + // optional + Text string `json:"text"` + // Entities is for text messages, special entities like usernames, + // URLs, bot commands, etc. that appear in the text; + // optional + Entities *[]MessageEntity `json:"entities"` + // CaptionEntities; + // optional + CaptionEntities *[]MessageEntity `json:"caption_entities"` + // Audio message is an audio file, information about the file; + // optional + Audio *Audio `json:"audio"` + // Document message is a general file, information about the file; + // optional + Document *Document `json:"document"` + // Animation message is an animation, information about the animation. + // For backward compatibility, when this field is set, the document field will also be set; + // optional + Animation *ChatAnimation `json:"animation"` + // Game message is a game, information about the game; + // optional + Game *Game `json:"game"` + // Photo message is a photo, available sizes of the photo; + // optional + Photo *[]PhotoSize `json:"photo"` + // Sticker message is a sticker, information about the sticker; + // optional + Sticker *Sticker `json:"sticker"` + // Video message is a video, information about the video; + // optional + Video *Video `json:"video"` + // VideoNote message is a video note, information about the video message; + // optional + VideoNote *VideoNote `json:"video_note"` + // Voice message is a voice message, information about the file; + // optional + Voice *Voice `json:"voice"` + // Caption for the animation, audio, document, photo, video or voice, 0-1024 characters; + // optional + Caption string `json:"caption"` + // Contact message is a shared contact, information about the contact; + // optional + Contact *Contact `json:"contact"` + // Location message is a shared location, information about the location; + // optional + Location *Location `json:"location"` + // Venue message is a venue, information about the venue. + // For backward compatibility, when this field is set, the location field will also be set; + // optional + Venue *Venue `json:"venue"` + // NewChatMembers that were added to the group or supergroup + // and information about them (the bot itself may be one of these members); + // optional + NewChatMembers *[]User `json:"new_chat_members"` + // LeftChatMember is a member was removed from the group, + // information about them (this member may be the bot itself); + // optional + LeftChatMember *User `json:"left_chat_member"` + // NewChatTitle is a chat title was changed to this value; + // optional + NewChatTitle string `json:"new_chat_title"` + // NewChatPhoto is a chat photo was change to this value; + // optional + NewChatPhoto *[]PhotoSize `json:"new_chat_photo"` + // DeleteChatPhoto is a service message: the chat photo was deleted; + // optional + DeleteChatPhoto bool `json:"delete_chat_photo"` + // GroupChatCreated is a service message: the group has been created; + // optional + GroupChatCreated bool `json:"group_chat_created"` + // SuperGroupChatCreated is a service message: the supergroup has been created. + // This field can't be received in a message coming through updates, + // because bot can't be a member of a supergroup when it is created. + // It can only be found in ReplyToMessage if someone replies to a very first message + // in a directly created supergroup; + // optional + SuperGroupChatCreated bool `json:"supergroup_chat_created"` + // ChannelChatCreated is a service message: the channel has been created. + // This field can't be received in a message coming through updates, + // because bot can't be a member of a channel when it is created. + // It can only be found in ReplyToMessage + // if someone replies to a very first message in a channel; + // optional + ChannelChatCreated bool `json:"channel_chat_created"` + // MigrateToChatID is the group has been migrated to a supergroup with the specified identifier. + // This number may be greater than 32 bits and some programming languages + // may have difficulty/silent defects in interpreting it. + // But it is smaller than 52 bits, so a signed 64 bit integer + // or double-precision float type are safe for storing this identifier; + // optional + MigrateToChatID int64 `json:"migrate_to_chat_id"` + // MigrateFromChatID is the supergroup has been migrated from a group with the specified identifier. + // This number may be greater than 32 bits and some programming languages + // may have difficulty/silent defects in interpreting it. + // But it is smaller than 52 bits, so a signed 64 bit integer + // or double-precision float type are safe for storing this identifier; + // optional + MigrateFromChatID int64 `json:"migrate_from_chat_id"` + // PinnedMessage is a specified message was pinned. + // Note that the Message object in this field will not contain further ReplyToMessage + // fields even if it is itself a reply; + // optional + PinnedMessage *Message `json:"pinned_message"` + // Invoice message is an invoice for a payment; + // optional + Invoice *Invoice `json:"invoice"` + // SuccessfulPayment message is a service message about a successful payment, + // information about the payment; + // optional + SuccessfulPayment *SuccessfulPayment `json:"successful_payment"` + // PassportData is a Telegram Passport data; + // optional + PassportData *PassportData `json:"passport_data,omitempty"` } // Time converts the message timestamp into a Time. From 5e61ed0493dec527a133234a57bda1b4d7d6e7f1 Mon Sep 17 00:00:00 2001 From: TJ Horner Date: Mon, 19 Oct 2020 17:00:31 -0400 Subject: [PATCH 36/70] Temporarily fix MediaGroup test (Imgur -> GitHub) Telegram decided that it's no longer friends with Imgur, so we will need to use the direct GitHub asset links for now. Probably will want to eventually swap this over to uploading the file since we don't want to accidentally DDOS GitHub. --- bot_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bot_test.go b/bot_test.go index 1118a08..619b4e3 100644 --- a/bot_test.go +++ b/bot_test.go @@ -549,9 +549,8 @@ func TestSendWithMediaGroup(t *testing.T) { bot, _ := getBot(t) cfg := tgbotapi.NewMediaGroup(ChatID, []interface{}{ - tgbotapi.NewInputMediaPhoto("https://i.imgur.com/unQLJIb.jpg"), - tgbotapi.NewInputMediaPhoto("https://i.imgur.com/J5qweNZ.jpg"), - tgbotapi.NewInputMediaVideo("https://i.imgur.com/F6RmI24.mp4"), + tgbotapi.NewInputMediaPhoto("https://github.com/go-telegram-bot-api/telegram-bot-api/raw/0a3a1c8716c4cd8d26a262af9f12dcbab7f3f28c/tests/image.jpg"), + tgbotapi.NewInputMediaVideo("https://github.com/go-telegram-bot-api/telegram-bot-api/raw/0a3a1c8716c4cd8d26a262af9f12dcbab7f3f28c/tests/video.mp4"), }) _, err := bot.Send(cfg) if err != nil { From b6df6c273aa804a6c7dd2f719ac8be1a95ce2790 Mon Sep 17 00:00:00 2001 From: zhuharev Date: Tue, 20 Oct 2020 06:52:08 +0300 Subject: [PATCH 37/70] Add params from develop branch, config for poll --- configs.go | 53 ++++++++++++++++++++++++ params.go | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 params.go diff --git a/configs.go b/configs.go index 3989774..98abace 100644 --- a/configs.go +++ b/configs.go @@ -72,6 +72,18 @@ type BaseChat struct { DisableNotification bool } +func (chat *BaseChat) params() (Params, error) { + params := make(Params) + + params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername) + params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID) + params.AddBool("disable_notification", chat.DisableNotification) + + err := params.AddInterface("reply_markup", chat.ReplyMarkup) + + return params, err +} + // values returns url.Values representation of BaseChat func (chat *BaseChat) values() (url.Values, error) { v := url.Values{} @@ -765,6 +777,47 @@ 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 + OpenPeriod int + CloseDate int + IsClosed bool +} + +func (config SendPollConfig) values() (url.Values, error) { + params, err := config.BaseChat.params() + if err != nil { + return params.toValues(), err + } + + params["question"] = config.Question + err = params.AddInterface("options", config.Options) + 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) + + return params.toValues(), err +} + +func (SendPollConfig) method() string { + return "sendPoll" +} + // GameConfig allows you to send a game. type GameConfig struct { BaseChat diff --git a/params.go b/params.go new file mode 100644 index 0000000..6dce6fb --- /dev/null +++ b/params.go @@ -0,0 +1,116 @@ +package tgbotapi + +import ( + "encoding/json" + "net/url" + "reflect" + "strconv" +) + +// Params represents a set of parameters that gets passed to a request. +type Params map[string]string + +func newParams(values url.Values) Params { + params := Params{} + for k, v := range values { + if len(v) > 0 { + params[k] = v[0] + } + } + return params +} + +func (p Params) toValues() url.Values { + values := url.Values{} + for k, v := range p { + values[k] = []string{v} + } + return values +} + +// AddNonEmpty adds a value if it not an empty string. +func (p Params) AddNonEmpty(key, value string) { + if value != "" { + p[key] = value + } +} + +// AddNonZero adds a value if it is not zero. +func (p Params) AddNonZero(key string, value int) { + if value != 0 { + p[key] = strconv.Itoa(value) + } +} + +// AddNonZero64 is the same as AddNonZero except uses an int64. +func (p Params) AddNonZero64(key string, value int64) { + if value != 0 { + p[key] = strconv.FormatInt(value, 10) + } +} + +// AddBool adds a value of a bool if it is true. +func (p Params) AddBool(key string, value bool) { + if value { + p[key] = strconv.FormatBool(value) + } +} + +// AddNonZeroFloat adds a floating point value that is not zero. +func (p Params) AddNonZeroFloat(key string, value float64) { + if value != 0 { + p[key] = strconv.FormatFloat(value, 'f', 6, 64) + } +} + +// AddInterface adds an interface if it is not nill and can be JSON marshalled. +func (p Params) AddInterface(key string, value interface{}) error { + if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) { + return nil + } + + b, err := json.Marshal(value) + if err != nil { + return err + } + + p[key] = string(b) + + return nil +} + +// AddFirstValid attempts to add the first item that is not a default value. +// +// For example, AddFirstValid(0, "", "test") would add "test". +func (p Params) AddFirstValid(key string, args ...interface{}) error { + for _, arg := range args { + switch v := arg.(type) { + case int: + if v != 0 { + p[key] = strconv.Itoa(v) + return nil + } + case int64: + if v != 0 { + p[key] = strconv.FormatInt(v, 10) + return nil + } + case string: + if v != "" { + p[key] = v + return nil + } + case nil: + default: + b, err := json.Marshal(arg) + if err != nil { + return err + } + + p[key] = string(b) + return nil + } + } + + return nil +} From e6fdc8e02a7cb652a10914ae21dd73483c193ca1 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 13:34:34 +0300 Subject: [PATCH 38/70] Add user type documentation --- types.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/types.go b/types.go index 8c907f0..62fb0d4 100644 --- a/types.go +++ b/types.go @@ -49,14 +49,25 @@ func (ch UpdatesChannel) Clear() { } } -// User is a user on Telegram. +// User represents a Telegram user or bot. type User struct { - ID int `json:"id"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` // optional - UserName string `json:"username"` // optional - LanguageCode string `json:"language_code"` // optional - IsBot bool `json:"is_bot"` // optional + // ID is a unique identifier for this user or bot + ID int `json:"id"` + // FirstName user's or bot's first name + FirstName string `json:"first_name"` + // LastName user's or bot's last name + // optional + LastName string `json:"last_name"` + // UserName user's or bot's username + // optional + UserName string `json:"username"` + // LanguageCode IETF language tag of the user's language + // more info: https://en.wikipedia.org/wiki/IETF_language_tag + // optional + LanguageCode string `json:"language_code"` + // IsBot true, if this user is a bot + // optional + IsBot bool `json:"is_bot"` } // String displays a simple text version of a user. From b4d9865c2b275606dbf4d84113b327dcc4a3aa62 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 13:36:41 +0300 Subject: [PATCH 39/70] Add chat type documentation --- types.go | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/types.go b/types.go index 62fb0d4..b15d693 100644 --- a/types.go +++ b/types.go @@ -104,17 +104,38 @@ type ChatPhoto struct { // Chat contains information about the place a message was sent. type Chat struct { - ID int64 `json:"id"` - Type string `json:"type"` - Title string `json:"title"` // optional - UserName string `json:"username"` // optional - FirstName string `json:"first_name"` // optional - LastName string `json:"last_name"` // optional - AllMembersAreAdmins bool `json:"all_members_are_administrators"` // optional - Photo *ChatPhoto `json:"photo"` - Description string `json:"description,omitempty"` // optional - InviteLink string `json:"invite_link,omitempty"` // optional - PinnedMessage *Message `json:"pinned_message"` // optional + // ID is a unique identifier for this chat + ID int64 `json:"id"` + // Type of chat, can be either “private”, “group”, “supergroup” or “channel” + Type string `json:"type"` + // Title for supergroups, channels and group chats + // optional + Title string `json:"title"` + // UserName for private chats, supergroups and channels if available + // optional + UserName string `json:"username"` + // FirstName of the other party in a private chat + // optional + FirstName string `json:"first_name"` + // LastName of the other party in a private chat + // optional + LastName string `json:"last_name"` + // AllMembersAreAdmins + // optional + AllMembersAreAdmins bool `json:"all_members_are_administrators"` + // Photo is a chat photo + Photo *ChatPhoto `json:"photo"` + // Description for groups, supergroups and channel chats + // optional + Description string `json:"description,omitempty"` + // InviteLink is a chat invite link, for groups, supergroups and channel chats. + // Each administrator in a chat generates their own invite links, + // so the bot must first generate the link using exportChatInviteLink + // optional + InviteLink string `json:"invite_link,omitempty"` + // PinnedMessage Pinned message, for groups, supergroups and channels + // optional + PinnedMessage *Message `json:"pinned_message"` } // IsPrivate returns if the Chat is a private conversation. From 26a3c9542175cf8cf2ae304c8ad0548dfe65fae7 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 13:43:23 +0300 Subject: [PATCH 40/70] Add some inbound types documentation --- types.go | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/types.go b/types.go index b15d693..2ab1f4a 100644 --- a/types.go +++ b/types.go @@ -98,8 +98,14 @@ type GroupChat struct { // ChatPhoto represents a chat photo. type ChatPhoto struct { + // SmallFileID is a file identifier of small (160x160) chat photo. + // This file_id can be used only for photo download and + // only for as long as the photo is not changed. SmallFileID string `json:"small_file_id"` - BigFileID string `json:"big_file_id"` + // BigFileID is a file identifier of big (640x640) chat photo. + // This file_id can be used only for photo download and + // only for as long as the photo is not changed. + BigFileID string `json:"big_file_id"` } // Chat contains information about the place a message was sent. @@ -392,11 +398,34 @@ func (m *Message) CommandArguments() string { // MessageEntity contains information about data in a Message. type MessageEntity struct { - Type string `json:"type"` - Offset int `json:"offset"` - Length int `json:"length"` - URL string `json:"url"` // optional - User *User `json:"user"` // optional + // Type of the entity. + // Can be: + // “mention” (@username), + // “hashtag” (#hashtag), + // “cashtag” ($USD), + // “bot_command” (/start@jobs_bot), + // “url” (https://telegram.org), + // “email” (do-not-reply@telegram.org), + // “phone_number” (+1-212-555-0123), + // “bold” (bold text), + // “italic” (italic text), + // “underline” (underlined text), + // “strikethrough” (strikethrough text), + // “code” (monowidth string), + // “pre” (monowidth block), + // “text_link” (for clickable text URLs), + // “text_mention” (for users without usernames) + Type string `json:"type"` + // Offset in UTF-16 code units to the start of the entity + Offset int `json:"offset"` + // Length + Length int `json:"length"` + // URL for “text_link” only, url that will be opened after user taps on the text + // optional + URL string `json:"url"` + // User for “text_mention” only, the mentioned user + // optional + User *User `json:"user"` } // ParseURL attempts to parse a URL contained within a MessageEntity. From 30c412fbe58ee9e0353028213807b01090f9565c Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 13:50:11 +0300 Subject: [PATCH 41/70] Add update type documentation --- types.go | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/types.go b/types.go index 2ab1f4a..a14ff1e 100644 --- a/types.go +++ b/types.go @@ -27,16 +27,44 @@ type ResponseParameters struct { // Update is an update response, from GetUpdates. type Update struct { - UpdateID int `json:"update_id"` - Message *Message `json:"message"` - EditedMessage *Message `json:"edited_message"` - ChannelPost *Message `json:"channel_post"` - EditedChannelPost *Message `json:"edited_channel_post"` - InlineQuery *InlineQuery `json:"inline_query"` + // UpdateID is the update's unique identifier. + // Update identifiers start from a certain positive number and increase sequentially. + // This ID becomes especially handy if you're using Webhooks, + // since it allows you to ignore repeated updates or to restore + // the correct update sequence, should they get out of order. + // If there are no new updates for at least a week, then identifier + // of the next update will be chosen randomly instead of sequentially. + UpdateID int `json:"update_id"` + // Message new incoming message of any kind — text, photo, sticker, etc. + // optional + Message *Message `json:"message"` + // EditedMessage + // optional + EditedMessage *Message `json:"edited_message"` + // ChannelPost new version of a message that is known to the bot and was edited + // optional + ChannelPost *Message `json:"channel_post"` + // EditedChannelPost new incoming channel post of any kind — text, photo, sticker, etc. + // optional + EditedChannelPost *Message `json:"edited_channel_post"` + // InlineQuery new incoming inline query + // optional + InlineQuery *InlineQuery `json:"inline_query"` + // ChosenInlineResult is the result of an inline query + // that was chosen by a user and sent to their chat partner. + // Please see our documentation on the feedback collecting + // for details on how to enable these updates for your bot. + // optional ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"` - CallbackQuery *CallbackQuery `json:"callback_query"` - ShippingQuery *ShippingQuery `json:"shipping_query"` - PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query"` + // CallbackQuery new incoming callback query + // optional + CallbackQuery *CallbackQuery `json:"callback_query"` + // ShippingQuery new incoming shipping query. Only for invoices with flexible price + // optional + ShippingQuery *ShippingQuery `json:"shipping_query"` + // PreCheckoutQuery new incoming pre-checkout query. Contains full information about checkout + // optional + PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query"` } // UpdatesChannel is the channel for getting updates. From 1f1d97f1e310f75af00438576a21abaf2d3a2e13 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 15:44:24 +0300 Subject: [PATCH 42/70] Add sticker and sticker set type documentation --- types.go | 103 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 29 deletions(-) diff --git a/types.go b/types.go index 8c907f0..f5390b5 100644 --- a/types.go +++ b/types.go @@ -428,51 +428,96 @@ func (e MessageEntity) IsTextLink() bool { // PhotoSize contains information about photos. type PhotoSize struct { - FileID string `json:"file_id"` - Width int `json:"width"` - Height int `json:"height"` - FileSize int `json:"file_size"` // optional + // FileID identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Width photo width + Width int `json:"width"` + // Height photo height + Height int `json:"height"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // Audio contains information about audio. type Audio struct { - FileID string `json:"file_id"` - Duration int `json:"duration"` - Performer string `json:"performer"` // optional - Title string `json:"title"` // optional - MimeType string `json:"mime_type"` // optional - FileSize int `json:"file_size"` // optional + // FileID is an identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Duration of the audio in seconds as defined by sender + Duration int `json:"duration"` + // Performer of the audio as defined by sender or by audio tags + // optional + Performer string `json:"performer"` + // Title of the audio as defined by sender or by audio tags + // optional + Title string `json:"title"` + // MimeType of the file as defined by sender + // optional + MimeType string `json:"mime_type"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // Document contains information about a document. type Document struct { - FileID string `json:"file_id"` - Thumbnail *PhotoSize `json:"thumb"` // optional - FileName string `json:"file_name"` // optional - MimeType string `json:"mime_type"` // optional - FileSize int `json:"file_size"` // optional + // FileID is a identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Thumbnail document thumbnail as defined by sender + // optional + Thumbnail *PhotoSize `json:"thumb"` + // FileName original filename as defined by sender + // optional + FileName string `json:"file_name"` + // MimeType of the file as defined by sender + // optional + MimeType string `json:"mime_type"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // Sticker contains information about a sticker. type Sticker struct { - FileUniqueID string `json:"file_unique_id"` - FileID string `json:"file_id"` - Width int `json:"width"` - Height int `json:"height"` - Thumbnail *PhotoSize `json:"thumb"` // optional - Emoji string `json:"emoji"` // optional - FileSize int `json:"file_size"` // optional - SetName string `json:"set_name"` // optional - IsAnimated bool `json:"is_animated"` // optional + // FileUniqueID is an unique identifier for this file, + // which is supposed to be the same over time and for different bots. + // Can't be used to download or reuse the file. + FileUniqueID string `json:"file_unique_id"` + // FileID is an identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Width sticker width + Width int `json:"width"` + // Height sticker height + Height int `json:"height"` + // Thumbnail sticker thumbnail in the .WEBP or .JPG format + // optional + Thumbnail *PhotoSize `json:"thumb"` + // Emoji associated with the sticker + // optional + Emoji string `json:"emoji"` + // FileSize + // optional + FileSize int `json:"file_size"` + // SetName of the sticker set to which the sticker belongs + // optional + SetName string `json:"set_name"` + // IsAnimated true, if the sticker is animated + // optional + IsAnimated bool `json:"is_animated"` } // StickerSet contains information about an sticker set. type StickerSet struct { - Name string `json:"name"` - Title string `json:"title"` - IsAnimated bool `json:"is_animated"` - ContainsMasks bool `json:"contains_masks"` - Stickers []Sticker `json:"stickers"` + // Name sticker set name + Name string `json:"name"` + // Title sticker set title + Title string `json:"title"` + // IsAnimated true, if the sticker set contains animated stickers + IsAnimated bool `json:"is_animated"` + // ContainsMasks true, if the sticker set contains masks + ContainsMasks bool `json:"contains_masks"` + // Stickers list of all set stickers + Stickers []Sticker `json:"stickers"` } // ChatAnimation contains information about an animation. From a005cff757a80dcb6ce777ca32b6308a02124c90 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:21:42 +0300 Subject: [PATCH 43/70] Add chat animation type documentation --- types.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/types.go b/types.go index f5390b5..888f97a 100644 --- a/types.go +++ b/types.go @@ -522,14 +522,26 @@ type StickerSet struct { // ChatAnimation contains information about an animation. type ChatAnimation struct { - FileID string `json:"file_id"` - Width int `json:"width"` - Height int `json:"height"` - Duration int `json:"duration"` - Thumbnail *PhotoSize `json:"thumb"` // optional - FileName string `json:"file_name"` // optional - MimeType string `json:"mime_type"` // optional - FileSize int `json:"file_size"` // optional + // FileID odentifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Width video width as defined by sender + Width int `json:"width"` + // Height video height as defined by sender + Height int `json:"height"` + // Duration of the video in seconds as defined by sender + Duration int `json:"duration"` + // Thumbnail animation thumbnail as defined by sender + // optional + Thumbnail *PhotoSize `json:"thumb"` + // FileName original animation filename as defined by sender + // optional + FileName string `json:"file_name"` + // MimeType of the file as defined by sender + // optional + MimeType string `json:"mime_type"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // Video contains information about a video. From 8e875a571162163512ed376fe0e0a8dc4c0a3354 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:25:05 +0300 Subject: [PATCH 44/70] Add video and video note type documentation --- types.go | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/types.go b/types.go index 888f97a..1f3a02b 100644 --- a/types.go +++ b/types.go @@ -546,22 +546,39 @@ type ChatAnimation struct { // Video contains information about a video. type Video struct { - FileID string `json:"file_id"` - Width int `json:"width"` - Height int `json:"height"` - Duration int `json:"duration"` - Thumbnail *PhotoSize `json:"thumb"` // optional - MimeType string `json:"mime_type"` // optional - FileSize int `json:"file_size"` // optional + // FileID identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Width video width as defined by sender + Width int `json:"width"` + // Height video height as defined by sender + Height int `json:"height"` + // Duration of the video in seconds as defined by sender + Duration int `json:"duration"` + // Thumbnail video thumbnail + // optional + Thumbnail *PhotoSize `json:"thumb"` + // MimeType of a file as defined by sender + // optional + MimeType string `json:"mime_type"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // VideoNote contains information about a video. type VideoNote struct { - FileID string `json:"file_id"` - Length int `json:"length"` - Duration int `json:"duration"` - Thumbnail *PhotoSize `json:"thumb"` // optional - FileSize int `json:"file_size"` // optional + // FileID identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Length video width and height (diameter of the video message) as defined by sender + Length int `json:"length"` + // Duration of the video in seconds as defined by sender + Duration int `json:"duration"` + // Thumbnail video thumbnail + // optional + Thumbnail *PhotoSize `json:"thumb"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // Voice contains information about a voice. From 1b845170c17a2379a5dc5d30e216e220789b1061 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:28:10 +0300 Subject: [PATCH 45/70] Add voice and contact type documentation --- types.go | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/types.go b/types.go index 1f3a02b..50c1425 100644 --- a/types.go +++ b/types.go @@ -583,20 +583,32 @@ type VideoNote struct { // Voice contains information about a voice. type Voice struct { - FileID string `json:"file_id"` - Duration int `json:"duration"` - MimeType string `json:"mime_type"` // optional - FileSize int `json:"file_size"` // optional + // FileID identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // Duration of the audio in seconds as defined by sender + Duration int `json:"duration"` + // MimeType of the file as defined by sender + // optional + MimeType string `json:"mime_type"` + // FileSize file size + // optional + FileSize int `json:"file_size"` } // Contact contains information about a contact. // // Note that LastName and UserID may be empty. type Contact struct { + // PhoneNumber contact's phone number PhoneNumber string `json:"phone_number"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` // optional - UserID int `json:"user_id"` // optional + // FirstName contact's first name + FirstName string `json:"first_name"` + // LastName contact's last name + // optional + LastName string `json:"last_name"` + // UserID contact's user identifier in Telegram + // optional + UserID int `json:"user_id"` } // Location contains information about a place. From 2497684181e131be5616e36bf9cdc6d3da7db290 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:30:45 +0300 Subject: [PATCH 46/70] Add location, venue and user profile photos type documentation --- types.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/types.go b/types.go index 50c1425..0698d40 100644 --- a/types.go +++ b/types.go @@ -613,22 +613,31 @@ type Contact struct { // Location contains information about a place. type Location struct { + // Longitude as defined by sender Longitude float64 `json:"longitude"` - Latitude float64 `json:"latitude"` + // Latitude as defined by sender + Latitude float64 `json:"latitude"` } // Venue contains information about a venue, including its Location. type Venue struct { - Location Location `json:"location"` - Title string `json:"title"` - Address string `json:"address"` - FoursquareID string `json:"foursquare_id"` // optional + // Location venue location + Location Location `json:"location"` + // Title name of the venue + Title string `json:"title"` + // Address of the venue + Address string `json:"address"` + // FoursquareID foursquare identifier of the venue + // optional + FoursquareID string `json:"foursquare_id"` } // UserProfilePhotos contains a set of user profile photos. type UserProfilePhotos struct { - TotalCount int `json:"total_count"` - Photos [][]PhotoSize `json:"photos"` + // TotalCount total number of profile pictures the target user has + TotalCount int `json:"total_count"` + // Photos requested profile pictures (in up to 4 sizes each) + Photos [][]PhotoSize `json:"photos"` } // File contains information about a file to download from Telegram. From bf143a9e9ba8a9e9e6265acc862c1f54fe1d87b7 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:47:12 +0300 Subject: [PATCH 47/70] Add keyboard types documentation --- types.go | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 177 insertions(+), 18 deletions(-) diff --git a/types.go b/types.go index 0698d40..73c93ed 100644 --- a/types.go +++ b/types.go @@ -137,6 +137,7 @@ type Message struct { // MessageID is a unique message identifier inside this chat MessageID int `json:"message_id"` // From is a sender, empty for messages sent to channels; + // // optional From *User `json:"from"` // Date of the message was sent in Unix time @@ -144,105 +145,136 @@ type Message struct { // Chat is the conversation the message belongs to Chat *Chat `json:"chat"` // ForwardFrom for forwarded messages, sender of the original message; + // // optional ForwardFrom *User `json:"forward_from"` // ForwardFromChat for messages forwarded from channels, // information about the original channel; + // // optional ForwardFromChat *Chat `json:"forward_from_chat"` // ForwardFromMessageID for messages forwarded from channels, // identifier of the original message in the channel; + // // optional ForwardFromMessageID int `json:"forward_from_message_id"` // ForwardDate for forwarded messages, date the original message was sent in Unix time; + // // optional ForwardDate int `json:"forward_date"` // ReplyToMessage for replies, the original message. // Note that the Message object in this field will not contain further ReplyToMessage fields // even if it itself is a reply; + // // optional ReplyToMessage *Message `json:"reply_to_message"` // ViaBot through which the message was sent; + // // optional ViaBot *User `json:"via_bot"` // EditDate of the message was last edited in Unix time; + // // optional EditDate int `json:"edit_date"` // MediaGroupID is the unique identifier of a media message group this message belongs to; + // // optional MediaGroupID string `json:"media_group_id"` // AuthorSignature is the signature of the post author for messages in channels; + // // optional AuthorSignature string `json:"author_signature"` // Text is for text messages, the actual UTF-8 text of the message, 0-4096 characters; + // // optional Text string `json:"text"` // Entities is for text messages, special entities like usernames, // URLs, bot commands, etc. that appear in the text; + // // optional Entities *[]MessageEntity `json:"entities"` // CaptionEntities; + // // optional CaptionEntities *[]MessageEntity `json:"caption_entities"` // Audio message is an audio file, information about the file; + // // optional Audio *Audio `json:"audio"` // Document message is a general file, information about the file; + // // optional Document *Document `json:"document"` // Animation message is an animation, information about the animation. // For backward compatibility, when this field is set, the document field will also be set; + // // optional Animation *ChatAnimation `json:"animation"` // Game message is a game, information about the game; + // // optional Game *Game `json:"game"` // Photo message is a photo, available sizes of the photo; + // // optional Photo *[]PhotoSize `json:"photo"` // Sticker message is a sticker, information about the sticker; + // // optional Sticker *Sticker `json:"sticker"` // Video message is a video, information about the video; + // // optional Video *Video `json:"video"` // VideoNote message is a video note, information about the video message; + // // optional VideoNote *VideoNote `json:"video_note"` // Voice message is a voice message, information about the file; + // // optional Voice *Voice `json:"voice"` // Caption for the animation, audio, document, photo, video or voice, 0-1024 characters; + // // optional Caption string `json:"caption"` // Contact message is a shared contact, information about the contact; + // // optional Contact *Contact `json:"contact"` // Location message is a shared location, information about the location; + // // optional Location *Location `json:"location"` // Venue message is a venue, information about the venue. // For backward compatibility, when this field is set, the location field will also be set; + // // optional Venue *Venue `json:"venue"` // NewChatMembers that were added to the group or supergroup // and information about them (the bot itself may be one of these members); + // // optional NewChatMembers *[]User `json:"new_chat_members"` // LeftChatMember is a member was removed from the group, // information about them (this member may be the bot itself); + // // optional LeftChatMember *User `json:"left_chat_member"` // NewChatTitle is a chat title was changed to this value; + // // optional NewChatTitle string `json:"new_chat_title"` // NewChatPhoto is a chat photo was change to this value; + // // optional NewChatPhoto *[]PhotoSize `json:"new_chat_photo"` // DeleteChatPhoto is a service message: the chat photo was deleted; + // // optional DeleteChatPhoto bool `json:"delete_chat_photo"` // GroupChatCreated is a service message: the group has been created; + // // optional GroupChatCreated bool `json:"group_chat_created"` // SuperGroupChatCreated is a service message: the supergroup has been created. @@ -250,6 +282,7 @@ type Message struct { // because bot can't be a member of a supergroup when it is created. // It can only be found in ReplyToMessage if someone replies to a very first message // in a directly created supergroup; + // // optional SuperGroupChatCreated bool `json:"supergroup_chat_created"` // ChannelChatCreated is a service message: the channel has been created. @@ -257,6 +290,7 @@ type Message struct { // because bot can't be a member of a channel when it is created. // It can only be found in ReplyToMessage // if someone replies to a very first message in a channel; + // // optional ChannelChatCreated bool `json:"channel_chat_created"` // MigrateToChatID is the group has been migrated to a supergroup with the specified identifier. @@ -264,6 +298,7 @@ type Message struct { // may have difficulty/silent defects in interpreting it. // But it is smaller than 52 bits, so a signed 64 bit integer // or double-precision float type are safe for storing this identifier; + // // optional MigrateToChatID int64 `json:"migrate_to_chat_id"` // MigrateFromChatID is the supergroup has been migrated from a group with the specified identifier. @@ -271,21 +306,26 @@ type Message struct { // may have difficulty/silent defects in interpreting it. // But it is smaller than 52 bits, so a signed 64 bit integer // or double-precision float type are safe for storing this identifier; + // // optional MigrateFromChatID int64 `json:"migrate_from_chat_id"` // PinnedMessage is a specified message was pinned. // Note that the Message object in this field will not contain further ReplyToMessage // fields even if it is itself a reply; + // // optional PinnedMessage *Message `json:"pinned_message"` // Invoice message is an invoice for a payment; + // // optional Invoice *Invoice `json:"invoice"` // SuccessfulPayment message is a service message about a successful payment, // information about the payment; + // // optional SuccessfulPayment *SuccessfulPayment `json:"successful_payment"` // PassportData is a Telegram Passport data; + // // optional PassportData *PassportData `json:"passport_data,omitempty"` } @@ -435,6 +475,7 @@ type PhotoSize struct { // Height photo height Height int `json:"height"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -446,15 +487,19 @@ type Audio struct { // Duration of the audio in seconds as defined by sender Duration int `json:"duration"` // Performer of the audio as defined by sender or by audio tags + // // optional Performer string `json:"performer"` // Title of the audio as defined by sender or by audio tags + // // optional Title string `json:"title"` // MimeType of the file as defined by sender + // // optional MimeType string `json:"mime_type"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -464,15 +509,19 @@ type Document struct { // FileID is a identifier for this file, which can be used to download or reuse the file FileID string `json:"file_id"` // Thumbnail document thumbnail as defined by sender + // // optional Thumbnail *PhotoSize `json:"thumb"` // FileName original filename as defined by sender + // // optional FileName string `json:"file_name"` // MimeType of the file as defined by sender + // // optional MimeType string `json:"mime_type"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -490,18 +539,23 @@ type Sticker struct { // Height sticker height Height int `json:"height"` // Thumbnail sticker thumbnail in the .WEBP or .JPG format + // // optional Thumbnail *PhotoSize `json:"thumb"` // Emoji associated with the sticker + // // optional Emoji string `json:"emoji"` // FileSize + // // optional FileSize int `json:"file_size"` // SetName of the sticker set to which the sticker belongs + // // optional SetName string `json:"set_name"` // IsAnimated true, if the sticker is animated + // // optional IsAnimated bool `json:"is_animated"` } @@ -531,15 +585,19 @@ type ChatAnimation struct { // Duration of the video in seconds as defined by sender Duration int `json:"duration"` // Thumbnail animation thumbnail as defined by sender + // // optional Thumbnail *PhotoSize `json:"thumb"` // FileName original animation filename as defined by sender + // // optional FileName string `json:"file_name"` // MimeType of the file as defined by sender + // // optional MimeType string `json:"mime_type"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -555,12 +613,15 @@ type Video struct { // Duration of the video in seconds as defined by sender Duration int `json:"duration"` // Thumbnail video thumbnail + // // optional Thumbnail *PhotoSize `json:"thumb"` // MimeType of a file as defined by sender + // // optional MimeType string `json:"mime_type"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -574,9 +635,11 @@ type VideoNote struct { // Duration of the video in seconds as defined by sender Duration int `json:"duration"` // Thumbnail video thumbnail + // // optional Thumbnail *PhotoSize `json:"thumb"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -588,9 +651,11 @@ type Voice struct { // Duration of the audio in seconds as defined by sender Duration int `json:"duration"` // MimeType of the file as defined by sender + // // optional MimeType string `json:"mime_type"` // FileSize file size + // // optional FileSize int `json:"file_size"` } @@ -604,9 +669,11 @@ type Contact struct { // FirstName contact's first name FirstName string `json:"first_name"` // LastName contact's last name + // // optional LastName string `json:"last_name"` // UserID contact's user identifier in Telegram + // // optional UserID int `json:"user_id"` } @@ -628,6 +695,7 @@ type Venue struct { // Address of the venue Address string `json:"address"` // FoursquareID foursquare identifier of the venue + // // optional FoursquareID string `json:"foursquare_id"` } @@ -642,9 +710,16 @@ type UserProfilePhotos struct { // File contains information about a file to download from Telegram. type File struct { - FileID string `json:"file_id"` - FileSize int `json:"file_size"` // optional - FilePath string `json:"file_path"` // optional + // FileID identifier for this file, which can be used to download or reuse the file + FileID string `json:"file_id"` + // FileSize file size, if known + // + // optional + FileSize int `json:"file_size"` + // FilePath file path + // + // optional + FilePath string `json:"file_path"` } // Link returns a full path to the download URL for a File. @@ -656,17 +731,52 @@ func (f *File) Link(token string) string { // ReplyKeyboardMarkup allows the Bot to set a custom keyboard. type ReplyKeyboardMarkup struct { - Keyboard [][]KeyboardButton `json:"keyboard"` - ResizeKeyboard bool `json:"resize_keyboard"` // optional - OneTimeKeyboard bool `json:"one_time_keyboard"` // optional - Selective bool `json:"selective"` // optional + // Keyboard is an array of button rows, each represented by an Array of KeyboardButton objects + Keyboard [][]KeyboardButton `json:"keyboard"` + // ResizeKeyboard requests clients to resize the keyboard vertically for optimal fit + // (e.g., make the keyboard smaller if there are just two rows of buttons). + // Defaults to false, in which case the custom keyboard + // is always of the same height as the app's standard keyboard. + // + // optional + ResizeKeyboard bool `json:"resize_keyboard"` + // OneTimeKeyboard requests clients to hide the keyboard as soon as it's been used. + // The keyboard will still be available, but clients will automatically display + // the usual letter-keyboard in the chat – the user can press a special button + // in the input field to see the custom keyboard again. + // Defaults to false. + // + // optional + OneTimeKeyboard bool `json:"one_time_keyboard"` + // Selective use this parameter if you want to show the keyboard to specific users only. + // Targets: + // 1) users that are @mentioned in the text of the Message object; + // 2) if the bot's message is a reply (has Message.ReplyToMessage not nil), sender of the original message. + // + // Example: A user requests to change the bot's language, + // bot replies to the request with a keyboard to select the new language. + // Other users in the group don't see the keyboard. + // + // optional + Selective bool `json:"selective"` } // KeyboardButton is a button within a custom keyboard. type KeyboardButton struct { - Text string `json:"text"` - RequestContact bool `json:"request_contact"` - RequestLocation bool `json:"request_location"` + // Text of the button. If none of the optional fields are used, + // it will be sent as a message when the button is pressed. + Text string `json:"text"` + // RequestContact if True, the user's phone number will be sent + // as a contact when the button is pressed. + // Available in private chats only. + // + // optional + RequestContact bool `json:"request_contact"` + // RequestLocation if True, the user's current location will be sent when the button is pressed. + // Available in private chats only. + // + // optional + RequestLocation bool `json:"request_location"` } // ReplyKeyboardHide allows the Bot to hide a custom keyboard. @@ -677,12 +787,27 @@ type ReplyKeyboardHide struct { // ReplyKeyboardRemove allows the Bot to hide a custom keyboard. type ReplyKeyboardRemove struct { + // RemoveKeyboard requests clients to remove the custom keyboard + // (user will not be able to summon this keyboard; + // if you want to hide the keyboard from sight but keep it accessible, + // use one_time_keyboard in ReplyKeyboardMarkup). RemoveKeyboard bool `json:"remove_keyboard"` - Selective bool `json:"selective"` + // Selective use this parameter if you want to remove the keyboard for specific users only. + // Targets: + // 1) users that are @mentioned in the text of the Message object; + // 2) if the bot's message is a reply (has Message.ReplyToMessage not nil), sender of the original message. + // + // Example: A user votes in a poll, bot returns confirmation message + // in reply to the vote and removes the keyboard for that user, + // while still showing the keyboard with poll options to users who haven't voted yet. + // + // optional + Selective bool `json:"selective"` } // InlineKeyboardMarkup is a custom keyboard presented for an inline bot. type InlineKeyboardMarkup struct { + // InlineKeyboard array of button rows, each represented by an Array of InlineKeyboardButton objects InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"` } @@ -694,13 +819,47 @@ type InlineKeyboardMarkup struct { // // CallbackGame, if set, MUST be first button in first row. type InlineKeyboardButton struct { - Text string `json:"text"` - URL *string `json:"url,omitempty"` // optional - CallbackData *string `json:"callback_data,omitempty"` // optional - SwitchInlineQuery *string `json:"switch_inline_query,omitempty"` // optional - SwitchInlineQueryCurrentChat *string `json:"switch_inline_query_current_chat,omitempty"` // optional - CallbackGame *CallbackGame `json:"callback_game,omitempty"` // optional - Pay bool `json:"pay,omitempty"` // optional + // Text label text on the button + Text string `json:"text"` + // URL HTTP or tg:// url to be opened when button is pressed. + // + // optional + URL *string `json:"url,omitempty"` + // CallbackData data to be sent in a callback query to the bot when button is pressed, 1-64 bytes. + // + // optional + CallbackData *string `json:"callback_data,omitempty"` + // SwitchInlineQuery if set, pressing the button will prompt the user to select one of their chats, + // open that chat and insert the bot's username and the specified inline query in the input field. + // Can be empty, in which case just the bot's username will be inserted. + // + // This offers an easy way for users to start using your bot + // in inline mode when they are currently in a private chat with it. + // Especially useful when combined with switch_pm… actions – in this case + // the user will be automatically returned to the chat they switched from, + // skipping the chat selection screen. + // + // optional + SwitchInlineQuery *string `json:"switch_inline_query,omitempty"` + // SwitchInlineQueryCurrentChat if set, pressing the button will insert the bot's username + // and the specified inline query in the current chat's input field. + // Can be empty, in which case only the bot's username will be inserted. + // + // This offers a quick way for the user to open your bot in inline mode + // in the same chat – good for selecting something from multiple options. + // + // optional + SwitchInlineQueryCurrentChat *string `json:"switch_inline_query_current_chat,omitempty"` + // CallbackGame description of the game that will be launched when the user presses the button. + // + // optional + CallbackGame *CallbackGame `json:"callback_game,omitempty"` + // Pay specify True, to send a Pay button. + // + // NOTE: This type of button must always be the first button in the first row. + // + // optional + Pay bool `json:"pay,omitempty"` } // CallbackQuery is data sent when a keyboard button with callback data From f54e99475aeeb0729f8e3212116e2f9bb3bc0bd5 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:52:22 +0300 Subject: [PATCH 48/70] Add callback and reply types documentation --- types.go | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/types.go b/types.go index 73c93ed..e697217 100644 --- a/types.go +++ b/types.go @@ -865,20 +865,48 @@ type InlineKeyboardButton struct { // CallbackQuery is data sent when a keyboard button with callback data // is clicked. type CallbackQuery struct { - ID string `json:"id"` - From *User `json:"from"` - Message *Message `json:"message"` // optional - InlineMessageID string `json:"inline_message_id"` // optional - ChatInstance string `json:"chat_instance"` - Data string `json:"data"` // optional - GameShortName string `json:"game_short_name"` // optional + // ID unique identifier for this query + ID string `json:"id"` + // From sender + From *User `json:"from"` + // Message with the callback button that originated the query. + // Note that message content and message date will not be available if the message is too old. + // + // optional + Message *Message `json:"message"` + // InlineMessageID identifier of the message sent via the bot in inline mode, that originated the query. + // + // optional + // + InlineMessageID string `json:"inline_message_id"` + // ChatInstance global identifier, uniquely corresponding to the chat to which + // the message with the callback button was sent. Useful for high scores in games. + // + ChatInstance string `json:"chat_instance"` + // Data associated with the callback button. Be aware that + // a bad client can send arbitrary data in this field. + // + // optional + Data string `json:"data"` + // GameShortName short name of a Game to be returned, serves as the unique identifier for the game. + // + // optional + GameShortName string `json:"game_short_name"` } // ForceReply allows the Bot to have users directly reply to it without // additional interaction. type ForceReply struct { + // ForceReply shows reply interface to the user, + // as if they manually selected the bot's message and tapped 'Reply'. ForceReply bool `json:"force_reply"` - Selective bool `json:"selective"` // optional + // Selective use this parameter if you want to force reply from specific users only. + // Targets: + // 1) users that are @mentioned in the text of the Message object; + // 2) if the bot's message is a reply (has Message.ReplyToMessage not nil), sender of the original message. + // + // optional + Selective bool `json:"selective"` } // ChatMember is information about a member in a chat. From d2ea97fb9b113760160c321b738352efa85e0f6e Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 16:58:02 +0300 Subject: [PATCH 49/70] Add chat member type documentation --- types.go | 106 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 17 deletions(-) diff --git a/types.go b/types.go index e697217..b252c47 100644 --- a/types.go +++ b/types.go @@ -911,23 +911,95 @@ type ForceReply struct { // ChatMember is information about a member in a chat. type ChatMember struct { - User *User `json:"user"` - Status string `json:"status"` - CustomTitle string `json:"custom_title,omitempty"` // optional - UntilDate int64 `json:"until_date,omitempty"` // optional - CanBeEdited bool `json:"can_be_edited,omitempty"` // optional - CanChangeInfo bool `json:"can_change_info,omitempty"` // optional - CanPostMessages bool `json:"can_post_messages,omitempty"` // optional - CanEditMessages bool `json:"can_edit_messages,omitempty"` // optional - CanDeleteMessages bool `json:"can_delete_messages,omitempty"` // optional - CanInviteUsers bool `json:"can_invite_users,omitempty"` // optional - CanRestrictMembers bool `json:"can_restrict_members,omitempty"` // optional - CanPinMessages bool `json:"can_pin_messages,omitempty"` // optional - CanPromoteMembers bool `json:"can_promote_members,omitempty"` // optional - CanSendMessages bool `json:"can_send_messages,omitempty"` // optional - CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"` // optional - CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"` // optional - CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"` // optional + // User information about the user + User *User `json:"user"` + // Status the member's status in the chat. + // Can be + // “creator”, + // “administrator”, + // “member”, + // “restricted”, + // “left” or + // “kicked” + Status string `json:"status"` + // CustomTitle owner and administrators only. Custom title for this user + // + // optional + CustomTitle string `json:"custom_title,omitempty"` + // UntilDate restricted and kicked only. + // Date when restrictions will be lifted for this user; + // unix time. + // + // optional + UntilDate int64 `json:"until_date,omitempty"` + // CanBeEdited administrators only. + // True, if the bot is allowed to edit administrator privileges of that user. + // + // optional + CanBeEdited bool `json:"can_be_edited,omitempty"` + // CanChangeInfo administrators and restricted only. + // True, if the user is allowed to change the chat title, photo and other settings. + // + // optional + CanChangeInfo bool `json:"can_change_info,omitempty"` + // CanChangeInfo administrators only. + // True, if the administrator can post in the channel; + // channels only. + // + // optional + CanPostMessages bool `json:"can_post_messages,omitempty"` + // CanEditMessages administrators only. + // True, if the administrator can edit messages of other users and can pin messages; + // channels only. + // + // optional + CanEditMessages bool `json:"can_edit_messages,omitempty"` + // CanDeleteMessages administrators only. + // True, if the administrator can delete messages of other users. + // + // optional + CanDeleteMessages bool `json:"can_delete_messages,omitempty"` + // CanInviteUsers administrators and restricted only. + // True, if the user is allowed to invite new users to the chat. + // + // optional + CanInviteUsers bool `json:"can_invite_users,omitempty"` + // CanRestrictMembers administrators only. + // True, if the administrator can restrict, ban or unban chat members. + // + // optional + CanRestrictMembers bool `json:"can_restrict_members,omitempty"` + // CanPinMessages + // + // optional + CanPinMessages bool `json:"can_pin_messages,omitempty"` + // CanPromoteMembers administrators only. + // True, if the administrator can add new administrators + // with a subset of their own privileges or demote administrators that he has promoted, + // directly or indirectly (promoted by administrators that were appointed by the user). + // + // optional + CanPromoteMembers bool `json:"can_promote_members,omitempty"` + // CanSendMessages + // + // optional + CanSendMessages bool `json:"can_send_messages,omitempty"` + // CanSendMediaMessages restricted only. + // True, if the user is allowed to send text messages, contacts, locations and venues + // + // optional + CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"` + // CanSendOtherMessages restricted only. + // True, if the user is allowed to send audios, documents, + // photos, videos, video notes and voice notes. + // + // optional + CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"` + // CanAddWebPagePreviews restricted only. + // True, if the user is allowed to add web page previews to their messages. + // + // optional + CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"` } // IsCreator returns if the ChatMember was the creator of the chat. From 5875a46cdedea21de70ec6f5b4d4825bb1fe6f6e Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 17:00:46 +0300 Subject: [PATCH 50/70] Add game type documentation --- types.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/types.go b/types.go index b252c47..7876c1f 100644 --- a/types.go +++ b/types.go @@ -1019,12 +1019,27 @@ func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" } // Game is a game within Telegram. type Game struct { - Title string `json:"title"` - Description string `json:"description"` - Photo []PhotoSize `json:"photo"` - Text string `json:"text"` + // Title of the game + Title string `json:"title"` + // Description of the game + Description string `json:"description"` + // Photo that will be displayed in the game message in chats. + Photo []PhotoSize `json:"photo"` + // Text a brief description of the game or high scores included in the game message. + // Can be automatically edited to include current high scores for the game + // when the bot calls setGameScore, or manually edited using editMessageText. 0-4096 characters. + // + // optional + Text string `json:"text"` + // TextEntities special entities that appear in text, such as usernames, URLs, bot commands, etc. + // + // optional TextEntities []MessageEntity `json:"text_entities"` - Animation Animation `json:"animation"` + // Animation animation that will be displayed in the game message in chats. + // Upload via BotFather (https://t.me/botfather). + // + // optional + Animation Animation `json:"animation"` } // Animation is a GIF animation demonstrating the game. From d885b2a98311bb04422cf57042feab295554302f Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 17:05:16 +0300 Subject: [PATCH 51/70] Add animation, game score and webhook types documentation --- types.go | 59 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/types.go b/types.go index 7876c1f..d80187c 100644 --- a/types.go +++ b/types.go @@ -1044,18 +1044,34 @@ type Game struct { // Animation is a GIF animation demonstrating the game. type Animation struct { - FileID string `json:"file_id"` - Thumb PhotoSize `json:"thumb"` - FileName string `json:"file_name"` - MimeType string `json:"mime_type"` - FileSize int `json:"file_size"` + // FileID identifier for this file, which can be used to download or reuse the file. + FileID string `json:"file_id"` + // Thumb animation thumbnail as defined by sender. + // + // optional + Thumb PhotoSize `json:"thumb"` + // FileName original animation filename as defined by sender. + // + // optional + FileName string `json:"file_name"` + // MimeType of the file as defined by sender. + // + // optional + MimeType string `json:"mime_type"` + // FileSize ile size + // + // optional + FileSize int `json:"file_size"` } // GameHighScore is a user's score and position on the leaderboard. type GameHighScore struct { - Position int `json:"position"` - User User `json:"user"` - Score int `json:"score"` + // Position in high score table for the game + Position int `json:"position"` + // User user + User User `json:"user"` + // Score score + Score int `json:"score"` } // CallbackGame is for starting a game in an inline keyboard button. @@ -1063,12 +1079,27 @@ type CallbackGame struct{} // WebhookInfo is information about a currently set webhook. type WebhookInfo struct { - URL string `json:"url"` - HasCustomCertificate bool `json:"has_custom_certificate"` - PendingUpdateCount int `json:"pending_update_count"` - LastErrorDate int `json:"last_error_date"` // optional - LastErrorMessage string `json:"last_error_message"` // optional - MaxConnections int `json:"max_connections"` // optional + // URL webhook URL, may be empty if webhook is not set up. + URL string `json:"url"` + // HasCustomCertificate true, if a custom certificate was provided for webhook certificate checks. + HasCustomCertificate bool `json:"has_custom_certificate"` + // PendingUpdateCount number of updates awaiting delivery. + PendingUpdateCount int `json:"pending_update_count"` + // LastErrorDate unix time for the most recent error + // that happened when trying to deliver an update via webhook. + // + // optional + LastErrorDate int `json:"last_error_date"` + // LastErrorMessage error message in human-readable format for the most recent error + // that happened when trying to deliver an update via webhook. + // + // optional + LastErrorMessage string `json:"last_error_message"` + // MaxConnections maximum allowed number of simultaneous + // HTTPS connections to the webhook for update delivery. + // + // optional + MaxConnections int `json:"max_connections"` } // IsSet returns true if a webhook is currently set. From 97c4ff439677d3d057bfa114067b93f85810b76d Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 17:12:11 +0300 Subject: [PATCH 52/70] Add input media types documentation --- types.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/types.go b/types.go index d80187c..e6ea20f 100644 --- a/types.go +++ b/types.go @@ -1109,23 +1109,64 @@ func (info WebhookInfo) IsSet() bool { // InputMediaPhoto contains a photo for displaying as part of a media group. type InputMediaPhoto struct { - Type string `json:"type"` - Media string `json:"media"` - Caption string `json:"caption"` + // Type of the result, must be photo. + Type string `json:"type"` + // Media file to send. Pass a file_id to send a file that + // exists on the Telegram servers (recommended), + // pass an HTTP URL for Telegram to get a file from the Internet, + // or pass “attach://” to upload a new one + // using multipart/form-data under name. + Media string `json:"media"` + // Caption of the photo to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the photo caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional ParseMode string `json:"parse_mode"` } // InputMediaVideo contains a video for displaying as part of a media group. type InputMediaVideo struct { - Type string `json:"type"` + // Type of the result, must be video. + Type string `json:"type"` + // Media file to send. Pass a file_id to send a file + // that exists on the Telegram servers (recommended), + // pass an HTTP URL for Telegram to get a file from the Internet, + // or pass “attach://” to upload a new one + // using multipart/form-data under name. Media string `json:"media"` // thumb intentionally missing as it is not currently compatible - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - Width int `json:"width"` - Height int `json:"height"` - Duration int `json:"duration"` - SupportsStreaming bool `json:"supports_streaming"` + + // Caption of the video to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the video caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // Width video width + // + // optional + Width int `json:"width"` + // Height video height + // + // optional + Height int `json:"height"` + // Duration video duration + // + // optional + Duration int `json:"duration"` + // SupportsStreaming pass True, if the uploaded video is suitable for streaming. + // + // optional + SupportsStreaming bool `json:"supports_streaming"` } // InlineQuery is a Query from Telegram for an inline request. From e539815a4954166c029361f28e3fd0be87a00110 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 17:18:15 +0300 Subject: [PATCH 53/70] Move optional flag to a new line --- types.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/types.go b/types.go index a14ff1e..62322c5 100644 --- a/types.go +++ b/types.go @@ -36,33 +36,42 @@ type Update struct { // of the next update will be chosen randomly instead of sequentially. UpdateID int `json:"update_id"` // Message new incoming message of any kind — text, photo, sticker, etc. + // // optional Message *Message `json:"message"` // EditedMessage + // // optional EditedMessage *Message `json:"edited_message"` // ChannelPost new version of a message that is known to the bot and was edited + // // optional ChannelPost *Message `json:"channel_post"` // EditedChannelPost new incoming channel post of any kind — text, photo, sticker, etc. + // // optional EditedChannelPost *Message `json:"edited_channel_post"` // InlineQuery new incoming inline query + // // optional InlineQuery *InlineQuery `json:"inline_query"` // ChosenInlineResult is the result of an inline query // that was chosen by a user and sent to their chat partner. // Please see our documentation on the feedback collecting // for details on how to enable these updates for your bot. + // // optional ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"` // CallbackQuery new incoming callback query + // // optional CallbackQuery *CallbackQuery `json:"callback_query"` // ShippingQuery new incoming shipping query. Only for invoices with flexible price + // // optional ShippingQuery *ShippingQuery `json:"shipping_query"` // PreCheckoutQuery new incoming pre-checkout query. Contains full information about checkout + // // optional PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query"` } @@ -84,16 +93,20 @@ type User struct { // FirstName user's or bot's first name FirstName string `json:"first_name"` // LastName user's or bot's last name + // // optional LastName string `json:"last_name"` // UserName user's or bot's username + // // optional UserName string `json:"username"` // LanguageCode IETF language tag of the user's language // more info: https://en.wikipedia.org/wiki/IETF_language_tag + // // optional LanguageCode string `json:"language_code"` // IsBot true, if this user is a bot + // // optional IsBot bool `json:"is_bot"` } @@ -143,31 +156,39 @@ type Chat struct { // Type of chat, can be either “private”, “group”, “supergroup” or “channel” Type string `json:"type"` // Title for supergroups, channels and group chats + // // optional Title string `json:"title"` // UserName for private chats, supergroups and channels if available + // // optional UserName string `json:"username"` // FirstName of the other party in a private chat + // // optional FirstName string `json:"first_name"` // LastName of the other party in a private chat + // // optional LastName string `json:"last_name"` // AllMembersAreAdmins + // // optional AllMembersAreAdmins bool `json:"all_members_are_administrators"` // Photo is a chat photo Photo *ChatPhoto `json:"photo"` // Description for groups, supergroups and channel chats + // // optional Description string `json:"description,omitempty"` // InviteLink is a chat invite link, for groups, supergroups and channel chats. // Each administrator in a chat generates their own invite links, // so the bot must first generate the link using exportChatInviteLink + // // optional InviteLink string `json:"invite_link,omitempty"` // PinnedMessage Pinned message, for groups, supergroups and channels + // // optional PinnedMessage *Message `json:"pinned_message"` } @@ -449,9 +470,11 @@ type MessageEntity struct { // Length Length int `json:"length"` // URL for “text_link” only, url that will be opened after user taps on the text + // // optional URL string `json:"url"` // User for “text_mention” only, the mentioned user + // // optional User *User `json:"user"` } From 12b37b42cc8cb7e2cf24d54fa330076868e5f104 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 17:44:17 +0300 Subject: [PATCH 54/70] Add inline query types documentation --- types.go | 136 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 107 insertions(+), 29 deletions(-) diff --git a/types.go b/types.go index 8c907f0..2943fff 100644 --- a/types.go +++ b/types.go @@ -730,43 +730,121 @@ type InputMediaVideo struct { // InlineQuery is a Query from Telegram for an inline request. type InlineQuery struct { - ID string `json:"id"` - From *User `json:"from"` - Location *Location `json:"location"` // optional - Query string `json:"query"` - Offset string `json:"offset"` + // ID unique identifier for this query + ID string `json:"id"` + // From sender + From *User `json:"from"` + // Location sender location, only for bots that request user location. + // + // optional + Location *Location `json:"location"` + // Query text of the query (up to 256 characters). + Query string `json:"query"` + // Offset of the results to be returned, can be controlled by the bot. + Offset string `json:"offset"` } // InlineQueryResultArticle is an inline query response article. type InlineQueryResultArticle struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - Title string `json:"title"` // required - InputMessageContent interface{} `json:"input_message_content,omitempty"` // required - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - URL string `json:"url"` - HideURL bool `json:"hide_url"` - Description string `json:"description"` - ThumbURL string `json:"thumb_url"` - ThumbWidth int `json:"thumb_width"` - ThumbHeight int `json:"thumb_height"` + // Type of the result, must be article. + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 Bytes. + // + // required + ID string `json:"id"` + // Title of the result + // + // required + Title string `json:"title"` + // InputMessageContent content of the message to be sent. + // + // required + InputMessageContent interface{} `json:"input_message_content,omitempty"` + // ReplyMarkup Inline keyboard attached to the message. + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // URL of the result. + // + // optional + URL string `json:"url"` + // HideURL pass True, if you don't want the URL to be shown in the message. + // + // optional + HideURL bool `json:"hide_url"` + // Description short description of the result. + // + // optional + Description string `json:"description"` + // ThumbURL url of the thumbnail for the result + // + // optional + ThumbURL string `json:"thumb_url"` + // ThumbWidth thumbnail width + // + // optional + ThumbWidth int `json:"thumb_width"` + // ThumbHeight thumbnail height + // + // optional + ThumbHeight int `json:"thumb_height"` } // InlineQueryResultPhoto is an inline query response photo. type InlineQueryResultPhoto struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - URL string `json:"photo_url"` // required - MimeType string `json:"mime_type"` - Width int `json:"photo_width"` - Height int `json:"photo_height"` - ThumbURL string `json:"thumb_url"` - Title string `json:"title"` - Description string `json:"description"` - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be article. + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 Bytes. + // + // required + ID string `json:"id"` + // URL a valid URL of the photo. Photo must be in jpeg format. + // Photo size must not exceed 5MB. + URL string `json:"photo_url"` + // MimeType + MimeType string `json:"mime_type"` + // Width of the photo + // + // optional + Width int `json:"photo_width"` + // Height of the photo + // + // optional + Height int `json:"photo_height"` + // ThumbURL url of the thumbnail for the photo. + // + // optional + ThumbURL string `json:"thumb_url"` + // Title for the result + // + // optional + Title string `json:"title"` + // Description short description of the result + // + // optional + Description string `json:"description"` + // Caption of the photo to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the photo caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message. + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the photo. + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedPhoto is an inline query response with cached photo. From 1e4e3c891c78837e05651fb0a8bfcd381cf1affd Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 17:54:45 +0300 Subject: [PATCH 55/70] Add inline query result cached photo and gif types documentation --- types.go | 102 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 20 deletions(-) diff --git a/types.go b/types.go index 2943fff..14915a5 100644 --- a/types.go +++ b/types.go @@ -849,30 +849,92 @@ type InlineQueryResultPhoto struct { // InlineQueryResultCachedPhoto is an inline query response with cached photo. type InlineQueryResultCachedPhoto struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - PhotoID string `json:"photo_file_id"` // required - Title string `json:"title"` - Description string `json:"description"` - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be photo. + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes. + // + // required + ID string `json:"id"` + // PhotoID a valid file identifier of the photo. + // + // required + PhotoID string `json:"photo_file_id"` + // Title for the result. + // + // optional + Title string `json:"title"` + // Description short description of the result. + // + // optional + Description string `json:"description"` + // Caption of the photo to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the photo caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message. + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the photo. + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultGIF is an inline query response GIF. type InlineQueryResultGIF struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - URL string `json:"gif_url"` // required - ThumbURL string `json:"thumb_url"` // required - Width int `json:"gif_width,omitempty"` - Height int `json:"gif_height,omitempty"` - Duration int `json:"gif_duration,omitempty"` - Title string `json:"title,omitempty"` - Caption string `json:"caption,omitempty"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be gif. + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes. + // + // required + ID string `json:"id"` + // URL a valid URL for the GIF file. File size must not exceed 1MB. + // + // required + URL string `json:"gif_url"` + // ThumbURL url of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result. + // + // required + ThumbURL string `json:"thumb_url"` + // Width of the GIF + // + // optional + Width int `json:"gif_width,omitempty"` + // Height of the GIF + // + // optional + Height int `json:"gif_height,omitempty"` + // Duration of the GIF + // + // optional + Duration int `json:"gif_duration,omitempty"` + // Title for the result + // + // optional + Title string `json:"title,omitempty"` + // Caption of the GIF file to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption,omitempty"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the GIF animation. + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedGIF is an inline query response with cached gif. From 30975af674dda4009c1c322b67f16e0ab7e2802b Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 18:02:39 +0300 Subject: [PATCH 56/70] Add inline query result gif and mpeg4gif types documentation --- types.go | 137 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 27 deletions(-) diff --git a/types.go b/types.go index 14915a5..b5b64b8 100644 --- a/types.go +++ b/types.go @@ -939,42 +939,125 @@ type InlineQueryResultGIF struct { // InlineQueryResultCachedGIF is an inline query response with cached gif. type InlineQueryResultCachedGIF struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - GifID string `json:"gif_file_id"` // required - Title string `json:"title"` - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be gif. + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes. + // + // required + ID string `json:"id"` + // GifID a valid file identifier for the GIF file. + // + // required + GifID string `json:"gif_file_id"` + // Title for the result + // + // optional + Title string `json:"title"` + // Caption of the GIF file to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message. + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the GIF animation. + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF. type InlineQueryResultMPEG4GIF struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - URL string `json:"mpeg4_url"` // required - Width int `json:"mpeg4_width"` - Height int `json:"mpeg4_height"` - Duration int `json:"mpeg4_duration"` - ThumbURL string `json:"thumb_url"` - Title string `json:"title"` - Caption string `json:"caption"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be mpeg4_gif + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // URL a valid URL for the MP4 file. File size must not exceed 1MB + // + // required + URL string `json:"mpeg4_url"` + // Width video width + // + // optional + Width int `json:"mpeg4_width"` + // Height vVideo height + // + // optional + Height int `json:"mpeg4_height"` + // Duration video duration + // + // optional + Duration int `json:"mpeg4_duration"` + // ThumbURL url of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result. + ThumbURL string `json:"thumb_url"` + // Title for the result + // + // optional + Title string `json:"title"` + // Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the video animation + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedMpeg4Gif is an inline query response with cached // H.264/MPEG-4 AVC video without sound gif. type InlineQueryResultCachedMpeg4Gif struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - MGifID string `json:"mpeg4_file_id"` // required - Title string `json:"title"` - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be mpeg4_gif + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // MGifID a valid file identifier for the MP4 file + // + // required + MGifID string `json:"mpeg4_file_id"` + // Title for the result + // + // optional + Title string `json:"title"` + // Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing. + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message. + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the video animation. + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultVideo is an inline query response video. From 11023a093fa4fb72a0a35a0f5ddf17633b309878 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 21:05:03 +0300 Subject: [PATCH 57/70] Add inline query result video types documentation --- types.go | 114 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 22 deletions(-) diff --git a/types.go b/types.go index b5b64b8..fad2948 100644 --- a/types.go +++ b/types.go @@ -1062,32 +1062,102 @@ type InlineQueryResultCachedMpeg4Gif struct { // InlineQueryResultVideo is an inline query response video. type InlineQueryResultVideo struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - URL string `json:"video_url"` // required - MimeType string `json:"mime_type"` // required - ThumbURL string `json:"thumb_url"` - Title string `json:"title"` - Caption string `json:"caption"` - Width int `json:"video_width"` - Height int `json:"video_height"` - Duration int `json:"video_duration"` - Description string `json:"description"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be video + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // URL a valid url for the embedded video player or video file + // + // required + URL string `json:"video_url"` + // MimeType of the content of video url, “text/html” or “video/mp4” + // + // required + MimeType string `json:"mime_type"` + // + // ThumbURL url of the thumbnail (jpeg only) for the video + // optional + ThumbURL string `json:"thumb_url"` + // Title for the result + // + // required + Title string `json:"title"` + // Caption of the video to be sent, 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // Width video width + // + // optional + Width int `json:"video_width"` + // Height video height + // + // optional + Height int `json:"video_height"` + // Duration video duration in seconds + // + // optional + Duration int `json:"video_duration"` + // Description short description of the result + // + // optional + Description string `json:"description"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent 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). + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedVideo is an inline query response with cached video. type InlineQueryResultCachedVideo struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - VideoID string `json:"video_file_id"` // required - Title string `json:"title"` // required - Description string `json:"description"` - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be video + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // VideoID a valid file identifier for the video file + // + // required + VideoID string `json:"video_file_id"` + // Title for the result + // + // required + Title string `json:"title"` + // Description short description of the result + // + // optional + Description string `json:"description"` + // Caption of the video to be sent, 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the video caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the video + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedSticker is an inline query response with cached sticker. From 45369759f12a4d2a226df2deddda8e596dea1573 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 21:12:17 +0300 Subject: [PATCH 58/70] Add inline query result audio types documentation --- types.go | 117 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 94 insertions(+), 23 deletions(-) diff --git a/types.go b/types.go index fad2948..b80eea8 100644 --- a/types.go +++ b/types.go @@ -1162,37 +1162,108 @@ type InlineQueryResultCachedVideo struct { // InlineQueryResultCachedSticker is an inline query response with cached sticker. type InlineQueryResultCachedSticker struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - StickerID string `json:"sticker_file_id"` // required - Title string `json:"title"` // required - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be sticker + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // StickerID a valid file identifier of the sticker + // + // required + StickerID string `json:"sticker_file_id"` + // Title is a title + Title string `json:"title"` + // ParseMode mode for parsing entities in the video caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the sticker + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultAudio is an inline query response audio. type InlineQueryResultAudio struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - URL string `json:"audio_url"` // required - Title string `json:"title"` // required - Caption string `json:"caption"` - Performer string `json:"performer"` - Duration int `json:"audio_duration"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be audio + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // URL a valid url for the audio file + // + // required + URL string `json:"audio_url"` + // Title is a title + // + // required + Title string `json:"title"` + // Caption 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // Performer is a performer + // + // optional + Performer string `json:"performer"` + // Duration audio duration in seconds + // + // optional + Duration int `json:"audio_duration"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the audio + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedAudio is an inline query response with cached audio. type InlineQueryResultCachedAudio struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - AudioID string `json:"audio_file_id"` // required - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be audio + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // AudioID a valid file identifier for the audio file + // + // required + AudioID string `json:"audio_file_id"` + // Caption 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the video caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the audio + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultVoice is an inline query response voice. From 515002232befb8ad10c86f31de61daa91f81fe29 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 21:16:28 +0300 Subject: [PATCH 59/70] Add inline query result voice types documentation --- types.go | 82 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/types.go b/types.go index b80eea8..38b8bab 100644 --- a/types.go +++ b/types.go @@ -1268,26 +1268,76 @@ type InlineQueryResultCachedAudio struct { // InlineQueryResultVoice is an inline query response voice. type InlineQueryResultVoice struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - URL string `json:"voice_url"` // required - Title string `json:"title"` // required - Caption string `json:"caption"` - Duration int `json:"voice_duration"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be voice + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // URL a valid URL for the voice recording + // + // required + URL string `json:"voice_url"` + // Title recording title + // + // required + Title string `json:"title"` + // Caption 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // Duration recording duration in seconds + // + // optional + Duration int `json:"voice_duration"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the voice recording + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultCachedVoice is an inline query response with cached voice. type InlineQueryResultCachedVoice struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - VoiceID string `json:"voice_file_id"` // required - Title string `json:"title"` // required - Caption string `json:"caption"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be voice + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // VoiceID a valid file identifier for the voice message + // + // required + VoiceID string `json:"voice_file_id"` + // Title voice message title + // + // required + Title string `json:"title"` + // Caption 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // ParseMode mode for parsing entities in the video caption. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the voice message + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultDocument is an inline query response document. From ea8eadd3c8c5abf53b7e18d9cbfbb27a01149972 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:07:01 +0300 Subject: [PATCH 60/70] Add inline query result document types documentation --- types.go | 107 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 86 insertions(+), 21 deletions(-) diff --git a/types.go b/types.go index 38b8bab..e592f02 100644 --- a/types.go +++ b/types.go @@ -1342,31 +1342,96 @@ type InlineQueryResultCachedVoice struct { // InlineQueryResultDocument is an inline query response document. type InlineQueryResultDocument struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - Title string `json:"title"` // required - Caption string `json:"caption"` - URL string `json:"document_url"` // required - MimeType string `json:"mime_type"` // required - Description string `json:"description"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` - ThumbURL string `json:"thumb_url"` - ThumbWidth int `json:"thumb_width"` - ThumbHeight int `json:"thumb_height"` + // Type of the result, must be document + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // Title for the result + // + // required + Title string `json:"title"` + // Caption of the document to be sent, 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // URL a valid url for the file + // + // required + URL string `json:"document_url"` + // MimeType of the content of the file, either “application/pdf” or “application/zip” + // + // required + MimeType string `json:"mime_type"` + // Description short description of the result + // + // optional + Description string `json:"description"` + // ReplyMarkup nline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the file + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` + // ThumbURL url of the thumbnail (jpeg only) for the file + // + // optional + ThumbURL string `json:"thumb_url"` + // ThumbWidth thumbnail width + // + // optional + ThumbWidth int `json:"thumb_width"` + // ThumbHeight thumbnail height + // + // optional + ThumbHeight int `json:"thumb_height"` } // InlineQueryResultCachedDocument is an inline query response with cached document. type InlineQueryResultCachedDocument struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - DocumentID string `json:"document_file_id"` // required - Title string `json:"title"` // required - Caption string `json:"caption"` - Description string `json:"description"` - ParseMode string `json:"parse_mode"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` + // Type of the result, must be document + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // DocumentID a valid file identifier for the file + // + // required + DocumentID string `json:"document_file_id"` + // Title for the result + // + // optional + Title string `json:"title"` // required + // Caption of the document to be sent, 0-1024 characters after entities parsing + // + // optional + Caption string `json:"caption"` + // Description short description of the result + // + // optional + Description string `json:"description"` + // ParseMode mode for parsing entities in the video caption. + // // See formatting options for more details + // // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the file + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` } // InlineQueryResultLocation is an inline query response location. From 874f3f2c471f99e45cea41b1908955d22c8828b6 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:13:56 +0300 Subject: [PATCH 61/70] Add inline query result location, venue and game types documentation --- types.go | 136 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 109 insertions(+), 27 deletions(-) diff --git a/types.go b/types.go index e592f02..7d02c36 100644 --- a/types.go +++ b/types.go @@ -1436,41 +1436,123 @@ type InlineQueryResultCachedDocument struct { // InlineQueryResultLocation is an inline query response location. type InlineQueryResultLocation struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - Latitude float64 `json:"latitude"` // required - Longitude float64 `json:"longitude"` // required - Title string `json:"title"` // required - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` - ThumbURL string `json:"thumb_url"` - ThumbWidth int `json:"thumb_width"` - ThumbHeight int `json:"thumb_height"` + // Type of the result, must be location + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 Bytes + // + // required + ID string `json:"id"` + // Latitude of the location in degrees + // + // required + Latitude float64 `json:"latitude"` + // Longitude of the location in degrees + // + // required + Longitude float64 `json:"longitude"` + // Title of the location + // + // required + Title string `json:"title"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the location + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` + // ThumbURL url of the thumbnail for the result + // + // optional + ThumbURL string `json:"thumb_url"` + // ThumbWidth thumbnail width + // + // optional + ThumbWidth int `json:"thumb_width"` + // ThumbHeight thumbnail height + // + // optional + ThumbHeight int `json:"thumb_height"` } // InlineQueryResultVenue is an inline query response venue. type InlineQueryResultVenue struct { - Type string `json:"type"` // required - ID string `json:"id"` // required - Latitude float64 `json:"latitude"` // required - Longitude float64 `json:"longitude"` // required - Title string `json:"title"` // required - Address string `json:"address"` // required - FoursquareID string `json:"foursquare_id"` - FoursquareType string `json:"foursquare_type"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` - InputMessageContent interface{} `json:"input_message_content,omitempty"` - ThumbURL string `json:"thumb_url"` - ThumbWidth int `json:"thumb_width"` - ThumbHeight int `json:"thumb_height"` + // Type of the result, must be venue + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 Bytes + // + // required + ID string `json:"id"` + // Latitude of the venue location in degrees + // + // required + Latitude float64 `json:"latitude"` + // Longitude of the venue location in degrees + // + // required + Longitude float64 `json:"longitude"` + // Title of the venue + // + // required + Title string `json:"title"` + // Address of the venue + // + // required + Address string `json:"address"` + // FoursquareID foursquare identifier of the venue if known + // + // optional + FoursquareID string `json:"foursquare_id"` + // FoursquareType foursquare type of the venue, if known. + // (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.) + // + // optional + FoursquareType string `json:"foursquare_type"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // InputMessageContent content of the message to be sent instead of the venue + // + // optional + InputMessageContent interface{} `json:"input_message_content,omitempty"` + // ThumbURL url of the thumbnail for the result + // + // optional + ThumbURL string `json:"thumb_url"` + // ThumbWidth thumbnail width + // + // optional + ThumbWidth int `json:"thumb_width"` + // ThumbHeight thumbnail height + // + // optional + ThumbHeight int `json:"thumb_height"` } // InlineQueryResultGame is an inline query response game. type InlineQueryResultGame struct { - Type string `json:"type"` - ID string `json:"id"` - GameShortName string `json:"game_short_name"` - ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` + // Type of the result, must be game + // + // required + Type string `json:"type"` + // ID unique identifier for this result, 1-64 bytes + // + // required + ID string `json:"id"` + // GameShortName short name of the game + // + // required + GameShortName string `json:"game_short_name"` + // ReplyMarkup inline keyboard attached to the message + // + // optional + ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` } // ChosenInlineResult is an inline query result chosen by a User From 536eb5215a3cda3806a95e4f68cf05a5988bccd4 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:16:34 +0300 Subject: [PATCH 62/70] Add chosen inline result type documentation --- types.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/types.go b/types.go index 7d02c36..056a506 100644 --- a/types.go +++ b/types.go @@ -1557,11 +1557,22 @@ type InlineQueryResultGame struct { // ChosenInlineResult is an inline query result chosen by a User type ChosenInlineResult struct { - ResultID string `json:"result_id"` - From *User `json:"from"` - Location *Location `json:"location"` - InlineMessageID string `json:"inline_message_id"` - Query string `json:"query"` + // ResultID the unique identifier for the result that was chosen + ResultID string `json:"result_id"` + // From the user that chose the result + From *User `json:"from"` + // Location sender location, only for bots that require user location + // + // optional + Location *Location `json:"location"` + // InlineMessageID identifier of the sent inline message. + // Available only if there is an inline keyboard attached to the message. + // Will be also received in callback queries and can be used to edit the message. + // + // optional + InlineMessageID string `json:"inline_message_id"` + // Query the query that was used to obtain the result + Query string `json:"query"` } // InputTextMessageContent contains text for displaying From 25c494b33521571360e1e71e78159e8510c64c51 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:21:34 +0300 Subject: [PATCH 63/70] Add input message content types documentation --- types.go | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/types.go b/types.go index 056a506..eab9afc 100644 --- a/types.go +++ b/types.go @@ -1578,34 +1578,57 @@ type ChosenInlineResult struct { // InputTextMessageContent contains text for displaying // as an inline query result. type InputTextMessageContent struct { - Text string `json:"message_text"` - ParseMode string `json:"parse_mode"` - DisableWebPagePreview bool `json:"disable_web_page_preview"` + // Text of the message to be sent, 1-4096 characters + Text string `json:"message_text"` + // ParseMode mode for parsing entities in the message text. + // See formatting options for more details + // (https://core.telegram.org/bots/api#formatting-options). + // + // optional + ParseMode string `json:"parse_mode"` + // DisableWebPagePreview disables link previews for links in the sent message + // + // optional + DisableWebPagePreview bool `json:"disable_web_page_preview"` } // InputLocationMessageContent contains a location for displaying // as an inline query result. type InputLocationMessageContent struct { - Latitude float64 `json:"latitude"` + // Latitude of the location in degrees + Latitude float64 `json:"latitude"` + // Longitude of the location in degrees Longitude float64 `json:"longitude"` } // InputVenueMessageContent contains a venue for displaying // as an inline query result. type InputVenueMessageContent struct { - Latitude float64 `json:"latitude"` - Longitude float64 `json:"longitude"` - Title string `json:"title"` - Address string `json:"address"` - FoursquareID string `json:"foursquare_id"` + // Latitude of the venue in degrees + Latitude float64 `json:"latitude"` + // Longitude of the venue in degrees + Longitude float64 `json:"longitude"` + // Title name of the venue + Title string `json:"title"` + // Address of the venue + Address string `json:"address"` + // FoursquareID foursquare identifier of the venue, if known + // + // optional + FoursquareID string `json:"foursquare_id"` } // InputContactMessageContent contains a contact for displaying // as an inline query result. type InputContactMessageContent struct { + // PhoneNumber contact's phone number PhoneNumber string `json:"phone_number"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` + // FirstName contact's first name + FirstName string `json:"first_name"` + // LastName contact's last name + // + // optional + LastName string `json:"last_name"` } // Invoice contains basic information about an invoice. From 6964c7af4e996f1d810386673a1aa286a5846cbb Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:23:18 +0300 Subject: [PATCH 64/70] Add iinvoice type documentation --- types.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/types.go b/types.go index eab9afc..907f888 100644 --- a/types.go +++ b/types.go @@ -1633,11 +1633,20 @@ type InputContactMessageContent struct { // Invoice contains basic information about an invoice. type Invoice struct { - Title string `json:"title"` - Description string `json:"description"` + // Title product name + Title string `json:"title"` + // Description product description + Description string `json:"description"` + // StartParameter unique bot deep-linking parameter that can be used to generate this invoice StartParameter string `json:"start_parameter"` - Currency string `json:"currency"` - TotalAmount int `json:"total_amount"` + // Currency three-letter ISO 4217 currency code + // (see https://core.telegram.org/bots/payments#supported-currencies) + Currency string `json:"currency"` + // TotalAmount otal price in the smallest units of the currency (integer, not float/double). + // For example, for a price of US$ 1.45 pass amount = 145. + // See the exp parameter in currencies.json, it shows the number of digits + // past the decimal point for each currency (2 for the majority of currencies). + TotalAmount int `json:"total_amount"` } // LabeledPrice represents a portion of the price for goods or services. From 5844ea113ed294770e0abfbb55f111720be7e29f Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:27:45 +0300 Subject: [PATCH 65/70] Add shipping types documentation --- types.go | 54 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/types.go b/types.go index 907f888..6bdb9e2 100644 --- a/types.go +++ b/types.go @@ -1644,39 +1644,69 @@ type Invoice struct { Currency string `json:"currency"` // TotalAmount otal price in the smallest units of the currency (integer, not float/double). // For example, for a price of US$ 1.45 pass amount = 145. - // See the exp parameter in currencies.json, it shows the number of digits - // past the decimal point for each currency (2 for the majority of currencies). + // See the exp parameter in currencies.json + // (https://core.telegram.org/bots/payments/currencies.json), + // it shows the number of digits past the decimal point + // for each currency (2 for the majority of currencies). TotalAmount int `json:"total_amount"` } // LabeledPrice represents a portion of the price for goods or services. type LabeledPrice struct { - Label string `json:"label"` - Amount int `json:"amount"` + // Label portion label + Label string `json:"label"` + // Amount price of the product in the smallest units of the currency (integer, not float/double). + // For example, for a price of US$ 1.45 pass amount = 145. + // See the exp parameter in currencies.json + // (https://core.telegram.org/bots/payments/currencies.json), + // it shows the number of digits past the decimal point + // for each currency (2 for the majority of currencies). + Amount int `json:"amount"` } // ShippingAddress represents a shipping address. type ShippingAddress struct { + // CountryCode ISO 3166-1 alpha-2 country code CountryCode string `json:"country_code"` - State string `json:"state"` - City string `json:"city"` + // State if applicable + State string `json:"state"` + // City city + City string `json:"city"` + // StreetLine1 fFirst line for the address StreetLine1 string `json:"street_line1"` + // StreetLine2 second line for the address StreetLine2 string `json:"street_line2"` - PostCode string `json:"post_code"` + // PostCode address post code + PostCode string `json:"post_code"` } // OrderInfo represents information about an order. type OrderInfo struct { - Name string `json:"name,omitempty"` - PhoneNumber string `json:"phone_number,omitempty"` - Email string `json:"email,omitempty"` + // Name user name + // + // optional + Name string `json:"name,omitempty"` + // PhoneNumber user's phone number + // + // optional + PhoneNumber string `json:"phone_number,omitempty"` + // Email user email + // + // optional + Email string `json:"email,omitempty"` + // ShippingAddress user shipping address + // + // optional ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"` } // ShippingOption represents one shipping option. type ShippingOption struct { - ID string `json:"id"` - Title string `json:"title"` + // ID shipping option identifier + ID string `json:"id"` + // Title option title + Title string `json:"title"` + // Prices list of price portions Prices *[]LabeledPrice `json:"prices"` } From 1e3171403ae5477fe03ad34fbff5295c91010e8b Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:31:18 +0300 Subject: [PATCH 66/70] Add payment type documentation --- types.go | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/types.go b/types.go index 6bdb9e2..b68f494 100644 --- a/types.go +++ b/types.go @@ -1642,7 +1642,7 @@ type Invoice struct { // Currency three-letter ISO 4217 currency code // (see https://core.telegram.org/bots/payments#supported-currencies) Currency string `json:"currency"` - // TotalAmount otal price in the smallest units of the currency (integer, not float/double). + // TotalAmount total price in the smallest units of the currency (integer, not float/double). // For example, for a price of US$ 1.45 pass amount = 145. // See the exp parameter in currencies.json // (https://core.telegram.org/bots/payments/currencies.json), @@ -1672,7 +1672,7 @@ type ShippingAddress struct { State string `json:"state"` // City city City string `json:"city"` - // StreetLine1 fFirst line for the address + // StreetLine1 first line for the address StreetLine1 string `json:"street_line1"` // StreetLine2 second line for the address StreetLine2 string `json:"street_line2"` @@ -1712,13 +1712,30 @@ type ShippingOption struct { // SuccessfulPayment contains basic information about a successful payment. type SuccessfulPayment struct { - Currency string `json:"currency"` - TotalAmount int `json:"total_amount"` - InvoicePayload string `json:"invoice_payload"` - ShippingOptionID string `json:"shipping_option_id,omitempty"` - OrderInfo *OrderInfo `json:"order_info,omitempty"` - TelegramPaymentChargeID string `json:"telegram_payment_charge_id"` - ProviderPaymentChargeID string `json:"provider_payment_charge_id"` + // Currency three-letter ISO 4217 currency code + // (see https://core.telegram.org/bots/payments#supported-currencies) + Currency string `json:"currency"` + // TotalAmount total price in the smallest units of the currency (integer, not float/double). + // For example, for a price of US$ 1.45 pass amount = 145. + // See the exp parameter in currencies.json, + // (https://core.telegram.org/bots/payments/currencies.json) + // it shows the number of digits past the decimal point + // for each currency (2 for the majority of currencies). + TotalAmount int `json:"total_amount"` + // InvoicePayload bot specified invoice payload + InvoicePayload string `json:"invoice_payload"` + // ShippingOptionID identifier of the shipping option chosen by the user + // + // optional + ShippingOptionID string `json:"shipping_option_id,omitempty"` + // OrderInfo order info provided by the user + // + // optional + OrderInfo *OrderInfo `json:"order_info,omitempty"` + // TelegramPaymentChargeID telegram payment identifier + TelegramPaymentChargeID string `json:"telegram_payment_charge_id"` + // ProviderPaymentChargeID provider payment identifier + ProviderPaymentChargeID string `json:"provider_payment_charge_id"` } // ShippingQuery contains information about an incoming shipping query. From 189bf08685f387c5807a0fdd2909b89705059d27 Mon Sep 17 00:00:00 2001 From: Ilya Kaznacheev Date: Sat, 24 Oct 2020 23:34:43 +0300 Subject: [PATCH 67/70] Add shipping and bot command types documentation --- types.go | 46 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/types.go b/types.go index b68f494..7a50c32 100644 --- a/types.go +++ b/types.go @@ -1740,21 +1740,42 @@ type SuccessfulPayment struct { // ShippingQuery contains information about an incoming shipping query. type ShippingQuery struct { - ID string `json:"id"` - From *User `json:"from"` - InvoicePayload string `json:"invoice_payload"` + // ID unique query identifier + ID string `json:"id"` + // From user who sent the query + From *User `json:"from"` + // InvoicePayload bot specified invoice payload + InvoicePayload string `json:"invoice_payload"` + // ShippingAddress user specified shipping address ShippingAddress *ShippingAddress `json:"shipping_address"` } // PreCheckoutQuery contains information about an incoming pre-checkout query. type PreCheckoutQuery struct { - ID string `json:"id"` - From *User `json:"from"` - Currency string `json:"currency"` - TotalAmount int `json:"total_amount"` - InvoicePayload string `json:"invoice_payload"` - ShippingOptionID string `json:"shipping_option_id,omitempty"` - OrderInfo *OrderInfo `json:"order_info,omitempty"` + // ID unique query identifier + ID string `json:"id"` + // From user who sent the query + From *User `json:"from"` + // Currency three-letter ISO 4217 currency code + // // (see https://core.telegram.org/bots/payments#supported-currencies) + Currency string `json:"currency"` + // TotalAmount total price in the smallest units of the currency (integer, not float/double). + // // For example, for a price of US$ 1.45 pass amount = 145. + // // See the exp parameter in currencies.json, + // // (https://core.telegram.org/bots/payments/currencies.json) + // // it shows the number of digits past the decimal point + // // for each currency (2 for the majority of currencies). + TotalAmount int `json:"total_amount"` + // InvoicePayload bot specified invoice payload + InvoicePayload string `json:"invoice_payload"` + // ShippingOptionID identifier of the shipping option chosen by the user + // + // optional + ShippingOptionID string `json:"shipping_option_id,omitempty"` + // OrderInfo order info provided by the user + // + // optional + OrderInfo *OrderInfo `json:"order_info,omitempty"` } // Error is an error containing extra information returned by the Telegram API. @@ -1770,6 +1791,9 @@ func (e Error) Error() string { // BotCommand represents a bot command. type BotCommand struct { - Command string `json:"command"` + // Command text of the command, 1-32 characters. + // Can contain only lowercase English letters, digits and underscores. + Command string `json:"command"` + // Description of the command, 3-256 characters. Description string `json:"description"` } From 85ecb116757bcc6b4ec985e495d206c5e4443063 Mon Sep 17 00:00:00 2001 From: Erik Pellizzon Date: Mon, 26 Oct 2020 17:41:02 +0100 Subject: [PATCH 68/70] Added EscapeText function --- bot.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/bot.go b/bot.go index cffe4c2..f1abe30 100644 --- a/bot.go +++ b/bot.go @@ -1065,3 +1065,30 @@ func (bot *BotAPI) SetMyCommands(commands []BotCommand) error { } return nil } + +// EscapeText takes an input text and escape Telegram markup symbols. +// In this way we can send a text without being afraid of having to escape the characters manually. +// Note that you don't have to include the formatting style in the input text, or it will be escaped too. +// +// parseMode is the text formatting mode (ModeMarkdown, ModeMarkdownV2 or ModeHTML) +// text is the input string that will be escaped +func (*BotAPI) EscapeText(parseMode string, text string) string { + var replacer *strings.Replacer + + if parseMode == ModeHTML { + replacer = strings.NewReplacer("<", "<", ">", ">", "&", "&") + } else if parseMode == ModeMarkdown { + replacer = strings.NewReplacer("_", "\\_", "*", "\\*", "`", "\\`", "[", "\\[") + } else if parseMode == ModeMarkdownV2 { + replacer = strings.NewReplacer( + "_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(", + "\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>", + "#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|", + "\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!", + ) + } else { + return "" + } + + return replacer.Replace(text) +} From 41e859781613898211b9b0d20d04a34c5fa27b69 Mon Sep 17 00:00:00 2001 From: Erik Pellizzon Date: Fri, 6 Nov 2020 11:25:32 +0100 Subject: [PATCH 69/70] Remove function from BotApi struct Co-authored-by: Syfaro --- bot.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.go b/bot.go index f1abe30..f407515 100644 --- a/bot.go +++ b/bot.go @@ -1072,7 +1072,7 @@ func (bot *BotAPI) SetMyCommands(commands []BotCommand) error { // // parseMode is the text formatting mode (ModeMarkdown, ModeMarkdownV2 or ModeHTML) // text is the input string that will be escaped -func (*BotAPI) EscapeText(parseMode string, text string) string { +func EscapeText(parseMode string, text string) string { var replacer *strings.Replacer if parseMode == ModeHTML { From 7d4ae712ae1064f8ad4baa8f66105ac55de21ed0 Mon Sep 17 00:00:00 2001 From: Erik Pellizzon Date: Fri, 6 Nov 2020 22:07:29 +0100 Subject: [PATCH 70/70] Added empty string error return in docs --- bot.go | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.go b/bot.go index f407515..626024e 100644 --- a/bot.go +++ b/bot.go @@ -1069,6 +1069,7 @@ func (bot *BotAPI) SetMyCommands(commands []BotCommand) error { // EscapeText takes an input text and escape Telegram markup symbols. // In this way we can send a text without being afraid of having to escape the characters manually. // Note that you don't have to include the formatting style in the input text, or it will be escaped too. +// If there is an error, an empty string will be returned. // // parseMode is the text formatting mode (ModeMarkdown, ModeMarkdownV2 or ModeHTML) // text is the input string that will be escaped