Alojamiento: Heroku
Asumimos que tienes los conocimientos básicos sobre la creación de bots usando grammY. Si aún no estás preparado, ¡no dudes en dirigirte a nuestra amigable Guía! :cohete:
Este tutorial te guiará en cómo desplegar un bot de Telegram en Heroku usando webhooks o long polling. También asumimos que ya tienes una cuenta en Heroku.
Requisitos previos
Primero, instala algunas dependencias:
# Crear un directorio de proyecto.
mkdir grammy-bot
cd grammy-bot
npm init --y
# Instalar las dependencias principales.
npm install grammy express
# Instala las dependencias de desarrollo.
npm install -D typescript @types/express @types/node
# Crear la configuración de TypeScript.
npx tsc --init
2
3
4
5
6
7
8
9
10
11
12
13
Almacenaremos nuestros archivos TypeScript dentro de una carpeta src
, y nuestros archivos compilados en una carpeta dist
. Crea las carpetas en el directorio raíz del proyecto. Luego, dentro de la carpeta src
, crea un nuevo archivo llamado bot
. Nuestra estructura de carpetas debería ser así:
.
├── node_modules/
├── dist/
├── src/
│ └── bot.ts
├── package.json
├── package-lock.json
└── tsconfig.json
Después, abre tsconfig
y cámbialo para usar esta configuración:
{
"compilerOptions": {
"target": "ESNEXT",
"module": "ESNext", // [!code hl] // cambiado de commonjs a 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
Debido a que la opción module
anterior se ha establecido de commonjs
a esnext
, tenemos que añadir "type":
a nuestro package
. Nuestro package
debería ser ahora similar a esto:
{
"name": "grammy-bot",
"version": "0.0.1",
"description": "",
"main": "dist/app.js",
"type": "module", // [!code hl] // añadir propiedad "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
Como hemos mencionado anteriormente, tenemos dos opciones para recibir datos de Telegram: los webhooks y el long polling. ¡Puedes aprender más sobre las dos ventajas y luego decidir cuál es la adecuada en estos increíbles consejos!
Webhooks
Si decides usar el long polling en su lugar, puedes saltarte esta sección y pasar a la sección sobre long polling. 🚀
En resumen, a diferencia del long polling, los webhooks no se ejecutan continuamente para comprobar los mensajes entrantes de Telegram. Esto reducirá la carga del servidor y nos ahorrará un montón de horas de dyno, especialmente si utiliza el plan Eco. 😁
Bien, ¡continuemos! ¿Recuerdas que hemos creado bot
antes? No vamos a volcar todo el código allí, y dejar la codificación del bot hasta usted. En su lugar, vamos a hacer que app
sea nuestro principal punto de entrada. Eso significa que cada vez que Telegram (o cualquier otra persona) visite nuestro sitio, express
decide qué parte de tu servidor será responsable de manejar la petición. Esto es útil cuando estás desplegando tanto el sitio web como el bot en el mismo dominio. Además, al dividir los códigos en diferentes archivos, hace que nuestro código se vea ordenado. ✨
Express y su Middleware
Ahora crea app
dentro de la carpeta src
y escribe este código dentro:
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 () => {
// ¡Asegúrate de que es `https` y no `http`!
await bot.api.setWebhook(`https://${domain}/${secretPath}`);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Echemos un vistazo a nuestro código anterior:
process
: Recuerda, ¡nunca almacenes credenciales en nuestro código! Para crear variables de entorno en Heroku, dirígete a esta guía..env secret
: Puede ser nuestroPath BOT
o cualquier cadena aleatoria. Es una buena práctica ocultar la ruta de nuestro bot, tal y como se explica en Telegram (https://_TOKEN core )..telegram .org /bots /api #setwebhook
⚡ Optimización (opcional)
bot
en la línea 14 siempre se ejecutará cuando Heroku inicie su servidor de nuevo. Para los bots de bajo tráfico, esto será para cada solicitud. Sin embargo, no necesitamos que este código se ejecute cada vez que llega una petición. Por lo tanto, podemos eliminar esta parte completamente, y ejecutar el GET
sólo una vez manualmente. Abre este enlace en tu navegador web después de desplegar nuestro bot:
https://api.telegram.org/bot<bot_token>/setWebhook?url=<webhook_url>
Ten en cuenta que algunos navegadores requieren que codifiques manualmente (https://webhook
antes de pasarla. Por ejemplo, si tenemos el token bot abcd:
y la URL https://
, entonces nuestro enlace debería tener este aspecto:
https://api.telegram.org/botabcd:1234/setWebhook?url=https%3A%2F%2Fgrammybot.herokuapp.com%2Fsecret_path
Optimización (opcional)
Utilice Webhook Reply para una mayor eficiencia.
Creando bot.ts
(Webhooks)
Siguiente paso, dirígete a bot
:
import { Bot } from "grammy";
const token = process.env.BOT_TOKEN;
if (!token) throw new Error("Falta BOT_TOKEN.");
export const bot = new Bot(token);
bot.command("start", (ctx) => ctx.reply("¡Hola!"));
bot.on("message", (ctx) => ctx.reply("¡Tengo otro mensaje!"));
2
3
4
5
6
7
8
9
Bien. Ya hemos terminado de codificar nuestros archivos principales. Pero antes de ir a los pasos de despliegue, podemos optimizar nuestro bot un poco. Como siempre, esto es opcional.
⚡ Optimización (opcional)
Cada vez que tu servidor se inicie, grammY solicitará información sobre el bot a Telegram para proporcionarla en el objeto de contexto bajo ctx
. Podemos establecer la información sobre el bot para evitar un exceso de llamadas a get
.
Abre este enlace
https://
en tu navegador web favorito. Se recomienda usar Firefox ya que muestra muy bien el formatoapi .telegram .org /bot<bot _token> /get Me json
.Cambia nuestro código en la línea 4 de arriba y rellena el valor de acuerdo con los resultados de
get
:Me tsconst token = process.env.BOT_TOKEN; if (!token) throw new Error("Falta 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
¡Genial! ¡Es hora de preparar nuestro entorno de despliegue! ¡Directamente a la Sección de Despliegue todo el mundo! 💪
Long Polling
Su script se ejecutará de forma continua cuando utilice el sondeo largo
A menos que sepa cómo manejar este comportamiento, asegúrese de que tiene suficientes horas de dyno.
¿Considerar el uso de webhooks? Vaya a la sección webhooks. 🚀
Usar long polling en tu servidor no es siempre una mala idea. A veces, es adecuado para los bots de recolección de datos que no necesitan responder rápidamente y manejar muchos datos. Si quieres hacerlo una vez por hora, puedes hacerlo fácilmente. Eso es algo que no puedes controlar con los webhooks. Si tu bot se inunda de mensajes, verás muchas peticiones de webhooks, sin embargo, puedes limitar más fácilmente la tasa de actualizaciones a procesar con un long polling.
Creando bot.ts
(Long Polling)
Abramos el archivo bot
que hemos creado anteriormente. Que contenga estas líneas de código:
import { Bot } from "grammy";
const token = process.env.BOT_TOKEN;
if (!token) throw new Error("Falta BOT_TOKEN");
const bot = new Bot(token);
bot.command(
"start",
(ctx) => ctx.reply("¡Estoy corriendo en Heroku usando long polling!"),
);
bot.start();
2
3
4
5
6
7
8
9
10
11
12
13
¡Ya está! Estamos listos para desplegarlo. Bastante sencillo, ¿verdad? 😃 Si crees que es demasiado fácil, ¡consulta nuestra Lista de verificación de despliegue! 🚀
Despliegue
No… nuestro Rocket Bot no está listo para ser lanzado todavía. ¡Completa estas etapas primero!
Compilar Archivos
Ejecute este código en su terminal para compilar los archivos TypeScript a JavaScript:
npx tsc
Si se ejecuta con éxito y no imprime ningún error, nuestros archivos compilados deberían estar en la carpeta dist
con extensiones .js
.
Configurar el Procfile
Por el momento, Heroku
tiene varios tipos de dynos. Dos de ellos son:
Web dynos:
Web dynos son dynos del proceso “web” que reciben tráfico HTTP de los routers. Este tipo de dyno tiene un tiempo de espera de 30 segundos para ejecutar código. Además, se suspenderá si no hay ninguna petición que atender en un periodo de 30 minutos. Este tipo de dyno es muy adecuado para los webhooks.
Worker dynos:
Worker dynos se utilizan normalmente para trabajos en segundo plano. NO tiene un tiempo de espera, y NO dormirá si no maneja ninguna petición web. Se adapta al long polling.
Crear un archivo llamado Procfile
sin extensión de archivo en el directorio raíz de nuestro proyecto. Por ejemplo, Procfile
y procfile
no son válidos. A continuación, escriba este formato de código de una sola línea:
<tipo de dyno>: <omando para ejecutar nuestro archivo de entrada principal>
Para nuestro caso debería serlo:
web: node dist/app.js
worker: node dist/bot.js
Configurar Git
Vamos a desplegar nuestro bot usando Git y Heroku Cli. Aquí está el enlace para la instalación:
Suponiendo que ya los tienes en tu máquina, y tienes una terminal abierta en la raíz del directorio de nuestro proyecto. Ahora inicializa un repositorio git local ejecutando este código en tu terminal:
git init
A continuación, tenemos que evitar que los archivos innecesarios lleguen a nuestro servidor de producción, en este caso Heroku
. Crea un archivo llamado .gitignore
en la raíz del directorio de nuestro proyecto. Luego añade esta lista:
node_modules/
src/
tsconfig.json
2
3
Nuestra estructura final de carpetas debería tener este aspecto:
.
├── .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
Confirmar los archivos a nuestro repositorio git:
git add .
git commit -m "My first commit"
2
Configurar un Heroku Remote
Si ya has creado una aplicación Heroku, pasa el nombre de tu Aplicación existente
en <mi
a continuación, y ejecuta el código. De lo contrario, ejecute Nueva aplicación
.
heroku create
git remote -v
2
heroku git:remote -a <myApp>
Despliegue del código
Finalmente, pulsa el botón rojo y ¡despega! 🚀
git push heroku main
Si no funciona, es probable que nuestra rama git no sea main
sino master
. Pulsa este botón azul en su lugar:
git push heroku master