Vytvoření MVP chatbotu pro Max.ru: zpracování zpětné vazby pomocí Long Polling a SQLite
S platformou Max.ru mají vývojáři přístup k Bot API pro tvorbu nástrojů interakce. Pro MVP chatbotu zpětné vazby se používá Node.js spolu s knihovnou @maxhub/max-bot-api a SQLite. Long Polling umožňuje spouštět bot lokálně bez nastavení webhooks, serveru nebo HTTPS.
Klíčovým výzvou je identifikace uživatele při odpovědi administrátora. Zpráva typu Reply obsahuje odkaz s mid původní zprávy, což umožňuje propojit odpověď s klientem prostřednictvím databáze.
Výběr technologického stacku a příprava projektu
Knihovna @maxhub/max-bot-api podporuje Long Polling od začátku. To vylučuje potřebu ngrok nebo Cloudflare Tunnel při vývoji.
SQLite je vhodné pro MVP: souborová databáze bez samostatného serveru, minimální latence, sériové zpracování požadavků.
Instalace závislostí:
npm init -y
npm install @maxhub/max-bot-api sqlite sqlite3 dotenv
Soubor .env:
BOT_TOKEN=vaš_token_tady
OWNER_ID=12345678
Token generujte na business.max.ru, OWNER_ID je váš osobní ID v Max.
Inicializace SQLite a struktura databáze
Asynchronní připojení s vytvořením tabulky reply_map pro mapování:
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('Databáze je připravena');
})();
Tabulka uchovává vztah owner_msg_mid → client_user_id.
Zpracování zpráv od klienta
Událost message_created ověřuje odesílatele. Zprávy od klientů jsou přesměrovány administrátorovi s formátováním 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 = `📩 **Zpráva od ${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;
}
// logika odpovědí
});
mid odeslané zprávy se uloží do reply_map.
Logika odpovědí administrátora
Zpráva typu Reply obsahuje pole link.type = 'reply' a link.message.mid — ID původní zprávy. Hledání klienta prostřednictvím reply_map:
- Pokud link.type === 'reply': extrahujte repliedMsgMid, dotaz do databáze.
- Odpovězte klientovi podle client_user_id.
- Potvrďte administrátorovi.
Struktura JSON Reply:
{
"body": { "text": "odpověď", ... },
"sender": { ... },
"link": {
"type": "reply",
"message": {
"mid": "mid.původní_zprávy..."
}
}
}
Výhody architektury
- Lokální spuštění: npm start bez portů a SSL.
- Rozhraní Reply: administrátor používá standardní funkci Reply.
- Jednoduchá databáze: jediný soubor database.sqlite pro zálohy.
- Škálovatelnost: migrace na PostgreSQL při růstu zátěže.
Co je důležité
- Long Polling zjednodušuje vývoj MVP, vylučuje potřebu webhooks.
- Reply-map v SQLite zajišťuje přesnou směrování odpovědí.
- Markdown v přesměrování přidává kontext (jméno, ID klienta).
- Fallback pro textové zprávy administrátora – poslední aktivní klient.
— Editorial Team
Zatím žádné komentáře.