Initial work on improving docs.
This commit is contained in:
parent
2f7211a708
commit
5be25266b5
12 changed files with 674 additions and 0 deletions
108
docs/internals/uploading-files.md
Normal file
108
docs/internals/uploading-files.md
Normal file
|
@ -0,0 +1,108 @@
|
|||
# Uploading Files
|
||||
|
||||
To make files work as expected, there's a lot going on behind the scenes. Make
|
||||
sure to read through the [Files](../getting-started/files.md) section in
|
||||
Getting Started first as we'll be building on that information.
|
||||
|
||||
This section only talks about file uploading. For non-uploaded files such as
|
||||
URLs and file IDs, you just need to pass a string.
|
||||
|
||||
## Fields
|
||||
|
||||
Let's start by talking about how the library represents files as part of a
|
||||
Config.
|
||||
|
||||
### Static Fields
|
||||
|
||||
Most endpoints use static file fields. For example, `sendPhoto` expects a single
|
||||
file named `photo`. All we have to do is set that single field with the correct
|
||||
value (either a string or multipart file). Methods like `sendDocument` take two
|
||||
file uploads, a `document` and a `thumb`. These are pretty straightforward.
|
||||
|
||||
Remembering that the `Fileable` interface only requires one method, let's
|
||||
implement it for `DocumentConfig`.
|
||||
|
||||
```go
|
||||
func (config DocumentConfig) files() []RequestFile {
|
||||
// We can have multiple files, so we'll create an array. We also know that
|
||||
// there always is a document file, so initialize the array with that.
|
||||
files := []RequestFile{{
|
||||
Name: "document",
|
||||
File: config.File,
|
||||
}}
|
||||
|
||||
// We'll only add a file if we have one.
|
||||
if config.Thumb != nil {
|
||||
files = append(files, RequestFile{
|
||||
Name: "thumb",
|
||||
File: config.Thumb,
|
||||
})
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
```
|
||||
|
||||
Telegram also supports the `attach://` syntax (discussed more later) for
|
||||
thumbnails, but there's no reason to make things more complicated.
|
||||
|
||||
### Dynamic Fields
|
||||
|
||||
Of course, not everything can be so simple. Methods like `sendMediaGroup`
|
||||
can accept many files, and each file can have custom markup. Using a static
|
||||
field isn't possible because we need to specify which field is attached to each
|
||||
item. Telegram introduced the `attach://` syntax for this.
|
||||
|
||||
Let's follow through creating a new media group with string and file uploads.
|
||||
|
||||
First, we start by creating some `InputMediaPhoto`.
|
||||
|
||||
```go
|
||||
photo := tgbotapi.NewInputMediaPhoto("tests/image.jpg")
|
||||
url := tgbotapi.NewInputMediaPhoto(tgbotapi.FileURL("https://i.imgur.com/unQLJIb.jpg"))
|
||||
```
|
||||
|
||||
This created a new `InputMediaPhoto` struct, with a type of `photo` and the
|
||||
media interface that we specified.
|
||||
|
||||
We'll now create our media group with the photo and URL.
|
||||
|
||||
```go
|
||||
mediaGroup := NewMediaGroup(ChatID, []interface{}{
|
||||
photo,
|
||||
url,
|
||||
})
|
||||
```
|
||||
|
||||
A `MediaGroupConfig` stores all of the media in an array of interfaces. We now
|
||||
have all of the data we need to upload, but how do we figure out field names for
|
||||
uploads? We didn't specify `attach://unique-file` anywhere.
|
||||
|
||||
When the library goes to upload the files, it looks at the `params` and `files`
|
||||
for the Config. The params are generated by transforming the file into a value
|
||||
more suitable for uploading, file IDs and URLs are untouched but uploaded types
|
||||
are all changed into `attach://file-%d`. When collecting a list of files to
|
||||
upload, it names them the same way. This creates a nearly transparent way of
|
||||
handling multiple files in the background without the user having to consider
|
||||
what's going on.
|
||||
|
||||
## Library Processing
|
||||
|
||||
If at some point in the future new upload types are required, let's talk about
|
||||
where the current types are used.
|
||||
|
||||
Upload types are defined in `configs.go`. Where possible, type aliases are
|
||||
preferred. Structs can be used when multiple fields are required.
|
||||
|
||||
The main usage of the upload types happens in `UploadFiles`. It switches on each
|
||||
file's type in order to determine how to upload it. Files that aren't uploaded
|
||||
(file IDs, URLs) are converted back into strings and passed through as strings
|
||||
into the correct field. Uploaded types are processed as needed (opening files,
|
||||
etc.) and written into the form using a copy approach in a goroutine to reduce
|
||||
memory usage.
|
||||
|
||||
In addition to `UploadFiles`, there's more processing of upload types in the
|
||||
`prepareInputMediaParam` and `prepareInputMediaFile` functions. These look at
|
||||
the `InputMedia` types to determine which files are uploaded and which are
|
||||
passed through as strings. They only need to be aware of which files need to be
|
||||
replaced with `attach://` fields.
|
Loading…
Add table
Add a link
Reference in a new issue