From f90493fac6ee3a4cc3918d3edb4da1f7999acc38 Mon Sep 17 00:00:00 2001 From: Amir Khazaie <733amir@gmail.com> Date: Sat, 30 Jun 2018 11:01:59 +0430 Subject: [PATCH 01/18] Add ParseMode to EditMessageCaption --- configs.go | 4 +++- helpers.go | 5 +++-- helpers_test.go | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configs.go b/configs.go index bcc850d..08aa491 100644 --- a/configs.go +++ b/configs.go @@ -793,13 +793,15 @@ func (config EditMessageTextConfig) method() string { // EditMessageCaptionConfig allows you to modify the caption of a message. type EditMessageCaptionConfig struct { BaseEdit - Caption string + Caption string + ParseMode string } func (config EditMessageCaptionConfig) values() (url.Values, error) { v, _ := config.BaseEdit.values() v.Add("caption", config.Caption) + v.Add("parse_mode", config.ParseMode) return v, nil } diff --git a/helpers.go b/helpers.go index b5480ea..9088d31 100644 --- a/helpers.go +++ b/helpers.go @@ -494,13 +494,14 @@ func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTex } // NewEditMessageCaption allows you to edit the caption of a message. -func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig { +func NewEditMessageCaption(chatID int64, messageID int, caption, parseMode string) EditMessageCaptionConfig { return EditMessageCaptionConfig{ BaseEdit: BaseEdit{ ChatID: chatID, MessageID: messageID, }, - Caption: caption, + Caption: caption, + ParseMode: parseMode, } } diff --git a/helpers_test.go b/helpers_test.go index 9542f02..6075612 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -148,9 +148,10 @@ func TestNewEditMessageText(t *testing.T) { } func TestNewEditMessageCaption(t *testing.T) { - edit := tgbotapi.NewEditMessageCaption(ChatID, ReplyToMessageID, "new caption") + edit := tgbotapi.NewEditMessageCaption(ChatID, ReplyToMessageID, "new caption", tgbotapi.ModeHTML) if edit.Caption != "new caption" || + edit.ParseMode != tgbotapi.ModeHTML || edit.BaseEdit.ChatID != ChatID || edit.BaseEdit.MessageID != ReplyToMessageID { t.Fail() From 31f4975464f318de5f00fb1c2fd905c259c14199 Mon Sep 17 00:00:00 2001 From: Amir Khazaie <733amir@gmail.com> Date: Wed, 4 Jul 2018 15:18:19 +0430 Subject: [PATCH 02/18] Add cached types for inline query answer --- helpers.go | 66 +++++++++++++++++++++++++++++++++++++++++ types.go | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) diff --git a/helpers.go b/helpers.go index 9088d31..d4ee98b 100644 --- a/helpers.go +++ b/helpers.go @@ -403,6 +403,15 @@ func NewInlineQueryResultGIF(id, url string) InlineQueryResultGIF { } } +// NewInlineQueryResultCachedGIF create a new inline query with cached photo. +func NewInlineQueryResultCachedGIF(id, gifID string) InlineQueryResultCachedGIF { + return InlineQueryResultCachedGIF{ + Type: "gif", + ID: id, + GifID: gifID, + } +} + // NewInlineQueryResultMPEG4GIF creates a new inline query MPEG4 GIF. func NewInlineQueryResultMPEG4GIF(id, url string) InlineQueryResultMPEG4GIF { return InlineQueryResultMPEG4GIF{ @@ -412,6 +421,15 @@ func NewInlineQueryResultMPEG4GIF(id, url string) InlineQueryResultMPEG4GIF { } } +// NewInlineQueryResultCachedPhoto create a new inline query with cached photo. +func NewInlineQueryResultCachedMPEG4GIF(id, MPEG4GifID string) InlineQueryResultCachedMpeg4Gif { + return InlineQueryResultCachedMpeg4Gif{ + Type: "mpeg4_gif", + ID: id, + MGifID: MPEG4GifID, + } +} + // NewInlineQueryResultPhoto creates a new inline query photo. func NewInlineQueryResultPhoto(id, url string) InlineQueryResultPhoto { return InlineQueryResultPhoto{ @@ -431,6 +449,15 @@ func NewInlineQueryResultPhotoWithThumb(id, url, thumb string) InlineQueryResult } } +// NewInlineQueryResultCachedPhoto create a new inline query with cached photo. +func NewInlineQueryResultCachedPhoto(id, photoID string) InlineQueryResultCachedPhoto { + return InlineQueryResultCachedPhoto{ + Type: "photo", + ID: id, + PhotoID: photoID, + } +} + // NewInlineQueryResultVideo creates a new inline query video. func NewInlineQueryResultVideo(id, url string) InlineQueryResultVideo { return InlineQueryResultVideo{ @@ -440,6 +467,16 @@ func NewInlineQueryResultVideo(id, url string) InlineQueryResultVideo { } } +// NewInlineQueryResultCachedVideo create a new inline query with cached video. +func NewInlineQueryResultCachedVideo(id, videoID, title string) InlineQueryResultCachedVideo { + return InlineQueryResultCachedVideo{ + Type: "video", + ID: id, + VideoID: videoID, + Title: title, + } +} + // NewInlineQueryResultAudio creates a new inline query audio. func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio { return InlineQueryResultAudio{ @@ -450,6 +487,15 @@ func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio { } } +// NewInlineQueryResultCachedAudio create a new inline query with cached photo. +func NewInlineQueryResultCachedAudio(id, audioID string) InlineQueryResultCachedAudio { + return InlineQueryResultCachedAudio{ + Type: "audio", + ID: id, + AudioID: audioID, + } +} + // NewInlineQueryResultVoice creates a new inline query voice. func NewInlineQueryResultVoice(id, url, title string) InlineQueryResultVoice { return InlineQueryResultVoice{ @@ -460,6 +506,16 @@ func NewInlineQueryResultVoice(id, url, title string) InlineQueryResultVoice { } } +// NewInlineQueryResultCachedVoice create a new inline query with cached photo. +func NewInlineQueryResultCachedVoice(id, voiceID, title string) InlineQueryResultCachedVoice { + return InlineQueryResultCachedVoice{ + Type: "voice", + ID: id, + VoiceID: voiceID, + Title: title, + } +} + // NewInlineQueryResultDocument creates a new inline query document. func NewInlineQueryResultDocument(id, url, title, mimeType string) InlineQueryResultDocument { return InlineQueryResultDocument{ @@ -471,6 +527,16 @@ func NewInlineQueryResultDocument(id, url, title, mimeType string) InlineQueryRe } } +// NewInlineQueryResultCachedDocument create a new inline query with cached photo. +func NewInlineQueryResultCachedDocument(id, documentID, title string) InlineQueryResultCachedDocument { + return InlineQueryResultCachedDocument{ + Type: "document", + ID: id, + DocumentID: documentID, + Title: title, + } +} + // NewInlineQueryResultLocation creates a new inline query location. func NewInlineQueryResultLocation(id, title string, latitude, longitude float64) InlineQueryResultLocation { return InlineQueryResultLocation{ diff --git a/types.go b/types.go index 0843ab9..da325f4 100644 --- a/types.go +++ b/types.go @@ -551,6 +551,19 @@ type InlineQueryResultPhoto struct { InputMessageContent interface{} `json:"input_message_content,omitempty"` } +// 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"` +} + // InlineQueryResultGIF is an inline query response GIF. type InlineQueryResultGIF struct { Type string `json:"type"` // required @@ -566,6 +579,18 @@ type InlineQueryResultGIF struct { InputMessageContent interface{} `json:"input_message_content,omitempty"` } +// 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"` +} + // InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF. type InlineQueryResultMPEG4GIF struct { Type string `json:"type"` // required @@ -581,6 +606,19 @@ type InlineQueryResultMPEG4GIF struct { 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"` +} + // InlineQueryResultVideo is an inline query response video. type InlineQueryResultVideo struct { Type string `json:"type"` // required @@ -598,6 +636,19 @@ type InlineQueryResultVideo struct { 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"` +} + // InlineQueryResultAudio is an inline query response audio. type InlineQueryResultAudio struct { Type string `json:"type"` // required @@ -611,6 +662,17 @@ type InlineQueryResultAudio struct { 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"` +} + // InlineQueryResultVoice is an inline query response voice. type InlineQueryResultVoice struct { Type string `json:"type"` // required @@ -623,6 +685,18 @@ type InlineQueryResultVoice struct { 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"` +} + // InlineQueryResultDocument is an inline query response document. type InlineQueryResultDocument struct { Type string `json:"type"` // required @@ -639,6 +713,19 @@ type InlineQueryResultDocument struct { 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"` +} + // InlineQueryResultLocation is an inline query response location. type InlineQueryResultLocation struct { Type string `json:"type"` // required From 4edcb0fa1ab5e691899ca33c58d79f517c6bf30f Mon Sep 17 00:00:00 2001 From: Amir Khazaie <733amir@gmail.com> Date: Wed, 4 Jul 2018 15:19:37 +0430 Subject: [PATCH 03/18] Correct formatting of code with `go fmt` --- helpers.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/helpers.go b/helpers.go index d4ee98b..310319f 100644 --- a/helpers.go +++ b/helpers.go @@ -406,8 +406,8 @@ func NewInlineQueryResultGIF(id, url string) InlineQueryResultGIF { // NewInlineQueryResultCachedGIF create a new inline query with cached photo. func NewInlineQueryResultCachedGIF(id, gifID string) InlineQueryResultCachedGIF { return InlineQueryResultCachedGIF{ - Type: "gif", - ID: id, + Type: "gif", + ID: id, GifID: gifID, } } @@ -424,8 +424,8 @@ func NewInlineQueryResultMPEG4GIF(id, url string) InlineQueryResultMPEG4GIF { // NewInlineQueryResultCachedPhoto create a new inline query with cached photo. func NewInlineQueryResultCachedMPEG4GIF(id, MPEG4GifID string) InlineQueryResultCachedMpeg4Gif { return InlineQueryResultCachedMpeg4Gif{ - Type: "mpeg4_gif", - ID: id, + Type: "mpeg4_gif", + ID: id, MGifID: MPEG4GifID, } } @@ -452,8 +452,8 @@ func NewInlineQueryResultPhotoWithThumb(id, url, thumb string) InlineQueryResult // NewInlineQueryResultCachedPhoto create a new inline query with cached photo. func NewInlineQueryResultCachedPhoto(id, photoID string) InlineQueryResultCachedPhoto { return InlineQueryResultCachedPhoto{ - Type: "photo", - ID: id, + Type: "photo", + ID: id, PhotoID: photoID, } } @@ -470,10 +470,10 @@ func NewInlineQueryResultVideo(id, url string) InlineQueryResultVideo { // NewInlineQueryResultCachedVideo create a new inline query with cached video. func NewInlineQueryResultCachedVideo(id, videoID, title string) InlineQueryResultCachedVideo { return InlineQueryResultCachedVideo{ - Type: "video", - ID: id, + Type: "video", + ID: id, VideoID: videoID, - Title: title, + Title: title, } } @@ -490,8 +490,8 @@ func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio { // NewInlineQueryResultCachedAudio create a new inline query with cached photo. func NewInlineQueryResultCachedAudio(id, audioID string) InlineQueryResultCachedAudio { return InlineQueryResultCachedAudio{ - Type: "audio", - ID: id, + Type: "audio", + ID: id, AudioID: audioID, } } @@ -509,10 +509,10 @@ func NewInlineQueryResultVoice(id, url, title string) InlineQueryResultVoice { // NewInlineQueryResultCachedVoice create a new inline query with cached photo. func NewInlineQueryResultCachedVoice(id, voiceID, title string) InlineQueryResultCachedVoice { return InlineQueryResultCachedVoice{ - Type: "voice", - ID: id, + Type: "voice", + ID: id, VoiceID: voiceID, - Title: title, + Title: title, } } @@ -530,10 +530,10 @@ func NewInlineQueryResultDocument(id, url, title, mimeType string) InlineQueryRe // NewInlineQueryResultCachedDocument create a new inline query with cached photo. func NewInlineQueryResultCachedDocument(id, documentID, title string) InlineQueryResultCachedDocument { return InlineQueryResultCachedDocument{ - Type: "document", - ID: id, + Type: "document", + ID: id, DocumentID: documentID, - Title: title, + Title: title, } } From 9860bdfd3a171ceafb6e1eafa163482a6ef92643 Mon Sep 17 00:00:00 2001 From: Syfaro Date: Mon, 8 Oct 2018 14:45:45 -0500 Subject: [PATCH 04/18] Fix capitalization in doc. --- passport.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passport.go b/passport.go index f949b88..5f55006 100644 --- a/passport.go +++ b/passport.go @@ -307,7 +307,7 @@ type ( MiddleNameNative string `json:"middle_name_native"` } - // IdDocumentData https://core.telegram.org/passport#iddocumentdata + // IDDocumentData https://core.telegram.org/passport#iddocumentdata IDDocumentData struct { DocumentNumber string `json:"document_no"` ExpiryDate string `json:"expiry_date"` From b2addf5f91a4c2750c3f03aa22e1aab243e6db6d Mon Sep 17 00:00:00 2001 From: Amir Khazaie <733amir@gmail.com> Date: Mon, 15 Oct 2018 12:31:37 +0330 Subject: [PATCH 05/18] Fix backwards compatibility problem --- helpers.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helpers.go b/helpers.go index b15b9f2..3dabe11 100644 --- a/helpers.go +++ b/helpers.go @@ -616,14 +616,13 @@ func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTex } // NewEditMessageCaption allows you to edit the caption of a message. -func NewEditMessageCaption(chatID int64, messageID int, caption, parseMode string) EditMessageCaptionConfig { +func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig { return EditMessageCaptionConfig{ BaseEdit: BaseEdit{ ChatID: chatID, MessageID: messageID, }, Caption: caption, - ParseMode: parseMode, } } From 97ba9e12bf1de0043362910282546d167e9f74f5 Mon Sep 17 00:00:00 2001 From: Amir Khazaie <733amir@gmail.com> Date: Mon, 15 Oct 2018 12:41:02 +0330 Subject: [PATCH 06/18] Fix help tests --- helpers_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helpers_test.go b/helpers_test.go index 6075612..9542f02 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -148,10 +148,9 @@ func TestNewEditMessageText(t *testing.T) { } func TestNewEditMessageCaption(t *testing.T) { - edit := tgbotapi.NewEditMessageCaption(ChatID, ReplyToMessageID, "new caption", tgbotapi.ModeHTML) + edit := tgbotapi.NewEditMessageCaption(ChatID, ReplyToMessageID, "new caption") if edit.Caption != "new caption" || - edit.ParseMode != tgbotapi.ModeHTML || edit.BaseEdit.ChatID != ChatID || edit.BaseEdit.MessageID != ReplyToMessageID { t.Fail() From ab8d5487da0c84a0923a44203aa0a4b3b8ca51fb Mon Sep 17 00:00:00 2001 From: bcmk <45658475+bcmk@users.noreply.github.com> Date: Mon, 10 Dec 2018 18:02:58 +0400 Subject: [PATCH 07/18] Closing update body --- bot.go | 1 + 1 file changed, 1 insertion(+) diff --git a/bot.go b/bot.go index d56aaf8..85e16c1 100644 --- a/bot.go +++ b/bot.go @@ -526,6 +526,7 @@ func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel { 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) From fdf31c7cf4973c36780adf1ad740330657d5225b Mon Sep 17 00:00:00 2001 From: Lev Zakharov Date: Thu, 10 Jan 2019 14:40:12 +0300 Subject: [PATCH 08/18] Add type helpers to message entities. --- types.go | 58 ++++++++++++++++++++++++++++++++++--- types_test.go | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/types.go b/types.go index c6cd642..7b4308a 100644 --- a/types.go +++ b/types.go @@ -183,7 +183,7 @@ func (m *Message) IsCommand() bool { } entity := (*m.Entities)[0] - return entity.Offset == 0 && entity.Type == "bot_command" + return entity.Offset == 0 && entity.IsCommand() } // Command checks if the message was a command and if it was, returns the @@ -249,12 +249,62 @@ type MessageEntity struct { } // ParseURL attempts to parse a URL contained within a MessageEntity. -func (entity MessageEntity) ParseURL() (*url.URL, error) { - if entity.URL == "" { +func (e MessageEntity) ParseURL() (*url.URL, error) { + if e.URL == "" { return nil, errors.New(ErrBadURL) } - return url.Parse(entity.URL) + return url.Parse(e.URL) +} + +// IsMention returns true if the type of the message entity is "mention" (@username). +func (e MessageEntity) IsMention() bool { + return e.Type == "mention" +} + +// IsHashtag returns true if the type of the message entity is "hashtag". +func (e MessageEntity) IsHashtag() bool { + return e.Type == "hashtag" +} + +// IsCommand returns true if the type of the message entity is "bot_command". +func (e MessageEntity) IsCommand() bool { + return e.Type == "bot_command" +} + +// IsUrl returns true if the type of the message entity is "url". +func (e MessageEntity) IsUrl() bool { + return e.Type == "url" +} + +// IsEmail returns true if the type of the message entity is "email". +func (e MessageEntity) IsEmail() bool { + return e.Type == "email" +} + +// IsBold returns true if the type of the message entity is "bold" (bold text). +func (e MessageEntity) IsBold() bool { + return e.Type == "bold" +} + +// IsItalic returns true if the type of the message entity is "italic" (italic text). +func (e MessageEntity) IsItalic() bool { + return e.Type == "italic" +} + +// IsCode returns true if the type of the message entity is "code" (monowidth string). +func (e MessageEntity) IsCode() bool { + return e.Type == "code" +} + +// IsPre returns true if the type of the message entity is "pre" (monowidth block). +func (e MessageEntity) IsPre() bool { + return e.Type == "pre" +} + +// IsTextLink returns true if the type of the message entity is "text_link" (clickable text URL). +func (e MessageEntity) IsTextLink() bool { + return e.Type == "text_link" } // PhotoSize contains information about photos. diff --git a/types_test.go b/types_test.go index bb7bb64..a5db1d4 100644 --- a/types_test.go +++ b/types_test.go @@ -191,6 +191,86 @@ func TestChatIsSuperGroup(t *testing.T) { } } +func TestMessageEntityIsMention(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "mention"} + + if !entity.IsMention() { + t.Fail() + } +} + +func TestMessageEntityIsHashtag(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "hashtag"} + + if !entity.IsHashtag() { + t.Fail() + } +} + +func TestMessageEntityIsBotCommand(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "bot_command"} + + if !entity.IsCommand() { + t.Fail() + } +} + +func TestMessageEntityIsUrl(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "url"} + + if !entity.IsUrl() { + t.Fail() + } +} + +func TestMessageEntityIsEmail(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "email"} + + if !entity.IsEmail() { + t.Fail() + } +} + +func TestMessageEntityIsBold(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "bold"} + + if !entity.IsBold() { + t.Fail() + } +} + +func TestMessageEntityIsItalic(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "italic"} + + if !entity.IsItalic() { + t.Fail() + } +} + +func TestMessageEntityIsCode(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "code"} + + if !entity.IsCode() { + t.Fail() + } +} + +func TestMessageEntityIsPre(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "pre"} + + if !entity.IsPre() { + t.Fail() + } +} + +func TestMessageEntityIsTextLink(t *testing.T) { + entity := tgbotapi.MessageEntity{Type: "text_link"} + + if !entity.IsTextLink() { + t.Fail() + } +} + func TestFileLink(t *testing.T) { file := tgbotapi.File{FilePath: "test/test.txt"} From 74b2a532930711f82a5ceb2d1d92adeeb4992131 Mon Sep 17 00:00:00 2001 From: Yauhen Lazurkin Date: Thu, 24 Jan 2019 09:39:10 +0100 Subject: [PATCH 09/18] Mark optional fields in InlineQueryResultGif as omitempty to not send zeros --- types.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/types.go b/types.go index c6cd642..9b43f83 100644 --- a/types.go +++ b/types.go @@ -604,9 +604,9 @@ type InlineQueryResultGIF struct { Type string `json:"type"` // required ID string `json:"id"` // required URL string `json:"gif_url"` // required - Width int `json:"gif_width"` - Height int `json:"gif_height"` - Duration int `json:"gif_duration"` + Width int `json:"gif_width,omitempty"` + Height int `json:"gif_height,omitempty"` + Duration int `json:"gif_duration,omitempty"` ThumbURL string `json:"thumb_url"` Title string `json:"title"` Caption string `json:"caption"` From 97a13fdf0f1ac653bbea47afa6658c0922ea3c56 Mon Sep 17 00:00:00 2001 From: Yauhen Lazurkin Date: Thu, 24 Jan 2019 09:45:45 +0100 Subject: [PATCH 10/18] Complete definition of InlineQueryResultGIF to comply with Bot API --- types.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/types.go b/types.go index 9b43f83..f529e63 100644 --- a/types.go +++ b/types.go @@ -601,15 +601,15 @@ type InlineQueryResultCachedPhoto struct { // 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 + 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"` - ThumbURL string `json:"thumb_url"` - Title string `json:"title"` - Caption string `json:"caption"` + Title string `json:"title,omitempty"` + Caption string `json:"caption,omitempty"` ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` InputMessageContent interface{} `json:"input_message_content,omitempty"` } From 0b788c7730d625b1c81e7a311754251951112a81 Mon Sep 17 00:00:00 2001 From: Maxim Zhukov Date: Tue, 12 Feb 2019 22:00:57 +0300 Subject: [PATCH 11/18] added PinnedMessage in Chat struct Since BotAPI 3.3: getChat now also returns pinned messages in supergroups, if present. Added the new field pinned_message to the Chat object. Signed-off-by: Maxim Zhukov --- types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types.go b/types.go index c6cd642..9d96fb9 100644 --- a/types.go +++ b/types.go @@ -100,6 +100,7 @@ type Chat struct { Photo *ChatPhoto `json:"photo"` Description string `json:"description,omitempty"` // optional InviteLink string `json:"invite_link,omitempty"` // optional + PinnedMessage *Message `json:"pinned_message"` // optional } // IsPrivate returns if the Chat is a private conversation. From 016d6acdf35787efe8b5bec12b0cfe91b04b5f8c Mon Sep 17 00:00:00 2001 From: bcmk <45658475+bcmk@users.noreply.github.com> Date: Fri, 1 Mar 2019 20:17:35 +0400 Subject: [PATCH 12/18] Passing error code --- bot.go | 2 +- types.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bot.go b/bot.go index 85e16c1..88d907e 100644 --- a/bot.go +++ b/bot.go @@ -84,7 +84,7 @@ func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, if apiResp.Parameters != nil { parameters = *apiResp.Parameters } - return apiResp, Error{apiResp.Description, parameters} + return apiResp, Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters} } return apiResp, nil diff --git a/types.go b/types.go index c6cd642..478aa89 100644 --- a/types.go +++ b/types.go @@ -897,6 +897,7 @@ type PreCheckoutQuery struct { // Error is an error containing extra information returned by the Telegram API. type Error struct { + Code int Message string ResponseParameters } From ab4ab5e531017f0213be57df9fd0369d8d06b63d Mon Sep 17 00:00:00 2001 From: Andrey Kuzmin Date: Tue, 9 Apr 2019 14:32:23 +0300 Subject: [PATCH 13/18] Add support for caption_entities in Message type. caption_entities are using for messages with a caption, special entities like usernames, URLs, bot commands, etc. that appear in the caption. --- types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types.go b/types.go index c6cd642..98af8c8 100644 --- a/types.go +++ b/types.go @@ -142,6 +142,7 @@ type Message struct { EditDate int `json:"edit_date"` // 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 From 8d345836d6a6a3b188ef4ff0cf2a54afd27edde5 Mon Sep 17 00:00:00 2001 From: zhuharev Date: Fri, 24 May 2019 13:14:48 +0300 Subject: [PATCH 14/18] Allow to change API endpoint for bot --- bot.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/bot.go b/bot.go index 88d907e..a996790 100644 --- a/bot.go +++ b/bot.go @@ -25,9 +25,11 @@ type BotAPI struct { Debug bool `json:"debug"` Buffer int `json:"buffer"` - Self User `json:"-"` - Client *http.Client `json:"-"` + Self User `json:"-"` + Client *http.Client `json:"-"` shutdownChannel chan interface{} + + apiEndpoint string } // NewBotAPI creates a new BotAPI instance. @@ -43,10 +45,12 @@ func NewBotAPI(token string) (*BotAPI, error) { // It requires a token, provided by @BotFather on Telegram. func NewBotAPIWithClient(token string, client *http.Client) (*BotAPI, error) { bot := &BotAPI{ - Token: token, - Client: client, - Buffer: 100, + Token: token, + Client: client, + Buffer: 100, shutdownChannel: make(chan interface{}), + + apiEndpoint: APIEndpoint, } self, err := bot.GetMe() @@ -59,9 +63,13 @@ func NewBotAPIWithClient(token string, client *http.Client) (*BotAPI, error) { return bot, nil } +func (b *BotAPI) SetAPIEndpoint(apiEndpoint string) { + b.apiEndpoint = apiEndpoint +} + // MakeRequest makes a request to a specific endpoint with our token. func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, error) { - method := fmt.Sprintf(APIEndpoint, bot.Token, endpoint) + method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint) resp, err := bot.Client.PostForm(method, params) if err != nil { @@ -186,7 +194,7 @@ func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldna return APIResponse{}, errors.New(ErrBadFileType) } - method := fmt.Sprintf(APIEndpoint, bot.Token, endpoint) + method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint) req, err := http.NewRequest("POST", method, nil) if err != nil { @@ -490,7 +498,7 @@ func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) (UpdatesChannel, error) { return default: } - + updates, err := bot.GetUpdates(config) if err != nil { log.Println(err) From c915cfd8fcdfbd73c3be604641a5e778592e0d04 Mon Sep 17 00:00:00 2001 From: merothh Date: Fri, 5 Jul 2019 03:42:37 +0530 Subject: [PATCH 15/18] README: fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9325061..bf341d2 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ func main() { ``` There are more examples on the [wiki](https://github.com/go-telegram-bot-api/telegram-bot-api/wiki) -with detailed information on how to do many differen kinds of things. +with detailed information on how to do many different kinds of things. It's a great place to get started on using keyboards, commands, or other kinds of reply markup. From 1f98cd2e470064aba333fce57528582065448889 Mon Sep 17 00:00:00 2001 From: mkishere <224617+mkishere@users.noreply.github.com> Date: Tue, 7 Jan 2020 00:28:13 +0800 Subject: [PATCH 16/18] Add inline venue type --- helpers.go | 14 +++++++++++++- types.go | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/helpers.go b/helpers.go index 3dabe11..c4d236f 100644 --- a/helpers.go +++ b/helpers.go @@ -604,6 +604,18 @@ func NewInlineQueryResultLocation(id, title string, latitude, longitude float64) } } +// NewInlineQueryResultVenue creates a new inline query venue. +func NewInlineQueryResultVenue(id, title, address string, latitude, longitude float64) InlineQueryResultVenue { + return InlineQueryResultVenue{ + Type: "venue", + ID: id, + Title: title, + Address: address, + Latitude: latitude, + Longitude: longitude, + } +} + // NewEditMessageText allows you to edit the text of a message. func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTextConfig { return EditMessageTextConfig{ @@ -622,7 +634,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..319f47f 100644 --- a/types.go +++ b/types.go @@ -827,6 +827,23 @@ type InlineQueryResultLocation struct { 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"` +} + // InlineQueryResultGame is an inline query response game. type InlineQueryResultGame struct { Type string `json:"type"` From 613005ba7b6d21b9362271e69af5f0e584c80ecb Mon Sep 17 00:00:00 2001 From: Konstantin Chukhlomin Date: Sun, 12 Jan 2020 23:54:08 -0500 Subject: [PATCH 17/18] Update types.go Added IsAnimated to Sticker struct --- types.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/types.go b/types.go index 52cb36c..abfb3a9 100644 --- a/types.go +++ b/types.go @@ -338,13 +338,14 @@ 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 + 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 6fcca60571ae7329d7db129d201a297e8ce033b3 Mon Sep 17 00:00:00 2001 From: zhuharev Date: Sat, 15 Feb 2020 16:19:31 +0300 Subject: [PATCH 18/18] Fix old package import --- types_test.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/types_test.go b/types_test.go index c1021bf..0e8ed14 100644 --- a/types_test.go +++ b/types_test.go @@ -190,7 +190,7 @@ func TestChatIsSuperGroup(t *testing.T) { } func TestMessageEntityIsMention(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "mention"} + entity := MessageEntity{Type: "mention"} if !entity.IsMention() { t.Fail() @@ -198,7 +198,7 @@ func TestMessageEntityIsMention(t *testing.T) { } func TestMessageEntityIsHashtag(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "hashtag"} + entity := MessageEntity{Type: "hashtag"} if !entity.IsHashtag() { t.Fail() @@ -206,7 +206,7 @@ func TestMessageEntityIsHashtag(t *testing.T) { } func TestMessageEntityIsBotCommand(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "bot_command"} + entity := MessageEntity{Type: "bot_command"} if !entity.IsCommand() { t.Fail() @@ -214,7 +214,7 @@ func TestMessageEntityIsBotCommand(t *testing.T) { } func TestMessageEntityIsUrl(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "url"} + entity := MessageEntity{Type: "url"} if !entity.IsUrl() { t.Fail() @@ -222,7 +222,7 @@ func TestMessageEntityIsUrl(t *testing.T) { } func TestMessageEntityIsEmail(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "email"} + entity := MessageEntity{Type: "email"} if !entity.IsEmail() { t.Fail() @@ -230,7 +230,7 @@ func TestMessageEntityIsEmail(t *testing.T) { } func TestMessageEntityIsBold(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "bold"} + entity := MessageEntity{Type: "bold"} if !entity.IsBold() { t.Fail() @@ -238,7 +238,7 @@ func TestMessageEntityIsBold(t *testing.T) { } func TestMessageEntityIsItalic(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "italic"} + entity := MessageEntity{Type: "italic"} if !entity.IsItalic() { t.Fail() @@ -246,7 +246,7 @@ func TestMessageEntityIsItalic(t *testing.T) { } func TestMessageEntityIsCode(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "code"} + entity := MessageEntity{Type: "code"} if !entity.IsCode() { t.Fail() @@ -254,7 +254,7 @@ func TestMessageEntityIsCode(t *testing.T) { } func TestMessageEntityIsPre(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "pre"} + entity := MessageEntity{Type: "pre"} if !entity.IsPre() { t.Fail() @@ -262,7 +262,7 @@ func TestMessageEntityIsPre(t *testing.T) { } func TestMessageEntityIsTextLink(t *testing.T) { - entity := tgbotapi.MessageEntity{Type: "text_link"} + entity := MessageEntity{Type: "text_link"} if !entity.IsTextLink() { t.Fail()