all repos — telegram-bot-api @ f6e575996e5319447140ff9aa4865d70e02e5447

Golang bindings for the Telegram Bot API

docs/internals/uploading-files.md (view raw)

  1# Uploading Files
  2
  3To make files work as expected, there's a lot going on behind the scenes. Make
  4sure to read through the [Files](../getting-started/files.md) section in
  5Getting Started first as we'll be building on that information.
  6
  7This section only talks about file uploading. For non-uploaded files such as
  8URLs and file IDs, you just need to pass a string.
  9
 10## Fields
 11
 12Let's start by talking about how the library represents files as part of a
 13Config.
 14
 15### Static Fields
 16
 17Most endpoints use static file fields. For example, `sendPhoto` expects a single
 18file named `photo`. All we have to do is set that single field with the correct
 19value (either a string or multipart file). Methods like `sendDocument` take two
 20file uploads, a `document` and a `thumb`. These are pretty straightforward.
 21
 22Remembering that the `Fileable` interface only requires one method, let's
 23implement it for `DocumentConfig`.
 24
 25```go
 26func (config DocumentConfig) files() []RequestFile {
 27    // We can have multiple files, so we'll create an array. We also know that
 28    // there always is a document file, so initialize the array with that.
 29	files := []RequestFile{{
 30		Name: "document",
 31		File: config.File,
 32	}}
 33
 34    // We'll only add a file if we have one.
 35	if config.Thumb != nil {
 36		files = append(files, RequestFile{
 37			Name: "thumb",
 38			File: config.Thumb,
 39		})
 40	}
 41
 42	return files
 43}
 44```
 45
 46Telegram also supports the `attach://` syntax (discussed more later) for
 47thumbnails, but there's no reason to make things more complicated.
 48
 49### Dynamic Fields
 50
 51Of course, not everything can be so simple. Methods like `sendMediaGroup`
 52can accept many files, and each file can have custom markup. Using a static
 53field isn't possible because we need to specify which field is attached to each
 54item. Telegram introduced the `attach://` syntax for this.
 55
 56Let's follow through creating a new media group with string and file uploads.
 57
 58First, we start by creating some `InputMediaPhoto`.
 59
 60```go
 61photo := tgbotapi.NewInputMediaPhoto("tests/image.jpg")
 62url := tgbotapi.NewInputMediaPhoto(tgbotapi.FileURL("https://i.imgur.com/unQLJIb.jpg"))
 63```
 64
 65This created a new `InputMediaPhoto` struct, with a type of `photo` and the
 66media interface that we specified.
 67
 68We'll now create our media group with the photo and URL.
 69
 70```go
 71mediaGroup := NewMediaGroup(ChatID, []interface{}{
 72    photo,
 73    url,
 74})
 75```
 76
 77A `MediaGroupConfig` stores all of the media in an array of interfaces. We now
 78have all of the data we need to upload, but how do we figure out field names for
 79uploads? We didn't specify `attach://unique-file` anywhere.
 80
 81When the library goes to upload the files, it looks at the `params` and `files`
 82for the Config. The params are generated by transforming the file into a value
 83more suitable for uploading, file IDs and URLs are untouched but uploaded types
 84are all changed into `attach://file-%d`. When collecting a list of files to
 85upload, it names them the same way. This creates a nearly transparent way of
 86handling multiple files in the background without the user having to consider
 87what's going on.
 88
 89## Library Processing
 90
 91If at some point in the future new upload types are required, let's talk about
 92where the current types are used.
 93
 94Upload types are defined in `configs.go`. Where possible, type aliases are
 95preferred. Structs can be used when multiple fields are required.
 96
 97The main usage of the upload types happens in `UploadFiles`. It switches on each
 98file's type in order to determine how to upload it. Files that aren't uploaded
 99(file IDs, URLs) are converted back into strings and passed through as strings
100into the correct field. Uploaded types are processed as needed (opening files,
101etc.) and written into the form using a copy approach in a goroutine to reduce
102memory usage.
103
104In addition to `UploadFiles`, there's more processing of upload types in the
105`prepareInputMediaParam` and `prepareInputMediaFile` functions. These look at
106the `InputMedia` types to determine which files are uploaded and which are
107passed through as strings. They only need to be aware of which files need to be
108replaced with `attach://` fields.