Обработка файлов
Боты Telegram могут не только отправлять и получать текстовые сообщения, но и многие другие виды сообщений, например, фото и видео. Это предполагает работу с файлами, которые прикрепляются к сообщениям.
Как работают файлы для ботов Telegram
Этот раздел объясняет, как работают файлы для ботов Telegram. Если вы хотите узнать, как можно работать с файлами в grammY, прокрутите страницу вниз, чтобы узнать о скачивании и загрузке файлов.
Файлы хранятся отдельно от сообщений. Файл на серверах Telegram идентифицируется по file
, который представляет собой длинную строку символов. Например, она может выглядеть как AgADBAADZRAx
.
Идентификаторы для полученных файлов
Боты получают только идентификаторы файлов. Если они хотят получить содержимое файла, они должны запросить его напрямую.
Когда ваш бот получает сообщение с файлом, на самом деле он получает не все данные файла, а только file
. Если ваш бот действительно хочет загрузить файл, то он может сделать это, вызвав метод get
(документация Telegram Bot API). Этот метод позволяет загрузить файл, сконструировав специальный временный URL. Обратите внимание, что этот URL гарантированно будет действителен только в течение 60 минут, после чего его срок действия может истечь. В этом случае вы можете просто вызвать get
снова.
Файлы могут быть получены вот так.
Идентификаторы для отправленных файлов
Отправляя файлы, вы также получаете идентификатор файла.
Всякий раз, когда ваш бот отправляет сообщение с файлом, он получает информацию об отправленном сообщении, включая file
отправленного файла. Это означает, что все файлы, которые видит бот, как при отправке, так и при получении, будут иметь file
. Если вы хотите работать с файлом после того, как ваш бот его увидит, вы всегда должны хранить его file
.
Используйте идентификаторы файлов всегда, когда это возможно. Они очень эффективны.
Когда бот отправляет сообщение, он может указать file
, который он уже видел. Это позволит ему отправить идентифицированный файл, без необходимости загружать данные для него.
Вы можете использовать один и тот же file
сколько угодно раз, так что вы можете отправить один и тот же файл в пять разных чатов, используя один и тот же file
. Однако вы должны убедиться, что используете правильный метод - например, вы не можете использовать file
, который идентифицирует фотографию, при вызове send
.
Файлы могут быть отправлены вот так.
Идентификаторы которые могут вас удивить
Идентификаторы файлов работают только для вашего бота. Если другой бот использует ваши идентификаторы файлов, он может случайно сработать, случайно разбиться и случайно убить невинных котят. 🐱 → 💀
Каждый бот имеет свой собственный набор file
для файлов, к которым он может получить доступ. Вы не сможете надежно использовать file
от бота вашего друга для доступа к файлу с помощью вашего бота. Каждый бот будет использовать разные идентификаторы для одного и того же файла. Это означает, что вы не можете просто угадать file
и получить доступ к файлу какого-то случайного человека, потому что Telegram отслеживает, какие file
действительны для вашего бота.
Использование других file
Обратите внимание, что в некоторых случаях технически возможно, что file
от другого бота работает корректно. Однако, использование чужих file
опасно, так как они могут перестать работать в любой момент без предупреждения. Поэтому всегда убеждайтесь, что все file
, которые вы используете, были изначально предназначены для вашего бота.
У файла может быть несколько идентификаторов.
С другой стороны, возможно, что бот в конечном итоге видит один и тот же файл, идентифицированный разными file
. Это означает, что вы не можете полагаться на сравнение file
для проверки того, являются ли два файла одним и тем же. Если вам нужно идентифицировать один и тот же файл в течение долгого времени (или для нескольких ботов), вы должны использовать значение file
, которое ваш бот получает вместе с каждым file
.
Значение file
не может быть использовано для загрузки файлов, но оно будет одинаковым для любого файла у всех ботов.
Получение файлов
Вы можете работать с файлами так же, как и с любыми другими сообщениями. Например, если вы хотите прослушать голосовые сообщения, вы можете сделать следующее:
bot.on("message:voice", async (ctx) => {
const voice = ctx.msg.voice;
const duration = voice.duration; // в секундах
await ctx.reply(`Ваше сообщение длиной ${duration} секунд(ы).`);
const fileId = voice.file_id;
await ctx.reply("Идентификатор файла вашего голосового сообщения: " + fileId);
const file = await ctx.getFile(); // Действует не менее 1 часа
const path = file.file_path; // путь к файлу на API сервере бота
await ctx.reply("Скачайте свой собственный файл снова: " + path);
});
2
3
4
5
6
7
8
9
10
11
12
13
Передача пользовательского идентификатора файла в getFile
На объекте контекста get
является краткой записью, и будет получать информацию о файле текущего сообщения. Если вы хотите получить другой файл при работе с сообщением, используйте ctx
вместо этого.
Посмотрите краткие записи
:
иmedia :
для фильтровую запросов, если вы хотите получить любой тип файла.file
Вызвав get
, вы можете использовать возвращаемый file
для загрузки файла по этому URL https://
, где <токен>
должен быть заменен на ваш токен бота.
Если вы запускаете свой собственный API сервер, то file
будет представлять собой абсолютный путь к файлу, который указывает на файл на вашем локальном диске. В этом случае вам больше не нужно ничего скачивать, так как сервер Bot API скачает файл за вас при вызове get
.
Плагин Files
grammY не поставляется в комплекте с собственным загрузчиком файлов, но вы можете установить официальный плагин files. Это позволит вам загружать файлы через await file
, а также получать URL для их загрузки через file
.
Отправка файлов
У ботов Telegram есть три способа отправки файлов:
- Через
file
, то есть отправляя файл по идентификатору, который уже известен боту._id - Через URL, т.е. передав публичный URL файла, который Telegram скачает и отправит за вас.
- Через загрузку собственного файла.
Во всех случаях методы, которые вам нужно вызвать, называются одинаково. В зависимости от того, какой из трех способов отправки файла вы выберете, параметры этих функций будут отличаться. Например, чтобы отправить фотографию, вы можете использовать ctx
(или send
, если вы используете ctx
или bot
).
Вы можете отправлять файлы других типов, просто переименовав метод и изменив тип передаваемых в него данных. Чтобы отправить видео, вы можете использовать ctx
. То же самое касается и документа: ctx
. Вы поняли суть.
Давайте разберемся, что представляют собой эти три способа отправки файла.
Через file_id
или URL
Первые два метода просты: вы просто передаете соответствующее значение в виде строки
, и все готово.
// Отправка через file_id.
await ctx.replyWithPhoto(existingFileId);
// Отправка через URL.
await ctx.replyWithPhoto("https://grammy.dev/images/grammY.png");
// В качестве альтернативы можно использовать bot.api.sendPhoto() или ctx.api.sendPhoto().
2
3
4
5
6
7
Загрузка ваших собственных файлов
В grammY есть хорошая поддержка загрузки собственных файлов. Для этого нужно импортировать и использовать класс Input
(документация grammY API).
// Отправка файла по локальному пути
await ctx.replyWithPhoto(new InputFile("/tmp/picture.jpg"));
// В качестве альтернативы используйте bot.api.sendPhoto() или ctx.api.sendPhoto()
2
3
4
Конструктор Input
принимает не только пути к файлам, но и потоки, объекты Buffer
, асинхронные итераторы и, в зависимости от вашей платформы - многое другое, или функцию, которая создает любую из этих вещей. Все, что вам нужно помнить, это: создайте экземпляр Input
и передайте его в любой метод для отправки файла. Экземпляры Input
можно передавать всем методам, которые принимают отправку файлов путем загрузки.
Вот несколько примеров того, как можно создать Input
.
Загрузка файлов с диска
Если у вас уже есть файл, хранящийся на вашем компьютере, вы можете позволить grammY загрузить этот файл.
import { createReadStream } from "fs";
// Отправка локального файла.
new InputFile("/path/to/file");
// Отправка потоком.
new InputFile(createReadStream("/path/to/file"));
2
3
4
5
6
7
// Отправка локального файла.
new InputFile("/path/to/file");
// Отправка из экземпляра `Deno.FsFile`.
new InputFile(await Deno.open("/path/to/file"));
2
3
4
5
Загрузка сырых бинарных данных
Вы также можете отправить объект Buffer
или итератор, который выдает объекты Buffer
. На Deno вы также можете отправлять объекты Blob
.
// Отправьте буфер или массив байтов.
const buffer = Uint8Array.from([65, 66, 67]);
new InputFile(buffer); // "ABC"
// Отправьте итерируемый объект.
new InputFile(function* () {
// "ABCABCABCABC"
for (let i = 0; i < 4; i++) yield buffer;
});
2
3
4
5
6
7
8
// Send a blob.
const blob = new Blob(["ABC"], { type: "text/plain" });
new InputFile(blob);
// Отправьте буфер или массив байтов.
const buffer = Uint8Array.from([65, 66, 67]);
new InputFile(buffer); // "ABC"
// Отправьте итерируемый объект.
new InputFile(function* () {
// "ABCABCABCABC"
for (let i = 0; i < 4; i++) yield buffer;
});
2
3
4
5
6
7
8
9
10
11
Загрузка и повторая отправка файлов
Вы даже можете заставить grammY загрузить файл из Интернета. При этом файл не будет сохранен на диске. Вместо этого grammY будет только передавать данные, сохраняя в памяти лишь небольшой фрагмент. Это очень эффективно.
Обратите внимание, что Telegram поддерживает загрузку файла многими способами. Если возможно, вы должны предпочесть отправить файл по URL, а не использовать
Input
для передачи содержимого файла через ваш сервер.File
// Загрузите файл и передайте ответ в Telegram.
new InputFile(new URL("https://grammy.dev/images/grammY.png"));
new InputFile({ url: "https://grammy.dev/images/grammY.png" }); // равносильно
2
3
Добавление подписи
При отправке файлов вы можете указать дополнительные параметры в объекте options типа Other
, точно так же, как объяснялось ранее. Например, это позволяет отправлять подписи.
// Отправьте фотографию из локального файла пользователю с ID 12345 с подписью "photo.jpg".
await bot.api.sendPhoto(12345, new InputFile("/path/to/photo.jpg"), {
caption: "photo.jpg",
});
2
3
4
Как всегда, как и все остальные методы API, вы можете отправлять файлы через ctx
(самый простой), ctx
или bot
.
Лимиты размеров файла
Сам grammY может отправлять файлы без ограничений по размеру, однако Telegram ограничивает размер файлов, как описано здесь. Это означает, что ваш бот не сможет скачивать файлы размером более 20 МБ или загружать файлы размером более 50 МБ. Некоторые комбинации имеют еще более строгие ограничения, например, фотографии, отправленные по URL (5 МБ).
Как уже упоминалось в предыдущем разделе, ваш бот может работать с большими файлами, приложив некоторые дополнительные усилия. Если вы хотите поддерживать загрузку файлов размером до 2000 МБ (максимальный размер файла в Telegram) и скачивание файлов любого размера (4000 МБ с Telegram Премиум), вам необходимо разместить собственный API сервер в дополнение к хостингу вашего бота.
Хостинг собственного API сервера бота сам по себе не имеет никакого отношения к grammY. Однако grammY поддерживает все методы, необходимые для настройки вашего бота на использование собственного API сервера.