Generalize InputMedia, fix editMessageMedia.

bot-api-6.1
Syfaro 2020-07-26 15:51:33 -05:00
parent 8d14bd7a56
commit a45216f441
3 changed files with 182 additions and 66 deletions

View File

@ -817,3 +817,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")
}
}

View File

@ -768,21 +768,23 @@ type EditMessageMediaConfig struct {
Media interface{} Media interface{}
} }
func (config EditMessageMediaConfig) files() []RequestFile {
return []RequestFile{
{
Name: "media",
File: config.Media,
},
}
}
func (EditMessageMediaConfig) method() string { func (EditMessageMediaConfig) method() string {
return "editMessageMedia" return "editMessageMedia"
} }
func (config EditMessageMediaConfig) params() (Params, error) { func (config EditMessageMediaConfig) params() (Params, error) {
return config.BaseEdit.params() params, err := config.BaseEdit.params()
if err != nil {
return params, err
}
err = params.AddInterface("media", prepareInputMediaParam(config.Media, 0))
return params, err
}
func (config EditMessageMediaConfig) files() []RequestFile {
return prepareInputMediaFile(config.Media, 0)
} }
// EditMessageReplyMarkupConfig allows you to modify the reply markup // EditMessageReplyMarkupConfig allows you to modify the reply markup
@ -892,9 +894,9 @@ func (config WebhookConfig) params() (Params, error) {
} }
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)
return params, nil return params, err
} }
func (config WebhookConfig) name() string { func (config WebhookConfig) name() string {
@ -1177,9 +1179,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.
@ -1492,12 +1494,10 @@ func (config UploadStickerConfig) params() (Params, error) {
} }
func (config UploadStickerConfig) files() []RequestFile { func (config UploadStickerConfig) files() []RequestFile {
return []RequestFile{ return []RequestFile{{
{ Name: "png_sticker",
Name: "png_sticker", File: config.PNGSticker,
File: config.PNGSticker, }}
},
}
} }
// NewStickerSetConfig allows creating a new sticker set. // NewStickerSetConfig allows creating a new sticker set.
@ -1715,56 +1715,13 @@ func (config MediaGroupConfig) params() (Params, error) {
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)
newMedia := make([]interface{}, len(config.Media)) err := params.AddInterface("media", prepareInputMediaForParams(config.Media))
copy(newMedia, config.Media)
for idx, media := range config.Media { return params, err
switch m := media.(type) {
case InputMediaPhoto:
switch m.Media.(type) {
case string, FileBytes, FileReader:
m.Media = fmt.Sprintf("attach://file-%d", idx)
newMedia[idx] = m
}
case InputMediaVideo:
switch m.Media.(type) {
case string, FileBytes, FileReader:
m.Media = fmt.Sprintf("attach://file-%d", idx)
newMedia[idx] = m
}
}
}
params.AddInterface("media", newMedia)
return params, nil
} }
func (config MediaGroupConfig) files() []RequestFile { func (config MediaGroupConfig) files() []RequestFile {
files := []RequestFile{} return prepareInputMediaForFiles(config.Media)
for idx, media := range config.Media {
switch m := media.(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,
})
}
}
}
return files
} }
// DiceConfig allows you to send a random dice roll to Telegram. // DiceConfig allows you to send a random dice roll to Telegram.
@ -1818,3 +1775,115 @@ func (config SetMyCommandsConfig) params() (Params, error) {
return params, err return params, err
} }
// prepareInputMediaParam evaluates a single InputMedia and determines if it
// needs to be modified for a successful upload. If it returns nil, then the
// value does not need to be included in the params. Otherwise, it will return
// the same type as was originally provided.
//
// The idx is used to calculate the file field name. If you only have a single
// file, 0 may be used. It is formatted into "attach://file-%d" for the primary
// media and "attach://file-%d-thumb" for thumbnails.
//
// It is expected to be used in conjunction with prepareInputMediaFile.
func prepareInputMediaParam(inputMedia interface{}, idx int) interface{} {
switch m := inputMedia.(type) {
case InputMediaPhoto:
switch m.Media.(type) {
case string, FileBytes, FileReader:
m.Media = fmt.Sprintf("attach://file-%d", idx)
}
return m
case InputMediaVideo:
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,
})
}
}
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
}

View File

@ -1126,6 +1126,7 @@ 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
Thumb interface{}
Width int `json:"width,omitempty"` Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"` Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"` Duration int `json:"duration,omitempty"`