喂!我是 Wei

Front-End Engineer

Be a Problem Solver.

⌘K

導覽

所有文章緣起互動小功能

文章分類

目錄
node-cron 是什麼?Cron 表達式格式安裝與初始化和既有 Bot 主流程整合Google Sheets 重置函式下一篇預告

相關文章

從本機到伺服器:Discord Bot 的 Docker 部署完整流程

2026年3月28日

Discord Bot 監控與告警:Bot 掛掉時自動發通知到頻道

2026年5月18日

Discord Bot 串接 Groq:打造高速 AI 對話助理

2026年4月1日

最新文章
全部 →
前端 CI/CD 與正式環境除錯:從 Pull Request 到事故排查
2026-06-24
即時資料怎麼選?Polling、SSE、WebSocket 比較
2026-06-23
前端系統設計:如何拆元件、資料流與大型專案架構?
2026-06-22
無障礙不是加 ARIA:語意化 HTML、鍵盤操作與焦點管理
2026-06-21
CSS 與 RWD 面試整理:Flexbox、Grid、定位與層疊脈絡
2026-06-19
← 返回文章列表

Discord Bot 排程任務:node-cron 做每日公告與資料重置

2026年3月31日·約 4 分鐘閱讀·
Discord.jsBotnode-cronDockerNode.js

前兩篇把輸入互動補齊後,這篇來做 Bot 最常見的營運需求:定時任務。

目標很明確:

  1. 每天早上固定發「今日任務」
  2. 每天凌晨重置簽到狀態

node-cron 是什麼?

node-cron 是 Node.js 的輕量排程函式庫,讓你用一行 cron 表達式 指定執行時間,不需要自己管 setInterval、時間累積或跨日邊界。

Cron 表達式格式

node-cron 使用 5 個欄位,由左到右依序是:

┌─ 分鐘 (0–59)
│  ┌─ 小時 (0–23)
│  │  ┌─ 日 (1–31)
│  │  │  ┌─ 月 (1–12)
│  │  │  │  ┌─ 星期 (0–7,0 與 7 都代表週日)
│  │  │  │  │
*  *  *  *  *

幾個常用範例:

表達式說明
0 8 * * *每天 08:00
0 0 * * *每天凌晨 00:00
*/30 * * * *每 30 分鐘執行一次
0 9 * * 1每週一 09:00
0 12 1 * *每月 1 號 12:00

* 代表「每個」,*/n 代表「每隔 n 個」,直接填數字就是指定值。

node-cron 也支援第 6 個欄位(秒),但預設是 5 個欄位,平常不需要精確到秒時用不到。


安裝與初始化

npm install node-cron

先補 .env 參數:

.env
# 既有設定(前幾篇已設定過)
BOT_TOKEN=你的BotToken
GUILD_ID=你的伺服器ID
FEEDBACK_CHANNEL_ID=回饋通知頻道ID
SPREADSHEET_ID=你的試算表ID
 
# 本篇新增
ANNOUNCE_CHANNEL_ID=每日公告頻道ID
LOG_CHANNEL_ID=排程日誌頻道ID

這篇把排程邏輯獨立成一支新檔案 scheduler.js,不放在 index.js 裡,好處是:主流程保持乾淨,日後新增或調整排程只改這一支檔案就好。

scheduler.js
import cron from "node-cron";
 
let schedulerStarted = false;
 
export function setupScheduler({ client, onDailyReset }) {
  if (schedulerStarted) return;
  schedulerStarted = true;
 
  const timezone = "Asia/Taipei";
 
  // 每天 08:00 發公告
  cron.schedule(
    "0 8 * * *",
    async () => {
      const channel = await client.channels.fetch(process.env.ANNOUNCE_CHANNEL_ID);
      if (!channel?.isTextBased()) return;
 
      await channel.send({
        content: "早安!今日任務已更新,記得簽到與完成挑戰。",
      });
    },
    { timezone }
  );
 
  // 每天 00:00 重置簽到資料
  cron.schedule(
    "0 0 * * *",
    async () => {
      await onDailyReset();
      const logChannel = await client.channels.fetch(process.env.LOG_CHANNEL_ID);
      if (logChannel?.isTextBased()) {
        await logChannel.send("簽到資料已完成每日重置。");
      }
    },
    { timezone }
  );
}

和既有 Bot 主流程整合

index.js(節錄)
import { setupScheduler } from "./scheduler.js";
import { resetDailyCheckIn } from "./googleSheets.js";
 
client.once("ready", async () => {
  console.log(`Bot 已上線:${client.user.tag}`);
 
  setupScheduler({
    client,
    onDailyReset: resetDailyCheckIn,
  });
  console.log("排程任務已啟動");
});

啟動後終端機會顯示 Bot 上線與排程啟動的訊息,確認排程有被正確註冊。

Bot 啟動,終端機顯示排程已啟動


Google Sheets 重置函式

簡化做法:把 簽到記錄 中的日期欄清空。

googleSheets.js(節錄)
export async function resetDailyCheckIn() {
  const response = await sheets.spreadsheets.values.get({
    spreadsheetId: process.env.SPREADSHEET_ID,
    range: "簽到記錄!A:B",
  });
 
  const rows = response.data.values ?? [];
  if (rows.length <= 1) return;
 
  // 第 1 列保留表頭,從第 2 列開始清空簽到日期
  const bodyRows = rows.slice(1);
  const cleared = bodyRows.map((row) => [row[0], ""]);
 
  await sheets.spreadsheets.values.update({
    spreadsheetId: process.env.SPREADSHEET_ID,
    range: `簽到記錄!A2:B${cleared.length + 1}`,
    valueInputOption: "USER_ENTERED",
    resource: { values: cleared },
  });
}

排程正常運作後,頻道就會依設定時間收到公告訊息。

測試說明:截圖中的排程改為 */1 * * * *(每分鐘觸發),方便快速驗證流程是否正常,不用等到早上 08:00。確認沒問題後再改回 0 8 * * *。

Discord 頻道收到排程公告


下一篇預告

排程加上去後,Bot 不再是被動回應工具,而是可以主動運營社群。下一篇進入 AI:串接 Groq 做 /ask 多輪對話。

分享:XLinkedIn
← 上一篇Discord Bot Autocomplete:Slash Command 即時搜尋實戰
下一篇 →Discord Bot 串接 Groq:打造高速 AI 對話助理