Merge pull request #356 from go-telegram-bot-api/multiple-uploads
Add support for uploading multiple filesbot-api-6.1
commit
badaa4056a
224
bot.go
224
bot.go
|
@ -9,13 +9,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/technoweenie/multipartstreamer"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPClient is the type needed for the bot to perform HTTP requests.
|
// HTTPClient is the type needed for the bot to perform HTTP requests.
|
||||||
|
@ -96,7 +95,7 @@ func buildParams(in Params) (out url.Values) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeRequest makes a request to a specific endpoint with our token.
|
// MakeRequest makes a request to a specific endpoint with our token.
|
||||||
func (bot *BotAPI) MakeRequest(endpoint string, params Params) (APIResponse, error) {
|
func (bot *BotAPI) MakeRequest(endpoint string, params Params) (*APIResponse, error) {
|
||||||
if bot.Debug {
|
if bot.Debug {
|
||||||
log.Printf("Endpoint: %s, params: %v\n", endpoint, params)
|
log.Printf("Endpoint: %s, params: %v\n", endpoint, params)
|
||||||
}
|
}
|
||||||
|
@ -107,14 +106,14 @@ func (bot *BotAPI) MakeRequest(endpoint string, params Params) (APIResponse, err
|
||||||
|
|
||||||
resp, err := bot.Client.PostForm(method, values)
|
resp, err := bot.Client.PostForm(method, values)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apiResp, err
|
return &apiResp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if bot.Debug {
|
if bot.Debug {
|
||||||
|
@ -128,14 +127,14 @@ func (bot *BotAPI) MakeRequest(endpoint string, params Params) (APIResponse, err
|
||||||
parameters = *apiResp.Parameters
|
parameters = *apiResp.Parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiResp, Error{
|
return &apiResp, &Error{
|
||||||
Code: apiResp.ErrorCode,
|
Code: apiResp.ErrorCode,
|
||||||
Message: apiResp.Description,
|
Message: apiResp.Description,
|
||||||
ResponseParameters: parameters,
|
ResponseParameters: parameters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiResp, nil
|
return &apiResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// decodeAPIResponse decode response and return slice of bytes if debug enabled.
|
// decodeAPIResponse decode response and return slice of bytes if debug enabled.
|
||||||
|
@ -162,86 +161,100 @@ func (bot *BotAPI) decodeAPIResponse(responseBody io.Reader, resp *APIResponse)
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadFile makes a request to the API with a file.
|
// UploadFiles makes a request to the API with files.
|
||||||
//
|
func (bot *BotAPI) UploadFiles(endpoint string, params Params, files []RequestFile) (*APIResponse, error) {
|
||||||
// Requires the parameter to hold the file not be in the params.
|
r, w := io.Pipe()
|
||||||
// File should be a string to a file path, a FileBytes struct,
|
m := multipart.NewWriter(w)
|
||||||
// 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 Params, fieldname string, file interface{}) (APIResponse, error) {
|
|
||||||
ms := multipartstreamer.New()
|
|
||||||
|
|
||||||
switch f := file.(type) {
|
// 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 {
|
||||||
|
switch f := file.File.(type) {
|
||||||
case string:
|
case string:
|
||||||
ms.WriteFields(params)
|
|
||||||
|
|
||||||
fileHandle, err := os.Open(f)
|
fileHandle, err := os.Open(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer fileHandle.Close()
|
defer fileHandle.Close()
|
||||||
|
|
||||||
fi, err := os.Stat(f)
|
part, err := m.CreateFormFile(file.Name, fileHandle.Name())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.WriteReader(fieldname, fileHandle.Name(), fi.Size(), fileHandle)
|
io.Copy(part, fileHandle)
|
||||||
case FileBytes:
|
case FileBytes:
|
||||||
ms.WriteFields(params)
|
part, err := m.CreateFormFile(file.Name, f.Name)
|
||||||
|
if err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(f.Bytes)
|
buf := bytes.NewBuffer(f.Bytes)
|
||||||
ms.WriteReader(fieldname, f.Name, int64(len(f.Bytes)), buf)
|
io.Copy(part, buf)
|
||||||
case FileReader:
|
case FileReader:
|
||||||
ms.WriteFields(params)
|
part, err := m.CreateFormFile(file.Name, f.Name)
|
||||||
|
|
||||||
if f.Size != -1 {
|
|
||||||
ms.WriteReader(fieldname, f.Name, f.Size, f.Reader)
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(f.Reader)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(data)
|
io.Copy(part, f.Reader)
|
||||||
|
case FileURL:
|
||||||
ms.WriteReader(fieldname, f.Name, int64(len(data)), buf)
|
val := string(f)
|
||||||
case url.URL:
|
if err := m.WriteField(file.Name, val); err != nil {
|
||||||
params[fieldname] = f.String()
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
ms.WriteFields(params)
|
}
|
||||||
|
case FileID:
|
||||||
|
val := string(f)
|
||||||
|
if err := m.WriteField(file.Name, val); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return APIResponse{}, errors.New(ErrBadFileType)
|
w.CloseWithError(errors.New(ErrBadFileType))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if bot.Debug {
|
if bot.Debug {
|
||||||
log.Printf("Endpoint: %s, fieldname: %s, params: %v, file: %T\n", endpoint, fieldname, params, file)
|
log.Printf("Endpoint: %s, params: %v, with %d files\n", endpoint, params, len(files))
|
||||||
}
|
}
|
||||||
|
|
||||||
method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
|
method := fmt.Sprintf(bot.apiEndpoint, bot.Token, endpoint)
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", method, nil)
|
req, err := http.NewRequest("POST", method, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ms.SetupRequest(req)
|
req.Header.Set("Content-Type", m.FormDataContentType())
|
||||||
|
|
||||||
resp, err := bot.Client.Do(req)
|
resp, err := bot.Client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
bytes, err := bot.decodeAPIResponse(resp.Body, &apiResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apiResp, err
|
return &apiResp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if bot.Debug {
|
if bot.Debug {
|
||||||
|
@ -255,13 +268,13 @@ func (bot *BotAPI) UploadFile(endpoint string, params Params, fieldname string,
|
||||||
parameters = *apiResp.Parameters
|
parameters = *apiResp.Parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiResp, Error{
|
return &apiResp, &Error{
|
||||||
Message: apiResp.Description,
|
Message: apiResp.Description,
|
||||||
ResponseParameters: parameters,
|
ResponseParameters: parameters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiResp, nil
|
return &apiResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFileDirectURL returns direct URL to file
|
// GetFileDirectURL returns direct URL to file
|
||||||
|
@ -301,23 +314,54 @@ func (bot *BotAPI) IsMessageToMe(message Message) bool {
|
||||||
return strings.Contains(message.Text, "@"+bot.Self.UserName)
|
return strings.Contains(message.Text, "@"+bot.Self.UserName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasFilesNeedingUpload(files []RequestFile) bool {
|
||||||
|
for _, file := range files {
|
||||||
|
switch file.File.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Request sends a Chattable to Telegram, and returns the APIResponse.
|
// Request sends a Chattable to Telegram, and returns the APIResponse.
|
||||||
func (bot *BotAPI) Request(c Chattable) (APIResponse, error) {
|
func (bot *BotAPI) Request(c Chattable) (*APIResponse, error) {
|
||||||
params, err := c.params()
|
params, err := c.params()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return APIResponse{}, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t := c.(type) {
|
if t, ok := c.(Fileable); ok {
|
||||||
case Fileable:
|
files := t.files()
|
||||||
if t.useExistingFile() {
|
|
||||||
return bot.MakeRequest(t.method(), params)
|
// 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bot.UploadFile(t.method(), params, t.name(), t.getFile())
|
// 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 {
|
||||||
|
var s string
|
||||||
|
|
||||||
|
switch f := file.File.(type) {
|
||||||
|
case string:
|
||||||
|
s = f
|
||||||
|
case FileID:
|
||||||
|
s = string(f)
|
||||||
|
case FileURL:
|
||||||
|
s = string(f)
|
||||||
default:
|
default:
|
||||||
return bot.MakeRequest(c.method(), params)
|
return nil, errors.New(ErrBadFileType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
params[file.Name] = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bot.MakeRequest(c.method(), params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send will send a Chattable item to Telegram and provides the
|
// Send will send a Chattable item to Telegram and provides the
|
||||||
|
@ -336,9 +380,7 @@ func (bot *BotAPI) Send(c Chattable) (Message, error) {
|
||||||
|
|
||||||
// SendMediaGroup sends a media group and returns the resulting messages.
|
// SendMediaGroup sends a media group and returns the resulting messages.
|
||||||
func (bot *BotAPI) SendMediaGroup(config MediaGroupConfig) ([]Message, error) {
|
func (bot *BotAPI) SendMediaGroup(config MediaGroupConfig) ([]Message, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -354,9 +396,7 @@ func (bot *BotAPI) SendMediaGroup(config MediaGroupConfig) ([]Message, error) {
|
||||||
// It requires UserID.
|
// It requires UserID.
|
||||||
// Offset and Limit are optional.
|
// Offset and Limit are optional.
|
||||||
func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
|
func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserProfilePhotos, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return UserProfilePhotos{}, err
|
return UserProfilePhotos{}, err
|
||||||
}
|
}
|
||||||
|
@ -371,9 +411,7 @@ func (bot *BotAPI) GetUserProfilePhotos(config UserProfilePhotosConfig) (UserPro
|
||||||
//
|
//
|
||||||
// Requires FileID.
|
// Requires FileID.
|
||||||
func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
|
func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return File{}, err
|
return File{}, err
|
||||||
}
|
}
|
||||||
|
@ -392,9 +430,7 @@ func (bot *BotAPI) GetFile(config FileConfig) (File, error) {
|
||||||
// Set Timeout to a large number to reduce requests so you can get updates
|
// Set Timeout to a large number to reduce requests so you can get updates
|
||||||
// instantly instead of having to wait between requests.
|
// instantly instead of having to wait between requests.
|
||||||
func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
|
func (bot *BotAPI) GetUpdates(config UpdateConfig) ([]Update, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []Update{}, err
|
return []Update{}, err
|
||||||
}
|
}
|
||||||
|
@ -510,7 +546,7 @@ func WriteToHTTPResponse(w http.ResponseWriter, c Chattable) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if t, ok := c.(Fileable); ok {
|
if t, ok := c.(Fileable); ok {
|
||||||
if !t.useExistingFile() {
|
if hasFilesNeedingUpload(t.files()) {
|
||||||
return errors.New("unable to use http response to upload files")
|
return errors.New("unable to use http response to upload files")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,9 +561,7 @@ func WriteToHTTPResponse(w http.ResponseWriter, c Chattable) error {
|
||||||
|
|
||||||
// GetChat gets information about a chat.
|
// GetChat gets information about a chat.
|
||||||
func (bot *BotAPI) GetChat(config ChatInfoConfig) (Chat, error) {
|
func (bot *BotAPI) GetChat(config ChatInfoConfig) (Chat, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Chat{}, err
|
return Chat{}, err
|
||||||
}
|
}
|
||||||
|
@ -543,9 +577,7 @@ func (bot *BotAPI) GetChat(config ChatInfoConfig) (Chat, error) {
|
||||||
// If none have been appointed, only the creator will be returned.
|
// If none have been appointed, only the creator will be returned.
|
||||||
// Bots are not shown, even if they are an administrator.
|
// Bots are not shown, even if they are an administrator.
|
||||||
func (bot *BotAPI) GetChatAdministrators(config ChatAdministratorsConfig) ([]ChatMember, error) {
|
func (bot *BotAPI) GetChatAdministrators(config ChatAdministratorsConfig) ([]ChatMember, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []ChatMember{}, err
|
return []ChatMember{}, err
|
||||||
}
|
}
|
||||||
|
@ -558,9 +590,7 @@ func (bot *BotAPI) GetChatAdministrators(config ChatAdministratorsConfig) ([]Cha
|
||||||
|
|
||||||
// GetChatMembersCount gets the number of users in a chat.
|
// GetChatMembersCount gets the number of users in a chat.
|
||||||
func (bot *BotAPI) GetChatMembersCount(config ChatMemberCountConfig) (int, error) {
|
func (bot *BotAPI) GetChatMembersCount(config ChatMemberCountConfig) (int, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
@ -573,9 +603,7 @@ func (bot *BotAPI) GetChatMembersCount(config ChatMemberCountConfig) (int, error
|
||||||
|
|
||||||
// GetChatMember gets a specific chat member.
|
// GetChatMember gets a specific chat member.
|
||||||
func (bot *BotAPI) GetChatMember(config GetChatMemberConfig) (ChatMember, error) {
|
func (bot *BotAPI) GetChatMember(config GetChatMemberConfig) (ChatMember, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ChatMember{}, err
|
return ChatMember{}, err
|
||||||
}
|
}
|
||||||
|
@ -588,9 +616,7 @@ func (bot *BotAPI) GetChatMember(config GetChatMemberConfig) (ChatMember, error)
|
||||||
|
|
||||||
// GetGameHighScores allows you to get the high scores for a game.
|
// GetGameHighScores allows you to get the high scores for a game.
|
||||||
func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) {
|
func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHighScore, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []GameHighScore{}, err
|
return []GameHighScore{}, err
|
||||||
}
|
}
|
||||||
|
@ -603,9 +629,7 @@ func (bot *BotAPI) GetGameHighScores(config GetGameHighScoresConfig) ([]GameHigh
|
||||||
|
|
||||||
// GetInviteLink get InviteLink for a chat
|
// GetInviteLink get InviteLink for a chat
|
||||||
func (bot *BotAPI) GetInviteLink(config ChatInviteLinkConfig) (string, error) {
|
func (bot *BotAPI) GetInviteLink(config ChatInviteLinkConfig) (string, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -618,9 +642,7 @@ func (bot *BotAPI) GetInviteLink(config ChatInviteLinkConfig) (string, error) {
|
||||||
|
|
||||||
// GetStickerSet returns a StickerSet.
|
// GetStickerSet returns a StickerSet.
|
||||||
func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) {
|
func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error) {
|
||||||
params, _ := config.params()
|
resp, err := bot.Request(config)
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return StickerSet{}, err
|
return StickerSet{}, err
|
||||||
}
|
}
|
||||||
|
@ -633,12 +655,7 @@ func (bot *BotAPI) GetStickerSet(config GetStickerSetConfig) (StickerSet, error)
|
||||||
|
|
||||||
// StopPoll stops a poll and returns the result.
|
// StopPoll stops a poll and returns the result.
|
||||||
func (bot *BotAPI) StopPoll(config StopPollConfig) (Poll, error) {
|
func (bot *BotAPI) StopPoll(config StopPollConfig) (Poll, error) {
|
||||||
params, err := config.params()
|
resp, err := bot.Request(config)
|
||||||
if err != nil {
|
|
||||||
return Poll{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Poll{}, err
|
return Poll{}, err
|
||||||
}
|
}
|
||||||
|
@ -653,12 +670,7 @@ func (bot *BotAPI) StopPoll(config StopPollConfig) (Poll, error) {
|
||||||
func (bot *BotAPI) GetMyCommands() ([]BotCommand, error) {
|
func (bot *BotAPI) GetMyCommands() ([]BotCommand, error) {
|
||||||
config := GetMyCommandsConfig{}
|
config := GetMyCommandsConfig{}
|
||||||
|
|
||||||
params, err := config.params()
|
resp, err := bot.Request(config)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := bot.MakeRequest(config.method(), params)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
165
bot_test.go
165
bot_test.go
|
@ -127,7 +127,7 @@ func TestCopyMessage(t *testing.T) {
|
||||||
func TestSendWithNewPhoto(t *testing.T) {
|
func TestSendWithNewPhoto(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewPhotoUpload(ChatID, "tests/image.jpg")
|
msg := NewPhoto(ChatID, "tests/image.jpg")
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ func TestSendWithNewPhotoWithFileBytes(t *testing.T) {
|
||||||
data, _ := ioutil.ReadFile("tests/image.jpg")
|
data, _ := ioutil.ReadFile("tests/image.jpg")
|
||||||
b := FileBytes{Name: "image.jpg", Bytes: data}
|
b := FileBytes{Name: "image.jpg", Bytes: data}
|
||||||
|
|
||||||
msg := NewPhotoUpload(ChatID, b)
|
msg := NewPhoto(ChatID, b)
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -155,9 +155,9 @@ func TestSendWithNewPhotoWithFileReader(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
f, _ := os.Open("tests/image.jpg")
|
f, _ := os.Open("tests/image.jpg")
|
||||||
reader := FileReader{Name: "image.jpg", Reader: f, Size: -1}
|
reader := FileReader{Name: "image.jpg", Reader: f}
|
||||||
|
|
||||||
msg := NewPhotoUpload(ChatID, reader)
|
msg := NewPhoto(ChatID, reader)
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ func TestSendWithNewPhotoWithFileReader(t *testing.T) {
|
||||||
func TestSendWithNewPhotoReply(t *testing.T) {
|
func TestSendWithNewPhotoReply(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewPhotoUpload(ChatID, "tests/image.jpg")
|
msg := NewPhoto(ChatID, "tests/image.jpg")
|
||||||
msg.ReplyToMessageID = ReplyToMessageID
|
msg.ReplyToMessageID = ReplyToMessageID
|
||||||
|
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
@ -182,7 +182,7 @@ func TestSendWithNewPhotoReply(t *testing.T) {
|
||||||
func TestSendNewPhotoToChannel(t *testing.T) {
|
func TestSendNewPhotoToChannel(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewPhotoUploadToChannel(Channel, "tests/image.jpg")
|
msg := NewPhotoToChannel(Channel, "tests/image.jpg")
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ func TestSendNewPhotoToChannelFileBytes(t *testing.T) {
|
||||||
data, _ := ioutil.ReadFile("tests/image.jpg")
|
data, _ := ioutil.ReadFile("tests/image.jpg")
|
||||||
b := FileBytes{Name: "image.jpg", Bytes: data}
|
b := FileBytes{Name: "image.jpg", Bytes: data}
|
||||||
|
|
||||||
msg := NewPhotoUploadToChannel(Channel, b)
|
msg := NewPhotoToChannel(Channel, b)
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -212,9 +212,9 @@ func TestSendNewPhotoToChannelFileReader(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
f, _ := os.Open("tests/image.jpg")
|
f, _ := os.Open("tests/image.jpg")
|
||||||
reader := FileReader{Name: "image.jpg", Reader: f, Size: -1}
|
reader := FileReader{Name: "image.jpg", Reader: f}
|
||||||
|
|
||||||
msg := NewPhotoUploadToChannel(Channel, reader)
|
msg := NewPhotoToChannel(Channel, reader)
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ func TestSendNewPhotoToChannelFileReader(t *testing.T) {
|
||||||
func TestSendWithExistingPhoto(t *testing.T) {
|
func TestSendWithExistingPhoto(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewPhotoShare(ChatID, ExistingPhotoFileID)
|
msg := NewPhoto(ChatID, FileID(ExistingPhotoFileID))
|
||||||
msg.Caption = "Test"
|
msg.Caption = "Test"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -239,7 +239,19 @@ func TestSendWithExistingPhoto(t *testing.T) {
|
||||||
func TestSendWithNewDocument(t *testing.T) {
|
func TestSendWithNewDocument(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewDocumentUpload(ChatID, "tests/image.jpg")
|
msg := NewDocument(ChatID, "tests/image.jpg")
|
||||||
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendWithNewDocumentAndThumb(t *testing.T) {
|
||||||
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
|
msg := NewDocument(ChatID, "tests/voice.ogg")
|
||||||
|
msg.Thumb = "tests/image.jpg"
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -250,7 +262,7 @@ func TestSendWithNewDocument(t *testing.T) {
|
||||||
func TestSendWithExistingDocument(t *testing.T) {
|
func TestSendWithExistingDocument(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewDocumentShare(ChatID, ExistingDocumentFileID)
|
msg := NewDocument(ChatID, FileID(ExistingDocumentFileID))
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -261,12 +273,10 @@ func TestSendWithExistingDocument(t *testing.T) {
|
||||||
func TestSendWithNewAudio(t *testing.T) {
|
func TestSendWithNewAudio(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewAudioUpload(ChatID, "tests/audio.mp3")
|
msg := NewAudio(ChatID, "tests/audio.mp3")
|
||||||
msg.Title = "TEST"
|
msg.Title = "TEST"
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
msg.Performer = "TEST"
|
msg.Performer = "TEST"
|
||||||
msg.MimeType = "audio/mpeg"
|
|
||||||
msg.FileSize = 688
|
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -277,7 +287,7 @@ func TestSendWithNewAudio(t *testing.T) {
|
||||||
func TestSendWithExistingAudio(t *testing.T) {
|
func TestSendWithExistingAudio(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewAudioShare(ChatID, ExistingAudioFileID)
|
msg := NewAudio(ChatID, FileID(ExistingAudioFileID))
|
||||||
msg.Title = "TEST"
|
msg.Title = "TEST"
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
msg.Performer = "TEST"
|
msg.Performer = "TEST"
|
||||||
|
@ -292,7 +302,7 @@ func TestSendWithExistingAudio(t *testing.T) {
|
||||||
func TestSendWithNewVoice(t *testing.T) {
|
func TestSendWithNewVoice(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewVoiceUpload(ChatID, "tests/voice.ogg")
|
msg := NewVoice(ChatID, "tests/voice.ogg")
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -304,7 +314,7 @@ func TestSendWithNewVoice(t *testing.T) {
|
||||||
func TestSendWithExistingVoice(t *testing.T) {
|
func TestSendWithExistingVoice(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewVoiceShare(ChatID, ExistingVoiceFileID)
|
msg := NewVoice(ChatID, FileID(ExistingVoiceFileID))
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -346,7 +356,7 @@ func TestSendWithVenue(t *testing.T) {
|
||||||
func TestSendWithNewVideo(t *testing.T) {
|
func TestSendWithNewVideo(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewVideoUpload(ChatID, "tests/video.mp4")
|
msg := NewVideo(ChatID, "tests/video.mp4")
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
msg.Caption = "TEST"
|
msg.Caption = "TEST"
|
||||||
|
|
||||||
|
@ -360,7 +370,7 @@ func TestSendWithNewVideo(t *testing.T) {
|
||||||
func TestSendWithExistingVideo(t *testing.T) {
|
func TestSendWithExistingVideo(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewVideoShare(ChatID, ExistingVideoFileID)
|
msg := NewVideo(ChatID, FileID(ExistingVideoFileID))
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
msg.Caption = "TEST"
|
msg.Caption = "TEST"
|
||||||
|
|
||||||
|
@ -374,7 +384,7 @@ func TestSendWithExistingVideo(t *testing.T) {
|
||||||
func TestSendWithNewVideoNote(t *testing.T) {
|
func TestSendWithNewVideoNote(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewVideoNoteUpload(ChatID, 240, "tests/videonote.mp4")
|
msg := NewVideoNote(ChatID, 240, "tests/videonote.mp4")
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
|
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
@ -387,7 +397,7 @@ func TestSendWithNewVideoNote(t *testing.T) {
|
||||||
func TestSendWithExistingVideoNote(t *testing.T) {
|
func TestSendWithExistingVideoNote(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewVideoNoteShare(ChatID, 240, ExistingVideoNoteFileID)
|
msg := NewVideoNote(ChatID, 240, FileID(ExistingVideoNoteFileID))
|
||||||
msg.Duration = 10
|
msg.Duration = 10
|
||||||
|
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
@ -400,7 +410,7 @@ func TestSendWithExistingVideoNote(t *testing.T) {
|
||||||
func TestSendWithNewSticker(t *testing.T) {
|
func TestSendWithNewSticker(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewStickerUpload(ChatID, "tests/image.jpg")
|
msg := NewSticker(ChatID, "tests/image.jpg")
|
||||||
|
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -412,7 +422,7 @@ func TestSendWithNewSticker(t *testing.T) {
|
||||||
func TestSendWithExistingSticker(t *testing.T) {
|
func TestSendWithExistingSticker(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewStickerShare(ChatID, ExistingStickerFileID)
|
msg := NewSticker(ChatID, FileID(ExistingStickerFileID))
|
||||||
|
|
||||||
_, err := bot.Send(msg)
|
_, err := bot.Send(msg)
|
||||||
|
|
||||||
|
@ -424,7 +434,7 @@ func TestSendWithExistingSticker(t *testing.T) {
|
||||||
func TestSendWithNewStickerAndKeyboardHide(t *testing.T) {
|
func TestSendWithNewStickerAndKeyboardHide(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewStickerUpload(ChatID, "tests/image.jpg")
|
msg := NewSticker(ChatID, "tests/image.jpg")
|
||||||
msg.ReplyMarkup = ReplyKeyboardRemove{
|
msg.ReplyMarkup = ReplyKeyboardRemove{
|
||||||
RemoveKeyboard: true,
|
RemoveKeyboard: true,
|
||||||
Selective: false,
|
Selective: false,
|
||||||
|
@ -439,7 +449,7 @@ func TestSendWithNewStickerAndKeyboardHide(t *testing.T) {
|
||||||
func TestSendWithExistingStickerAndKeyboardHide(t *testing.T) {
|
func TestSendWithExistingStickerAndKeyboardHide(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
msg := NewStickerShare(ChatID, ExistingStickerFileID)
|
msg := NewSticker(ChatID, FileID(ExistingStickerFileID))
|
||||||
msg.ReplyMarkup = ReplyKeyboardRemove{
|
msg.ReplyMarkup = ReplyKeyboardRemove{
|
||||||
RemoveKeyboard: true,
|
RemoveKeyboard: true,
|
||||||
Selective: false,
|
Selective: false,
|
||||||
|
@ -583,12 +593,13 @@ func TestSetWebhookWithoutCert(t *testing.T) {
|
||||||
bot.Request(DeleteWebhookConfig{})
|
bot.Request(DeleteWebhookConfig{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSendWithMediaGroup(t *testing.T) {
|
func TestSendWithMediaGroupPhotoVideo(t *testing.T) {
|
||||||
bot, _ := getBot(t)
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
cfg := NewMediaGroup(ChatID, []interface{}{
|
cfg := NewMediaGroup(ChatID, []interface{}{
|
||||||
NewInputMediaPhoto("https://github.com/go-telegram-bot-api/telegram-bot-api/raw/0a3a1c8716c4cd8d26a262af9f12dcbab7f3f28c/tests/image.jpg"),
|
NewInputMediaPhoto(FileURL("https://github.com/go-telegram-bot-api/telegram-bot-api/raw/0a3a1c8716c4cd8d26a262af9f12dcbab7f3f28c/tests/image.jpg")),
|
||||||
NewInputMediaVideo("https://github.com/go-telegram-bot-api/telegram-bot-api/raw/0a3a1c8716c4cd8d26a262af9f12dcbab7f3f28c/tests/video.mp4"),
|
NewInputMediaPhoto("tests/image.jpg"),
|
||||||
|
NewInputMediaVideo("tests/video.mp4"),
|
||||||
})
|
})
|
||||||
|
|
||||||
messages, err := bot.SendMediaGroup(cfg)
|
messages, err := bot.SendMediaGroup(cfg)
|
||||||
|
@ -597,11 +608,55 @@ func TestSendWithMediaGroup(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if messages == nil {
|
if messages == nil {
|
||||||
t.Error()
|
t.Error("No received messages")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(messages) != 2 {
|
if len(messages) != len(cfg.Media) {
|
||||||
t.Error()
|
t.Errorf("Different number of messages: %d", len(messages))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendWithMediaGroupDocument(t *testing.T) {
|
||||||
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
|
cfg := NewMediaGroup(ChatID, []interface{}{
|
||||||
|
NewInputMediaDocument(FileURL("https://i.imgur.com/unQLJIb.jpg")),
|
||||||
|
NewInputMediaDocument("tests/image.jpg"),
|
||||||
|
})
|
||||||
|
|
||||||
|
messages, err := bot.SendMediaGroup(cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if messages == nil {
|
||||||
|
t.Error("No received messages")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(messages) != len(cfg.Media) {
|
||||||
|
t.Errorf("Different number of messages: %d", len(messages))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendWithMediaGroupAudio(t *testing.T) {
|
||||||
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
|
cfg := NewMediaGroup(ChatID, []interface{}{
|
||||||
|
NewInputMediaAudio("tests/audio.mp3"),
|
||||||
|
NewInputMediaAudio("tests/audio.mp3"),
|
||||||
|
})
|
||||||
|
|
||||||
|
messages, err := bot.SendMediaGroup(cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if messages == nil {
|
||||||
|
t.Error("No received messages")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(messages) != len(cfg.Media) {
|
||||||
|
t.Errorf("Different number of messages: %d", len(messages))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,3 +954,49 @@ func TestSetCommands(t *testing.T) {
|
||||||
t.Error("Commands were incorrectly set")
|
t.Error("Commands were incorrectly set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEditMessageMedia(t *testing.T) {
|
||||||
|
bot, _ := getBot(t)
|
||||||
|
|
||||||
|
msg := NewPhoto(ChatID, "tests/image.jpg")
|
||||||
|
msg.Caption = "Test"
|
||||||
|
m, err := bot.Send(msg)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
edit := EditMessageMediaConfig{
|
||||||
|
BaseEdit: BaseEdit{
|
||||||
|
ChatID: ChatID,
|
||||||
|
MessageID: m.MessageID,
|
||||||
|
},
|
||||||
|
Media: NewInputMediaVideo("tests/video.mp4"),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = bot.Request(edit)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrepareInputMediaForParams(t *testing.T) {
|
||||||
|
media := []interface{}{
|
||||||
|
NewInputMediaPhoto("tests/image.jpg"),
|
||||||
|
NewInputMediaVideo(FileID("test")),
|
||||||
|
}
|
||||||
|
|
||||||
|
prepared := prepareInputMediaForParams(media)
|
||||||
|
|
||||||
|
if media[0].(InputMediaPhoto).Media != "tests/image.jpg" {
|
||||||
|
t.Error("Original media was changed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if prepared[0].(InputMediaPhoto).Media != "attach://file-0" {
|
||||||
|
t.Error("New media was not replaced")
|
||||||
|
}
|
||||||
|
|
||||||
|
if prepared[1].(InputMediaVideo).Media != FileID("test") {
|
||||||
|
t.Error("Passthrough value was not the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
581
configs.go
581
configs.go
|
@ -1,6 +1,7 @@
|
||||||
package tgbotapi
|
package tgbotapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -103,12 +104,19 @@ type Chattable interface {
|
||||||
method() string
|
method() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestFile represents a file associated with a request. May involve
|
||||||
|
// uploading a file, or passing an existing ID.
|
||||||
|
type RequestFile struct {
|
||||||
|
// The multipart upload field name.
|
||||||
|
Name string
|
||||||
|
// The file to upload.
|
||||||
|
File interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// Fileable is any config type that can be sent that includes a file.
|
// Fileable is any config type that can be sent that includes a file.
|
||||||
type Fileable interface {
|
type Fileable interface {
|
||||||
Chattable
|
Chattable
|
||||||
name() string
|
files() []RequestFile
|
||||||
getFile() interface{}
|
|
||||||
useExistingFile() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogOutConfig is a request to log out of the cloud Bot API server.
|
// LogOutConfig is a request to log out of the cloud Bot API server.
|
||||||
|
@ -165,27 +173,10 @@ func (chat *BaseChat) params() (Params, error) {
|
||||||
type BaseFile struct {
|
type BaseFile struct {
|
||||||
BaseChat
|
BaseChat
|
||||||
File interface{}
|
File interface{}
|
||||||
FileID string
|
|
||||||
UseExisting bool
|
|
||||||
MimeType string
|
|
||||||
FileSize int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file BaseFile) params() (Params, error) {
|
func (file BaseFile) params() (Params, error) {
|
||||||
params, err := file.BaseChat.params()
|
return file.BaseChat.params()
|
||||||
|
|
||||||
params.AddNonEmpty("mime_type", file.MimeType)
|
|
||||||
params.AddNonZero("file_size", file.FileSize)
|
|
||||||
|
|
||||||
return params, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (file BaseFile) getFile() interface{} {
|
|
||||||
return file.File
|
|
||||||
}
|
|
||||||
|
|
||||||
func (file BaseFile) useExistingFile() bool {
|
|
||||||
return file.UseExisting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaseEdit is base type of all chat edits.
|
// BaseEdit is base type of all chat edits.
|
||||||
|
@ -296,6 +287,7 @@ func (config CopyMessageConfig) method() string {
|
||||||
// PhotoConfig contains information about a SendPhoto request.
|
// PhotoConfig contains information about a SendPhoto request.
|
||||||
type PhotoConfig struct {
|
type PhotoConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
Thumb interface{}
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
CaptionEntities []MessageEntity
|
CaptionEntities []MessageEntity
|
||||||
|
@ -307,7 +299,6 @@ func (config PhotoConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
err = params.AddInterface("caption_entities", config.CaptionEntities)
|
||||||
|
@ -315,17 +306,30 @@ func (config PhotoConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config PhotoConfig) name() string {
|
|
||||||
return "photo"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config PhotoConfig) method() string {
|
func (config PhotoConfig) method() string {
|
||||||
return "sendPhoto"
|
return "sendPhoto"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config PhotoConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "photo",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// AudioConfig contains information about a SendAudio request.
|
// AudioConfig contains information about a SendAudio request.
|
||||||
type AudioConfig struct {
|
type AudioConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
Thumb interface{}
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
CaptionEntities []MessageEntity
|
CaptionEntities []MessageEntity
|
||||||
|
@ -340,7 +344,6 @@ func (config AudioConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonZero("duration", config.Duration)
|
params.AddNonZero("duration", config.Duration)
|
||||||
params.AddNonEmpty("performer", config.Performer)
|
params.AddNonEmpty("performer", config.Performer)
|
||||||
params.AddNonEmpty("title", config.Title)
|
params.AddNonEmpty("title", config.Title)
|
||||||
|
@ -351,17 +354,30 @@ func (config AudioConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config AudioConfig) name() string {
|
|
||||||
return "audio"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config AudioConfig) method() string {
|
func (config AudioConfig) method() string {
|
||||||
return "sendAudio"
|
return "sendAudio"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config AudioConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "audio",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// DocumentConfig contains information about a SendDocument request.
|
// DocumentConfig contains information about a SendDocument request.
|
||||||
type DocumentConfig struct {
|
type DocumentConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
Thumb interface{}
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
CaptionEntities []MessageEntity
|
CaptionEntities []MessageEntity
|
||||||
|
@ -371,7 +387,6 @@ type DocumentConfig struct {
|
||||||
func (config DocumentConfig) params() (Params, error) {
|
func (config DocumentConfig) params() (Params, error) {
|
||||||
params, err := config.BaseFile.params()
|
params, err := config.BaseFile.params()
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
params.AddBool("disable_content_type_detection", config.DisableContentTypeDetection)
|
params.AddBool("disable_content_type_detection", config.DisableContentTypeDetection)
|
||||||
|
@ -379,38 +394,50 @@ func (config DocumentConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config DocumentConfig) name() string {
|
|
||||||
return "document"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config DocumentConfig) method() string {
|
func (config DocumentConfig) method() string {
|
||||||
return "sendDocument"
|
return "sendDocument"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config DocumentConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "document",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// StickerConfig contains information about a SendSticker request.
|
// StickerConfig contains information about a SendSticker request.
|
||||||
type StickerConfig struct {
|
type StickerConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config StickerConfig) params() (Params, error) {
|
func (config StickerConfig) params() (Params, error) {
|
||||||
params, err := config.BaseChat.params()
|
return config.BaseChat.params()
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
|
|
||||||
return params, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config StickerConfig) name() string {
|
|
||||||
return "sticker"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config StickerConfig) method() string {
|
func (config StickerConfig) method() string {
|
||||||
return "sendSticker"
|
return "sendSticker"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config StickerConfig) files() []RequestFile {
|
||||||
|
return []RequestFile{{
|
||||||
|
Name: "sticker",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
// VideoConfig contains information about a SendVideo request.
|
// VideoConfig contains information about a SendVideo request.
|
||||||
type VideoConfig struct {
|
type VideoConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
Thumb interface{}
|
||||||
Duration int
|
Duration int
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
|
@ -424,7 +451,6 @@ func (config VideoConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonZero("duration", config.Duration)
|
params.AddNonZero("duration", config.Duration)
|
||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
|
@ -434,18 +460,31 @@ func (config VideoConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config VideoConfig) name() string {
|
|
||||||
return "video"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config VideoConfig) method() string {
|
func (config VideoConfig) method() string {
|
||||||
return "sendVideo"
|
return "sendVideo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config VideoConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "video",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// AnimationConfig contains information about a SendAnimation request.
|
// AnimationConfig contains information about a SendAnimation request.
|
||||||
type AnimationConfig struct {
|
type AnimationConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
Duration int
|
Duration int
|
||||||
|
Thumb interface{}
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
CaptionEntities []MessageEntity
|
CaptionEntities []MessageEntity
|
||||||
|
@ -457,7 +496,6 @@ func (config AnimationConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonZero("duration", config.Duration)
|
params.AddNonZero("duration", config.Duration)
|
||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
|
@ -466,17 +504,30 @@ func (config AnimationConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config AnimationConfig) name() string {
|
|
||||||
return "animation"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config AnimationConfig) method() string {
|
func (config AnimationConfig) method() string {
|
||||||
return "sendAnimation"
|
return "sendAnimation"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config AnimationConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "animation",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// VideoNoteConfig contains information about a SendVideoNote request.
|
// VideoNoteConfig contains information about a SendVideoNote request.
|
||||||
type VideoNoteConfig struct {
|
type VideoNoteConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
Thumb interface{}
|
||||||
Duration int
|
Duration int
|
||||||
Length int
|
Length int
|
||||||
}
|
}
|
||||||
|
@ -484,24 +535,36 @@ type VideoNoteConfig struct {
|
||||||
func (config VideoNoteConfig) params() (Params, error) {
|
func (config VideoNoteConfig) params() (Params, error) {
|
||||||
params, err := config.BaseChat.params()
|
params, err := config.BaseChat.params()
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonZero("duration", config.Duration)
|
params.AddNonZero("duration", config.Duration)
|
||||||
params.AddNonZero("length", config.Length)
|
params.AddNonZero("length", config.Length)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config VideoNoteConfig) name() string {
|
|
||||||
return "video_note"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config VideoNoteConfig) method() string {
|
func (config VideoNoteConfig) method() string {
|
||||||
return "sendVideoNote"
|
return "sendVideoNote"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config VideoNoteConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "video_note",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// VoiceConfig contains information about a SendVoice request.
|
// VoiceConfig contains information about a SendVoice request.
|
||||||
type VoiceConfig struct {
|
type VoiceConfig struct {
|
||||||
BaseFile
|
BaseFile
|
||||||
|
Thumb interface{}
|
||||||
Caption string
|
Caption string
|
||||||
ParseMode string
|
ParseMode string
|
||||||
CaptionEntities []MessageEntity
|
CaptionEntities []MessageEntity
|
||||||
|
@ -514,7 +577,6 @@ func (config VoiceConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddNonEmpty(config.name(), config.FileID)
|
|
||||||
params.AddNonZero("duration", config.Duration)
|
params.AddNonZero("duration", config.Duration)
|
||||||
params.AddNonEmpty("caption", config.Caption)
|
params.AddNonEmpty("caption", config.Caption)
|
||||||
params.AddNonEmpty("parse_mode", config.ParseMode)
|
params.AddNonEmpty("parse_mode", config.ParseMode)
|
||||||
|
@ -523,14 +585,26 @@ func (config VoiceConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config VoiceConfig) name() string {
|
|
||||||
return "voice"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config VoiceConfig) method() string {
|
func (config VoiceConfig) method() string {
|
||||||
return "sendVoice"
|
return "sendVoice"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config VoiceConfig) files() []RequestFile {
|
||||||
|
files := []RequestFile{{
|
||||||
|
Name: "voice",
|
||||||
|
File: config.File,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if config.Thumb != nil {
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
// LocationConfig contains information about a SendLocation request.
|
// LocationConfig contains information about a SendLocation request.
|
||||||
type LocationConfig struct {
|
type LocationConfig struct {
|
||||||
BaseChat
|
BaseChat
|
||||||
|
@ -849,7 +923,7 @@ func (config EditMessageCaptionConfig) method() string {
|
||||||
return "editMessageCaption"
|
return "editMessageCaption"
|
||||||
}
|
}
|
||||||
|
|
||||||
// EditMessageMediaConfig contains information about editing a message's media.
|
// EditMessageMediaConfig allows you to make an editMessageMedia request.
|
||||||
type EditMessageMediaConfig struct {
|
type EditMessageMediaConfig struct {
|
||||||
BaseEdit
|
BaseEdit
|
||||||
|
|
||||||
|
@ -862,12 +936,19 @@ func (EditMessageMediaConfig) method() string {
|
||||||
|
|
||||||
func (config EditMessageMediaConfig) params() (Params, error) {
|
func (config EditMessageMediaConfig) params() (Params, error) {
|
||||||
params, err := config.BaseEdit.params()
|
params, err := config.BaseEdit.params()
|
||||||
|
if err != nil {
|
||||||
|
return params, err
|
||||||
|
}
|
||||||
|
|
||||||
params.AddInterface("media", config.Media)
|
err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0))
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config EditMessageMediaConfig) files() []RequestFile {
|
||||||
|
return prepareInputMediaFile(config.Media, 0)
|
||||||
|
}
|
||||||
|
|
||||||
// EditMessageReplyMarkupConfig allows you to modify the reply markup
|
// EditMessageReplyMarkupConfig allows you to modify the reply markup
|
||||||
// of a message.
|
// of a message.
|
||||||
type EditMessageReplyMarkupConfig struct {
|
type EditMessageReplyMarkupConfig struct {
|
||||||
|
@ -980,22 +1061,21 @@ func (config WebhookConfig) params() (Params, error) {
|
||||||
|
|
||||||
params.AddNonEmpty("ip_address", config.IPAddress)
|
params.AddNonEmpty("ip_address", config.IPAddress)
|
||||||
params.AddNonZero("max_connections", config.MaxConnections)
|
params.AddNonZero("max_connections", config.MaxConnections)
|
||||||
params.AddInterface("allowed_updates", config.AllowedUpdates)
|
err := params.AddInterface("allowed_updates", config.AllowedUpdates)
|
||||||
params.AddBool("drop_pending_updates", config.DropPendingUpdates)
|
params.AddBool("drop_pending_updates", config.DropPendingUpdates)
|
||||||
|
|
||||||
return params, nil
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config WebhookConfig) name() string {
|
func (config WebhookConfig) files() []RequestFile {
|
||||||
return "certificate"
|
if config.Certificate != nil {
|
||||||
}
|
return []RequestFile{{
|
||||||
|
Name: "certificate",
|
||||||
|
File: config.Certificate,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
func (config WebhookConfig) getFile() interface{} {
|
return nil
|
||||||
return config.Certificate
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config WebhookConfig) useExistingFile() bool {
|
|
||||||
return config.URL != nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteWebhookConfig is a helper to delete a webhook.
|
// DeleteWebhookConfig is a helper to delete a webhook.
|
||||||
|
@ -1023,14 +1103,17 @@ type FileBytes struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileReader contains information about a reader to upload as a File.
|
// 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 {
|
type FileReader struct {
|
||||||
Name string
|
Name string
|
||||||
Reader io.Reader
|
Reader io.Reader
|
||||||
Size int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileURL is a URL to use as a file for a request.
|
||||||
|
type FileURL string
|
||||||
|
|
||||||
|
// FileID is an ID of a file already uploaded to Telegram.
|
||||||
|
type FileID string
|
||||||
|
|
||||||
// InlineConfig contains information on making an InlineQuery response.
|
// InlineConfig contains information on making an InlineQuery response.
|
||||||
type InlineConfig struct {
|
type InlineConfig struct {
|
||||||
InlineQueryID string `json:"inline_query_id"`
|
InlineQueryID string `json:"inline_query_id"`
|
||||||
|
@ -1278,9 +1361,9 @@ func (config SetChatPermissionsConfig) params() (Params, error) {
|
||||||
params := make(Params)
|
params := make(Params)
|
||||||
|
|
||||||
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
params.AddFirstValid("chat_id", config.ChatID, config.SuperGroupUsername)
|
||||||
params.AddInterface("permissions", config.Permissions)
|
err := params.AddInterface("permissions", config.Permissions)
|
||||||
|
|
||||||
return params, nil
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChatInviteLinkConfig contains information about getting a chat link.
|
// ChatInviteLinkConfig contains information about getting a chat link.
|
||||||
|
@ -1610,16 +1693,11 @@ func (config SetChatPhotoConfig) method() string {
|
||||||
return "setChatPhoto"
|
return "setChatPhoto"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config SetChatPhotoConfig) name() string {
|
func (config SetChatPhotoConfig) files() []RequestFile {
|
||||||
return "photo"
|
return []RequestFile{{
|
||||||
}
|
Name: "photo",
|
||||||
|
File: config.File,
|
||||||
func (config SetChatPhotoConfig) getFile() interface{} {
|
}}
|
||||||
return config.File
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config SetChatPhotoConfig) useExistingFile() bool {
|
|
||||||
return config.UseExisting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
|
// DeleteChatPhotoConfig allows you to delete a group, supergroup, or channel's photo.
|
||||||
|
@ -1717,18 +1795,11 @@ func (config UploadStickerConfig) params() (Params, error) {
|
||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config UploadStickerConfig) name() string {
|
func (config UploadStickerConfig) files() []RequestFile {
|
||||||
return "png_sticker"
|
return []RequestFile{{
|
||||||
}
|
Name: "png_sticker",
|
||||||
|
File: config.PNGSticker,
|
||||||
func (config UploadStickerConfig) getFile() interface{} {
|
}}
|
||||||
return config.PNGSticker
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config UploadStickerConfig) useExistingFile() bool {
|
|
||||||
_, ok := config.PNGSticker.(string)
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStickerSetConfig allows creating a new sticker set.
|
// NewStickerSetConfig allows creating a new sticker set.
|
||||||
|
@ -1756,12 +1827,6 @@ func (config NewStickerSetConfig) params() (Params, error) {
|
||||||
params["name"] = config.Name
|
params["name"] = config.Name
|
||||||
params["title"] = config.Title
|
params["title"] = config.Title
|
||||||
|
|
||||||
if sticker, ok := config.PNGSticker.(string); ok {
|
|
||||||
params[config.name()] = sticker
|
|
||||||
} else if sticker, ok := config.TGSSticker.(string); ok {
|
|
||||||
params[config.name()] = sticker
|
|
||||||
}
|
|
||||||
|
|
||||||
params["emojis"] = config.Emojis
|
params["emojis"] = config.Emojis
|
||||||
|
|
||||||
params.AddBool("contains_masks", config.ContainsMasks)
|
params.AddBool("contains_masks", config.ContainsMasks)
|
||||||
|
@ -1771,26 +1836,18 @@ func (config NewStickerSetConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config NewStickerSetConfig) getFile() interface{} {
|
func (config NewStickerSetConfig) files() []RequestFile {
|
||||||
return config.PNGSticker
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config NewStickerSetConfig) name() string {
|
|
||||||
return "png_sticker"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config NewStickerSetConfig) useExistingFile() bool {
|
|
||||||
if config.PNGSticker != nil {
|
if config.PNGSticker != nil {
|
||||||
_, ok := config.PNGSticker.(string)
|
return []RequestFile{{
|
||||||
return ok
|
Name: "png_sticker",
|
||||||
|
File: config.PNGSticker,
|
||||||
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.TGSSticker != nil {
|
return []RequestFile{{
|
||||||
_, ok := config.TGSSticker.(string)
|
Name: "tgs_sticker",
|
||||||
return ok
|
File: config.TGSSticker,
|
||||||
}
|
}}
|
||||||
|
|
||||||
panic("NewStickerSetConfig had nil PNGSticker and TGSSticker")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddStickerConfig allows you to add a sticker to a set.
|
// AddStickerConfig allows you to add a sticker to a set.
|
||||||
|
@ -1814,29 +1871,24 @@ func (config AddStickerConfig) params() (Params, error) {
|
||||||
params["name"] = config.Name
|
params["name"] = config.Name
|
||||||
params["emojis"] = config.Emojis
|
params["emojis"] = config.Emojis
|
||||||
|
|
||||||
if sticker, ok := config.PNGSticker.(string); ok {
|
|
||||||
params[config.name()] = sticker
|
|
||||||
} else if sticker, ok := config.TGSSticker.(string); ok {
|
|
||||||
params[config.name()] = sticker
|
|
||||||
}
|
|
||||||
|
|
||||||
err := params.AddInterface("mask_position", config.MaskPosition)
|
err := params.AddInterface("mask_position", config.MaskPosition)
|
||||||
|
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config AddStickerConfig) name() string {
|
func (config AddStickerConfig) files() []RequestFile {
|
||||||
return "png_sticker"
|
if config.PNGSticker != nil {
|
||||||
}
|
return []RequestFile{{
|
||||||
|
Name: "png_sticker",
|
||||||
|
File: config.PNGSticker,
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
func (config AddStickerConfig) getFile() interface{} {
|
return []RequestFile{{
|
||||||
return config.PNGSticker
|
Name: "tgs_sticker",
|
||||||
}
|
File: config.TGSSticker,
|
||||||
|
}}
|
||||||
|
|
||||||
func (config AddStickerConfig) useExistingFile() bool {
|
|
||||||
_, ok := config.PNGSticker.(string)
|
|
||||||
|
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStickerPositionConfig allows you to change the position of a sticker in a set.
|
// SetStickerPositionConfig allows you to change the position of a sticker in a set.
|
||||||
|
@ -1892,24 +1944,14 @@ func (config SetStickerSetThumbConfig) params() (Params, error) {
|
||||||
params["name"] = config.Name
|
params["name"] = config.Name
|
||||||
params.AddNonZero("user_id", config.UserID)
|
params.AddNonZero("user_id", config.UserID)
|
||||||
|
|
||||||
if thumb, ok := config.Thumb.(string); ok {
|
|
||||||
params["thumb"] = thumb
|
|
||||||
}
|
|
||||||
|
|
||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config SetStickerSetThumbConfig) name() string {
|
func (config SetStickerSetThumbConfig) files() []RequestFile {
|
||||||
return "thumb"
|
return []RequestFile{{
|
||||||
}
|
Name: "thumb",
|
||||||
|
File: config.Thumb,
|
||||||
func (config SetStickerSetThumbConfig) getFile() interface{} {
|
}}
|
||||||
return config.Thumb
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config SetStickerSetThumbConfig) useExistingFile() bool {
|
|
||||||
_, ok := config.Thumb.(string)
|
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
|
// SetChatStickerSetConfig allows you to set the sticker set for a supergroup.
|
||||||
|
@ -1971,13 +2013,42 @@ func (config MediaGroupConfig) params() (Params, error) {
|
||||||
params := make(Params)
|
params := make(Params)
|
||||||
|
|
||||||
params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
|
params.AddFirstValid("chat_id", config.ChatID, config.ChannelUsername)
|
||||||
if err := params.AddInterface("media", config.Media); err != nil {
|
|
||||||
return params, nil
|
|
||||||
}
|
|
||||||
params.AddBool("disable_notification", config.DisableNotification)
|
params.AddBool("disable_notification", config.DisableNotification)
|
||||||
params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
|
params.AddNonZero("reply_to_message_id", config.ReplyToMessageID)
|
||||||
|
|
||||||
return params, nil
|
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.
|
// GetMyCommandsConfig gets a list of the currently registered commands.
|
||||||
|
@ -2008,28 +2079,170 @@ func (config SetMyCommandsConfig) params() (Params, error) {
|
||||||
return params, err
|
return params, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiceConfig contains information about a sendDice request.
|
// prepareInputMediaParam evaluates a single InputMedia and determines if it
|
||||||
type DiceConfig struct {
|
// needs to be modified for a successful upload. If it returns nil, then the
|
||||||
BaseChat
|
// value does not need to be included in the params. Otherwise, it will return
|
||||||
// Emoji on which the dice throw animation is based.
|
// the same type as was originally provided.
|
||||||
// Currently, must be one of 🎲, 🎯, 🏀, ⚽, 🎳, or 🎰.
|
//
|
||||||
// Dice can have values 1-6 for 🎲, 🎯, and 🎳, values 1-5 for 🏀 and ⚽,
|
// The idx is used to calculate the file field name. If you only have a single
|
||||||
// and values 1-64 for 🎰.
|
// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
|
||||||
// Defaults to “🎲”
|
// media and "attach://file-%d-thumb" for thumbnails.
|
||||||
Emoji string
|
//
|
||||||
}
|
// It is expected to be used in conjunction with prepareInputMediaFile.
|
||||||
|
func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
|
||||||
func (config DiceConfig) method() string {
|
switch m := inputMedia.(type) {
|
||||||
return "sendDice"
|
case InputMediaPhoto:
|
||||||
}
|
switch m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
func (config DiceConfig) params() (Params, error) {
|
m.Media = fmt.Sprintf("attach://file-%d", idx)
|
||||||
params, err := config.BaseChat.params()
|
|
||||||
if err != nil {
|
|
||||||
return params, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
params.AddNonEmpty("emoji", config.Emoji)
|
return m
|
||||||
|
case InputMediaVideo:
|
||||||
|
switch m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
m.Media = fmt.Sprintf("attach://file-%d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
return params, err
|
switch m.Thumb.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
m.Thumb = fmt.Sprintf("attach://file-%d-thumb", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
case InputMediaAudio:
|
||||||
|
switch m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
m.Media = fmt.Sprintf("attach://file-%d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.Thumb.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
m.Thumb = fmt.Sprintf("attach://file-%d-thumb", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
case InputMediaDocument:
|
||||||
|
switch m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
m.Media = fmt.Sprintf("attach://file-%d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m.Thumb.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
m.Thumb = 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:
|
||||||
|
switch f := m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
case InputMediaVideo:
|
||||||
|
switch f := m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
switch f := m.Thumb.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d-thumb", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
case InputMediaDocument:
|
||||||
|
switch f := m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
switch f := m.Thumb.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
case InputMediaAudio:
|
||||||
|
switch f := m.Media.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
switch f := m.Thumb.(type) {
|
||||||
|
case string, FileBytes, FileReader:
|
||||||
|
files = append(files, RequestFile{
|
||||||
|
Name: fmt.Sprintf("file-%d", idx),
|
||||||
|
File: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,5 +1,3 @@
|
||||||
module github.com/go-telegram-bot-api/telegram-bot-api/v5
|
module github.com/go-telegram-bot-api/telegram-bot-api/v5
|
||||||
|
|
||||||
require github.com/technoweenie/multipartstreamer v1.0.1
|
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -1,2 +0,0 @@
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
|
231
helpers.go
231
helpers.go
|
@ -64,259 +64,105 @@ func NewCopyMessage(chatID int64, fromChatID int64, messageID int) CopyMessageCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPhotoUpload creates a new photo uploader.
|
// NewPhoto creates a new sendPhoto request.
|
||||||
//
|
//
|
||||||
// chatID is where to send it, file is a string path to the file,
|
// chatID is where to send it, file is a string path to the file,
|
||||||
// FileReader, or FileBytes.
|
// FileReader, or FileBytes.
|
||||||
//
|
//
|
||||||
// Note that you must send animated GIFs as a document.
|
// Note that you must send animated GIFs as a document.
|
||||||
func NewPhotoUpload(chatID int64, file interface{}) PhotoConfig {
|
func NewPhoto(chatID int64, file interface{}) PhotoConfig {
|
||||||
return PhotoConfig{
|
return PhotoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPhotoUploadToChannel creates a new photo uploader to send a photo to a channel.
|
// NewPhotoToChannel creates a new photo uploader to send a photo to a channel.
|
||||||
//
|
|
||||||
// username is the username of the channel, file is a string path to the file,
|
|
||||||
// FileReader, or FileBytes.
|
|
||||||
//
|
//
|
||||||
// Note that you must send animated GIFs as a document.
|
// Note that you must send animated GIFs as a document.
|
||||||
func NewPhotoUploadToChannel(username string, file interface{}) PhotoConfig {
|
func NewPhotoToChannel(username string, file interface{}) PhotoConfig {
|
||||||
return PhotoConfig{
|
return PhotoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{
|
BaseChat: BaseChat{
|
||||||
ChannelUsername: username,
|
ChannelUsername: username,
|
||||||
},
|
},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPhotoShare shares an existing photo.
|
// NewAudio creates a new sendAudio request.
|
||||||
// You may use this to reshare an existing photo without reuploading it.
|
func NewAudio(chatID int64, file interface{}) AudioConfig {
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the file
|
|
||||||
// already uploaded.
|
|
||||||
func NewPhotoShare(chatID int64, fileID string) 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{
|
return AudioConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAudioShare shares an existing audio file.
|
// NewDocument creates a new sendDocument request.
|
||||||
// You may use this to reshare an existing audio file without
|
func NewDocument(chatID int64, file interface{}) DocumentConfig {
|
||||||
// reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the audio
|
|
||||||
// already uploaded.
|
|
||||||
func NewAudioShare(chatID int64, fileID string) 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{
|
return DocumentConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDocumentShare shares an existing document.
|
// NewSticker creates a new sendSticker request.
|
||||||
// You may use this to reshare an existing document without
|
func NewSticker(chatID int64, file interface{}) StickerConfig {
|
||||||
// reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the document
|
|
||||||
// already uploaded.
|
|
||||||
func NewDocumentShare(chatID int64, fileID string) 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{
|
return StickerConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStickerShare shares an existing sticker.
|
// NewVideo creates a new sendVideo request.
|
||||||
// You may use this to reshare an existing sticker without
|
func NewVideo(chatID int64, file interface{}) VideoConfig {
|
||||||
// reuploading it.
|
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the sticker
|
|
||||||
// already uploaded.
|
|
||||||
func NewStickerShare(chatID int64, fileID string) StickerConfig {
|
|
||||||
return StickerConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 {
|
|
||||||
return VideoConfig{
|
return VideoConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVideoShare shares an existing video.
|
// NewAnimation creates a new sendAnimation request.
|
||||||
// You may use this to reshare an existing video without reuploading it.
|
func NewAnimation(chatID int64, file interface{}) AnimationConfig {
|
||||||
//
|
|
||||||
// chatID is where to send it, fileID is the ID of the video
|
|
||||||
// already uploaded.
|
|
||||||
func NewVideoShare(chatID int64, fileID string) VideoConfig {
|
|
||||||
return VideoConfig{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAnimationUpload creates a new animation uploader.
|
|
||||||
//
|
|
||||||
// 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{
|
return AnimationConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAnimationShare shares an existing animation.
|
// NewVideoNote creates a new sendVideoNote request.
|
||||||
// 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{
|
|
||||||
BaseFile: BaseFile{
|
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
|
||||||
FileID: fileID,
|
|
||||||
UseExisting: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewVideoNoteUpload creates a new video note uploader.
|
|
||||||
//
|
//
|
||||||
// chatID is where to send it, file is a string path to the file,
|
// chatID is where to send it, file is a string path to the file,
|
||||||
// FileReader, or FileBytes.
|
// FileReader, or FileBytes.
|
||||||
func NewVideoNoteUpload(chatID int64, length int, file interface{}) VideoNoteConfig {
|
func NewVideoNote(chatID int64, length int, file interface{}) VideoNoteConfig {
|
||||||
return VideoNoteConfig{
|
return VideoNoteConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
},
|
||||||
Length: length,
|
Length: length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVideoNoteShare shares an existing video.
|
// NewVoice creates a new sendVoice request.
|
||||||
// You may use this to reshare an existing video without reuploading it.
|
func NewVoice(chatID int64, file interface{}) VoiceConfig {
|
||||||
//
|
|
||||||
// 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,
|
|
||||||
},
|
|
||||||
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{
|
return VoiceConfig{
|
||||||
BaseFile: BaseFile{
|
BaseFile: BaseFile{
|
||||||
BaseChat: BaseChat{ChatID: chatID},
|
BaseChat: BaseChat{ChatID: chatID},
|
||||||
File: file,
|
File: file,
|
||||||
UseExisting: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,7 +177,7 @@ func NewMediaGroup(chatID int64, files []interface{}) MediaGroupConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaPhoto creates a new InputMediaPhoto.
|
// NewInputMediaPhoto creates a new InputMediaPhoto.
|
||||||
func NewInputMediaPhoto(media string) InputMediaPhoto {
|
func NewInputMediaPhoto(media interface{}) InputMediaPhoto {
|
||||||
return InputMediaPhoto{
|
return InputMediaPhoto{
|
||||||
BaseInputMedia{
|
BaseInputMedia{
|
||||||
Type: "photo",
|
Type: "photo",
|
||||||
|
@ -341,7 +187,7 @@ func NewInputMediaPhoto(media string) InputMediaPhoto {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaVideo creates a new InputMediaVideo.
|
// NewInputMediaVideo creates a new InputMediaVideo.
|
||||||
func NewInputMediaVideo(media string) InputMediaVideo {
|
func NewInputMediaVideo(media interface{}) InputMediaVideo {
|
||||||
return InputMediaVideo{
|
return InputMediaVideo{
|
||||||
BaseInputMedia: BaseInputMedia{
|
BaseInputMedia: BaseInputMedia{
|
||||||
Type: "video",
|
Type: "video",
|
||||||
|
@ -351,7 +197,7 @@ func NewInputMediaVideo(media string) InputMediaVideo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaAnimation creates a new InputMediaAnimation.
|
// NewInputMediaAnimation creates a new InputMediaAnimation.
|
||||||
func NewInputMediaAnimation(media string) InputMediaAnimation {
|
func NewInputMediaAnimation(media interface{}) InputMediaAnimation {
|
||||||
return InputMediaAnimation{
|
return InputMediaAnimation{
|
||||||
BaseInputMedia: BaseInputMedia{
|
BaseInputMedia: BaseInputMedia{
|
||||||
Type: "animation",
|
Type: "animation",
|
||||||
|
@ -361,7 +207,7 @@ func NewInputMediaAnimation(media string) InputMediaAnimation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaAudio creates a new InputMediaAudio.
|
// NewInputMediaAudio creates a new InputMediaAudio.
|
||||||
func NewInputMediaAudio(media string) InputMediaAudio {
|
func NewInputMediaAudio(media interface{}) InputMediaAudio {
|
||||||
return InputMediaAudio{
|
return InputMediaAudio{
|
||||||
BaseInputMedia: BaseInputMedia{
|
BaseInputMedia: BaseInputMedia{
|
||||||
Type: "audio",
|
Type: "audio",
|
||||||
|
@ -371,7 +217,7 @@ func NewInputMediaAudio(media string) InputMediaAudio {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInputMediaDocument creates a new InputMediaDocument.
|
// NewInputMediaDocument creates a new InputMediaDocument.
|
||||||
func NewInputMediaDocument(media string) InputMediaDocument {
|
func NewInputMediaDocument(media interface{}) InputMediaDocument {
|
||||||
return InputMediaDocument{
|
return InputMediaDocument{
|
||||||
BaseInputMedia: BaseInputMedia{
|
BaseInputMedia: BaseInputMedia{
|
||||||
Type: "document",
|
Type: "document",
|
||||||
|
@ -889,37 +735,6 @@ func NewInvoice(chatID int64, title, description, payload, providerToken, startP
|
||||||
Prices: prices}
|
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,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewChatTitle allows you to update the title of a chat.
|
// NewChatTitle allows you to update the title of a chat.
|
||||||
func NewChatTitle(chatID int64, title string) SetChatTitleConfig {
|
func NewChatTitle(chatID int64, title string) SetChatTitleConfig {
|
||||||
return SetChatTitleConfig{
|
return SetChatTitleConfig{
|
||||||
|
|
28
types.go
28
types.go
|
@ -180,12 +180,6 @@ func (u *User) String() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// GroupChat is a group chat.
|
|
||||||
type GroupChat struct {
|
|
||||||
ID int `json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chat represents a chat.
|
// Chat represents a chat.
|
||||||
type Chat struct {
|
type Chat struct {
|
||||||
// ID is a unique identifier for this chat
|
// ID is a unique identifier for this chat
|
||||||
|
@ -1654,7 +1648,7 @@ type BaseInputMedia struct {
|
||||||
// pass an HTTP URL for Telegram to get a file from the Internet,
|
// pass an HTTP URL for Telegram to get a file from the Internet,
|
||||||
// or pass “attach://<file_attach_name>” to upload a new one
|
// or pass “attach://<file_attach_name>” to upload a new one
|
||||||
// using multipart/form-data under <file_attach_name> name.
|
// using multipart/form-data under <file_attach_name> name.
|
||||||
Media string `json:"media"`
|
Media interface{} `json:"media"`
|
||||||
// thumb intentionally missing as it is not currently compatible
|
// thumb intentionally missing as it is not currently compatible
|
||||||
|
|
||||||
// Caption of the video to be sent, 0-1024 characters after entities parsing.
|
// Caption of the video to be sent, 0-1024 characters after entities parsing.
|
||||||
|
@ -1682,6 +1676,11 @@ type InputMediaPhoto struct {
|
||||||
// InputMediaVideo is a video to send as part of a media group.
|
// InputMediaVideo is a video to send as part of a media group.
|
||||||
type InputMediaVideo struct {
|
type InputMediaVideo struct {
|
||||||
BaseInputMedia
|
BaseInputMedia
|
||||||
|
// Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
// the file is supported server-side.
|
||||||
|
//
|
||||||
|
// optional
|
||||||
|
Thumb interface{} `json:"thumb"`
|
||||||
// Width video width
|
// Width video width
|
||||||
//
|
//
|
||||||
// optional
|
// optional
|
||||||
|
@ -1703,6 +1702,11 @@ type InputMediaVideo struct {
|
||||||
// InputMediaAnimation is an animation to send as part of a media group.
|
// InputMediaAnimation is an animation to send as part of a media group.
|
||||||
type InputMediaAnimation struct {
|
type InputMediaAnimation struct {
|
||||||
BaseInputMedia
|
BaseInputMedia
|
||||||
|
// Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
// the file is supported server-side.
|
||||||
|
//
|
||||||
|
// optional
|
||||||
|
Thumb interface{} `json:"thumb"`
|
||||||
// Width video width
|
// Width video width
|
||||||
//
|
//
|
||||||
// optional
|
// optional
|
||||||
|
@ -1720,6 +1724,11 @@ type InputMediaAnimation struct {
|
||||||
// InputMediaAudio is a audio to send as part of a media group.
|
// InputMediaAudio is a audio to send as part of a media group.
|
||||||
type InputMediaAudio struct {
|
type InputMediaAudio struct {
|
||||||
BaseInputMedia
|
BaseInputMedia
|
||||||
|
// Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
// the file is supported server-side.
|
||||||
|
//
|
||||||
|
// optional
|
||||||
|
Thumb interface{} `json:"thumb"`
|
||||||
// Duration of the audio in seconds
|
// Duration of the audio in seconds
|
||||||
//
|
//
|
||||||
// optional
|
// optional
|
||||||
|
@ -1737,6 +1746,11 @@ type InputMediaAudio struct {
|
||||||
// InputMediaDocument is a general file to send as part of a media group.
|
// InputMediaDocument is a general file to send as part of a media group.
|
||||||
type InputMediaDocument struct {
|
type InputMediaDocument struct {
|
||||||
BaseInputMedia
|
BaseInputMedia
|
||||||
|
// Thumbnail of the file sent; can be ignored if thumbnail generation for
|
||||||
|
// the file is supported server-side.
|
||||||
|
//
|
||||||
|
// optional
|
||||||
|
Thumb interface{} `json:"thumb"`
|
||||||
// DisableContentTypeDetection disables automatic server-side content type
|
// DisableContentTypeDetection disables automatic server-side content type
|
||||||
// detection for files uploaded using multipart/form-data. Always true, if
|
// detection for files uploaded using multipart/form-data. Always true, if
|
||||||
// the document is sent as part of an album
|
// the document is sent as part of an album
|
||||||
|
|
|
@ -339,3 +339,24 @@ var (
|
||||||
_ Chattable = VoiceConfig{}
|
_ Chattable = VoiceConfig{}
|
||||||
_ Chattable = WebhookConfig{}
|
_ Chattable = WebhookConfig{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ensure all Fileable types are correct.
|
||||||
|
var (
|
||||||
|
_ Fileable = (*PhotoConfig)(nil)
|
||||||
|
_ Fileable = (*AudioConfig)(nil)
|
||||||
|
_ Fileable = (*DocumentConfig)(nil)
|
||||||
|
_ Fileable = (*StickerConfig)(nil)
|
||||||
|
_ Fileable = (*VideoConfig)(nil)
|
||||||
|
_ Fileable = (*AnimationConfig)(nil)
|
||||||
|
_ Fileable = (*VideoNoteConfig)(nil)
|
||||||
|
_ Fileable = (*VoiceConfig)(nil)
|
||||||
|
_ Fileable = (*SetChatPhotoConfig)(nil)
|
||||||
|
_ Fileable = (*EditMessageMediaConfig)(nil)
|
||||||
|
_ Fileable = (*SetChatPhotoConfig)(nil)
|
||||||
|
_ Fileable = (*UploadStickerConfig)(nil)
|
||||||
|
_ Fileable = (*NewStickerSetConfig)(nil)
|
||||||
|
_ Fileable = (*AddStickerConfig)(nil)
|
||||||
|
_ Fileable = (*MediaGroupConfig)(nil)
|
||||||
|
_ Fileable = (*WebhookConfig)(nil)
|
||||||
|
_ Fileable = (*SetStickerSetThumbConfig)(nil)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue