// bot.js
import { Bot, defineBot, flow, isMainModule, slashCommandsPlugin } from '@botmesh/core'
import { BaileysProvider } from '@botmesh/baileys'
// Bot admins: their user ids, as /id shows them (WhatsApp: 573001234567@s.whatsapp.net)
const ADMINS = (process.env.ADMINS ?? 'ana').split(',')
const createBot = defineBot((provider) => {
// 1. Defaults that matter in groups: every group message is routed (groupMode: 'all')
// and each participant gets their own conversation (conversationScope: 'participant')
const bot = new Bot({ provider })
const rules = new Map() // group id → rules text
const scores = new Map() // group id → Map(name → points)
const isAdmin = (ctx) => ADMINS.includes(ctx.sender)
const nameOf = (ctx) => ctx.pushName ?? ctx.sender
bot.plug(slashCommandsPlugin) // /id, /help, /cancel...
// 2. A quiz per participant: two people can play at the same time
bot.use(
flow({ pattern: 'quiz', match: 'contains' })
.scope('group')
.ask((ctx) => `🧠 ${nameOf(ctx)}, 2 + 2 = ?`, 'q1')
.ask((ctx) => `🌍 ${nameOf(ctx)}, capital of France?`, 'q2')
.say((ctx, c) => {
const points = (c.state.q1.trim() === '4' ? 1 : 0) + (c.state.q2.trim().toLowerCase() === 'paris' ? 1 : 0)
const board = scores.get(ctx.from) ?? new Map()
board.set(nameOf(ctx), (board.get(nameOf(ctx)) ?? 0) + points)
scores.set(ctx.from, board)
return `🏁 ${nameOf(ctx)}: ${points}/2`
}),
)
// 3. Commands anyone can use
bot.command('rules', (ctx) => ctx.reply(rules.get(ctx.from) ?? 'No rules yet.'))
bot.command('scores', (ctx) => {
const board = [...(scores.get(ctx.from) ?? [])].sort((a, b) => b[1] - a[1])
return ctx.reply(board.length ? board.map(([name, points]) => `${name}: ${points}`).join('\n') : 'No scores yet. Send "quiz".')
})
// 4. Admin-only commands
bot.command('setrules', async (ctx, args) => {
if (!isAdmin(ctx)) return ctx.reply('⛔ Only admins can change the rules.')
rules.set(ctx.from, `📜 ${args.join(' ')}`)
await ctx.reply('✅ Rules updated.')
})
bot.command('resetscores', async (ctx) => {
if (!isAdmin(ctx)) return ctx.reply('⛔ Only admins can reset the scores.')
scores.delete(ctx.from)
await ctx.reply('🧹 Scores cleared.')
})
// 5. In a DM, explain; in a group, answer only when someone mentions the bot
bot.onMessage((ctx) => {
if (!ctx.isGroup) return ctx.reply('Add me to a group and send "quiz" there.')
if (provider.selfId != null && ctx.mentions.includes(provider.selfId)) {
return ctx.reply(`👋 Hi ${nameOf(ctx)}! Send "quiz" to play, /scores or /rules.`)
}
})
return bot
})
export default createBot
// `node bot.js` connects to WhatsApp; `npx botmesh dev bot.js` skips this block
if (isMainModule(import.meta)) {
const bot = await createBot(new BaileysProvider({ session: 'group-bot' }))
bot.on('ready', () => console.log('✅ Connected'))
await bot.start()
}