Telegram-бот для скачивания видео на grammY
grammY — современный Node.js-фреймворк для Telegram-ботов, и бот «ссылка → видео» на нём — около тридцати строк, когда разрешение — это HTTP-вызов. Это руководство — фильтр entity, ловящий ссылки, методы ответа, принимающие URL напрямую, понятные пользователю фразы ошибок и единственное, что стоит кешировать.
Обновлено
Установка
Только grammY; fetch встроен в Node 18+. Никакого стека скрейпинга и браузера, который нужно держать живым.
Terminalnpm install grammy
Разрешите ссылку
Один GET с ключом в заголовке Authorization. AbortSignal.timeout не даёт медленному источнику держать ваш обработчик. Эндпоинт определяет платформу по URL, бот не ветвится по домену.
JavaScriptconst API = "https://api.saveapi.org/v1/download";
async function resolve(link) {
const res = await fetch(API + "?url=" + encodeURIComponent(link), {
headers: { Authorization: "Bearer sk_live_xxxx" },
signal: AbortSignal.timeout(30_000),
});
return res.json();
}Ловите ссылки и отвечайте медиа
message::url срабатывает на любое сообщение с entity типа URL; ctx.entities("url") отдаёт текст. replyWithVideo и replyWithPhoto принимают URL медиа напрямую — Telegram скачает сам. Проверяйте medias[0].type: слайдшоу или карусель — изображения, не видео.
JavaScriptimport { Bot } from "grammy";
const bot = new Bot(process.env.BOT_TOKEN);
bot.on("message::url", async (ctx) => {
const link = ctx.entities("url")[0].text;
const data = await resolve(link);
if (!data.success) {
return ctx.reply(EXPLAIN[data.error.code] ?? "Try another link.");
}
const media = data.medias[0];
return media.type === "video"
? ctx.replyWithVideo(media.url, { caption: data.meta?.title ?? "" })
: ctx.replyWithPhoto(media.url);
});
bot.start();Объясняйте ошибки, с которыми люди сталкиваются
Пользователи целый день вставляют закрытые посты и мёртвые ссылки. Сопоставьте стабильные коды с фразами: бот, говорящий «этот аккаунт закрыт», получает другую ссылку, бот, говорящий «ошибка», — злое сообщение. Закрытые и отсутствующие стоят 0.1 кредита, а не полные 1.5.
JavaScriptconst EXPLAIN = {
PRIVATE_CONTENT: "That account is private — I can only fetch public posts.",
MEDIA_NOT_FOUND: "That post has no media, or it was deleted.",
UNSUPPORTED_PLATFORM: "I do not know that site yet.",
QUOTA_EXCEEDED: "Out of credits.",
UPSTREAM_TIMEOUT: "The source was slow. Send the link again.",
};Кешируйте file_id Telegram, а не URL медиа
После первой отправки Telegram даёт file_id; его повторная отправка ничего не загружает и не тратит кредиты. URL медиа хранить не стоит — ссылки CDN подписаны и истекают за часы.
Вопросы перед началом
- Бот может отправлять файлы больше 50 МБ?
- Не загрузкой; 50 МБ — потолок Telegram для загрузки ботом. Передача URL медиа позволяет Telegram забрать файл самому, а повторная отправка по file_id не зависит от размера.
- Работает с webhook?
- Да — обработчик тот же; меняется только bot.start() на webhookCallback. Сохраните таймаут fetch: у webhook-обработчика тоже есть дедлайн.
- А если Telegram отказывается забирать URL?
- Скачайте байты сами и отправьте как InputFile. Чаще всего это Instagram и всегда — медиагруппы; оставьте это запасным путём, а не основным.
Платформы, использованные здесь
Другие руководства
Запустите это руководство со своим ключом
Ключ за минуту. 1 000 бесплатных кредитов, без карты и без срока.