> ## Documentation Index
> Fetch the complete documentation index at: https://botmesh.afaya.com.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Reminder Bot

> Build a bot that sets one-off reminders ("remind 10m call mom") and sends a daily tip at 9:00 to everyone who subscribes.

**Level:** Beginner · **Tags:** WhatsApp, Telegram, Scheduler

**Features shown:** [`bot.delay()`](https://botmesh.afaya.com.co/guide/scheduler) ·
[`bot.schedule()` with cron and time zone](https://botmesh.afaya.com.co/guide/scheduler) ·
[cancelling a task](https://botmesh.afaya.com.co/guide/scheduler.md#cancelling-a-task) ·
[`bot.send()` outside a handler](https://botmesh.afaya.com.co/guide/messages#sending-outside-a-handler) ·
[regex triggers](https://botmesh.afaya.com.co/guide/concepts.md#when-simple-responses)

## Prerequisites

Node.js 22.12 or newer and a folder with `"type": "module"` (see
[Getting started](https://botmesh.afaya.com.co/guide/getting-started.md#requirements)). Then install:

```bash theme={null}
npm install @botmesh/core @botmesh/baileys
```

## The complete bot

```js theme={null}
// bot.js
import { Bot, defineBot, isMainModule } from '@botmesh/core'
import { BaileysProvider } from '@botmesh/baileys'

const createBot = defineBot((provider) => {
  const bot = new Bot({ provider })
  const pending = new Map() // chat id → Set of pending reminder tasks
  const subscribers = new Set() // chat ids that get the daily tip

  // "remind 10m call mom": a one-off task with bot.delay()
  bot.when(/^remind\s/i, async (ctx) => {
    const match = /^remind\s+(\d+[smhd])\s+(.+)$/i.exec(ctx.body)
    if (!match) return ctx.reply('Usage: remind <10s|5m|2h|1d> <text>')
    const [, wait, text] = match
    const chatId = ctx.from
    const tasks = pending.get(chatId) ?? new Set()
    pending.set(chatId, tasks)
    const task = bot.delay(wait, async () => {
      tasks.delete(task)
      await bot.send(chatId, `⏰ Reminder: ${text}`)
    })
    tasks.add(task)
    await ctx.reply(`👍 I will remind you in ${wait}.`)
  })

  bot.when('reminders', (ctx) => ctx.reply(`📋 Pending reminders: ${pending.get(ctx.from)?.size ?? 0}`))

  bot.when('cancel reminders', async (ctx) => {
    const tasks = pending.get(ctx.from) ?? new Set()
    for (const task of tasks) task.cancel()
    await ctx.reply(`🗑️ Cancelled ${tasks.size} reminder(s).`)
    tasks.clear()
  })

  // Every day at 9:00, Bogota time, wherever the server runs
  bot.schedule('0 9 * * *', { timeZone: 'America/Bogota' }, async () => {
    for (const chatId of subscribers) await bot.send(chatId, '☀️ Tip of the day: drink a glass of water.')
  })
  bot.when('daily on', (ctx) => {
    subscribers.add(ctx.from)
    return ctx.reply('☀️ Subscribed: a tip every day at 9:00 (Bogota time).')
  })
  bot.when('daily off', (ctx) => {
    subscribers.delete(ctx.from)
    return ctx.reply('👋 Unsubscribed from the daily tip.')
  })

  bot.onMessage((ctx) => ctx.reply('Try: remind 10m call mom · reminders · cancel reminders · daily on'))

  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: 'reminder-bot' }))
  bot.on('ready', () => console.log('✅ Connected. Send "remind 1m test" from another phone.'))
  await bot.start()
}
```

## Sample transcript

Captured with `npx botmesh dev bot.js`; the first reminder arrives two
seconds later:

```text theme={null}
user › remind 2s stretch your legs
bot › 👍 I will remind you in 2s.
bot › ⏰ Reminder: stretch your legs
user › remind 1h call mom
bot › 👍 I will remind you in 1h.
user › reminders
bot › 📋 Pending reminders: 1
user › cancel reminders
bot › 🗑️ Cancelled 1 reminder(s).
user › remind tomorrow
bot › Usage: remind <10s|5m|2h|1d> <text>
user › daily on
bot › ☀️ Subscribed: a tip every day at 9:00 (Bogota time).
```

## How it works

* **`bot.delay(duration, fn)`** runs `fn` once after `duration` (`'10s'`,
  `'5m'`, `'2h'`, `'1d'` or milliseconds) and returns a task with
  `cancel()`. The handler keeps each task to list or cancel it later.
* **`bot.send(chatId, text)`** sends outside a handler: by the time the
  reminder fires, the message that created it is long gone, so the chat id
  (`ctx.from`) is saved first.
* **`bot.schedule(cron, { timeZone }, fn)`** runs on a 5-field cron
  expression read in an IANA time zone. `bot.every('30m', fn)` repeats at a
  fixed interval instead.
* **In memory.** These tasks live in the process: a restart forgets them.
  To survive restarts (and run once across several replicas), give a task an
  `id` and a schedule store: see
  [Durable tasks](https://botmesh.afaya.com.co/guide/scheduler.md#durable-tasks-survive-restarts-one-replica-per-run).

## Run it on WhatsApp or Telegram

`node bot.js` prints a QR: scan it in WhatsApp → Linked devices. On
Telegram, install `@botmesh/telegram` and swap the provider as shown in
[Or connect Telegram](https://botmesh.afaya.com.co/guide/getting-started.md#or-connect-telegram); the
factory does not change.

## Next steps

* [Scheduler](https://botmesh.afaya.com.co/guide/scheduler.md): `every`, cron syntax, daylight-saving rules
* [Persistent user data](https://botmesh.afaya.com.co/guide/user-data.md): remember subscribers across restarts
* [Greeting bot](https://botmesh.afaya.com.co/examples/greeting-bot.md): add `/help` and a welcome message


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.