github.com/alexis81/domosgo@v0.0.0-20191016125037-5aee90a434af/Domos/src/gopkg.in/telegram-bot-api.v4/bot.go (about)

     1  // Package tgbotapi has functions and types used for interacting with
     2  // the Telegram Bot API.
     3  package tgbotapi
     4  
     5  import (
     6  	"bytes"
     7  	"encoding/json"
     8  	"errors"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"log"
    13  	"net/http"
    14  	"net/url"
    15  	"os"
    16  	"strconv"
    17  	"strings"
    18  	"time"
    19  
    20  	"github.com/technoweenie/multipartstreamer"
    21  )
    22  
    23  // BotAPI allows you to interact with the Telegram Bot API.
    24  type BotAPI struct {
    25  	Token  string `json:"token"`
    26  	Debug  bool   `json:"debug"`
    27  	Buffer int    `json:"buffer"`
    28  
    29  	Self   User         `json:"-"`
    30  	Client *http.Client `json:"-"`
    31  }
    32  
    33  // NewBotAPI creates a new BotAPI instance.
    34  //
    35  // It requires a token, provided by @BotFather on Telegram.
    36  func NewBotAPI(token string) (*BotAPI, error) {
    37  	return NewBotAPIWithClient(token, &http.Client{})
    38  }
    39  
    40  // NewBotAPIWithClient creates a new BotAPI instance
    41  // and allows you to pass a http.Client.
    42  //
    43  // It requires a token, provided by @BotFather on Telegram.
    44  func NewBotAPIWithClient(token string, client *http.Client) (*BotAPI, error) {
    45  	bot := &BotAPI{
    46  		Token:  token,
    47  		Client: client,
    48  		Buffer: 100,
    49  	}
    50  
    51  	self, err := bot.GetMe()
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	bot.Self = self
    57  
    58  	return bot, nil
    59  }
    60  
    61  // MakeRequest makes a request to a specific endpoint with our token.
    62  func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, error) {
    63  	method := fmt.Sprintf(APIEndpoint, bot.Token, endpoint)
    64  
    65  	resp, err := bot.Client.PostForm(method, params)
    66  	if err != nil {
    67  		return APIResponse{}, err
    68  	}
    69  	defer resp.Body.Close()
    70  
    71  	var apiResp APIResponse
    72  	bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
    73  	if err != nil {
    74  		return apiResp, err
    75  	}
    76  
    77  	if bot.Debug {
    78  		log.Printf("%s resp: %s", endpoint, bytes)
    79  	}
    80  
    81  	if !apiResp.Ok {
    82  		parameters := ResponseParameters{}
    83  		if apiResp.Parameters != nil {
    84  			parameters = *apiResp.Parameters
    85  		}
    86  		return apiResp, Error{apiResp.Description, parameters}
    87  	}
    88  
    89  	return apiResp, nil
    90  }
    91  
    92  // decodeAPIResponse decode response and return slice of bytes if debug enabled.
    93  // If debug disabled, just decode http.Response.Body stream to APIResponse struct
    94  // for efficient memory usage
    95  func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse) (_ []byte, err error) {
    96  	if !bot.Debug {
    97  		dec := json.NewDecoder(responseBody)
    98  		err = dec.Decode(resp)
    99  		return
   100  	}
   101  
   102  	// if debug, read reponse body
   103  	data, err := ioutil.ReadAll(responseBody)
   104  	if err != nil {
   105  		return
   106  	}
   107  
   108  	err = json.Unmarshal(data, resp)
   109  	if err != nil {
   110  		return
   111  	}
   112  
   113  	return data, nil
   114  }
   115  
   116  // makeMessageRequest makes a request to a method that returns a Message.
   117  func (bot *BotAPI) makeMessageRequest(endpoint string, params url.Values) (Message, error) {
   118  	resp, err := bot.MakeRequest(endpoint, params)
   119  	if err != nil {
   120  		return Message{}, err
   121  	}
   122  
   123  	var message Message
   124  	json.Unmarshal(resp.Result, &message)
   125  
   126  	bot.debugLog(endpoint, params, message)
   127  
   128  	return message, nil
   129  }
   130  
   131  // UploadFile makes a request to the API with a file.
   132  //
   133  // Requires the parameter to hold the file not be in the params.
   134  // File should be a string to a file path, a FileBytes struct,
   135  // a FileReader struct, or a url.URL.
   136  //
   137  // Note that if your FileReader has a size set to -1, it will read
   138  // the file into memory to calculate a size.
   139  func (bot *BotAPI) UploadFile(endpoint string, params map[string]string, fieldname string, file interface{}) (APIResponse, error) {
   140  	ms := multipartstreamer.New()
   141  
   142  	switch f := file.(type) {
   143  	case string:
   144  		ms.WriteFields(params)
   145  
   146  		fileHandle, err := os.Open(f)
   147  		if err != nil {
   148  			return APIResponse{}, err
   149  		}
   150  		defer fileHandle.Close()
   151  
   152  		fi, err := os.Stat(f)
   153  		if err != nil {
   154  			return APIResponse{}, err
   155  		}
   156  
   157  		ms.WriteReader(fieldname, fileHandle.Name(), fi.Size(), fileHandle)
   158  	case FileBytes:
   159  		ms.WriteFields(params)
   160  
   161  		buf := bytes.NewBuffer(f.Bytes)
   162  		ms.WriteReader(fieldname, f.Name, int64(len(f.Bytes)), buf)
   163  	case FileReader:
   164  		ms.WriteFields(params)
   165  
   166  		if f.Size != -1 {
   167  			ms.WriteReader(fieldname, f.Name, f.Size, f.Reader)
   168  
   169  			break
   170  		}
   171  
   172  		data, err := ioutil.ReadAll(f.Reader)
   173  		if err != nil {
   174  			return APIResponse{}, err
   175  		}
   176  
   177  		buf := bytes.NewBuffer(data)
   178  
   179  		ms.WriteReader(fieldname, f.Name, int64(len(data)), buf)
   180  	case url.URL:
   181  		params[fieldname] = f.String()
   182  
   183  		ms.WriteFields(params)
   184  	default:
   185  		return APIResponse{}, errors.New(ErrBadFileType)
   186  	}
   187  
   188  	method := fmt.Sprintf(APIEndpoint, bot.Token, endpoint)
   189  
   190  	req, err := http.NewRequest("POST", method, nil)
   191  	if err != nil {
   192  		return APIResponse{}, err
   193  	}
   194  
   195  	ms.SetupRequest(req)
   196  
   197  	res, err := bot.Client.Do(req)
   198  	if err != nil {
   199  		return APIResponse{}, err
   200  	}
   201  	defer res.Body.Close()
   202  
   203  	bytes, err := ioutil.ReadAll(res.Body)
   204  	if err != nil {
   205  		return APIResponse{}, err
   206  	}
   207  
   208  	if bot.Debug {
   209  		log.Println(string(bytes))
   210  	}
   211  
   212  	var apiResp APIResponse
   213  
   214  	err = json.Unmarshal(bytes, &apiResp)
   215  	if err != nil {
   216  		return APIResponse{}, err
   217  	}
   218  
   219  	if !apiResp.Ok {
   220  		return APIResponse{}, errors.New(apiResp.Description)
   221  	}
   222  
   223  	return apiResp, nil
   224  }
   225  
   226  // GetFileDirectURL returns direct URL to file
   227  //
   228  // It requires the FileID.
   229  func (bot *BotAPI) GetFileDirectURL(fileID string) (string, error) {
   230  	file, err := bot.GetFile(FileConfig{fileID})
   231  
   232  	if err != nil {
   233  		return "", err
   234  	}
   235  
   236  	return file.Link(bot.Token), nil
   237  }
   238  
   239  // GetMe fetches the currently authenticated bot.
   240  //
   241  // This method is called upon creation to validate the token,
   242  // and so you may get this data from BotAPI.Self without the need for
   243  // another request.
   244  func (bot *BotAPI) GetMe() (User, error) {
   245  	resp, err := bot.MakeRequest("getMe", nil)
   246  	if err != nil {
   247  		return User{}, err
   248  	}
   249  
   250  	var user User
   251  	json.Unmarshal(resp.Result, &user)
   252  
   253  	bot.debugLog("getMe", nil, user)
   254  
   255  	return user, nil
   256  }
   257  
   258  // IsMessageToMe returns true if message directed to this bot.
   259  //
   260  // It requires the Message.
   261  func (bot *BotAPI) IsMessageToMe(message Message) bool {
   262  	return strings.Contains(message.Text, "@"+bot.Self.UserName)
   263  }
   264  
   265  // Send will send a Chattable item to Telegram.
   266  //
   267  // It requires the Chattable to send.
   268  func (bot *BotAPI) Send(c Chattable) (Message, error) {
   269  	switch c.(type) {
   270  	case Fileable:
   271  		return bot.sendFile(c.(Fileable))
   272  	default:
   273  		return bot.sendChattable(c)
   274  	}
   275  }
   276  
   277  // debugLog checks if the bot is currently running in debug mode, and if
   278  // so will display information about the request and response in the
   279  // debug log.
   280  func (bot *BotAPI) debugLog(context string, v url.Values, message interface{}) {
   281  	if bot.Debug {
   282  		log.Printf("%s req : %+v\n", context, v)
   283  		log.Printf("%s resp: %+v\n", context, message)
   284  	}
   285  }
   286  
   287  // sendExisting will send a Message with an existing file to Telegram.
   288  func (bot *BotAPI) sendExisting(method string, config Fileable) (Message, error) {
   289  	v, err := config.values()
   290  
   291  	if err != nil {
   292  		return Message{}, err
   293  	}
   294  
   295  	message, err := bot.makeMessageRequest(method, v)
   296  	if err != nil {
   297  		return Message{}, err
   298  	}
   299  
   300  	return message, nil
   301  }
   302  
   303  // uploadAndSend will send a Message with a new file to Telegram.
   304  func (bot *BotAPI) uploadAndSend(method string, config Fileable) (Message, error) {
   305  	params, err := config.params()
   306  	if err != nil {
   307  		return Message{}, err
   308  	}
   309  
   310  	file := config.getFile()
   311  
   312  	resp, err := bot.UploadFile(method, params, config.name(), file)
   313  	if err != nil {
   314  		return Message{}, err
   315  	}
   316  
   317  	var message Message
   318  	json.Unmarshal(resp.Result, &message)
   319  
   320  	bot.debugLog(method, nil, message)
   321  
   322  	return message, nil
   323  }
   324  
   325  // sendFile determines if the file is using an existing file or uploading
   326  // a new file, then sends it as needed.
   327  func (bot *BotAPI) sendFile(config Fileable) (Message, error) {
   328  	if config.useExistingFile() {
   329  		return bot.sendExisting(config.method(), config)
   330  	}
   331  
   332  	return bot.uploadAndSend(config.method(), config)
   333  }
   334  
   335  // sendChattable sends a Chattable.
   336  func (bot *BotAPI) sendChattable(config Chattable) (Message, error) {
   337  	v, err := config.values()
   338  	if err != nil {
   339  		return Message{}, err
   340  	}
   341  
   342  	message, err := bot.makeMessageRequest(config.method(), v)
   343  
   344  	if err != nil {
   345  		return Message{}, err
   346  	}
   347  
   348  	return message, nil
   349  }
   350  
   351  // GetUserProfilePhotos gets a user's profile photos.
   352  //
   353  // It requires UserID.
   354  // Offset and Limit are optional.
   355  func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
   356  	v := url.Values{}
   357  	v.Add("user_id", strconv.Itoa(config.UserID))
   358  	if config.Offset != 0 {
   359  		v.Add("offset", strconv.Itoa(config.Offset))
   360  	}
   361  	if config.Limit != 0 {
   362  		v.Add("limit", strconv.Itoa(config.Limit))
   363  	}
   364  
   365  	resp, err := bot.MakeRequest("getUserProfilePhotos", v)
   366  	if err != nil {
   367  		return UserProfilePhotos{}, err
   368  	}
   369  
   370  	var profilePhotos UserProfilePhotos
   371  	json.Unmarshal(resp.Result, &profilePhotos)
   372  
   373  	bot.debugLog("GetUserProfilePhoto", v, profilePhotos)
   374  
   375  	return profilePhotos, nil
   376  }
   377  
   378  // GetFile returns a File which can download a file from Telegram.
   379  //
   380  // Requires FileID.
   381  func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
   382  	v := url.Values{}
   383  	v.Add("file_id", config.FileID)
   384  
   385  	resp, err := bot.MakeRequest("getFile", v)
   386  	if err != nil {
   387  		return File{}, err
   388  	}
   389  
   390  	var file File
   391  	json.Unmarshal(resp.Result, &file)
   392  
   393  	bot.debugLog("GetFile", v, file)
   394  
   395  	return file, nil
   396  }
   397  
   398  // GetUpdates fetches updates.
   399  // If a WebHook is set, this will not return any data!
   400  //
   401  // Offset, Limit, and Timeout are optional.
   402  // To avoid stale items, set Offset to one higher than the previous item.
   403  // Set Timeout to a large number to reduce requests so you can get updates
   404  // instantly instead of having to wait between requests.
   405  func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
   406  	v := url.Values{}
   407  	if config.Offset != 0 {
   408  		v.Add("offset", strconv.Itoa(config.Offset))
   409  	}
   410  	if config.Limit > 0 {
   411  		v.Add("limit", strconv.Itoa(config.Limit))
   412  	}
   413  	if config.Timeout > 0 {
   414  		v.Add("timeout", strconv.Itoa(config.Timeout))
   415  	}
   416  
   417  	resp, err := bot.MakeRequest("getUpdates", v)
   418  	if err != nil {
   419  		return []Update{}, err
   420  	}
   421  
   422  	var updates []Update
   423  	json.Unmarshal(resp.Result, &updates)
   424  
   425  	bot.debugLog("getUpdates", v, updates)
   426  
   427  	return updates, nil
   428  }
   429  
   430  // RemoveWebhook unsets the webhook.
   431  func (bot *BotAPI) RemoveWebhook() (APIResponse, error) {
   432  	return bot.MakeRequest("setWebhook", url.Values{})
   433  }
   434  
   435  // SetWebhook sets a webhook.
   436  //
   437  // If this is set, GetUpdates will not get any data!
   438  //
   439  // If you do not have a legitimate TLS certificate, you need to include
   440  // your self signed certificate with the config.
   441  func (bot *BotAPI) SetWebhook(config WebhookConfig) (APIResponse, error) {
   442  
   443  	if config.Certificate == nil {
   444  		v := url.Values{}
   445  		v.Add("url", config.URL.String())
   446  		if config.MaxConnections != 0 {
   447  			v.Add("max_connections", strconv.Itoa(config.MaxConnections))
   448  		}
   449  
   450  		return bot.MakeRequest("setWebhook", v)
   451  	}
   452  
   453  	params := make(map[string]string)
   454  	params["url"] = config.URL.String()
   455  	if config.MaxConnections != 0 {
   456  		params["max_connections"] = strconv.Itoa(config.MaxConnections)
   457  	}
   458  
   459  	resp, err := bot.UploadFile("setWebhook", params, "certificate", config.Certificate)
   460  	if err != nil {
   461  		return APIResponse{}, err
   462  	}
   463  
   464  	return resp, nil
   465  }
   466  
   467  // GetWebhookInfo allows you to fetch information about a webhook and if
   468  // one currently is set, along with pending update count and error messages.
   469  func (bot *BotAPI) GetWebhookInfo() (WebhookInfo, error) {
   470  	resp, err := bot.MakeRequest("getWebhookInfo", url.Values{})
   471  	if err != nil {
   472  		return WebhookInfo{}, err
   473  	}
   474  
   475  	var info WebhookInfo
   476  	err = json.Unmarshal(resp.Result, &info)
   477  
   478  	return info, err
   479  }
   480  
   481  // GetUpdatesChan starts and returns a channel for getting updates.
   482  func (bot *BotAPI) GetUpdatesChan(config UpdateConfig) (UpdatesChannel, error) {
   483  	ch := make(chan Update, bot.Buffer)
   484  
   485  	go func() {
   486  		for {
   487  			updates, err := bot.GetUpdates(config)
   488  			if err != nil {
   489  				log.Println(err)
   490  				log.Println("Failed to get updates, retrying in 3 seconds...")
   491  				time.Sleep(time.Second * 3)
   492  
   493  				continue
   494  			}
   495  
   496  			for _, update := range updates {
   497  				if update.UpdateID >= config.Offset {
   498  					config.Offset = update.UpdateID + 1
   499  					ch <- update
   500  				}
   501  			}
   502  		}
   503  	}()
   504  
   505  	return ch, nil
   506  }
   507  
   508  // ListenForWebhook registers a http handler for a webhook.
   509  func (bot *BotAPI) ListenForWebhook(pattern string) UpdatesChannel {
   510  	ch := make(chan Update, bot.Buffer)
   511  
   512  	http.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
   513  		bytes, _ := ioutil.ReadAll(r.Body)
   514  
   515  		var update Update
   516  		json.Unmarshal(bytes, &update)
   517  
   518  		ch <- update
   519  	})
   520  
   521  	return ch
   522  }
   523  
   524  // AnswerInlineQuery sends a response to an inline query.
   525  //
   526  // Note that you must respond to an inline query within 30 seconds.
   527  func (bot *BotAPI) AnswerInlineQuery(config InlineConfig) (APIResponse, error) {
   528  	v := url.Values{}
   529  
   530  	v.Add("inline_query_id", config.InlineQueryID)
   531  	v.Add("cache_time", strconv.Itoa(config.CacheTime))
   532  	v.Add("is_personal", strconv.FormatBool(config.IsPersonal))
   533  	v.Add("next_offset", config.NextOffset)
   534  	data, err := json.Marshal(config.Results)
   535  	if err != nil {
   536  		return APIResponse{}, err
   537  	}
   538  	v.Add("results", string(data))
   539  	v.Add("switch_pm_text", config.SwitchPMText)
   540  	v.Add("switch_pm_parameter", config.SwitchPMParameter)
   541  
   542  	bot.debugLog("answerInlineQuery", v, nil)
   543  
   544  	return bot.MakeRequest("answerInlineQuery", v)
   545  }
   546  
   547  // AnswerCallbackQuery sends a response to an inline query callback.
   548  func (bot *BotAPI) AnswerCallbackQuery(config CallbackConfig) (APIResponse, error) {
   549  	v := url.Values{}
   550  
   551  	v.Add("callback_query_id", config.CallbackQueryID)
   552  	if config.Text != "" {
   553  		v.Add("text", config.Text)
   554  	}
   555  	v.Add("show_alert", strconv.FormatBool(config.ShowAlert))
   556  	if config.URL != "" {
   557  		v.Add("url", config.URL)
   558  	}
   559  	v.Add("cache_time", strconv.Itoa(config.CacheTime))
   560  
   561  	bot.debugLog("answerCallbackQuery", v, nil)
   562  
   563  	return bot.MakeRequest("answerCallbackQuery", v)
   564  }
   565  
   566  // KickChatMember kicks a user from a chat. Note that this only will work
   567  // in supergroups, and requires the bot to be an admin. Also note they
   568  // will be unable to rejoin until they are unbanned.
   569  func (bot *BotAPI) KickChatMember(config KickChatMemberConfig) (APIResponse, error) {
   570  	v := url.Values{}
   571  
   572  	if config.SuperGroupUsername == "" {
   573  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   574  	} else {
   575  		v.Add("chat_id", config.SuperGroupUsername)
   576  	}
   577  	v.Add("user_id", strconv.Itoa(config.UserID))
   578  
   579  	if config.UntilDate != 0 {
   580  		v.Add("until_date", strconv.FormatInt(config.UntilDate, 10))
   581  	}
   582  
   583  	bot.debugLog("kickChatMember", v, nil)
   584  
   585  	return bot.MakeRequest("kickChatMember", v)
   586  }
   587  
   588  // LeaveChat makes the bot leave the chat.
   589  func (bot *BotAPI) LeaveChat(config ChatConfig) (APIResponse, error) {
   590  	v := url.Values{}
   591  
   592  	if config.SuperGroupUsername == "" {
   593  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   594  	} else {
   595  		v.Add("chat_id", config.SuperGroupUsername)
   596  	}
   597  
   598  	bot.debugLog("leaveChat", v, nil)
   599  
   600  	return bot.MakeRequest("leaveChat", v)
   601  }
   602  
   603  // GetChat gets information about a chat.
   604  func (bot *BotAPI) GetChat(config ChatConfig) (Chat, error) {
   605  	v := url.Values{}
   606  
   607  	if config.SuperGroupUsername == "" {
   608  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   609  	} else {
   610  		v.Add("chat_id", config.SuperGroupUsername)
   611  	}
   612  
   613  	resp, err := bot.MakeRequest("getChat", v)
   614  	if err != nil {
   615  		return Chat{}, err
   616  	}
   617  
   618  	var chat Chat
   619  	err = json.Unmarshal(resp.Result, &chat)
   620  
   621  	bot.debugLog("getChat", v, chat)
   622  
   623  	return chat, err
   624  }
   625  
   626  // GetChatAdministrators gets a list of administrators in the chat.
   627  //
   628  // If none have been appointed, only the creator will be returned.
   629  // Bots are not shown, even if they are an administrator.
   630  func (bot *BotAPI) GetChatAdministrators(config ChatConfig) ([]ChatMember, error) {
   631  	v := url.Values{}
   632  
   633  	if config.SuperGroupUsername == "" {
   634  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   635  	} else {
   636  		v.Add("chat_id", config.SuperGroupUsername)
   637  	}
   638  
   639  	resp, err := bot.MakeRequest("getChatAdministrators", v)
   640  	if err != nil {
   641  		return []ChatMember{}, err
   642  	}
   643  
   644  	var members []ChatMember
   645  	err = json.Unmarshal(resp.Result, &members)
   646  
   647  	bot.debugLog("getChatAdministrators", v, members)
   648  
   649  	return members, err
   650  }
   651  
   652  // GetChatMembersCount gets the number of users in a chat.
   653  func (bot *BotAPI) GetChatMembersCount(config ChatConfig) (int, error) {
   654  	v := url.Values{}
   655  
   656  	if config.SuperGroupUsername == "" {
   657  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   658  	} else {
   659  		v.Add("chat_id", config.SuperGroupUsername)
   660  	}
   661  
   662  	resp, err := bot.MakeRequest("getChatMembersCount", v)
   663  	if err != nil {
   664  		return -1, err
   665  	}
   666  
   667  	var count int
   668  	err = json.Unmarshal(resp.Result, &count)
   669  
   670  	bot.debugLog("getChatMembersCount", v, count)
   671  
   672  	return count, err
   673  }
   674  
   675  // GetChatMember gets a specific chat member.
   676  func (bot *BotAPI) GetChatMember(config ChatConfigWithUser) (ChatMember, error) {
   677  	v := url.Values{}
   678  
   679  	if config.SuperGroupUsername == "" {
   680  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   681  	} else {
   682  		v.Add("chat_id", config.SuperGroupUsername)
   683  	}
   684  	v.Add("user_id", strconv.Itoa(config.UserID))
   685  
   686  	resp, err := bot.MakeRequest("getChatMember", v)
   687  	if err != nil {
   688  		return ChatMember{}, err
   689  	}
   690  
   691  	var member ChatMember
   692  	err = json.Unmarshal(resp.Result, &member)
   693  
   694  	bot.debugLog("getChatMember", v, member)
   695  
   696  	return member, err
   697  }
   698  
   699  // UnbanChatMember unbans a user from a chat. Note that this only will work
   700  // in supergroups and channels, and requires the bot to be an admin.
   701  func (bot *BotAPI) UnbanChatMember(config ChatMemberConfig) (APIResponse, error) {
   702  	v := url.Values{}
   703  
   704  	if config.SuperGroupUsername != "" {
   705  		v.Add("chat_id", config.SuperGroupUsername)
   706  	} else if config.ChannelUsername != "" {
   707  		v.Add("chat_id", config.ChannelUsername)
   708  	} else {
   709  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   710  	}
   711  	v.Add("user_id", strconv.Itoa(config.UserID))
   712  
   713  	bot.debugLog("unbanChatMember", v, nil)
   714  
   715  	return bot.MakeRequest("unbanChatMember", v)
   716  }
   717  
   718  // RestrictChatMember to restrict a user in a supergroup. The bot must be an
   719  //administrator in the supergroup for this to work and must have the
   720  //appropriate admin rights. Pass True for all boolean parameters to lift
   721  //restrictions from a user. Returns True on success.
   722  func (bot *BotAPI) RestrictChatMember(config RestrictChatMemberConfig) (APIResponse, error) {
   723  	v := url.Values{}
   724  
   725  	if config.SuperGroupUsername != "" {
   726  		v.Add("chat_id", config.SuperGroupUsername)
   727  	} else if config.ChannelUsername != "" {
   728  		v.Add("chat_id", config.ChannelUsername)
   729  	} else {
   730  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   731  	}
   732  	v.Add("user_id", strconv.Itoa(config.UserID))
   733  
   734  	if config.CanSendMessages != nil {
   735  		v.Add("can_send_messages", strconv.FormatBool(*config.CanSendMessages))
   736  	}
   737  	if config.CanSendMediaMessages != nil {
   738  		v.Add("can_send_media_messages", strconv.FormatBool(*config.CanSendMediaMessages))
   739  	}
   740  	if config.CanSendOtherMessages != nil {
   741  		v.Add("can_send_other_messages", strconv.FormatBool(*config.CanSendOtherMessages))
   742  	}
   743  	if config.CanAddWebPagePreviews != nil {
   744  		v.Add("can_add_web_page_previews", strconv.FormatBool(*config.CanAddWebPagePreviews))
   745  	}
   746  	if config.UntilDate != 0 {
   747  		v.Add("until_date", strconv.FormatInt(config.UntilDate, 10))
   748  	}
   749  
   750  	bot.debugLog("restrictChatMember", v, nil)
   751  
   752  	return bot.MakeRequest("restrictChatMember", v)
   753  }
   754  
   755  // PromoteChatMember add admin rights to user
   756  func (bot *BotAPI) PromoteChatMember(config PromoteChatMemberConfig) (APIResponse, error) {
   757  	v := url.Values{}
   758  
   759  	if config.SuperGroupUsername != "" {
   760  		v.Add("chat_id", config.SuperGroupUsername)
   761  	} else if config.ChannelUsername != "" {
   762  		v.Add("chat_id", config.ChannelUsername)
   763  	} else {
   764  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   765  	}
   766  	v.Add("user_id", strconv.Itoa(config.UserID))
   767  
   768  	if config.CanChangeInfo != nil {
   769  		v.Add("can_change_info", strconv.FormatBool(*config.CanChangeInfo))
   770  	}
   771  	if config.CanPostMessages != nil {
   772  		v.Add("can_post_messages", strconv.FormatBool(*config.CanPostMessages))
   773  	}
   774  	if config.CanEditMessages != nil {
   775  		v.Add("can_edit_messages", strconv.FormatBool(*config.CanEditMessages))
   776  	}
   777  	if config.CanDeleteMessages != nil {
   778  		v.Add("can_delete_messages", strconv.FormatBool(*config.CanDeleteMessages))
   779  	}
   780  	if config.CanInviteUsers != nil {
   781  		v.Add("can_invite_users", strconv.FormatBool(*config.CanInviteUsers))
   782  	}
   783  	if config.CanRestrictMembers != nil {
   784  		v.Add("can_restrict_members", strconv.FormatBool(*config.CanRestrictMembers))
   785  	}
   786  	if config.CanPinMessages != nil {
   787  		v.Add("can_pin_messages", strconv.FormatBool(*config.CanPinMessages))
   788  	}
   789  	if config.CanPromoteMembers != nil {
   790  		v.Add("can_promote_members", strconv.FormatBool(*config.CanPromoteMembers))
   791  	}
   792  
   793  	bot.debugLog("promoteChatMember", v, nil)
   794  
   795  	return bot.MakeRequest("promoteChatMember", v)
   796  }
   797  
   798  // GetGameHighScores allows you to get the high scores for a game.
   799  func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) {
   800  	v, _ := config.values()
   801  
   802  	resp, err := bot.MakeRequest(config.method(), v)
   803  	if err != nil {
   804  		return []GameHighScore{}, err
   805  	}
   806  
   807  	var highScores []GameHighScore
   808  	err = json.Unmarshal(resp.Result, &highScores)
   809  
   810  	return highScores, err
   811  }
   812  
   813  // AnswerShippingQuery allows you to reply to Update with shipping_query parameter.
   814  func (bot *BotAPI) AnswerShippingQuery(config ShippingConfig) (APIResponse, error) {
   815  	v := url.Values{}
   816  
   817  	v.Add("shipping_query_id", config.ShippingQueryID)
   818  	v.Add("ok", strconv.FormatBool(config.OK))
   819  	if config.OK == true {
   820  		data, err := json.Marshal(config.ShippingOptions)
   821  		if err != nil {
   822  			return APIResponse{}, err
   823  		}
   824  		v.Add("shipping_options", string(data))
   825  	} else {
   826  		v.Add("error_message", config.ErrorMessage)
   827  	}
   828  
   829  	bot.debugLog("answerShippingQuery", v, nil)
   830  
   831  	return bot.MakeRequest("answerShippingQuery", v)
   832  }
   833  
   834  // AnswerPreCheckoutQuery allows you to reply to Update with pre_checkout_query.
   835  func (bot *BotAPI) AnswerPreCheckoutQuery(config PreCheckoutConfig) (APIResponse, error) {
   836  	v := url.Values{}
   837  
   838  	v.Add("pre_checkout_query_id", config.PreCheckoutQueryID)
   839  	v.Add("ok", strconv.FormatBool(config.OK))
   840  	if config.OK != true {
   841  		v.Add("error", config.ErrorMessage)
   842  	}
   843  
   844  	bot.debugLog("answerPreCheckoutQuery", v, nil)
   845  
   846  	return bot.MakeRequest("answerPreCheckoutQuery", v)
   847  }
   848  
   849  // DeleteMessage deletes a message in a chat
   850  func (bot *BotAPI) DeleteMessage(config DeleteMessageConfig) (APIResponse, error) {
   851  	v, err := config.values()
   852  	if err != nil {
   853  		return APIResponse{}, err
   854  	}
   855  
   856  	bot.debugLog(config.method(), v, nil)
   857  
   858  	return bot.MakeRequest(config.method(), v)
   859  }
   860  
   861  // GetInviteLink get InviteLink for a chat
   862  func (bot *BotAPI) GetInviteLink(config ChatConfig) (string, error) {
   863  	v := url.Values{}
   864  
   865  	if config.SuperGroupUsername == "" {
   866  		v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
   867  	} else {
   868  		v.Add("chat_id", config.SuperGroupUsername)
   869  	}
   870  
   871  	resp, err := bot.MakeRequest("exportChatInviteLink", v)
   872  	if err != nil {
   873  		return "", err
   874  	}
   875  
   876  	var inviteLink string
   877  	err = json.Unmarshal(resp.Result, &inviteLink)
   878  
   879  	return inviteLink, err
   880  }
   881  
   882  // PinChatMessage pin message in supergroup
   883  func (bot *BotAPI) PinChatMessage(config PinChatMessageConfig) (APIResponse, error) {
   884  	v, err := config.values()
   885  	if err != nil {
   886  		return APIResponse{}, err
   887  	}
   888  
   889  	bot.debugLog(config.method(), v, nil)
   890  
   891  	return bot.MakeRequest(config.method(), v)
   892  }
   893  
   894  // UnpinChatMessage unpin message in supergroup
   895  func (bot *BotAPI) UnpinChatMessage(config UnpinChatMessageConfig) (APIResponse, error) {
   896  	v, err := config.values()
   897  	if err != nil {
   898  		return APIResponse{}, err
   899  	}
   900  
   901  	bot.debugLog(config.method(), v, nil)
   902  
   903  	return bot.MakeRequest(config.method(), v)
   904  }
   905  
   906  // SetChatTitle change title of chat.
   907  func (bot *BotAPI) SetChatTitle(config SetChatTitleConfig) (APIResponse, error) {
   908  	v, err := config.values()
   909  	if err != nil {
   910  		return APIResponse{}, err
   911  	}
   912  
   913  	bot.debugLog(config.method(), v, nil)
   914  
   915  	return bot.MakeRequest(config.method(), v)
   916  }
   917  
   918  // SetChatDescription change description of chat.
   919  func (bot *BotAPI) SetChatDescription(config SetChatDescriptionConfig) (APIResponse, error) {
   920  	v, err := config.values()
   921  	if err != nil {
   922  		return APIResponse{}, err
   923  	}
   924  
   925  	bot.debugLog(config.method(), v, nil)
   926  
   927  	return bot.MakeRequest(config.method(), v)
   928  }
   929  
   930  // SetChatPhoto change photo of chat.
   931  func (bot *BotAPI) SetChatPhoto(config SetChatPhotoConfig) (APIResponse, error) {
   932  	params, err := config.params()
   933  	if err != nil {
   934  		return APIResponse{}, err
   935  	}
   936  
   937  	file := config.getFile()
   938  
   939  	return bot.UploadFile(config.method(), params, config.name(), file)
   940  }
   941  
   942  // DeleteChatPhoto delete photo of chat.
   943  func (bot *BotAPI) DeleteChatPhoto(config DeleteChatPhotoConfig) (APIResponse, error) {
   944  	v, err := config.values()
   945  	if err != nil {
   946  		return APIResponse{}, err
   947  	}
   948  
   949  	bot.debugLog(config.method(), v, nil)
   950  
   951  	return bot.MakeRequest(config.method(), v)
   952  }