Хостинг: Heroku
Мы предполагаем, что у вас есть базовые знания о создании ботов с помощью grammY. Если вы еще не готовы, не стесняйтесь заглянуть в наш дружественный Гайд! 🚀
В этом руководстве мы расскажем вам, как развернуть Telegram бота на Heroku с помощью вебхуков или long polling. Мы также предполагаем, что у вас уже есть аккаунт на Heroku.
Необходимые условия
Сначала установите некоторые зависимости:
# Создайте директорию проекта.
mkdir grammy-bot
cd grammy-bot
npm init --y
# Установите основные зависимости.
npm install grammy express
# Установите зависимости для разработки.
npm install -D typescript @types/express @types/node
# Создайте конфиг TypeScript.
npx tsc --init2
3
4
5
6
7
8
9
10
11
12
13
Мы будем хранить наши файлы TypeScript в папке src, а скомпилированные файлы — в папке dist. Создайте эти папки в корневом каталоге проекта. Затем в папке src создайте новый файл с именем bot. Теперь наша структура папок должна выглядеть следующим образом:
.
├── node_modules/
├── dist/
├── src/
│ └── bot.ts
├── package.json
├── package-lock.json
└── tsconfig.jsonПосле этого откройте файл tsconfig и измените его, чтобы использовать эту конфигурацию:
{
"compilerOptions": {
"target": "ESNEXT",
"module": "ESNext", // [!code hl] // переход с commonjs на esnext
"lib": ["ES2021"],
"outDir": "./dist/",
"strict": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src"]
}2
3
4
5
6
7
8
9
10
11
12
13
14
Поскольку опция module выше была установлена с commonjs на esnext, мы должны добавить "type": в наш package. Теперь наш package должен быть похож на этот:
{
"name": "grammy-bot",
"version": "0.0.1",
"description": "",
"main": "dist/app.js",
"type": "module", // [!code hl] // добавьте свойство "type": "module"
"scripts": {
"dev-build": "tsc"
},
"author": "",
"license": "ISC",
"dependencies": {
"grammy": "^1.2.0",
"express": "^4.17.1"
},
"devDependencies": {
"typescript": "^4.3.5",
"@types/express": "^4.17.13",
"@types/node": "^16.3.1"
},
"keywords": []
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Как уже говорилось, у нас есть два варианта получения данных из Telegram: вебхуки и long polling. Вы можете узнать больше о преимуществах обоих вариантов, а затем решить, какой из них подходит, в этих потрясающих советах!
Вебхуки
Если вы решите использовать long polling вместо этого, вы можете пропустить этот раздел и перейти к разделу о long polling. 🚀
Вкратце, в отличие от long polling, вебхук не будет запускаться постоянно для проверки входящих сообщений от Telegram. Это снизит нагрузку на сервер и сэкономит нам много dyno часов, особенно если вы используете тарифный план Eco. 😁
Хорошо, давайте продолжим! Помните, мы ранее создали bot? Мы не будем сбрасывать туда весь код и оставим программирование бота на ваше усмотрение. Вместо этого мы сделаем app нашей основной точкой входа. Это означает, что каждый раз, когда Telegram (или кто-то другой) заходит на наш сайт, express решает, какая часть вашего сервера будет отвечать за обработку запроса. Это полезно, когда вы разворачиваете и сайт, и бота в одном домене. Кроме того, разделение кодов по разным файлам позволяет сделать наш код более аккуратным. ✨
Express и его middleware
Теперь создайте app в папке src и напишите в нем этот код:
import express from "express";
import { webhookCallback } from "grammy";
import { bot } from "./bot.js";
const domain = String(process.env.DOMAIN);
const secretPath = String(process.env.BOT_TOKEN);
const app = express();
app.use(express.json());
app.use(`/${secretPath}`, webhookCallback(bot, "express"));
app.listen(Number(process.env.PORT), async () => {
// Убедитесь, что это `https`, а не `http`!
await bot.api.setWebhook(`https://${domain}/${secretPath}`);
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
Давайте посмотрим на наш код выше:
process: Помните, НИКОГДА не храните учетные данные в коде! Для создания переменных окружения в Heroku, перейдите по этому руководству..env secret: Это может быть нашPath BOTили любая произвольная строка. Лучше всего скрывать путь нашего бота, как объясняет Telegram._TOKEN
⚡ Оптимизация (необязательно)
bot в строке 14 будет запускаться всегда, когда Heroku снова запустит ваш сервер. Для ботов с низким трафиком это будет происходить при каждом запросе. Однако нам не нужно, чтобы этот код выполнялся каждый раз, когда приходит запрос. Поэтому мы можем полностью удалить эту часть и выполнять GET только один раз вручную. Откройте эту ссылку в браузере после развертывания нашего бота:
https://api.telegram.org/bot<токен>/setWebhook?url=<webhook_url>Обратите внимание, что некоторые браузеры требуют вручную закодировать webhook перед передачей. Например, если у нас есть токен бота abcd: и URL https://, то наша ссылка должна выглядеть следующим образом:
https://api.telegram.org/botabcd:1234/setWebhook?url=https%3A%2F%2Fgrammybot.herokuapp.com%2Fsecret_path⚡ Оптимизация (необязательно)
Используйте Webhook Reply для большей эффективности.
Создание bot.ts (вебхуки)
Следующим шагом перейдите к файлу bot:
import { Bot } from "grammy";
const token = process.env.BOT_TOKEN;
if (!token) throw new Error("BOT_TOKEN не установлен");
export const bot = new Bot(token);
bot.command("start", (ctx) => ctx.reply("Привет!"));
bot.on("message", (ctx) => ctx.reply("Получил сообщение!"));2
3
4
5
6
7
8
9
Отлично! Теперь мы закончили написание наших основных файлов. Но прежде чем перейти к шагам развертывания, мы можем немного оптимизировать нашего бота. Как обычно, это необязательно.
⚡ Оптимизация (необязательно)
При каждом запуске вашего сервера, grammY будет запрашивать информацию о боте у Telegram, чтобы предоставить ее в объект контекста в ctx. Мы можем заранее обозначить всю информацию о боте, чтобы предотвратить чрезмерные вызовы get.
Откройте эту ссылку
https://в вашем любимом браузере. Рекомендуем Firefox, так как он хорошо справляется с отображениемapi .telegram .org /bot<токен> /get Me JSON.Измените наш код в строке 4 выше и заполните значение в соответствии с результатами, полученными от
get:Me tsconst token = process.env.BOT_TOKEN; if (!token) throw new Error("BOT_TOKEN не установлен"); export const bot = new Bot(token, { botInfo: { id: 111111111, is_bot: true, first_name: "xxxxxxxxx", username: "xxxxxxbot", can_join_groups: true, can_read_all_group_messages: false, supports_inline_queries: false, }, });1
2
3
4
5
6
7
8
9
10
11
12
13
14
Круто! Пришло время подготовить среду развертывания! Всем прямая дорога в раздел Развертывания! 💪
Long Polling
Ваш код будет выполняться непрерывно при использовании long polling
Если вы не знаете, как справиться с таким поведением, убедитесь, что у вас достаточно dyno часов.
Рассмотрите возможность использования вебхуков? Перейдите к разделу вебхуки. 🚀
Использование long polling на вашем сервере — не всегда плохая идея. Иногда он подходит для ботов, собирающих данные, которым не нужно быстро реагировать и обрабатывать большое количество данных. Если вы хотите делать это раз в час, вы можете легко это сделать. Это то, что вы не можете контролировать с помощью вебхуков. Если ваш бот будет переполнен сообщениями, вы увидите много запросов вебхука, однако вы можете более легко ограничить скорость обработки обновлений с помощью long polling.
Создание bot.ts (Long Polling)
Откроем файл bot, который мы создали ранее. Пусть он содержит следующие строки кода:
import { Bot } from "grammy";
const token = process.env.BOT_TOKEN;
if (!token) throw new Error("BOT_TOKEN не установлен");
const bot = new Bot(token);
bot.command(
"start",
(ctx) => ctx.reply("Я работаю на Heroku, используя long polling!"),
);
bot.start();2
3
4
5
6
7
8
9
10
11
12
13
Вот и все! Мы готовы к развертыванию. Довольно просто, правда? 😃 Если вам кажется, что это слишком просто, посмотрите наши советы по развертыванию! 🚀
Развертывание
Нет… наш Шикарный бот еще не готов к запуску. Сначала завершите эти этапы!
Компиляция файлов
Запустите этот код в терминале, чтобы скомпилировать файлы TypeScript в JavaScript:
npx tscЕсли он запустится успешно и не выдаст никаких ошибок, наши скомпилированные файлы должны оказаться в папке dist с расширением .js.
Установите Procfile
На данный момент у Heroku есть несколько типов dyno. Два из них:
Web dynos:
Web dynos — это dynos процесса “web”, которые получают HTTP-трафик от роутеров. Этот вид дино имеет таймаут в 30 секунд на выполнение кода. Кроме того, он отключится, если в течение 30 минут не будет обработано ни одного запроса. Этот тип дино вполне подходит для вебхуков.
Worker dynos
Worker dynos обычно используются для фоновых заданий. У них нет таймаута, и они НЕ отключатся, если не обработают никаких запросов. Он подходит для long polling.
Создайте файл с именем Procfile без расширения в корневой директории нашего проекта. Например, Procfile и procfile не подходят. Затем напишите код в формате одной строки:
<тип dynos>: <наш главный файл>Для нашего случая должно быть так:
web: node dist/app.jsworker: node dist/bot.jsУстановка Git
Мы собираемся развернуть нашего бота с помощью Git и Heroku Cli. Вот ссылка для установки:
Предположим, что они уже установлены на вашем компьютере, и у вас открыт терминал в корневой директории нашего проекта. Теперь инициализируйте локальный git-репозиторий, выполнив этот код в терминале:
git initДалее нам нужно предотвратить попадание ненужных файлов на наш рабочий сервер, в данном случае Heroku. Создайте файл с именем .gitignore в корневой директории нашего проекта. Затем добавьте в него этот список:
node_modules/
src/
tsconfig.json2
3
Теперь наша окончательная структура папок должна выглядеть следующим образом:
.
├── .git/
├── node_modules/
├── dist/
│ ├── bot.js
│ └── app.js
├── src/
│ ├── bot.ts
│ └── app.ts
├── package.json
├── package-lock.json
├── tsconfig.json
├── Procfile
└── .gitignore.
├── .git/
├── node_modules/
├── dist/
│ └── bot.js
├── src/
│ └── bot.ts
├── package.json
├── package-lock.json
├── tsconfig.json
├── Procfile
└── .gitignoreЗафиксируйте файлы в нашем git-репозитории:
git add .
git commit -m "My first commit"2
Настройте удаленный доступ к Heroku
Если вы уже создали Heroku app, передайте имя вашего Existing app в <my ниже, затем запустите код. В противном случае запустите New app.
heroku create
git remote -v2
heroku git:remote -a <myApp>Развертывание кода
Наконец, нажмите красную кнопку и взлетайте! 🚀
git push heroku mainЕсли это не сработает, то, скорее всего, наша ветка git не main, а master. Вместо этого нажмите эту синюю кнопку:
git push heroku master