月曜日, 6月 30, 2025
月曜日, 6月 30, 2025
- Advertisment -
ホームニューステックニュース全人類、いますぐ Discord Webhook を使いこなそう

全人類、いますぐ Discord Webhook を使いこなそう


Discord の Webhook は個人的に めちゃくちゃお手軽で最強 です。そのお手軽さゆえに、活用範囲は想像以上に広いです。しかも無料で使えるので、個人ユースケースでもめちゃくちゃ有用で、使わない手はないです。

本記事では、Discord の Webhook について基本をしっかりと押さえ、実装に必要な基本機能を解説します。この記事を読み終わる頃には、あなたも Discord Webhook 沼に落ちていることでしょう。

プチ宣伝

最近 Discord 好きが集まる『Discorders Cafe』を始めました。Discord に関連する勉強会を定期的に行う予定です。
初回は 2025 年 7 月 5 日 に、この記事の内容をベースとしたハンズオン会を開催予定ですので、よかったらご参加ください。

そもそも Discord Webhook とは?

Discord Webhook は、外部サービスから Discord チャンネルにメッセージを送信するための仕組みです。Bot を作らずとも、HTTP リクエスト一発でメッセージが送れるという手軽さが最大の魅力です。

Webhook vs Bot の使い分け

機能 Webhook Bot
実装難易度 簡単(URL に POST するだけ) ちょっと複雑
双方向通信 ❌ 送信のみ ✅ 受信・返信可能
リアルタイム性 ⚡ 即座に送信 ⚡ 即座に送受信
認証 URL のみ Token 必須
ユーザー操作への反応
メッセージ編集・削除 ✅(制限あり) ✅(自由度高い)

「通知を送るだけ」なら Webhook、「対話が必要」なら Bot で実装するのが一般的に良いでしょう。なお、今回は Webhook をテーマとしますが、今後は Bot に関する記事もあげていく予定です。

ざっくり Webhook の作成方法

1. チャンネルの設定を開く

送信先のテキストチャンネルを右クリック → 「チャンネルの編集」を選択します。

チャンネルの編集

2. 連携サービスから Webhook を作成

左メニューの「連携サービス」→「ウェブフックを作成」をクリックします。

ウェブフックを作成

3. Webhook の設定

  • お名前: メッセージ送信時の表示名
  • アバター: アイコン画像(オプション)
  • チャンネル: メッセージ送信先

※ 全て後から変更可能です。

ウェブフックを作成

4. URL をコピー

https://discord.com/api/webhooks/[ID]/[TOKEN] 形式の URL が発行されます。
※ この URL は秘密情報として扱ってください。

とりあえず送信してみよう

curl でシンプルなテキスト送信

curl -H "Content-Type: application/json" \
     -X POST \
     -d '{"content": "Hello, Discord!"}' \
     https://discord.com/api/webhooks/YOUR_WEBHOOK_URL

curl でシンプルなテキスト送信

TypeScript で送信する

const webhookUrl = "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL";


fetch(webhookUrl, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ content: "TypeScriptから送信!" }),
});

TypeScript で送信する

ですこうぇぶふっ君 で送信する

今回用に『ですこうぇぶふっ君』を作っておきました。
もし手元に実行環境を用意できない人は、こちらからお試しください。

https://x.com/oliver_diary/status/1939175999427748115

Embed でメッセージの見た目をカスタマイズしてみる

先ほどの例では、プレーンなテキストだけで味気ないので、Embed を使いリッチなメッセージを送信してみましょう。

Embed で使用可能な全プロパティ

Discord Embed では以下のプロパティが使用できます。各プロパティの詳細と制限事項を理解することで、より柔軟なメッセージ作成が可能になります。

プロパティ 説明
title Embed のタイトル string
description メインの説明文 string
url タイトルをクリック可能なリンクにする string
timestamp タイムスタンプ(ISO8601 形式) string
color 左側の縦線の色(整数値) integer
footer フッター情報 object
image メイン画像 object
thumbnail 右上の小さい画像 object
author 著者情報 object
fields フィールドの配列 array

各プロパティの解説

1. title と url – クリック可能なタイトル

title と url - クリック可能なタイトル

コード(TypeScript)
{
  embeds: [
    {
      title: "ここにタイトル",
      url: "https://discorders.cafe/",
      description: "これは説明文の例です!",
    },
  ],
}

2. description – マークダウン対応

description - マークダウン対応

