用 TypeScript 打造 Discord 自動通知系統:Webhook 快速上手

作者: Calpa Liu
字數:1801
出版:2025 年 5 月 17 日
使用 TypeScript 與 Discord Webhook API,打造自動發送訊息到頻道的完整流程。從設定 Webhook 到訊息格式、編輯與刪除操作,全方位實戰解析,適合開發者應用於文章通知、自動通報等場景。

過去我習慣透過 RSS 搭配 Telegram Bot,自動推送部落格更新通知至頻道。近期開始將社群互動轉移至 Discord,便思考是否也能實現類似的自動化流程。經研究後發現,Discord 提供了 Webhook API,可在不建立機器人帳號的情況下發送格式化訊息。為此,我使用 TypeScript 實作了一套訊息推送邏輯,結合 Zod 驗證、自訂嵌入內容與錯誤處理,成功將新文章資訊即時發送至指定頻道。本文將詳解整體架構與程式碼實作,協助你快速建立自己的 Discord 通知系統。

什麼是 Discord Webhook?

Discord 是一款以社群為核心的即時通訊平台,廣泛用於遊戲、開發者、教育與創作者社群。它支援頻道分類、身分組、語音/影像通話與豐富的第三方整合功能,尤其受到技術社群與開源專案歡迎。許多團隊會將 Discord 作為內部通報、異常監控、或社群公告的資訊中樞,對自動化有高度需求。

Discord Webhook 則是 Discord 提供的一種輕量整合方式,允許開發者在不建立機器人帳號的前提下,自動發送訊息到指定頻道。Webhook 支援 JSON 格式、豐富的 embeds 區塊與自訂頭像、名稱等外觀設定。由於設置簡單、無需身份驗證,特別適合用於 CI/CD 成果通知、文章更新、錯誤報告等用途。

Webhook 並非 Discord 專屬功能,而是一種通用的事件驅動技術。在 GitHub 中,可以透過 Webhook 將每次 Push、PR 或部署事件傳送至外部系統;Slack 也支援 Webhook 發送格式化訊息。透過這種「主動推送」的機制,開發者能串連不同平台,打造自動化的跨系統通訊流程,是許多現代 DevOps 與 SaaS 服務不可或缺的整合技術。

適用場景

這套 Discord Webhook 自動推播系統,特別適合以下使用情境:

  • 部落格發佈新文章自動通知
  • CI/CD 构建完成、部署成功後推播結果
  • 錯誤日誌、系統監控自動回報
  • 團隊更新、公告通知整合至 Discord 頻道

如何在 Discord 中產生 Webhook 並取得網址

要在 Discord 設定 Webhook,首先進入伺服器設定頁面,點選「整合」(Integrations),並新增一個 Webhook。你可以自訂 Webhook 的名稱和頭像,並選擇要發送訊息的頻道,最後複製產生的 Webhook URL。

取得的 Webhook URL 形式為 https://discord.com/api/webhooks/your-webhook-id/your-webhook-token。請妥善保存這個網址,因為持有此 URL 的任何人都能將訊息發送到指定頻道。

Webhook 訊息格式解析:content 與 embeds

Webhook 訊息支援以下元素:

  • username:訊息顯示名稱
  • avatar_url:顯示頭像
  • content:純文字訊息內容
  • embeds:豐富格式訊息(可包含標題、描述、顏色、縮圖、欄位、時間戳等)

嵌入(embeds)常用屬性:

屬性說明限制
title標題最多 256 字元
description描述最多 4096 字元
url點擊標題跳轉的連結-
color左側顏色(十進位數字)-
timestamp時間戳ISO8601 格式
thumbnail縮圖 URL-
footer頁腳文字最多 2048 字元
fields自訂欄位最多 25 個

用 TypeScript 發送 Webhook:完整實作教學

以下展示一個完整範例,包含資料驗證、組裝訊息與錯誤處理:

