summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-telegram-bot-api/telegram-bot-api
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-telegram-bot-api/telegram-bot-api')
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/.travis.yml8
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go1014
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go1279
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go990
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/.gitignore (renamed from vendor/github.com/go-telegram-bot-api/telegram-bot-api/.gitignore)1
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/LICENSE.txt (renamed from vendor/github.com/go-telegram-bot-api/telegram-bot-api/LICENSE.txt)0
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/README.md (renamed from vendor/github.com/go-telegram-bot-api/telegram-bot-api/README.md)44
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/book.toml9
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/bot.go726
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/configs.go2468
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/helpers.go (renamed from vendor/github.com/go-telegram-bot-api/telegram-bot-api/helpers.go)559
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/log.go (renamed from vendor/github.com/go-telegram-bot-api/telegram-bot-api/log.go)0
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/params.go97
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/passport.go (renamed from vendor/github.com/go-telegram-bot-api/telegram-bot-api/passport.go)6
-rw-r--r--vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/types.go3225
15 files changed, 6881 insertions, 3545 deletions
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/.travis.yml b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/.travis.yml
deleted file mode 100644
index 51865c84..00000000
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-language: go
-
-go:
- - '1.10'
- - '1.11'
- - '1.12'
- - '1.13'
- - tip
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go
deleted file mode 100644
index e6c2cc83..00000000
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/bot.go
+++ /dev/null
@@ -1,1014 +0,0 @@
-// Package tgbotapi has functions and types used for interacting with
-// the Telegram Bot API.
-package tgbotapi
-
-import (
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "net/url"
- "os"
- "strconv"
- "strings"
- "time"
-
- "github.com/technoweenie/multipartstreamer"
-)
-
-type HttpClient interface {
- Do(req *http.Request) (*http.Response, error)
-}
-
-// BotAPI allows you to interact with the Telegram Bot API.
-type BotAPI struct {
- Token string `json:"token"`
- Debug bool `json:"debug"`
- Buffer int `json:"buffer"`
-
- Self User `json:"-"`
- Client HttpClient `json:"-"`
- shutdownChannel chan interface{}
-
- apiEndpoint string
-}
-
-// NewBotAPI creates a new BotAPI instance.
-//
-// It requires a token, provided by @BotFather on Telegram.
-func NewBotAPI(token string) (*BotAPI, error) {
- return NewBotAPIWithClient(token, APIEndpoint, &http.Client{})
-}
-
-// NewBotAPIWithAPIEndpoint creates a new BotAPI instance
-// and allows you to pass API endpoint.
-//
-// It requires a token, provided by @BotFather on Telegram and API endpoint.
-func NewBotAPIWithAPIEndpoint(token, apiEndpoint string) (*BotAPI, error) {
- return NewBotAPIWithClient(token, apiEndpoint, &http.Client{})
-}
-
-// NewBotAPIWithClient creates a new BotAPI instance
-// and allows you to pass a http.Client.
-//
-// It requires a token, provided by @BotFather on Telegram and API endpoint.
-func NewBotAPIWithClient(token, apiEndpoint string, client HttpClient) (*BotAPI, error) {
- bot := &BotAPI{
- Token: token,
- Client: client,
- Buffer: 100,
- shutdownChannel: make(chan interface{}),
-
- apiEndpoint: apiEndpoint,
- }
-
- self, err := bot.GetMe()
- if err != nil {
- return nil, err
- }
-
- bot.Self = self
-
- 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(bot.apiEndpoint, bot.Token, endpoint)
-
- req, err := http.NewRequest("POST", method, strings.NewReader(params.Encode()))
- if err != nil {
- return APIResponse{}, err
- }
- req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
-
- resp, err := bot.Client.Do(req)
- if err != nil {
- return APIResponse{}, err
- }
- defer resp.Body.Close()
-
- var apiResp APIResponse
- bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
- if err != nil {
- return apiResp, err
- }
-
- if bot.Debug {
- log.Printf("%s resp: %s", endpoint, bytes)
- }
-
- if !apiResp.Ok {
- parameters := ResponseParameters{}
- if apiResp.Parameters != nil {
- parameters = *apiResp.Parameters
- }
- return apiResp, &Error{Code: apiResp.ErrorCode, Message: apiResp.Description, ResponseParameters: parameters}
- }
-
- return apiResp, nil
-}
-
-// decodeAPIResponse decode response and return slice of bytes if debug enabled.
-// If debug disabled, just decode http.Response.Body stream to APIResponse struct
-// for efficient memory usage
-func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse) (_ []byte, err error) {
- if !bot.Debug {
- dec := json.NewDecoder(responseBody)
- err = dec.Decode(resp)
- return
- }
-
- // if debug, read reponse body
- data, err := ioutil.ReadAll(responseBody)
- if err != nil {
- return
- }
-
- err = json.Unmarshal(data, resp)
- if err != nil {
- return
- }
-
- return data, nil
-}
-
-// makeMessageRequest makes a request to a method that returns a Message.
-func (bot *BotAPI) makeMessageRequest(endpoint string, params url.Values) (Message, error) {
- resp, err := bot.MakeRequest(endpoint, params)
- if err != nil {
- return Message{}, err
- }
-
- var message Message
- json.Unmarshal(resp.Result, &message)
-
- bot.debugLog(endpoint, params, message)
-
- return message, nil
-}
-
-// UploadFile makes a request to the API with a file.
-//
-// Requires the parameter to hold the file not be in the params.
-// File should be a string to a file path, a FileBytes struct,
-// a FileReader struct, or a url.URL.
-//
-// Note that if your FileReader has a size set to -1, it will read
-// the file into memory to calculate a size.
-func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldname string, file interface{}) (APIResponse, error) {
- ms := multipartstreamer.New()
-
- switch f := file.(type) {
- case string:
- ms.WriteFields(params)
-
- fileHandle, err := os.Open(f)
- if err != nil {
- return APIResponse{}, err
- }
- defer fileHandle.Close()
-
- fi, err := os.Stat(f)
- if err != nil {
- return APIResponse{}, err
- }
-
- ms.WriteReader(fieldname, fileHandle.Name(), fi.Size(), fileHandle)
- case FileBytes:
- ms.WriteFields(params)
-
- buf := bytes.NewBuffer(f.Bytes)
- ms.WriteReader(fieldname, f.Name, int64(len(f.Bytes)), buf)
- case FileReader:
- ms.WriteFields(params)
-
- if f.Size != -1 {
- ms.WriteReader(fieldname, f.Name, f.Size, f.Reader)
-
- break
- }
-
- data, err := ioutil.ReadAll(f.Reader)
- if err != nil {
- return APIResponse{}, err
- }
-
- buf := bytes.NewBuffer(data)
-
- ms.WriteReader(fieldname, f.Name, int64(len(data)), buf)
- case url.URL:
- params[fieldname] = f.String()
-
- ms.WriteFields(params)
- default:
- return APIResponse{}, errors.New(ErrBadFileType)
- }
-
- method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
-
- req, err := http.NewRequest("POST", method, nil)
- if err != nil {
- return APIResponse{}, err
- }
-
- ms.SetupRequest(req)
-
- res, err := bot.Client.Do(req)
- if err != nil {
- return APIResponse{}, err
- }
- defer res.Body.Close()
-
- bytes, err := ioutil.ReadAll(res.Body)
- if err != nil {
- return APIResponse{}, err
- }
-
- if bot.Debug {
- log.Println(string(bytes))
- }
-
- var apiResp APIResponse
-
- err = json.Unmarshal(bytes, &apiResp)
- if err != nil {
- return APIResponse{}, err
- }
-
- if !apiResp.Ok {
- return APIResponse{}, errors.New(apiResp.Description)
- }
-
- return apiResp, nil
-}
-
-// GetFileDirectURL returns direct URL to file
-//
-// It requires the FileID.
-func (bot *BotAPI) GetFileDirectURL(fileID string) (string, error) {
- file, err := bot.GetFile(FileConfig{fileID})
-
- if err != nil {
- return "", err
- }
-
- return file.Link(bot.Token), nil
-}
-
-// GetMe fetches the currently authenticated bot.
-//
-// This method is called upon creation to validate the token,
-// and so you may get this data from BotAPI.Self without the need for
-// another request.
-func (bot *BotAPI) GetMe() (User, error) {
- resp, err := bot.MakeRequest("getMe", nil)
- if err != nil {
- return User{}, err
- }
-
- var user User
- json.Unmarshal(resp.Result, &user)
-
- bot.debugLog("getMe", nil, user)
-
- return user, nil
-}
-
-// IsMessageToMe returns true if message directed to this bot.
-//
-// It requires the Message.
-func (bot *BotAPI) IsMessageToMe(message Message) bool {
- return strings.Contains(message.Text, "@"+bot.Self.UserName)
-}
-
-// Send will send a Chattable item to Telegram.
-//
-// It requires the Chattable to send.
-func (bot *BotAPI) Send(c Chattable) (Message, error) {
- switch c.(type) {
- case Fileable:
- return bot.sendFile(c.(Fileable))
- default:
- return bot.sendChattable(c)
- }
-}
-
-// debugLog checks if the bot is currently running in debug mode, and if
-// so will display information about the request and response in the
-// debug log.
-func (bot *BotAPI) debugLog(context string, v url.Values, message interface{}) {
- if bot.Debug {
- log.Printf("%s req : %+v\n", context, v)
- log.Printf("%s resp: %+v\n", context, message)
- }
-}
-
-// sendExisting will send a Message with an existing file to Telegram.
-func (bot *BotAPI) sendExisting(method string, config Fileable) (Message, error) {
- v, err := config.values()
-
- if err != nil {
- return Message{}, err
- }
-
- message, err := bot.makeMessageRequest(method, v)
- if err != nil {
- return Message{}, err
- }
-
- return message, nil
-}
-
-// uploadAndSend will send a Message with a new file to Telegram.
-func (bot *BotAPI) uploadAndSend(method string, config Fileable) (Message, error) {
- params, err := config.params()
- if err != nil {
- return Message{}, err
- }
-
- file := config.getFile()
-
- resp, err := bot.UploadFile(method, params, config.name(), file)
- if err != nil {
- return Message{}, err
- }
-
- var message Message
- json.Unmarshal(resp.Result, &message)
-
- bot.debugLog(method, nil, message)
-
- return message, nil
-}
-
-// sendFile determines if the file is using an existing file or uploading
-// a new file, then sends it as needed.
-func (bot *BotAPI) sendFile(config Fileable) (Message, error) {
- if config.useExistingFile() {
- return bot.sendExisting(config.method(), config)
- }
-
- return bot.uploadAndSend(config.method(), config)
-}
-
-// sendChattable sends a Chattable.
-func (bot *BotAPI) sendChattable(config Chattable) (Message, error) {
- v, err := config.values()
- if err != nil {
- return Message{}, err
- }
-
- message, err := bot.makeMessageRequest(config.method(), v)
-
- if err != nil {
- return Message{}, err
- }
-
- return message, nil
-}
-
-// GetUserProfilePhotos gets a user's profile photos.
-//
-// It requires UserID.
-// Offset and Limit are optional.
-func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
- v := url.Values{}
- v.Add("user_id", strconv.Itoa(config.UserID))
- if config.Offset != 0 {
- v.Add("offset", strconv.Itoa(config.Offset))
- }
- if config.Limit != 0 {
- v.Add("limit", strconv.Itoa(config.Limit))
- }
-
- resp, err := bot.MakeRequest("getUserProfilePhotos", v)
- if err != nil {
- return UserProfilePhotos{}, err
- }
-
- var profilePhotos UserProfilePhotos
- json.Unmarshal(resp.Result, &profilePhotos)
-
- bot.debugLog("GetUserProfilePhoto", v, profilePhotos)
-
- return profilePhotos, nil
-}
-
-// GetFile returns a File which can download a file from Telegram.
-//
-// Requires FileID.
-func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
- v := url.Values{}
- v.Add("file_id", config.FileID)
-
- resp, err := bot.MakeRequest("getFile", v)
- if err != nil {
- return File{}, err
- }
-
- var file File
- json.Unmarshal(resp.Result, &file)
-
- bot.debugLog("GetFile", v, file)
-
- return file, nil
-}
-
-// GetUpdates fetches updates.
-// If a WebHook is set, this will not return any data!
-//
-// Offset, Limit, and Timeout are optional.
-// To avoid stale items, set Offset to one higher than the previous item.
-// Set Timeout to a large number to reduce requests so you can get updates
-// instantly instead of having to wait between requests.
-func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
- v := url.Values{}
- if config.Offset != 0 {
- v.Add("offset", strconv.Itoa(config.Offset))
- }
- if config.Limit > 0 {
- v.Add("limit", strconv.Itoa(config.Limit))
- }
- if config.Timeout > 0 {
- v.Add("timeout", strconv.Itoa(config.Timeout))
- }
-
- resp, err := bot.MakeRequest("getUpdates", v)
- if err != nil {
- return []Update{}, err
- }
-
- var updates []Update
- json.Unmarshal(resp.Result, &updates)
-
- bot.debugLog("getUpdates", v, updates)
-
- return updates, nil
-}
-
-// RemoveWebhook unsets the webhook.
-func (bot *BotAPI) RemoveWebhook() (APIResponse, error) {
- return bot.MakeRequest("deleteWebhook", url.Values{})
-}
-
-// SetWebhook sets a webhook.
-//
-// If this is set, GetUpdates will not get any data!
-//
-// If you do not have a legitimate TLS certificate, you need to include
-// your self signed certificate with the config.
-func (bot *BotAPI) SetWebhook(config WebhookConfig) (APIResponse, error) {
-
- if config.Certificate == nil {
- v := url.Values{}
- v.Add("url", config.URL.String())
- if config.MaxConnections != 0 {
- v.Add("max_connections", strconv.Itoa(config.MaxConnections))
- }
-
- return bot.MakeRequest("setWebhook", v)
- }
-
- params := make(map[string]string)
- params["url"] = config.URL.String()
- if config.MaxConnections != 0 {
- params["max_connections"] = strconv.Itoa(config.MaxConnections)
- }
-
- resp, err := bot.UploadFile("setWebhook", params, "certificate", config.Certificate)
- if err != nil {
- return APIResponse{}, err
- }
-
- return resp, nil
-}
-
-// GetWebhookInfo allows you to fetch information about a webhook and if
-// one currently is set, along with pending update count and error messages.
-func (bot *BotAPI) GetWebhookInfo() (WebhookInfo, error) {
- resp, err := bot.MakeRequest("getWebhookInfo", url.Values{})
- if err != nil {
- return WebhookInfo{}, err
- }
-
- var info WebhookInfo
- err = json.Unmarshal(resp.Result, &info)
-
- return info, err
-}
-
-// GetUpdatesChan starts and returns a channel for getting updates.
-func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) (UpdatesChannel, error) {
- ch := make(chan Update, bot.Buffer)
-
- go func() {
- for {
- select {
- case <-bot.shutdownChannel:
- close(ch)
- return
- default:
- }
-
- updates, err := bot.GetUpdates(config)
- if err != nil {
- log.Println(err)
- log.Println("Failed to get updates, retrying in 3 seconds...")
- time.Sleep(time.Second * 3)
-
- continue
- }
-
- for _, update := range updates {
- if update.UpdateID >= config.Offset {
- config.Offset = update.UpdateID + 1
- ch <- update
- }
- }
- }
- }()
-
- return ch, nil
-}
-
-// StopReceivingUpdates stops the go routine which receives updates
-func (bot *BotAPI) StopReceivingUpdates() {
- if bot.Debug {
- log.Println("Stopping the update receiver routine...")
- }
- close(bot.shutdownChannel)
-}
-
-// ListenForWebhook registers a http handler for a webhook.
-func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel {
- ch := make(chan Update, bot.Buffer)
-
- http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
- bytes, _ := ioutil.ReadAll(r.Body)
- r.Body.Close()
-
- var update Update
- json.Unmarshal(bytes, &update)
-
- ch <- update
- })
-
- return ch
-}
-
-// AnswerInlineQuery sends a response to an inline query.
-//
-// Note that you must respond to an inline query within 30 seconds.
-func (bot *BotAPI) AnswerInlineQuery(config InlineConfig) (APIResponse, error) {
- v := url.Values{}
-
- v.Add("inline_query_id", config.InlineQueryID)
- v.Add("cache_time", strconv.Itoa(config.CacheTime))
- v.Add("is_personal", strconv.FormatBool(config.IsPersonal))
- v.Add("next_offset", config.NextOffset)
- data, err := json.Marshal(config.Results)
- if err != nil {
- return APIResponse{}, err
- }
- v.Add("results", string(data))
- v.Add("switch_pm_text", config.SwitchPMText)
- v.Add("switch_pm_parameter", config.SwitchPMParameter)
-
- bot.debugLog("answerInlineQuery", v, nil)
-
- return bot.MakeRequest("answerInlineQuery", v)
-}
-
-// AnswerCallbackQuery sends a response to an inline query callback.
-func (bot *BotAPI) AnswerCallbackQuery(config CallbackConfig) (APIResponse, error) {
- v := url.Values{}
-
- v.Add("callback_query_id", config.CallbackQueryID)
- if config.Text != "" {
- v.Add("text", config.Text)
- }
- v.Add("show_alert", strconv.FormatBool(config.ShowAlert))
- if config.URL != "" {
- v.Add("url", config.URL)
- }
- v.Add("cache_time", strconv.Itoa(config.CacheTime))
-
- bot.debugLog("answerCallbackQuery", v, nil)
-
- return bot.MakeRequest("answerCallbackQuery", v)
-}
-
-// KickChatMember kicks a user from a chat. Note that this only will work
-// in supergroups, and requires the bot to be an admin. Also note they
-// will be unable to rejoin until they are unbanned.
-func (bot *BotAPI) KickChatMember(config KickChatMemberConfig) (APIResponse, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
- v.Add("user_id", strconv.Itoa(config.UserID))
-
- if config.UntilDate != 0 {
- v.Add("until_date", strconv.FormatInt(config.UntilDate, 10))
- }
-
- bot.debugLog("kickChatMember", v, nil)
-
- return bot.MakeRequest("kickChatMember", v)
-}
-
-// LeaveChat makes the bot leave the chat.
-func (bot *BotAPI) LeaveChat(config ChatConfig) (APIResponse, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
-
- bot.debugLog("leaveChat", v, nil)
-
- return bot.MakeRequest("leaveChat", v)
-}
-
-// GetChat gets information about a chat.
-func (bot *BotAPI) GetChat(config ChatConfig) (Chat, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
-
- resp, err := bot.MakeRequest("getChat", v)
- if err != nil {
- return Chat{}, err
- }
-
- var chat Chat
- err = json.Unmarshal(resp.Result, &chat)
-
- bot.debugLog("getChat", v, chat)
-
- return chat, err
-}
-
-// GetChatAdministrators gets a list of administrators in the chat.
-//
-// If none have been appointed, only the creator will be returned.
-// Bots are not shown, even if they are an administrator.
-func (bot *BotAPI) GetChatAdministrators(config ChatConfig) ([]ChatMember, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
-
- resp, err := bot.MakeRequest("getChatAdministrators", v)
- if err != nil {
- return []ChatMember{}, err
- }
-
- var members []ChatMember
- err = json.Unmarshal(resp.Result, &members)
-
- bot.debugLog("getChatAdministrators", v, members)
-
- return members, err
-}
-
-// GetChatMembersCount gets the number of users in a chat.
-func (bot *BotAPI) GetChatMembersCount(config ChatConfig) (int, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
-
- resp, err := bot.MakeRequest("getChatMembersCount", v)
- if err != nil {
- return -1, err
- }
-
- var count int
- err = json.Unmarshal(resp.Result, &count)
-
- bot.debugLog("getChatMembersCount", v, count)
-
- return count, err
-}
-
-// GetChatMember gets a specific chat member.
-func (bot *BotAPI) GetChatMember(config ChatConfigWithUser) (ChatMember, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
- v.Add("user_id", strconv.Itoa(config.UserID))
-
- resp, err := bot.MakeRequest("getChatMember", v)
- if err != nil {
- return ChatMember{}, err
- }
-
- var member ChatMember
- err = json.Unmarshal(resp.Result, &member)
-
- bot.debugLog("getChatMember", v, member)
-
- return member, err
-}
-
-// UnbanChatMember unbans a user from a chat. Note that this only will work
-// in supergroups and channels, and requires the bot to be an admin.
-func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername != "" {
- v.Add("chat_id", config.SuperGroupUsername)
- } else if config.ChannelUsername != "" {
- v.Add("chat_id", config.ChannelUsername)
- } else {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- }
- v.Add("user_id", strconv.Itoa(config.UserID))
-
- bot.debugLog("unbanChatMember", v, nil)
-
- return bot.MakeRequest("unbanChatMember", v)
-}
-
-// RestrictChatMember to restrict a user in a supergroup. The bot must be an
-//administrator in the supergroup for this to work and must have the
-//appropriate admin rights. Pass True for all boolean parameters to lift
-//restrictions from a user. Returns True on success.
-func (bot *BotAPI) RestrictChatMember(config RestrictChatMemberConfig) (APIResponse, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername != "" {
- v.Add("chat_id", config.SuperGroupUsername)
- } else if config.ChannelUsername != "" {
- v.Add("chat_id", config.ChannelUsername)
- } else {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- }
- v.Add("user_id", strconv.Itoa(config.UserID))
-
- if config.CanSendMessages != nil {
- v.Add("can_send_messages", strconv.FormatBool(*config.CanSendMessages))
- }
- if config.CanSendMediaMessages != nil {
- v.Add("can_send_media_messages", strconv.FormatBool(*config.CanSendMediaMessages))
- }
- if config.CanSendOtherMessages != nil {
- v.Add("can_send_other_messages", strconv.FormatBool(*config.CanSendOtherMessages))
- }
- if config.CanAddWebPagePreviews != nil {
- v.Add("can_add_web_page_previews", strconv.FormatBool(*config.CanAddWebPagePreviews))
- }
- if config.UntilDate != 0 {
- v.Add("until_date", strconv.FormatInt(config.UntilDate, 10))
- }
-
- bot.debugLog("restrictChatMember", v, nil)
-
- return bot.MakeRequest("restrictChatMember", v)
-}
-
-// PromoteChatMember add admin rights to user
-func (bot *BotAPI) PromoteChatMember(config PromoteChatMemberConfig) (APIResponse, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername != "" {
- v.Add("chat_id", config.SuperGroupUsername)
- } else if config.ChannelUsername != "" {
- v.Add("chat_id", config.ChannelUsername)
- } else {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- }
- v.Add("user_id", strconv.Itoa(config.UserID))
-
- if config.CanChangeInfo != nil {
- v.Add("can_change_info", strconv.FormatBool(*config.CanChangeInfo))
- }
- if config.CanPostMessages != nil {
- v.Add("can_post_messages", strconv.FormatBool(*config.CanPostMessages))
- }
- if config.CanEditMessages != nil {
- v.Add("can_edit_messages", strconv.FormatBool(*config.CanEditMessages))
- }
- if config.CanDeleteMessages != nil {
- v.Add("can_delete_messages", strconv.FormatBool(*config.CanDeleteMessages))
- }
- if config.CanInviteUsers != nil {
- v.Add("can_invite_users", strconv.FormatBool(*config.CanInviteUsers))
- }
- if config.CanRestrictMembers != nil {
- v.Add("can_restrict_members", strconv.FormatBool(*config.CanRestrictMembers))
- }
- if config.CanPinMessages != nil {
- v.Add("can_pin_messages", strconv.FormatBool(*config.CanPinMessages))
- }
- if config.CanPromoteMembers != nil {
- v.Add("can_promote_members", strconv.FormatBool(*config.CanPromoteMembers))
- }
-
- bot.debugLog("promoteChatMember", v, nil)
-
- return bot.MakeRequest("promoteChatMember", v)
-}
-
-// GetGameHighScores allows you to get the high scores for a game.
-func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) {
- v, _ := config.values()
-
- resp, err := bot.MakeRequest(config.method(), v)
- if err != nil {
- return []GameHighScore{}, err
- }
-
- var highScores []GameHighScore
- err = json.Unmarshal(resp.Result, &highScores)
-
- return highScores, err
-}
-
-// AnswerShippingQuery allows you to reply to Update with shipping_query parameter.
-func (bot *BotAPI) AnswerShippingQuery(config ShippingConfig) (APIResponse, error) {
- v := url.Values{}
-
- v.Add("shipping_query_id", config.ShippingQueryID)
- v.Add("ok", strconv.FormatBool(config.OK))
- if config.OK == true {
- data, err := json.Marshal(config.ShippingOptions)
- if err != nil {
- return APIResponse{}, err
- }
- v.Add("shipping_options", string(data))
- } else {
- v.Add("error_message", config.ErrorMessage)
- }
-
- bot.debugLog("answerShippingQuery", v, nil)
-
- return bot.MakeRequest("answerShippingQuery", v)
-}
-
-// AnswerPreCheckoutQuery allows you to reply to Update with pre_checkout_query.
-func (bot *BotAPI) AnswerPreCheckoutQuery(config PreCheckoutConfig) (APIResponse, error) {
- v := url.Values{}
-
- v.Add("pre_checkout_query_id", config.PreCheckoutQueryID)
- v.Add("ok", strconv.FormatBool(config.OK))
- if config.OK != true {
- v.Add("error", config.ErrorMessage)
- }
-
- bot.debugLog("answerPreCheckoutQuery", v, nil)
-
- return bot.MakeRequest("answerPreCheckoutQuery", v)
-}
-
-// DeleteMessage deletes a message in a chat
-func (bot *BotAPI) DeleteMessage(config DeleteMessageConfig) (APIResponse, error) {
- v, err := config.values()
- if err != nil {
- return APIResponse{}, err
- }
-
- bot.debugLog(config.method(), v, nil)
-
- return bot.MakeRequest(config.method(), v)
-}
-
-// GetInviteLink get InviteLink for a chat
-func (bot *BotAPI) GetInviteLink(config ChatConfig) (string, error) {
- v := url.Values{}
-
- if config.SuperGroupUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.SuperGroupUsername)
- }
-
- resp, err := bot.MakeRequest("exportChatInviteLink", v)
- if err != nil {
- return "", err
- }
-
- var inviteLink string
- err = json.Unmarshal(resp.Result, &inviteLink)
-
- return inviteLink, err
-}
-
-// PinChatMessage pin message in supergroup
-func (bot *BotAPI) PinChatMessage(config PinChatMessageConfig) (APIResponse, error) {
- v, err := config.values()
- if err != nil {
- return APIResponse{}, err
- }
-
- bot.debugLog(config.method(), v, nil)
-
- return bot.MakeRequest(config.method(), v)
-}
-
-// UnpinChatMessage unpin message in supergroup
-func (bot *BotAPI) UnpinChatMessage(config UnpinChatMessageConfig) (APIResponse, error) {
- v, err := config.values()
- if err != nil {
- return APIResponse{}, err
- }
-
- bot.debugLog(config.method(), v, nil)
-
- return bot.MakeRequest(config.method(), v)
-}
-
-// SetChatTitle change title of chat.
-func (bot *BotAPI) SetChatTitle(config SetChatTitleConfig) (APIResponse, error) {
- v, err := config.values()
- if err != nil {
- return APIResponse{}, err
- }
-
- bot.debugLog(config.method(), v, nil)
-
- return bot.MakeRequest(config.method(), v)
-}
-
-// SetChatDescription change description of chat.
-func (bot *BotAPI) SetChatDescription(config SetChatDescriptionConfig) (APIResponse, error) {
- v, err := config.values()
- if err != nil {
- return APIResponse{}, err
- }
-
- bot.debugLog(config.method(), v, nil)
-
- return bot.MakeRequest(config.method(), v)
-}
-
-// SetChatPhoto change photo of chat.
-func (bot *BotAPI) SetChatPhoto(config SetChatPhotoConfig) (APIResponse, error) {
- params, err := config.params()
- if err != nil {
- return APIResponse{}, err
- }
-
- file := config.getFile()
-
- return bot.UploadFile(config.method(), params, config.name(), file)
-}
-
-// DeleteChatPhoto delete photo of chat.
-func (bot *BotAPI) DeleteChatPhoto(config DeleteChatPhotoConfig) (APIResponse, error) {
- v, err := config.values()
- if err != nil {
- return APIResponse{}, err
- }
-
- bot.debugLog(config.method(), v, nil)
-
- return bot.MakeRequest(config.method(), v)
-}
-
-// GetStickerSet get a sticker set.
-func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) {
- v, err := config.values()
- if err != nil {
- return StickerSet{}, err
- }
- bot.debugLog(config.method(), v, nil)
- res, err := bot.MakeRequest(config.method(), v)
- if err != nil {
- return StickerSet{}, err
- }
- stickerSet := StickerSet{}
- err = json.Unmarshal(res.Result, &stickerSet)
- if err != nil {
- return StickerSet{}, err
- }
- return stickerSet, nil
-}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go
deleted file mode 100644
index a7052ddc..00000000
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/configs.go
+++ /dev/null
@@ -1,1279 +0,0 @@
-package tgbotapi
-
-import (
- "encoding/json"
- "io"
- "net/url"
- "strconv"
-)
-
-// Telegram constants
-const (
- // APIEndpoint is the endpoint for all API methods,
- // with formatting for Sprintf.
- APIEndpoint = "https://api.telegram.org/bot%s/%s"
- // FileEndpoint is the endpoint for downloading a file from Telegram.
- FileEndpoint = "https://api.telegram.org/file/bot%s/%s"
-)
-
-// Constant values for ChatActions
-const (
- ChatTyping = "typing"
- ChatUploadPhoto = "upload_photo"
- ChatRecordVideo = "record_video"
- ChatUploadVideo = "upload_video"
- ChatRecordAudio = "record_audio"
- ChatUploadAudio = "upload_audio"
- ChatUploadDocument = "upload_document"
- ChatFindLocation = "find_location"
-)
-
-// API errors
-const (
- // ErrAPIForbidden happens when a token is bad
- ErrAPIForbidden = "forbidden"
-)
-
-// Constant values for ParseMode in MessageConfig
-const (
- ModeMarkdown = "Markdown"
- ModeHTML = "HTML"
-)
-
-// Library errors
-const (
- // ErrBadFileType happens when you pass an unknown type
- ErrBadFileType = "bad file type"
- ErrBadURL = "bad or empty url"
-)
-
-// Chattable is any config type that can be sent.
-type Chattable interface {
- values() (url.Values, error)
- method() string
-}
-
-// Fileable is any config type that can be sent that includes a file.
-type Fileable interface {
- Chattable
- params() (map[string]string, error)
- name() string
- getFile() interface{}
- useExistingFile() bool
-}
-
-// BaseChat is base type for all chat config types.
-type BaseChat struct {
- ChatID int64 // required
- ChannelUsername string
- ReplyToMessageID int
- ReplyMarkup interface{}
- DisableNotification bool
-}
-
-// values returns url.Values representation of BaseChat
-func (chat *BaseChat) values() (url.Values, error) {
- v := url.Values{}
- if chat.ChannelUsername != "" {
- v.Add("chat_id", chat.ChannelUsername)
- } else {
- v.Add("chat_id", strconv.FormatInt(chat.ChatID, 10))
- }
-
- if chat.ReplyToMessageID != 0 {
- v.Add("reply_to_message_id", strconv.Itoa(chat.ReplyToMessageID))
- }
-
- if chat.ReplyMarkup != nil {
- data, err := json.Marshal(chat.ReplyMarkup)
- if err != nil {
- return v, err
- }
-
- v.Add("reply_markup", string(data))
- }
-
- v.Add("disable_notification", strconv.FormatBool(chat.DisableNotification))
-
- return v, nil
-}
-
-// BaseFile is a base type for all file config types.
-type BaseFile struct {
- BaseChat
- File interface{}
- FileID string
- UseExisting bool
- MimeType string
- FileSize int
-}
-
-// params returns a map[string]string representation of BaseFile.
-func (file BaseFile) params() (map[string]string, error) {
- params := make(map[string]string)
-
- if file.ChannelUsername != "" {
- params["chat_id"] = file.ChannelUsername
- } else {
- params["chat_id"] = strconv.FormatInt(file.ChatID, 10)
- }
-
- if file.ReplyToMessageID != 0 {
- params["reply_to_message_id"] = strconv.Itoa(file.ReplyToMessageID)
- }
-
- if file.ReplyMarkup != nil {
- data, err := json.Marshal(file.ReplyMarkup)
- if err != nil {
- return params, err
- }
-
- params["reply_markup"] = string(data)
- }
-
- if file.MimeType != "" {
- params["mime_type"] = file.MimeType
- }
-
- if file.FileSize > 0 {
- params["file_size"] = strconv.Itoa(file.FileSize)
- }
-
- params["disable_notification"] = strconv.FormatBool(file.DisableNotification)
-
- return params, nil
-}
-
-// getFile returns the file.
-func (file BaseFile) getFile() interface{} {
- return file.File
-}
-
-// useExistingFile returns if the BaseFile has already been uploaded.
-func (file BaseFile) useExistingFile() bool {
- return file.UseExisting
-}
-
-// BaseEdit is base type of all chat edits.
-type BaseEdit struct {
- ChatID int64
- ChannelUsername string
- MessageID int
- InlineMessageID string
- ReplyMarkup *InlineKeyboardMarkup
-}
-
-func (edit BaseEdit) values() (url.Values, error) {
- v := url.Values{}
-
- if edit.InlineMessageID == "" {
- if edit.ChannelUsername != "" {
- v.Add("chat_id", edit.ChannelUsername)
- } else {
- v.Add("chat_id", strconv.FormatInt(edit.ChatID, 10))
- }
- v.Add("message_id", strconv.Itoa(edit.MessageID))
- } else {
- v.Add("inline_message_id", edit.InlineMessageID)
- }
-
- if edit.ReplyMarkup != nil {
- data, err := json.Marshal(edit.ReplyMarkup)
- if err != nil {
- return v, err
- }
- v.Add("reply_markup", string(data))
- }
-
- return v, nil
-}
-
-// MessageConfig contains information about a SendMessage request.
-type MessageConfig struct {
- BaseChat
- Text string
- ParseMode string
- DisableWebPagePreview bool
-}
-
-// values returns a url.Values representation of MessageConfig.
-func (config MessageConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
- v.Add("text", config.Text)
- v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
-
- return v, nil
-}
-
-// method returns Telegram API method name for sending Message.
-func (config MessageConfig) method() string {
- return "sendMessage"
-}
-
-// ForwardConfig contains information about a ForwardMessage request.
-type ForwardConfig struct {
- BaseChat
- FromChatID int64 // required
- FromChannelUsername string
- MessageID int // required
-}
-
-// values returns a url.Values representation of ForwardConfig.
-func (config ForwardConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
- v.Add("from_chat_id", strconv.FormatInt(config.FromChatID, 10))
- v.Add("message_id", strconv.Itoa(config.MessageID))
- return v, nil
-}
-
-// method returns Telegram API method name for sending Forward.
-func (config ForwardConfig) method() string {
- return "forwardMessage"
-}
-
-// PhotoConfig contains information about a SendPhoto request.
-type PhotoConfig struct {
- BaseFile
- Caption string
- ParseMode string
-}
-
-// Params returns a map[string]string representation of PhotoConfig.
-func (config PhotoConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Caption != "" {
- params["caption"] = config.Caption
- if config.ParseMode != "" {
- params["parse_mode"] = config.ParseMode
- }
- }
-
- return params, nil
-}
-
-// Values returns a url.Values representation of PhotoConfig.
-func (config PhotoConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Caption != "" {
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
- }
-
- return v, nil
-}
-
-// name returns the field name for the Photo.
-func (config PhotoConfig) name() string {
- return "photo"
-}
-
-// method returns Telegram API method name for sending Photo.
-func (config PhotoConfig) method() string {
- return "sendPhoto"
-}
-
-// AudioConfig contains information about a SendAudio request.
-type AudioConfig struct {
- BaseFile
- Caption string
- ParseMode string
- Duration int
- Performer string
- Title string
-}
-
-// values returns a url.Values representation of AudioConfig.
-func (config AudioConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Duration != 0 {
- v.Add("duration", strconv.Itoa(config.Duration))
- }
-
- if config.Performer != "" {
- v.Add("performer", config.Performer)
- }
- if config.Title != "" {
- v.Add("title", config.Title)
- }
- if config.Caption != "" {
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
- }
-
- return v, nil
-}
-
-// params returns a map[string]string representation of AudioConfig.
-func (config AudioConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Duration != 0 {
- params["duration"] = strconv.Itoa(config.Duration)
- }
-
- if config.Performer != "" {
- params["performer"] = config.Performer
- }
- if config.Title != "" {
- params["title"] = config.Title
- }
- if config.Caption != "" {
- params["caption"] = config.Caption
- if config.ParseMode != "" {
- params["parse_mode"] = config.ParseMode
- }
- }
-
- return params, nil
-}
-
-// name returns the field name for the Audio.
-func (config AudioConfig) name() string {
- return "audio"
-}
-
-// method returns Telegram API method name for sending Audio.
-func (config AudioConfig) method() string {
- return "sendAudio"
-}
-
-// DocumentConfig contains information about a SendDocument request.
-type DocumentConfig struct {
- BaseFile
- Caption string
- ParseMode string
-}
-
-// values returns a url.Values representation of DocumentConfig.
-func (config DocumentConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Caption != "" {
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
- }
-
- return v, nil
-}
-
-// params returns a map[string]string representation of DocumentConfig.
-func (config DocumentConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Caption != "" {
- params["caption"] = config.Caption
- if config.ParseMode != "" {
- params["parse_mode"] = config.ParseMode
- }
- }
-
- return params, nil
-}
-
-// name returns the field name for the Document.
-func (config DocumentConfig) name() string {
- return "document"
-}
-
-// method returns Telegram API method name for sending Document.
-func (config DocumentConfig) method() string {
- return "sendDocument"
-}
-
-// StickerConfig contains information about a SendSticker request.
-type StickerConfig struct {
- BaseFile
-}
-
-// values returns a url.Values representation of StickerConfig.
-func (config StickerConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
-
- return v, nil
-}
-
-// params returns a map[string]string representation of StickerConfig.
-func (config StickerConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- return params, nil
-}
-
-// name returns the field name for the Sticker.
-func (config StickerConfig) name() string {
- return "sticker"
-}
-
-// method returns Telegram API method name for sending Sticker.
-func (config StickerConfig) method() string {
- return "sendSticker"
-}
-
-// VideoConfig contains information about a SendVideo request.
-type VideoConfig struct {
- BaseFile
- Duration int
- Caption string
- ParseMode string
-}
-
-// values returns a url.Values representation of VideoConfig.
-func (config VideoConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Duration != 0 {
- v.Add("duration", strconv.Itoa(config.Duration))
- }
- if config.Caption != "" {
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
- }
-
- return v, nil
-}
-
-// params returns a map[string]string representation of VideoConfig.
-func (config VideoConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Caption != "" {
- params["caption"] = config.Caption
- if config.ParseMode != "" {
- params["parse_mode"] = config.ParseMode
- }
- }
-
- return params, nil
-}
-
-// name returns the field name for the Video.
-func (config VideoConfig) name() string {
- return "video"
-}
-
-// method returns Telegram API method name for sending Video.
-func (config VideoConfig) method() string {
- return "sendVideo"
-}
-
-// AnimationConfig contains information about a SendAnimation request.
-type AnimationConfig struct {
- BaseFile
- Duration int
- Caption string
- ParseMode string
-}
-
-// values returns a url.Values representation of AnimationConfig.
-func (config AnimationConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Duration != 0 {
- v.Add("duration", strconv.Itoa(config.Duration))
- }
- if config.Caption != "" {
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
- }
-
- return v, nil
-}
-
-// params returns a map[string]string representation of AnimationConfig.
-func (config AnimationConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Caption != "" {
- params["caption"] = config.Caption
- if config.ParseMode != "" {
- params["parse_mode"] = config.ParseMode
- }
- }
-
- return params, nil
-}
-
-// name returns the field name for the Animation.
-func (config AnimationConfig) name() string {
- return "animation"
-}
-
-// method returns Telegram API method name for sending Animation.
-func (config AnimationConfig) method() string {
- return "sendAnimation"
-}
-
-// VideoNoteConfig contains information about a SendVideoNote request.
-type VideoNoteConfig struct {
- BaseFile
- Duration int
- Length int
-}
-
-// values returns a url.Values representation of VideoNoteConfig.
-func (config VideoNoteConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Duration != 0 {
- v.Add("duration", strconv.Itoa(config.Duration))
- }
-
- // Telegram API seems to have a bug, if no length is provided or it is 0, it will send an error response
- if config.Length != 0 {
- v.Add("length", strconv.Itoa(config.Length))
- }
-
- return v, nil
-}
-
-// params returns a map[string]string representation of VideoNoteConfig.
-func (config VideoNoteConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Length != 0 {
- params["length"] = strconv.Itoa(config.Length)
- }
- if config.Duration != 0 {
- params["duration"] = strconv.Itoa(config.Duration)
- }
-
- return params, nil
-}
-
-// name returns the field name for the VideoNote.
-func (config VideoNoteConfig) name() string {
- return "video_note"
-}
-
-// method returns Telegram API method name for sending VideoNote.
-func (config VideoNoteConfig) method() string {
- return "sendVideoNote"
-}
-
-// VoiceConfig contains information about a SendVoice request.
-type VoiceConfig struct {
- BaseFile
- Caption string
- ParseMode string
- Duration int
-}
-
-// values returns a url.Values representation of VoiceConfig.
-func (config VoiceConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add(config.name(), config.FileID)
- if config.Duration != 0 {
- v.Add("duration", strconv.Itoa(config.Duration))
- }
- if config.Caption != "" {
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
- }
-
- return v, nil
-}
-
-// params returns a map[string]string representation of VoiceConfig.
-func (config VoiceConfig) params() (map[string]string, error) {
- params, _ := config.BaseFile.params()
-
- if config.Duration != 0 {
- params["duration"] = strconv.Itoa(config.Duration)
- }
- if config.Caption != "" {
- params["caption"] = config.Caption
- if config.ParseMode != "" {
- params["parse_mode"] = config.ParseMode
- }
- }
-
- return params, nil
-}
-
-// name returns the field name for the Voice.
-func (config VoiceConfig) name() string {
- return "voice"
-}
-
-// method returns Telegram API method name for sending Voice.
-func (config VoiceConfig) method() string {
- return "sendVoice"
-}
-
-// MediaGroupConfig contains information about a sendMediaGroup request.
-type MediaGroupConfig struct {
- BaseChat
- InputMedia []interface{}
-}
-
-func (config MediaGroupConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- data, err := json.Marshal(config.InputMedia)
- if err != nil {
- return v, err
- }
-
- v.Add("media", string(data))
-
- return v, nil
-}
-
-func (config MediaGroupConfig) method() string {
- return "sendMediaGroup"
-}
-
-// LocationConfig contains information about a SendLocation request.
-type LocationConfig struct {
- BaseChat
- Latitude float64 // required
- Longitude float64 // required
-}
-
-// values returns a url.Values representation of LocationConfig.
-func (config LocationConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
- v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
-
- return v, nil
-}
-
-// method returns Telegram API method name for sending Location.
-func (config LocationConfig) method() string {
- return "sendLocation"
-}
-
-// VenueConfig contains information about a SendVenue request.
-type VenueConfig struct {
- BaseChat
- Latitude float64 // required
- Longitude float64 // required
- Title string // required
- Address string // required
- FoursquareID string
-}
-
-func (config VenueConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add("latitude", strconv.FormatFloat(config.Latitude, 'f', 6, 64))
- v.Add("longitude", strconv.FormatFloat(config.Longitude, 'f', 6, 64))
- v.Add("title", config.Title)
- v.Add("address", config.Address)
- if config.FoursquareID != "" {
- v.Add("foursquare_id", config.FoursquareID)
- }
-
- return v, nil
-}
-
-func (config VenueConfig) method() string {
- return "sendVenue"
-}
-
-// ContactConfig allows you to send a contact.
-type ContactConfig struct {
- BaseChat
- PhoneNumber string
- FirstName string
- LastName string
-}
-
-func (config ContactConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add("phone_number", config.PhoneNumber)
- v.Add("first_name", config.FirstName)
- v.Add("last_name", config.LastName)
-
- return v, nil
-}
-
-func (config ContactConfig) method() string {
- return "sendContact"
-}
-
-// GameConfig allows you to send a game.
-type GameConfig struct {
- BaseChat
- GameShortName string
-}
-
-func (config GameConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
-
- v.Add("game_short_name", config.GameShortName)
-
- return v, nil
-}
-
-func (config GameConfig) method() string {
- return "sendGame"
-}
-
-// SetGameScoreConfig allows you to update the game score in a chat.
-type SetGameScoreConfig struct {
- UserID int
- Score int
- Force bool
- DisableEditMessage bool
- ChatID int64
- ChannelUsername string
- MessageID int
- InlineMessageID string
-}
-
-func (config SetGameScoreConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("user_id", strconv.Itoa(config.UserID))
- v.Add("score", strconv.Itoa(config.Score))
- if config.InlineMessageID == "" {
- if config.ChannelUsername == "" {
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- } else {
- v.Add("chat_id", config.ChannelUsername)
- }
- v.Add("message_id", strconv.Itoa(config.MessageID))
- } else {
- v.Add("inline_message_id", config.InlineMessageID)
- }
- v.Add("disable_edit_message", strconv.FormatBool(config.DisableEditMessage))
-
- return v, nil
-}
-
-func (config SetGameScoreConfig) method() string {
- return "setGameScore"
-}
-
-// GetGameHighScoresConfig allows you to fetch the high scores for a game.
-type GetGameHighScoresConfig struct {
- UserID int
- ChatID int
- ChannelUsername string
- MessageID int
- InlineMessageID string
-}
-
-func (config GetGameHighScoresConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("user_id", strconv.Itoa(config.UserID))
- if config.InlineMessageID == "" {
- if config.ChannelUsername == "" {
- v.Add("chat_id", strconv.Itoa(config.ChatID))
- } else {
- v.Add("chat_id", config.ChannelUsername)
- }
- v.Add("message_id", strconv.Itoa(config.MessageID))
- } else {
- v.Add("inline_message_id", config.InlineMessageID)
- }
-
- return v, nil
-}
-
-func (config GetGameHighScoresConfig) method() string {
- return "getGameHighScores"
-}
-
-// ChatActionConfig contains information about a SendChatAction request.
-type ChatActionConfig struct {
- BaseChat
- Action string // required
-}
-
-// values returns a url.Values representation of ChatActionConfig.
-func (config ChatActionConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
- v.Add("action", config.Action)
- return v, nil
-}
-
-// method returns Telegram API method name for sending ChatAction.
-func (config ChatActionConfig) method() string {
- return "sendChatAction"
-}
-
-// EditMessageTextConfig allows you to modify the text in a message.
-type EditMessageTextConfig struct {
- BaseEdit
- Text string
- ParseMode string
- DisableWebPagePreview bool
-}
-
-func (config EditMessageTextConfig) values() (url.Values, error) {
- v, err := config.BaseEdit.values()
- if err != nil {
- return v, err
- }
-
- v.Add("text", config.Text)
- v.Add("parse_mode", config.ParseMode)
- v.Add("disable_web_page_preview", strconv.FormatBool(config.DisableWebPagePreview))
-
- return v, nil
-}
-
-func (config EditMessageTextConfig) method() string {
- return "editMessageText"
-}
-
-// EditMessageCaptionConfig allows you to modify the caption of a message.
-type EditMessageCaptionConfig struct {
- BaseEdit
- Caption string
- ParseMode string
-}
-
-func (config EditMessageCaptionConfig) values() (url.Values, error) {
- v, _ := config.BaseEdit.values()
-
- v.Add("caption", config.Caption)
- if config.ParseMode != "" {
- v.Add("parse_mode", config.ParseMode)
- }
-
- return v, nil
-}
-
-func (config EditMessageCaptionConfig) method() string {
- return "editMessageCaption"
-}
-
-// EditMessageReplyMarkupConfig allows you to modify the reply markup
-// of a message.
-type EditMessageReplyMarkupConfig struct {
- BaseEdit
-}
-
-func (config EditMessageReplyMarkupConfig) values() (url.Values, error) {
- return config.BaseEdit.values()
-}
-
-func (config EditMessageReplyMarkupConfig) method() string {
- return "editMessageReplyMarkup"
-}
-
-// UserProfilePhotosConfig contains information about a
-// GetUserProfilePhotos request.
-type UserProfilePhotosConfig struct {
- UserID int
- Offset int
- Limit int
-}
-
-// FileConfig has information about a file hosted on Telegram.
-type FileConfig struct {
- FileID string
-}
-
-// UpdateConfig contains information about a GetUpdates request.
-type UpdateConfig struct {
- Offset int
- Limit int
- Timeout int
-}
-
-// WebhookConfig contains information about a SetWebhook request.
-type WebhookConfig struct {
- URL *url.URL
- Certificate interface{}
- MaxConnections int
-}
-
-// FileBytes contains information about a set of bytes to upload
-// as a File.
-type FileBytes struct {
- Name string
- Bytes []byte
-}
-
-// FileReader contains information about a reader to upload as a File.
-// If Size is -1, it will read the entire Reader into memory to
-// calculate a Size.
-type FileReader struct {
- Name string
- Reader io.Reader
- Size int64
-}
-
-// InlineConfig contains information on making an InlineQuery response.
-type InlineConfig struct {
- InlineQueryID string `json:"inline_query_id"`
- Results []interface{} `json:"results"`
- CacheTime int `json:"cache_time"`
- IsPersonal bool `json:"is_personal"`
- NextOffset string `json:"next_offset"`
- SwitchPMText string `json:"switch_pm_text"`
- SwitchPMParameter string `json:"switch_pm_parameter"`
-}
-
-// CallbackConfig contains information on making a CallbackQuery response.
-type CallbackConfig struct {
- CallbackQueryID string `json:"callback_query_id"`
- Text string `json:"text"`
- ShowAlert bool `json:"show_alert"`
- URL string `json:"url"`
- CacheTime int `json:"cache_time"`
-}
-
-// ChatMemberConfig contains information about a user in a chat for use
-// with administrative functions such as kicking or unbanning a user.
-type ChatMemberConfig struct {
- ChatID int64
- SuperGroupUsername string
- ChannelUsername string
- UserID int
-}
-
-// KickChatMemberConfig contains extra fields to kick user
-type KickChatMemberConfig struct {
- ChatMemberConfig
- UntilDate int64
-}
-
-// RestrictChatMemberConfig contains fields to restrict members of chat
-type RestrictChatMemberConfig struct {
- ChatMemberConfig
- UntilDate int64
- CanSendMessages *bool
- CanSendMediaMessages *bool
- CanSendOtherMessages *bool
- CanAddWebPagePreviews *bool
-}
-
-// PromoteChatMemberConfig contains fields to promote members of chat
-type PromoteChatMemberConfig struct {
- ChatMemberConfig
- CanChangeInfo *bool
- CanPostMessages *bool
- CanEditMessages *bool
- CanDeleteMessages *bool
- CanInviteUsers *bool
- CanRestrictMembers *bool
- CanPinMessages *bool
- CanPromoteMembers *bool
-}
-
-// ChatConfig contains information about getting information on a chat.
-type ChatConfig struct {
- ChatID int64
- SuperGroupUsername string
-}
-
-// ChatConfigWithUser contains information about getting information on
-// a specific user within a chat.
-type ChatConfigWithUser struct {
- ChatID int64
- SuperGroupUsername string
- UserID int
-}
-
-// InvoiceConfig contains information for sendInvoice request.
-type InvoiceConfig struct {
- BaseChat
- Title string // required
- Description string // required
- Payload string // required
- ProviderToken string // required
- StartParameter string // required
- Currency string // required
- Prices *[]LabeledPrice // required
- PhotoURL string
- PhotoSize int
- PhotoWidth int
- PhotoHeight int
- NeedName bool
- NeedPhoneNumber bool
- NeedEmail bool
- NeedShippingAddress bool
- IsFlexible bool
-}
-
-func (config InvoiceConfig) values() (url.Values, error) {
- v, err := config.BaseChat.values()
- if err != nil {
- return v, err
- }
- v.Add("title", config.Title)
- v.Add("description", config.Description)
- v.Add("payload", config.Payload)
- v.Add("provider_token", config.ProviderToken)
- v.Add("start_parameter", config.StartParameter)
- v.Add("currency", config.Currency)
- data, err := json.Marshal(config.Prices)
- if err != nil {
- return v, err
- }
- v.Add("prices", string(data))
- if config.PhotoURL != "" {
- v.Add("photo_url", config.PhotoURL)
- }
- if config.PhotoSize != 0 {
- v.Add("photo_size", strconv.Itoa(config.PhotoSize))
- }
- if config.PhotoWidth != 0 {
- v.Add("photo_width", strconv.Itoa(config.PhotoWidth))
- }
- if config.PhotoHeight != 0 {
- v.Add("photo_height", strconv.Itoa(config.PhotoHeight))
- }
- if config.NeedName != false {
- v.Add("need_name", strconv.FormatBool(config.NeedName))
- }
- if config.NeedPhoneNumber != false {
- v.Add("need_phone_number", strconv.FormatBool(config.NeedPhoneNumber))
- }
- if config.NeedEmail != false {
- v.Add("need_email", strconv.FormatBool(config.NeedEmail))
- }
- if config.NeedShippingAddress != false {
- v.Add("need_shipping_address", strconv.FormatBool(config.NeedShippingAddress))
- }
- if config.IsFlexible != false {
- v.Add("is_flexible", strconv.FormatBool(config.IsFlexible))
- }
-
- return v, nil
-}
-
-func (config InvoiceConfig) method() string {
- return "sendInvoice"
-}
-
-// ShippingConfig contains information for answerShippingQuery request.
-type ShippingConfig struct {
- ShippingQueryID string // required
- OK bool // required
- ShippingOptions *[]ShippingOption
- ErrorMessage string
-}
-
-// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
-type PreCheckoutConfig struct {
- PreCheckoutQueryID string // required
- OK bool // required
- ErrorMessage string
-}
-
-// DeleteMessageConfig contains information of a message in a chat to delete.
-type DeleteMessageConfig struct {
- ChatID int64
- MessageID int
-}
-
-func (config DeleteMessageConfig) method() string {
- return "deleteMessage"
-}
-
-func (config DeleteMessageConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- v.Add("message_id", strconv.Itoa(config.MessageID))
-
- return v, nil
-}
-
-// PinChatMessageConfig contains information of a message in a chat to pin.
-type PinChatMessageConfig struct {
- ChatID int64
- MessageID int
- DisableNotification bool
-}
-
-func (config PinChatMessageConfig) method() string {
- return "pinChatMessage"
-}
-
-func (config PinChatMessageConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- v.Add("message_id", strconv.Itoa(config.MessageID))
- v.Add("disable_notification", strconv.FormatBool(config.DisableNotification))
-
- return v, nil
-}
-
-// UnpinChatMessageConfig contains information of chat to unpin.
-type UnpinChatMessageConfig struct {
- ChatID int64
-}
-
-func (config UnpinChatMessageConfig) method() string {
- return "unpinChatMessage"
-}
-
-func (config UnpinChatMessageConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
-
- return v, nil
-}
-
-// SetChatTitleConfig contains information for change chat title.
-type SetChatTitleConfig struct {
- ChatID int64
- Title string
-}
-
-func (config SetChatTitleConfig) method() string {
- return "setChatTitle"
-}
-
-func (config SetChatTitleConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- v.Add("title", config.Title)
-
- return v, nil
-}
-
-// SetChatDescriptionConfig contains information for change chat description.
-type SetChatDescriptionConfig struct {
- ChatID int64
- Description string
-}
-
-func (config SetChatDescriptionConfig) method() string {
- return "setChatDescription"
-}
-
-func (config SetChatDescriptionConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
- v.Add("description", config.Description)
-
- return v, nil
-}
-
-// SetChatPhotoConfig contains information for change chat photo
-type SetChatPhotoConfig struct {
- BaseFile
-}
-
-// name returns the field name for the Photo.
-func (config SetChatPhotoConfig) name() string {
- return "photo"
-}
-
-// method returns Telegram API method name for sending Photo.
-func (config SetChatPhotoConfig) method() string {
- return "setChatPhoto"
-}
-
-// DeleteChatPhotoConfig contains information for delete chat photo.
-type DeleteChatPhotoConfig struct {
- ChatID int64
-}
-
-func (config DeleteChatPhotoConfig) method() string {
- return "deleteChatPhoto"
-}
-
-func (config DeleteChatPhotoConfig) values() (url.Values, error) {
- v := url.Values{}
-
- v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
-
- return v, nil
-}
-
-// GetStickerSetConfig contains information for get sticker set.
-type GetStickerSetConfig struct {
- Name string
-}
-
-func (config GetStickerSetConfig) method() string {
- return "getStickerSet"
-}
-
-func (config GetStickerSetConfig) values() (url.Values, error) {
- v := url.Values{}
- v.Add("name", config.Name)
- return v, nil
-}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go
deleted file mode 100644
index 6e295cab..00000000
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/types.go
+++ /dev/null
@@ -1,990 +0,0 @@
-package tgbotapi
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "net/url"
- "strings"
- "time"
-)
-
-// APIResponse is a response from the Telegram API with the result
-// stored raw.
-type APIResponse struct {
- Ok bool `json:"ok"`
- Result json.RawMessage `json:"result"`
- ErrorCode int `json:"error_code"`
- Description string `json:"description"`
- Parameters *ResponseParameters `json:"parameters"`
-}
-
-// ResponseParameters are various errors that can be returned in APIResponse.
-type ResponseParameters struct {
- MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional
- RetryAfter int `json:"retry_after"` // optional
-}
-
-// Update is an update response, from GetUpdates.
-type Update struct {
- UpdateID int `json:"update_id"`
- Message *Message `json:"message"`
- EditedMessage *Message `json:"edited_message"`
- ChannelPost *Message `json:"channel_post"`
- EditedChannelPost *Message `json:"edited_channel_post"`
- InlineQuery *InlineQuery `json:"inline_query"`
- ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result"`
- CallbackQuery *CallbackQuery `json:"callback_query"`
- ShippingQuery *ShippingQuery `json:"shipping_query"`
- PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query"`
-}
-
-// UpdatesChannel is the channel for getting updates.
-type UpdatesChannel <-chan Update
-
-// Clear discards all unprocessed incoming updates.
-func (ch UpdatesChannel) Clear() {
- for len(ch) != 0 {
- <-ch
- }
-}
-
-// User is a user on Telegram.
-type User struct {
- ID int `json:"id"`
- FirstName string `json:"first_name"`
- LastName string `json:"last_name"` // optional
- UserName string `json:"username"` // optional
- LanguageCode string `json:"language_code"` // optional
- IsBot bool `json:"is_bot"` // optional
-}
-
-// String displays a simple text version of a user.
-//
-// It is normally a user's username, but falls back to a first/last
-// name as available.
-func (u *User) String() string {
- if u == nil {
- return ""
- }
- if u.UserName != "" {
- return u.UserName
- }
-
- name := u.FirstName
- if u.LastName != "" {
- name += " " + u.LastName
- }
-
- return name
-}
-
-// GroupChat is a group chat.
-type GroupChat struct {
- ID int `json:"id"`
- Title string `json:"title"`
-}
-
-// ChatPhoto represents a chat photo.
-type ChatPhoto struct {
- SmallFileID string `json:"small_file_id"`
- BigFileID string `json:"big_file_id"`
-}
-
-// Chat contains information about the place a message was sent.
-type Chat struct {
- ID int64 `json:"id"`
- Type string `json:"type"`
- Title string `json:"title"` // optional
- UserName string `json:"username"` // optional
- FirstName string `json:"first_name"` // optional
- LastName string `json:"last_name"` // optional
- AllMembersAreAdmins bool `json:"all_members_are_administrators"` // optional
- Photo *ChatPhoto `json:"photo"`
- Description string `json:"description,omitempty"` // optional
- InviteLink string `json:"invite_link,omitempty"` // optional
- PinnedMessage *Message `json:"pinned_message"` // optional
-}
-
-// IsPrivate returns if the Chat is a private conversation.
-func (c Chat) IsPrivate() bool {
- return c.Type == "private"
-}
-
-// IsGroup returns if the Chat is a group.
-func (c Chat) IsGroup() bool {
- return c.Type == "group"
-}
-
-// IsSuperGroup returns if the Chat is a supergroup.
-func (c Chat) IsSuperGroup() bool {
- return c.Type == "supergroup"
-}
-
-// IsChannel returns if the Chat is a channel.
-func (c Chat) IsChannel() bool {
- return c.Type == "channel"
-}
-
-// ChatConfig returns a ChatConfig struct for chat related methods.
-func (c Chat) ChatConfig() ChatConfig {
- return ChatConfig{ChatID: c.ID}
-}
-
-// Message is returned by almost every request, and contains data about
-// almost anything.
-type Message struct {
- MessageID int `json:"message_id"`
- From *User `json:"from"` // optional
- Date int `json:"date"`
- Chat *Chat `json:"chat"`
- ForwardFrom *User `json:"forward_from"` // optional
- ForwardFromChat *Chat `json:"forward_from_chat"` // optional
- ForwardFromMessageID int `json:"forward_from_message_id"` // optional
- ForwardDate int `json:"forward_date"` // optional
- ReplyToMessage *Message `json:"reply_to_message"` // optional
- 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
- Game *Game `json:"game"` // optional
- Photo *[]PhotoSize `json:"photo"` // optional
- Sticker *Sticker `json:"sticker"` // optional
- Video *Video `json:"video"` // optional
- VideoNote *VideoNote `json:"video_note"` // optional
- Voice *Voice `json:"voice"` // optional
- Caption string `json:"caption"` // optional
- Contact *Contact `json:"contact"` // optional
- Location *Location `json:"location"` // optional
- Venue *Venue `json:"venue"` // optional
- NewChatMembers *[]User `json:"new_chat_members"` // optional
- LeftChatMember *User `json:"left_chat_member"` // optional
- NewChatTitle string `json:"new_chat_title"` // optional
- NewChatPhoto *[]PhotoSize `json:"new_chat_photo"` // optional
- DeleteChatPhoto bool `json:"delete_chat_photo"` // optional
- GroupChatCreated bool `json:"group_chat_created"` // optional
- SuperGroupChatCreated bool `json:"supergroup_chat_created"` // optional
- ChannelChatCreated bool `json:"channel_chat_created"` // optional
- MigrateToChatID int64 `json:"migrate_to_chat_id"` // optional
- MigrateFromChatID int64 `json:"migrate_from_chat_id"` // optional
- PinnedMessage *Message `json:"pinned_message"` // optional
- Invoice *Invoice `json:"invoice"` // optional
- SuccessfulPayment *SuccessfulPayment `json:"successful_payment"` // optional
- PassportData *PassportData `json:"passport_data,omitempty"` // optional
-}
-
-// Time converts the message timestamp into a Time.
-func (m *Message) Time() time.Time {
- return time.Unix(int64(m.Date), 0)
-}
-
-// IsCommand returns true if message starts with a "bot_command" entity.
-func (m *Message) IsCommand() bool {
- if m.Entities == nil || len(*m.Entities) == 0 {
- return false
- }
-
- entity := (*m.Entities)[0]
- return entity.Offset == 0 && entity.IsCommand()
-}
-
-// Command checks if the message was a command and if it was, returns the
-// command. If the Message was not a command, it returns an empty string.
-//
-// If the command contains the at name syntax, it is removed. Use
-// CommandWithAt() if you do not want that.
-func (m *Message) Command() string {
- command := m.CommandWithAt()
-
- if i := strings.Index(command, "@"); i != -1 {
- command = command[:i]
- }
-
- return command
-}
-
-// CommandWithAt checks if the message was a command and if it was, returns the
-// command. If the Message was not a command, it returns an empty string.
-//
-// If the command contains the at name syntax, it is not removed. Use Command()
-// if you want that.
-func (m *Message) CommandWithAt() string {
- if !m.IsCommand() {
- return ""
- }
-
- // IsCommand() checks that the message begins with a bot_command entity
- entity := (*m.Entities)[0]
- return m.Text[1:entity.Length]
-}
-
-// CommandArguments checks if the message was a command and if it was,
-// returns all text after the command name. If the Message was not a
-// command, it returns an empty string.
-//
-// Note: The first character after the command name is omitted:
-// - "/foo bar baz" yields "bar baz", not " bar baz"
-// - "/foo-bar baz" yields "bar baz", too
-// Even though the latter is not a command conforming to the spec, the API
-// marks "/foo" as command entity.
-func (m *Message) CommandArguments() string {
- if !m.IsCommand() {
- return ""
- }
-
- // IsCommand() checks that the message begins with a bot_command entity
- entity := (*m.Entities)[0]
- if len(m.Text) == entity.Length {
- return "" // The command makes up the whole message
- }
-
- return m.Text[entity.Length+1:]
-}
-
-// MessageEntity contains information about data in a Message.
-type MessageEntity struct {
- Type string `json:"type"`
- Offset int `json:"offset"`
- Length int `json:"length"`
- URL string `json:"url"` // optional
- User *User `json:"user"` // optional
-}
-
-// ParseURL attempts to parse a URL contained within a MessageEntity.
-func (e MessageEntity) ParseURL() (*url.URL, error) {
- if e.URL == "" {
- return nil, errors.New(ErrBadURL)
- }
-
- 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.
-type PhotoSize struct {
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- FileSize int `json:"file_size"` // optional
-}
-
-// Audio contains information about audio.
-type Audio struct {
- FileID string `json:"file_id"`
- Duration int `json:"duration"`
- Performer string `json:"performer"` // optional
- Title string `json:"title"` // optional
- MimeType string `json:"mime_type"` // optional
- FileSize int `json:"file_size"` // optional
-}
-
-// Document contains information about a document.
-type Document struct {
- FileID string `json:"file_id"`
- Thumbnail *PhotoSize `json:"thumb"` // optional
- FileName string `json:"file_name"` // optional
- MimeType string `json:"mime_type"` // optional
- FileSize int `json:"file_size"` // optional
-}
-
-// Sticker contains information about a sticker.
-type Sticker struct {
- FileUniqueID string `json:"file_unique_id"`
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- Thumbnail *PhotoSize `json:"thumb"` // optional
- Emoji string `json:"emoji"` // optional
- FileSize int `json:"file_size"` // optional
- SetName string `json:"set_name"` // optional
- IsAnimated bool `json:"is_animated"` // optional
-}
-
-type StickerSet struct {
- Name string `json:"name"`
- Title string `json:"title"`
- IsAnimated bool `json:"is_animated"`
- ContainsMasks bool `json:"contains_masks"`
- Stickers []Sticker `json:"stickers"`
-}
-
-// ChatAnimation contains information about an animation.
-type ChatAnimation struct {
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- Duration int `json:"duration"`
- Thumbnail *PhotoSize `json:"thumb"` // optional
- FileName string `json:"file_name"` // optional
- MimeType string `json:"mime_type"` // optional
- FileSize int `json:"file_size"` // optional
-}
-
-// Video contains information about a video.
-type Video struct {
- FileID string `json:"file_id"`
- Width int `json:"width"`
- Height int `json:"height"`
- Duration int `json:"duration"`
- Thumbnail *PhotoSize `json:"thumb"` // optional
- MimeType string `json:"mime_type"` // optional
- FileSize int `json:"file_size"` // optional
-}
-
-// VideoNote contains information about a video.
-type VideoNote struct {
- FileID string `json:"file_id"`
- Length int `json:"length"`
- Duration int `json:"duration"`
- Thumbnail *PhotoSize `json:"thumb"` // optional
- FileSize int `json:"file_size"` // optional
-}
-
-// Voice contains information about a voice.
-type Voice struct {
- FileID string `json:"file_id"`
- Duration int `json:"duration"`
- MimeType string `json:"mime_type"` // optional
- FileSize int `json:"file_size"` // optional
-}
-
-// Contact contains information about a contact.
-//
-// Note that LastName and UserID may be empty.
-type Contact struct {
- PhoneNumber string `json:"phone_number"`
- FirstName string `json:"first_name"`
- LastName string `json:"last_name"` // optional
- UserID int `json:"user_id"` // optional
-}
-
-// Location contains information about a place.
-type Location struct {
- Longitude float64 `json:"longitude"`
- Latitude float64 `json:"latitude"`
-}
-
-// Venue contains information about a venue, including its Location.
-type Venue struct {
- Location Location `json:"location"`
- Title string `json:"title"`
- Address string `json:"address"`
- FoursquareID string `json:"foursquare_id"` // optional
-}
-
-// UserProfilePhotos contains a set of user profile photos.
-type UserProfilePhotos struct {
- TotalCount int `json:"total_count"`
- Photos [][]PhotoSize `json:"photos"`
-}
-
-// File contains information about a file to download from Telegram.
-type File struct {
- FileID string `json:"file_id"`
- FileSize int `json:"file_size"` // optional
- FilePath string `json:"file_path"` // optional
-}
-
-// Link returns a full path to the download URL for a File.
-//
-// It requires the Bot Token to create the link.
-func (f *File) Link(token string) string {
- return fmt.Sprintf(FileEndpoint, token, f.FilePath)
-}
-
-// ReplyKeyboardMarkup allows the Bot to set a custom keyboard.
-type ReplyKeyboardMarkup struct {
- Keyboard [][]KeyboardButton `json:"keyboard"`
- ResizeKeyboard bool `json:"resize_keyboard"` // optional
- OneTimeKeyboard bool `json:"one_time_keyboard"` // optional
- Selective bool `json:"selective"` // optional
-}
-
-// KeyboardButton is a button within a custom keyboard.
-type KeyboardButton struct {
- Text string `json:"text"`
- RequestContact bool `json:"request_contact"`
- RequestLocation bool `json:"request_location"`
-}
-
-// ReplyKeyboardHide allows the Bot to hide a custom keyboard.
-type ReplyKeyboardHide struct {
- HideKeyboard bool `json:"hide_keyboard"`
- Selective bool `json:"selective"` // optional
-}
-
-// ReplyKeyboardRemove allows the Bot to hide a custom keyboard.
-type ReplyKeyboardRemove struct {
- RemoveKeyboard bool `json:"remove_keyboard"`
- Selective bool `json:"selective"`
-}
-
-// InlineKeyboardMarkup is a custom keyboard presented for an inline bot.
-type InlineKeyboardMarkup struct {
- InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
-}
-
-// InlineKeyboardButton is a button within a custom keyboard for
-// inline query responses.
-//
-// Note that some values are references as even an empty string
-// will change behavior.
-//
-// CallbackGame, if set, MUST be first button in first row.
-type InlineKeyboardButton struct {
- Text string `json:"text"`
- URL *string `json:"url,omitempty"` // optional
- CallbackData *string `json:"callback_data,omitempty"` // optional
- SwitchInlineQuery *string `json:"switch_inline_query,omitempty"` // optional
- SwitchInlineQueryCurrentChat *string `json:"switch_inline_query_current_chat,omitempty"` // optional
- CallbackGame *CallbackGame `json:"callback_game,omitempty"` // optional
- Pay bool `json:"pay,omitempty"` // optional
-}
-
-// CallbackQuery is data sent when a keyboard button with callback data
-// is clicked.
-type CallbackQuery struct {
- ID string `json:"id"`
- From *User `json:"from"`
- Message *Message `json:"message"` // optional
- InlineMessageID string `json:"inline_message_id"` // optional
- ChatInstance string `json:"chat_instance"`
- Data string `json:"data"` // optional
- GameShortName string `json:"game_short_name"` // optional
-}
-
-// ForceReply allows the Bot to have users directly reply to it without
-// additional interaction.
-type ForceReply struct {
- ForceReply bool `json:"force_reply"`
- Selective bool `json:"selective"` // optional
-}
-
-// ChatMember is information about a member in a chat.
-type ChatMember struct {
- User *User `json:"user"`
- Status string `json:"status"`
- UntilDate int64 `json:"until_date,omitempty"` // optional
- CanBeEdited bool `json:"can_be_edited,omitempty"` // optional
- CanChangeInfo bool `json:"can_change_info,omitempty"` // optional
- CanPostMessages bool `json:"can_post_messages,omitempty"` // optional
- CanEditMessages bool `json:"can_edit_messages,omitempty"` // optional
- CanDeleteMessages bool `json:"can_delete_messages,omitempty"` // optional
- CanInviteUsers bool `json:"can_invite_users,omitempty"` // optional
- CanRestrictMembers bool `json:"can_restrict_members,omitempty"` // optional
- CanPinMessages bool `json:"can_pin_messages,omitempty"` // optional
- CanPromoteMembers bool `json:"can_promote_members,omitempty"` // optional
- CanSendMessages bool `json:"can_send_messages,omitempty"` // optional
- CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"` // optional
- CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"` // optional
- CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"` // optional
-}
-
-// IsCreator returns if the ChatMember was the creator of the chat.
-func (chat ChatMember) IsCreator() bool { return chat.Status == "creator" }
-
-// IsAdministrator returns if the ChatMember is a chat administrator.
-func (chat ChatMember) IsAdministrator() bool { return chat.Status == "administrator" }
-
-// IsMember returns if the ChatMember is a current member of the chat.
-func (chat ChatMember) IsMember() bool { return chat.Status == "member" }
-
-// HasLeft returns if the ChatMember left the chat.
-func (chat ChatMember) HasLeft() bool { return chat.Status == "left" }
-
-// WasKicked returns if the ChatMember was kicked from the chat.
-func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" }
-
-// Game is a game within Telegram.
-type Game struct {
- Title string `json:"title"`
- Description string `json:"description"`
- Photo []PhotoSize `json:"photo"`
- Text string `json:"text"`
- TextEntities []MessageEntity `json:"text_entities"`
- Animation Animation `json:"animation"`
-}
-
-// Animation is a GIF animation demonstrating the game.
-type Animation struct {
- FileID string `json:"file_id"`
- Thumb PhotoSize `json:"thumb"`
- FileName string `json:"file_name"`
- MimeType string `json:"mime_type"`
- FileSize int `json:"file_size"`
-}
-
-// GameHighScore is a user's score and position on the leaderboard.
-type GameHighScore struct {
- Position int `json:"position"`
- User User `json:"user"`
- Score int `json:"score"`
-}
-
-// CallbackGame is for starting a game in an inline keyboard button.
-type CallbackGame struct{}
-
-// WebhookInfo is information about a currently set webhook.
-type WebhookInfo struct {
- URL string `json:"url"`
- HasCustomCertificate bool `json:"has_custom_certificate"`
- PendingUpdateCount int `json:"pending_update_count"`
- LastErrorDate int `json:"last_error_date"` // optional
- LastErrorMessage string `json:"last_error_message"` // optional
-}
-
-// IsSet returns true if a webhook is currently set.
-func (info WebhookInfo) IsSet() bool {
- return info.URL != ""
-}
-
-// InputMediaPhoto contains a photo for displaying as part of a media group.
-type InputMediaPhoto struct {
- Type string `json:"type"`
- Media string `json:"media"`
- Caption string `json:"caption"`
- ParseMode string `json:"parse_mode"`
-}
-
-// InputMediaVideo contains a video for displaying as part of a media group.
-type InputMediaVideo struct {
- Type string `json:"type"`
- Media string `json:"media"`
- // thumb intentionally missing as it is not currently compatible
- Caption string `json:"caption"`
- ParseMode string `json:"parse_mode"`
- Width int `json:"width"`
- Height int `json:"height"`
- Duration int `json:"duration"`
- SupportsStreaming bool `json:"supports_streaming"`
-}
-
-// InlineQuery is a Query from Telegram for an inline request.
-type InlineQuery struct {
- ID string `json:"id"`
- From *User `json:"from"`
- Location *Location `json:"location"` // optional
- Query string `json:"query"`
- Offset string `json:"offset"`
-}
-
-// InlineQueryResultArticle is an inline query response article.
-type InlineQueryResultArticle struct {
- Type string `json:"type"` // required
- ID string `json:"id"` // required
- Title string `json:"title"` // required
- InputMessageContent interface{} `json:"input_message_content,omitempty"` // required
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- URL string `json:"url"`
- HideURL bool `json:"hide_url"`
- Description string `json:"description"`
- ThumbURL string `json:"thumb_url"`
- ThumbWidth int `json:"thumb_width"`
- ThumbHeight int `json:"thumb_height"`
-}
-
-// InlineQueryResultPhoto is an inline query response photo.
-type InlineQueryResultPhoto struct {
- Type string `json:"type"` // required
- ID string `json:"id"` // required
- URL string `json:"photo_url"` // required
- MimeType string `json:"mime_type"`
- Width int `json:"photo_width"`
- Height int `json:"photo_height"`
- ThumbURL string `json:"thumb_url"`
- Title string `json:"title"`
- Description string `json:"description"`
- Caption string `json:"caption"`
- ParseMode string `json:"parse_mode"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
-}
-
-// 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
- ID string `json:"id"` // required
- URL string `json:"gif_url"` // required
- ThumbURL string `json:"thumb_url"` // required
- Width int `json:"gif_width,omitempty"`
- Height int `json:"gif_height,omitempty"`
- Duration int `json:"gif_duration,omitempty"`
- Title string `json:"title,omitempty"`
- Caption string `json:"caption,omitempty"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
-}
-
-// 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
- ID string `json:"id"` // required
- URL string `json:"mpeg4_url"` // required
- Width int `json:"mpeg4_width"`
- Height int `json:"mpeg4_height"`
- Duration int `json:"mpeg4_duration"`
- ThumbURL string `json:"thumb_url"`
- Title string `json:"title"`
- Caption string `json:"caption"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
-}
-
-// 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
- ID string `json:"id"` // required
- URL string `json:"video_url"` // required
- MimeType string `json:"mime_type"` // required
- ThumbURL string `json:"thumb_url"`
- Title string `json:"title"`
- Caption string `json:"caption"`
- Width int `json:"video_width"`
- Height int `json:"video_height"`
- Duration int `json:"video_duration"`
- Description string `json:"description"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
-}
-
-// 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
- ID string `json:"id"` // required
- URL string `json:"audio_url"` // required
- Title string `json:"title"` // required
- Caption string `json:"caption"`
- Performer string `json:"performer"`
- Duration int `json:"audio_duration"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
-}
-
-// 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
- ID string `json:"id"` // required
- URL string `json:"voice_url"` // required
- Title string `json:"title"` // required
- Caption string `json:"caption"`
- Duration int `json:"voice_duration"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
-}
-
-// 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
- ID string `json:"id"` // required
- Title string `json:"title"` // required
- Caption string `json:"caption"`
- URL string `json:"document_url"` // required
- MimeType string `json:"mime_type"` // required
- Description string `json:"description"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
- ThumbURL string `json:"thumb_url"`
- ThumbWidth int `json:"thumb_width"`
- ThumbHeight int `json:"thumb_height"`
-}
-
-// 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
- ID string `json:"id"` // required
- Latitude float64 `json:"latitude"` // required
- Longitude float64 `json:"longitude"` // required
- Title string `json:"title"` // required
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
- InputMessageContent interface{} `json:"input_message_content,omitempty"`
- ThumbURL string `json:"thumb_url"`
- ThumbWidth int `json:"thumb_width"`
- ThumbHeight int `json:"thumb_height"`
-}
-
-// 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"`
- ID string `json:"id"`
- GameShortName string `json:"game_short_name"`
- ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
-}
-
-// ChosenInlineResult is an inline query result chosen by a User
-type ChosenInlineResult struct {
- ResultID string `json:"result_id"`
- From *User `json:"from"`
- Location *Location `json:"location"`
- InlineMessageID string `json:"inline_message_id"`
- Query string `json:"query"`
-}
-
-// InputTextMessageContent contains text for displaying
-// as an inline query result.
-type InputTextMessageContent struct {
- Text string `json:"message_text"`
- ParseMode string `json:"parse_mode"`
- DisableWebPagePreview bool `json:"disable_web_page_preview"`
-}
-
-// InputLocationMessageContent contains a location for displaying
-// as an inline query result.
-type InputLocationMessageContent struct {
- Latitude float64 `json:"latitude"`
- Longitude float64 `json:"longitude"`
-}
-
-// InputVenueMessageContent contains a venue for displaying
-// as an inline query result.
-type InputVenueMessageContent struct {
- Latitude float64 `json:"latitude"`
- Longitude float64 `json:"longitude"`
- Title string `json:"title"`
- Address string `json:"address"`
- FoursquareID string `json:"foursquare_id"`
-}
-
-// InputContactMessageContent contains a contact for displaying
-// as an inline query result.
-type InputContactMessageContent struct {
- PhoneNumber string `json:"phone_number"`
- FirstName string `json:"first_name"`
- LastName string `json:"last_name"`
-}
-
-// Invoice contains basic information about an invoice.
-type Invoice struct {
- Title string `json:"title"`
- Description string `json:"description"`
- StartParameter string `json:"start_parameter"`
- Currency string `json:"currency"`
- TotalAmount int `json:"total_amount"`
-}
-
-// LabeledPrice represents a portion of the price for goods or services.
-type LabeledPrice struct {
- Label string `json:"label"`
- Amount int `json:"amount"`
-}
-
-// ShippingAddress represents a shipping address.
-type ShippingAddress struct {
- CountryCode string `json:"country_code"`
- State string `json:"state"`
- City string `json:"city"`
- StreetLine1 string `json:"street_line1"`
- StreetLine2 string `json:"street_line2"`
- PostCode string `json:"post_code"`
-}
-
-// OrderInfo represents information about an order.
-type OrderInfo struct {
- Name string `json:"name,omitempty"`
- PhoneNumber string `json:"phone_number,omitempty"`
- Email string `json:"email,omitempty"`
- ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
-}
-
-// ShippingOption represents one shipping option.
-type ShippingOption struct {
- ID string `json:"id"`
- Title string `json:"title"`
- Prices *[]LabeledPrice `json:"prices"`
-}
-
-// SuccessfulPayment contains basic information about a successful payment.
-type SuccessfulPayment struct {
- Currency string `json:"currency"`
- TotalAmount int `json:"total_amount"`
- InvoicePayload string `json:"invoice_payload"`
- ShippingOptionID string `json:"shipping_option_id,omitempty"`
- OrderInfo *OrderInfo `json:"order_info,omitempty"`
- TelegramPaymentChargeID string `json:"telegram_payment_charge_id"`
- ProviderPaymentChargeID string `json:"provider_payment_charge_id"`
-}
-
-// ShippingQuery contains information about an incoming shipping query.
-type ShippingQuery struct {
- ID string `json:"id"`
- From *User `json:"from"`
- InvoicePayload string `json:"invoice_payload"`
- ShippingAddress *ShippingAddress `json:"shipping_address"`
-}
-
-// PreCheckoutQuery contains information about an incoming pre-checkout query.
-type PreCheckoutQuery struct {
- ID string `json:"id"`
- From *User `json:"from"`
- Currency string `json:"currency"`
- TotalAmount int `json:"total_amount"`
- InvoicePayload string `json:"invoice_payload"`
- ShippingOptionID string `json:"shipping_option_id,omitempty"`
- OrderInfo *OrderInfo `json:"order_info,omitempty"`
-}
-
-// Error is an error containing extra information returned by the Telegram API.
-type Error struct {
- Code int
- Message string
- ResponseParameters
-}
-
-func (e Error) Error() string {
- return e.Message
-}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/.gitignore b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/.gitignore
index fb5a5e83..eb7a23b2 100644
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/.gitignore
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/.gitignore
@@ -1,3 +1,4 @@
.idea/
coverage.out
tmp/
+book/
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/LICENSE.txt b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/LICENSE.txt
index b1fef93b..b1fef93b 100644
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/LICENSE.txt
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/LICENSE.txt
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/README.md b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/README.md
index 43b33ed8..45d3e1db 100644
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/README.md
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/README.md
@@ -1,12 +1,14 @@
# Golang bindings for the Telegram Bot API
-[![GoDoc](https://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api?status.svg)](http://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api)
-[![Travis](https://travis-ci.org/go-telegram-bot-api/telegram-bot-api.svg)](https://travis-ci.org/go-telegram-bot-api/telegram-bot-api)
+[![Go Reference](https://pkg.go.dev/badge/github.com/go-telegram-bot-api/telegram-bot-api/v5.svg)](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5)
+[![Test](https://github.com/go-telegram-bot-api/telegram-bot-api/actions/workflows/test.yml/badge.svg)](https://github.com/go-telegram-bot-api/telegram-bot-api/actions/workflows/test.yml)
-All methods are fairly self explanatory, and reading the [godoc](http://godoc.org/github.com/go-telegram-bot-api/telegram-bot-api) page should
+All methods are fairly self-explanatory, and reading the [godoc](https://pkg.go.dev/github.com/go-telegram-bot-api/telegram-bot-api/v5) page should
explain everything. If something isn't clear, open an issue or submit
a pull request.
+There are more tutorials and high-level information on the website, [go-telegram-bot-api.dev](https://go-telegram-bot-api.dev).
+
The scope of this project is just to provide a wrapper around the API
without any additional features. There are other projects for creating
something with plugins and command handlers without having to design
@@ -18,7 +20,7 @@ you want to ask questions or discuss development.
## Example
First, ensure the library is installed and up to date by running
-`go get -u github.com/go-telegram-bot-api/telegram-bot-api`.
+`go get -u github.com/go-telegram-bot-api/telegram-bot-api/v5`.
This is a very simple bot that just displays any gotten updates,
then replies it to that chat.
@@ -29,7 +31,7 @@ package main
import (
"log"
- "github.com/go-telegram-bot-api/telegram-bot-api"
+ tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
func main() {
@@ -45,28 +47,21 @@ func main() {
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
- updates, err := bot.GetUpdatesChan(u)
+ updates := bot.GetUpdatesChan(u)
for update := range updates {
- if update.Message == nil { // ignore any non-Message Updates
- continue
- }
-
- log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
+ if update.Message != nil { // If we got a message
+ log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text)
- msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
- msg.ReplyToMessageID = update.Message.MessageID
+ msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text)
+ msg.ReplyToMessageID = update.Message.MessageID
- bot.Send(msg)
+ bot.Send(msg)
+ }
}
}
```
-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 different kinds of things.
-It's a great place to get started on using keyboards, commands, or other
-kinds of reply markup.
-
If you need to use webhooks (if you wish to run on Google App Engine),
you may use a slightly different method.
@@ -77,7 +72,7 @@ import (
"log"
"net/http"
- "github.com/go-telegram-bot-api/telegram-bot-api"
+ "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
func main() {
@@ -90,17 +85,22 @@ func main() {
log.Printf("Authorized on account %s", bot.Self.UserName)
- _, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem"))
+ wh, _ := tgbotapi.NewWebhookWithCert("https://www.google.com:8443/"+bot.Token, "cert.pem")
+
+ _, err = bot.SetWebhook(wh)
if err != nil {
log.Fatal(err)
}
+
info, err := bot.GetWebhookInfo()
if err != nil {
log.Fatal(err)
}
+
if info.LastErrorDate != 0 {
log.Printf("Telegram callback failed: %s", info.LastErrorMessage)
}
+
updates := bot.ListenForWebhook("/" + bot.Token)
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
@@ -110,7 +110,7 @@ func main() {
}
```
-If you need, you may generate a self signed certficate, as this requires
+If you need, you may generate a self-signed certificate, as this requires
HTTPS / TLS. The above example tells Telegram that this is your
certificate and that it should be trusted, even though it is not
properly signed.
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/book.toml b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/book.toml
new file mode 100644
index 00000000..841d5ba6
--- /dev/null
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/book.toml
@@ -0,0 +1,9 @@
+[book]
+authors = ["Syfaro"]
+language = "en"
+multilingual = false
+src = "docs"
+title = "Go Telegram Bot API"
+
+[output.html]
+git-repository-url = "https://github.com/go-telegram-bot-api/telegram-bot-api"
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/bot.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/bot.go
new file mode 100644
index 00000000..c58afec4
--- /dev/null
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/bot.go
@@ -0,0 +1,726 @@
+// Package tgbotapi has functions and types used for interacting with
+// the Telegram Bot API.
+package tgbotapi
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+)
+
+// HTTPClient is the type needed for the bot to perform HTTP requests.
+type HTTPClient interface {
+ Do(req *http.Request) (*http.Response, error)
+}
+
+// BotAPI allows you to interact with the Telegram Bot API.
+type BotAPI struct {
+ Token string `json:"token"`
+ Debug bool `json:"debug"`
+ Buffer int `json:"buffer"`
+
+ Self User `json:"-"`
+ Client HTTPClient `json:"-"`
+ shutdownChannel chan interface{}
+
+ apiEndpoint string
+}
+
+// NewBotAPI creates a new BotAPI instance.
+//
+// It requires a token, provided by @BotFather on Telegram.
+func NewBotAPI(token string) (*BotAPI, error) {
+ return NewBotAPIWithClient(token, APIEndpoint, &http.Client{})
+}
+
+// NewBotAPIWithAPIEndpoint creates a new BotAPI instance
+// and allows you to pass API endpoint.
+//
+// It requires a token, provided by @BotFather on Telegram and API endpoint.
+func NewBotAPIWithAPIEndpoint(token, apiEndpoint string) (*BotAPI, error) {
+ return NewBotAPIWithClient(token, apiEndpoint, &http.Client{})
+}
+
+// NewBotAPIWithClient creates a new BotAPI instance
+// and allows you to pass a http.Client.
+//
+// It requires a token, provided by @BotFather on Telegram and API endpoint.
+func NewBotAPIWithClient(token, apiEndpoint string, client HTTPClient) (*BotAPI, error) {
+ bot := &BotAPI{
+ Token: token,
+ Client: client,
+ Buffer: 100,
+ shutdownChannel: make(chan interface{}),
+
+ apiEndpoint: apiEndpoint,
+ }
+
+ self, err := bot.GetMe()
+ if err != nil {
+ return nil, err
+ }
+
+ bot.Self = self
+
+ return bot, nil
+}
+
+// SetAPIEndpoint changes the Telegram Bot API endpoint used by the instance.
+func (bot *BotAPI) SetAPIEndpoint(apiEndpoint string) {
+ bot.apiEndpoint = apiEndpoint
+}
+
+func buildParams(in Params) url.Values {
+ if in == nil {
+ return url.Values{}
+ }
+
+ out := url.Values{}
+
+ for key, value := range in {
+ out.Set(key, value)
+ }
+
+ return out
+}
+
+// MakeRequest makes a request to a specific endpoint with our token.
+func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, error) {
+ if bot.Debug {
+ log.Printf("Endpoint: %s, params: %v\n", endpoint, params)
+ }
+
+ method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
+
+ values := buildParams(params)
+
+ req, err := http.NewRequest("POST", method, strings.NewReader(values.Encode()))
+ if err != nil {
+ return &APIResponse{}, err
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+
+ resp, err := bot.Client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ var apiResp APIResponse
+ bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
+ if err != nil {
+ return &apiResp, err
+ }
+
+ if bot.Debug {
+ log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
+ }
+
+ if !apiResp.Ok {
+ var parameters ResponseParameters
+
+ if apiResp.Parameters != nil {
+ parameters = *apiResp.Parameters
+ }
+
+ return &apiResp, &Error{
+ Code: apiResp.ErrorCode,
+ Message: apiResp.Description,
+ ResponseParameters: parameters,
+ }
+ }
+
+ return &apiResp, nil
+}
+
+// decodeAPIResponse decode response and return slice of bytes if debug enabled.
+// If debug disabled, just decode http.Response.Body stream to APIResponse struct
+// for efficient memory usage
+func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse) ([]byte, error) {
+ if !bot.Debug {
+ dec := json.NewDecoder(responseBody)
+ err := dec.Decode(resp)
+ return nil, err
+ }
+
+ // if debug, read response body
+ data, err := ioutil.ReadAll(responseBody)
+ if err != nil {
+ return nil, err
+ }
+
+ err = json.Unmarshal(data, resp)
+ if err != nil {
+ return nil, err
+ }
+
+ return data, nil
+}
+
+// UploadFiles makes a request to the API with files.
+func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFile) (*APIResponse, error) {
+ r, w := io.Pipe()
+ m := multipart.NewWriter(w)
+
+ // This code modified from the very helpful @HirbodBehnam
+ // https://github.com/go-telegram-bot-api/telegram-bot-api/issues/354#issuecomment-663856473
+ go func() {
+ defer w.Close()
+ defer m.Close()
+
+ for field, value := range params {
+ if err := m.WriteField(field, value); err != nil {
+ w.CloseWithError(err)
+ return
+ }
+ }
+
+ for _, file := range files {
+ if file.Data.NeedsUpload() {
+ name, reader, err := file.Data.UploadData()
+ if err != nil {
+ w.CloseWithError(err)
+ return
+ }
+
+ part, err := m.CreateFormFile(file.Name, name)
+ if err != nil {
+ w.CloseWithError(err)
+ return
+ }
+
+ if _, err := io.Copy(part, reader); err != nil {
+ w.CloseWithError(err)
+ return
+ }
+
+ if closer, ok := reader.(io.ReadCloser); ok {
+ if err = closer.Close(); err != nil {
+ w.CloseWithError(err)
+ return
+ }
+ }
+ } else {
+ value := file.Data.SendData()
+
+ if err := m.WriteField(file.Name, value); err != nil {
+ w.CloseWithError(err)
+ return
+ }
+ }
+ }
+ }()
+
+ if bot.Debug {
+ log.Printf("Endpoint: %s, params: %v, with %d files\n", endpoint, params, len(files))
+ }
+
+ method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
+
+ req, err := http.NewRequest("POST", method, r)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Set("Content-Type", m.FormDataContentType())
+
+ resp, err := bot.Client.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ var apiResp APIResponse
+ bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
+ if err != nil {
+ return &apiResp, err
+ }
+
+ if bot.Debug {
+ log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
+ }
+
+ if !apiResp.Ok {
+ var parameters ResponseParameters
+
+ if apiResp.Parameters != nil {
+ parameters = *apiResp.Parameters
+ }
+
+ return &apiResp, &Error{
+ Message: apiResp.Description,
+ ResponseParameters: parameters,
+ }
+ }
+
+ return &apiResp, nil
+}
+
+// GetFileDirectURL returns direct URL to file
+//
+// It requires the FileID.
+func (bot *BotAPI) GetFileDirectURL(fileID string) (string, error) {
+ file, err := bot.GetFile(FileConfig{fileID})
+
+ if err != nil {
+ return "", err
+ }
+
+ return file.Link(bot.Token), nil
+}
+
+// GetMe fetches the currently authenticated bot.
+//
+// This method is called upon creation to validate the token,
+// and so you may get this data from BotAPI.Self without the need for
+// another request.
+func (bot *BotAPI) GetMe() (User, error) {
+ resp, err := bot.MakeRequest("getMe", nil)
+ if err != nil {
+ return User{}, err
+ }
+
+ var user User
+ err = json.Unmarshal(resp.Result, &user)
+
+ return user, err
+}
+
+// IsMessageToMe returns true if message directed to this bot.
+//
+// It requires the Message.
+func (bot *BotAPI) IsMessageToMe(message Message) bool {
+ return strings.Contains(message.Text, "@"+bot.Self.UserName)
+}
+
+func hasFilesNeedingUpload(files []RequestFile) bool {
+ for _, file := range files {
+ if file.Data.NeedsUpload() {
+ return true
+ }
+ }
+
+ return false
+}
+
+// Request sends a Chattable to Telegram, and returns the APIResponse.
+func (bot *BotAPI) Request(c Chattable) (*APIResponse, error) {
+ params, err := c.params()
+ if err != nil {
+ return nil, err
+ }
+
+ if t, ok := c.(Fileable); ok {
+ files := t.files()
+
+ // If we have files that need to be uploaded, we should delegate the
+ // request to UploadFile.
+ if hasFilesNeedingUpload(files) {
+ return bot.UploadFiles(t.method(), params, files)
+ }
+
+ // However, if there are no files to be uploaded, there's likely things
+ // that need to be turned into params instead.
+ for _, file := range files {
+ params[file.Name] = file.Data.SendData()
+ }
+ }
+
+ return bot.MakeRequest(c.method(), params)
+}
+
+// Send will send a Chattable item to Telegram and provides the
+// returned Message.
+func (bot *BotAPI) Send(c Chattable) (Message, error) {
+ resp, err := bot.Request(c)
+ if err != nil {
+ return Message{}, err
+ }
+
+ var message Message
+ err = json.Unmarshal(resp.Result, &message)
+
+ return message, err
+}
+
+// SendMediaGroup sends a media group and returns the resulting messages.
+func (bot *BotAPI) SendMediaGroup(config MediaGroupConfig) ([]Message, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return nil, err
+ }
+
+ var messages []Message
+ err = json.Unmarshal(resp.Result, &messages)
+
+ return messages, err
+}
+
+// GetUserProfilePhotos gets a user's profile photos.
+//
+// It requires UserID.
+// Offset and Limit are optional.
+func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return UserProfilePhotos{}, err
+ }
+
+ var profilePhotos UserProfilePhotos
+ err = json.Unmarshal(resp.Result, &profilePhotos)
+
+ return profilePhotos, err
+}
+
+// GetFile returns a File which can download a file from Telegram.
+//
+// Requires FileID.
+func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return File{}, err
+ }
+
+ var file File
+ err = json.Unmarshal(resp.Result, &file)
+
+ return file, err
+}
+
+// GetUpdates fetches updates.
+// If a WebHook is set, this will not return any data!
+//
+// Offset, Limit, Timeout, and AllowedUpdates are optional.
+// To avoid stale items, set Offset to one higher than the previous item.
+// Set Timeout to a large number to reduce requests, so you can get updates
+// instantly instead of having to wait between requests.
+func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return []Update{}, err
+ }
+
+ var updates []Update
+ err = json.Unmarshal(resp.Result, &updates)
+
+ return updates, err
+}
+
+// GetWebhookInfo allows you to fetch information about a webhook and if
+// one currently is set, along with pending update count and error messages.
+func (bot *BotAPI) GetWebhookInfo() (WebhookInfo, error) {
+ resp, err := bot.MakeRequest("getWebhookInfo", nil)
+ if err != nil {
+ return WebhookInfo{}, err
+ }
+
+ var info WebhookInfo
+ err = json.Unmarshal(resp.Result, &info)
+
+ return info, err
+}
+
+// GetUpdatesChan starts and returns a channel for getting updates.
+func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) UpdatesChannel {
+ ch := make(chan Update, bot.Buffer)
+
+ go func() {
+ for {
+ select {
+ case <-bot.shutdownChannel:
+ close(ch)
+ return
+ default:
+ }
+
+ updates, err := bot.GetUpdates(config)
+ if err != nil {
+ log.Println(err)
+ log.Println("Failed to get updates, retrying in 3 seconds...")
+ time.Sleep(time.Second * 3)
+
+ continue
+ }
+
+ for _, update := range updates {
+ if update.UpdateID >= config.Offset {
+ config.Offset = update.UpdateID + 1
+ ch <- update
+ }
+ }
+ }
+ }()
+
+ return ch
+}
+
+// StopReceivingUpdates stops the go routine which receives updates
+func (bot *BotAPI) StopReceivingUpdates() {
+ if bot.Debug {
+ log.Println("Stopping the update receiver routine...")
+ }
+ close(bot.shutdownChannel)
+}
+
+// ListenForWebhook registers a http handler for a webhook.
+func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel {
+ ch := make(chan Update, bot.Buffer)
+
+ http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
+ update, err := bot.HandleUpdate(r)
+ if err != nil {
+ errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})
+ w.WriteHeader(http.StatusBadRequest)
+ w.Header().Set("Content-Type", "application/json")
+ _, _ = w.Write(errMsg)
+ return
+ }
+
+ ch <- *update
+ })
+
+ return ch
+}
+
+// ListenForWebhookRespReqFormat registers a http handler for a single incoming webhook.
+func (bot *BotAPI) ListenForWebhookRespReqFormat(w http.ResponseWriter, r *http.Request) UpdatesChannel {
+ ch := make(chan Update, bot.Buffer)
+
+ func(w http.ResponseWriter, r *http.Request) {
+ update, err := bot.HandleUpdate(r)
+ if err != nil {
+ errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})
+ w.WriteHeader(http.StatusBadRequest)
+ w.Header().Set("Content-Type", "application/json")
+ _, _ = w.Write(errMsg)
+ return
+ }
+
+ ch <- *update
+ close(ch)
+ }(w, r)
+
+ return ch
+}
+
+// HandleUpdate parses and returns update received via webhook
+func (bot *BotAPI) HandleUpdate(r *http.Request) (*Update, error) {
+ if r.Method != http.MethodPost {
+ err := errors.New("wrong HTTP method required POST")
+ return nil, err
+ }
+
+ var update Update
+ err := json.NewDecoder(r.Body).Decode(&update)
+ if err != nil {
+ return nil, err
+ }
+
+ return &update, nil
+}
+
+// WriteToHTTPResponse writes the request to the HTTP ResponseWriter.
+//
+// It doesn't support uploading files.
+//
+// See https://core.telegram.org/bots/api#making-requests-when-getting-updates
+// for details.
+func WriteToHTTPResponse(w http.ResponseWriter, c Chattable) error {
+ params, err := c.params()
+ if err != nil {
+ return err
+ }
+
+ if t, ok := c.(Fileable); ok {
+ if hasFilesNeedingUpload(t.files()) {
+ return errors.New("unable to use http response to upload files")
+ }
+ }
+
+ values := buildParams(params)
+ values.Set("method", c.method())
+
+ w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
+ _, err = w.Write([]byte(values.Encode()))
+ return err
+}
+
+// GetChat gets information about a chat.
+func (bot *BotAPI) GetChat(config ChatInfoConfig) (Chat, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return Chat{}, err
+ }
+
+ var chat Chat
+ err = json.Unmarshal(resp.Result, &chat)
+
+ return chat, err
+}
+
+// GetChatAdministrators gets a list of administrators in the chat.
+//
+// If none have been appointed, only the creator will be returned.
+// Bots are not shown, even if they are an administrator.
+func (bot *BotAPI) GetChatAdministrators(config ChatAdministratorsConfig) ([]ChatMember, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return []ChatMember{}, err
+ }
+
+ var members []ChatMember
+ err = json.Unmarshal(resp.Result, &members)
+
+ return members, err
+}
+
+// GetChatMembersCount gets the number of users in a chat.
+func (bot *BotAPI) GetChatMembersCount(config ChatMemberCountConfig) (int, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return -1, err
+ }
+
+ var count int
+ err = json.Unmarshal(resp.Result, &count)
+
+ return count, err
+}
+
+// GetChatMember gets a specific chat member.
+func (bot *BotAPI) GetChatMember(config GetChatMemberConfig) (ChatMember, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return ChatMember{}, err
+ }
+
+ var member ChatMember
+ err = json.Unmarshal(resp.Result, &member)
+
+ return member, err
+}
+
+// GetGameHighScores allows you to get the high scores for a game.
+func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return []GameHighScore{}, err
+ }
+
+ var highScores []GameHighScore
+ err = json.Unmarshal(resp.Result, &highScores)
+
+ return highScores, err
+}
+
+// GetInviteLink get InviteLink for a chat
+func (bot *BotAPI) GetInviteLink(config ChatInviteLinkConfig) (string, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return "", err
+ }
+
+ var inviteLink string
+ err = json.Unmarshal(resp.Result, &inviteLink)
+
+ return inviteLink, err
+}
+
+// GetStickerSet returns a StickerSet.
+func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return StickerSet{}, err
+ }
+
+ var stickers StickerSet
+ err = json.Unmarshal(resp.Result, &stickers)
+
+ return stickers, err
+}
+
+// StopPoll stops a poll and returns the result.
+func (bot *BotAPI) StopPoll(config StopPollConfig) (Poll, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return Poll{}, err
+ }
+
+ var poll Poll
+ err = json.Unmarshal(resp.Result, &poll)
+
+ return poll, err
+}
+
+// GetMyCommands gets the currently registered commands.
+func (bot *BotAPI) GetMyCommands() ([]BotCommand, error) {
+ return bot.GetMyCommandsWithConfig(GetMyCommandsConfig{})
+}
+
+// GetMyCommandsWithConfig gets the currently registered commands with a config.
+func (bot *BotAPI) GetMyCommandsWithConfig(config GetMyCommandsConfig) ([]BotCommand, error) {
+ resp, err := bot.Request(config)
+ if err != nil {
+ return nil, err
+ }
+
+ var commands []BotCommand
+ err = json.Unmarshal(resp.Result, &commands)
+
+ return commands, err
+}
+
+// CopyMessage copy messages of any kind. The method is analogous to the method
+// forwardMessage, but the copied message doesn't have a link to the original
+// message. Returns the MessageID of the sent message on success.
+func (bot *BotAPI) CopyMessage(config CopyMessageConfig) (MessageID, error) {
+ params, err := config.params()
+ if err != nil {
+ return MessageID{}, err
+ }
+
+ resp, err := bot.MakeRequest(config.method(), params)
+ if err != nil {
+ return MessageID{}, err
+ }
+
+ var messageID MessageID
+ err = json.Unmarshal(resp.Result, &messageID)
+
+ return messageID, err
+}
+
+// EscapeText takes an input text and escape Telegram markup symbols.
+// In this way we can send a text without being afraid of having to escape the characters manually.
+// Note that you don't have to include the formatting style in the input text, or it will be escaped too.
+// If there is an error, an empty string will be returned.
+//
+// parseMode is the text formatting mode (ModeMarkdown, ModeMarkdownV2 or ModeHTML)
+// text is the input string that will be escaped
+func EscapeText(parseMode string, text string) string {
+ var replacer *strings.Replacer
+
+ if parseMode == ModeHTML {
+ replacer = strings.NewReplacer("<", "&lt;", ">", "&gt;", "&", "&amp;")
+ } else if parseMode == ModeMarkdown {
+ replacer = strings.NewReplacer("_", "\\_", "*", "\\*", "`", "\\`", "[", "\\[")
+ } else if parseMode == ModeMarkdownV2 {
+ replacer = strings.NewReplacer(
+ "_", "\\_", "*", "\\*", "[", "\\[", "]", "\\]", "(",
+ "\\(", ")", "\\)", "~", "\\~", "`", "\\`", ">", "\\>",
+ "#", "\\#", "+", "\\+", "-", "\\-", "=", "\\=", "|",
+ "\\|", "{", "\\{", "}", "\\}", ".", "\\.", "!", "\\!",
+ )
+ } else {
+ return ""
+ }
+
+ return replacer.Replace(text)
+}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/configs.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/configs.go
new file mode 100644
index 00000000..5e43af49
--- /dev/null
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/configs.go
@@ -0,0 +1,2468 @@
+package tgbotapi
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net/url"
+ "os"
+ "strconv"
+)
+
+// Telegram constants
+const (
+ // APIEndpoint is the endpoint for all API methods,
+ // with formatting for Sprintf.
+ APIEndpoint = "https://api.telegram.org/bot%s/%s"
+ // FileEndpoint is the endpoint for downloading a file from Telegram.
+ FileEndpoint = "https://api.telegram.org/file/bot%s/%s"
+)
+
+// Constant values for ChatActions
+const (
+ ChatTyping = "typing"
+ ChatUploadPhoto = "upload_photo"
+ ChatRecordVideo = "record_video"
+ ChatUploadVideo = "upload_video"
+ ChatRecordVoice = "record_voice"
+ ChatUploadVoice = "upload_voice"
+ ChatUploadDocument = "upload_document"
+ ChatChooseSticker = "choose_sticker"
+ ChatFindLocation = "find_location"
+ ChatRecordVideoNote = "record_video_note"
+ ChatUploadVideoNote = "upload_video_note"
+)
+
+// API errors
+const (
+ // ErrAPIForbidden happens when a token is bad
+ ErrAPIForbidden = "forbidden"
+)
+
+// Constant values for ParseMode in MessageConfig
+const (
+ ModeMarkdown = "Markdown"
+ ModeMarkdownV2 = "MarkdownV2"
+ ModeHTML = "HTML"
+)
+
+// Constant values for update types
+const (
+ // UpdateTypeMessage is new incoming message of any kind — text, photo, sticker, etc.
+ UpdateTypeMessage = "message"
+
+ // UpdateTypeEditedMessage is new version of a message that is known to the bot and was edited
+ UpdateTypeEditedMessage = "edited_message"
+
+ // UpdateTypeChannelPost is new incoming channel post of any kind — text, photo, sticker, etc.
+ UpdateTypeChannelPost = "channel_post"
+
+ // UpdateTypeEditedChannelPost is new version of a channel post that is known to the bot and was edited
+ UpdateTypeEditedChannelPost = "edited_channel_post"
+
+ // UpdateTypeInlineQuery is new incoming inline query
+ UpdateTypeInlineQuery = "inline_query"
+
+ // UpdateTypeChosenInlineResult i the result of an inline query that was chosen by a user and sent to their
+ // chat partner. Please see the documentation on the feedback collecting for
+ // details on how to enable these updates for your bot.
+ UpdateTypeChosenInlineResult = "chosen_inline_result"
+
+ // UpdateTypeCallbackQuery is new incoming callback query
+ UpdateTypeCallbackQuery = "callback_query"
+
+ // UpdateTypeShippingQuery is new incoming shipping query. Only for invoices with flexible price
+ UpdateTypeShippingQuery = "shipping_query"
+
+ // UpdateTypePreCheckoutQuery is new incoming pre-checkout query. Contains full information about checkout
+ UpdateTypePreCheckoutQuery = "pre_checkout_query"
+
+ // UpdateTypePoll is new poll state. Bots receive only updates about stopped polls and polls
+ // which are sent by the bot
+ UpdateTypePoll = "poll"
+
+ // UpdateTypePollAnswer is when user changed their answer in a non-anonymous poll. Bots receive new votes
+ // only in polls that were sent by the bot itself.
+ UpdateTypePollAnswer = "poll_answer"
+
+ // UpdateTypeMyChatMember is when the bot's chat member status was updated in a chat. For private chats, this
+ // update is received only when the bot is blocked or unblocked by the user.
+ UpdateTypeMyChatMember = "my_chat_member"
+
+ // UpdateTypeChatMember is when the bot must be an administrator in the chat and must explicitly specify
+ // this update in the list of allowed_updates to receive these updates.
+ UpdateTypeChatMember = "chat_member"
+)
+
+// Library errors
+const (
+ ErrBadURL = "bad or empty url"
+)
+
+// Chattable is any config type that can be sent.
+type Chattable interface {
+ params() (Params, error)
+ method() string
+}
+
+// Fileable is any config type that can be sent that includes a file.
+type Fileable interface {
+ Chattable
+ files() []RequestFile
+}
+
+// RequestFile represents a file associated with a field name.
+type RequestFile struct {
+ // The file field name.
+ Name string
+ // The file data to include.
+ Data RequestFileData
+}
+
+// RequestFileData represents the data to be used for a file.
+type RequestFileData interface {
+ // NeedsUpload shows if the file needs to be uploaded.
+ NeedsUpload() bool
+
+ // UploadData gets the file name and an `io.Reader` for the file to be uploaded. This
+ // must only be called when the file needs to be uploaded.
+ UploadData() (string, io.Reader, error)
+ // SendData gets the file data to send when a file does not need to be uploaded. This
+ // must only be called when the file does not need to be uploaded.
+ SendData() string
+}
+
+// FileBytes contains information about a set of bytes to upload
+// as a File.
+type FileBytes struct {
+ Name string
+ Bytes []byte
+}
+
+func (fb FileBytes) NeedsUpload() bool {
+ return true
+}
+
+func (fb FileBytes) UploadData() (string, io.Reader, error) {
+ return fb.Name, bytes.NewReader(fb.Bytes), nil
+}
+
+func (fb FileBytes) SendData() string {
+ panic("FileBytes must be uploaded")
+}
+
+// FileReader contains information about a reader to upload as a File.
+type FileReader struct {
+ Name string
+ Reader io.Reader
+}
+
+func (fr FileReader) NeedsUpload() bool {
+ return true
+}
+
+func (fr FileReader) UploadData() (string, io.Reader, error) {
+ return fr.Name, fr.Reader, nil
+}
+
+func (fr FileReader) SendData() string {
+ panic("FileReader must be uploaded")
+}
+
+// FilePath is a path to a local file.
+type FilePath string
+
+func (fp FilePath) NeedsUpload() bool {
+ return true
+}
+
+func (fp FilePath) UploadData() (string, io.Reader, error) {
+ fileHandle, err := os.Open(string(fp))
+ if err != nil {
+ return "", nil, err
+ }
+
+ name := fileHandle.Name()
+ return name, fileHandle, err
+}
+
+func (fp FilePath) SendData() string {
+ panic("FilePath must be uploaded")
+}
+
+// FileURL is a URL to use as a file for a request.
+type FileURL string
+
+func (fu FileURL) NeedsUpload() bool {
+ return false
+}
+
+func (fu FileURL) UploadData() (string, io.Reader, error) {
+ panic("FileURL cannot be uploaded")
+}
+
+func (fu FileURL) SendData() string {
+ return string(fu)
+}
+
+// FileID is an ID of a file already uploaded to Telegram.
+type FileID string
+
+func (fi FileID) NeedsUpload() bool {
+ return false
+}
+
+func (fi FileID) UploadData() (string, io.Reader, error) {
+ panic("FileID cannot be uploaded")
+}
+
+func (fi FileID) SendData() string {
+ return string(fi)
+}
+
+// fileAttach is an internal file type used for processed media groups.
+type fileAttach string
+
+func (fa fileAttach) NeedsUpload() bool {
+ return false
+}
+
+func (fa fileAttach) UploadData() (string, io.Reader, error) {
+ panic("fileAttach cannot be uploaded")
+}
+
+func (fa fileAttach) SendData() string {
+ return string(fa)
+}
+
+// LogOutConfig is a request to log out of the cloud Bot API server.
+//
+// Note that you may not log back in for at least 10 minutes.
+type LogOutConfig struct{}
+
+func (LogOutConfig) method() string {
+ return "logOut"
+}
+
+func (LogOutConfig) params() (Params, error) {
+ return nil, nil
+}
+
+// CloseConfig is a request to close the bot instance on a local server.
+//
+// Note that you may not close an instance for the first 10 minutes after the
+// bot has started.
+type CloseConfig struct{}
+
+func (CloseConfig) method() string {
+ return "close"
+}
+
+func (CloseConfig) params() (Params, error) {
+ return nil, nil
+}
+
+// BaseChat is base type for all chat config types.
+type BaseChat struct {
+ ChatID int64 // required
+ ChannelUsername string
+ ReplyToMessageID int
+ ReplyMarkup interface{}
+ DisableNotification bool
+ AllowSendingWithoutReply bool
+}
+
+func (chat *BaseChat) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", chat.ChatID, chat.ChannelUsername)
+ params.AddNonZero("reply_to_message_id", chat.ReplyToMessageID)
+ params.AddBool("disable_notification", chat.DisableNotification)
+ params.AddBool("allow_sending_without_reply", chat.AllowSendingWithoutReply)
+
+ err := params.AddInterface("reply_markup", chat.ReplyMarkup)
+
+ return params, err
+}
+
+// BaseFile is a base type for all file config types.
+type BaseFile struct {
+ BaseChat
+ File RequestFileData
+}
+
+func (file BaseFile) params() (Params, error) {
+ return file.BaseChat.params()
+}
+
+// BaseEdit is base type of all chat edits.
+type BaseEdit struct {
+ ChatID int64
+ ChannelUsername string
+ MessageID int
+ InlineMessageID string
+ ReplyMarkup *InlineKeyboardMarkup
+}
+
+func (edit BaseEdit) params() (Params, error) {
+ params := make(Params)
+
+ if edit.InlineMessageID != "" {
+ params["inline_message_id"] = edit.InlineMessageID
+ } else {
+ params.AddFirstValid("chat_id", edit.ChatID, edit.ChannelUsername)
+ params.AddNonZero("message_id", edit.MessageID)
+ }
+
+ err := params.AddInterface("reply_markup", edit.ReplyMarkup)
+
+ return params, err
+}
+
+// MessageConfig contains information about a SendMessage request.
+type MessageConfig struct {
+ BaseChat
+ Text string
+ ParseMode string
+ Entities []MessageEntity
+ DisableWebPagePreview bool
+}
+
+func (config MessageConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonEmpty("text", config.Text)
+ params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("entities", config.Entities)
+
+ return params, err
+}
+
+func (config MessageConfig) method() string {
+ return "sendMessage"
+}
+
+// ForwardConfig contains information about a ForwardMessage request.
+type ForwardConfig struct {
+ BaseChat
+ FromChatID int64 // required
+ FromChannelUsername string
+ MessageID int // required
+}
+
+func (config ForwardConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonZero64("from_chat_id", config.FromChatID)
+ params.AddNonZero("message_id", config.MessageID)
+
+ return params, nil
+}
+
+func (config ForwardConfig) method() string {
+ return "forwardMessage"
+}
+
+// CopyMessageConfig contains information about a copyMessage request.
+type CopyMessageConfig struct {
+ BaseChat
+ FromChatID int64
+ FromChannelUsername string
+ MessageID int
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+}
+
+func (config CopyMessageConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddFirstValid("from_chat_id", config.FromChatID, config.FromChannelUsername)
+ params.AddNonZero("message_id", config.MessageID)
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config CopyMessageConfig) method() string {
+ return "copyMessage"
+}
+
+// PhotoConfig contains information about a SendPhoto request.
+type PhotoConfig struct {
+ BaseFile
+ Thumb RequestFileData
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+}
+
+func (config PhotoConfig) params() (Params, error) {
+ params, err := config.BaseFile.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config PhotoConfig) method() string {
+ return "sendPhoto"
+}
+
+func (config PhotoConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "photo",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// AudioConfig contains information about a SendAudio request.
+type AudioConfig struct {
+ BaseFile
+ Thumb RequestFileData
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+ Duration int
+ Performer string
+ Title string
+}
+
+func (config AudioConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonZero("duration", config.Duration)
+ params.AddNonEmpty("performer", config.Performer)
+ params.AddNonEmpty("title", config.Title)
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config AudioConfig) method() string {
+ return "sendAudio"
+}
+
+func (config AudioConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "audio",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// DocumentConfig contains information about a SendDocument request.
+type DocumentConfig struct {
+ BaseFile
+ Thumb RequestFileData
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+ DisableContentTypeDetection bool
+}
+
+func (config DocumentConfig) params() (Params, error) {
+ params, err := config.BaseFile.params()
+
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ params.AddBool("disable_content_type_detection", config.DisableContentTypeDetection)
+
+ return params, err
+}
+
+func (config DocumentConfig) method() string {
+ return "sendDocument"
+}
+
+func (config DocumentConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "document",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// StickerConfig contains information about a SendSticker request.
+type StickerConfig struct {
+ BaseFile
+}
+
+func (config StickerConfig) params() (Params, error) {
+ return config.BaseChat.params()
+}
+
+func (config StickerConfig) method() string {
+ return "sendSticker"
+}
+
+func (config StickerConfig) files() []RequestFile {
+ return []RequestFile{{
+ Name: "sticker",
+ Data: config.File,
+ }}
+}
+
+// VideoConfig contains information about a SendVideo request.
+type VideoConfig struct {
+ BaseFile
+ Thumb RequestFileData
+ Duration int
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+ SupportsStreaming bool
+}
+
+func (config VideoConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonZero("duration", config.Duration)
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ params.AddBool("supports_streaming", config.SupportsStreaming)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config VideoConfig) method() string {
+ return "sendVideo"
+}
+
+func (config VideoConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "video",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// AnimationConfig contains information about a SendAnimation request.
+type AnimationConfig struct {
+ BaseFile
+ Duration int
+ Thumb RequestFileData
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+}
+
+func (config AnimationConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonZero("duration", config.Duration)
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config AnimationConfig) method() string {
+ return "sendAnimation"
+}
+
+func (config AnimationConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "animation",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// VideoNoteConfig contains information about a SendVideoNote request.
+type VideoNoteConfig struct {
+ BaseFile
+ Thumb RequestFileData
+ Duration int
+ Length int
+}
+
+func (config VideoNoteConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+
+ params.AddNonZero("duration", config.Duration)
+ params.AddNonZero("length", config.Length)
+
+ return params, err
+}
+
+func (config VideoNoteConfig) method() string {
+ return "sendVideoNote"
+}
+
+func (config VideoNoteConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "video_note",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// VoiceConfig contains information about a SendVoice request.
+type VoiceConfig struct {
+ BaseFile
+ Thumb RequestFileData
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+ Duration int
+}
+
+func (config VoiceConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonZero("duration", config.Duration)
+ params.AddNonEmpty("caption", config.Caption)
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config VoiceConfig) method() string {
+ return "sendVoice"
+}
+
+func (config VoiceConfig) files() []RequestFile {
+ files := []RequestFile{{
+ Name: "voice",
+ Data: config.File,
+ }}
+
+ if config.Thumb != nil {
+ files = append(files, RequestFile{
+ Name: "thumb",
+ Data: config.Thumb,
+ })
+ }
+
+ return files
+}
+
+// LocationConfig contains information about a SendLocation request.
+type LocationConfig struct {
+ BaseChat
+ Latitude float64 // required
+ Longitude float64 // required
+ HorizontalAccuracy float64 // optional
+ LivePeriod int // optional
+ Heading int // optional
+ ProximityAlertRadius int // optional
+}
+
+func (config LocationConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+
+ params.AddNonZeroFloat("latitude", config.Latitude)
+ params.AddNonZeroFloat("longitude", config.Longitude)
+ params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy)
+ params.AddNonZero("live_period", config.LivePeriod)
+ params.AddNonZero("heading", config.Heading)
+ params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius)
+
+ return params, err
+}
+
+func (config LocationConfig) method() string {
+ return "sendLocation"
+}
+
+// EditMessageLiveLocationConfig allows you to update a live location.
+type EditMessageLiveLocationConfig struct {
+ BaseEdit
+ Latitude float64 // required
+ Longitude float64 // required
+ HorizontalAccuracy float64 // optional
+ Heading int // optional
+ ProximityAlertRadius int // optional
+}
+
+func (config EditMessageLiveLocationConfig) params() (Params, error) {
+ params, err := config.BaseEdit.params()
+
+ params.AddNonZeroFloat("latitude", config.Latitude)
+ params.AddNonZeroFloat("longitude", config.Longitude)
+ params.AddNonZeroFloat("horizontal_accuracy", config.HorizontalAccuracy)
+ params.AddNonZero("heading", config.Heading)
+ params.AddNonZero("proximity_alert_radius", config.ProximityAlertRadius)
+
+ return params, err
+}
+
+func (config EditMessageLiveLocationConfig) method() string {
+ return "editMessageLiveLocation"
+}
+
+// StopMessageLiveLocationConfig stops updating a live location.
+type StopMessageLiveLocationConfig struct {
+ BaseEdit
+}
+
+func (config StopMessageLiveLocationConfig) params() (Params, error) {
+ return config.BaseEdit.params()
+}
+
+func (config StopMessageLiveLocationConfig) method() string {
+ return "stopMessageLiveLocation"
+}
+
+// VenueConfig contains information about a SendVenue request.
+type VenueConfig struct {
+ BaseChat
+ Latitude float64 // required
+ Longitude float64 // required
+ Title string // required
+ Address string // required
+ FoursquareID string
+ FoursquareType string
+ GooglePlaceID string
+ GooglePlaceType string
+}
+
+func (config VenueConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+
+ params.AddNonZeroFloat("latitude", config.Latitude)
+ params.AddNonZeroFloat("longitude", config.Longitude)
+ params["title"] = config.Title
+ params["address"] = config.Address
+ params.AddNonEmpty("foursquare_id", config.FoursquareID)
+ params.AddNonEmpty("foursquare_type", config.FoursquareType)
+ params.AddNonEmpty("google_place_id", config.GooglePlaceID)
+ params.AddNonEmpty("google_place_type", config.GooglePlaceType)
+
+ return params, err
+}
+
+func (config VenueConfig) method() string {
+ return "sendVenue"
+}
+
+// ContactConfig allows you to send a contact.
+type ContactConfig struct {
+ BaseChat
+ PhoneNumber string
+ FirstName string
+ LastName string
+ VCard string
+}
+
+func (config ContactConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+
+ params["phone_number"] = config.PhoneNumber
+ params["first_name"] = config.FirstName
+
+ params.AddNonEmpty("last_name", config.LastName)
+ params.AddNonEmpty("vcard", config.VCard)
+
+ return params, err
+}
+
+func (config ContactConfig) method() string {
+ return "sendContact"
+}
+
+// SendPollConfig allows you to send a poll.
+type SendPollConfig struct {
+ BaseChat
+ Question string
+ Options []string
+ IsAnonymous bool
+ Type string
+ AllowsMultipleAnswers bool
+ CorrectOptionID int64
+ Explanation string
+ ExplanationParseMode string
+ ExplanationEntities []MessageEntity
+ OpenPeriod int
+ CloseDate int
+ IsClosed bool
+}
+
+func (config SendPollConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params["question"] = config.Question
+ if err = params.AddInterface("options", config.Options); err != nil {
+ return params, err
+ }
+ params["is_anonymous"] = strconv.FormatBool(config.IsAnonymous)
+ params.AddNonEmpty("type", config.Type)
+ params["allows_multiple_answers"] = strconv.FormatBool(config.AllowsMultipleAnswers)
+ params["correct_option_id"] = strconv.FormatInt(config.CorrectOptionID, 10)
+ params.AddBool("is_closed", config.IsClosed)
+ params.AddNonEmpty("explanation", config.Explanation)
+ params.AddNonEmpty("explanation_parse_mode", config.ExplanationParseMode)
+ params.AddNonZero("open_period", config.OpenPeriod)
+ params.AddNonZero("close_date", config.CloseDate)
+ err = params.AddInterface("explanation_entities", config.ExplanationEntities)
+
+ return params, err
+}
+
+func (SendPollConfig) method() string {
+ return "sendPoll"
+}
+
+// GameConfig allows you to send a game.
+type GameConfig struct {
+ BaseChat
+ GameShortName string
+}
+
+func (config GameConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+
+ params["game_short_name"] = config.GameShortName
+
+ return params, err
+}
+
+func (config GameConfig) method() string {
+ return "sendGame"
+}
+
+// SetGameScoreConfig allows you to update the game score in a chat.
+type SetGameScoreConfig struct {
+ UserID int64
+ Score int
+ Force bool
+ DisableEditMessage bool
+ ChatID int64
+ ChannelUsername string
+ MessageID int
+ InlineMessageID string
+}
+
+func (config SetGameScoreConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero64("user_id", config.UserID)
+ params.AddNonZero("scrore", config.Score)
+ params.AddBool("disable_edit_message", config.DisableEditMessage)
+
+ if config.InlineMessageID != "" {
+ params["inline_message_id"] = config.InlineMessageID
+ } else {
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero("message_id", config.MessageID)
+ }
+
+ return params, nil
+}
+
+func (config SetGameScoreConfig) method() string {
+ return "setGameScore"
+}
+
+// GetGameHighScoresConfig allows you to fetch the high scores for a game.
+type GetGameHighScoresConfig struct {
+ UserID int64
+ ChatID int64
+ ChannelUsername string
+ MessageID int
+ InlineMessageID string
+}
+
+func (config GetGameHighScoresConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero64("user_id", config.UserID)
+
+ if config.InlineMessageID != "" {
+ params["inline_message_id"] = config.InlineMessageID
+ } else {
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero("message_id", config.MessageID)
+ }
+
+ return params, nil
+}
+
+func (config GetGameHighScoresConfig) method() string {
+ return "getGameHighScores"
+}
+
+// ChatActionConfig contains information about a SendChatAction request.
+type ChatActionConfig struct {
+ BaseChat
+ Action string // required
+}
+
+func (config ChatActionConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+
+ params["action"] = config.Action
+
+ return params, err
+}
+
+func (config ChatActionConfig) method() string {
+ return "sendChatAction"
+}
+
+// EditMessageTextConfig allows you to modify the text in a message.
+type EditMessageTextConfig struct {
+ BaseEdit
+ Text string
+ ParseMode string
+ Entities []MessageEntity
+ DisableWebPagePreview bool
+}
+
+func (config EditMessageTextConfig) params() (Params, error) {
+ params, err := config.BaseEdit.params()
+ if err != nil {
+ return params, err
+ }
+
+ params["text"] = config.Text
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ params.AddBool("disable_web_page_preview", config.DisableWebPagePreview)
+ err = params.AddInterface("entities", config.Entities)
+
+ return params, err
+}
+
+func (config EditMessageTextConfig) method() string {
+ return "editMessageText"
+}
+
+// EditMessageCaptionConfig allows you to modify the caption of a message.
+type EditMessageCaptionConfig struct {
+ BaseEdit
+ Caption string
+ ParseMode string
+ CaptionEntities []MessageEntity
+}
+
+func (config EditMessageCaptionConfig) params() (Params, error) {
+ params, err := config.BaseEdit.params()
+ if err != nil {
+ return params, err
+ }
+
+ params["caption"] = config.Caption
+ params.AddNonEmpty("parse_mode", config.ParseMode)
+ err = params.AddInterface("caption_entities", config.CaptionEntities)
+
+ return params, err
+}
+
+func (config EditMessageCaptionConfig) method() string {
+ return "editMessageCaption"
+}
+
+// EditMessageMediaConfig allows you to make an editMessageMedia request.
+type EditMessageMediaConfig struct {
+ BaseEdit
+
+ Media interface{}
+}
+
+func (EditMessageMediaConfig) method() string {
+ return "editMessageMedia"
+}
+
+func (config EditMessageMediaConfig) params() (Params, error) {
+ params, err := config.BaseEdit.params()
+ if err != nil {
+ return params, err
+ }
+
+ err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0))
+
+ return params, err
+}
+
+func (config EditMessageMediaConfig) files() []RequestFile {
+ return prepareInputMediaFile(config.Media, 0)
+}
+
+// EditMessageReplyMarkupConfig allows you to modify the reply markup
+// of a message.
+type EditMessageReplyMarkupConfig struct {
+ BaseEdit
+}
+
+func (config EditMessageReplyMarkupConfig) params() (Params, error) {
+ return config.BaseEdit.params()
+}
+
+func (config EditMessageReplyMarkupConfig) method() string {
+ return "editMessageReplyMarkup"
+}
+
+// StopPollConfig allows you to stop a poll sent by the bot.
+type StopPollConfig struct {
+ BaseEdit
+}
+
+func (config StopPollConfig) params() (Params, error) {
+ return config.BaseEdit.params()
+}
+
+func (StopPollConfig) method() string {
+ return "stopPoll"
+}
+
+// UserProfilePhotosConfig contains information about a
+// GetUserProfilePhotos request.
+type UserProfilePhotosConfig struct {
+ UserID int64
+ Offset int
+ Limit int
+}
+
+func (UserProfilePhotosConfig) method() string {
+ return "getUserProfilePhotos"
+}
+
+func (config UserProfilePhotosConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero64("user_id", config.UserID)
+ params.AddNonZero("offset", config.Offset)
+ params.AddNonZero("limit", config.Limit)
+
+ return params, nil
+}
+
+// FileConfig has information about a file hosted on Telegram.
+type FileConfig struct {
+ FileID string
+}
+
+func (FileConfig) method() string {
+ return "getFile"
+}
+
+func (config FileConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["file_id"] = config.FileID
+
+ return params, nil
+}
+
+// UpdateConfig contains information about a GetUpdates request.
+type UpdateConfig struct {
+ Offset int
+ Limit int
+ Timeout int
+ AllowedUpdates []string
+}
+
+func (UpdateConfig) method() string {
+ return "getUpdates"
+}
+
+func (config UpdateConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero("offset", config.Offset)
+ params.AddNonZero("limit", config.Limit)
+ params.AddNonZero("timeout", config.Timeout)
+ params.AddInterface("allowed_updates", config.AllowedUpdates)
+
+ return params, nil
+}
+
+// WebhookConfig contains information about a SetWebhook request.
+type WebhookConfig struct {
+ URL *url.URL
+ Certificate RequestFileData
+ IPAddress string
+ MaxConnections int
+ AllowedUpdates []string
+ DropPendingUpdates bool
+}
+
+func (config WebhookConfig) method() string {
+ return "setWebhook"
+}
+
+func (config WebhookConfig) params() (Params, error) {
+ params := make(Params)
+
+ if config.URL != nil {
+ params["url"] = config.URL.String()
+ }
+
+ params.AddNonEmpty("ip_address", config.IPAddress)
+ params.AddNonZero("max_connections", config.MaxConnections)
+ err := params.AddInterface("allowed_updates", config.AllowedUpdates)
+ params.AddBool("drop_pending_updates", config.DropPendingUpdates)
+
+ return params, err
+}
+
+func (config WebhookConfig) files() []RequestFile {
+ if config.Certificate != nil {
+ return []RequestFile{{
+ Name: "certificate",
+ Data: config.Certificate,
+ }}
+ }
+
+ return nil
+}
+
+// DeleteWebhookConfig is a helper to delete a webhook.
+type DeleteWebhookConfig struct {
+ DropPendingUpdates bool
+}
+
+func (config DeleteWebhookConfig) method() string {
+ return "deleteWebhook"
+}
+
+func (config DeleteWebhookConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddBool("drop_pending_updates", config.DropPendingUpdates)
+
+ return params, nil
+}
+
+// InlineConfig contains information on making an InlineQuery response.
+type InlineConfig struct {
+ InlineQueryID string `json:"inline_query_id"`
+ Results []interface{} `json:"results"`
+ CacheTime int `json:"cache_time"`
+ IsPersonal bool `json:"is_personal"`
+ NextOffset string `json:"next_offset"`
+ SwitchPMText string `json:"switch_pm_text"`
+ SwitchPMParameter string `json:"switch_pm_parameter"`
+}
+
+func (config InlineConfig) method() string {
+ return "answerInlineQuery"
+}
+
+func (config InlineConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["inline_query_id"] = config.InlineQueryID
+ params.AddNonZero("cache_time", config.CacheTime)
+ params.AddBool("is_personal", config.IsPersonal)
+ params.AddNonEmpty("next_offset", config.NextOffset)
+ params.AddNonEmpty("switch_pm_text", config.SwitchPMText)
+ params.AddNonEmpty("switch_pm_parameter", config.SwitchPMParameter)
+ err := params.AddInterface("results", config.Results)
+
+ return params, err
+}
+
+// CallbackConfig contains information on making a CallbackQuery response.
+type CallbackConfig struct {
+ CallbackQueryID string `json:"callback_query_id"`
+ Text string `json:"text"`
+ ShowAlert bool `json:"show_alert"`
+ URL string `json:"url"`
+ CacheTime int `json:"cache_time"`
+}
+
+func (config CallbackConfig) method() string {
+ return "answerCallbackQuery"
+}
+
+func (config CallbackConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["callback_query_id"] = config.CallbackQueryID
+ params.AddNonEmpty("text", config.Text)
+ params.AddBool("show_alert", config.ShowAlert)
+ params.AddNonEmpty("url", config.URL)
+ params.AddNonZero("cache_time", config.CacheTime)
+
+ return params, nil
+}
+
+// ChatMemberConfig contains information about a user in a chat for use
+// with administrative functions such as kicking or unbanning a user.
+type ChatMemberConfig struct {
+ ChatID int64
+ SuperGroupUsername string
+ ChannelUsername string
+ UserID int64
+}
+
+// UnbanChatMemberConfig allows you to unban a user.
+type UnbanChatMemberConfig struct {
+ ChatMemberConfig
+ OnlyIfBanned bool
+}
+
+func (config UnbanChatMemberConfig) method() string {
+ return "unbanChatMember"
+}
+
+func (config UnbanChatMemberConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
+ params.AddNonZero64("user_id", config.UserID)
+ params.AddBool("only_if_banned", config.OnlyIfBanned)
+
+ return params, nil
+}
+
+// BanChatMemberConfig contains extra fields to kick user.
+type BanChatMemberConfig struct {
+ ChatMemberConfig
+ UntilDate int64
+ RevokeMessages bool
+}
+
+func (config BanChatMemberConfig) method() string {
+ return "banChatMember"
+}
+
+func (config BanChatMemberConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params.AddNonZero64("user_id", config.UserID)
+ params.AddNonZero64("until_date", config.UntilDate)
+ params.AddBool("revoke_messages", config.RevokeMessages)
+
+ return params, nil
+}
+
+// KickChatMemberConfig contains extra fields to ban user.
+//
+// This was renamed to BanChatMember in later versions of the Telegram Bot API.
+type KickChatMemberConfig = BanChatMemberConfig
+
+// RestrictChatMemberConfig contains fields to restrict members of chat
+type RestrictChatMemberConfig struct {
+ ChatMemberConfig
+ UntilDate int64
+ Permissions *ChatPermissions
+}
+
+func (config RestrictChatMemberConfig) method() string {
+ return "restrictChatMember"
+}
+
+func (config RestrictChatMemberConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
+ params.AddNonZero64("user_id", config.UserID)
+
+ err := params.AddInterface("permissions", config.Permissions)
+ params.AddNonZero64("until_date", config.UntilDate)
+
+ return params, err
+}
+
+// PromoteChatMemberConfig contains fields to promote members of chat
+type PromoteChatMemberConfig struct {
+ ChatMemberConfig
+ IsAnonymous bool
+ CanManageChat bool
+ CanChangeInfo bool
+ CanPostMessages bool
+ CanEditMessages bool
+ CanDeleteMessages bool
+ CanManageVoiceChats bool
+ CanInviteUsers bool
+ CanRestrictMembers bool
+ CanPinMessages bool
+ CanPromoteMembers bool
+}
+
+func (config PromoteChatMemberConfig) method() string {
+ return "promoteChatMember"
+}
+
+func (config PromoteChatMemberConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
+ params.AddNonZero64("user_id", config.UserID)
+
+ params.AddBool("is_anonymous", config.IsAnonymous)
+ params.AddBool("can_manage_chat", config.CanManageChat)
+ params.AddBool("can_change_info", config.CanChangeInfo)
+ params.AddBool("can_post_messages", config.CanPostMessages)
+ params.AddBool("can_edit_messages", config.CanEditMessages)
+ params.AddBool("can_delete_messages", config.CanDeleteMessages)
+ params.AddBool("can_manage_voice_chats", config.CanManageVoiceChats)
+ params.AddBool("can_invite_users", config.CanInviteUsers)
+ params.AddBool("can_restrict_members", config.CanRestrictMembers)
+ params.AddBool("can_pin_messages", config.CanPinMessages)
+ params.AddBool("can_promote_members", config.CanPromoteMembers)
+
+ return params, nil
+}
+
+// SetChatAdministratorCustomTitle sets the title of an administrative user
+// promoted by the bot for a chat.
+type SetChatAdministratorCustomTitle struct {
+ ChatMemberConfig
+ CustomTitle string
+}
+
+func (SetChatAdministratorCustomTitle) method() string {
+ return "setChatAdministratorCustomTitle"
+}
+
+func (config SetChatAdministratorCustomTitle) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername, config.ChannelUsername)
+ params.AddNonZero64("user_id", config.UserID)
+ params.AddNonEmpty("custom_title", config.CustomTitle)
+
+ return params, nil
+}
+
+// BanChatSenderChatConfig bans a channel chat in a supergroup or a channel. The
+// owner of the chat will not be able to send messages and join live streams on
+// behalf of the chat, unless it is unbanned first. The bot must be an
+// administrator in the supergroup or channel for this to work and must have the
+// appropriate administrator rights.
+type BanChatSenderChatConfig struct {
+ ChatID int64
+ ChannelUsername string
+ SenderChatID int64
+ UntilDate int
+}
+
+func (config BanChatSenderChatConfig) method() string {
+ return "banChatSenderChat"
+}
+
+func (config BanChatSenderChatConfig) params() (Params, error) {
+ params := make(Params)
+
+ _ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero64("sender_chat_id", config.SenderChatID)
+ params.AddNonZero("until_date", config.UntilDate)
+
+ return params, nil
+}
+
+// UnbanChatSenderChatConfig unbans a previously banned channel chat in a
+// supergroup or channel. The bot must be an administrator for this to work and
+// must have the appropriate administrator rights.
+type UnbanChatSenderChatConfig struct {
+ ChatID int64
+ ChannelUsername string
+ SenderChatID int64
+}
+
+func (config UnbanChatSenderChatConfig) method() string {
+ return "unbanChatSenderChat"
+}
+
+func (config UnbanChatSenderChatConfig) params() (Params, error) {
+ params := make(Params)
+
+ _ = params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero64("sender_chat_id", config.SenderChatID)
+
+ return params, nil
+}
+
+// ChatConfig contains information about getting information on a chat.
+type ChatConfig struct {
+ ChatID int64
+ SuperGroupUsername string
+}
+
+func (config ChatConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+
+ return params, nil
+}
+
+// ChatInfoConfig contains information about getting chat information.
+type ChatInfoConfig struct {
+ ChatConfig
+}
+
+func (ChatInfoConfig) method() string {
+ return "getChat"
+}
+
+// ChatMemberCountConfig contains information about getting the number of users in a chat.
+type ChatMemberCountConfig struct {
+ ChatConfig
+}
+
+func (ChatMemberCountConfig) method() string {
+ return "getChatMembersCount"
+}
+
+// ChatAdministratorsConfig contains information about getting chat administrators.
+type ChatAdministratorsConfig struct {
+ ChatConfig
+}
+
+func (ChatAdministratorsConfig) method() string {
+ return "getChatAdministrators"
+}
+
+// SetChatPermissionsConfig allows you to set default permissions for the
+// members in a group. The bot must be an administrator and have rights to
+// restrict members.
+type SetChatPermissionsConfig struct {
+ ChatConfig
+ Permissions *ChatPermissions
+}
+
+func (SetChatPermissionsConfig) method() string {
+ return "setChatPermissions"
+}
+
+func (config SetChatPermissionsConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ err := params.AddInterface("permissions", config.Permissions)
+
+ return params, err
+}
+
+// ChatInviteLinkConfig contains information about getting a chat link.
+//
+// Note that generating a new link will revoke any previous links.
+type ChatInviteLinkConfig struct {
+ ChatConfig
+}
+
+func (ChatInviteLinkConfig) method() string {
+ return "exportChatInviteLink"
+}
+
+func (config ChatInviteLinkConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+
+ return params, nil
+}
+
+// CreateChatInviteLinkConfig allows you to create an additional invite link for
+// a chat. The bot must be an administrator in the chat for this to work and
+// must have the appropriate admin rights. The link can be revoked using the
+// RevokeChatInviteLinkConfig.
+type CreateChatInviteLinkConfig struct {
+ ChatConfig
+ Name string
+ ExpireDate int
+ MemberLimit int
+ CreatesJoinRequest bool
+}
+
+func (CreateChatInviteLinkConfig) method() string {
+ return "createChatInviteLink"
+}
+
+func (config CreateChatInviteLinkConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonEmpty("name", config.Name)
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params.AddNonZero("expire_date", config.ExpireDate)
+ params.AddNonZero("member_limit", config.MemberLimit)
+ params.AddBool("creates_join_request", config.CreatesJoinRequest)
+
+ return params, nil
+}
+
+// EditChatInviteLinkConfig allows you to edit a non-primary invite link created
+// by the bot. The bot must be an administrator in the chat for this to work and
+// must have the appropriate admin rights.
+type EditChatInviteLinkConfig struct {
+ ChatConfig
+ InviteLink string
+ Name string
+ ExpireDate int
+ MemberLimit int
+ CreatesJoinRequest bool
+}
+
+func (EditChatInviteLinkConfig) method() string {
+ return "editChatInviteLink"
+}
+
+func (config EditChatInviteLinkConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params.AddNonEmpty("name", config.Name)
+ params["invite_link"] = config.InviteLink
+ params.AddNonZero("expire_date", config.ExpireDate)
+ params.AddNonZero("member_limit", config.MemberLimit)
+ params.AddBool("creates_join_request", config.CreatesJoinRequest)
+
+ return params, nil
+}
+
+// RevokeChatInviteLinkConfig allows you to revoke an invite link created by the
+// bot. If the primary link is revoked, a new link is automatically generated.
+// The bot must be an administrator in the chat for this to work and must have
+// the appropriate admin rights.
+type RevokeChatInviteLinkConfig struct {
+ ChatConfig
+ InviteLink string
+}
+
+func (RevokeChatInviteLinkConfig) method() string {
+ return "revokeChatInviteLink"
+}
+
+func (config RevokeChatInviteLinkConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params["invite_link"] = config.InviteLink
+
+ return params, nil
+}
+
+// ApproveChatJoinRequestConfig allows you to approve a chat join request.
+type ApproveChatJoinRequestConfig struct {
+ ChatConfig
+ UserID int64
+}
+
+func (ApproveChatJoinRequestConfig) method() string {
+ return "approveChatJoinRequest"
+}
+
+func (config ApproveChatJoinRequestConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params.AddNonZero("user_id", int(config.UserID))
+
+ return params, nil
+}
+
+// DeclineChatJoinRequest allows you to decline a chat join request.
+type DeclineChatJoinRequest struct {
+ ChatConfig
+ UserID int64
+}
+
+func (DeclineChatJoinRequest) method() string {
+ return "declineChatJoinRequest"
+}
+
+func (config DeclineChatJoinRequest) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params.AddNonZero("user_id", int(config.UserID))
+
+ return params, nil
+}
+
+// LeaveChatConfig allows you to leave a chat.
+type LeaveChatConfig struct {
+ ChatID int64
+ ChannelUsername string
+}
+
+func (config LeaveChatConfig) method() string {
+ return "leaveChat"
+}
+
+func (config LeaveChatConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+
+ return params, nil
+}
+
+// ChatConfigWithUser contains information about a chat and a user.
+type ChatConfigWithUser struct {
+ ChatID int64
+ SuperGroupUsername string
+ UserID int64
+}
+
+func (config ChatConfigWithUser) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params.AddNonZero64("user_id", config.UserID)
+
+ return params, nil
+}
+
+// GetChatMemberConfig is information about getting a specific member in a chat.
+type GetChatMemberConfig struct {
+ ChatConfigWithUser
+}
+
+func (GetChatMemberConfig) method() string {
+ return "getChatMember"
+}
+
+// InvoiceConfig contains information for sendInvoice request.
+type InvoiceConfig struct {
+ BaseChat
+ Title string // required
+ Description string // required
+ Payload string // required
+ ProviderToken string // required
+ Currency string // required
+ Prices []LabeledPrice // required
+ MaxTipAmount int
+ SuggestedTipAmounts []int
+ StartParameter string
+ ProviderData string
+ PhotoURL string
+ PhotoSize int
+ PhotoWidth int
+ PhotoHeight int
+ NeedName bool
+ NeedPhoneNumber bool
+ NeedEmail bool
+ NeedShippingAddress bool
+ SendPhoneNumberToProvider bool
+ SendEmailToProvider bool
+ IsFlexible bool
+}
+
+func (config InvoiceConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params["title"] = config.Title
+ params["description"] = config.Description
+ params["payload"] = config.Payload
+ params["provider_token"] = config.ProviderToken
+ params["currency"] = config.Currency
+ if err = params.AddInterface("prices", config.Prices); err != nil {
+ return params, err
+ }
+
+ params.AddNonZero("max_tip_amount", config.MaxTipAmount)
+ err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts)
+ params.AddNonEmpty("start_parameter", config.StartParameter)
+ params.AddNonEmpty("provider_data", config.ProviderData)
+ params.AddNonEmpty("photo_url", config.PhotoURL)
+ params.AddNonZero("photo_size", config.PhotoSize)
+ params.AddNonZero("photo_width", config.PhotoWidth)
+ params.AddNonZero("photo_height", config.PhotoHeight)
+ params.AddBool("need_name", config.NeedName)
+ params.AddBool("need_phone_number", config.NeedPhoneNumber)
+ params.AddBool("need_email", config.NeedEmail)
+ params.AddBool("need_shipping_address", config.NeedShippingAddress)
+ params.AddBool("is_flexible", config.IsFlexible)
+ params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider)
+ params.AddBool("send_email_to_provider", config.SendEmailToProvider)
+
+ return params, err
+}
+
+func (config InvoiceConfig) method() string {
+ return "sendInvoice"
+}
+
+// ShippingConfig contains information for answerShippingQuery request.
+type ShippingConfig struct {
+ ShippingQueryID string // required
+ OK bool // required
+ ShippingOptions []ShippingOption
+ ErrorMessage string
+}
+
+func (config ShippingConfig) method() string {
+ return "answerShippingQuery"
+}
+
+func (config ShippingConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["shipping_query_id"] = config.ShippingQueryID
+ params.AddBool("ok", config.OK)
+ err := params.AddInterface("shipping_options", config.ShippingOptions)
+ params.AddNonEmpty("error_message", config.ErrorMessage)
+
+ return params, err
+}
+
+// PreCheckoutConfig conatins information for answerPreCheckoutQuery request.
+type PreCheckoutConfig struct {
+ PreCheckoutQueryID string // required
+ OK bool // required
+ ErrorMessage string
+}
+
+func (config PreCheckoutConfig) method() string {
+ return "answerPreCheckoutQuery"
+}
+
+func (config PreCheckoutConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["pre_checkout_query_id"] = config.PreCheckoutQueryID
+ params.AddBool("ok", config.OK)
+ params.AddNonEmpty("error_message", config.ErrorMessage)
+
+ return params, nil
+}
+
+// DeleteMessageConfig contains information of a message in a chat to delete.
+type DeleteMessageConfig struct {
+ ChannelUsername string
+ ChatID int64
+ MessageID int
+}
+
+func (config DeleteMessageConfig) method() string {
+ return "deleteMessage"
+}
+
+func (config DeleteMessageConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero("message_id", config.MessageID)
+
+ return params, nil
+}
+
+// PinChatMessageConfig contains information of a message in a chat to pin.
+type PinChatMessageConfig struct {
+ ChatID int64
+ ChannelUsername string
+ MessageID int
+ DisableNotification bool
+}
+
+func (config PinChatMessageConfig) method() string {
+ return "pinChatMessage"
+}
+
+func (config PinChatMessageConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero("message_id", config.MessageID)
+ params.AddBool("disable_notification", config.DisableNotification)
+
+ return params, nil
+}
+
+// UnpinChatMessageConfig contains information of a chat message to unpin.
+//
+// If MessageID is not specified, it will unpin the most recent pin.
+type UnpinChatMessageConfig struct {
+ ChatID int64
+ ChannelUsername string
+ MessageID int
+}
+
+func (config UnpinChatMessageConfig) method() string {
+ return "unpinChatMessage"
+}
+
+func (config UnpinChatMessageConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddNonZero("message_id", config.MessageID)
+
+ return params, nil
+}
+
+// UnpinAllChatMessagesConfig contains information of all messages to unpin in
+// a chat.
+type UnpinAllChatMessagesConfig struct {
+ ChatID int64
+ ChannelUsername string
+}
+
+func (config UnpinAllChatMessagesConfig) method() string {
+ return "unpinAllChatMessages"
+}
+
+func (config UnpinAllChatMessagesConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+
+ return params, nil
+}
+
+// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
+type SetChatPhotoConfig struct {
+ BaseFile
+}
+
+func (config SetChatPhotoConfig) method() string {
+ return "setChatPhoto"
+}
+
+func (config SetChatPhotoConfig) files() []RequestFile {
+ return []RequestFile{{
+ Name: "photo",
+ Data: config.File,
+ }}
+}
+
+// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
+type DeleteChatPhotoConfig struct {
+ ChatID int64
+ ChannelUsername string
+}
+
+func (config DeleteChatPhotoConfig) method() string {
+ return "deleteChatPhoto"
+}
+
+func (config DeleteChatPhotoConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+
+ return params, nil
+}
+
+// SetChatTitleConfig allows you to set the title of something other than a private chat.
+type SetChatTitleConfig struct {
+ ChatID int64
+ ChannelUsername string
+
+ Title string
+}
+
+func (config SetChatTitleConfig) method() string {
+ return "setChatTitle"
+}
+
+func (config SetChatTitleConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params["title"] = config.Title
+
+ return params, nil
+}
+
+// SetChatDescriptionConfig allows you to set the description of a supergroup or channel.
+type SetChatDescriptionConfig struct {
+ ChatID int64
+ ChannelUsername string
+
+ Description string
+}
+
+func (config SetChatDescriptionConfig) method() string {
+ return "setChatDescription"
+}
+
+func (config SetChatDescriptionConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params["description"] = config.Description
+
+ return params, nil
+}
+
+// GetStickerSetConfig allows you to get the stickers in a set.
+type GetStickerSetConfig struct {
+ Name string
+}
+
+func (config GetStickerSetConfig) method() string {
+ return "getStickerSet"
+}
+
+func (config GetStickerSetConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["name"] = config.Name
+
+ return params, nil
+}
+
+// UploadStickerConfig allows you to upload a sticker for use in a set later.
+type UploadStickerConfig struct {
+ UserID int64
+ PNGSticker RequestFileData
+}
+
+func (config UploadStickerConfig) method() string {
+ return "uploadStickerFile"
+}
+
+func (config UploadStickerConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero64("user_id", config.UserID)
+
+ return params, nil
+}
+
+func (config UploadStickerConfig) files() []RequestFile {
+ return []RequestFile{{
+ Name: "png_sticker",
+ Data: config.PNGSticker,
+ }}
+}
+
+// NewStickerSetConfig allows creating a new sticker set.
+//
+// You must set either PNGSticker or TGSSticker.
+type NewStickerSetConfig struct {
+ UserID int64
+ Name string
+ Title string
+ PNGSticker RequestFileData
+ TGSSticker RequestFileData
+ Emojis string
+ ContainsMasks bool
+ MaskPosition *MaskPosition
+}
+
+func (config NewStickerSetConfig) method() string {
+ return "createNewStickerSet"
+}
+
+func (config NewStickerSetConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero64("user_id", config.UserID)
+ params["name"] = config.Name
+ params["title"] = config.Title
+
+ params["emojis"] = config.Emojis
+
+ params.AddBool("contains_masks", config.ContainsMasks)
+
+ err := params.AddInterface("mask_position", config.MaskPosition)
+
+ return params, err
+}
+
+func (config NewStickerSetConfig) files() []RequestFile {
+ if config.PNGSticker != nil {
+ return []RequestFile{{
+ Name: "png_sticker",
+ Data: config.PNGSticker,
+ }}
+ }
+
+ return []RequestFile{{
+ Name: "tgs_sticker",
+ Data: config.TGSSticker,
+ }}
+}
+
+// AddStickerConfig allows you to add a sticker to a set.
+type AddStickerConfig struct {
+ UserID int64
+ Name string
+ PNGSticker RequestFileData
+ TGSSticker RequestFileData
+ Emojis string
+ MaskPosition *MaskPosition
+}
+
+func (config AddStickerConfig) method() string {
+ return "addStickerToSet"
+}
+
+func (config AddStickerConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddNonZero64("user_id", config.UserID)
+ params["name"] = config.Name
+ params["emojis"] = config.Emojis
+
+ err := params.AddInterface("mask_position", config.MaskPosition)
+
+ return params, err
+}
+
+func (config AddStickerConfig) files() []RequestFile {
+ if config.PNGSticker != nil {
+ return []RequestFile{{
+ Name: "png_sticker",
+ Data: config.PNGSticker,
+ }}
+ }
+
+ return []RequestFile{{
+ Name: "tgs_sticker",
+ Data: config.TGSSticker,
+ }}
+
+}
+
+// SetStickerPositionConfig allows you to change the position of a sticker in a set.
+type SetStickerPositionConfig struct {
+ Sticker string
+ Position int
+}
+
+func (config SetStickerPositionConfig) method() string {
+ return "setStickerPositionInSet"
+}
+
+func (config SetStickerPositionConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["sticker"] = config.Sticker
+ params.AddNonZero("position", config.Position)
+
+ return params, nil
+}
+
+// DeleteStickerConfig allows you to delete a sticker from a set.
+type DeleteStickerConfig struct {
+ Sticker string
+}
+
+func (config DeleteStickerConfig) method() string {
+ return "deleteStickerFromSet"
+}
+
+func (config DeleteStickerConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["sticker"] = config.Sticker
+
+ return params, nil
+}
+
+// SetStickerSetThumbConfig allows you to set the thumbnail for a sticker set.
+type SetStickerSetThumbConfig struct {
+ Name string
+ UserID int64
+ Thumb RequestFileData
+}
+
+func (config SetStickerSetThumbConfig) method() string {
+ return "setStickerSetThumb"
+}
+
+func (config SetStickerSetThumbConfig) params() (Params, error) {
+ params := make(Params)
+
+ params["name"] = config.Name
+ params.AddNonZero64("user_id", config.UserID)
+
+ return params, nil
+}
+
+func (config SetStickerSetThumbConfig) files() []RequestFile {
+ return []RequestFile{{
+ Name: "thumb",
+ Data: config.Thumb,
+ }}
+}
+
+// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
+type SetChatStickerSetConfig struct {
+ ChatID int64
+ SuperGroupUsername string
+
+ StickerSetName string
+}
+
+func (config SetChatStickerSetConfig) method() string {
+ return "setChatStickerSet"
+}
+
+func (config SetChatStickerSetConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+ params["sticker_set_name"] = config.StickerSetName
+
+ return params, nil
+}
+
+// DeleteChatStickerSetConfig allows you to remove a supergroup's sticker set.
+type DeleteChatStickerSetConfig struct {
+ ChatID int64
+ SuperGroupUsername string
+}
+
+func (config DeleteChatStickerSetConfig) method() string {
+ return "deleteChatStickerSet"
+}
+
+func (config DeleteChatStickerSetConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
+
+ return params, nil
+}
+
+// MediaGroupConfig allows you to send a group of media.
+//
+// Media consist of InputMedia items (InputMediaPhoto, InputMediaVideo).
+type MediaGroupConfig struct {
+ ChatID int64
+ ChannelUsername string
+
+ Media []interface{}
+ DisableNotification bool
+ ReplyToMessageID int
+}
+
+func (config MediaGroupConfig) method() string {
+ return "sendMediaGroup"
+}
+
+func (config MediaGroupConfig) params() (Params, error) {
+ params := make(Params)
+
+ params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
+ params.AddBool("disable_notification", config.DisableNotification)
+ params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
+
+ err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
+
+ return params, err
+}
+
+func (config MediaGroupConfig) files() []RequestFile {
+ return prepareInputMediaForFiles(config.Media)
+}
+
+// DiceConfig contains information about a sendDice request.
+type DiceConfig struct {
+ BaseChat
+ // Emoji on which the dice throw animation is based.
+ // Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰.
+ // Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽,
+ // and values 1-64 for 🎰.
+ // Defaults to “🎲”
+ Emoji string
+}
+
+func (config DiceConfig) method() string {
+ return "sendDice"
+}
+
+func (config DiceConfig) params() (Params, error) {
+ params, err := config.BaseChat.params()
+ if err != nil {
+ return params, err
+ }
+
+ params.AddNonEmpty("emoji", config.Emoji)
+
+ return params, err
+}
+
+// GetMyCommandsConfig gets a list of the currently registered commands.
+type GetMyCommandsConfig struct {
+ Scope *BotCommandScope
+ LanguageCode string
+}
+
+func (config GetMyCommandsConfig) method() string {
+ return "getMyCommands"
+}
+
+func (config GetMyCommandsConfig) params() (Params, error) {
+ params := make(Params)
+
+ err := params.AddInterface("scope", config.Scope)
+ params.AddNonEmpty("language_code", config.LanguageCode)
+
+ return params, err
+}
+
+// SetMyCommandsConfig sets a list of commands the bot understands.
+type SetMyCommandsConfig struct {
+ Commands []BotCommand
+ Scope *BotCommandScope
+ LanguageCode string
+}
+
+func (config SetMyCommandsConfig) method() string {
+ return "setMyCommands"
+}
+
+func (config SetMyCommandsConfig) params() (Params, error) {
+ params := make(Params)
+
+ if err := params.AddInterface("commands", config.Commands); err != nil {
+ return params, err
+ }
+ err := params.AddInterface("scope", config.Scope)
+ params.AddNonEmpty("language_code", config.LanguageCode)
+
+ return params, err
+}
+
+type DeleteMyCommandsConfig struct {
+ Scope *BotCommandScope
+ LanguageCode string
+}
+
+func (config DeleteMyCommandsConfig) method() string {
+ return "deleteMyCommands"
+}
+
+func (config DeleteMyCommandsConfig) params() (Params, error) {
+ params := make(Params)
+
+ err := params.AddInterface("scope", config.Scope)
+ params.AddNonEmpty("language_code", config.LanguageCode)
+
+ return params, err
+}
+
+// prepareInputMediaParam evaluates a single InputMedia and determines if it
+// needs to be modified for a successful upload. If it returns nil, then the
+// value does not need to be included in the params. Otherwise, it will return
+// the same type as was originally provided.
+//
+// The idx is used to calculate the file field name. If you only have a single
+// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
+// media and "attach://file-%d-thumb" for thumbnails.
+//
+// It is expected to be used in conjunction with prepareInputMediaFile.
+func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
+ switch m := inputMedia.(type) {
+ case InputMediaPhoto:
+ if m.Media.NeedsUpload() {
+ m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
+ }
+
+ return m
+ case InputMediaVideo:
+ if m.Media.NeedsUpload() {
+ m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
+ }
+
+ if m.Thumb != nil && m.Thumb.NeedsUpload() {
+ m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
+ }
+
+ return m
+ case InputMediaAudio:
+ if m.Media.NeedsUpload() {
+ m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
+ }
+
+ if m.Thumb != nil && m.Thumb.NeedsUpload() {
+ m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
+ }
+
+ return m
+ case InputMediaDocument:
+ if m.Media.NeedsUpload() {
+ m.Media = fileAttach(fmt.Sprintf("attach://file-%d", idx))
+ }
+
+ if m.Thumb != nil && m.Thumb.NeedsUpload() {
+ m.Thumb = fileAttach(fmt.Sprintf("attach://file-%d-thumb", idx))
+ }
+
+ return m
+ }
+
+ return nil
+}
+
+// prepareInputMediaFile generates an array of RequestFile to provide for
+// Fileable's files method. It returns an array as a single InputMedia may have
+// multiple files, for the primary media and a thumbnail.
+//
+// The idx parameter is used to generate file field names. It uses the names
+// "file-%d" for the main file and "file-%d-thumb" for the thumbnail.
+//
+// It is expected to be used in conjunction with prepareInputMediaParam.
+func prepareInputMediaFile(inputMedia interface{}, idx int) []RequestFile {
+ files := []RequestFile{}
+
+ switch m := inputMedia.(type) {
+ case InputMediaPhoto:
+ if m.Media.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Media,
+ })
+ }
+ case InputMediaVideo:
+ if m.Media.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Media,
+ })
+ }
+
+ if m.Thumb != nil && m.Thumb.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Thumb,
+ })
+ }
+ case InputMediaDocument:
+ if m.Media.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Media,
+ })
+ }
+
+ if m.Thumb != nil && m.Thumb.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Thumb,
+ })
+ }
+ case InputMediaAudio:
+ if m.Media.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Media,
+ })
+ }
+
+ if m.Thumb != nil && m.Thumb.NeedsUpload() {
+ files = append(files, RequestFile{
+ Name: fmt.Sprintf("file-%d", idx),
+ Data: m.Thumb,
+ })
+ }
+ }
+
+ return files
+}
+
+// prepareInputMediaForParams calls prepareInputMediaParam for each item
+// provided and returns a new array with the correct params for a request.
+//
+// It is expected that files will get data from the associated function,
+// prepareInputMediaForFiles.
+func prepareInputMediaForParams(inputMedia []interface{}) []interface{} {
+ newMedia := make([]interface{}, len(inputMedia))
+ copy(newMedia, inputMedia)
+
+ for idx, media := range inputMedia {
+ if param := prepareInputMediaParam(media, idx); param != nil {
+ newMedia[idx] = param
+ }
+ }
+
+ return newMedia
+}
+
+// prepareInputMediaForFiles calls prepareInputMediaFile for each item
+// provided and returns a new array with the correct files for a request.
+//
+// It is expected that params will get data from the associated function,
+// prepareInputMediaForParams.
+func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile {
+ files := []RequestFile{}
+
+ for idx, media := range inputMedia {
+ if file := prepareInputMediaFile(media, idx); file != nil {
+ files = append(files, file...)
+ }
+ }
+
+ return files
+}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/helpers.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/helpers.go
index d2fb165a..8220e74e 100644
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/helpers.go
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/helpers.go
@@ -52,269 +52,177 @@ func NewForward(chatID int64, fromChatID int64, messageID int) ForwardConfig {
}
}
-// NewPhotoUpload creates a new photo uploader.
+// NewCopyMessage creates a new copy message.
+//
+// chatID is where to send it, fromChatID is the source chat,
+// and messageID is the ID of the original message.
+func NewCopyMessage(chatID int64, fromChatID int64, messageID int) CopyMessageConfig {
+ return CopyMessageConfig{
+ BaseChat: BaseChat{ChatID: chatID},
+ FromChatID: fromChatID,
+ MessageID: messageID,
+ }
+}
+
+// NewPhoto creates a new sendPhoto request.
//
// chatID is where to send it, file is a string path to the file,
// FileReader, or FileBytes.
//
// Note that you must send animated GIFs as a document.
-func NewPhotoUpload(chatID int64, file interface{}) PhotoConfig {
+func NewPhoto(chatID int64, file RequestFileData) PhotoConfig {
return PhotoConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewPhotoShare shares an existing photo.
-// You may use this to reshare an existing photo without reuploading it.
+// NewPhotoToChannel creates a new photo uploader to send a photo to a channel.
//
-// chatID is where to send it, fileID is the ID of the file
-// already uploaded.
-func NewPhotoShare(chatID int64, fileID string) PhotoConfig {
+// Note that you must send animated GIFs as a document.
+func NewPhotoToChannel(username string, file RequestFileData) PhotoConfig {
return PhotoConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
- },
- }
-}
-
-// NewAudioUpload creates a new audio uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-func NewAudioUpload(chatID int64, file interface{}) AudioConfig {
- return AudioConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{
+ ChannelUsername: username,
+ },
+ File: file,
},
}
}
-// NewAudioShare shares an existing audio file.
-// You may use this to reshare an existing audio file without
-// reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the audio
-// already uploaded.
-func NewAudioShare(chatID int64, fileID string) AudioConfig {
+// NewAudio creates a new sendAudio request.
+func NewAudio(chatID int64, file RequestFileData) AudioConfig {
return AudioConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
- },
- }
-}
-
-// NewDocumentUpload creates a new document uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-func NewDocumentUpload(chatID int64, file interface{}) DocumentConfig {
- return DocumentConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewDocumentShare shares an existing document.
-// You may use this to reshare an existing document without
-// reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the document
-// already uploaded.
-func NewDocumentShare(chatID int64, fileID string) DocumentConfig {
+// NewDocument creates a new sendDocument request.
+func NewDocument(chatID int64, file RequestFileData) DocumentConfig {
return DocumentConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
- },
- }
-}
-
-// NewStickerUpload creates a new sticker uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-func NewStickerUpload(chatID int64, file interface{}) StickerConfig {
- return StickerConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewStickerShare shares an existing sticker.
-// You may use this to reshare an existing sticker without
-// reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the sticker
-// already uploaded.
-func NewStickerShare(chatID int64, fileID string) StickerConfig {
+// NewSticker creates a new sendSticker request.
+func NewSticker(chatID int64, file RequestFileData) StickerConfig {
return StickerConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewVideoUpload creates a new video uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-func NewVideoUpload(chatID int64, file interface{}) VideoConfig {
+// NewVideo creates a new sendVideo request.
+func NewVideo(chatID int64, file RequestFileData) VideoConfig {
return VideoConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewVideoShare shares an existing video.
-// You may use this to reshare an existing video without reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the video
-// already uploaded.
-func NewVideoShare(chatID int64, fileID string) VideoConfig {
- return VideoConfig{
+// NewAnimation creates a new sendAnimation request.
+func NewAnimation(chatID int64, file RequestFileData) AnimationConfig {
+ return AnimationConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewAnimationUpload creates a new animation uploader.
+// NewVideoNote creates a new sendVideoNote request.
//
// chatID is where to send it, file is a string path to the file,
// FileReader, or FileBytes.
-func NewAnimationUpload(chatID int64, file interface{}) AnimationConfig {
- return AnimationConfig{
+func NewVideoNote(chatID int64, length int, file RequestFileData) VideoNoteConfig {
+ return VideoNoteConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
+ Length: length,
}
}
-// NewAnimationShare shares an existing animation.
-// You may use this to reshare an existing animation without reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the animation
-// already uploaded.
-func NewAnimationShare(chatID int64, fileID string) AnimationConfig {
- return AnimationConfig{
+// NewVoice creates a new sendVoice request.
+func NewVoice(chatID int64, file RequestFileData) VoiceConfig {
+ return VoiceConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
+ BaseChat: BaseChat{ChatID: chatID},
+ File: file,
},
}
}
-// NewVideoNoteUpload creates a new video note uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-func NewVideoNoteUpload(chatID int64, length int, file interface{}) VideoNoteConfig {
- return VideoNoteConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
- },
- Length: length,
+// NewMediaGroup creates a new media group. Files should be an array of
+// two to ten InputMediaPhoto or InputMediaVideo.
+func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig {
+ return MediaGroupConfig{
+ ChatID: chatID,
+ Media: files,
}
}
-// NewVideoNoteShare shares an existing video.
-// You may use this to reshare an existing video without reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the video
-// already uploaded.
-func NewVideoNoteShare(chatID int64, length int, fileID string) VideoNoteConfig {
- return VideoNoteConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
+// NewInputMediaPhoto creates a new InputMediaPhoto.
+func NewInputMediaPhoto(media RequestFileData) InputMediaPhoto {
+ return InputMediaPhoto{
+ BaseInputMedia{
+ Type: "photo",
+ Media: media,
},
- Length: length,
}
}
-// NewVoiceUpload creates a new voice uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-func NewVoiceUpload(chatID int64, file interface{}) VoiceConfig {
- return VoiceConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+// NewInputMediaVideo creates a new InputMediaVideo.
+func NewInputMediaVideo(media RequestFileData) InputMediaVideo {
+ return InputMediaVideo{
+ BaseInputMedia: BaseInputMedia{
+ Type: "video",
+ Media: media,
},
}
}
-// NewVoiceShare shares an existing voice.
-// You may use this to reshare an existing voice without reuploading it.
-//
-// chatID is where to send it, fileID is the ID of the video
-// already uploaded.
-func NewVoiceShare(chatID int64, fileID string) VoiceConfig {
- return VoiceConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
+// NewInputMediaAnimation creates a new InputMediaAnimation.
+func NewInputMediaAnimation(media RequestFileData) InputMediaAnimation {
+ return InputMediaAnimation{
+ BaseInputMedia: BaseInputMedia{
+ Type: "animation",
+ Media: media,
},
}
}
-// NewMediaGroup creates a new media group. Files should be an array of
-// two to ten InputMediaPhoto or InputMediaVideo.
-func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig {
- return MediaGroupConfig{
- BaseChat: BaseChat{
- ChatID: chatID,
+// NewInputMediaAudio creates a new InputMediaAudio.
+func NewInputMediaAudio(media RequestFileData) InputMediaAudio {
+ return InputMediaAudio{
+ BaseInputMedia: BaseInputMedia{
+ Type: "audio",
+ Media: media,
},
- InputMedia: files,
}
}
-// NewInputMediaPhoto creates a new InputMediaPhoto.
-func NewInputMediaPhoto(media string) InputMediaPhoto {
- return InputMediaPhoto{
- Type: "photo",
- Media: media,
- }
-}
-
-// NewInputMediaVideo creates a new InputMediaVideo.
-func NewInputMediaVideo(media string) InputMediaVideo {
- return InputMediaVideo{
- Type: "video",
- Media: media,
+// NewInputMediaDocument creates a new InputMediaDocument.
+func NewInputMediaDocument(media RequestFileData) InputMediaDocument {
+ return InputMediaDocument{
+ BaseInputMedia: BaseInputMedia{
+ Type: "document",
+ Media: media,
+ },
}
}
@@ -369,7 +277,7 @@ func NewChatAction(chatID int64, action string) ChatActionConfig {
// NewUserProfilePhotos gets user profile photos.
//
// userID is the ID of the user you wish to get profile photos from.
-func NewUserProfilePhotos(userID int) UserProfilePhotosConfig {
+func NewUserProfilePhotos(userID int64) UserProfilePhotosConfig {
return UserProfilePhotosConfig{
UserID: userID,
Offset: 0,
@@ -392,25 +300,33 @@ func NewUpdate(offset int) UpdateConfig {
// NewWebhook creates a new webhook.
//
// link is the url parsable link you wish to get the updates.
-func NewWebhook(link string) WebhookConfig {
- u, _ := url.Parse(link)
+func NewWebhook(link string) (WebhookConfig, error) {
+ u, err := url.Parse(link)
+
+ if err != nil {
+ return WebhookConfig{}, err
+ }
return WebhookConfig{
URL: u,
- }
+ }, nil
}
// NewWebhookWithCert creates a new webhook with a certificate.
//
// link is the url you wish to get webhooks,
// file contains a string to a file, FileReader, or FileBytes.
-func NewWebhookWithCert(link string, file interface{}) WebhookConfig {
- u, _ := url.Parse(link)
+func NewWebhookWithCert(link string, file RequestFileData) (WebhookConfig, error) {
+ u, err := url.Parse(link)
+
+ if err != nil {
+ return WebhookConfig{}, err
+ }
return WebhookConfig{
URL: u,
Certificate: file,
- }
+ }, nil
}
// NewInlineQueryResultArticle creates a new inline query article.
@@ -438,6 +354,19 @@ func NewInlineQueryResultArticleMarkdown(id, title, messageText string) InlineQu
}
}
+// NewInlineQueryResultArticleMarkdownV2 creates a new inline query article with MarkdownV2 parsing.
+func NewInlineQueryResultArticleMarkdownV2(id, title, messageText string) InlineQueryResultArticle {
+ return InlineQueryResultArticle{
+ Type: "article",
+ ID: id,
+ Title: title,
+ InputMessageContent: InputTextMessageContent{
+ Text: messageText,
+ ParseMode: "MarkdownV2",
+ },
+ }
+}
+
// NewInlineQueryResultArticleHTML creates a new inline query article with HTML parsing.
func NewInlineQueryResultArticleHTML(id, title, messageText string) InlineQueryResultArticle {
return InlineQueryResultArticle{
@@ -465,7 +394,7 @@ func NewInlineQueryResultCachedGIF(id, gifID string) InlineQueryResultCachedGIF
return InlineQueryResultCachedGIF{
Type: "gif",
ID: id,
- GifID: gifID,
+ GIFID: gifID,
}
}
@@ -478,12 +407,12 @@ 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,
+// NewInlineQueryResultCachedMPEG4GIF create a new inline query with cached MPEG4 GIF.
+func NewInlineQueryResultCachedMPEG4GIF(id, MPEG4GIFID string) InlineQueryResultCachedMPEG4GIF {
+ return InlineQueryResultCachedMPEG4GIF{
+ Type: "mpeg4_gif",
+ ID: id,
+ MPEG4FileID: MPEG4GIFID,
}
}
@@ -534,6 +463,16 @@ func NewInlineQueryResultCachedVideo(id, videoID, title string) InlineQueryResul
}
}
+// NewInlineQueryResultCachedSticker create a new inline query with cached sticker.
+func NewInlineQueryResultCachedSticker(id, stickerID, title string) InlineQueryResultCachedSticker {
+ return InlineQueryResultCachedSticker{
+ Type: "sticker",
+ ID: id,
+ StickerID: stickerID,
+ Title: title,
+ }
+}
+
// NewInlineQueryResultAudio creates a new inline query audio.
func NewInlineQueryResultAudio(id, url, title string) InlineQueryResultAudio {
return InlineQueryResultAudio{
@@ -628,6 +567,18 @@ func NewEditMessageText(chatID int64, messageID int, text string) EditMessageTex
}
}
+// NewEditMessageTextAndMarkup allows you to edit the text and replymarkup of a message.
+func NewEditMessageTextAndMarkup(chatID int64, messageID int, text string, replyMarkup InlineKeyboardMarkup) EditMessageTextConfig {
+ return EditMessageTextConfig{
+ BaseEdit: BaseEdit{
+ ChatID: chatID,
+ MessageID: messageID,
+ ReplyMarkup: &replyMarkup,
+ },
+ Text: text,
+ }
+}
+
// NewEditMessageCaption allows you to edit the caption of a message.
func NewEditMessageCaption(chatID int64, messageID int, caption string) EditMessageCaptionConfig {
return EditMessageCaptionConfig{
@@ -651,17 +602,6 @@ func NewEditMessageReplyMarkup(chatID int64, messageID int, replyMarkup InlineKe
}
}
-// NewHideKeyboard hides the keyboard, with the option for being selective
-// or hiding for everyone.
-func NewHideKeyboard(selective bool) ReplyKeyboardHide {
- log.Println("NewHideKeyboard is deprecated, please use NewRemoveKeyboard")
-
- return ReplyKeyboardHide{
- HideKeyboard: true,
- Selective: selective,
- }
-}
-
// NewRemoveKeyboard hides the keyboard, with the option for being selective
// or hiding for everyone.
func NewRemoveKeyboard(selective bool) ReplyKeyboardRemove {
@@ -717,6 +657,13 @@ func NewReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup {
}
}
+// NewOneTimeReplyKeyboard creates a new one time keyboard.
+func NewOneTimeReplyKeyboard(rows ...[]KeyboardButton) ReplyKeyboardMarkup {
+ markup := NewReplyKeyboard(rows...)
+ markup.OneTimeKeyboard = true
+ return markup
+}
+
// NewInlineKeyboardButtonData creates an inline keyboard button with text
// and data for a callback.
func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton {
@@ -726,6 +673,15 @@ func NewInlineKeyboardButtonData(text, data string) InlineKeyboardButton {
}
}
+// NewInlineKeyboardButtonLoginURL creates an inline keyboard button with text
+// which goes to a LoginURL.
+func NewInlineKeyboardButtonLoginURL(text string, loginURL LoginURL) InlineKeyboardButton {
+ return InlineKeyboardButton{
+ Text: text,
+ LoginURL: &loginURL,
+ }
+}
+
// NewInlineKeyboardButtonURL creates an inline keyboard button with text
// which goes to a URL.
func NewInlineKeyboardButtonURL(text, url string) InlineKeyboardButton {
@@ -784,7 +740,7 @@ func NewCallbackWithAlert(id, text string) CallbackConfig {
}
// NewInvoice creates a new Invoice request to the user.
-func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices *[]LabeledPrice) InvoiceConfig {
+func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices []LabeledPrice) InvoiceConfig {
return InvoiceConfig{
BaseChat: BaseChat{ChatID: chatID},
Title: title,
@@ -796,33 +752,176 @@ func NewInvoice(chatID int64, title, description, payload, providerToken, startP
Prices: prices}
}
-// NewSetChatPhotoUpload creates a new chat photo uploader.
-//
-// chatID is where to send it, file is a string path to the file,
-// FileReader, or FileBytes.
-//
-// Note that you must send animated GIFs as a document.
-func NewSetChatPhotoUpload(chatID int64, file interface{}) SetChatPhotoConfig {
+// NewChatTitle allows you to update the title of a chat.
+func NewChatTitle(chatID int64, title string) SetChatTitleConfig {
+ return SetChatTitleConfig{
+ ChatID: chatID,
+ Title: title,
+ }
+}
+
+// NewChatDescription allows you to update the description of a chat.
+func NewChatDescription(chatID int64, description string) SetChatDescriptionConfig {
+ return SetChatDescriptionConfig{
+ ChatID: chatID,
+ Description: description,
+ }
+}
+
+// NewChatPhoto allows you to update the photo for a chat.
+func NewChatPhoto(chatID int64, photo RequestFileData) SetChatPhotoConfig {
return SetChatPhotoConfig{
BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- File: file,
- UseExisting: false,
+ BaseChat: BaseChat{
+ ChatID: chatID,
+ },
+ File: photo,
},
}
}
-// NewSetChatPhotoShare shares an existing photo.
-// You may use this to reshare an existing photo without reuploading it.
+// NewDeleteChatPhoto allows you to delete the photo for a chat.
+func NewDeleteChatPhoto(chatID int64) DeleteChatPhotoConfig {
+ return DeleteChatPhotoConfig{
+ ChatID: chatID,
+ }
+}
+
+// NewPoll allows you to create a new poll.
+func NewPoll(chatID int64, question string, options ...string) SendPollConfig {
+ return SendPollConfig{
+ BaseChat: BaseChat{
+ ChatID: chatID,
+ },
+ Question: question,
+ Options: options,
+ IsAnonymous: true, // This is Telegram's default.
+ }
+}
+
+// NewStopPoll allows you to stop a poll.
+func NewStopPoll(chatID int64, messageID int) StopPollConfig {
+ return StopPollConfig{
+ BaseEdit{
+ ChatID: chatID,
+ MessageID: messageID,
+ },
+ }
+}
+
+// NewDice allows you to send a random dice roll.
+func NewDice(chatID int64) DiceConfig {
+ return DiceConfig{
+ BaseChat: BaseChat{
+ ChatID: chatID,
+ },
+ }
+}
+
+// NewDiceWithEmoji allows you to send a random roll of one of many types.
//
-// chatID is where to send it, fileID is the ID of the file
-// already uploaded.
-func NewSetChatPhotoShare(chatID int64, fileID string) SetChatPhotoConfig {
- return SetChatPhotoConfig{
- BaseFile: BaseFile{
- BaseChat: BaseChat{ChatID: chatID},
- FileID: fileID,
- UseExisting: true,
+// Emoji may be 🎲 (1-6), 🎯 (1-6), or 🏀 (1-5).
+func NewDiceWithEmoji(chatID int64, emoji string) DiceConfig {
+ return DiceConfig{
+ BaseChat: BaseChat{
+ ChatID: chatID,
},
+ Emoji: emoji,
}
}
+
+// NewBotCommandScopeDefault represents the default scope of bot commands.
+func NewBotCommandScopeDefault() BotCommandScope {
+ return BotCommandScope{Type: "default"}
+}
+
+// NewBotCommandScopeAllPrivateChats represents the scope of bot commands,
+// covering all private chats.
+func NewBotCommandScopeAllPrivateChats() BotCommandScope {
+ return BotCommandScope{Type: "all_private_chats"}
+}
+
+// NewBotCommandScopeAllGroupChats represents the scope of bot commands,
+// covering all group and supergroup chats.
+func NewBotCommandScopeAllGroupChats() BotCommandScope {
+ return BotCommandScope{Type: "all_group_chats"}
+}
+
+// NewBotCommandScopeAllChatAdministrators represents the scope of bot commands,
+// covering all group and supergroup chat administrators.
+func NewBotCommandScopeAllChatAdministrators() BotCommandScope {
+ return BotCommandScope{Type: "all_chat_administrators"}
+}
+
+// NewBotCommandScopeChat represents the scope of bot commands, covering a
+// specific chat.
+func NewBotCommandScopeChat(chatID int64) BotCommandScope {
+ return BotCommandScope{
+ Type: "chat",
+ ChatID: chatID,
+ }
+}
+
+// NewBotCommandScopeChatAdministrators represents the scope of bot commands,
+// covering all administrators of a specific group or supergroup chat.
+func NewBotCommandScopeChatAdministrators(chatID int64) BotCommandScope {
+ return BotCommandScope{
+ Type: "chat_administrators",
+ ChatID: chatID,
+ }
+}
+
+// NewBotCommandScopeChatMember represents the scope of bot commands, covering a
+// specific member of a group or supergroup chat.
+func NewBotCommandScopeChatMember(chatID, userID int64) BotCommandScope {
+ return BotCommandScope{
+ Type: "chat_member",
+ ChatID: chatID,
+ UserID: userID,
+ }
+}
+
+// NewGetMyCommandsWithScope allows you to set the registered commands for a
+// given scope.
+func NewGetMyCommandsWithScope(scope BotCommandScope) GetMyCommandsConfig {
+ return GetMyCommandsConfig{Scope: &scope}
+}
+
+// NewGetMyCommandsWithScopeAndLanguage allows you to set the registered
+// commands for a given scope and language code.
+func NewGetMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) GetMyCommandsConfig {
+ return GetMyCommandsConfig{Scope: &scope, LanguageCode: languageCode}
+}
+
+// NewSetMyCommands allows you to set the registered commands.
+func NewSetMyCommands(commands ...BotCommand) SetMyCommandsConfig {
+ return SetMyCommandsConfig{Commands: commands}
+}
+
+// NewSetMyCommandsWithScope allows you to set the registered commands for a given scope.
+func NewSetMyCommandsWithScope(scope BotCommandScope, commands ...BotCommand) SetMyCommandsConfig {
+ return SetMyCommandsConfig{Commands: commands, Scope: &scope}
+}
+
+// NewSetMyCommandsWithScopeAndLanguage allows you to set the registered commands for a given scope
+// and language code.
+func NewSetMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string, commands ...BotCommand) SetMyCommandsConfig {
+ return SetMyCommandsConfig{Commands: commands, Scope: &scope, LanguageCode: languageCode}
+}
+
+// NewDeleteMyCommands allows you to delete the registered commands.
+func NewDeleteMyCommands() DeleteMyCommandsConfig {
+ return DeleteMyCommandsConfig{}
+}
+
+// NewDeleteMyCommandsWithScope allows you to delete the registered commands for a given
+// scope.
+func NewDeleteMyCommandsWithScope(scope BotCommandScope) DeleteMyCommandsConfig {
+ return DeleteMyCommandsConfig{Scope: &scope}
+}
+
+// NewDeleteMyCommandsWithScopeAndLanguage allows you to delete the registered commands for a given
+// scope and language code.
+func NewDeleteMyCommandsWithScopeAndLanguage(scope BotCommandScope, languageCode string) DeleteMyCommandsConfig {
+ return DeleteMyCommandsConfig{Scope: &scope, LanguageCode: languageCode}
+}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/log.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/log.go
index 18725514..18725514 100644
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/log.go
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/log.go
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/params.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/params.go
new file mode 100644
index 00000000..134f85e4
--- /dev/null
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/params.go
@@ -0,0 +1,97 @@
+package tgbotapi
+
+import (
+ "encoding/json"
+ "reflect"
+ "strconv"
+)
+
+// Params represents a set of parameters that gets passed to a request.
+type Params map[string]string
+
+// AddNonEmpty adds a value if it not an empty string.
+func (p Params) AddNonEmpty(key, value string) {
+ if value != "" {
+ p[key] = value
+ }
+}
+
+// AddNonZero adds a value if it is not zero.
+func (p Params) AddNonZero(key string, value int) {
+ if value != 0 {
+ p[key] = strconv.Itoa(value)
+ }
+}
+
+// AddNonZero64 is the same as AddNonZero except uses an int64.
+func (p Params) AddNonZero64(key string, value int64) {
+ if value != 0 {
+ p[key] = strconv.FormatInt(value, 10)
+ }
+}
+
+// AddBool adds a value of a bool if it is true.
+func (p Params) AddBool(key string, value bool) {
+ if value {
+ p[key] = strconv.FormatBool(value)
+ }
+}
+
+// AddNonZeroFloat adds a floating point value that is not zero.
+func (p Params) AddNonZeroFloat(key string, value float64) {
+ if value != 0 {
+ p[key] = strconv.FormatFloat(value, 'f', 6, 64)
+ }
+}
+
+// AddInterface adds an interface if it is not nil and can be JSON marshalled.
+func (p Params) AddInterface(key string, value interface{}) error {
+ if value == nil || (reflect.ValueOf(value).Kind() == reflect.Ptr && reflect.ValueOf(value).IsNil()) {
+ return nil
+ }
+
+ b, err := json.Marshal(value)
+ if err != nil {
+ return err
+ }
+
+ p[key] = string(b)
+
+ return nil
+}
+
+// AddFirstValid attempts to add the first item that is not a default value.
+//
+// For example, AddFirstValid(0, "", "test") would add "test".
+func (p Params) AddFirstValid(key string, args ...interface{}) error {
+ for _, arg := range args {
+ switch v := arg.(type) {
+ case int:
+ if v != 0 {
+ p[key] = strconv.Itoa(v)
+ return nil
+ }
+ case int64:
+ if v != 0 {
+ p[key] = strconv.FormatInt(v, 10)
+ return nil
+ }
+ case string:
+ if v != "" {
+ p[key] = v
+ return nil
+ }
+ case nil:
+ default:
+ b, err := json.Marshal(arg)
+ if err != nil {
+ return err
+ }
+
+ p[key] = string(b)
+ return nil
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/passport.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/passport.go
index 5f55006d..4fedb965 100644
--- a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/passport.go
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/passport.go
@@ -54,13 +54,15 @@ type (
Credentials *EncryptedCredentials `json:"credentials"`
}
- // PassportFile represents a file uploaded to Telegram Passport. Currently all
+ // PassportFile represents a file uploaded to Telegram Passport. Currently, all
// Telegram Passport files are in JPEG format when decrypted and don't exceed
// 10MB.
PassportFile struct {
// Unique identifier for this file
FileID string `json:"file_id"`
+ FileUniqueID string `json:"file_unique_id"`
+
// File size
FileSize int `json:"file_size"`
@@ -212,7 +214,7 @@ type (
// PassportElementErrorFile represents an issue with a document scan. The
// error is considered resolved when the file with the document scan changes.
PassportElementErrorFile struct {
- // Error source, must be file
+ // Error source, must be a file
Source string `json:"source"`
// The section of the user's Telegram Passport which has the issue, one
diff --git a/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/types.go b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/types.go
new file mode 100644
index 00000000..18b4decb
--- /dev/null
+++ b/vendor/github.com/go-telegram-bot-api/telegram-bot-api/v5/types.go
@@ -0,0 +1,3225 @@
+package tgbotapi
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/url"
+ "strings"
+ "time"
+)
+
+// APIResponse is a response from the Telegram API with the result
+// stored raw.
+type APIResponse struct {
+ Ok bool `json:"ok"`
+ Result json.RawMessage `json:"result,omitempty"`
+ ErrorCode int `json:"error_code,omitempty"`
+ Description string `json:"description,omitempty"`
+ Parameters *ResponseParameters `json:"parameters,omitempty"`
+}
+
+// Error is an error containing extra information returned by the Telegram API.
+type Error struct {
+ Code int
+ Message string
+ ResponseParameters
+}
+
+// Error message string.
+func (e Error) Error() string {
+ return e.Message
+}
+
+// Update is an update response, from GetUpdates.
+type Update struct {
+ // UpdateID is the update's unique identifier.
+ // Update identifiers start from a certain positive number and increase
+ // sequentially.
+ // This ID becomes especially handy if you're using Webhooks,
+ // since it allows you to ignore repeated updates or to restore
+ // the correct update sequence, should they get out of order.
+ // If there are no new updates for at least a week, then identifier
+ // of the next update will be chosen randomly instead of sequentially.
+ UpdateID int `json:"update_id"`
+ // Message new incoming message of any kind — text, photo, sticker, etc.
+ //
+ // optional
+ Message *Message `json:"message,omitempty"`
+ // EditedMessage new version of a message that is known to the bot and was
+ // edited
+ //
+ // optional
+ EditedMessage *Message `json:"edited_message,omitempty"`
+ // ChannelPost new version of a message that is known to the bot and was
+ // edited
+ //
+ // optional
+ ChannelPost *Message `json:"channel_post,omitempty"`
+ // EditedChannelPost new incoming channel post of any kind — text, photo,
+ // sticker, etc.
+ //
+ // optional
+ EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
+ // InlineQuery new incoming inline query
+ //
+ // optional
+ InlineQuery *InlineQuery `json:"inline_query,omitempty"`
+ // ChosenInlineResult is the result of an inline query
+ // that was chosen by a user and sent to their chat partner.
+ // Please see our documentation on the feedback collecting
+ // for details on how to enable these updates for your bot.
+ //
+ // optional
+ ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result,omitempty"`
+ // CallbackQuery new incoming callback query
+ //
+ // optional
+ CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
+ // ShippingQuery new incoming shipping query. Only for invoices with
+ // flexible price
+ //
+ // optional
+ ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"`
+ // PreCheckoutQuery new incoming pre-checkout query. Contains full
+ // information about checkout
+ //
+ // optional
+ PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
+ // Pool new poll state. Bots receive only updates about stopped polls and
+ // polls, which are sent by the bot
+ //
+ // optional
+ Poll *Poll `json:"poll,omitempty"`
+ // PollAnswer user changed their answer in a non-anonymous poll. Bots
+ // receive new votes only in polls that were sent by the bot itself.
+ //
+ // optional
+ PollAnswer *PollAnswer `json:"poll_answer,omitempty"`
+ // MyChatMember is the bot's chat member status was updated in a chat. For
+ // private chats, this update is received only when the bot is blocked or
+ // unblocked by the user.
+ //
+ // optional
+ MyChatMember *ChatMemberUpdated `json:"my_chat_member"`
+ // ChatMember is a chat member's status was updated in a chat. The bot must
+ // be an administrator in the chat and must explicitly specify "chat_member"
+ // in the list of allowed_updates to receive these updates.
+ //
+ // optional
+ ChatMember *ChatMemberUpdated `json:"chat_member"`
+ // ChatJoinRequest is a request to join the chat has been sent. The bot must
+ // have the can_invite_users administrator right in the chat to receive
+ // these updates.
+ //
+ // optional
+ ChatJoinRequest *ChatJoinRequest `json:"chat_join_request"`
+}
+
+// SentFrom returns the user who sent an update. Can be nil, if Telegram did not provide information
+// about the user in the update object.
+func (u *Update) SentFrom() *User {
+ switch {
+ case u.Message != nil:
+ return u.Message.From
+ case u.EditedMessage != nil:
+ return u.EditedMessage.From
+ case u.InlineQuery != nil:
+ return u.InlineQuery.From
+ case u.ChosenInlineResult != nil:
+ return u.ChosenInlineResult.From
+ case u.CallbackQuery != nil:
+ return u.CallbackQuery.From
+ case u.ShippingQuery != nil:
+ return u.ShippingQuery.From
+ case u.PreCheckoutQuery != nil:
+ return u.PreCheckoutQuery.From
+ default:
+ return nil
+ }
+}
+
+// CallbackData returns the callback query data, if it exists.
+func (u *Update) CallbackData() string {
+ if u.CallbackQuery != nil {
+ return u.CallbackQuery.Data
+ }
+ return ""
+}
+
+// FromChat returns the chat where an update occurred.
+func (u *Update) FromChat() *Chat {
+ switch {
+ case u.Message != nil:
+ return u.Message.Chat
+ case u.EditedMessage != nil:
+ return u.EditedMessage.Chat
+ case u.ChannelPost != nil:
+ return u.ChannelPost.Chat
+ case u.EditedChannelPost != nil:
+ return u.EditedChannelPost.Chat
+ case u.CallbackQuery != nil:
+ return u.CallbackQuery.Message.Chat
+ default:
+ return nil
+ }
+}
+
+// UpdatesChannel is the channel for getting updates.
+type UpdatesChannel <-chan Update
+
+// Clear discards all unprocessed incoming updates.
+func (ch UpdatesChannel) Clear() {
+ for len(ch) != 0 {
+ <-ch
+ }
+}
+
+// User represents a Telegram user or bot.
+type User struct {
+ // ID is a unique identifier for this user or bot
+ ID int64 `json:"id"`
+ // IsBot true, if this user is a bot
+ //
+ // optional
+ IsBot bool `json:"is_bot,omitempty"`
+ // FirstName user's or bot's first name
+ FirstName string `json:"first_name"`
+ // LastName user's or bot's last name
+ //
+ // optional
+ LastName string `json:"last_name,omitempty"`
+ // UserName user's or bot's username
+ //
+ // optional
+ UserName string `json:"username,omitempty"`
+ // LanguageCode IETF language tag of the user's language
+ // more info: https://en.wikipedia.org/wiki/IETF_language_tag
+ //
+ // optional
+ LanguageCode string `json:"language_code,omitempty"`
+ // CanJoinGroups is true, if the bot can be invited to groups.
+ // Returned only in getMe.
+ //
+ // optional
+ CanJoinGroups bool `json:"can_join_groups,omitempty"`
+ // CanReadAllGroupMessages is true, if privacy mode is disabled for the bot.
+ // Returned only in getMe.
+ //
+ // optional
+ CanReadAllGroupMessages bool `json:"can_read_all_group_messages,omitempty"`
+ // SupportsInlineQueries is true, if the bot supports inline queries.
+ // Returned only in getMe.
+ //
+ // optional
+ SupportsInlineQueries bool `json:"supports_inline_queries,omitempty"`
+}
+
+// String displays a simple text version of a user.
+//
+// It is normally a user's username, but falls back to a first/last
+// name as available.
+func (u *User) String() string {
+ if u == nil {
+ return ""
+ }
+ if u.UserName != "" {
+ return u.UserName
+ }
+
+ name := u.FirstName
+ if u.LastName != "" {
+ name += " " + u.LastName
+ }
+
+ return name
+}
+
+// Chat represents a chat.
+type Chat struct {
+ // ID is a unique identifier for this chat
+ ID int64 `json:"id"`
+ // Type of chat, can be either “private”, “group”, “supergroup” or “channel”
+ Type string `json:"type"`
+ // Title for supergroups, channels and group chats
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // UserName for private chats, supergroups and channels if available
+ //
+ // optional
+ UserName string `json:"username,omitempty"`
+ // FirstName of the other party in a private chat
+ //
+ // optional
+ FirstName string `json:"first_name,omitempty"`
+ // LastName of the other party in a private chat
+ //
+ // optional
+ LastName string `json:"last_name,omitempty"`
+ // Photo is a chat photo
+ Photo *ChatPhoto `json:"photo"`
+ // Bio is the bio of the other party in a private chat. Returned only in
+ // getChat
+ //
+ // optional
+ Bio string `json:"bio,omitempty"`
+ // HasPrivateForwards is true if privacy settings of the other party in the
+ // private chat allows to use tg://user?id=<user_id> links only in chats
+ // with the user. Returned only in getChat.
+ //
+ // optional
+ HasPrivateForwards bool `json:"has_private_forwards,omitempty"`
+ // Description for groups, supergroups and channel chats
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // InviteLink is a chat invite link, for groups, supergroups and channel chats.
+ // Each administrator in a chat generates their own invite links,
+ // so the bot must first generate the link using exportChatInviteLink
+ //
+ // optional
+ InviteLink string `json:"invite_link,omitempty"`
+ // PinnedMessage is the pinned message, for groups, supergroups and channels
+ //
+ // optional
+ PinnedMessage *Message `json:"pinned_message,omitempty"`
+ // Permissions are default chat member permissions, for groups and
+ // supergroups. Returned only in getChat.
+ //
+ // optional
+ Permissions *ChatPermissions `json:"permissions,omitempty"`
+ // SlowModeDelay is for supergroups, the minimum allowed delay between
+ // consecutive messages sent by each unpriviledged user. Returned only in
+ // getChat.
+ //
+ // optional
+ SlowModeDelay int `json:"slow_mode_delay,omitempty"`
+ // MessageAutoDeleteTime is the time after which all messages sent to the
+ // chat will be automatically deleted; in seconds. Returned only in getChat.
+ //
+ // optional
+ MessageAutoDeleteTime int `json:"message_auto_delete_time,omitempty"`
+ // HasProtectedContent is true if messages from the chat can't be forwarded
+ // to other chats. Returned only in getChat.
+ //
+ // optional
+ HasProtectedContent bool `json:"has_protected_content,omitempty"`
+ // StickerSetName is for supergroups, name of group sticker set.Returned
+ // only in getChat.
+ //
+ // optional
+ StickerSetName string `json:"sticker_set_name,omitempty"`
+ // CanSetStickerSet is true, if the bot can change the group sticker set.
+ // Returned only in getChat.
+ //
+ // optional
+ CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"`
+ // LinkedChatID is a unique identifier for the linked chat, i.e. the
+ // discussion group identifier for a channel and vice versa; for supergroups
+ // and channel chats.
+ //
+ // optional
+ LinkedChatID int64 `json:"linked_chat_id,omitempty"`
+ // Location is for supergroups, the location to which the supergroup is
+ // connected. Returned only in getChat.
+ //
+ // optional
+ Location *ChatLocation `json:"location"`
+}
+
+// IsPrivate returns if the Chat is a private conversation.
+func (c Chat) IsPrivate() bool {
+ return c.Type == "private"
+}
+
+// IsGroup returns if the Chat is a group.
+func (c Chat) IsGroup() bool {
+ return c.Type == "group"
+}
+
+// IsSuperGroup returns if the Chat is a supergroup.
+func (c Chat) IsSuperGroup() bool {
+ return c.Type == "supergroup"
+}
+
+// IsChannel returns if the Chat is a channel.
+func (c Chat) IsChannel() bool {
+ return c.Type == "channel"
+}
+
+// ChatConfig returns a ChatConfig struct for chat related methods.
+func (c Chat) ChatConfig() ChatConfig {
+ return ChatConfig{ChatID: c.ID}
+}
+
+// Message represents a message.
+type Message struct {
+ // MessageID is a unique message identifier inside this chat
+ MessageID int `json:"message_id"`
+ // From is a sender, empty for messages sent to channels;
+ //
+ // optional
+ From *User `json:"from,omitempty"`
+ // SenderChat is the sender of the message, sent on behalf of a chat. The
+ // channel itself for channel messages. The supergroup itself for messages
+ // from anonymous group administrators. The linked channel for messages
+ // automatically forwarded to the discussion group
+ //
+ // optional
+ SenderChat *Chat `json:"sender_chat,omitempty"`
+ // Date of the message was sent in Unix time
+ Date int `json:"date"`
+ // Chat is the conversation the message belongs to
+ Chat *Chat `json:"chat"`
+ // ForwardFrom for forwarded messages, sender of the original message;
+ //
+ // optional
+ ForwardFrom *User `json:"forward_from,omitempty"`
+ // ForwardFromChat for messages forwarded from channels,
+ // information about the original channel;
+ //
+ // optional
+ ForwardFromChat *Chat `json:"forward_from_chat,omitempty"`
+ // ForwardFromMessageID for messages forwarded from channels,
+ // identifier of the original message in the channel;
+ //
+ // optional
+ ForwardFromMessageID int `json:"forward_from_message_id,omitempty"`
+ // ForwardSignature for messages forwarded from channels, signature of the
+ // post author if present
+ //
+ // optional
+ ForwardSignature string `json:"forward_signature,omitempty"`
+ // ForwardSenderName is the sender's name for messages forwarded from users
+ // who disallow adding a link to their account in forwarded messages
+ //
+ // optional
+ ForwardSenderName string `json:"forward_sender_name,omitempty"`
+ // ForwardDate for forwarded messages, date the original message was sent in Unix time;
+ //
+ // optional
+ ForwardDate int `json:"forward_date,omitempty"`
+ // IsAutomaticForward is true if the message is a channel post that was
+ // automatically forwarded to the connected discussion group.
+ //
+ // optional
+ IsAutomaticForward bool `json:"is_automatic_forward,omitempty"`
+ // ReplyToMessage for replies, the original message.
+ // Note that the Message object in this field will not contain further ReplyToMessage fields
+ // even if it itself is a reply;
+ //
+ // optional
+ ReplyToMessage *Message `json:"reply_to_message,omitempty"`
+ // ViaBot through which the message was sent;
+ //
+ // optional
+ ViaBot *User `json:"via_bot,omitempty"`
+ // EditDate of the message was last edited in Unix time;
+ //
+ // optional
+ EditDate int `json:"edit_date,omitempty"`
+ // HasProtectedContent is true if the message can't be forwarded.
+ //
+ // optional
+ HasProtectedContent bool `json:"has_protected_content,omitempty"`
+ // MediaGroupID is the unique identifier of a media message group this message belongs to;
+ //
+ // optional
+ MediaGroupID string `json:"media_group_id,omitempty"`
+ // AuthorSignature is the signature of the post author for messages in channels;
+ //
+ // optional
+ AuthorSignature string `json:"author_signature,omitempty"`
+ // Text is for text messages, the actual UTF-8 text of the message, 0-4096 characters;
+ //
+ // optional
+ Text string `json:"text,omitempty"`
+ // Entities are for text messages, special entities like usernames,
+ // URLs, bot commands, etc. that appear in the text;
+ //
+ // optional
+ Entities []MessageEntity `json:"entities,omitempty"`
+ // Animation message is an animation, information about the animation.
+ // For backward compatibility, when this field is set, the document field will also be set;
+ //
+ // optional
+ Animation *Animation `json:"animation,omitempty"`
+ // Audio message is an audio file, information about the file;
+ //
+ // optional
+ Audio *Audio `json:"audio,omitempty"`
+ // Document message is a general file, information about the file;
+ //
+ // optional
+ Document *Document `json:"document,omitempty"`
+ // Photo message is a photo, available sizes of the photo;
+ //
+ // optional
+ Photo []PhotoSize `json:"photo,omitempty"`
+ // Sticker message is a sticker, information about the sticker;
+ //
+ // optional
+ Sticker *Sticker `json:"sticker,omitempty"`
+ // Video message is a video, information about the video;
+ //
+ // optional
+ Video *Video `json:"video,omitempty"`
+ // VideoNote message is a video note, information about the video message;
+ //
+ // optional
+ VideoNote *VideoNote `json:"video_note,omitempty"`
+ // Voice message is a voice message, information about the file;
+ //
+ // optional
+ Voice *Voice `json:"voice,omitempty"`
+ // Caption for the animation, audio, document, photo, video or voice, 0-1024 characters;
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // CaptionEntities;
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // Contact message is a shared contact, information about the contact;
+ //
+ // optional
+ Contact *Contact `json:"contact,omitempty"`
+ // Dice is a dice with random value;
+ //
+ // optional
+ Dice *Dice `json:"dice,omitempty"`
+ // Game message is a game, information about the game;
+ //
+ // optional
+ Game *Game `json:"game,omitempty"`
+ // Poll is a native poll, information about the poll;
+ //
+ // optional
+ Poll *Poll `json:"poll,omitempty"`
+ // Venue message is a venue, information about the venue.
+ // For backward compatibility, when this field is set, the location field
+ // will also be set;
+ //
+ // optional
+ Venue *Venue `json:"venue,omitempty"`
+ // Location message is a shared location, information about the location;
+ //
+ // optional
+ Location *Location `json:"location,omitempty"`
+ // NewChatMembers that were added to the group or supergroup
+ // and information about them (the bot itself may be one of these members);
+ //
+ // optional
+ NewChatMembers []User `json:"new_chat_members,omitempty"`
+ // LeftChatMember is a member was removed from the group,
+ // information about them (this member may be the bot itself);
+ //
+ // optional
+ LeftChatMember *User `json:"left_chat_member,omitempty"`
+ // NewChatTitle is a chat title was changed to this value;
+ //
+ // optional
+ NewChatTitle string `json:"new_chat_title,omitempty"`
+ // NewChatPhoto is a chat photo was change to this value;
+ //
+ // optional
+ NewChatPhoto []PhotoSize `json:"new_chat_photo,omitempty"`
+ // DeleteChatPhoto is a service message: the chat photo was deleted;
+ //
+ // optional
+ DeleteChatPhoto bool `json:"delete_chat_photo,omitempty"`
+ // GroupChatCreated is a service message: the group has been created;
+ //
+ // optional
+ GroupChatCreated bool `json:"group_chat_created,omitempty"`
+ // SuperGroupChatCreated is a service message: the supergroup has been created.
+ // This field can't be received in a message coming through updates,
+ // because bot can't be a member of a supergroup when it is created.
+ // It can only be found in ReplyToMessage if someone replies to a very first message
+ // in a directly created supergroup;
+ //
+ // optional
+ SuperGroupChatCreated bool `json:"supergroup_chat_created,omitempty"`
+ // ChannelChatCreated is a service message: the channel has been created.
+ // This field can't be received in a message coming through updates,
+ // because bot can't be a member of a channel when it is created.
+ // It can only be found in ReplyToMessage
+ // if someone replies to a very first message in a channel;
+ //
+ // optional
+ ChannelChatCreated bool `json:"channel_chat_created,omitempty"`
+ // MessageAutoDeleteTimerChanged is a service message: auto-delete timer
+ // settings changed in the chat.
+ //
+ // optional
+ MessageAutoDeleteTimerChanged *MessageAutoDeleteTimerChanged `json:"message_auto_delete_timer_changed"`
+ // MigrateToChatID is the group has been migrated to a supergroup with the specified identifier.
+ // This number may be greater than 32 bits and some programming languages
+ // may have difficulty/silent defects in interpreting it.
+ // But it is smaller than 52 bits, so a signed 64-bit integer
+ // or double-precision float type are safe for storing this identifier;
+ //
+ // optional
+ MigrateToChatID int64 `json:"migrate_to_chat_id,omitempty"`
+ // MigrateFromChatID is the supergroup has been migrated from a group with the specified identifier.
+ // This number may be greater than 32 bits and some programming languages
+ // may have difficulty/silent defects in interpreting it.
+ // But it is smaller than 52 bits, so a signed 64-bit integer
+ // or double-precision float type are safe for storing this identifier;
+ //
+ // optional
+ MigrateFromChatID int64 `json:"migrate_from_chat_id,omitempty"`
+ // PinnedMessage is a specified message was pinned.
+ // Note that the Message object in this field will not contain further ReplyToMessage
+ // fields even if it is itself a reply;
+ //
+ // optional
+ PinnedMessage *Message `json:"pinned_message,omitempty"`
+ // Invoice message is an invoice for a payment;
+ //
+ // optional
+ Invoice *Invoice `json:"invoice,omitempty"`
+ // SuccessfulPayment message is a service message about a successful payment,
+ // information about the payment;
+ //
+ // optional
+ SuccessfulPayment *SuccessfulPayment `json:"successful_payment,omitempty"`
+ // ConnectedWebsite is the domain name of the website on which the user has
+ // logged in;
+ //
+ // optional
+ ConnectedWebsite string `json:"connected_website,omitempty"`
+ // PassportData is a Telegram Passport data;
+ //
+ // optional
+ PassportData *PassportData `json:"passport_data,omitempty"`
+ // ProximityAlertTriggered is a service message. A user in the chat
+ // triggered another user's proximity alert while sharing Live Location
+ //
+ // optional
+ ProximityAlertTriggered *ProximityAlertTriggered `json:"proximity_alert_triggered"`
+ // VoiceChatScheduled is a service message: voice chat scheduled.
+ //
+ // optional
+ VoiceChatScheduled *VoiceChatScheduled `json:"voice_chat_scheduled"`
+ // VoiceChatStarted is a service message: voice chat started.
+ //
+ // optional
+ VoiceChatStarted *VoiceChatStarted `json:"voice_chat_started"`
+ // VoiceChatEnded is a service message: voice chat ended.
+ //
+ // optional
+ VoiceChatEnded *VoiceChatEnded `json:"voice_chat_ended"`
+ // VoiceChatParticipantsInvited is a service message: new participants
+ // invited to a voice chat.
+ //
+ // optional
+ VoiceChatParticipantsInvited *VoiceChatParticipantsInvited `json:"voice_chat_participants_invited"`
+ // ReplyMarkup is the Inline keyboard attached to the message.
+ // login_url buttons are represented as ordinary url buttons.
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+}
+
+// Time converts the message timestamp into a Time.
+func (m *Message) Time() time.Time {
+ return time.Unix(int64(m.Date), 0)
+}
+
+// IsCommand returns true if message starts with a "bot_command" entity.
+func (m *Message) IsCommand() bool {
+ if m.Entities == nil || len(m.Entities) == 0 {
+ return false
+ }
+
+ entity := m.Entities[0]
+ return entity.Offset == 0 && entity.IsCommand()
+}
+
+// Command checks if the message was a command and if it was, returns the
+// command. If the Message was not a command, it returns an empty string.
+//
+// If the command contains the at name syntax, it is removed. Use
+// CommandWithAt() if you do not want that.
+func (m *Message) Command() string {
+ command := m.CommandWithAt()
+
+ if i := strings.Index(command, "@"); i != -1 {
+ command = command[:i]
+ }
+
+ return command
+}
+
+// CommandWithAt checks if the message was a command and if it was, returns the
+// command. If the Message was not a command, it returns an empty string.
+//
+// If the command contains the at name syntax, it is not removed. Use Command()
+// if you want that.
+func (m *Message) CommandWithAt() string {
+ if !m.IsCommand() {
+ return ""
+ }
+
+ // IsCommand() checks that the message begins with a bot_command entity
+ entity := m.Entities[0]
+ return m.Text[1:entity.Length]
+}
+
+// CommandArguments checks if the message was a command and if it was,
+// returns all text after the command name. If the Message was not a
+// command, it returns an empty string.
+//
+// Note: The first character after the command name is omitted:
+// - "/foo bar baz" yields "bar baz", not " bar baz"
+// - "/foo-bar baz" yields "bar baz", too
+// Even though the latter is not a command conforming to the spec, the API
+// marks "/foo" as command entity.
+func (m *Message) CommandArguments() string {
+ if !m.IsCommand() {
+ return ""
+ }
+
+ // IsCommand() checks that the message begins with a bot_command entity
+ entity := m.Entities[0]
+
+ if len(m.Text) == entity.Length {
+ return "" // The command makes up the whole message
+ }
+
+ return m.Text[entity.Length+1:]
+}
+
+// MessageID represents a unique message identifier.
+type MessageID struct {
+ MessageID int `json:"message_id"`
+}
+
+// MessageEntity represents one special entity in a text message.
+type MessageEntity struct {
+ // Type of the entity.
+ // Can be:
+ // “mention” (@username),
+ // “hashtag” (#hashtag),
+ // “cashtag” ($USD),
+ // “bot_command” (/start@jobs_bot),
+ // “url” (https://telegram.org),
+ // “email” (do-not-reply@telegram.org),
+ // “phone_number” (+1-212-555-0123),
+ // “bold” (bold text),
+ // “italic” (italic text),
+ // “underline” (underlined text),
+ // “strikethrough” (strikethrough text),
+ // “code” (monowidth string),
+ // “pre” (monowidth block),
+ // “text_link” (for clickable text URLs),
+ // “text_mention” (for users without usernames)
+ Type string `json:"type"`
+ // Offset in UTF-16 code units to the start of the entity
+ Offset int `json:"offset"`
+ // Length
+ Length int `json:"length"`
+ // URL for “text_link” only, url that will be opened after user taps on the text
+ //
+ // optional
+ URL string `json:"url,omitempty"`
+ // User for “text_mention” only, the mentioned user
+ //
+ // optional
+ User *User `json:"user,omitempty"`
+ // Language for “pre” only, the programming language of the entity text
+ //
+ // optional
+ Language string `json:"language,omitempty"`
+}
+
+// ParseURL attempts to parse a URL contained within a MessageEntity.
+func (e MessageEntity) ParseURL() (*url.URL, error) {
+ if e.URL == "" {
+ return nil, errors.New(ErrBadURL)
+ }
+
+ 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 represents one size of a photo or a file / sticker thumbnail.
+type PhotoSize struct {
+ // FileID identifier for this file, which can be used to download or reuse
+ // the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Width photo width
+ Width int `json:"width"`
+ // Height photo height
+ Height int `json:"height"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// Animation represents an animation file.
+type Animation struct {
+ // FileID is the identifier for this file, which can be used to download or reuse
+ // the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Width video width as defined by sender
+ Width int `json:"width"`
+ // Height video height as defined by sender
+ Height int `json:"height"`
+ // Duration of the video in seconds as defined by sender
+ Duration int `json:"duration"`
+ // Thumbnail animation thumbnail as defined by sender
+ //
+ // optional
+ Thumbnail *PhotoSize `json:"thumb,omitempty"`
+ // FileName original animation filename as defined by sender
+ //
+ // optional
+ FileName string `json:"file_name,omitempty"`
+ // MimeType of the file as defined by sender
+ //
+ // optional
+ MimeType string `json:"mime_type,omitempty"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// Audio represents an audio file to be treated as music by the Telegram clients.
+type Audio struct {
+ // FileID is an identifier for this file, which can be used to download or
+ // reuse the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Duration of the audio in seconds as defined by sender
+ Duration int `json:"duration"`
+ // Performer of the audio as defined by sender or by audio tags
+ //
+ // optional
+ Performer string `json:"performer,omitempty"`
+ // Title of the audio as defined by sender or by audio tags
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // FileName is the original filename as defined by sender
+ //
+ // optional
+ FileName string `json:"file_name,omitempty"`
+ // MimeType of the file as defined by sender
+ //
+ // optional
+ MimeType string `json:"mime_type,omitempty"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+ // Thumbnail is the album cover to which the music file belongs
+ //
+ // optional
+ Thumbnail *PhotoSize `json:"thumb,omitempty"`
+}
+
+// Document represents a general file.
+type Document struct {
+ // FileID is an identifier for this file, which can be used to download or
+ // reuse the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Thumbnail document thumbnail as defined by sender
+ //
+ // optional
+ Thumbnail *PhotoSize `json:"thumb,omitempty"`
+ // FileName original filename as defined by sender
+ //
+ // optional
+ FileName string `json:"file_name,omitempty"`
+ // MimeType of the file as defined by sender
+ //
+ // optional
+ MimeType string `json:"mime_type,omitempty"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// Video represents a video file.
+type Video struct {
+ // FileID identifier for this file, which can be used to download or reuse
+ // the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Width video width as defined by sender
+ Width int `json:"width"`
+ // Height video height as defined by sender
+ Height int `json:"height"`
+ // Duration of the video in seconds as defined by sender
+ Duration int `json:"duration"`
+ // Thumbnail video thumbnail
+ //
+ // optional
+ Thumbnail *PhotoSize `json:"thumb,omitempty"`
+ // FileName is the original filename as defined by sender
+ //
+ // optional
+ FileName string `json:"file_name,omitempty"`
+ // MimeType of a file as defined by sender
+ //
+ // optional
+ MimeType string `json:"mime_type,omitempty"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// VideoNote object represents a video message.
+type VideoNote struct {
+ // FileID identifier for this file, which can be used to download or reuse the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Length video width and height (diameter of the video message) as defined by sender
+ Length int `json:"length"`
+ // Duration of the video in seconds as defined by sender
+ Duration int `json:"duration"`
+ // Thumbnail video thumbnail
+ //
+ // optional
+ Thumbnail *PhotoSize `json:"thumb,omitempty"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// Voice represents a voice note.
+type Voice struct {
+ // FileID identifier for this file, which can be used to download or reuse the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Duration of the audio in seconds as defined by sender
+ Duration int `json:"duration"`
+ // MimeType of the file as defined by sender
+ //
+ // optional
+ MimeType string `json:"mime_type,omitempty"`
+ // FileSize file size
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// Contact represents a phone contact.
+//
+// Note that LastName and UserID may be empty.
+type Contact struct {
+ // PhoneNumber contact's phone number
+ PhoneNumber string `json:"phone_number"`
+ // FirstName contact's first name
+ FirstName string `json:"first_name"`
+ // LastName contact's last name
+ //
+ // optional
+ LastName string `json:"last_name,omitempty"`
+ // UserID contact's user identifier in Telegram
+ //
+ // optional
+ UserID int64 `json:"user_id,omitempty"`
+ // VCard is additional data about the contact in the form of a vCard.
+ //
+ // optional
+ VCard string `json:"vcard,omitempty"`
+}
+
+// Dice represents an animated emoji that displays a random value.
+type Dice struct {
+ // Emoji on which the dice throw animation is based
+ Emoji string `json:"emoji"`
+ // Value of the dice
+ Value int `json:"value"`
+}
+
+// PollOption contains information about one answer option in a poll.
+type PollOption struct {
+ // Text is the option text, 1-100 characters
+ Text string `json:"text"`
+ // VoterCount is the number of users that voted for this option
+ VoterCount int `json:"voter_count"`
+}
+
+// PollAnswer represents an answer of a user in a non-anonymous poll.
+type PollAnswer struct {
+ // PollID is the unique poll identifier
+ PollID string `json:"poll_id"`
+ // User who changed the answer to the poll
+ User User `json:"user"`
+ // OptionIDs is the 0-based identifiers of poll options chosen by the user.
+ // May be empty if user retracted vote.
+ OptionIDs []int `json:"option_ids"`
+}
+
+// Poll contains information about a poll.
+type Poll struct {
+ // ID is the unique poll identifier
+ ID string `json:"id"`
+ // Question is the poll question, 1-255 characters
+ Question string `json:"question"`
+ // Options is the list of poll options
+ Options []PollOption `json:"options"`
+ // TotalVoterCount is the total numbers of users who voted in the poll
+ TotalVoterCount int `json:"total_voter_count"`
+ // IsClosed is if the poll is closed
+ IsClosed bool `json:"is_closed"`
+ // IsAnonymous is if the poll is anonymous
+ IsAnonymous bool `json:"is_anonymous"`
+ // Type is the poll type, currently can be "regular" or "quiz"
+ Type string `json:"type"`
+ // AllowsMultipleAnswers is true, if the poll allows multiple answers
+ AllowsMultipleAnswers bool `json:"allows_multiple_answers"`
+ // CorrectOptionID is the 0-based identifier of the correct answer option.
+ // Available only for polls in quiz mode, which are closed, or was sent (not
+ // forwarded) by the bot or to the private chat with the bot.
+ //
+ // optional
+ CorrectOptionID int `json:"correct_option_id,omitempty"`
+ // Explanation is text that is shown when a user chooses an incorrect answer
+ // or taps on the lamp icon in a quiz-style poll, 0-200 characters
+ //
+ // optional
+ Explanation string `json:"explanation,omitempty"`
+ // ExplanationEntities are special entities like usernames, URLs, bot
+ // commands, etc. that appear in the explanation
+ //
+ // optional
+ ExplanationEntities []MessageEntity `json:"explanation_entities,omitempty"`
+ // OpenPeriod is the amount of time in seconds the poll will be active
+ // after creation
+ //
+ // optional
+ OpenPeriod int `json:"open_period,omitempty"`
+ // CloseDate is the point in time (unix timestamp) when the poll will be
+ // automatically closed
+ //
+ // optional
+ CloseDate int `json:"close_date,omitempty"`
+}
+
+// Location represents a point on the map.
+type Location struct {
+ // Longitude as defined by sender
+ Longitude float64 `json:"longitude"`
+ // Latitude as defined by sender
+ Latitude float64 `json:"latitude"`
+ // HorizontalAccuracy is the radius of uncertainty for the location,
+ // measured in meters; 0-1500
+ //
+ // optional
+ HorizontalAccuracy float64 `json:"horizontal_accuracy,omitempty"`
+ // LivePeriod is time relative to the message sending date, during which the
+ // location can be updated, in seconds. For active live locations only.
+ //
+ // optional
+ LivePeriod int `json:"live_period,omitempty"`
+ // Heading is the direction in which user is moving, in degrees; 1-360. For
+ // active live locations only.
+ //
+ // optional
+ Heading int `json:"heading,omitempty"`
+ // ProximityAlertRadius is the maximum distance for proximity alerts about
+ // approaching another chat member, in meters. For sent live locations only.
+ //
+ // optional
+ ProximityAlertRadius int `json:"proximity_alert_radius,omitempty"`
+}
+
+// Venue represents a venue.
+type Venue struct {
+ // Location is the venue location
+ Location Location `json:"location"`
+ // Title is the name of the venue
+ Title string `json:"title"`
+ // Address of the venue
+ Address string `json:"address"`
+ // FoursquareID is the foursquare identifier of the venue
+ //
+ // optional
+ FoursquareID string `json:"foursquare_id,omitempty"`
+ // FoursquareType is the foursquare type of the venue
+ //
+ // optional
+ FoursquareType string `json:"foursquare_type,omitempty"`
+ // GooglePlaceID is the Google Places identifier of the venue
+ //
+ // optional
+ GooglePlaceID string `json:"google_place_id,omitempty"`
+ // GooglePlaceType is the Google Places type of the venue
+ //
+ // optional
+ GooglePlaceType string `json:"google_place_type,omitempty"`
+}
+
+// ProximityAlertTriggered represents a service message sent when a user in the
+// chat triggers a proximity alert sent by another user.
+type ProximityAlertTriggered struct {
+ // Traveler is the user that triggered the alert
+ Traveler User `json:"traveler"`
+ // Watcher is the user that set the alert
+ Watcher User `json:"watcher"`
+ // Distance is the distance between the users
+ Distance int `json:"distance"`
+}
+
+// MessageAutoDeleteTimerChanged represents a service message about a change in
+// auto-delete timer settings.
+type MessageAutoDeleteTimerChanged struct {
+ // New auto-delete time for messages in the chat.
+ MessageAutoDeleteTime int `json:"message_auto_delete_time"`
+}
+
+// VoiceChatScheduled represents a service message about a voice chat scheduled
+// in the chat.
+type VoiceChatScheduled struct {
+ // Point in time (Unix timestamp) when the voice chat is supposed to be
+ // started by a chat administrator
+ StartDate int `json:"start_date"`
+}
+
+// Time converts the scheduled start date into a Time.
+func (m *VoiceChatScheduled) Time() time.Time {
+ return time.Unix(int64(m.StartDate), 0)
+}
+
+// VoiceChatStarted represents a service message about a voice chat started in
+// the chat.
+type VoiceChatStarted struct{}
+
+// VoiceChatEnded represents a service message about a voice chat ended in the
+// chat.
+type VoiceChatEnded struct {
+ // Voice chat duration; in seconds.
+ Duration int `json:"duration"`
+}
+
+// VoiceChatParticipantsInvited represents a service message about new members
+// invited to a voice chat.
+type VoiceChatParticipantsInvited struct {
+ // New members that were invited to the voice chat.
+ //
+ // optional
+ Users []User `json:"users"`
+}
+
+// UserProfilePhotos contains a set of user profile photos.
+type UserProfilePhotos struct {
+ // TotalCount total number of profile pictures the target user has
+ TotalCount int `json:"total_count"`
+ // Photos requested profile pictures (in up to 4 sizes each)
+ Photos [][]PhotoSize `json:"photos"`
+}
+
+// File contains information about a file to download from Telegram.
+type File struct {
+ // FileID identifier for this file, which can be used to download or reuse
+ // the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is the unique identifier for this file, which is supposed to
+ // be the same over time and for different bots. Can't be used to download
+ // or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // FileSize file size, if known
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+ // FilePath file path
+ //
+ // optional
+ FilePath string `json:"file_path,omitempty"`
+}
+
+// Link returns a full path to the download URL for a File.
+//
+// It requires the Bot token to create the link.
+func (f *File) Link(token string) string {
+ return fmt.Sprintf(FileEndpoint, token, f.FilePath)
+}
+
+// ReplyKeyboardMarkup represents a custom keyboard with reply options.
+type ReplyKeyboardMarkup struct {
+ // Keyboard is an array of button rows, each represented by an Array of KeyboardButton objects
+ Keyboard [][]KeyboardButton `json:"keyboard"`
+ // ResizeKeyboard requests clients to resize the keyboard vertically for optimal fit
+ // (e.g., make the keyboard smaller if there are just two rows of buttons).
+ // Defaults to false, in which case the custom keyboard
+ // is always of the same height as the app's standard keyboard.
+ //
+ // optional
+ ResizeKeyboard bool `json:"resize_keyboard,omitempty"`
+ // OneTimeKeyboard requests clients to hide the keyboard as soon as it's been used.
+ // The keyboard will still be available, but clients will automatically display
+ // the usual letter-keyboard in the chat – the user can press a special button
+ // in the input field to see the custom keyboard again.
+ // Defaults to false.
+ //
+ // optional
+ OneTimeKeyboard bool `json:"one_time_keyboard,omitempty"`
+ // InputFieldPlaceholder is the placeholder to be shown in the input field when
+ // the keyboard is active; 1-64 characters.
+ //
+ // optional
+ InputFieldPlaceholder string `json:"input_field_placeholder,omitempty"`
+ // Selective use this parameter if you want to show the keyboard to specific users only.
+ // Targets:
+ // 1) users that are @mentioned in the text of the Message object;
+ // 2) if the bot's message is a reply (has Message.ReplyToMessage not nil), sender of the original message.
+ //
+ // Example: A user requests to change the bot's language,
+ // bot replies to the request with a keyboard to select the new language.
+ // Other users in the group don't see the keyboard.
+ //
+ // optional
+ Selective bool `json:"selective,omitempty"`
+}
+
+// KeyboardButton represents one button of the reply keyboard. For simple text
+// buttons String can be used instead of this object to specify text of the
+// button. Optional fields request_contact, request_location, and request_poll
+// are mutually exclusive.
+type KeyboardButton struct {
+ // Text of the button. If none of the optional fields are used,
+ // it will be sent as a message when the button is pressed.
+ Text string `json:"text"`
+ // RequestContact if True, the user's phone number will be sent
+ // as a contact when the button is pressed.
+ // Available in private chats only.
+ //
+ // optional
+ RequestContact bool `json:"request_contact,omitempty"`
+ // RequestLocation if True, the user's current location will be sent when
+ // the button is pressed.
+ // Available in private chats only.
+ //
+ // optional
+ RequestLocation bool `json:"request_location,omitempty"`
+ // RequestPoll if True, the user will be asked to create a poll and send it
+ // to the bot when the button is pressed. Available in private chats only
+ //
+ // optional
+ RequestPoll *KeyboardButtonPollType `json:"request_poll,omitempty"`
+}
+
+// KeyboardButtonPollType represents type of poll, which is allowed to
+// be created and sent when the corresponding button is pressed.
+type KeyboardButtonPollType struct {
+ // Type is if quiz is passed, the user will be allowed to create only polls
+ // in the quiz mode. If regular is passed, only regular polls will be
+ // allowed. Otherwise, the user will be allowed to create a poll of any type.
+ Type string `json:"type"`
+}
+
+// ReplyKeyboardRemove Upon receiving a message with this object, Telegram
+// clients will remove the current custom keyboard and display the default
+// letter-keyboard. By default, custom keyboards are displayed until a new
+// keyboard is sent by a bot. An exception is made for one-time keyboards
+// that are hidden immediately after the user presses a button.
+type ReplyKeyboardRemove struct {
+ // RemoveKeyboard requests clients to remove the custom keyboard
+ // (user will not be able to summon this keyboard;
+ // if you want to hide the keyboard from sight but keep it accessible,
+ // use one_time_keyboard in ReplyKeyboardMarkup).
+ RemoveKeyboard bool `json:"remove_keyboard"`
+ // Selective use this parameter if you want to remove the keyboard for specific users only.
+ // Targets:
+ // 1) users that are @mentioned in the text of the Message object;
+ // 2) if the bot's message is a reply (has Message.ReplyToMessage not nil), sender of the original message.
+ //
+ // Example: A user votes in a poll, bot returns confirmation message
+ // in reply to the vote and removes the keyboard for that user,
+ // while still showing the keyboard with poll options to users who haven't voted yet.
+ //
+ // optional
+ Selective bool `json:"selective,omitempty"`
+}
+
+// InlineKeyboardMarkup represents an inline keyboard that appears right next to
+// the message it belongs to.
+type InlineKeyboardMarkup struct {
+ // InlineKeyboard array of button rows, each represented by an Array of
+ // InlineKeyboardButton objects
+ InlineKeyboard [][]InlineKeyboardButton `json:"inline_keyboard"`
+}
+
+// InlineKeyboardButton represents one button of an inline keyboard. You must
+// use exactly one of the optional fields.
+//
+// Note that some values are references as even an empty string
+// will change behavior.
+//
+// CallbackGame, if set, MUST be first button in first row.
+type InlineKeyboardButton struct {
+ // Text label text on the button
+ Text string `json:"text"`
+ // URL HTTP or tg:// url to be opened when button is pressed.
+ //
+ // optional
+ URL *string `json:"url,omitempty"`
+ // LoginURL is an HTTP URL used to automatically authorize the user. Can be
+ // used as a replacement for the Telegram Login Widget
+ //
+ // optional
+ LoginURL *LoginURL `json:"login_url,omitempty"`
+ // CallbackData data to be sent in a callback query to the bot when button is pressed, 1-64 bytes.
+ //
+ // optional
+ CallbackData *string `json:"callback_data,omitempty"`
+ // SwitchInlineQuery if set, pressing the button will prompt the user to select one of their chats,
+ // open that chat and insert the bot's username and the specified inline query in the input field.
+ // Can be empty, in which case just the bot's username will be inserted.
+ //
+ // This offers an easy way for users to start using your bot
+ // in inline mode when they are currently in a private chat with it.
+ // Especially useful when combined with switch_pm… actions – in this case
+ // the user will be automatically returned to the chat they switched from,
+ // skipping the chat selection screen.
+ //
+ // optional
+ SwitchInlineQuery *string `json:"switch_inline_query,omitempty"`
+ // SwitchInlineQueryCurrentChat if set, pressing the button will insert the bot's username
+ // and the specified inline query in the current chat's input field.
+ // Can be empty, in which case only the bot's username will be inserted.
+ //
+ // This offers a quick way for the user to open your bot in inline mode
+ // in the same chat – good for selecting something from multiple options.
+ //
+ // optional
+ SwitchInlineQueryCurrentChat *string `json:"switch_inline_query_current_chat,omitempty"`
+ // CallbackGame description of the game that will be launched when the user presses the button.
+ //
+ // optional
+ CallbackGame *CallbackGame `json:"callback_game,omitempty"`
+ // Pay specify True, to send a Pay button.
+ //
+ // NOTE: This type of button must always be the first button in the first row.
+ //
+ // optional
+ Pay bool `json:"pay,omitempty"`
+}
+
+// LoginURL represents a parameter of the inline keyboard button used to
+// automatically authorize a user. Serves as a great replacement for the
+// Telegram Login Widget when the user is coming from Telegram. All the user
+// needs to do is tap/click a button and confirm that they want to log in.
+type LoginURL struct {
+ // URL is an HTTP URL to be opened with user authorization data added to the
+ // query string when the button is pressed. If the user refuses to provide
+ // authorization data, the original URL without information about the user
+ // will be opened. The data added is the same as described in Receiving
+ // authorization data.
+ //
+ // NOTE: You must always check the hash of the received data to verify the
+ // authentication and the integrity of the data as described in Checking
+ // authorization.
+ URL string `json:"url"`
+ // ForwardText is the new text of the button in forwarded messages
+ //
+ // optional
+ ForwardText string `json:"forward_text,omitempty"`
+ // BotUsername is the username of a bot, which will be used for user
+ // authorization. See Setting up a bot for more details. If not specified,
+ // the current bot's username will be assumed. The url's domain must be the
+ // same as the domain linked with the bot. See Linking your domain to the
+ // bot for more details.
+ //
+ // optional
+ BotUsername string `json:"bot_username,omitempty"`
+ // RequestWriteAccess if true requests permission for your bot to send
+ // messages to the user
+ //
+ // optional
+ RequestWriteAccess bool `json:"request_write_access,omitempty"`
+}
+
+// CallbackQuery represents an incoming callback query from a callback button in
+// an inline keyboard. If the button that originated the query was attached to a
+// message sent by the bot, the field message will be present. If the button was
+// attached to a message sent via the bot (in inline mode), the field
+// inline_message_id will be present. Exactly one of the fields data or
+// game_short_name will be present.
+type CallbackQuery struct {
+ // ID unique identifier for this query
+ ID string `json:"id"`
+ // From sender
+ From *User `json:"from"`
+ // Message with the callback button that originated the query.
+ // Note that message content and message date will not be available if the
+ // message is too old.
+ //
+ // optional
+ Message *Message `json:"message,omitempty"`
+ // InlineMessageID identifier of the message sent via the bot in inline
+ // mode, that originated the query.
+ //
+ // optional
+ InlineMessageID string `json:"inline_message_id,omitempty"`
+ // ChatInstance global identifier, uniquely corresponding to the chat to
+ // which the message with the callback button was sent. Useful for high
+ // scores in games.
+ ChatInstance string `json:"chat_instance"`
+ // Data associated with the callback button. Be aware that
+ // a bad client can send arbitrary data in this field.
+ //
+ // optional
+ Data string `json:"data,omitempty"`
+ // GameShortName short name of a Game to be returned, serves as the unique identifier for the game.
+ //
+ // optional
+ GameShortName string `json:"game_short_name,omitempty"`
+}
+
+// ForceReply when receiving a message with this object, Telegram clients will
+// display a reply interface to the user (act as if the user has selected the
+// bot's message and tapped 'Reply'). This can be extremely useful if you want
+// to create user-friendly step-by-step interfaces without having to sacrifice
+// privacy mode.
+type ForceReply struct {
+ // ForceReply shows reply interface to the user,
+ // as if they manually selected the bot's message and tapped 'Reply'.
+ ForceReply bool `json:"force_reply"`
+ // InputFieldPlaceholder is the placeholder to be shown in the input field when
+ // the reply is active; 1-64 characters.
+ //
+ // optional
+ InputFieldPlaceholder string `json:"input_field_placeholder,omitempty"`
+ // Selective use this parameter if you want to force reply from specific users only.
+ // Targets:
+ // 1) users that are @mentioned in the text of the Message object;
+ // 2) if the bot's message is a reply (has Message.ReplyToMessage not nil), sender of the original message.
+ //
+ // optional
+ Selective bool `json:"selective,omitempty"`
+}
+
+// ChatPhoto represents a chat photo.
+type ChatPhoto struct {
+ // SmallFileID is a file identifier of small (160x160) chat photo.
+ // This file_id can be used only for photo download and
+ // only for as long as the photo is not changed.
+ SmallFileID string `json:"small_file_id"`
+ // SmallFileUniqueID is a unique file identifier of small (160x160) chat
+ // photo, which is supposed to be the same over time and for different bots.
+ // Can't be used to download or reuse the file.
+ SmallFileUniqueID string `json:"small_file_unique_id"`
+ // BigFileID is a file identifier of big (640x640) chat photo.
+ // This file_id can be used only for photo download and
+ // only for as long as the photo is not changed.
+ BigFileID string `json:"big_file_id"`
+ // BigFileUniqueID is a file identifier of big (640x640) chat photo, which
+ // is supposed to be the same over time and for different bots. Can't be
+ // used to download or reuse the file.
+ BigFileUniqueID string `json:"big_file_unique_id"`
+}
+
+// ChatInviteLink represents an invite link for a chat.
+type ChatInviteLink struct {
+ // InviteLink is the invite link. If the link was created by another chat
+ // administrator, then the second part of the link will be replaced with “…”.
+ InviteLink string `json:"invite_link"`
+ // Creator of the link.
+ Creator User `json:"creator"`
+ // CreatesJoinRequest is true if users joining the chat via the link need to
+ // be approved by chat administrators.
+ //
+ // optional
+ CreatesJoinRequest bool `json:"creates_join_request"`
+ // IsPrimary is true, if the link is primary.
+ IsPrimary bool `json:"is_primary"`
+ // IsRevoked is true, if the link is revoked.
+ IsRevoked bool `json:"is_revoked"`
+ // Name is the name of the invite link.
+ //
+ // optional
+ Name string `json:"name"`
+ // ExpireDate is the point in time (Unix timestamp) when the link will
+ // expire or has been expired.
+ //
+ // optional
+ ExpireDate int `json:"expire_date"`
+ // MemberLimit is the maximum number of users that can be members of the
+ // chat simultaneously after joining the chat via this invite link; 1-99999.
+ //
+ // optional
+ MemberLimit int `json:"member_limit"`
+ // PendingJoinRequestCount is the number of pending join requests created
+ // using this link.
+ //
+ // optional
+ PendingJoinRequestCount int `json:"pending_join_request_count"`
+}
+
+// ChatMember contains information about one member of a chat.
+type ChatMember struct {
+ // User information about the user
+ User *User `json:"user"`
+ // Status the member's status in the chat.
+ // Can be
+ // “creator”,
+ // “administrator”,
+ // “member”,
+ // “restricted”,
+ // “left” or
+ // “kicked”
+ Status string `json:"status"`
+ // CustomTitle owner and administrators only. Custom title for this user
+ //
+ // optional
+ CustomTitle string `json:"custom_title,omitempty"`
+ // IsAnonymous owner and administrators only. True, if the user's presence
+ // in the chat is hidden
+ //
+ // optional
+ IsAnonymous bool `json:"is_anonymous"`
+ // UntilDate restricted and kicked only.
+ // Date when restrictions will be lifted for this user;
+ // unix time.
+ //
+ // optional
+ UntilDate int64 `json:"until_date,omitempty"`
+ // CanBeEdited administrators only.
+ // True, if the bot is allowed to edit administrator privileges of that user.
+ //
+ // optional
+ CanBeEdited bool `json:"can_be_edited,omitempty"`
+ // CanManageChat administrators only.
+ // True, if the administrator can access the chat event log, chat
+ // statistics, message statistics in channels, see channel members, see
+ // anonymous administrators in supergroups and ignore slow mode. Implied by
+ // any other administrator privilege.
+ //
+ // optional
+ CanManageChat bool `json:"can_manage_chat"`
+ // CanPostMessages administrators only.
+ // True, if the administrator can post in the channel;
+ // channels only.
+ //
+ // optional
+ CanPostMessages bool `json:"can_post_messages,omitempty"`
+ // CanEditMessages administrators only.
+ // True, if the administrator can edit messages of other users and can pin messages;
+ // channels only.
+ //
+ // optional
+ CanEditMessages bool `json:"can_edit_messages,omitempty"`
+ // CanDeleteMessages administrators only.
+ // True, if the administrator can delete messages of other users.
+ //
+ // optional
+ CanDeleteMessages bool `json:"can_delete_messages,omitempty"`
+ // CanManageVoiceChats administrators only.
+ // True, if the administrator can manage voice chats.
+ //
+ // optional
+ CanManageVoiceChats bool `json:"can_manage_voice_chats"`
+ // CanRestrictMembers administrators only.
+ // True, if the administrator can restrict, ban or unban chat members.
+ //
+ // optional
+ CanRestrictMembers bool `json:"can_restrict_members,omitempty"`
+ // CanPromoteMembers administrators only.
+ // True, if the administrator can add new administrators
+ // with a subset of their own privileges or demote administrators that he has promoted,
+ // directly or indirectly (promoted by administrators that were appointed by the user).
+ //
+ // optional
+ CanPromoteMembers bool `json:"can_promote_members,omitempty"`
+ // CanChangeInfo administrators and restricted only.
+ // True, if the user is allowed to change the chat title, photo and other settings.
+ //
+ // optional
+ CanChangeInfo bool `json:"can_change_info,omitempty"`
+ // CanInviteUsers administrators and restricted only.
+ // True, if the user is allowed to invite new users to the chat.
+ //
+ // optional
+ CanInviteUsers bool `json:"can_invite_users,omitempty"`
+ // CanPinMessages administrators and restricted only.
+ // True, if the user is allowed to pin messages; groups and supergroups only
+ //
+ // optional
+ CanPinMessages bool `json:"can_pin_messages,omitempty"`
+ // IsMember is true, if the user is a member of the chat at the moment of
+ // the request
+ IsMember bool `json:"is_member"`
+ // CanSendMessages
+ //
+ // optional
+ CanSendMessages bool `json:"can_send_messages,omitempty"`
+ // CanSendMediaMessages restricted only.
+ // True, if the user is allowed to send text messages, contacts, locations and venues
+ //
+ // optional
+ CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"`
+ // CanSendPolls restricted only.
+ // True, if the user is allowed to send polls
+ //
+ // optional
+ CanSendPolls bool `json:"can_send_polls,omitempty"`
+ // CanSendOtherMessages restricted only.
+ // True, if the user is allowed to send audios, documents,
+ // photos, videos, video notes and voice notes.
+ //
+ // optional
+ CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"`
+ // CanAddWebPagePreviews restricted only.
+ // True, if the user is allowed to add web page previews to their messages.
+ //
+ // optional
+ CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"`
+}
+
+// IsCreator returns if the ChatMember was the creator of the chat.
+func (chat ChatMember) IsCreator() bool { return chat.Status == "creator" }
+
+// IsAdministrator returns if the ChatMember is a chat administrator.
+func (chat ChatMember) IsAdministrator() bool { return chat.Status == "administrator" }
+
+// HasLeft returns if the ChatMember left the chat.
+func (chat ChatMember) HasLeft() bool { return chat.Status == "left" }
+
+// WasKicked returns if the ChatMember was kicked from the chat.
+func (chat ChatMember) WasKicked() bool { return chat.Status == "kicked" }
+
+// ChatMemberUpdated represents changes in the status of a chat member.
+type ChatMemberUpdated struct {
+ // Chat the user belongs to.
+ Chat Chat `json:"chat"`
+ // From is the performer of the action, which resulted in the change.
+ From User `json:"from"`
+ // Date the change was done in Unix time.
+ Date int `json:"date"`
+ // Previous information about the chat member.
+ OldChatMember ChatMember `json:"old_chat_member"`
+ // New information about the chat member.
+ NewChatMember ChatMember `json:"new_chat_member"`
+ // InviteLink is the link which was used by the user to join the chat;
+ // for joining by invite link events only.
+ //
+ // optional
+ InviteLink *ChatInviteLink `json:"invite_link"`
+}
+
+// ChatJoinRequest represents a join request sent to a chat.
+type ChatJoinRequest struct {
+ // Chat to which the request was sent.
+ Chat Chat `json:"chat"`
+ // User that sent the join request.
+ From User `json:"user"`
+ // Date the request was sent in Unix time.
+ Date int `json:"date"`
+ // Bio of the user.
+ //
+ // optional
+ Bio string `json:"bio"`
+ // InviteLink is the link that was used by the user to send the join request.
+ //
+ // optional
+ InviteLink *ChatInviteLink `json:"invite_link"`
+}
+
+// ChatPermissions describes actions that a non-administrator user is
+// allowed to take in a chat. All fields are optional.
+type ChatPermissions struct {
+ // CanSendMessages is true, if the user is allowed to send text messages,
+ // contacts, locations and venues
+ //
+ // optional
+ CanSendMessages bool `json:"can_send_messages,omitempty"`
+ // CanSendMediaMessages is true, if the user is allowed to send audios,
+ // documents, photos, videos, video notes and voice notes, implies
+ // can_send_messages
+ //
+ // optional
+ CanSendMediaMessages bool `json:"can_send_media_messages,omitempty"`
+ // CanSendPolls is true, if the user is allowed to send polls, implies
+ // can_send_messages
+ //
+ // optional
+ CanSendPolls bool `json:"can_send_polls,omitempty"`
+ // CanSendOtherMessages is true, if the user is allowed to send animations,
+ // games, stickers and use inline bots, implies can_send_media_messages
+ //
+ // optional
+ CanSendOtherMessages bool `json:"can_send_other_messages,omitempty"`
+ // CanAddWebPagePreviews is true, if the user is allowed to add web page
+ // previews to their messages, implies can_send_media_messages
+ //
+ // optional
+ CanAddWebPagePreviews bool `json:"can_add_web_page_previews,omitempty"`
+ // CanChangeInfo is true, if the user is allowed to change the chat title,
+ // photo and other settings. Ignored in public supergroups
+ //
+ // optional
+ CanChangeInfo bool `json:"can_change_info,omitempty"`
+ // CanInviteUsers is true, if the user is allowed to invite new users to the
+ // chat
+ //
+ // optional
+ CanInviteUsers bool `json:"can_invite_users,omitempty"`
+ // CanPinMessages is true, if the user is allowed to pin messages. Ignored
+ // in public supergroups
+ //
+ // optional
+ CanPinMessages bool `json:"can_pin_messages,omitempty"`
+}
+
+// ChatLocation represents a location to which a chat is connected.
+type ChatLocation struct {
+ // Location is the location to which the supergroup is connected. Can't be a
+ // live location.
+ Location Location `json:"location"`
+ // Address is the location address; 1-64 characters, as defined by the chat
+ // owner
+ Address string `json:"address"`
+}
+
+// BotCommand represents a bot command.
+type BotCommand struct {
+ // Command text of the command, 1-32 characters.
+ // Can contain only lowercase English letters, digits and underscores.
+ Command string `json:"command"`
+ // Description of the command, 3-256 characters.
+ Description string `json:"description"`
+}
+
+// BotCommandScope represents the scope to which bot commands are applied.
+//
+// It contains the fields for all types of scopes, different types only support
+// specific (or no) fields.
+type BotCommandScope struct {
+ Type string `json:"type"`
+ ChatID int64 `json:"chat_id,omitempty"`
+ UserID int64 `json:"user_id,omitempty"`
+}
+
+// ResponseParameters are various errors that can be returned in APIResponse.
+type ResponseParameters struct {
+ // The group has been migrated to a supergroup with the specified identifier.
+ //
+ // optional
+ MigrateToChatID int64 `json:"migrate_to_chat_id,omitempty"`
+ // In case of exceeding flood control, the number of seconds left to wait
+ // before the request can be repeated.
+ //
+ // optional
+ RetryAfter int `json:"retry_after,omitempty"`
+}
+
+// BaseInputMedia is a base type for the InputMedia types.
+type BaseInputMedia struct {
+ // Type of the result.
+ Type string `json:"type"`
+ // Media file to send. Pass a file_id to send a file
+ // that exists on the Telegram servers (recommended),
+ // pass an HTTP URL for Telegram to get a file from the Internet,
+ // or pass “attach://<file_attach_name>” to upload a new one
+ // using multipart/form-data under <file_attach_name> name.
+ Media RequestFileData `json:"media"`
+ // thumb intentionally missing as it is not currently compatible
+
+ // Caption of the video to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities"`
+}
+
+// InputMediaPhoto is a photo to send as part of a media group.
+type InputMediaPhoto struct {
+ BaseInputMedia
+}
+
+// InputMediaVideo is a video to send as part of a media group.
+type InputMediaVideo struct {
+ BaseInputMedia
+ // Thumbnail of the file sent; can be ignored if thumbnail generation for
+ // the file is supported server-side.
+ //
+ // optional
+ Thumb RequestFileData `json:"thumb,omitempty"`
+ // Width video width
+ //
+ // optional
+ Width int `json:"width,omitempty"`
+ // Height video height
+ //
+ // optional
+ Height int `json:"height,omitempty"`
+ // Duration video duration
+ //
+ // optional
+ Duration int `json:"duration,omitempty"`
+ // SupportsStreaming pass True, if the uploaded video is suitable for streaming.
+ //
+ // optional
+ SupportsStreaming bool `json:"supports_streaming,omitempty"`
+}
+
+// InputMediaAnimation is an animation to send as part of a media group.
+type InputMediaAnimation struct {
+ BaseInputMedia
+ // Thumbnail of the file sent; can be ignored if thumbnail generation for
+ // the file is supported server-side.
+ //
+ // optional
+ Thumb RequestFileData `json:"thumb,omitempty"`
+ // Width video width
+ //
+ // optional
+ Width int `json:"width,omitempty"`
+ // Height video height
+ //
+ // optional
+ Height int `json:"height,omitempty"`
+ // Duration video duration
+ //
+ // optional
+ Duration int `json:"duration,omitempty"`
+}
+
+// InputMediaAudio is an audio to send as part of a media group.
+type InputMediaAudio struct {
+ BaseInputMedia
+ // Thumbnail of the file sent; can be ignored if thumbnail generation for
+ // the file is supported server-side.
+ //
+ // optional
+ Thumb RequestFileData `json:"thumb,omitempty"`
+ // Duration of the audio in seconds
+ //
+ // optional
+ Duration int `json:"duration,omitempty"`
+ // Performer of the audio
+ //
+ // optional
+ Performer string `json:"performer,omitempty"`
+ // Title of the audio
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+}
+
+// InputMediaDocument is a general file to send as part of a media group.
+type InputMediaDocument struct {
+ BaseInputMedia
+ // Thumbnail of the file sent; can be ignored if thumbnail generation for
+ // the file is supported server-side.
+ //
+ // optional
+ Thumb RequestFileData `json:"thumb,omitempty"`
+ // DisableContentTypeDetection disables automatic server-side content type
+ // detection for files uploaded using multipart/form-data. Always true, if
+ // the document is sent as part of an album
+ //
+ // optional
+ DisableContentTypeDetection bool `json:"disable_content_type_detection,omitempty"`
+}
+
+// Sticker represents a sticker.
+type Sticker struct {
+ // FileID is an identifier for this file, which can be used to download or
+ // reuse the file
+ FileID string `json:"file_id"`
+ // FileUniqueID is a unique identifier for this file,
+ // which is supposed to be the same over time and for different bots.
+ // Can't be used to download or reuse the file.
+ FileUniqueID string `json:"file_unique_id"`
+ // Width sticker width
+ Width int `json:"width"`
+ // Height sticker height
+ Height int `json:"height"`
+ // IsAnimated true, if the sticker is animated
+ //
+ // optional
+ IsAnimated bool `json:"is_animated,omitempty"`
+ // Thumbnail sticker thumbnail in the .WEBP or .JPG format
+ //
+ // optional
+ Thumbnail *PhotoSize `json:"thumb,omitempty"`
+ // Emoji associated with the sticker
+ //
+ // optional
+ Emoji string `json:"emoji,omitempty"`
+ // SetName of the sticker set to which the sticker belongs
+ //
+ // optional
+ SetName string `json:"set_name,omitempty"`
+ // MaskPosition is for mask stickers, the position where the mask should be
+ // placed
+ //
+ // optional
+ MaskPosition *MaskPosition `json:"mask_position,omitempty"`
+ // FileSize
+ //
+ // optional
+ FileSize int `json:"file_size,omitempty"`
+}
+
+// StickerSet represents a sticker set.
+type StickerSet struct {
+ // Name sticker set name
+ Name string `json:"name"`
+ // Title sticker set title
+ Title string `json:"title"`
+ // IsAnimated true, if the sticker set contains animated stickers
+ IsAnimated bool `json:"is_animated"`
+ // ContainsMasks true, if the sticker set contains masks
+ ContainsMasks bool `json:"contains_masks"`
+ // Stickers list of all set stickers
+ Stickers []Sticker `json:"stickers"`
+ // Thumb is the sticker set thumbnail in the .WEBP or .TGS format
+ Thumbnail *PhotoSize `json:"thumb"`
+}
+
+// MaskPosition describes the position on faces where a mask should be placed
+// by default.
+type MaskPosition struct {
+ // The part of the face relative to which the mask should be placed.
+ // One of “forehead”, “eyes”, “mouth”, or “chin”.
+ Point string `json:"point"`
+ // Shift by X-axis measured in widths of the mask scaled to the face size,
+ // from left to right. For example, choosing -1.0 will place mask just to
+ // the left of the default mask position.
+ XShift float64 `json:"x_shift"`
+ // Shift by Y-axis measured in heights of the mask scaled to the face size,
+ // from top to bottom. For example, 1.0 will place the mask just below the
+ // default mask position.
+ YShift float64 `json:"y_shift"`
+ // Mask scaling coefficient. For example, 2.0 means double size.
+ Scale float64 `json:"scale"`
+}
+
+// Game represents a game. Use BotFather to create and edit games, their short
+// names will act as unique identifiers.
+type Game struct {
+ // Title of the game
+ Title string `json:"title"`
+ // Description of the game
+ Description string `json:"description"`
+ // Photo that will be displayed in the game message in chats.
+ Photo []PhotoSize `json:"photo"`
+ // Text a brief description of the game or high scores included in the game message.
+ // Can be automatically edited to include current high scores for the game
+ // when the bot calls setGameScore, or manually edited using editMessageText. 0-4096 characters.
+ //
+ // optional
+ Text string `json:"text,omitempty"`
+ // TextEntities special entities that appear in text, such as usernames, URLs, bot commands, etc.
+ //
+ // optional
+ TextEntities []MessageEntity `json:"text_entities,omitempty"`
+ // Animation is an animation that will be displayed in the game message in chats.
+ // Upload via BotFather (https://t.me/botfather).
+ //
+ // optional
+ Animation Animation `json:"animation,omitempty"`
+}
+
+// GameHighScore is a user's score and position on the leaderboard.
+type GameHighScore struct {
+ // Position in high score table for the game
+ Position int `json:"position"`
+ // User user
+ User User `json:"user"`
+ // Score score
+ Score int `json:"score"`
+}
+
+// CallbackGame is for starting a game in an inline keyboard button.
+type CallbackGame struct{}
+
+// WebhookInfo is information about a currently set webhook.
+type WebhookInfo struct {
+ // URL webhook URL, may be empty if webhook is not set up.
+ URL string `json:"url"`
+ // HasCustomCertificate true, if a custom certificate was provided for webhook certificate checks.
+ HasCustomCertificate bool `json:"has_custom_certificate"`
+ // PendingUpdateCount number of updates awaiting delivery.
+ PendingUpdateCount int `json:"pending_update_count"`
+ // IPAddress is the currently used webhook IP address
+ //
+ // optional
+ IPAddress string `json:"ip_address,omitempty"`
+ // LastErrorDate unix time for the most recent error
+ // that happened when trying to deliver an update via webhook.
+ //
+ // optional
+ LastErrorDate int `json:"last_error_date,omitempty"`
+ // LastErrorMessage error message in human-readable format for the most recent error
+ // that happened when trying to deliver an update via webhook.
+ //
+ // optional
+ LastErrorMessage string `json:"last_error_message,omitempty"`
+ // MaxConnections maximum allowed number of simultaneous
+ // HTTPS connections to the webhook for update delivery.
+ //
+ // optional
+ MaxConnections int `json:"max_connections,omitempty"`
+ // AllowedUpdates is a list of update types the bot is subscribed to.
+ // Defaults to all update types
+ //
+ // optional
+ AllowedUpdates []string `json:"allowed_updates,omitempty"`
+}
+
+// IsSet returns true if a webhook is currently set.
+func (info WebhookInfo) IsSet() bool {
+ return info.URL != ""
+}
+
+// InlineQuery is a Query from Telegram for an inline request.
+type InlineQuery struct {
+ // ID unique identifier for this query
+ ID string `json:"id"`
+ // From sender
+ From *User `json:"from"`
+ // Query text of the query (up to 256 characters).
+ Query string `json:"query"`
+ // Offset of the results to be returned, can be controlled by the bot.
+ Offset string `json:"offset"`
+ // Type of the chat, from which the inline query was sent. Can be either
+ // “sender” for a private chat with the inline query sender, “private”,
+ // “group”, “supergroup”, or “channel”. The chat type should be always known
+ // for requests sent from official clients and most third-party clients,
+ // unless the request was sent from a secret chat
+ //
+ // optional
+ ChatType string `json:"chat_type"`
+ // Location sender location, only for bots that request user location.
+ //
+ // optional
+ Location *Location `json:"location,omitempty"`
+}
+
+// InlineQueryResultCachedAudio is an inline query response with cached audio.
+type InlineQueryResultCachedAudio struct {
+ // Type of the result, must be audio
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // AudioID a valid file identifier for the audio file
+ AudioID string `json:"audio_file_id"`
+ // Caption 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the audio
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedDocument is an inline query response with cached document.
+type InlineQueryResultCachedDocument struct {
+ // Type of the result, must be a document
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // DocumentID a valid file identifier for the file
+ DocumentID string `json:"document_file_id"`
+ // Title for the result
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Caption of the document to be sent, 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // Description short description of the result
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // // See formatting options for more details
+ // // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the file
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedGIF is an inline query response with cached gif.
+type InlineQueryResultCachedGIF struct {
+ // Type of the result, must be gif.
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes.
+ ID string `json:"id"`
+ // GifID a valid file identifier for the GIF file.
+ GIFID string `json:"gif_file_id"`
+ // Title for the result
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Caption of the GIF file to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message.
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the GIF animation.
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedMPEG4GIF is an inline query response with cached
+// H.264/MPEG-4 AVC video without sound gif.
+type InlineQueryResultCachedMPEG4GIF struct {
+ // Type of the result, must be mpeg4_gif
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // MPEG4FileID a valid file identifier for the MP4 file
+ MPEG4FileID string `json:"mpeg4_file_id"`
+ // Title for the result
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message.
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the video animation.
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedPhoto is an inline query response with cached photo.
+type InlineQueryResultCachedPhoto struct {
+ // Type of the result, must be a photo.
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes.
+ ID string `json:"id"`
+ // PhotoID a valid file identifier of the photo.
+ PhotoID string `json:"photo_file_id"`
+ // Title for the result.
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Description short description of the result.
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // Caption of the photo to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the photo caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message.
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the photo.
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedSticker is an inline query response with cached sticker.
+type InlineQueryResultCachedSticker struct {
+ // Type of the result, must be a sticker
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // StickerID a valid file identifier of the sticker
+ StickerID string `json:"sticker_file_id"`
+ // Title is a title
+ Title string `json:"title"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the sticker
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedVideo is an inline query response with cached video.
+type InlineQueryResultCachedVideo struct {
+ // Type of the result, must be video
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // VideoID a valid file identifier for the video file
+ VideoID string `json:"video_file_id"`
+ // Title for the result
+ Title string `json:"title"`
+ // Description short description of the result
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // Caption of the video to be sent, 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the video
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultCachedVoice is an inline query response with cached voice.
+type InlineQueryResultCachedVoice struct {
+ // Type of the result, must be voice
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // VoiceID a valid file identifier for the voice message
+ VoiceID string `json:"voice_file_id"`
+ // Title voice message title
+ Title string `json:"title"`
+ // Caption 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the voice message
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultArticle represents a link to an article or web page.
+type InlineQueryResultArticle struct {
+ // Type of the result, must be article.
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 Bytes.
+ ID string `json:"id"`
+ // Title of the result
+ Title string `json:"title"`
+ // InputMessageContent content of the message to be sent.
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+ // ReplyMarkup Inline keyboard attached to the message.
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // URL of the result.
+ //
+ // optional
+ URL string `json:"url,omitempty"`
+ // HideURL pass True, if you don't want the URL to be shown in the message.
+ //
+ // optional
+ HideURL bool `json:"hide_url,omitempty"`
+ // Description short description of the result.
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // ThumbURL url of the thumbnail for the result
+ //
+ // optional
+ ThumbURL string `json:"thumb_url,omitempty"`
+ // ThumbWidth thumbnail width
+ //
+ // optional
+ ThumbWidth int `json:"thumb_width,omitempty"`
+ // ThumbHeight thumbnail height
+ //
+ // optional
+ ThumbHeight int `json:"thumb_height,omitempty"`
+}
+
+// InlineQueryResultAudio is an inline query response audio.
+type InlineQueryResultAudio struct {
+ // Type of the result, must be audio
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // URL a valid url for the audio file
+ URL string `json:"audio_url"`
+ // Title is a title
+ Title string `json:"title"`
+ // Caption 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // Performer is a performer
+ //
+ // optional
+ Performer string `json:"performer,omitempty"`
+ // Duration audio duration in seconds
+ //
+ // optional
+ Duration int `json:"audio_duration,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the audio
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultContact is an inline query response contact.
+type InlineQueryResultContact struct {
+ Type string `json:"type"` // required
+ ID string `json:"id"` // required
+ PhoneNumber string `json:"phone_number"` // required
+ FirstName string `json:"first_name"` // required
+ LastName string `json:"last_name"`
+ VCard string `json:"vcard"`
+ 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 of the result, must be game
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // GameShortName short name of the game
+ GameShortName string `json:"game_short_name"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+}
+
+// InlineQueryResultDocument is an inline query response document.
+type InlineQueryResultDocument struct {
+ // Type of the result, must be a document
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // Title for the result
+ Title string `json:"title"`
+ // Caption of the document to be sent, 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // URL a valid url for the file
+ URL string `json:"document_url"`
+ // MimeType of the content of the file, either “application/pdf” or “application/zip”
+ MimeType string `json:"mime_type"`
+ // Description short description of the result
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the file
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+ // ThumbURL url of the thumbnail (jpeg only) for the file
+ //
+ // optional
+ ThumbURL string `json:"thumb_url,omitempty"`
+ // ThumbWidth thumbnail width
+ //
+ // optional
+ ThumbWidth int `json:"thumb_width,omitempty"`
+ // ThumbHeight thumbnail height
+ //
+ // optional
+ ThumbHeight int `json:"thumb_height,omitempty"`
+}
+
+// InlineQueryResultGIF is an inline query response GIF.
+type InlineQueryResultGIF struct {
+ // Type of the result, must be gif.
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes.
+ ID string `json:"id"`
+ // URL a valid URL for the GIF file. File size must not exceed 1MB.
+ URL string `json:"gif_url"`
+ // ThumbURL url of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result.
+ ThumbURL string `json:"thumb_url"`
+ // Width of the GIF
+ //
+ // optional
+ Width int `json:"gif_width,omitempty"`
+ // Height of the GIF
+ //
+ // optional
+ Height int `json:"gif_height,omitempty"`
+ // Duration of the GIF
+ //
+ // optional
+ Duration int `json:"gif_duration,omitempty"`
+ // Title for the result
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Caption of the GIF file to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the GIF animation.
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultLocation is an inline query response location.
+type InlineQueryResultLocation struct {
+ // Type of the result, must be location
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 Bytes
+ ID string `json:"id"`
+ // Latitude of the location in degrees
+ Latitude float64 `json:"latitude"`
+ // Longitude of the location in degrees
+ Longitude float64 `json:"longitude"`
+ // Title of the location
+ Title string `json:"title"`
+ // HorizontalAccuracy is the radius of uncertainty for the location,
+ // measured in meters; 0-1500
+ //
+ // optional
+ HorizontalAccuracy float64 `json:"horizontal_accuracy"`
+ // LivePeriod is the period in seconds for which the location can be
+ // updated, should be between 60 and 86400.
+ //
+ // optional
+ LivePeriod int `json:"live_period"`
+ // Heading is for live locations, a direction in which the user is moving,
+ // in degrees. Must be between 1 and 360 if specified.
+ //
+ // optional
+ Heading int `json:"heading"`
+ // ProximityAlertRadius is for live locations, a maximum distance for
+ // proximity alerts about approaching another chat member, in meters. Must
+ // be between 1 and 100000 if specified.
+ //
+ // optional
+ ProximityAlertRadius int `json:"proximity_alert_radius"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the location
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+ // ThumbURL url of the thumbnail for the result
+ //
+ // optional
+ ThumbURL string `json:"thumb_url,omitempty"`
+ // ThumbWidth thumbnail width
+ //
+ // optional
+ ThumbWidth int `json:"thumb_width,omitempty"`
+ // ThumbHeight thumbnail height
+ //
+ // optional
+ ThumbHeight int `json:"thumb_height,omitempty"`
+}
+
+// InlineQueryResultMPEG4GIF is an inline query response MPEG4 GIF.
+type InlineQueryResultMPEG4GIF struct {
+ // Type of the result, must be mpeg4_gif
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // URL a valid URL for the MP4 file. File size must not exceed 1MB
+ URL string `json:"mpeg4_url"`
+ // Width video width
+ //
+ // optional
+ Width int `json:"mpeg4_width"`
+ // Height vVideo height
+ //
+ // optional
+ Height int `json:"mpeg4_height"`
+ // Duration video duration
+ //
+ // optional
+ Duration int `json:"mpeg4_duration"`
+ // ThumbURL url of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result.
+ ThumbURL string `json:"thumb_url"`
+ // Title for the result
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Caption of the MPEG-4 file to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the video animation
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultPhoto is an inline query response photo.
+type InlineQueryResultPhoto struct {
+ // Type of the result, must be article.
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 Bytes.
+ ID string `json:"id"`
+ // URL a valid URL of the photo. Photo must be in jpeg format.
+ // Photo size must not exceed 5MB.
+ URL string `json:"photo_url"`
+ // MimeType
+ MimeType string `json:"mime_type"`
+ // Width of the photo
+ //
+ // optional
+ Width int `json:"photo_width,omitempty"`
+ // Height of the photo
+ //
+ // optional
+ Height int `json:"photo_height,omitempty"`
+ // ThumbURL url of the thumbnail for the photo.
+ //
+ // optional
+ ThumbURL string `json:"thumb_url,omitempty"`
+ // Title for the result
+ //
+ // optional
+ Title string `json:"title,omitempty"`
+ // Description short description of the result
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // Caption of the photo to be sent, 0-1024 characters after entities parsing.
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the photo caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message.
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the photo.
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultVenue is an inline query response venue.
+type InlineQueryResultVenue struct {
+ // Type of the result, must be venue
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 Bytes
+ ID string `json:"id"`
+ // Latitude of the venue location in degrees
+ Latitude float64 `json:"latitude"`
+ // Longitude of the venue location in degrees
+ Longitude float64 `json:"longitude"`
+ // Title of the venue
+ Title string `json:"title"`
+ // Address of the venue
+ Address string `json:"address"`
+ // FoursquareID foursquare identifier of the venue if known
+ //
+ // optional
+ FoursquareID string `json:"foursquare_id,omitempty"`
+ // FoursquareType foursquare type of the venue, if known.
+ // (For example, “arts_entertainment/default”, “arts_entertainment/aquarium” or “food/icecream”.)
+ //
+ // optional
+ FoursquareType string `json:"foursquare_type,omitempty"`
+ // GooglePlaceID is the Google Places identifier of the venue
+ //
+ // optional
+ GooglePlaceID string `json:"google_place_id,omitempty"`
+ // GooglePlaceType is the Google Places type of the venue
+ //
+ // optional
+ GooglePlaceType string `json:"google_place_type,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the venue
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+ // ThumbURL url of the thumbnail for the result
+ //
+ // optional
+ ThumbURL string `json:"thumb_url,omitempty"`
+ // ThumbWidth thumbnail width
+ //
+ // optional
+ ThumbWidth int `json:"thumb_width,omitempty"`
+ // ThumbHeight thumbnail height
+ //
+ // optional
+ ThumbHeight int `json:"thumb_height,omitempty"`
+}
+
+// InlineQueryResultVideo is an inline query response video.
+type InlineQueryResultVideo struct {
+ // Type of the result, must be video
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // URL a valid url for the embedded video player or video file
+ URL string `json:"video_url"`
+ // MimeType of the content of video url, “text/html” or “video/mp4”
+ MimeType string `json:"mime_type"`
+ //
+ // ThumbURL url of the thumbnail (jpeg only) for the video
+ // optional
+ ThumbURL string `json:"thumb_url,omitempty"`
+ // Title for the result
+ Title string `json:"title"`
+ // Caption of the video to be sent, 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // Width video width
+ //
+ // optional
+ Width int `json:"video_width,omitempty"`
+ // Height video height
+ //
+ // optional
+ Height int `json:"video_height,omitempty"`
+ // Duration video duration in seconds
+ //
+ // optional
+ Duration int `json:"video_duration,omitempty"`
+ // Description short description of the result
+ //
+ // optional
+ Description string `json:"description,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the video.
+ // This field is required if InlineQueryResultVideo is used to send
+ // an HTML-page as a result (e.g., a YouTube video).
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// InlineQueryResultVoice is an inline query response voice.
+type InlineQueryResultVoice struct {
+ // Type of the result, must be voice
+ Type string `json:"type"`
+ // ID unique identifier for this result, 1-64 bytes
+ ID string `json:"id"`
+ // URL a valid URL for the voice recording
+ URL string `json:"voice_url"`
+ // Title recording title
+ Title string `json:"title"`
+ // Caption 0-1024 characters after entities parsing
+ //
+ // optional
+ Caption string `json:"caption,omitempty"`
+ // ParseMode mode for parsing entities in the video caption.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // CaptionEntities is a list of special entities that appear in the caption,
+ // which can be specified instead of parse_mode
+ //
+ // optional
+ CaptionEntities []MessageEntity `json:"caption_entities,omitempty"`
+ // Duration recording duration in seconds
+ //
+ // optional
+ Duration int `json:"voice_duration,omitempty"`
+ // ReplyMarkup inline keyboard attached to the message
+ //
+ // optional
+ ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
+ // InputMessageContent content of the message to be sent instead of the voice recording
+ //
+ // optional
+ InputMessageContent interface{} `json:"input_message_content,omitempty"`
+}
+
+// ChosenInlineResult is an inline query result chosen by a User
+type ChosenInlineResult struct {
+ // ResultID the unique identifier for the result that was chosen
+ ResultID string `json:"result_id"`
+ // From the user that chose the result
+ From *User `json:"from"`
+ // Location sender location, only for bots that require user location
+ //
+ // optional
+ Location *Location `json:"location,omitempty"`
+ // InlineMessageID identifier of the sent inline message.
+ // Available only if there is an inline keyboard attached to the message.
+ // Will be also received in callback queries and can be used to edit the message.
+ //
+ // optional
+ InlineMessageID string `json:"inline_message_id,omitempty"`
+ // Query the query that was used to obtain the result
+ Query string `json:"query"`
+}
+
+// InputTextMessageContent contains text for displaying
+// as an inline query result.
+type InputTextMessageContent struct {
+ // Text of the message to be sent, 1-4096 characters
+ Text string `json:"message_text"`
+ // ParseMode mode for parsing entities in the message text.
+ // See formatting options for more details
+ // (https://core.telegram.org/bots/api#formatting-options).
+ //
+ // optional
+ ParseMode string `json:"parse_mode,omitempty"`
+ // Entities is a list of special entities that appear in message text, which
+ // can be specified instead of parse_mode
+ //
+ // optional
+ Entities []MessageEntity `json:"entities,omitempty"`
+ // DisableWebPagePreview disables link previews for links in the sent message
+ //
+ // optional
+ DisableWebPagePreview bool `json:"disable_web_page_preview,omitempty"`
+}
+
+// InputLocationMessageContent contains a location for displaying
+// as an inline query result.
+type InputLocationMessageContent struct {
+ // Latitude of the location in degrees
+ Latitude float64 `json:"latitude"`
+ // Longitude of the location in degrees
+ Longitude float64 `json:"longitude"`
+ // HorizontalAccuracy is the radius of uncertainty for the location,
+ // measured in meters; 0-1500
+ //
+ // optional
+ HorizontalAccuracy float64 `json:"horizontal_accuracy"`
+ // LivePeriod is the period in seconds for which the location can be
+ // updated, should be between 60 and 86400
+ //
+ // optional
+ LivePeriod int `json:"live_period,omitempty"`
+ // Heading is for live locations, a direction in which the user is moving,
+ // in degrees. Must be between 1 and 360 if specified.
+ //
+ // optional
+ Heading int `json:"heading"`
+ // ProximityAlertRadius is for live locations, a maximum distance for
+ // proximity alerts about approaching another chat member, in meters. Must
+ // be between 1 and 100000 if specified.
+ //
+ // optional
+ ProximityAlertRadius int `json:"proximity_alert_radius"`
+}
+
+// InputVenueMessageContent contains a venue for displaying
+// as an inline query result.
+type InputVenueMessageContent struct {
+ // Latitude of the venue in degrees
+ Latitude float64 `json:"latitude"`
+ // Longitude of the venue in degrees
+ Longitude float64 `json:"longitude"`
+ // Title name of the venue
+ Title string `json:"title"`
+ // Address of the venue
+ Address string `json:"address"`
+ // FoursquareID foursquare identifier of the venue, if known
+ //
+ // optional
+ FoursquareID string `json:"foursquare_id,omitempty"`
+ // FoursquareType Foursquare type of the venue, if known
+ //
+ // optional
+ FoursquareType string `json:"foursquare_type,omitempty"`
+ // GooglePlaceID is the Google Places identifier of the venue
+ //
+ // optional
+ GooglePlaceID string `json:"google_place_id"`
+ // GooglePlaceType is the Google Places type of the venue
+ //
+ // optional
+ GooglePlaceType string `json:"google_place_type"`
+}
+
+// InputContactMessageContent contains a contact for displaying
+// as an inline query result.
+type InputContactMessageContent struct {
+ // PhoneNumber contact's phone number
+ PhoneNumber string `json:"phone_number"`
+ // FirstName contact's first name
+ FirstName string `json:"first_name"`
+ // LastName contact's last name
+ //
+ // optional
+ LastName string `json:"last_name,omitempty"`
+ // Additional data about the contact in the form of a vCard
+ //
+ // optional
+ VCard string `json:"vcard,omitempty"`
+}
+
+// InputInvoiceMessageContent represents the content of an invoice message to be
+// sent as the result of an inline query.
+type InputInvoiceMessageContent struct {
+ // Product name, 1-32 characters
+ Title string `json:"title"`
+ // Product description, 1-255 characters
+ Description string `json:"description"`
+ // Bot-defined invoice payload, 1-128 bytes. This will not be displayed to
+ // the user, use for your internal processes.
+ Payload string `json:"payload"`
+ // Payment provider token, obtained via Botfather
+ ProviderToken string `json:"provider_token"`
+ // Three-letter ISO 4217 currency code
+ Currency string `json:"currency"`
+ // Price breakdown, a JSON-serialized list of components (e.g. product
+ // price, tax, discount, delivery cost, delivery tax, bonus, etc.)
+ Prices []LabeledPrice `json:"prices"`
+ // The maximum accepted amount for tips in the smallest units of the
+ // currency (integer, not float/double).
+ //
+ // optional
+ MaxTipAmount int `json:"max_tip_amount,omitempty"`
+ // An array of suggested amounts of tip in the smallest units of the
+ // currency (integer, not float/double). At most 4 suggested tip amounts can
+ // be specified. The suggested tip amounts must be positive, passed in a
+ // strictly increased order and must not exceed max_tip_amount.
+ //
+ // optional
+ SuggestedTipAmounts []int `json:"suggested_tip_amounts,omitempty"`
+ // A JSON-serialized object for data about the invoice, which will be shared
+ // with the payment provider. A detailed description of the required fields
+ // should be provided by the payment provider.
+ //
+ // optional
+ ProviderData string `json:"provider_data,omitempty"`
+ // URL of the product photo for the invoice. Can be a photo of the goods or
+ // a marketing image for a service. People like it better when they see what
+ // they are paying for.
+ //
+ // optional
+ PhotoURL string `json:"photo_url,omitempty"`
+ // Photo size
+ //
+ // optional
+ PhotoSize int `json:"photo_size,omitempty"`
+ // Photo width
+ //
+ // optional
+ PhotoWidth int `json:"photo_width,omitempty"`
+ // Photo height
+ //
+ // optional
+ PhotoHeight int `json:"photo_height,omitempty"`
+ // Pass True, if you require the user's full name to complete the order
+ //
+ // optional
+ NeedName bool `json:"need_name,omitempty"`
+ // Pass True, if you require the user's phone number to complete the order
+ //
+ // optional
+ NeedPhoneNumber bool `json:"need_phone_number,omitempty"`
+ // Pass True, if you require the user's email address to complete the order
+ //
+ // optional
+ NeedEmail bool `json:"need_email,omitempty"`
+ // Pass True, if you require the user's shipping address to complete the order
+ //
+ // optional
+ NeedShippingAddress bool `json:"need_shipping_address,omitempty"`
+ // Pass True, if user's phone number should be sent to provider
+ //
+ // optional
+ SendPhoneNumberToProvider bool `json:"send_phone_number_to_provider,omitempty"`
+ // Pass True, if user's email address should be sent to provider
+ //
+ // optional
+ SendEmailToProvider bool `json:"send_email_to_provider,omitempty"`
+ // Pass True, if the final price depends on the shipping method
+ //
+ // optional
+ IsFlexible bool `json:"is_flexible,omitempty"`
+}
+
+// LabeledPrice represents a portion of the price for goods or services.
+type LabeledPrice struct {
+ // Label portion label
+ Label string `json:"label"`
+ // Amount price of the product in the smallest units of the currency (integer, not float/double).
+ // For example, for a price of US$ 1.45 pass amount = 145.
+ // See the exp parameter in currencies.json
+ // (https://core.telegram.org/bots/payments/currencies.json),
+ // it shows the number of digits past the decimal point
+ // for each currency (2 for the majority of currencies).
+ Amount int `json:"amount"`
+}
+
+// Invoice contains basic information about an invoice.
+type Invoice struct {
+ // Title product name
+ Title string `json:"title"`
+ // Description product description
+ Description string `json:"description"`
+ // StartParameter unique bot deep-linking parameter that can be used to generate this invoice
+ StartParameter string `json:"start_parameter"`
+ // Currency three-letter ISO 4217 currency code
+ // (see https://core.telegram.org/bots/payments#supported-currencies)
+ Currency string `json:"currency"`
+ // TotalAmount total price in the smallest units of the currency (integer, not float/double).
+ // For example, for a price of US$ 1.45 pass amount = 145.
+ // See the exp parameter in currencies.json
+ // (https://core.telegram.org/bots/payments/currencies.json),
+ // it shows the number of digits past the decimal point
+ // for each currency (2 for the majority of currencies).
+ TotalAmount int `json:"total_amount"`
+}
+
+// ShippingAddress represents a shipping address.
+type ShippingAddress struct {
+ // CountryCode ISO 3166-1 alpha-2 country code
+ CountryCode string `json:"country_code"`
+ // State if applicable
+ State string `json:"state"`
+ // City city
+ City string `json:"city"`
+ // StreetLine1 first line for the address
+ StreetLine1 string `json:"street_line1"`
+ // StreetLine2 second line for the address
+ StreetLine2 string `json:"street_line2"`
+ // PostCode address post code
+ PostCode string `json:"post_code"`
+}
+
+// OrderInfo represents information about an order.
+type OrderInfo struct {
+ // Name user name
+ //
+ // optional
+ Name string `json:"name,omitempty"`
+ // PhoneNumber user's phone number
+ //
+ // optional
+ PhoneNumber string `json:"phone_number,omitempty"`
+ // Email user email
+ //
+ // optional
+ Email string `json:"email,omitempty"`
+ // ShippingAddress user shipping address
+ //
+ // optional
+ ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
+}
+
+// ShippingOption represents one shipping option.
+type ShippingOption struct {
+ // ID shipping option identifier
+ ID string `json:"id"`
+ // Title option title
+ Title string `json:"title"`
+ // Prices list of price portions
+ Prices []LabeledPrice `json:"prices"`
+}
+
+// SuccessfulPayment contains basic information about a successful payment.
+type SuccessfulPayment struct {
+ // Currency three-letter ISO 4217 currency code
+ // (see https://core.telegram.org/bots/payments#supported-currencies)
+ Currency string `json:"currency"`
+ // TotalAmount total price in the smallest units of the currency (integer, not float/double).
+ // For example, for a price of US$ 1.45 pass amount = 145.
+ // See the exp parameter in currencies.json,
+ // (https://core.telegram.org/bots/payments/currencies.json)
+ // it shows the number of digits past the decimal point
+ // for each currency (2 for the majority of currencies).
+ TotalAmount int `json:"total_amount"`
+ // InvoicePayload bot specified invoice payload
+ InvoicePayload string `json:"invoice_payload"`
+ // ShippingOptionID identifier of the shipping option chosen by the user
+ //
+ // optional
+ ShippingOptionID string `json:"shipping_option_id,omitempty"`
+ // OrderInfo order info provided by the user
+ //
+ // optional
+ OrderInfo *OrderInfo `json:"order_info,omitempty"`
+ // TelegramPaymentChargeID telegram payment identifier
+ TelegramPaymentChargeID string `json:"telegram_payment_charge_id"`
+ // ProviderPaymentChargeID provider payment identifier
+ ProviderPaymentChargeID string `json:"provider_payment_charge_id"`
+}
+
+// ShippingQuery contains information about an incoming shipping query.
+type ShippingQuery struct {
+ // ID unique query identifier
+ ID string `json:"id"`
+ // From user who sent the query
+ From *User `json:"from"`
+ // InvoicePayload bot specified invoice payload
+ InvoicePayload string `json:"invoice_payload"`
+ // ShippingAddress user specified shipping address
+ ShippingAddress *ShippingAddress `json:"shipping_address"`
+}
+
+// PreCheckoutQuery contains information about an incoming pre-checkout query.
+type PreCheckoutQuery struct {
+ // ID unique query identifier
+ ID string `json:"id"`
+ // From user who sent the query
+ From *User `json:"from"`
+ // Currency three-letter ISO 4217 currency code
+ // // (see https://core.telegram.org/bots/payments#supported-currencies)
+ Currency string `json:"currency"`
+ // TotalAmount total price in the smallest units of the currency (integer, not float/double).
+ // // For example, for a price of US$ 1.45 pass amount = 145.
+ // // See the exp parameter in currencies.json,
+ // // (https://core.telegram.org/bots/payments/currencies.json)
+ // // it shows the number of digits past the decimal point
+ // // for each currency (2 for the majority of currencies).
+ TotalAmount int `json:"total_amount"`
+ // InvoicePayload bot specified invoice payload
+ InvoicePayload string `json:"invoice_payload"`
+ // ShippingOptionID identifier of the shipping option chosen by the user
+ //
+ // optional
+ ShippingOptionID string `json:"shipping_option_id,omitempty"`
+ // OrderInfo order info provided by the user
+ //
+ // optional
+ OrderInfo *OrderInfo `json:"order_info,omitempty"`
+}