Skip to content

教程 04:定时任务

目标:使用 app.useJob() 和 cron 表达式实现定时推送、周期检查等场景。

有些事情不需要用户开口,Bot 自己就该去做——每天早上八点发一条早报,每周一提醒大家周会,整点报时。这类"到时间就执行"的任务(Job),用定时任务来写。

基本用法

typescript
app.useJob('Cron 表达式', async (ctx) => {
  // ...
})

useJob 返回 this,支持链式注册多个定时任务。

ctx 详解

Job 的 ctx 同样有两个属性:

ctx.event — 描述本次触发的定时信息:

字段类型说明
timestampnumber触发时间戳(毫秒),可直接传给 new Date()
specstring触发本次任务的 cron 表达式
typescript
app.useJob('0 9 * * *', async (ctx) => {
  const now = new Date(ctx.event.timestamp)
  console.log(`触发时间: ${now.toLocaleString('zh-CN')}`)
  console.log(`来自规则: ${ctx.event.spec}`)  // '0 9 * * *'
})

ctx.send(req, onSuccess?, onFailure?) — 与中间件中的 ctx.send 完全相同,用于调用 OneBot API 发送消息或执行操作。Job 里没有 next(),每个任务独立执行。

Cron 表达式速查

Aurorax 使用标准 5 字段 cron 语法:

┌─── 分钟 (0-59)
│  ┌─── 小时 (0-23)
│  │  ┌─── 日 (1-31)
│  │  │  ┌─── 月 (1-12)
│  │  │  │  ┌─── 星期 (0-7, 0 和 7 均表示周日)
│  │  │  │  │
*  *  *  *  *
表达式含义
0 9 * * *每天上午 9:00
0 9 * * 1-5工作日上午 9:00
*/5 * * * *每 5 分钟
0 */2 * * *每 2 小时整点
0 8 1 * *每月 1 日早 8:00
30 17 * * 5每周五下午 17:30

常见场景

每日早报推送

typescript
const NOTIFY_GROUP = 123456789

app.useJob('0 8 * * *', async (ctx) => {
  const date = new Date(ctx.event.timestamp).toLocaleDateString('zh-CN')

  ctx.send({
    action: 'send_group_msg',
    params: {
      group_id: NOTIFY_GROUP,
      message: `📅 早安!今天是 ${date},祝大家一天顺利~`
    }
  })
})

周期性状态检查

typescript
// 每 10 分钟检查一次,模拟外部服务健康监测
app.useJob('*/10 * * * *', async (ctx) => {
  const time = new Date(ctx.event.timestamp).toLocaleTimeString('zh-CN')
  console.log(`[${time}] 执行健康检查...`)

  try {
    // 在此调用你的检查逻辑,例如 fetch 某个接口
    // const ok = await checkService()
    // if (!ok) alert(...)
  } catch (err) {
    console.error('健康检查异常:', err)
  }
})

工作日提醒

typescript
// 工作日 18:00 下班提醒
app.useJob('0 18 * * 1-5', async (ctx) => {
  ctx.send({
    action: 'send_group_msg',
    params: {
      group_id: NOTIFY_GROUP,
      message: '🕕 下班时间到!记得打卡!'
    }
  })
})

月末报表

typescript
// 每月最后一天 23:00(用第 28 天保证每月都有,或结合代码判断实际月末)
app.useJob('0 23 28-31 * *', async (ctx) => {
  const now = new Date(ctx.event.timestamp)
  const tomorrow = new Date(now)
  tomorrow.setDate(now.getDate() + 1)

  // 判断明天是否是新月第一天
  if (tomorrow.getDate() === 1) {
    const month = now.getMonth() + 1
    ctx.send({
      action: 'send_group_msg',
      params: {
        group_id: NOTIFY_GROUP,
        message: `📊 ${month} 月即将结束,请完成本月汇总!`
      }
    })
  }
})

注册多个任务

typescript
app
  .useJob('0 8 * * *',   morningGreeting)
  .useJob('0 12 * * *',  noonReminder)
  .useJob('0 18 * * *',  eveningReport)
  .useJob('*/30 * * * *', healthCheck)

Job 与中间件的区别

特性useMwuseJob
触发来源OneBot 事件(实时)Cron 定时器
ctx.event 类型OnebotEventCronEvent
是否有 next()是(中间件链)否(独立执行)
典型用途响应用户消息定时推送、巡检

下一步