// 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. Un archivo SQLite guarda los flujos a medias y los datos de usuario entre reinicios
const bot = new Bot({ provider, lang: 'es', store: new SQLiteStore({ file: './citas.db' }) })
bot.plug(slashCommandsPlugin, {
greeting: '💈 ¡Hola! Envía "reservar" para pedir cita o "mi cita" para verla. /cancel detiene una reserva.',
})
// 2. El flujo de reserva: persistente, validado y con confirmación
bot.use(
flow('reservar')
.persistent()
.timeout('10m')
.ask('📅 Vamos a reservar tu cita. ¿A nombre de quién?', 'name', {
validate: (body) => (body.trim().length >= 2 ? true : '✋ Escribe al menos 2 letras.'),
maxAttempts: 3,
})
// 3. Un formulario: campos tipados, validados uno a uno (un WhatsApp Flow nativo en la Cloud API)
.form(
{
id: 'slot',
fields: [
{ type: 'date', name: 'day', label: 'Día', prompt: '¿Qué día? (p. ej. 14/03/2030)', min: today(), error: '❌ Elige un día a partir de hoy.' },
{ type: 'select', name: 'time', label: 'Hora', prompt: '¿A qué hora?', options: ['09:00', '11:30', '16:00'] },
],
},
{ flatten: true, maxAttempts: 3 },
)
// 4. Confirmación antes de guardar nada
.say((_ctx, c) => `📝 ${c.state.name}, el ${c.state.day} a las ${c.state.time}.`)
.choose('¿La reservo?', { yes: 'Sí, resérvala', no: 'No, cancela' }, 'confirm')
.do(async (ctx, c) => {
if (c.state.confirm === 'no') return c.end('👌 Cancelado, no se reservó nada.')
// 5. Guarda la cita en el perfil del usuario (en el mismo archivo SQLite)
await userOf(ctx).set('appointment', { name: c.state.name, day: c.state.day, time: c.state.time })
})
.say('✅ ¡Reservada! Envía "mi cita" para verla.'),
)
bot.when('mi cita', async (ctx) => {
const appointment = await ctx.user.get('appointment')
await ctx.reply(
appointment
? `📅 ${appointment.name}: el ${appointment.day} a las ${appointment.time}`
: 'Todavía no tienes cita. Envía "reservar".',
)
})
bot.onMessage((ctx) => ctx.reply('Envía "reservar", "mi cita" o /help.'))
return bot
})
export default createBot
// `node bot.js` se conecta a WhatsApp; `npx botmesh dev bot.js` se salta este bloque
if (isMainModule(import.meta)) {
const bot = await createBot(new BaileysProvider({ session: 'bot-citas' }))
bot.on('ready', () => console.log('✅ Conectado'))
await bot.start()
}