Skip to main content

Message Handler

The message handler receives all messages and decides how to respond:
router.onMessage(async (message, context) => {
  // Return string for custom response
  // Return null to let AI handle

  if (message.content === '/help') {
    return 'Here are the available commands...';
  }

  return null; // Let AI respond
});

Message Object

router.onMessage(async (message, context) => {
  console.log({
    content: message.content,      // User's message text
    userId: message.userId,         // User ID
    platform: message.platform,     // Platform name
    channelId: message.channelId,   // Channel/chat ID (if applicable)
    timestamp: message.timestamp    // Message timestamp
  });
});

Context Object

router.onMessage(async (message, context) => {
  // Access Core SDK
  const bots = await context.boostgpt.listBots();

  // Access router config
  console.log(context.config.defaultBotId);

  // Platform-specific data
  console.log(context.platform);
});

Command Handling

Handle specific commands:
router.onMessage(async (message, context) => {
  const content = message.content.toLowerCase();

  // Help command
  if (content === '/help' || content === 'help') {
    return 'Available commands:\n/help - Show this message\n/ping - Test bot\n/info - Bot information';
  }

  // Ping command
  if (content === '/ping') {
    return 'Pong! Bot is online.';
  }

  // Info command
  if (content === '/info') {
    const bots = await context.boostgpt.listBots();
    return `Running ${bots.response.length} bots`;
  }

  // Let AI handle everything else
  return null;
});

Pattern Matching

Use regex for flexible commands:
router.onMessage(async (message, context) => {
  const content = message.content;

  // Match /weather <city>
  const weatherMatch = content.match(/^\/weather\s+(.+)/i);
  if (weatherMatch) {
    const city = weatherMatch[1];
    return `Weather in ${city}: Sunny, 72�F`;
  }

  // Match /search <query>
  const searchMatch = content.match(/^\/search\s+(.+)/i);
  if (searchMatch) {
    const query = searchMatch[1];
    // Perform search...
    return `Search results for: ${query}`;
  }

  return null;
});

User-Specific Logic

Handle users differently:
const admins = ['user_123', 'user_456'];

router.onMessage(async (message, context) => {
  // Admin-only commands
  if (message.content === '/admin' && admins.includes(message.userId)) {
    return 'Admin panel: ...';
  }

  // Block specific users
  if (message.userId === 'blocked_user') {
    return 'You are blocked from using this bot.';
  }

  return null;
});

Platform-Specific Handling

router.onMessage(async (message, context) => {
  if (message.platform === 'discord') {
    // Discord-specific logic
    if (message.content === '/roles') {
      return 'Discord roles: ...';
    }
  }

  if (message.platform === 'telegram') {
    // Telegram-specific logic
    if (message.content === '/telegram_only') {
      return 'This command only works on Telegram';
    }
  }

  return null;
});

Rate Limiting

Implement rate limiting per user:
const userLastMessage = new Map();
const RATE_LIMIT_MS = 5000; // 5 seconds

router.onMessage(async (message, context) => {
  const lastTime = userLastMessage.get(message.userId);
  const now = Date.now();

  if (lastTime && now - lastTime < RATE_LIMIT_MS) {
    return 'Please wait a few seconds before sending another message.';
  }

  userLastMessage.set(message.userId, now);

  return null; // Continue with AI
});

Access User Session

Maintain user context:
router.onMessage(async (message, context) => {
  const sessionId = `${message.platform}_${message.userId}`;

  const response = await context.boostgpt.chat({
    bot_id: context.config.defaultBotId,
    message: message.content,
    session_id: sessionId,
    user_id: message.userId
  });

  if (response.err) {
    return 'Sorry, something went wrong.';
  }

  return response.response;
});

Error Handling

Handle errors gracefully:
router.onMessage(async (message, context) => {
  try {
    if (message.content === '/stats') {
      const bots = await context.boostgpt.listBots();

      if (bots.err) {
        return 'Error fetching stats. Please try again.';
      }

      return `You have ${bots.response.length} bots`;
    }

    return null;
  } catch (error) {
    console.error('Handler error:', error);
    return 'An unexpected error occurred.';
  }
});

Complete Example

import { Router, DiscordAdapter } from '@boostgpt/router';

const router = new Router({
  apiKey: process.env.BOOSTGPT_API_KEY,
  projectId: process.env.BOOSTGPT_PROJECT_ID,
  defaultBotId: process.env.BOOSTGPT_BOT_ID,
  adapters: [
    new DiscordAdapter({
      discordToken: process.env.DISCORD_TOKEN
    })
  ]
});

const admins = ['admin_123'];
const userLastMessage = new Map();

router.onMessage(async (message, context) => {
  // Rate limiting
  const lastTime = userLastMessage.get(message.userId);
  if (lastTime && Date.now() - lastTime < 3000) {
    return 'Please wait before sending another message.';
  }
  userLastMessage.set(message.userId, Date.now());

  const content = message.content.toLowerCase();

  // Help command
  if (content === '/help') {
    return 'Commands: /help, /ping, /stats';
  }

  // Ping command
  if (content === '/ping') {
    return 'Pong!';
  }

  // Stats (admin only)
  if (content === '/stats' && admins.includes(message.userId)) {
    const bots = await context.boostgpt.listBots();
    return `Bots: ${bots.response.length}`;
  }

  // Let AI handle everything else
  return null;
});

await router.start();

Next Steps