diff --git a/api.go b/api.go
index 1167e7a..d9f3b4f 100644
--- a/api.go
+++ b/api.go
@@ -139,7 +139,7 @@ func (b *Bot) sendText(to Recipient, text string, opt *SendOptions) (*Message, e
"chat_id": to.Recipient(),
"text": text,
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
data, err := b.Raw("sendMessage", params)
if err != nil {
diff --git a/bot.go b/bot.go
index 0ddad3e..17e114d 100644
--- a/bot.go
+++ b/bot.go
@@ -38,6 +38,7 @@ func NewBot(pref Settings) (*Bot, error) {
handlers: make(map[string]interface{}),
synchronous: pref.Synchronous,
verbose: pref.Verbose,
+ parseMode: pref.ParseMode,
stop: make(chan struct{}),
reporter: pref.Reporter,
client: client,
@@ -67,6 +68,7 @@ type Bot struct {
handlers map[string]interface{}
synchronous bool
verbose bool
+ parseMode ParseMode
reporter func(error)
stop chan struct{}
client *http.Client
@@ -95,6 +97,11 @@ type Settings struct {
// Shows upcoming requests
Verbose bool
+ // ParseMode used to set default parse mode of all sent messages.
+ // It attaches to every send, edit or whatever method. You also
+ // will be able to override the default mode by passing a new one.
+ ParseMode ParseMode
+
// Reporter is a callback function that will get called
// on any panics recovered from endpoint handlers.
Reporter func(error)
@@ -524,7 +531,7 @@ func (b *Bot) Send(to Recipient, what interface{}, options ...interface{}) (*Mes
// SendAlbum sends multiple instances of media as a single message.
//
-// From all existing options, it only supports tb.Silent option.
+// From all existing options, it only supports tb.Silent.
func (b *Bot) SendAlbum(to Recipient, a Album, options ...interface{}) ([]Message, error) {
if to == nil {
return nil, ErrBadRecipient
@@ -596,7 +603,7 @@ func (b *Bot) SendAlbum(to Recipient, a Album, options ...interface{}) ([]Messag
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
data, err := b.sendFiles("sendMediaGroup", files, params)
if err != nil {
@@ -655,7 +662,7 @@ func (b *Bot) Forward(to Recipient, msg Editable, options ...interface{}) (*Mess
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
data, err := b.Raw("forwardMessage", params)
if err != nil {
@@ -667,11 +674,16 @@ func (b *Bot) Forward(to Recipient, msg Editable, options ...interface{}) (*Mess
// Edit is magic, it lets you change already sent message.
//
+// If edited message is sent by the bot, returns it,
+// otherwise returns nil and ErrTrueResult.
+//
// Use cases:
//
-// b.Edit(msg, msg.Text, newMarkup)
-// b.Edit(msg, "new text", tb.ModeHTML)
-// b.Edit(msg, tb.Location{42.1337, 69.4242})
+// b.Edit(m, m.Text, newMarkup)
+// b.Edit(m, "new text", tb.ModeHTML)
+// b.Edit(m, &tb.ReplyMarkup{...})
+// b.Edit(m, &tb.Photo{File: ...})
+// b.Edit(m, tb.Location{42.1337, 69.4242})
//
// This function will panic upon nil Editable.
func (b *Bot) Edit(msg Editable, what interface{}, options ...interface{}) (*Message, error) {
@@ -681,6 +693,10 @@ func (b *Bot) Edit(msg Editable, what interface{}, options ...interface{}) (*Mes
)
switch v := what.(type) {
+ case *ReplyMarkup:
+ return b.EditReplyMarkup(msg, v)
+ case InputMedia:
+ return b.EditMedia(msg, v, options...)
case string:
method = "editMessageText"
params["text"] = v
@@ -702,7 +718,7 @@ func (b *Bot) Edit(msg Editable, what interface{}, options ...interface{}) (*Mes
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
data, err := b.Raw(method, params)
if err != nil {
@@ -715,6 +731,9 @@ func (b *Bot) Edit(msg Editable, what interface{}, options ...interface{}) (*Mes
// EditReplyMarkup edits reply markup of already sent message.
// Pass nil or empty ReplyMarkup to delete it from the message.
//
+// If edited message is sent by the bot, returns it,
+// otherwise returns nil and ErrTrueResult.
+//
// On success, returns edited message object.
// This function will panic upon nil Editable.
func (b *Bot) EditReplyMarkup(msg Editable, markup *ReplyMarkup) (*Message, error) {
@@ -747,6 +766,9 @@ func (b *Bot) EditReplyMarkup(msg Editable, markup *ReplyMarkup) (*Message, erro
// EditCaption edits already sent photo caption with known recipient and message id.
//
+// If edited message is sent by the bot, returns it,
+// otherwise returns nil and ErrTrueResult.
+//
// On success, returns edited message object.
// This function will panic upon nil Editable.
func (b *Bot) EditCaption(msg Editable, caption string, options ...interface{}) (*Message, error) {
@@ -764,7 +786,7 @@ func (b *Bot) EditCaption(msg Editable, caption string, options ...interface{})
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
data, err := b.Raw("editMessageCaption", params)
if err != nil {
@@ -776,10 +798,13 @@ func (b *Bot) EditCaption(msg Editable, caption string, options ...interface{})
// EditMedia edits already sent media with known recipient and message id.
//
+// If edited message is sent by the bot, returns it,
+// otherwise returns nil and ErrTrueResult.
+//
// Use cases:
//
-// bot.EditMedia(msg, &tb.Photo{File: tb.FromDisk("chicken.jpg")})
-// bot.EditMedia(msg, &tb.Video{File: tb.FromURL("http://video.mp4")})
+// b.EditMedia(m, &tb.Photo{File: tb.FromDisk("chicken.jpg")})
+// b.EditMedia(m, &tb.Video{File: tb.FromURL("http://video.mp4")})
//
// This function will panic upon nil Editable.
func (b *Bot) EditMedia(msg Editable, media InputMedia, options ...interface{}) (*Message, error) {
@@ -875,7 +900,7 @@ func (b *Bot) EditMedia(msg Editable, media InputMedia, options ...interface{})
params := make(map[string]string)
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
if sendOpts != nil {
result.ParseMode = sendOpts.ParseMode
@@ -888,7 +913,7 @@ func (b *Bot) EditMedia(msg Editable, media InputMedia, options ...interface{})
data, _ := json.Marshal(result)
params["media"] = string(data)
- if chatID == 0 { // If inline message.
+ if chatID == 0 { // if inline message
params["inline_message_id"] = msgID
} else {
params["chat_id"] = strconv.FormatInt(chatID, 10)
@@ -1121,6 +1146,9 @@ func (b *Bot) GetFile(file *File) (io.ReadCloser, error) {
// StopLiveLocation stops broadcasting live message location
// before Location.LivePeriod expires.
//
+// If the message is sent by the bot, returns it,
+// otherwise returns nil and ErrTrueResult.
+//
// It supports tb.ReplyMarkup.
// This function will panic upon nil Editable.
func (b *Bot) StopLiveLocation(msg Editable, options ...interface{}) (*Message, error) {
@@ -1132,7 +1160,7 @@ func (b *Bot) StopLiveLocation(msg Editable, options ...interface{}) (*Message,
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
data, err := b.Raw("stopMessageLiveLocation", params)
if err != nil {
@@ -1156,7 +1184,7 @@ func (b *Bot) StopPoll(msg Editable, options ...interface{}) (*Poll, error) {
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
data, err := b.Raw("stopPoll", params)
if err != nil {
@@ -1289,7 +1317,7 @@ func (b *Bot) Pin(msg Editable, options ...interface{}) error {
}
sendOpts := extractOptions(options)
- embedSendOptions(params, sendOpts)
+ b.embedSendOptions(params, sendOpts)
_, err := b.Raw("pinChatMessage", params)
return err
diff --git a/bot_test.go b/bot_test.go
index 7b21fae..73712ad 100644
--- a/bot_test.go
+++ b/bot_test.go
@@ -63,6 +63,7 @@ func TestNewBot(t *testing.T) {
pref.Client = client
pref.Poller = &LongPoller{Timeout: time.Second}
pref.Updates = 50
+ pref.ParseMode = ModeHTML
pref.offline = true
b, err = NewBot(pref)
@@ -71,6 +72,7 @@ func TestNewBot(t *testing.T) {
assert.Equal(t, pref.URL, b.URL)
assert.Equal(t, pref.Poller, b.Poller)
assert.Equal(t, 50, cap(b.Updates))
+ assert.Equal(t, ModeHTML, b.parseMode)
}
func TestBotHandle(t *testing.T) {
@@ -309,23 +311,36 @@ func TestBot(t *testing.T) {
_, err = b.Forward(nil, nil)
assert.Equal(t, ErrBadRecipient, err)
- t.Run("Send(what=Sendable)", func(t *testing.T) {
- photo := &Photo{
- File: File{FileID: photoID},
- Caption: t.Name(),
- }
+ photo := &Photo{
+ File: File{FileID: photoID},
+ Caption: t.Name(),
+ }
+ var msg *Message
- msg, err := b.Send(to, photo)
+ t.Run("Send(what=Sendable)", func(t *testing.T) {
+ msg, err = b.Send(to, photo)
assert.NoError(t, err)
assert.NotNil(t, msg.Photo)
assert.Equal(t, photo.Caption, msg.Caption)
+ })
+
+ t.Run("EditCaption()+ParseMode", func(t *testing.T) {
+ b.parseMode = ModeHTML
+ edited, err := b.EditCaption(msg, "new caption with parse mode")
+ assert.NoError(t, err)
+ assert.Equal(t, "new caption with parse mode", edited.Caption)
- msg, err = b.EditCaption(msg, "new caption")
+ b.parseMode = ModeDefault
+ edited, err = b.EditCaption(msg, "*new caption w/o parse mode*", ModeMarkdown)
assert.NoError(t, err)
- assert.Equal(t, "new caption", msg.Caption)
+ assert.Equal(t, "new caption w/o parse mode", edited.Caption)
})
- var msg *Message
+ t.Run("Edit(what=InputMedia)", func(t *testing.T) {
+ edited, err := b.Edit(msg, photo)
+ assert.NoError(t, err)
+ assert.Equal(t, edited.Photo.FileID, photo.FileID)
+ })
t.Run("Send(what=string)", func(t *testing.T) {
msg, err = b.Send(to, t.Name())
@@ -358,20 +373,8 @@ func TestBot(t *testing.T) {
assert.Error(t, err) // message is not modified
})
- t.Run("Edit(what=Location)", func(t *testing.T) {
- loc := &Location{Lat: 42, Lng: 69, LivePeriod: 60}
- msg, err := b.Send(to, loc)
- assert.NoError(t, err)
- assert.NotNil(t, msg.Location)
-
- loc = &Location{Lat: loc.Lng, Lng: loc.Lat}
- msg, err = b.Edit(msg, *loc)
- assert.NoError(t, err)
- assert.NotNil(t, msg.Location)
- })
-
- t.Run("EditReplyMarkup()", func(t *testing.T) {
- markup := &ReplyMarkup{
+ t.Run("Edit(what=ReplyMarkup)", func(t *testing.T) {
+ good := &ReplyMarkup{
InlineKeyboard: [][]InlineButton{
{{
Data: "btn",
@@ -379,7 +382,7 @@ func TestBot(t *testing.T) {
}},
},
}
- badMarkup := &ReplyMarkup{
+ bad := &ReplyMarkup{
InlineKeyboard: [][]InlineButton{
{{
Data: strings.Repeat("*", 65),
@@ -388,18 +391,30 @@ func TestBot(t *testing.T) {
},
}
- msg, err := b.EditReplyMarkup(msg, markup)
+ edited, err := b.Edit(msg, good)
assert.NoError(t, err)
- assert.Equal(t, msg.ReplyMarkup.InlineKeyboard, markup.InlineKeyboard)
+ assert.Equal(t, edited.ReplyMarkup.InlineKeyboard, good.InlineKeyboard)
- msg, err = b.EditReplyMarkup(msg, nil)
+ edited, err = b.EditReplyMarkup(edited, nil)
assert.NoError(t, err)
- assert.Nil(t, msg.ReplyMarkup.InlineKeyboard)
+ assert.Nil(t, edited.ReplyMarkup.InlineKeyboard)
- _, err = b.EditReplyMarkup(msg, badMarkup)
+ _, err = b.Edit(edited, bad)
assert.Equal(t, ErrButtonDataInvalid, err)
})
+ t.Run("Edit(what=Location)", func(t *testing.T) {
+ loc := &Location{Lat: 42, Lng: 69, LivePeriod: 60}
+ edited, err := b.Send(to, loc)
+ assert.NoError(t, err)
+ assert.NotNil(t, edited.Location)
+
+ loc = &Location{Lat: loc.Lng, Lng: loc.Lat}
+ edited, err = b.Edit(edited, *loc)
+ assert.NoError(t, err)
+ assert.NotNil(t, edited.Location)
+ })
+
t.Run("Notify()", func(t *testing.T) {
assert.Equal(t, ErrBadRecipient, b.Notify(nil, Typing))
assert.NoError(t, b.Notify(to, Typing))
diff --git a/filters.go b/filters.go
deleted file mode 100644
index 7384fff..0000000
--- a/filters.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package telebot
-
-// Filter is some thing that does filtering for
-// incoming updates.
-//
-// Return false if you wish to sieve the update out.
-type Filter interface {
- Filter(*Update) bool
-}
-
-// FilterFunc is basically a lightweight version of Filter.
-type FilterFunc func(*Update) bool
-
-func NewChain(parent Poller) *Chain {
- c := &Chain{}
- c.Poller = parent
- c.Filter = func(upd *Update) bool {
- for _, filter := range c.Filters {
- switch f := filter.(type) {
- case Filter:
- if !f.Filter(upd) {
- return false
- }
-
- case FilterFunc:
- if !f(upd) {
- return false
- }
-
- case func(*Update) bool:
- if !f(upd) {
- return false
- }
- }
-
- }
-
- return true
- }
-
- return c
-}
-
-// Chain is a chain of middle
-type Chain struct {
- MiddlewarePoller
-
- // (Filter | FilterFunc | func(*Update) bool)
- Filters []interface{}
-}
-
-// Add accepts either Filter interface or FilterFunc
-func (c *Chain) Add(filter interface{}) {
- switch filter.(type) {
- case Filter:
- break
- case FilterFunc:
- break
- case func(*Update) bool:
- break
- default:
- panic("telebot: unsupported filter type")
- }
-
- c.Filters = append(c.Filters, filter)
-}
diff --git a/games.go b/games.go
index 96292d1..cceba14 100644
--- a/games.go
+++ b/games.go
@@ -70,11 +70,8 @@ func (b *Bot) GetGameScores(user Recipient, msg Editable) ([]GameHighScore, erro
// SetGameScore sets the score of the specified user in a game.
//
-// NOTE:
-// If the message was sent by the bot, returns the edited Message,
-// otherwise returns nil Message and ErrNoGameMessage.
-// If you expect successful True result, you must check
-// for `telebot: no game message` error.
+// If the message was sent by the bot, returns the edited Message,
+// otherwise returns nil and ErrTrueResult.
//
func (b *Bot) SetGameScore(user Recipient, msg Editable, score GameHighScore) (*Message, error) {
msgID, chatID := msg.MessageSig()
@@ -97,13 +94,5 @@ func (b *Bot) SetGameScore(user Recipient, msg Editable, score GameHighScore) (*
if err != nil {
return nil, err
}
-
- m, err := extractMessage(data)
- if err != nil {
- return nil, err
- }
- if m == nil {
- return nil, ErrNoGameMessage
- }
- return m, nil
+ return extractMessage(data)
}
diff --git a/inline_types.go b/inline_types.go
index 5d542af..cd745eb 100644
--- a/inline_types.go
+++ b/inline_types.go
@@ -182,6 +182,13 @@ type GifResult struct {
// Optional. Duration of the GIF.
Duration int `json:"gif_duration,omitempty"`
+ // URL of the static thumbnail for the result (jpeg or gif).
+ ThumbURL string `json:"thumb_url"`
+
+ // Optional. MIME type of the thumbnail, must be one of
+ // “image/jpeg”, “image/gif”, or “video/mp4”.
+ ThumbMIME string `json:"thumb_mime_type,omitempty"`
+
// Optional. Title for the result.
Title string `json:"title,omitempty"`
@@ -192,9 +199,6 @@ type GifResult struct {
// bold, italic, fixed-width text or inline URLs in the media caption.
ParseMode ParseMode `json:"parse_mode,omitempty"`
- // URL of the static thumbnail for the result (jpeg or gif).
- ThumbURL string `json:"thumb_url"`
-
// If Cache != "", it'll be used instead
Cache string `json:"gif_file_id,omitempty"`
}
@@ -234,6 +238,10 @@ type Mpeg4GifResult struct {
// URL of the static thumbnail (jpeg or gif) for the result.
ThumbURL string `json:"thumb_url,omitempty"`
+ // Optional. MIME type of the thumbnail, must be one of
+ // “image/jpeg”, “image/gif”, or “video/mp4”.
+ ThumbMIME string `json:"thumb_mime_type,omitempty"`
+
// Optional. Title for the result.
Title string `json:"title,omitempty"`
diff --git a/message.go b/message.go
index 8877642..e314c1a 100644
--- a/message.go
+++ b/message.go
@@ -37,6 +37,9 @@ type Message struct {
// itself is a reply.
ReplyTo *Message `json:"reply_to_message"`
+ // Shows through which bot the message was sent.
+ Via *User `json:"via_bot"`
+
// (Optional) Time of last edit in Unix
LastEdit int64 `json:"edit_date"`
diff --git a/sendable.go b/sendable.go
index 5816d72..0ec8150 100644
--- a/sendable.go
+++ b/sendable.go
@@ -30,7 +30,7 @@ func (p *Photo) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
"caption": p.Caption,
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&p.File, "photo", params, nil)
if err != nil {
@@ -58,7 +58,7 @@ func (a *Audio) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params["duration"] = strconv.Itoa(a.Duration)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&a.File, "audio", params, thumbnailToFilemap(a.Thumbnail))
if err != nil {
@@ -91,7 +91,7 @@ func (d *Document) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error
params["file_size"] = strconv.Itoa(d.FileSize)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&d.File, "document", params, thumbnailToFilemap(d.Thumbnail))
if err != nil {
@@ -110,7 +110,7 @@ func (s *Sticker) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error)
params := map[string]string{
"chat_id": to.Recipient(),
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&s.File, "sticker", params, nil)
if err != nil {
@@ -144,7 +144,7 @@ func (v *Video) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params["supports_streaming"] = "true"
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&v.File, "video", params, thumbnailToFilemap(v.Thumbnail))
if err != nil {
@@ -191,7 +191,7 @@ func (a *Animation) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, erro
params["file_name"] = filepath.Base(a.File.FileLocal)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&a.File, "animation", params, nil)
if err != nil {
@@ -215,7 +215,7 @@ func (v *Voice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
params["duration"] = strconv.Itoa(v.Duration)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&v.File, "voice", params, nil)
if err != nil {
@@ -241,7 +241,7 @@ func (v *VideoNote) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, erro
params["length"] = strconv.Itoa(v.Length)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
msg, err := b.sendObject(&v.File, "videoNote", params, thumbnailToFilemap(v.Thumbnail))
if err != nil {
@@ -262,7 +262,7 @@ func (x *Location) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error
"longitude": fmt.Sprintf("%f", x.Lng),
"live_period": strconv.Itoa(x.LivePeriod),
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
data, err := b.Raw("sendLocation", params)
if err != nil {
@@ -283,7 +283,7 @@ func (v *Venue) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
"foursquare_id": v.FoursquareID,
"foursquare_type": v.FoursquareType,
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
data, err := b.Raw("sendVenue", params)
if err != nil {
@@ -329,7 +329,7 @@ func (i *Invoice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error)
data, _ := json.Marshal(i.Prices)
params["prices"] = string(data)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
data, err := b.Raw("sendInvoice", params)
if err != nil {
@@ -359,7 +359,7 @@ func (p *Poll) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
} else if p.CloseUnixdate != 0 {
params["close_date"] = strconv.FormatInt(p.CloseUnixdate, 10)
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
var options []string
for _, o := range p.Options {
@@ -382,7 +382,7 @@ func (d *Dice) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
"chat_id": to.Recipient(),
"emoji": string(d.Type),
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
data, err := b.Raw("sendDice", params)
if err != nil {
@@ -398,7 +398,7 @@ func (g *Game) Send(b *Bot, to Recipient, opt *SendOptions) (*Message, error) {
"chat_id": to.Recipient(),
"game_short_name": g.Title,
}
- embedSendOptions(params, opt)
+ b.embedSendOptions(params, opt)
data, err := b.Raw("sendGame", params)
if err != nil {
diff --git a/stickers.go b/stickers.go
index d6c8cdc..2d878ba 100644
--- a/stickers.go
+++ b/stickers.go
@@ -13,11 +13,7 @@ type Sticker struct {
Animated bool `json:"is_animated"`
Thumbnail *Photo `json:"thumb"`
Emoji string `json:"emoji"`
- Name string `json:"name"`
SetName string `json:"set_name"`
- PNG *File `json:"png_sticker"`
- TGS *File `json:"tgs_file"`
- Emojis string `json:"emojis"`
MaskPosition *MaskPosition `json:"mask_position"`
}
@@ -26,12 +22,12 @@ type StickerSet struct {
Name string `json:"name"`
Title string `json:"title"`
Animated bool `json:"is_animated"`
- ContainsMasks bool `json:"contains_masks"`
Stickers []Sticker `json:"stickers"`
Thumbnail *Photo `json:"thumb"`
PNG *File `json:"png_sticker"`
- TGS *File `json:"tgs_file"`
+ TGS *File `json:"tgs_sticker"`
Emojis string `json:"emojis"`
+ ContainsMasks bool `json:"contains_masks"`
MaskPosition *MaskPosition `json:"mask_position"`
}
@@ -44,15 +40,6 @@ type MaskPosition struct {
Scale float32 `json:"scale"`
}
-// StickerSetParams describes the payload in creating new sticker set api-method.
-type StickerSetParams struct {
- UserID int
- Name string
- Title string
- PngSticker *File
- Emojis string
-}
-
// UploadStickerFile uploads a .PNG file with a sticker for later use.
func (b *Bot) UploadStickerFile(to Recipient, png *File) (*File, error) {
files := map[string]File{
@@ -123,7 +110,7 @@ func (b *Bot) CreateNewStickerSet(to Recipient, s StickerSet) error {
}
// AddStickerToSet adds new sticker to existing sticker set.
-func (b *Bot) AddStickerToSet(to Recipient, s Sticker) error {
+func (b *Bot) AddStickerToSet(to Recipient, s StickerSet) error {
files := make(map[string]File)
if s.PNG != nil {
files["png_sticker"] = *s.PNG
@@ -176,7 +163,7 @@ func (b *Bot) DeleteStickerFromSet(sticker string) error {
//
// Animated sticker set thumbnail can't be uploaded via HTTP URL.
//
-func (b *Bot) SetStickerSetThumb(to Recipient, s Sticker) error {
+func (b *Bot) SetStickerSetThumb(to Recipient, s StickerSet) error {
files := map[string]File{}
if s.PNG != nil {
files["thumb"] = *s.PNG
diff --git a/telebot.go b/telebot.go
index be4c864..c5a1ceb 100644
--- a/telebot.go
+++ b/telebot.go
@@ -34,7 +34,7 @@ var (
ErrBadRecipient = errors.New("telebot: recipient is nil")
ErrUnsupportedWhat = errors.New("telebot: unsupported what argument")
ErrCouldNotUpdate = errors.New("telebot: could not fetch new updates")
- ErrNoGameMessage = errors.New("telebot: no game message")
+ ErrTrueResult = errors.New("telebot: result is True")
)
const DefaultApiURL = "https://api.telegram.org"
@@ -218,4 +218,5 @@ type DiceType string
var (
Cube = &Dice{Type: "🎲"}
Dart = &Dice{Type: "🎯"}
+ Ball = &Dice{Type: "🏀"}
)
diff --git a/util.go b/util.go
index eae707c..ba81e1a 100644
--- a/util.go
+++ b/util.go
@@ -70,6 +70,15 @@ func extractMessage(data []byte) (*Message, error) {
Result *Message
}
if err := json.Unmarshal(data, &resp); err != nil {
+ var resp struct {
+ Result bool
+ }
+ if err := json.Unmarshal(data, &resp); err != nil {
+ return nil, wrapError(err)
+ }
+ if resp.Result {
+ return nil, ErrTrueResult
+ }
return nil, wrapError(err)
}
return resp.Result, nil
@@ -123,7 +132,11 @@ func extractOptions(how []interface{}) *SendOptions {
return opts
}
-func embedSendOptions(params map[string]string, opt *SendOptions) {
+func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) {
+ if b.parseMode != ModeDefault {
+ params["parse_mode"] = b.parseMode
+ }
+
if opt == nil {
return
}
diff --git a/util_test.go b/util_test.go
index 2272cdf..0837dec 100644
--- a/util_test.go
+++ b/util_test.go
@@ -13,6 +13,16 @@ func TestExtractOk(t *testing.T) {
data = []byte(`{"ok":false,"error_code":429,"description":"Too Many Requests: retry after 8","parameters":{"retry_after":8}}`)
assert.Error(t, extractOk(data))
- data = []byte(`{"ok":false,"error_code":400,"description":"Bad Request: reply message not found"}`) // Also check the old format
+ data = []byte(`{"ok":false,"error_code":400,"description":"Bad Request: reply message not found"}`)
assert.EqualError(t, extractOk(data), ErrToReplyNotFound.Error())
}
+
+func TestExtractMessage(t *testing.T) {
+ data := []byte(`{"ok":true,"result":true}`)
+ _, err := extractMessage(data)
+ assert.Equal(t, ErrTrueResult, err)
+
+ data = []byte(`{"ok":true,"result":{"foo":"bar"}}`)
+ _, err = extractMessage(data)
+ assert.NoError(t, err)
+}
diff --git a/webhook.go b/webhook.go
index a17a1c0..e3f953a 100644
--- a/webhook.go
+++ b/webhook.go
@@ -17,9 +17,9 @@ type WebhookTLS struct {
// A WebhookEndpoint describes the endpoint to which telegram will send its requests.
// This must be a public URL and can be a loadbalancer or something similar. If the
-// endpoint uses TLS and the certificate is selfsigned you have to add the certificate
+// endpoint uses TLS and the certificate is self-signed you have to add the certificate
// path of this certificate so telegram will trust it. This field can be ignored if you
-// have a trusted certifcate (letsencrypt, ...).
+// have a trusted certificate (letsencrypt, ...).
type WebhookEndpoint struct {
PublicURL string
Cert string
@@ -28,13 +28,16 @@ type WebhookEndpoint struct {
// A Webhook configures the poller for webhooks. It opens a port on the given
// listen address. If TLS is filled, the listener will use the key and cert to open
// a secure port. Otherwise it will use plain HTTP.
+//
// If you have a loadbalancer ore other infrastructure in front of your service, you
// must fill the Endpoint structure so this poller will send this data to telegram. If
// you leave these values empty, your local address will be sent to telegram which is mostly
// not what you want (at least while developing). If you have a single instance of your
// bot you should consider to use the LongPoller instead of a WebHook.
+//
// You can also leave the Listen field empty. In this case it is up to the caller to
// add the Webhook to a http-mux.
+//
type Webhook struct {
Listen string `json:"url"`
MaxConnections int `json:"max_connections"`