2015-06-26 07:34:10 +00:00
|
|
|
package telebot
|
|
|
|
|
|
|
|
import (
|
2015-07-03 18:54:40 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
2015-06-26 07:34:10 +00:00
|
|
|
"time"
|
2017-08-15 13:44:01 +00:00
|
|
|
|
2017-08-15 15:00:22 +00:00
|
|
|
"github.com/armon/go-radix"
|
2017-08-15 13:44:01 +00:00
|
|
|
"github.com/pkg/errors"
|
2015-06-26 07:34:10 +00:00
|
|
|
)
|
|
|
|
|
2015-06-27 15:44:12 +00:00
|
|
|
// Bot represents a separate Telegram bot instance.
|
2015-06-26 07:34:10 +00:00
|
|
|
type Bot struct {
|
2016-04-21 20:31:30 +00:00
|
|
|
Token string
|
|
|
|
Identity User
|
|
|
|
Messages chan Message
|
|
|
|
Queries chan Query
|
|
|
|
Callbacks chan Callback
|
2017-08-15 13:44:01 +00:00
|
|
|
|
|
|
|
// Telebot debugging channel. If present, Telebot
|
|
|
|
// will use it to report all occuring errors.
|
|
|
|
Errors chan error
|
2017-08-15 15:00:22 +00:00
|
|
|
|
|
|
|
tree *radix.Tree
|
2015-06-26 07:34:10 +00:00
|
|
|
}
|
|
|
|
|
2015-07-03 18:54:40 +00:00
|
|
|
// NewBot does try to build a Bot with token `token`, which
|
|
|
|
// is a secret API key assigned to particular bot.
|
|
|
|
func NewBot(token string) (*Bot, error) {
|
2017-08-15 15:00:22 +00:00
|
|
|
bot := &Bot{
|
|
|
|
Token: token,
|
|
|
|
tree: radix.New(),
|
|
|
|
}
|
2017-08-15 13:44:01 +00:00
|
|
|
|
|
|
|
user, err := bot.getMe()
|
2015-07-03 18:54:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-08-15 13:44:01 +00:00
|
|
|
bot.Identity = user
|
|
|
|
return bot, nil
|
2015-07-03 18:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-08-15 13:44:01 +00:00
|
|
|
// Listen starts a new polling goroutine, one that periodically looks for
|
|
|
|
// updates and delivers new messages to the subscription channel.
|
2016-01-22 11:38:45 +00:00
|
|
|
func (b *Bot) Listen(subscription chan Message, timeout time.Duration) {
|
2016-04-21 20:31:30 +00:00
|
|
|
go b.poll(subscription, nil, nil, timeout)
|
2016-01-22 11:38:45 +00:00
|
|
|
}
|
|
|
|
|
2017-08-15 13:44:01 +00:00
|
|
|
// Start periodically polls messages, updates and callbacks into their
|
|
|
|
// corresponding channels of the bot object.
|
|
|
|
//
|
|
|
|
// NOTE: It's a blocking method!
|
2016-01-22 11:38:45 +00:00
|
|
|
func (b *Bot) Start(timeout time.Duration) {
|
2016-04-21 20:31:30 +00:00
|
|
|
b.poll(b.Messages, b.Queries, b.Callbacks, timeout)
|
2016-01-22 11:38:45 +00:00
|
|
|
}
|
2015-11-16 10:22:37 +00:00
|
|
|
|
2017-08-15 13:44:01 +00:00
|
|
|
func (b *Bot) debug(err error) {
|
|
|
|
if b.Errors != nil {
|
|
|
|
b.Errors <- errors.WithStack(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-22 11:38:45 +00:00
|
|
|
func (b *Bot) poll(
|
|
|
|
messages chan Message,
|
|
|
|
queries chan Query,
|
2016-04-21 20:31:30 +00:00
|
|
|
callbacks chan Callback,
|
2016-01-22 11:38:45 +00:00
|
|
|
timeout time.Duration,
|
|
|
|
) {
|
2016-11-10 19:34:02 +00:00
|
|
|
var latestUpdate int64
|
2016-01-22 11:38:45 +00:00
|
|
|
|
|
|
|
for {
|
2017-08-15 13:44:01 +00:00
|
|
|
updates, err := b.getUpdates(latestUpdate+1, timeout)
|
2016-01-22 11:38:45 +00:00
|
|
|
|
|
|
|
if err != nil {
|
2017-08-15 13:44:01 +00:00
|
|
|
b.debug(errors.Wrap(err, "getUpdates() failed"))
|
2016-01-22 11:38:45 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, update := range updates {
|
2016-04-21 20:31:30 +00:00
|
|
|
if update.Payload != nil /* if message */ {
|
2016-01-22 11:38:45 +00:00
|
|
|
if messages == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2016-04-21 20:31:30 +00:00
|
|
|
messages <- *update.Payload
|
|
|
|
} else if update.Query != nil /* if query */ {
|
2016-01-22 11:38:45 +00:00
|
|
|
if queries == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
queries <- *update.Query
|
2016-04-21 20:31:30 +00:00
|
|
|
} else if update.Callback != nil {
|
|
|
|
if callbacks == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
callbacks <- *update.Callback
|
2015-06-27 10:30:25 +00:00
|
|
|
}
|
2016-01-22 11:38:45 +00:00
|
|
|
|
|
|
|
latestUpdate = update.ID
|
2015-06-26 07:34:10 +00:00
|
|
|
}
|
2016-01-22 11:38:45 +00:00
|
|
|
}
|
2015-06-26 07:34:10 +00:00
|
|
|
}
|
2015-06-26 16:12:54 +00:00
|
|
|
|
2017-11-18 13:06:20 +00:00
|
|
|
func (b *Bot) sendText(to Recipient, text string, opt *SendOptions) (*Message, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": to.Destination(),
|
|
|
|
"text": text,
|
|
|
|
}
|
|
|
|
embedSendOptions(params, opt)
|
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("sendMessage", params)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return extractMsgResponse(respJSON)
|
|
|
|
}
|
|
|
|
|
2017-11-17 14:29:44 +00:00
|
|
|
// Send accepts 2+ arguments, starting with destination chat, followed by
|
|
|
|
// some Sendable (or string!) and optional send options.
|
|
|
|
//
|
|
|
|
// Note: since most arguments are of type interface{}, make sure to pass
|
|
|
|
// them by-pointer, NOT by-value, which will result in a panic.
|
|
|
|
//
|
|
|
|
// What is a send option exactly? It can be one of the following types:
|
|
|
|
//
|
|
|
|
// - Option (a shorcut flag for popular options)
|
|
|
|
// - *SendOptions (the actual object accepted by Telegram API)
|
|
|
|
// - *ReplyMarkup (a component of SendOptions)
|
|
|
|
// - ParseMode (HTML, Markdown, etc)
|
|
|
|
//
|
|
|
|
// This function will panic upon unsupported payloads and options!
|
2017-11-17 06:20:36 +00:00
|
|
|
func (b *Bot) Send(to Recipient, what interface{}, how ...interface{}) (*Message, error) {
|
|
|
|
options := extractOptions(how)
|
2015-07-06 13:46:19 +00:00
|
|
|
|
2017-11-17 06:20:36 +00:00
|
|
|
switch object := what.(type) {
|
|
|
|
case string:
|
|
|
|
return b.sendText(to, object, options)
|
|
|
|
case Sendable:
|
|
|
|
return object.Send(b, to, options)
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("telebot: object %v is not Sendable", object))
|
2015-07-03 18:54:40 +00:00
|
|
|
}
|
2015-06-26 16:12:54 +00:00
|
|
|
}
|
2015-07-02 09:05:50 +00:00
|
|
|
|
2017-11-17 14:29:44 +00:00
|
|
|
// Reply behaves just like Send() with an exception of "reply-to" indicator.
|
|
|
|
//
|
|
|
|
// This function will panic upon unsupported payloads and options!
|
2017-11-17 06:20:36 +00:00
|
|
|
func (b *Bot) Reply(to *Message, what interface{}, how ...interface{}) (*Message, error) {
|
|
|
|
options := extractOptions(how)
|
|
|
|
if options == nil {
|
|
|
|
options = &SendOptions{}
|
2015-07-03 18:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-11-17 06:20:36 +00:00
|
|
|
options.ReplyTo = to
|
2015-07-03 18:54:40 +00:00
|
|
|
|
2017-11-17 06:20:36 +00:00
|
|
|
return b.Send(to.Chat, what, options)
|
2015-07-02 09:05:50 +00:00
|
|
|
}
|
2015-07-02 18:39:39 +00:00
|
|
|
|
2017-11-17 14:29:44 +00:00
|
|
|
// Forward behaves just like Send() but of all options it
|
|
|
|
// only supports Silent (see Bots API).
|
|
|
|
//
|
|
|
|
// This function will panic upon unsupported payloads and options!
|
2017-11-17 06:20:36 +00:00
|
|
|
func (b *Bot) Forward(to Recipient, what *Message, how ...interface{}) (*Message, error) {
|
2016-06-26 14:05:37 +00:00
|
|
|
params := map[string]string{
|
2017-11-17 06:20:36 +00:00
|
|
|
"chat_id": to.Destination(),
|
|
|
|
"from_chat_id": strconv.Itoa(what.Origin().ID),
|
|
|
|
"message_id": strconv.Itoa(what.ID),
|
2015-07-06 13:46:19 +00:00
|
|
|
}
|
|
|
|
|
2017-11-17 06:20:36 +00:00
|
|
|
options := extractOptions(how)
|
|
|
|
if options == nil {
|
|
|
|
options = &SendOptions{}
|
2015-07-03 18:54:40 +00:00
|
|
|
}
|
2017-11-17 06:20:36 +00:00
|
|
|
embedSendOptions(params, options)
|
2015-07-03 18:54:40 +00:00
|
|
|
|
2017-11-17 06:20:36 +00:00
|
|
|
respJSON, err := b.sendCommand("forwardMessage", params)
|
2015-07-03 18:54:40 +00:00
|
|
|
if err != nil {
|
2017-01-12 00:48:11 +00:00
|
|
|
return nil, err
|
2015-07-03 18:54:40 +00:00
|
|
|
}
|
|
|
|
|
2017-11-17 06:20:36 +00:00
|
|
|
return extractMsgResponse(respJSON)
|
2016-05-24 04:43:16 +00:00
|
|
|
}
|
2016-07-04 10:56:53 +00:00
|
|
|
|
2017-11-17 14:29:44 +00:00
|
|
|
// Delete removes the message, including service messages,
|
|
|
|
// with the following limitations:
|
|
|
|
//
|
|
|
|
// - A message can only be deleted if it was sent less than 48 hours ago.
|
|
|
|
// - Bots can delete outgoing messages in groups and supergroups.
|
|
|
|
// - Bots granted can_post_messages permissions can delete outgoing
|
|
|
|
// messages in channels.
|
|
|
|
// - If the bot is an administrator of a group, it can delete any message there.
|
|
|
|
// - If the bot has can_delete_messages permission in a supergroup or a
|
|
|
|
// channel, it can delete any message there.
|
2017-11-17 07:22:16 +00:00
|
|
|
func (b *Bot) Delete(what *Message) error {
|
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": what.Chat.Destination(),
|
|
|
|
"message_id": strconv.Itoa(what.ID),
|
|
|
|
}
|
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("deleteMessage", params)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return extractOkResponse(respJSON)
|
|
|
|
}
|
|
|
|
|
2015-07-06 16:13:08 +00:00
|
|
|
// SendChatAction updates a chat action for recipient.
|
|
|
|
//
|
|
|
|
// Chat action is a status message that recipient would see where
|
|
|
|
// you typically see "Harry is typing" status message. The only
|
|
|
|
// difference is that bots' chat actions live only for 5 seconds
|
|
|
|
// and die just once the client recieves a message from the bot.
|
|
|
|
//
|
|
|
|
// Currently, Telegram supports only a narrow range of possible
|
|
|
|
// actions, these are aligned as constants of this package.
|
2016-11-10 20:04:50 +00:00
|
|
|
func (b *Bot) SendChatAction(recipient Recipient, action ChatAction) error {
|
2016-06-26 14:05:37 +00:00
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
2016-11-10 20:04:50 +00:00
|
|
|
"action": string(action),
|
2016-06-26 14:05:37 +00:00
|
|
|
}
|
2015-07-06 16:13:08 +00:00
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("sendChatAction", params)
|
2016-01-22 11:38:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return extractOkResponse(respJSON)
|
2015-07-06 16:13:08 +00:00
|
|
|
}
|
2016-06-26 14:05:37 +00:00
|
|
|
|
|
|
|
// AnswerInlineQuery sends a response for a given inline query. A query can
|
|
|
|
// only be responded to once, subsequent attempts to respond to the same query
|
|
|
|
// will result in an error.
|
|
|
|
func (b *Bot) AnswerInlineQuery(query *Query, response *QueryResponse) error {
|
|
|
|
response.QueryID = query.ID
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("answerInlineQuery", response)
|
2016-06-26 14:05:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return extractOkResponse(respJSON)
|
2016-06-26 14:05:37 +00:00
|
|
|
}
|
2016-07-25 22:09:18 +00:00
|
|
|
|
|
|
|
// AnswerCallbackQuery sends a response for a given callback query. A callback can
|
|
|
|
// only be responded to once, subsequent attempts to respond to the same callback
|
|
|
|
// will result in an error.
|
|
|
|
func (b *Bot) AnswerCallbackQuery(callback *Callback, response *CallbackResponse) error {
|
|
|
|
response.CallbackID = callback.ID
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("answerCallbackQuery", response)
|
2016-07-25 22:09:18 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return extractOkResponse(respJSON)
|
2016-07-25 22:09:18 +00:00
|
|
|
}
|
2016-09-27 12:04:13 +00:00
|
|
|
|
|
|
|
// GetFile returns full file object including File.FilePath, which allow you to load file from Telegram
|
|
|
|
//
|
|
|
|
// Usually File objects does not contain any FilePath so you need to perform additional request
|
2017-11-18 10:19:58 +00:00
|
|
|
func (b *Bot) GetFile(fileID string) (*File, error) {
|
2016-09-27 12:04:13 +00:00
|
|
|
params := map[string]string{
|
2016-10-09 19:57:08 +00:00
|
|
|
"file_id": fileID,
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
2017-11-18 10:19:58 +00:00
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("getFile", params)
|
2016-09-27 12:04:13 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, err
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2016-09-27 12:04:13 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
2017-11-18 10:19:58 +00:00
|
|
|
Result *File
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2016-09-27 12:04:13 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, errors.Wrap(err, "bad response json")
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, errors.Errorf("api error: %s", resp.Description)
|
2017-08-15 13:44:01 +00:00
|
|
|
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return resp.Result, nil
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
|
|
|
|
2016-11-09 23:28:00 +00:00
|
|
|
// LeaveChat makes bot leave a group, supergroup or channel.
|
2016-10-15 07:22:58 +00:00
|
|
|
func (b *Bot) LeaveChat(recipient Recipient) error {
|
2016-10-09 19:57:08 +00:00
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("leaveChat", params)
|
2016-10-09 19:57:08 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return err
|
2016-10-09 20:00:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return extractOkResponse(respJSON)
|
2016-10-09 20:00:04 +00:00
|
|
|
}
|
|
|
|
|
2016-11-09 23:28:00 +00:00
|
|
|
// GetChat get up to date information about the chat.
|
|
|
|
//
|
|
|
|
// Including current name of the user for one-on-one conversations,
|
|
|
|
// current username of a user, group or channel, etc.
|
2016-10-09 20:00:04 +00:00
|
|
|
//
|
|
|
|
// Returns a Chat object on success.
|
2017-11-18 10:19:58 +00:00
|
|
|
func (b *Bot) GetChat(recipient Recipient) (*Chat, error) {
|
2016-10-09 20:00:04 +00:00
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
}
|
2017-11-18 10:19:58 +00:00
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("getChat", params)
|
2016-10-09 20:00:04 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, err
|
2016-10-09 20:00:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2016-11-09 23:28:00 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
2017-11-18 10:19:58 +00:00
|
|
|
Result *Chat
|
2016-10-09 20:00:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2016-10-09 20:00:04 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, errors.Wrap(err, "bad response json")
|
2016-10-09 20:00:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, errors.Errorf("api error: %s", resp.Description)
|
2016-10-09 19:57:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return resp.Result, nil
|
2016-10-09 19:57:08 +00:00
|
|
|
}
|
|
|
|
|
2016-10-14 15:01:45 +00:00
|
|
|
// GetChatAdministrators return list of administrators in a chat.
|
2016-10-09 20:09:07 +00:00
|
|
|
//
|
2016-10-09 20:42:07 +00:00
|
|
|
// On success, returns an Array of ChatMember objects that
|
|
|
|
// contains information about all chat administrators except other bots.
|
2016-10-09 20:09:07 +00:00
|
|
|
//
|
2016-10-09 20:42:07 +00:00
|
|
|
// If the chat is a group or a supergroup and
|
|
|
|
// no administrators were appointed, only the creator will be returned.
|
2016-10-09 20:09:07 +00:00
|
|
|
func (b *Bot) GetChatAdministrators(recipient Recipient) ([]ChatMember, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
}
|
2017-11-18 10:19:58 +00:00
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("getChatAdministrators", params)
|
2016-10-09 20:09:07 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, err
|
2016-10-09 20:09:07 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2016-10-09 20:09:07 +00:00
|
|
|
Ok bool
|
|
|
|
Result []ChatMember
|
2016-11-10 19:34:02 +00:00
|
|
|
Description string `json:"description"`
|
2016-10-09 20:09:07 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2016-10-09 20:09:07 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, errors.Wrap(err, "bad response json")
|
2016-10-09 20:09:07 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, errors.Errorf("api error: %s", resp.Description)
|
2016-10-09 20:09:07 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return resp.Result, nil
|
2016-10-09 20:09:07 +00:00
|
|
|
}
|
|
|
|
|
2016-10-14 15:01:45 +00:00
|
|
|
// GetChatMembersCount return the number of members in a chat.
|
2016-10-09 20:11:23 +00:00
|
|
|
//
|
|
|
|
// Returns Int on success.
|
|
|
|
func (b *Bot) GetChatMembersCount(recipient Recipient) (int, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
}
|
2017-11-18 10:19:58 +00:00
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("getChatMembersCount", params)
|
2016-10-09 20:11:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2016-10-09 20:11:23 +00:00
|
|
|
Ok bool
|
|
|
|
Result int
|
2016-11-10 19:34:02 +00:00
|
|
|
Description string `json:"description"`
|
2016-10-09 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2016-10-09 20:11:23 +00:00
|
|
|
if err != nil {
|
2017-08-15 13:44:01 +00:00
|
|
|
return 0, errors.Wrap(err, "bad response json")
|
2016-10-09 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return 0, errors.Errorf("api error: %s", resp.Description)
|
2016-10-09 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return resp.Result, nil
|
2016-10-09 20:11:23 +00:00
|
|
|
}
|
|
|
|
|
2016-10-14 15:01:45 +00:00
|
|
|
// GetUserProfilePhotos return list of profile pictures for a user.
|
2016-10-09 20:29:03 +00:00
|
|
|
//
|
2017-11-18 10:19:58 +00:00
|
|
|
// Returns a list[photos][sizes].
|
|
|
|
func (b *Bot) GetUserProfilePhotos(recipient Recipient) ([][]Photo, error) {
|
2016-10-09 20:29:03 +00:00
|
|
|
params := map[string]string{
|
|
|
|
"user_id": recipient.Destination(),
|
|
|
|
}
|
2017-11-18 10:19:58 +00:00
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("getUserProfilePhotos", params)
|
2016-10-09 20:29:03 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, err
|
2016-10-09 20:29:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
|
|
|
Ok bool
|
|
|
|
Result struct {
|
|
|
|
Count int `json:"total_count"`
|
|
|
|
Photos [][]Photo `json:"photos"`
|
|
|
|
}
|
|
|
|
|
2016-11-10 19:34:02 +00:00
|
|
|
Description string `json:"description"`
|
2016-10-09 20:29:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2016-10-09 20:29:03 +00:00
|
|
|
if err != nil {
|
2017-11-18 10:19:58 +00:00
|
|
|
return nil, errors.Wrap(err, "bad response json")
|
2016-10-09 20:29:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, errors.Errorf("api error: %s", resp.Description)
|
2016-10-09 20:29:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return resp.Result.Photos, nil
|
2016-10-09 20:29:03 +00:00
|
|
|
}
|
|
|
|
|
2016-10-14 15:01:45 +00:00
|
|
|
// GetChatMember return information about a member of a chat.
|
2016-10-09 20:16:33 +00:00
|
|
|
//
|
|
|
|
// Returns a ChatMember object on success.
|
2017-11-18 13:06:20 +00:00
|
|
|
func (b *Bot) GetChatMember(recipient Recipient, user User) (ChatMember, error) {
|
2016-10-09 20:16:33 +00:00
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
"user_id": user.Destination(),
|
|
|
|
}
|
2017-11-18 10:19:58 +00:00
|
|
|
|
|
|
|
respJSON, err := b.sendCommand("getChatMember", params)
|
2016-10-09 20:16:33 +00:00
|
|
|
if err != nil {
|
2017-11-18 13:06:20 +00:00
|
|
|
return ChatMember{}, err
|
2016-10-09 20:16:33 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2016-10-09 20:16:33 +00:00
|
|
|
Ok bool
|
2017-11-18 13:06:20 +00:00
|
|
|
Result ChatMember
|
2016-11-10 19:34:02 +00:00
|
|
|
Description string `json:"description"`
|
2016-10-09 20:16:33 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2016-10-09 20:16:33 +00:00
|
|
|
if err != nil {
|
2017-11-18 13:06:20 +00:00
|
|
|
return ChatMember{}, errors.Wrap(err, "bad response json")
|
2016-10-09 20:16:33 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
2017-11-18 13:06:20 +00:00
|
|
|
return ChatMember{}, errors.Errorf("api error: %s", resp.Description)
|
2016-10-09 20:16:33 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return resp.Result, nil
|
2016-10-09 20:16:33 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 12:04:13 +00:00
|
|
|
// GetFileDirectURL returns direct url for files using FileId which you can get from File object
|
|
|
|
func (b *Bot) GetFileDirectURL(fileID string) (string, error) {
|
|
|
|
f, err := b.GetFile(fileID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2016-10-09 19:57:08 +00:00
|
|
|
return "https://api.telegram.org/file/bot" + b.Token + "/" + f.FilePath, nil
|
2016-09-27 12:04:13 +00:00
|
|
|
}
|
2017-01-12 00:48:11 +00:00
|
|
|
|
|
|
|
// EditMessageText used to edit already sent message with known recepient and message id.
|
|
|
|
//
|
|
|
|
// On success, returns edited message object
|
2017-11-18 13:06:20 +00:00
|
|
|
func (b *Bot) Edit(chatID string, messageID int, message string, how ...interface{}) (*Message, error) {
|
2017-01-12 00:48:11 +00:00
|
|
|
params := map[string]string{
|
2017-11-18 13:06:20 +00:00
|
|
|
"chat_id": chatID,
|
2017-01-12 00:48:11 +00:00
|
|
|
"message_id": strconv.Itoa(messageID),
|
|
|
|
"text": message,
|
|
|
|
}
|
|
|
|
|
2017-11-18 13:06:20 +00:00
|
|
|
options := extractOptions(how)
|
|
|
|
embedSendOptions(params, options)
|
2017-01-12 00:48:11 +00:00
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("editMessageText", params)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 13:06:20 +00:00
|
|
|
return extractMsgResponse(respJSON)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// EditInlineMessageText used to edit already sent inline message with known inline message id.
|
|
|
|
//
|
|
|
|
// On success, returns edited message object
|
2017-05-10 07:08:11 +00:00
|
|
|
func (b *Bot) EditInlineMessageText(messageID string, message string, sendOptions *SendOptions) (*Message, error) {
|
2017-01-12 00:48:11 +00:00
|
|
|
params := map[string]string{
|
|
|
|
"inline_message_id": messageID,
|
|
|
|
"text": message,
|
|
|
|
}
|
|
|
|
|
2017-05-10 07:08:11 +00:00
|
|
|
if sendOptions != nil {
|
|
|
|
embedSendOptions(params, sendOptions)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("editMessageText", params)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2017-01-12 00:48:11 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
|
|
|
Message Message `json:"result"`
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, fmt.Errorf("telebot: %s", resp.Description)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return &resp.Message, err
|
2017-01-12 00:48:11 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// EditMessageCaption used to edit already sent photo caption with known recepient and message id.
|
|
|
|
//
|
|
|
|
// On success, returns edited message object
|
|
|
|
func (b *Bot) EditMessageCaption(recipient Recipient, messageID int, caption string, inlineKeyboard *InlineKeyboardMarkup) (*Message, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
"message_id": strconv.Itoa(messageID),
|
|
|
|
"caption": caption,
|
|
|
|
}
|
|
|
|
|
|
|
|
if inlineKeyboard != nil {
|
|
|
|
embedSendOptions(params, &SendOptions{
|
2017-11-17 02:51:03 +00:00
|
|
|
ReplyMarkup: &ReplyMarkup{
|
2017-01-12 00:48:11 +00:00
|
|
|
InlineKeyboard: inlineKeyboard.InlineKeyboard,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("editMessageCaption", params)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2017-01-12 00:48:11 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
|
|
|
Message Message `json:"result"`
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, fmt.Errorf("telebot: %s", resp.Description)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return &resp.Message, err
|
2017-01-12 00:48:11 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// EditInlineMessageCaption used to edit already sent photo caption with known inline message id.
|
|
|
|
//
|
|
|
|
// On success, returns edited message object
|
|
|
|
func (b *Bot) EditInlineMessageCaption(messageID string, caption string, inlineKeyboard *InlineKeyboardMarkup) (*Message, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"inline_message_id": messageID,
|
|
|
|
"caption": caption,
|
|
|
|
}
|
|
|
|
|
|
|
|
if inlineKeyboard != nil {
|
|
|
|
embedSendOptions(params, &SendOptions{
|
2017-11-17 02:51:03 +00:00
|
|
|
ReplyMarkup: &ReplyMarkup{
|
2017-01-12 00:48:11 +00:00
|
|
|
InlineKeyboard: inlineKeyboard.InlineKeyboard,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("editMessageCaption", params)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2017-01-12 00:48:11 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
|
|
|
Message Message `json:"result"`
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, fmt.Errorf("telebot: %s", resp.Description)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return &resp.Message, err
|
2017-01-12 00:48:11 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// EditMessageReplyMarkup used to edit already sent message inline keyboard markup with known recepient and message id.
|
|
|
|
//
|
|
|
|
// On success, returns edited message object
|
|
|
|
func (b *Bot) EditMessageReplyMarkup(recipient Recipient, messageID int, inlineKeyboard *InlineKeyboardMarkup) (*Message, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"chat_id": recipient.Destination(),
|
|
|
|
"message_id": strconv.Itoa(messageID),
|
|
|
|
}
|
|
|
|
|
|
|
|
if inlineKeyboard != nil {
|
|
|
|
embedSendOptions(params, &SendOptions{
|
2017-11-17 02:51:03 +00:00
|
|
|
ReplyMarkup: &ReplyMarkup{
|
2017-01-12 00:48:11 +00:00
|
|
|
InlineKeyboard: inlineKeyboard.InlineKeyboard,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("editMessageReplyMarkup", params)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2017-01-12 00:48:11 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
|
|
|
Message Message `json:"result"`
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, fmt.Errorf("telebot: %s", resp.Description)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return &resp.Message, err
|
2017-01-12 00:48:11 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// EditInlineMessageReplyMarkup used to edit already sent message inline keyboard markup with known inline message id.
|
|
|
|
//
|
|
|
|
// On success, returns edited message object
|
|
|
|
func (b *Bot) EditInlineMessageReplyMarkup(messageID string, caption string, inlineKeyboard *InlineKeyboardMarkup) (*Message, error) {
|
|
|
|
params := map[string]string{
|
|
|
|
"inline_message_id": messageID,
|
|
|
|
}
|
|
|
|
|
|
|
|
if inlineKeyboard != nil {
|
|
|
|
embedSendOptions(params, &SendOptions{
|
2017-11-17 02:51:03 +00:00
|
|
|
ReplyMarkup: &ReplyMarkup{
|
2017-01-12 00:48:11 +00:00
|
|
|
InlineKeyboard: inlineKeyboard.InlineKeyboard,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
respJSON, err := b.sendCommand("editMessageReplyMarkup", params)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
var resp struct {
|
2017-01-12 00:48:11 +00:00
|
|
|
Ok bool
|
|
|
|
Description string
|
|
|
|
Message Message `json:"result"`
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
err = json.Unmarshal(respJSON, &resp)
|
2017-01-12 00:48:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
if !resp.Ok {
|
|
|
|
return nil, fmt.Errorf("telebot: %s", resp.Description)
|
2017-01-12 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 10:19:58 +00:00
|
|
|
return &resp.Message, err
|
2017-01-12 00:48:11 +00:00
|
|
|
|
|
|
|
}
|