Volver al inicio

Bot MVP para Max.ru: Long Polling y mapeo de respuestas

El artículo describe la creación de un bot de retroalimentación MVP para Max.ru en Node.js usando Long Polling y SQLite. La lógica de mapeo de respuestas se implementa para enrutar las respuestas del administrador. Se proporciona código completo para la inicialización de la BD y el manejo de eventos

Bot para Max.ru: desde la instalación hasta la lógica de respuestas
Advertisement 728x90

Creando un bot de feedback MVP para Max.ru con polling largo y SQLite

Max.ru ofrece a los desarrolladores acceso a su API de bots para crear herramientas interactivas. Para este bot de feedback MVP, utilizamos Node.js con la biblioteca @maxhub/max-bot-api y SQLite. El polling largo permite el desarrollo local sin necesidad de webhooks, servidores ni HTTPS.

El mayor desafío consiste en identificar al cliente cuando el administrador responde. Los mensajes de respuesta incluyen un enlace con el mid del mensaje original, lo que nos permite mapear las respuestas de vuelta a los usuarios mediante la base de datos.

Elección de la pila tecnológica y configuración del proyecto

La biblioteca @maxhub/max-bot-api soporta polling largo de forma nativa, eliminando la necesidad de ngrok o Cloudflare Tunnel durante el desarrollo.

Google AdInline article slot

SQLite es ideal para un MVP: es una base de datos basada en archivos, sin servidor separado, con latencia mínima y manejo consistente de solicitudes.

Instala las dependencias:

npm init -y
npm install @maxhub/max-bot-api sqlite sqlite3 dotenv

Crea un archivo .env:

Google AdInline article slot
BOT_TOKEN=your_token_here
OWNER_ID=12345678

El token se genera en business.max.ru, y OWNER_ID es tu ID de usuario personal en Max.

Inicializando SQLite y estructura de la base de datos

Usa conexión asíncrona y crea la tabla reply_map para el mapeo:

import { open } from 'sqlite';
import sqlite3 from 'sqlite3';

let db;
(async () => {
  db = await open({ filename: './database.sqlite', driver: sqlite3.Database });
  
  await db.exec(`
    CREATE TABLE IF NOT EXISTS reply_map (
      owner_msg_mid TEXT PRIMARY KEY,
      client_user_id INTEGER
    )
  `);
  console.log('Base de datos lista');
})();

Esta tabla almacena el mapeo desde owner_msg_mid hasta client_user_id.

Google AdInline article slot

Manejo de mensajes de los clientes

El evento message_created verifica al remitente. Los mensajes de clientes se reenvían al administrador con formato Markdown:

const ownerId = Number(process.env.OWNER_ID);

bot.on('message_created', async (ctx) => {
  const msg = ctx.message;
  const senderId = msg.sender.user_id;
  const text = msg.body.text;

  if (senderId !== ownerId) {
    
    const forwardText = `📩 **Mensaje de ${msg.sender.first_name}** (ID: ${senderId}):

${text}`;
    
    const sentMsg = await bot.api.sendMessageToUser(ownerId, forwardText, { format: 'markdown' });

    if (sentMsg && sentMsg.body && sentMsg.body.mid) {
        await db.run('INSERT OR REPLACE INTO reply_map (owner_msg_mid, client_user_id) VALUES (?, ?)', 
          [sentMsg.body.mid, senderId]);
    }
    return;
  }
  // lógica de respuesta
});

El mid del mensaje enviado se almacena en reply_map para su posterior enrutamiento.

Lógica de respuesta del administrador

Los mensajes de respuesta contienen link.type = 'reply' y link.message.mid — el ID del mensaje original. Para encontrar al cliente:

  • Si link.type === 'reply': extrae repliedMsgMid, consulta la DB.
  • Envía la respuesta al cliente usando client_user_id.
  • Confirma la recepción al administrador.

Estructura JSON de ejemplo para la respuesta:

{
  "body": { "text": "respuesta", ... },
  "sender": { ... },
  "link": {
    "type": "reply",
    "message": {
      "mid": "mid.mensaje_original..."
    }
  }
}

Beneficios de esta arquitectura

  • Desarrollo local: Ejecuta con npm start — no necesitas puertos ni configuración SSL.
  • Interfaz de respuesta: Los administradores usan la función estándar de respuesta sin problemas.
  • Base de datos sencilla: Un solo archivo (database.sqlite) para copias de seguridad fáciles.
  • Escalabilidad: Migración sencilla a PostgreSQL conforme crece el tráfico.

Conclusiones clave

  • El polling largo simplifica el desarrollo de MVP al eliminar la necesidad de webhooks.
  • La tabla reply_map de SQLite asegura un enrutamiento preciso de las respuestas.
  • El uso de Markdown en los mensajes reenviados añade contexto (nombre del cliente, ID).
  • Respuesta de respaldo: si no hay coincidencia, se usa al último cliente activo.

— Editorial Team

Advertisement 728x90

Leer después