El día de hoy te voy a enseñar a comunicar un Bot de Telegram con una aplicación web programada usando JavaScript. Vas a aprender a enviar un botón desde el Bot de Telegram; cuando el usuario haga clic en ese botón se va a abrir una aplicación web (Telegram Mini App) y después vas a poder enviar datos desde JavaScript de vuelta al Bot.
Básicamente vamos a ver cómo conectar una aplicación web de JavaScript con un Bot de Telegram enviando información del Bot a la Mini web app y de la aplicación web al Bot de Telegram.
Para abrir una aplicación web en la app de Telegram necesitamos colocarla como acción de un ReplyKeyboardMarkup, mismo que es un arreglo de KeyboardButton. Vamos a definir la propiedad text para el contenido del botón y web_app con la propiedad url según WebAppInfo.
En Golang con la librería go-telegram queda como se ve a continuación. Tú puedes usar cualquier lenguaje de programación y librería, solo es cuestión de usar los métodos correctos de la API.
if update.Message.Text == "/registrar_notificacion" {
b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: update.Message.Chat.ID,
Text: "Webapp",
ReplyMarkup: models.ReplyKeyboardMarkup{
Keyboard: [][]models.KeyboardButton{
{
{
Text: "Por favor toca el botón para abrir la webapp",
WebApp: &models.WebAppInfo{
URL: "https://parzibyte.github.io/ejemplos-javascript/webapp-telegram/index.html?rutas=W3sibm9tYnJlIjoiTmV3IERvbmsgQ2l0eSIsImlkIjoxfSx7Im5vbWJyZSI6IkxvbiBMb24gUmFuY2giLCJpZCI6Mn1d&version=2",
},
},
},
},
ResizeKeyboard: true,
OneTimeKeyboard: true,
},
})
}
Al enviar ese mensaje desde un Bot de Telegram, el usuario verá un botón para abrir la aplicación web:
La URL de la WebApp debe ser pública y contar con certificado SSL. Todo será manejado con JavaScript del lado del cliente.
La URL del ejemplo es:
https://parzibyte.github.io/ejemplos-javascript/webapp-telegram/index.html?rutas=W3sibm9tYnJlIjoiTmV3IERvbmsgQ2l0eSIsImlkIjoxfSx7Im5vbWJyZSI6IkxvbiBMb24gUmFuY2giLCJpZCI6Mn1d&version=2
Fíjate en que yo le estoy pasando dos parámetros en la URL: rutas
y version
. La versión es para saltar la caché en caso de que exista, y las rutas son un arreglo de objetos primero codificados como JSON y luego codificados como Base64.
Tengo un arreglo de objetos:
[
{ "nombre": "New Donk City", "id": 1 },
{ "nombre": "Lon Lon Ranch", "id": 2 },
]
Los codifico como JSON y el resultado es:
'[{"nombre":"New Donk City","id":1},{"nombre":"Lon Lon Ranch","id":2}]'
Luego codifico eso a base64 y tengo:
W3sibm9tYnJlIjoiTmV3IERvbmsgQ2l0eSIsImlkIjoxfSx7Im5vbWJyZSI6IkxvbiBMb24gUmFuY2giLCJpZCI6Mn1d
De este modo puedo pasar los datos del Bot de Telegram hacia la aplicación web, todo colocado directamente en la URL.
Estoy codificando los datos en base64 para que sean amigables con la URL. Esta cadena de datos puede ser traída de cualquier lugar y puedes armarla a partir de los datos de tu Bot o de una base de datos.
Por ejemplo, ya que estamos usando Go podemos traer los datos de MySQL, codificarlos como JSON y luego como base64 para pasarlos a la URL.
Pasemos a la programación de la Mini web app de Telegram. En este caso podemos usar JavaScript que se va a ejecutar en el navegador web.
Gracias a URLSearchParams podemos leer y obtener los datos pasados desde el Bot usando JavaScript. Ya en la WebApp hacemos el proceso inverso: leemos la variable de la URL, decodificamos el base64 y decodificamos el JSON.
En este ejemplo estoy usando ese arreglo para llenar 2 selects. Justamente en este punto es en donde tenemos la comunicación del Bot de Telegram hacia la aplicación web.
const rutasEnBase64 = new URLSearchParams(window.location.search).get("rutas");
if (rutasEnBase64) {
const rutas = JSON.parse(atob(rutasEnBase64));
for (const ruta of rutas) {
$rutaOrigen.appendChild(Object.assign(document.createElement("option"), {
value: ruta.id,
text: ruta.nombre,
}));
$rutaDestino.appendChild(Object.assign(document.createElement("option"), {
value: ruta.id,
text: ruta.nombre,
}));
}
}
Al abrir la Mini App podremos notar que los datos fueron pasados correctamente:
Ya vimos cómo pasar datos del Bot a la app de JS y leer esos datos, ahora veamos cómo enviar datos desde JavaScript hacia el Bot sin usar la API de Bots para enviar un mensaje desde JS, lo haremos usando la propia librería de Telegram para las web apps.
Para ello debes incluir el siguiente script:
<script src="https://telegram.org/js/telegram-web-app.js"></script>
Y cuando quieras enviar datos de vuelta al bot, invoca a Telegram.WebApp.sendData("aquí los datos");
Al invocar a sendData
la aplicación web será cerrada y los datos serán enviados al Bot en donde ya puedes manejarlos. Volviendo a nuestro ejemplo, yo estoy solicitando la hora de inicio, fin, radio en metros y días de una notificación.
Para enviar esos datos estoy usando JSON de nuevo y lo estoy haciendo en el clic de un botón:
$enviar.addEventListener("click", () => {
// Enviar datos de vuelta al bot
const payload = JSON.stringify({
idRutaOrigen: parseInt($rutaOrigen.value),
idRutaDestino: parseInt($rutaDestino.value),
inicio: $inicio.value,
fin: $fin.value,
radio: $radio.valueAsNumber,
dias: ["lunes", "martes", "miercoles", "jueves", "viernes", "sabado", "domingo"].filter(nombreDia => {
const $elemento = document.querySelector("#" + nombreDia);
return $elemento.checked;
}).join(","),
});
console.log({payload});
Telegram.WebApp.sendData(payload);
});
Al final estoy invocando a sendData
con el payload
, que será mi objeto con todos los datos codificado como JSON.
Hasta este punto ya vimos cómo enviar datos desde un Bot de Telegram a una Mini App, cómo leerlos en la aplicación web y cómo enviar datos desde la webapp hasta el Bot de Telegram.
Falta una cosa: recibir y manejar los datos en el Bot. En este caso los datos van a estar en message.web_app_data.data
. Si quisieras saber cuál es el texto del botón que los activó puedes acceder a message.web_app_data.button_text
.
Lo que yo estoy haciendo es simplemente volver a enviar un mensaje al usuario indicando los datos que fueron enviados desde la Mini Web App.
Esto no es obligatorio, aquí bien podrías validar y guardar los datos o actuar según el contenido de los mismos, no es obligatorio enviar los datos recibidos de vuelta al usuario, yo lo hago para depurar.
if update.Message.WebAppData != nil {
b.SendMessage(ctx, &bot.SendMessageParams{
ChatID: update.Message.Chat.ID,
Text: fmt.Sprintf("Los datos recibidos por la webapp son %s", update.Message.WebAppData.Data),
})
}
El código completo de Go lo dejo en GitHub.
Instala las dependencias con go mod tidy
, configura tu token y después compila con go build
. Finalmente ejecuta el binario resultante.
En cuanto al código de la aplicación web puedes revisarlo en mi repositorio de ejemplos con JavaScript.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.