Step 1:定義與驗證訊息資料格式(Zod)

首先,使用 Zod 定義並驗證文章元數據與 Discord 訊息格式,確保資料正確性:

import { z } from "zod";

// 文章元數據結構
export const ArticleMetadataSchema = z.object({
  title: z.string(),
  url: z.string().url(),
  description: z.string(),
  timestamp: z.string().datetime(),
  thumbnailURL: z.string().url(),
});
export type ArticleMetadata = z.infer<typeof ArticleMetadataSchema>;

// Discord Webhook 訊息格式
export const DiscordMessageSchema = z.object({
  username: z.string().optional(),
  avatar_url: z.string().url().optional(),
  content: z.string().optional(),
  embeds: z.array(
    z.object({
      title: z.string(),
      url: z.string().url(),
      description: z.string(),
      color: z.number().int().optional(),
      footer: z.object({ text: z.string() }).optional(),
      timestamp: z.string().datetime().optional(),
      thumbnail: z.object({ url: z.string().url() }).optional(),
    })
  ) 
});
export type DiscordMessage = z.infer<typeof DiscordMessageSchema>;

Step 2:根據文章資訊組裝 Webhook 訊息

根據文章元數據組裝符合 Discord Webhook 格式的訊息物件:

/**
 * 將文章元數據轉換為 Discord Webhook 訊息內容
 */
export function buildDiscordMessage(article: ArticleMetadata): DiscordMessage {
  const { title, url, description, timestamp, thumbnailURL } = ArticleMetadataSchema.parse(article);

  return DiscordMessageSchema.parse({
    username: "Calpa 的自動人形",
    avatar_url: "https://assets.calpa.me/telegram/public/pfp.png",
    content: "📰 Calpa 發佈新文章啦!",
    embeds: [
      {
        title,
        url,
        description,
        color: 0x58a6ff,
        footer: { text: "Calpa 的煉金工房" },
        timestamp,
        thumbnail: { url: thumbnailURL }
      }
    ]
  });
}

Step 3:發送訊息並處理錯誤回傳

最後,封裝發送邏輯,捕捉錯誤並回傳結果:

/**
 * 發送格式化的 Discord Webhook 訊息
 * @param webhookUrl Discord webhook URL
 * @param message DiscordMessage 物件
 * @returns 發送成功返回 true,否則 false
 */
export async function sendDiscordMessage(
  webhookUrl: string,
  message: DiscordMessage
): Promise<boolean> {
  const response = await fetch(webhookUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(message),
  });

  if (!response.ok) {
    console.error(`Failed to send to Discord: ${response.status} ${await response.text()}`);
    return false;
  }
  return true;
}

Step 4:整合訊息組裝與發送

兩步組合:先組裝訊息,再發送:

// 1. 組裝訊息
const message = buildDiscordMessage(articleMetadata);
// 2. 發送訊息
const success = await sendDiscordMessage(DISCORD_WEBHOOK_URL, message);

Webhook 實作限制與最佳實踐建議

Discord Webhook 訊息本身有諸多格式與容量限制,例如單則訊息內容不得超過 2000 字元,每則訊息可附帶的嵌入(embed)上限為 10 個,所有嵌入的總字元數不得超過 6000。單一嵌入的標題與描述分別限制為 256 與 4096 字元,欄位(fields)數量最多為 25,每個欄位名稱與值則分別不得超過 256 與 1024 字元。此外,API 頻率限制為每個 webhook 每分鐘最多 30 次。

為確保訊息傳遞穩定,建議採用 Zod 這類 schema library 進行資料驗證,嚴格比對格式與長度。實作完整錯誤處理機制、詳細記錄響應狀態與訊息,有助於後續除錯。可視需求自訂 usernameavatar_url 等外觀設定,並適度善用 color 屬性提升可讀性。同時要特別留意速率限制,避免短時間內大量發送導致訊息遭拒。

