Хостинг: 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 --init
2
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", // переход с 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", // добавьте свойство "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.js
worker: node dist/bot.js
Установка Git
Мы собираемся развернуть нашего бота с помощью Git и Heroku Cli. Вот ссылка для установки:
Предположим, что они уже установлены на вашем компьютере, и у вас открыт терминал в корневой директории нашего проекта. Теперь инициализируйте локальный git-репозиторий, выполнив этот код в терминале:
git init
Далее нам нужно предотвратить попадание ненужных файлов на наш рабочий сервер, в данном случае Heroku
. Создайте файл с именем .gitignore
в корневой директории нашего проекта. Затем добавьте в него этот список:
node_modules/
src/
tsconfig.json
2
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 -v
2
heroku git:remote -a <myApp>
Развертывание кода
Наконец, нажмите красную кнопку и взлетайте! 🚀
git push heroku main
Если это не сработает, то, скорее всего, наша ветка git не main
, а master
. Вместо этого нажмите эту синюю кнопку:
git push heroku master