Обробка файлів
Боти 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
не можна використовувати для завантаження файлів, але він буде однаковим для будь-якого файлу в усіх ботів.
Отримання файлів
Ви можете обробляти файли так само, як і будь-які інші повідомлення. Наприклад, якщо ви хочете обробляти голосові повідомлення, ви можете зробити це:
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; // шлях до файлу на сервері Bot API
await ctx.reply("Завантажте власний файл: " + path);
});
2
3
4
5
6
7
8
9
10
11
12
13
Передача власного file
до get
В обʼєкті контексту get
є скороченим методом і отримуватиме інформацію для файлу в поточному повідомленні. Якщо ви хочете отримати інший файл під час обробки повідомлення, використовуйте натомість ctx
.
Перегляньте скорочення
:
таmedia :
для запитів фільтрування, якщо ви хочете отримувати будь-які файли.file
Викликавши get
, ви можете використати повернутий file
(шлях до файлу), щоб завантажити файл за цією URL-адресою https://
, де <токен
має бути замінено токеном вашого бота.
Якщо ви запускаєте власний сервер Bot API, file
замість цього буде абсолютним шляхом до файлу, який вказує на файл на вашому локальному диску. У цьому випадку вам більше не потрібно нічого завантажувати, оскільки сервер Bot API завантажить файл за вас при виклику get
.
Плагін файлів
grammY не постачається в комплекті з власним завантажувачем файлів, але ви можете встановити офіційний плагін файлів. Він дає змогу завантажувати файли за допомогою await file
і отримувати URL-адресу для завантаження за допомогою file
.
Надсилання файлів
Боти Telegram можуть надсилати файли трьома способами:
- Через
file
, тобто відправивши файл за допомогою ідентифікатора, який уже відомий боту._id - Через URL-адресу, тобто передаючи загальнодоступну URL-адресу файлу, яку Telegram завантажує та надсилає для вас.
- Через завантаження власного файлу.
У всіх випадках методи, які потрібно викликати, мають однакові назви. Залежно від того, який із трьох способів ви оберете для надсилання файлу, параметри цих функцій відрізнятимуться. Наприклад, щоб надіслати фотографію, ви можете використати ctx
або send
, якщо ви використовуєте ctx
або bot
.
Ви можете надсилати інші типи файлів, просто перейменувавши метод і змінивши тип даних, які ви йому передаєте. Щоб надіслати відео, ви можете використовувати ctx
. Так само й для документа: ctx
. Ну, ідею ви зрозуміли.
Давайте розглянемо три способи надсилання файлу.
Через file_id
або URL-адресу
Перші два методи прості: ви просто передаєте відповідне значення як string
, і готово.
// Надсилаємо через 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
(довідка API grammY).
// Надсилаємо файл через локальний шлях
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
// Надсилаємо 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 у багатьох методах API. Якщо можливо, вам слід віддати перевагу надсиланню файлу через 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
Додавання підпису
Під час надсилання файлів ви можете вказати додаткові параметри в обʼєкті параметрів типу Other
, як пояснювалося раніше. Наприклад, це дозволяє надсилати підписи.
// Надсилаємо фотографію з локального файлу із підписом "photo.jpg" користувачу з id 12345.
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 МБ.
Як згадувалося в попередньому розділі, ваш бот може працювати з великими файлами, тільки якщо докласти певні додаткові зусилля. Якщо ви хочете підтримувати завантаження в Telegram файлів до 2000 МБ (максимальний розмір файлу в Telegram) і завантаження файлів до себе будь-якого розміру (4000 МБ з Telegram Premium), вам необхідно розмістити власний сервер Bot API на додачу до розміщення вашого бота.
Розміщення власного сервера Bot API не має нічого спільного з grammY. Однак grammY підтримує всі методи, необхідні для налаштування вашого бота для використання власного сервера Bot API.