過去我習慣透過 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 進行資料驗證,嚴格比對格式與長度。實作完整錯誤處理機制、詳細記錄響應狀態與訊息,有助於後續除錯。可視需求自訂 username
、avatar_url
等外觀設定,並適度善用 color
屬性提升可讀性。同時要特別留意速率限制,避免短時間內大量發送導致訊息遭拒。
如果發送失敗,可觀察 response.status
和 response.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,避免被他人濫用,讓自動化體驗維持順暢與安全!
如果你有 AI 專案、網站開發或技術整合需求,歡迎來信交流: partner@calpa.me
歡迎訂閱 Calpa 的頻道,一同將想像力化為可能: