diff --git a/file.go b/file.go index ecfd218..7162886 100644 --- a/file.go +++ b/file.go @@ -11,7 +11,7 @@ import ( // This object represents the contents of a file to be uploaded. // Must be posted using multipart/form-data in the usual way that files are uploaded via the browser. type InputFile interface { - Attach(name string, data map[string]FileReader) (string, error) + InputFileOrString justFiles() } @@ -19,7 +19,7 @@ type InputFile interface { // // This object represents a publicly accessible URL to be reused, or a file_id already available on telegram servers. type InputString interface { - Attach(name string, data map[string]FileReader) (string, error) + InputFileOrString justStrings() } @@ -28,56 +28,74 @@ type InputString interface { // This object represents the contents of a file to be uploaded, or a publicly accessible URL to be reused. // Files must be posted using multipart/form-data in the usual way that files are uploaded via the browser. type InputFileOrString interface { - Attach(name string, data map[string]FileReader) (string, error) + Attach(name string, data map[string]FileReader) error + getValue() string } var ( - _ InputFileOrString = FileString{} - _ InputString = FileString{} + _ InputFileOrString = &FileString{} + _ InputString = &FileString{} - _ InputFileOrString = FileReader{} - _ InputFile = FileReader{} + _ InputFileOrString = &FileReader{} + _ InputFile = &FileReader{} ) type FileString struct { Value string } -func (f FileString) justStrings() {} +func (f *FileString) justStrings() {} -func (f FileString) MarshalJSON() ([]byte, error) { - return json.Marshal(f.Value) +func (f *FileString) MarshalJSON() ([]byte, error) { + return json.Marshal(f.getValue()) } -func (f FileString) Attach(_ string, _ map[string]FileReader) (string, error) { - return f.Value, nil +func (f *FileString) Attach(_ string, _ map[string]FileReader) error { + return nil +} + +func (f *FileString) getValue() string { + return f.Value } type FileReader struct { Name string Data io.Reader + + value string +} + +func (f *FileReader) MarshalJSON() ([]byte, error) { + return json.Marshal(f.getValue()) } var ErrAttachmentKeyAlreadyExists = errors.New("key already exists") -func (f FileReader) Attach(key string, data map[string]FileReader) (string, error) { +func (f *FileReader) justFiles() {} + +func (f *FileReader) Attach(key string, data map[string]FileReader) error { if _, ok := data[key]; ok { - return "", ErrAttachmentKeyAlreadyExists + return ErrAttachmentKeyAlreadyExists } - data[key] = f - return "attach://" + key, nil + f.value = key + data[key] = *f + return nil } -func (f FileReader) justFiles() {} +// getValue returns the file attach reference for the relevant multipart form. +// Calling getValue is only valid after having called Attach on this struct. +func (f *FileReader) getValue() string { + return "attach://" + f.value +} // InputFileByURL is used to send a file on the internet via a publicly accessible HTTP URL. func InputFileByURL(url string) InputFileOrString { - return FileString{Value: url} + return &FileString{Value: url} } // InputFileByID is used to send a file that is already present on telegram's servers, using its telegram file_id. func InputFileByID(fileID string) InputFileOrString { - return FileString{Value: fileID} + return &FileString{Value: fileID} } // InputFileByReader is used to send a file by a reader interface; such as a filehandle from os.Open(), or from a byte @@ -96,5 +114,5 @@ func InputFileByID(fileID string) InputFileOrString { // // m, err := b.SendDocument(, gotgbot.InputFileByReader("file.txt", strings.NewReader("Some file contents")), nil) func InputFileByReader(name string, r io.Reader) InputFile { - return FileReader{Name: name, Data: r} + return &FileReader{Name: name, Data: r} } diff --git a/gen_methods.go b/gen_methods.go index 3e6e1cd..005eb8a 100755 --- a/gen_methods.go +++ b/gen_methods.go @@ -2925,11 +2925,11 @@ func (bot *Bot) SendAnimation(chatId int64, animation InputFileOrString, opts *S data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if animation != nil { - key, err := animation.Attach("animation", data) + err := animation.Attach("animation", data) if err != nil { return nil, err } - v["animation"] = key + v["animation"] = animation.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -2946,11 +2946,11 @@ func (bot *Bot) SendAnimation(chatId int64, animation InputFileOrString, opts *S v["height"] = strconv.FormatInt(opts.Height, 10) } if opts.Thumbnail != nil { - key, err := opts.Thumbnail.Attach("thumbnail", data) + err := opts.Thumbnail.Attach("thumbnail", data) if err != nil { return nil, err } - v["thumbnail"] = key + v["thumbnail"] = opts.Thumbnail.getValue() } v["caption"] = opts.Caption v["parse_mode"] = opts.ParseMode @@ -3042,11 +3042,11 @@ func (bot *Bot) SendAudio(chatId int64, audio InputFileOrString, opts *SendAudio data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if audio != nil { - key, err := audio.Attach("audio", data) + err := audio.Attach("audio", data) if err != nil { return nil, err } - v["audio"] = key + v["audio"] = audio.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -3068,11 +3068,11 @@ func (bot *Bot) SendAudio(chatId int64, audio InputFileOrString, opts *SendAudio v["performer"] = opts.Performer v["title"] = opts.Title if opts.Thumbnail != nil { - key, err := opts.Thumbnail.Attach("thumbnail", data) + err := opts.Thumbnail.Attach("thumbnail", data) if err != nil { return nil, err } - v["thumbnail"] = key + v["thumbnail"] = opts.Thumbnail.getValue() } v["disable_notification"] = strconv.FormatBool(opts.DisableNotification) v["protect_content"] = strconv.FormatBool(opts.ProtectContent) @@ -3335,11 +3335,11 @@ func (bot *Bot) SendDocument(chatId int64, document InputFileOrString, opts *Sen data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if document != nil { - key, err := document.Attach("document", data) + err := document.Attach("document", data) if err != nil { return nil, err } - v["document"] = key + v["document"] = document.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -3347,11 +3347,11 @@ func (bot *Bot) SendDocument(chatId int64, document InputFileOrString, opts *Sen v["message_thread_id"] = strconv.FormatInt(opts.MessageThreadId, 10) } if opts.Thumbnail != nil { - key, err := opts.Thumbnail.Attach("thumbnail", data) + err := opts.Thumbnail.Attach("thumbnail", data) if err != nil { return nil, err } - v["thumbnail"] = key + v["thumbnail"] = opts.Thumbnail.getValue() } v["caption"] = opts.Caption v["parse_mode"] = opts.ParseMode @@ -3895,11 +3895,11 @@ func (bot *Bot) SendPhoto(chatId int64, photo InputFileOrString, opts *SendPhoto data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if photo != nil { - key, err := photo.Attach("photo", data) + err := photo.Attach("photo", data) if err != nil { return nil, err } - v["photo"] = key + v["photo"] = photo.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -4114,11 +4114,11 @@ func (bot *Bot) SendSticker(chatId int64, sticker InputFileOrString, opts *SendS data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if sticker != nil { - key, err := sticker.Attach("sticker", data) + err := sticker.Attach("sticker", data) if err != nil { return nil, err } - v["sticker"] = key + v["sticker"] = sticker.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -4296,11 +4296,11 @@ func (bot *Bot) SendVideo(chatId int64, video InputFileOrString, opts *SendVideo data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if video != nil { - key, err := video.Attach("video", data) + err := video.Attach("video", data) if err != nil { return nil, err } - v["video"] = key + v["video"] = video.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -4317,11 +4317,11 @@ func (bot *Bot) SendVideo(chatId int64, video InputFileOrString, opts *SendVideo v["height"] = strconv.FormatInt(opts.Height, 10) } if opts.Thumbnail != nil { - key, err := opts.Thumbnail.Attach("thumbnail", data) + err := opts.Thumbnail.Attach("thumbnail", data) if err != nil { return nil, err } - v["thumbnail"] = key + v["thumbnail"] = opts.Thumbnail.getValue() } v["caption"] = opts.Caption v["parse_mode"] = opts.ParseMode @@ -4405,11 +4405,11 @@ func (bot *Bot) SendVideoNote(chatId int64, videoNote InputFileOrString, opts *S data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if videoNote != nil { - key, err := videoNote.Attach("video_note", data) + err := videoNote.Attach("video_note", data) if err != nil { return nil, err } - v["video_note"] = key + v["video_note"] = videoNote.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -4423,11 +4423,11 @@ func (bot *Bot) SendVideoNote(chatId int64, videoNote InputFileOrString, opts *S v["length"] = strconv.FormatInt(opts.Length, 10) } if opts.Thumbnail != nil { - key, err := opts.Thumbnail.Attach("thumbnail", data) + err := opts.Thumbnail.Attach("thumbnail", data) if err != nil { return nil, err } - v["thumbnail"] = key + v["thumbnail"] = opts.Thumbnail.getValue() } v["disable_notification"] = strconv.FormatBool(opts.DisableNotification) v["protect_content"] = strconv.FormatBool(opts.ProtectContent) @@ -4501,11 +4501,11 @@ func (bot *Bot) SendVoice(chatId int64, voice InputFileOrString, opts *SendVoice data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if voice != nil { - key, err := voice.Attach("voice", data) + err := voice.Attach("voice", data) if err != nil { return nil, err } - v["voice"] = key + v["voice"] = voice.getValue() } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId @@ -4722,11 +4722,11 @@ func (bot *Bot) SetChatPhoto(chatId int64, photo InputFile, opts *SetChatPhotoOp data := map[string]FileReader{} v["chat_id"] = strconv.FormatInt(chatId, 10) if photo != nil { - key, err := photo.Attach("photo", data) + err := photo.Attach("photo", data) if err != nil { return false, err } - v["photo"] = key + v["photo"] = photo.getValue() } var reqOpts *RequestOpts @@ -5346,11 +5346,11 @@ func (bot *Bot) SetStickerSetThumbnail(name string, userId int64, format string, v["format"] = format if opts != nil { if opts.Thumbnail != nil { - key, err := opts.Thumbnail.Attach("thumbnail", data) + err := opts.Thumbnail.Attach("thumbnail", data) if err != nil { return false, err } - v["thumbnail"] = key + v["thumbnail"] = opts.Thumbnail.getValue() } } @@ -5429,11 +5429,11 @@ func (bot *Bot) SetWebhook(url string, opts *SetWebhookOpts) (bool, error) { v["url"] = url if opts != nil { if opts.Certificate != nil { - key, err := opts.Certificate.Attach("certificate", data) + err := opts.Certificate.Attach("certificate", data) if err != nil { return false, err } - v["certificate"] = key + v["certificate"] = opts.Certificate.getValue() } v["ip_address"] = opts.IpAddress if opts.MaxConnections != 0 { @@ -5800,11 +5800,11 @@ func (bot *Bot) UploadStickerFile(userId int64, sticker InputFile, stickerFormat data := map[string]FileReader{} v["user_id"] = strconv.FormatInt(userId, 10) if sticker != nil { - key, err := sticker.Attach("sticker", data) + err := sticker.Attach("sticker", data) if err != nil { return nil, err } - v["sticker"] = key + v["sticker"] = sticker.getValue() } v["sticker_format"] = stickerFormat diff --git a/gen_types.go b/gen_types.go index 17dbd11..4cd5de8 100755 --- a/gen_types.go +++ b/gen_types.go @@ -4816,12 +4816,10 @@ func (v InputMediaAnimation) inputMedia() {} func (v InputMediaAnimation) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.Media != nil { - key, err := v.Media.Attach(mediaName, data) + err := v.Media.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.Media = FileString{Value: key} } return json.Marshal(v) @@ -4892,12 +4890,10 @@ func (v InputMediaAudio) inputMedia() {} func (v InputMediaAudio) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.Media != nil { - key, err := v.Media.Attach(mediaName, data) + err := v.Media.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.Media = FileString{Value: key} } return json.Marshal(v) @@ -4962,12 +4958,10 @@ func (v InputMediaDocument) inputMedia() {} func (v InputMediaDocument) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.Media != nil { - key, err := v.Media.Attach(mediaName, data) + err := v.Media.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.Media = FileString{Value: key} } return json.Marshal(v) @@ -5032,12 +5026,10 @@ func (v InputMediaPhoto) inputMedia() {} func (v InputMediaPhoto) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.Media != nil { - key, err := v.Media.Attach(mediaName, data) + err := v.Media.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.Media = FileString{Value: key} } return json.Marshal(v) @@ -5117,12 +5109,10 @@ func (v InputMediaVideo) inputMedia() {} func (v InputMediaVideo) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.Media != nil { - key, err := v.Media.Attach(mediaName, data) + err := v.Media.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.Media = FileString{Value: key} } return json.Marshal(v) @@ -5180,12 +5170,10 @@ type InputSticker struct { func (v InputSticker) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.Sticker != nil { - key, err := v.Sticker.Attach(mediaName, data) + err := v.Sticker.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.Sticker = FileString{Value: key} } return json.Marshal(v) diff --git a/scripts/generate/methods.go b/scripts/generate/methods.go index dcac2ff..c8d344c 100644 --- a/scripts/generate/methods.go +++ b/scripts/generate/methods.go @@ -400,11 +400,11 @@ type readerBranchesData struct { // TODO: Make sure this doesn't allow strings, ONLY readers! const inputFileBranch = ` if {{.GoParam}} != nil { - key, err := {{.GoParam}}.Attach("{{.Name}}", data) + err := {{.GoParam}}.Attach("{{.Name}}", data) if err != nil { return {{.DefaultReturn}}, err } - v["{{.Name}}"] = key + v["{{.Name}}"] = {{.GoParam}}.getValue() }` const inputParamsBranch = ` diff --git a/scripts/generate/types.go b/scripts/generate/types.go index af3e28a..6c5d52a 100644 --- a/scripts/generate/types.go +++ b/scripts/generate/types.go @@ -91,6 +91,7 @@ func generateTypeDef(d APIDescription, tgType TypeDescription) (string, error) { return "", fmt.Errorf("failed to check if type requires special handling: %w", err) } if ok { + // TODO: Investigate if thumbnails need special handling too. err = inputParamsTmpl.Execute(&typeDef, inputParamsMethodData{ Type: tgType.Name, Field: snakeToTitle(fieldName), @@ -758,12 +759,10 @@ type inputParamsMethodData struct { const inputParamsMethod = ` func (v {{.Type}}) InputParams(mediaName string, data map[string]FileReader) ([]byte, error) { if v.{{.Field}} != nil { - key, err := v.{{.Field}}.Attach(mediaName, data) + err := v.{{.Field}}.Attach(mediaName, data) if err != nil { return nil, err } - // Now that we've attached the file as a piece of data, we can pass in its file reference. - v.{{.Field}} = FileString{Value: key} } return json.Marshal(v)