コード(TypeScript)
{
  embeds: [
    {
      title: "これは説明文の例です。Markdownも使えます!",
      description: `
**太字のテキスト**
*イタリック体*
~~取り消し線~~
__下線__
||スポイラーテキスト||

# 見出しは使えない
## これも使えない

\`インラインコード\`

\`\`\`javascript
// コードブロック
const message = "Hello, Discord!";
console.log(message);
\`\`\`

> 引用ブロック
> 複数行の引用も可能

- リスト項目1
- リスト項目2
  - ネストも可能

[リンクテキスト](https://discorders.cafe/)
`,
    },
  ],
}

3. author – 著者情報の表示

author - 著者情報の表示

コード(TypeScript)
{
  embeds: [
    {
      author: {
        name: "ですこうぇぶふっ君",
        url: "https://discorders.cafe/",
        icon_url: "https://assets.discorders.cafe/webhook/logo.png",
      },
      title: "ここにタイトル",
      description: "これは説明文の例です",
    },
  ],
}

4. fields – 構造化された情報表示

fields - 構造化された情報表示

コード(TypeScript)
{
  embeds: [
    {
      title: "フィールドの活用例",
      fields: [
        
        {
          name: "バージョン",
          value: "v1.0.0",
          inline: true,
        },
        {
          name: "リリース日",
          value: "2025/06/29",
          inline: true,
        },
        {
          name: "ステータス",
          value: "✅ Stable",
          inline: true,
        },
        
        {
          name: "変更内容",
          value: "- 新しいUI実装\n- パフォーマンス改善\n- バグ修正",
          inline: false,
        },
        
        {
          name: "\u200b", 
          value: "\u200b",
          inline: false,
        },
        {
          name: "📝 備考",
          value: "アップデート後は再起動が必要です",
          inline: false,
        },
      ],
    },
  ],
}

5. thumbnail と image – 画像の使い分け

thumbnail と image - 画像の使い分け

コード(TypeScript)
{
  embeds: [
    {
      title: "画像の配置例",
      description: "thumbnailは右上、imageは下部に表示",
      thumbnail: {
        url: "https://assets.discorders.cafe/webhook/sample02.jpeg",
      },
      image: {
        url: "https://assets.discorders.cafe/webhook/sample01.jpeg",
      },
    },
  ],
}

footer - フッター情報

コード(TypeScript)
{
  embeds: [
    {
      title: "お知らせ",
      description: "重要なお知らせです",
      footer: {
        text: "システム管理者より",
        icon_url: "https://assets.discorders.cafe/webhook/logo.png",
      },
      timestamp: new Date().toISOString(), 
    },
  ],
}

Embed の型定義例

interface EmbedField {
  name: string;
  value: string;
  inline?: boolean;
}

interface EmbedAuthor {
  name?: string;
  url?: string;
  icon_url?: string;
}

interface EmbedFooter {
  text: string;
  icon_url?: string;
}

interface EmbedImage {
  url: string;
}

interface Embed {
  title?: string;
  description?: string;
  url?: string;
  timestamp?: string;
  color?: number;
  footer?: EmbedFooter;
  image?: EmbedImage;
  thumbnail?: EmbedImage;
  author?: EmbedAuthor;
  fields?: EmbedField[];
}

interface WebhookMessage {
  content?: string;
  embeds?: Embed[];
}

const embedMessage: WebhookMessage = {
  embeds: [
    {
      title: "サーバーステータス",
      description: "現在のサーバー状況をお知らせします",
      color: 0x00ff00, 
      fields: [
        {
          name: "CPU使用率",
          value: "45%",
          inline: true,
        },
        {
          name: "メモリ使用率",
          value: "72%",
          inline: true,
        },
        {
          name: "ディスク容量",
          value: "234GB / 500GB",
          inline: false,
        },
      ],
      thumbnail: {
        url: "https://assets.discorders.cafe/webhook/sample02.jpeg",
      },
      footer: {
        text: "最終更新",
        icon_url: "https://assets.discorders.cafe/webhook/logo.png",
      },
      timestamp: new Date().toISOString(),
    },
  ],
};

fetch(webhookUrl, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(embedMessage),
});

サーバーステータス

また、discord.js の EmbedBuilder を使い、生成するのも手です。

高度なテクニック集

ここからはちょっと踏み込んだテクニックを紹介します。

ファイル添付

Discord の Webhook では、最大 10 ファイルまで添付することが可能です。なお、サイズ上限はサーバーブーストや Nitro 加入状況で変動します。

