Merge master into develop.
commit
6a6de7e674
10
README.md
10
README.md
|
@ -91,6 +91,16 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
info, err := bot.GetWebhookInfo()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if info.LastErrorDate != 0 {
|
||||
log.Printf("failed to set webhook: %s", info.LastErrorMessage)
|
||||
}
|
||||
|
||||
updates := bot.ListenForWebhook("/" + bot.Token)
|
||||
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
|
||||
|
||||
|
|
87
bot.go
87
bot.go
|
@ -7,6 +7,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
@ -71,28 +72,56 @@ func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse,
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bytes, err := ioutil.ReadAll(resp.Body)
|
||||
var apiResp APIResponse
|
||||
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
||||
if err != nil {
|
||||
return APIResponse{}, err
|
||||
return apiResp, err
|
||||
}
|
||||
|
||||
if bot.Debug {
|
||||
log.Printf("Endpoint: %s, response: %s\n", endpoint, string(bytes))
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(bytes, &apiResp)
|
||||
if err != nil {
|
||||
return APIResponse{}, err
|
||||
if !apiResp.Ok {
|
||||
var parameters ResponseParameters
|
||||
|
||||
if apiResp.Parameters != nil {
|
||||
parameters = *apiResp.Parameters
|
||||
}
|
||||
|
||||
if !apiResp.Ok {
|
||||
return apiResp, errors.New(apiResp.Description)
|
||||
return apiResp, Error{
|
||||
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
|
||||
}
|
||||
|
||||
// UploadFile makes a request to the API with a file.
|
||||
//
|
||||
// Requires the parameter to hold the file not be in the params.
|
||||
|
@ -543,3 +572,45 @@ func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error)
|
|||
|
||||
return stickers, err
|
||||
}
|
||||
|
||||
// SetChatTitle change title of chat.
|
||||
func (bot *BotAPI) SetChatTitle(config SetChatTitleConfig) (APIResponse, error) {
|
||||
v, err := config.values()
|
||||
if err != nil {
|
||||
return APIResponse{}, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return bot.MakeRequest(config.method(), v)
|
||||
}
|
||||
|
|
32
bot_test.go
32
bot_test.go
|
@ -476,6 +476,16 @@ func TestSetWebhookWithCert(t *testing.T) {
|
|||
t.Fail()
|
||||
}
|
||||
|
||||
info, err := bot.GetWebhookInfo()
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if info.LastErrorDate != 0 {
|
||||
t.Errorf("failed to set webhook: %s", info.LastErrorMessage)
|
||||
}
|
||||
|
||||
bot.Request(tgbotapi.RemoveWebhookConfig{})
|
||||
}
|
||||
|
||||
|
@ -493,6 +503,16 @@ func TestSetWebhookWithoutCert(t *testing.T) {
|
|||
t.Fail()
|
||||
}
|
||||
|
||||
info, err := bot.GetWebhookInfo()
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if info.LastErrorDate != 0 {
|
||||
t.Errorf("failed to set webhook: %s", info.LastErrorMessage)
|
||||
}
|
||||
|
||||
bot.Request(tgbotapi.RemoveWebhookConfig{})
|
||||
}
|
||||
|
||||
|
@ -558,6 +578,16 @@ func ExampleNewWebhook() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
info, err := bot.GetWebhookInfo()
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if info.LastErrorDate != 0 {
|
||||
log.Printf("failed to set webhook: %s", info.LastErrorMessage)
|
||||
}
|
||||
|
||||
updates := bot.ListenForWebhook("/" + bot.Token)
|
||||
go http.ListenAndServeTLS("0.0.0.0:8443", "cert.pem", "key.pem", nil)
|
||||
|
||||
|
@ -566,7 +596,7 @@ func ExampleNewWebhook() {
|
|||
}
|
||||
}
|
||||
|
||||
func ExampleAnswerInlineQuery() {
|
||||
func ExampleInlineConfig() {
|
||||
bot, err := tgbotapi.NewBotAPI("MyAwesomeBotToken") // create new bot
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
|
|
37
configs.go
37
configs.go
|
@ -720,7 +720,7 @@ type SetGameScoreConfig struct {
|
|||
Score int
|
||||
Force bool
|
||||
DisableEditMessage bool
|
||||
ChatID int
|
||||
ChatID int64
|
||||
ChannelUsername string
|
||||
MessageID int
|
||||
InlineMessageID string
|
||||
|
@ -733,7 +733,7 @@ func (config SetGameScoreConfig) values() (url.Values, error) {
|
|||
v.Add("score", strconv.Itoa(config.Score))
|
||||
if config.InlineMessageID == "" {
|
||||
if config.ChannelUsername == "" {
|
||||
v.Add("chat_id", strconv.Itoa(config.ChatID))
|
||||
v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
|
||||
} else {
|
||||
v.Add("chat_id", config.ChannelUsername)
|
||||
}
|
||||
|
@ -1376,10 +1376,7 @@ func (config UnpinChatMessageConfig) values() (url.Values, error) {
|
|||
|
||||
// SetChatPhotoConfig allows you to set a group, supergroup, or channel's photo.
|
||||
type SetChatPhotoConfig struct {
|
||||
ChatID int64
|
||||
ChannelUsername string
|
||||
|
||||
Photo interface{}
|
||||
BaseFile
|
||||
}
|
||||
|
||||
func (config SetChatPhotoConfig) method() string {
|
||||
|
@ -1390,36 +1387,12 @@ func (config SetChatPhotoConfig) name() string {
|
|||
return "photo"
|
||||
}
|
||||
|
||||
func (config SetChatPhotoConfig) values() (url.Values, error) {
|
||||
v := url.Values{}
|
||||
|
||||
if config.ChannelUsername == "" {
|
||||
v.Add("chat_id", strconv.FormatInt(config.ChatID, 10))
|
||||
} else {
|
||||
v.Add("chat_id", config.ChannelUsername)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (config SetChatPhotoConfig) params() map[string]string {
|
||||
params := make(map[string]string)
|
||||
|
||||
if config.ChannelUsername == "" {
|
||||
params["chat_id"] = strconv.FormatInt(config.ChatID, 10)
|
||||
} else {
|
||||
params["chat_id"] = config.ChannelUsername
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
func (config SetChatPhotoConfig) getFile() interface{} {
|
||||
return config.Photo
|
||||
return config.File
|
||||
}
|
||||
|
||||
func (config SetChatPhotoConfig) useExistingFile() bool {
|
||||
return false
|
||||
return config.UseExisting
|
||||
}
|
||||
|
||||
// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
|
||||
|
|
33
helpers.go
33
helpers.go
|
@ -641,7 +641,7 @@ func NewCallbackWithAlert(id, text string) CallbackConfig {
|
|||
}
|
||||
}
|
||||
|
||||
// NewInvoice created a new Invoice request to the user.
|
||||
// NewInvoice creates a new Invoice request to the user.
|
||||
func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices *[]LabeledPrice) InvoiceConfig {
|
||||
return InvoiceConfig{
|
||||
BaseChat: BaseChat{ChatID: chatID},
|
||||
|
@ -653,3 +653,34 @@ func NewInvoice(chatID int64, title, description, payload, providerToken, startP
|
|||
Currency: currency,
|
||||
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 {
|
||||
return SetChatPhotoConfig{
|
||||
BaseFile: BaseFile{
|
||||
BaseChat: BaseChat{ChatID: chatID},
|
||||
File: file,
|
||||
UseExisting: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewSetChatPhotoShare shares an existing photo.
|
||||
// You may use this to reshare an existing photo without reuploading it.
|
||||
//
|
||||
// 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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
13
types.go
13
types.go
|
@ -676,7 +676,7 @@ type InlineQueryResultGame struct {
|
|||
Type string `json:"type"`
|
||||
ID string `json:"id"`
|
||||
GameShortName string `json:"game_short_name"`
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup"`
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// ChosenInlineResult is an inline query result chosen by a User
|
||||
|
@ -819,3 +819,14 @@ type InputMediaVideo struct {
|
|||
Height int `json:"height,omitempty"`
|
||||
Duration int `json:"duration,omitempty"`
|
||||
}
|
||||
|
||||
// Error is an error containing extra information returned by the Telegram API.
|
||||
type Error struct {
|
||||
Message string
|
||||
ResponseParameters
|
||||
}
|
||||
|
||||
// Error message string.
|
||||
func (e Error) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue