diff --git a/bot_test.go b/bot_test.go index a2e35d6..a001dcd 100644 --- a/bot_test.go +++ b/bot_test.go @@ -12,19 +12,21 @@ import ( ) const ( - TestToken = "153667468:AAHlSHlMqSt1f_uFmVRJbm5gntu2HI4WW8I" - ChatID = 76918703 - ReplyToMessageID = 35 - ExistingPhotoFileID = "AgADAgADw6cxG4zHKAkr42N7RwEN3IFShCoABHQwXEtVks4EH2wBAAEC" - ExistingDocumentFileID = "BQADAgADOQADjMcoCcioX1GrDvp3Ag" - ExistingAudioFileID = "BQADAgADRgADjMcoCdXg3lSIN49lAg" - ExistingVoiceFileID = "AwADAgADWQADjMcoCeul6r_q52IyAg" - ExistingVideoFileID = "BAADAgADZgADjMcoCav432kYe0FRAg" - ExistingStickerFileID = "BQADAgADcwADjMcoCbdl-6eB--YPAg" + TestToken = "153667468:AAHlSHlMqSt1f_uFmVRJbm5gntu2HI4WW8I" + ChatID = 76918703 + ReplyToMessageID = 35 + ExistingPhotoFileID = "AgADAgADw6cxG4zHKAkr42N7RwEN3IFShCoABHQwXEtVks4EH2wBAAEC" + ExistingDocumentFileID = "BQADAgADOQADjMcoCcioX1GrDvp3Ag" + ExistingAudioFileID = "BQADAgADRgADjMcoCdXg3lSIN49lAg" + ExistingVoiceFileID = "AwADAgADWQADjMcoCeul6r_q52IyAg" + ExistingVideoFileID = "BAADAgADZgADjMcoCav432kYe0FRAg" + ExistingVideoNoteFileID = "DQADAgADdQAD70cQSUK41dLsRMqfAg" + ExistingStickerFileID = "BQADAgADcwADjMcoCbdl-6eB--YPAg" ) func getBot(t *testing.T) (*tgbotapi.BotAPI, error) { bot, err := tgbotapi.NewBotAPI(TestToken) + bot.Debug = true if err != nil { t.Error(err) @@ -312,6 +314,34 @@ func TestSendWithExistingVideo(t *testing.T) { } } +func TestSendWithNewVideoNote(t *testing.T) { + bot, _ := getBot(t) + + msg := tgbotapi.NewVideoNoteUpload(ChatID, 240, "tests/videonote.mp4") + msg.Duration = 10 + + _, err := bot.Send(msg) + + if err != nil { + t.Error(err) + t.Fail() + } +} + +func TestSendWithExistingVideoNote(t *testing.T) { + bot, _ := getBot(t) + + msg := tgbotapi.NewVideoNoteShare(ChatID, 240, ExistingVideoNoteFileID) + msg.Duration = 10 + + _, err := bot.Send(msg) + + if err != nil { + t.Error(err) + t.Fail() + } +} + func TestSendWithNewSticker(t *testing.T) { bot, _ := getBot(t) diff --git a/configs.go b/configs.go index 132ea9d..1e64568 100644 --- a/configs.go +++ b/configs.go @@ -468,6 +468,57 @@ func (config VideoConfig) method() string { return "sendVideo" } +// VideoNoteConfig contains information about a SendVideoNote request. +type VideoNoteConfig struct { + BaseFile + Duration int + Length int +} + +// values returns a url.Values representation of VideoNoteConfig. +func (config VideoNoteConfig) values() (url.Values, error) { + v, err := config.BaseChat.values() + if err != nil { + return v, err + } + + v.Add(config.name(), config.FileID) + if config.Duration != 0 { + v.Add("duration", strconv.Itoa(config.Duration)) + } + + // Telegram API seems to have a bug, if no length is provided or it is 0, it will send an error response + if config.Length != 0 { + v.Add("length", strconv.Itoa(config.Length)) + } + + return v, nil +} + +// params returns a map[string]string representation of VideoNoteConfig. +func (config VideoNoteConfig) params() (map[string]string, error) { + params, _ := config.BaseFile.params() + + if config.Length != 0 { + params["length"] = strconv.Itoa(config.Length) + } + if config.Duration != 0 { + params["duration"] = strconv.Itoa(config.Duration) + } + + return params, nil +} + +// name returns the field name for the VideoNote. +func (config VideoNoteConfig) name() string { + return "video_note" +} + +// method returns Telegram API method name for sending VideoNote. +func (config VideoNoteConfig) method() string { + return "sendVideoNote" +} + // VoiceConfig contains information about a SendVoice request. type VoiceConfig struct { BaseFile diff --git a/debug.test b/debug.test new file mode 100755 index 0000000..5d99a83 Binary files /dev/null and b/debug.test differ diff --git a/helpers.go b/helpers.go index 476eeeb..627f656 100644 --- a/helpers.go +++ b/helpers.go @@ -194,6 +194,37 @@ func NewVideoShare(chatID int64, fileID string) VideoConfig { } } +// NewVideoNoteUpload creates a new video note uploader. +// +// chatID is where to send it, file is a string path to the file, +// FileReader, or FileBytes. +func NewVideoNoteUpload(chatID int64, length int, file interface{}) VideoNoteConfig { + return VideoNoteConfig{ + BaseFile: BaseFile{ + BaseChat: BaseChat{ChatID: chatID}, + File: file, + UseExisting: false, + }, + Length: length, + } +} + +// NewVideoNoteShare shares an existing video. +// You may use this to reshare an existing video without reuploading it. +// +// chatID is where to send it, fileID is the ID of the video +// already uploaded. +func NewVideoNoteShare(chatID int64, length int, fileID string) VideoNoteConfig { + return VideoNoteConfig{ + BaseFile: BaseFile{ + BaseChat: BaseChat{ChatID: chatID}, + FileID: fileID, + UseExisting: true, + }, + Length: length, + } +} + // NewVoiceUpload creates a new voice uploader. // // chatID is where to send it, file is a string path to the file, diff --git a/tests/videonote.mp4 b/tests/videonote.mp4 new file mode 100644 index 0000000..649d16f Binary files /dev/null and b/tests/videonote.mp4 differ diff --git a/types.go b/types.go index 70960ae..31f70e0 100644 --- a/types.go +++ b/types.go @@ -135,6 +135,7 @@ type Message struct { Photo *[]PhotoSize `json:"photo"` // optional Sticker *Sticker `json:"sticker"` // optional Video *Video `json:"video"` // optional + VideoNote *VideoNote `json:"video_note"` // optional Voice *Voice `json:"voice"` // optional Caption string `json:"caption"` // optional Contact *Contact `json:"contact"` // optional @@ -263,6 +264,15 @@ type Video struct { FileSize int `json:"file_size"` // optional } +// VideoNote contains information about a video. +type VideoNote struct { + FileID string `json:"file_id"` + Length int `json:"length"` + Duration int `json:"duration"` + Thumbnail *PhotoSize `json:"thumb"` // optional + FileSize int `json:"file_size"` // optional +} + // Voice contains information about a voice. type Voice struct { FileID string `json:"file_id"`