import * as fs from "fs";

const webhookUrl = "YOUR_WEBHOOK_URL";


async function sendMultipleFiles(
  message: string,
  filePaths: string[]
): PromiseResponse> {
  const form = new FormData();
  
  form.append("payload_json", JSON.stringify({ content: message }));
  
  filePaths.slice(0, 10).forEach((path, index) => {
    
    const fileName = path.split("https://zenn.dev/").pop();
    if (!fileName) return;
    form.append(fileName, new Blob([fs.readFileSync(path)]), fileName);
  });
  
  const response = await fetch(webhookUrl, { method: "POST", body: form });
  return response;
}

sendMultipleFiles("ファイル送信テスト", ["", ""]);

メッセージの編集と削除

Webhook URL に wait=true を付与すると、レスポンスからメッセージの ID が取得できるようになります。それを利用して、編集と削除を試してみましょう。

const webhookUrl = "YOUR_WEBHOOK_URL";


async function sendAndEditAndDeleteMessage(): Promise"ok"> {
  
  const response = await fetch(`${webhookUrl}?wait=true`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      content: "処理中...",
      embeds: [{ title: "⏳ タスク実行中", color: 0xffff00 }],
    }),
  });

  
  const message = (await response.json()) as { id: string };

  
  await new Promise((resolve) => setTimeout(resolve, 3000));

  
  await fetch(`${webhookUrl}/messages/${message.id}`, {
    method: "PATCH",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      content: "完了!",
      embeds: [
        {
          title: "✅ タスク完了",
          color: 0x00ff00,
          description: "全ての処理が正常に完了しました",
        },
      ],
    }),
  });

  
  await new Promise((resolve) => setTimeout(resolve, 3000));

  
  await fetch(`${webhookUrl}/messages/${message.id}`, { method: "DELETE" });
  return "ok";
}

sendAndEditAndDeleteMessage();

スレッド / フォーラム対応

Webhook でスレッドにメッセージを送信することも可能です。
特にフォーラムチャンネルでは thread_name を指定することで、新しいスレッドを作成することも可能です。

const webhookUrl = "YOUR_WEBHOOK_URL";


async function sendToThread(
  threadId: string,
  message: string
): PromiseResponse> {
  const url = `${webhookUrl}?thread_id=${threadId}`;

  return fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ content: message }),
  });
}


async function createForumThread(
  name: string,
  message: string
): PromiseResponse> {
  return fetch(webhookUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ content: message, thread_name: name }),
  });
}

sendToThread("", "Hello Thread");
createForumThread("", "Hello Forum");

【補足】Rate Limit について

Discord Webhook には以下の Rate Limit があります。

  • チャンネルあたり、1 分間に最大 30 メッセージ まで送信可能
  • 401/403/429 など 無効リクエスト合計が 10,000 回/10 分 を超えると一時的に API へ接続不可に
  • X-RateLimit-Remaining ヘッダ が 0 になったら X-RateLimit-Reset-After ヘッダ 秒待機

特に、最後の HTTP ヘッダーですが、公式情報ではありませんが、現状は 1 秒間に 5 回ほど送ると Limit に達するらしいです。

特に Rate Limit 周りは変わる可能性がありますので、公式の最新ドキュメントを確認するのが良いでしょう。

まとめ

Discord の Webhook は Bot と違い、発行も検証も手軽です。
プログラミング初心者でも簡単に扱え、学習テーマとしても便利ですので、ぜひこの記事を参考にして、プログラミングを始めてみてはどうでしょうか?

実際のユースケースとしては、サービスの通知を検知したり、監視やアラート、ログ収集や定期レポート、GAS との連携など、活躍できる場面がとても多く、個人の Discord 鯖でプライベート運用するソフトウェアエンジニアも多く散見されます。ぜひ、この機会に活用してみると良いでしょう。

なお、双方向のやり取りやリアクション検知、音声チャンネル操作、ユーザー情報取得などが必要な場合は Bot 実装が必要です。Bot 周りの実装は、後日別の記事で紹介したいと思いますので、ぜひウォッチしていただけますと幸いです。

リンク集

公式ドキュメント。詳細な仕様を知りたい方はここを見ましょう。

Webhook を簡単に試せる Embed 早見表。とりあえず書き方忘れたらここを見ましょう。

Discord が好きな人が集まる鯖。盛り上げていきます。

X で Discord の発信をしていきますので、よかったらフォローお願いします。



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -