Powrót do strony głównej

MVP-bot dla Max.ru: Long Polling i mapowanie Reply

Artykuł opisuje stworzenie MVP bota do opinii zwrotnej dla Max.ru na Node.js z wykorzystaniem Long Polling i SQLite. Zaimplementowano logikę mapowania Reply do kierowania odpowiedzi administratora. Podano pełny kod inicjalizacji bazy danych i obsługi zdarzeń.

Bot dla Max.ru: od instalacji do logiki Reply
Advertisement 728x90

Tworzenie MVP bota dla Max.ru: obsługa feedbacku przez Long Polling i SQLite

Platforma Max.ru umożliwia developerom dostęp do Bot API, aby tworzyć narzędzia interakcji. Do MVP bota z feedbackiem wykorzystuje się Node.js w połączeniu z biblioteką @maxhub/max-bot-api oraz SQLite. Mechanizm Long Polling pozwala uruchomić bota lokalnie bez konfiguracji webhooków, serwera czy HTTPS.

Głównym wyzwaniem jest identyfikacja klienta podczas odpowiedzi administratora. Wiadomość typu reply zawiera link z mid oryginalnej wiadomości, co umożliwia powiązanie odpowiedzi z klientem poprzez bazę danych.

Wybór technologii i przygotowanie projektu

Biblioteka @maxhub/max-bot-api wspiera Long Polling od razu — nie trzeba używać ngrok ani Cloudflare Tunnel podczas rozwoju.

Google AdInline article slot

SQLite idealnie nadaje się do MVP: baza danych plikowa, bez oddzielnego serwera, minimalne opóźnienia, sekwencyjne przetwarzanie zapytań.

Instalacja zależności:

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

Plik .env:

Google AdInline article slot
BOT_TOKEN=twój_tekst_tutaj
OWNER_ID=12345678

Token generuje się w business.max.ru, a OWNER_ID to indywidualny identyfikator użytkownika w Max.

Inicjalizacja SQLite i struktura bazy danych

Połączenie asynchroniczne z utworzeniem tabeli reply_map do mapowania:

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('Baza danych gotowa');
})();

Tabela przechowuje relację owner_msg_mid → client_user_id.

Google AdInline article slot

Przetwarzanie wiadomości od klienta

Zdarzenie message_created sprawdza nadawcę. Wiadomości od klientów są przesyłane do administratora w formacie 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 = `📩 **Wiadomość 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 odpowiedzi
});

mid wysłanej wiadomości zostaje zapisane w tabeli reply_map.

Logika odpowiedzi administratora

Wiadomość typu reply zawiera pole link.type = 'reply' oraz link.message.mid — ID oryginalnej wiadomości. Wyszukiwanie klienta poprzez reply_map:

  • Jeśli link.type === 'reply': wyodrębnij repliedMsgMid, wykonaj zapytanie do bazy.
  • Wyślij odpowiedź klientowi na podstawie client_user_id.
  • Potwierdź administratorowi.

Struktura JSON reply:

{
  "body": { "text": "odpowiedź", ... },
  "sender": { ... },
  "link": {
    "type": "reply",
    "message": {
      "mid": "mid.oryginalnej_wiadomości..."
    }
  }
}

Zalety architektury

  • Uruchomienie lokalne: npm start bez portów i SSL.
  • Interfejs Reply: administrator korzysta z standardowej funkcji odpowiedzi.
  • Prosta baza danych: pojedynczy plik database.sqlite do backupu.
  • Skalowalność: migracja do PostgreSQL przy wzroście obciążenia.

Co warto pamiętać

  • Long Polling upraszcza rozwój MVP, eliminując potrzebę webhooków.
  • Mapowanie reply w SQLite zapewnia precyzyjną dystrybucję odpowiedzi.
  • Format Markdown w przesyłaniu dodaje kontekst (imię, ID klienta).
  • Fallback dla tekstowych odpowiedzi administratora — ostatni aktywny klient.

— Editorial Team

Advertisement 728x90

Czytaj dalej