// bot.js
import { Bot, defineBot, flow, isMainModule, slashCommandsPlugin, userOf } from '@botmesh/core'
import { SQLiteStore } from '@botmesh/sqlite-store'
import { BaileysProvider } from '@botmesh/baileys'
const today = () => new Date().toISOString().slice(0, 10)
const createBot = defineBot((provider) => {
// 1. A SQLite file keeps flows in progress and user data across restarts
const bot = new Bot({ provider, store: new SQLiteStore({ file: './bookings.db' }) })
bot.plug(slashCommandsPlugin, {
greeting: '💈 Hi! Send "book" to book an appointment or "my appointment" to see it. /cancel stops a booking.',
})
// 2. The booking flow: persistent, validated, confirmed
bot.use(
flow('book')
.persistent()
.timeout('10m')
.ask('📅 Let us book your appointment. What name should I put it under?', 'name', {
validate: (body) => (body.trim().length >= 2 ? true : '✋ Please type at least 2 letters.'),
maxAttempts: 3,
})
// 3. A form: typed fields, validated one by one (a native WhatsApp Flow on the Cloud API)
.form(
{
id: 'slot',
fields: [
{ type: 'date', name: 'day', label: 'Day', prompt: 'Which day? (e.g. 2030-03-14)', min: today(), error: '❌ Pick a day from today on.' },
{ type: 'select', name: 'time', label: 'Time', prompt: 'What time?', options: ['09:00', '11:30', '16:00'] },
],
},
{ flatten: true, maxAttempts: 3 },
)
// 4. Confirmation before saving anything
.say((_ctx, c) => `📝 ${c.state.name}, ${c.state.day} at ${c.state.time}.`)
.choose('Shall I book it?', { yes: 'Yes, book it', no: 'No, cancel' }, 'confirm')
.do(async (ctx, c) => {
if (c.state.confirm === 'no') return c.end('👌 Cancelled, nothing was booked.')
// 5. Save the booking in the user's profile (same SQLite file)
await userOf(ctx).set('appointment', { name: c.state.name, day: c.state.day, time: c.state.time })
})
.say('✅ Booked! Send "my appointment" to see it.'),
)
bot.when('my appointment', async (ctx) => {
const appointment = await ctx.user.get('appointment')
await ctx.reply(
appointment
? `📅 ${appointment.name}: ${appointment.day} at ${appointment.time}`
: 'You have no appointment yet. Send "book".',
)
})
bot.onMessage((ctx) => ctx.reply('Send "book", "my appointment" or /help.'))
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: 'booking-bot' }))
bot.on('ready', () => console.log('✅ Connected'))
await bot.start()
}