如果發送失敗,可觀察 response.statusresponse.text() 的錯誤訊息內容,大多能找出格式錯誤或速率限制等問題。

.env 管理 Webhook URL

為了更加安全地管理 Webhook URL,我們可以使用 .env 檔案。首先,在專案根目錄下建立 .env 檔案,並添加 Webhook URL:

DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/your-webhook-id/your-webhook-token

這樣可以避免將 Webhook URL 直接硬編入程式碼中,增加安全性。

結語:從 Telegram 過渡到 Discord 的自動化體驗

從 Telegram 轉移到 Discord Webhook 的自動推播,其實過程十分順暢。無需額外建立機器人帳號,只要設定好 Webhook 並發送合適格式的訊息,就能輕鬆完成自動化通知。這種方式讓資訊推送變得更簡單,也便於融入各種開發或社群應用。

如果你開始善用 Discord Webhook,相信會發現自動化流程變得更高效與友善。最後,記得妥善保存 Webhook URL,避免被他人濫用,讓自動化體驗維持順暢與安全!

關於 Calpa

Calpa 擅長使用 TypeScriptReact.jsVue.js 建立 Responsive Website。

他積極參與開源社區,曾在 2019 年的香港開源大會上擔任講者,提供工作經驗和見解。此外,他也在 GitHub 上公開分享個人博客程式碼,已獲得超過 300 顆星星和 60 個分支的支持。

他熱愛學習新技術,並樂意分享經驗。他相信,唯有不斷學習才能跟上快速演變的技術環境。

熱門文章

最新文章

圖片管理中心
管理圖片資源
IP 查詢
快速查詢和定位 IP 地址的地理位置和相關信息
Python 運行器
無需後端、無需登入,只需打開瀏覽器即可運行 Python 代碼(由 Pyodide 提供支持)
封面圖生成器
自動創建適合各種平台的文章封面圖
原作(青山剛昌)產生器
一鍵創建原作(青山剛昌)的封面圖
日本色彩
探索和使用傳統日本色彩
部落格內容洞察儀表板
以視覺化儀表板方式追蹤文章成效、分享熱度與分類分布,協助創作者掌握內容表現。
蒙特卡羅估算 π
使用蒙特卡羅方法演示 π 值的估算過程
LLM
使用 LLM 模型進行聊天
活動圖生成器
一鍵創建活動的封面圖
Wagmi Card
一鍵創建 Wagmi 的封面圖
Facebook Quote
Facebook Quote
Music Macro Language (MML) Studio
用程式語法編寫旋律,用音符構築想像
Blurhash
一鍵創建 Blurhash
文字分類器
使用 MediaPipe TextClassifier 分類文字
前端工程師免費工具資源
前端工程師免費工具資源
後端工程師免費工具資源
後端工程師免費工具資源
全端工程師免費工具資源
全端工程師免費工具資源
Web3 工程師免費工具資源
Web3 工程師免費工具資源
紫微斗數排盤系統|結合 AI 的命盤性格與事業財務分析生成器
紫微斗數排盤工具,輸入生日與時辰,自動生成完整命盤分析提示(Prompt)。結合最專業紫微理論與 AI 助力,助你深入解析性格、事業、財務與人際課題。免費使用,適合命理師及紫微愛好者。
PixAI Prompt 組合器|快速打造可用於 AI 繪圖的語言拼圖
使用 PixAI 卻不會寫 prompt?這個工具幫你一鍵組裝角色、表情、風格語彙,輸出高品質繪圖提示語句(Prompt),可直接貼入 PixAI 使用。適合插畫師、創作者、AI 新手與 VTuber 角色開發者。
你擁有的 .eth 是誰?一鍵查出 ENS 背後地址
只要輸入一個 ENS 名稱,我們就能幫你查出它指向哪個以太坊地址,還能看到頭像。如果你常常看到 .eth 名稱卻不知道誰在背後,這個小工具幫得上忙。