【Python対応】Discord Webhookの使い方|Botとの違い・設定方法・通知を送るサンプルコード

目次

はじめに

以前、LINE Notifyの代替として、Discord Botを使ってメッセージや画像を通知する方法を紹介しました。
前回の記事はこちらです。

前回はDiscord Developer PortalでBotを作成し、BotトークンとチャンネルIDを取得して、PythonからDiscordへ通知しました。この方法でも問題なく通知できます。しかし、実際に使い続けてみると、単純にメッセージや画像を送りたいだけなら、Discord BotよりもWebhookのほうがはるかに簡単であることに気付きました。

Discord公式ドキュメントでも、Incoming WebhookはBotユーザーや通常の認証を用意せず、生成されたURLを使ってチャンネルへメッセージを投稿できる仕組みとして説明されています。この記事では、次の内容を電子工作・Python初学者向けに解説します。

  • Discord Webhookの仕組み
  • Webhook URLの作成方法
  • Pythonから文字を送信する方法
  • Pythonから画像を送信する方法
  • Webhookを部品化して別のプログラムから呼び出す方法
  • Discord BotとWebhookの違い
  • Botにしかできないこと
  • Discord Botを使ってメッセージに応答する方法
  • Webhook URLやBotトークンを安全に管理する方法

Raspberry Piのセンサー監視、カメラ撮影、バス時刻通知、サーバー監視などにも、そのまま応用できます。

Discord Webhookとは

Webhookは、指定されたURLへHTTPリクエストを送信することで、外部サービスを動かす仕組みです。Discordの場合は、Discord側で専用のWebhook URLを作成し、そのURLにデータを送ると、指定したチャンネルへメッセージが投稿されます。

イメージとしては、次のようになります。

Raspberry Piやパソコン
        │
        │ HTTP POST
        ▼
Discord Webhook URL
        │
        ▼
指定したDiscordチャンネル

Pythonプログラムから見ると、Webhook URLはDiscordへ通知を届けるための専用住所です。郵便に例えると、次のような関係です。

Webhook URL = 通知先の住所
POSTデータ  = 送る荷物
Discord     = 荷物を受け取って表示する場所

Webhook URLへ次のようなJSONデータを送るだけで、Discordへ文字を投稿できます。

{
  "content": "Raspberry Piからの通知です"
}

これがDiscord Webhookの基本原理です。

WebhookとAPIの関係

WebhookとAPIは似ていますが、まったく同じものではありません。一般的なAPIでは、プログラム側からサービスへ要求を送ります。

プログラム
   │
   │ データをください
   ▼
サービスのAPI

一方、一般的なWebhookは、何らかのイベントが発生したときに、あらかじめ登録されたURLへ情報を送るために使われます。

サービスでイベント発生
   │
   │ 自動通知
   ▼
登録されたWebhook URL

ただし、DiscordのIncoming Webhookは少し用途が異なります。こちらからDiscordのWebhook URLへPOSTリクエストを送ることで、Discordチャンネルにメッセージを投稿します。そのため、次のように覚えておけば十分です。

Discord Webhookは専用URLへデータを送るだけでDiscordに投稿できる簡易的な通知用インターフェース

Discord BotとWebhookの大きな違い

先に結論を示すと、次のように使い分けます。

やりたいこと適した方法
一方的に文字を通知するWebhook
一方的に画像を送るWebhook
センサー異常を通知するWebhook
定期実行結果を通知するWebhook
ユーザーの発言に返信するBot
コマンドを受け付けるBot
リアクションや参加イベントを検知するBot
DiscordからRaspberry Piを操作するBot

つまり、

通知だけならWebhook、Discordからの入力も処理するならBot

と考えると分かりやすいです。

Discord Webhookを作成する

ここから実際にWebhookを作成します。Discord Botを作成するときはDiscord Developer Portalを使いましたが、WebhookはDiscordのサーバー設定から作成できます。Developer Portalでアプリケーションを作る必要はありません。

前提条件

Webhookを作成するには、次のものが必要です。

  • Discordアカウント
  • 自分が管理できるDiscordサーバー
  • 通知先となるテキストチャンネル
  • Webhookを管理できる権限

個人用の通知であれば、自分だけが参加するDiscordサーバーで十分です。
PCでの作業になりますので、ご注意ください

STEP
Discordサーバーを開く

Webhookを設定したいDiscordサーバーを開きます。サーバー名を右クリックし、次の項目を選択します。

サーバ設定
STEP
連携サービスを開く

サーバー設定の中から、次の項目を開きます。

連携サービス
STEP
ウェブフックを作成する

「ウェブフック」または「Webhooks」を選択し、新しいWebhookを作成します。

画面の表示に従って、次の内容を設定します。

  • Webhookの名前
  • Webhookのアイコン
  • 通知を投稿するチャンネル

Webhookの名前は、何から送られてきた通知なのか分かる名前がおすすめです。

STEP
Webhook URLをコピーする

Webhookの設定画面にある、Webhook URLをコピーします。URLは、おおむね次のような形式になっています。“discordapp”となっている場合があります。使用する時”app”を削除するとうまくいきます。

https://discord.com/api/webhooks/数字/長い文字列

このURLがあれば、Pythonなどの外部プログラムからDiscordへ投稿できます。ただし、非常に重要な注意点があります。

Webhook URLはパスワードと同じです!

Webhook URLを知っている人は、そのWebhookを使ってチャンネルへ投稿できてしまいます。ブログ、GitHub、SNS、スクリーンショットなどに、実際のURLを掲載してはいけません。

PythonからWebhookで文字を送信する

LINE Notifyと同じことを実現してみます。LINEより若干複雑になっていますが、使い方はシンプルです。
取得したトークン、チャンネルIDを入力し、discord_send_message.pyとして保存してください。

import requests
import os

class DiscordSendMessage:
    __default_token: str = '****.*********'  #トークン
    __default_channel_id: str = '*********'  #チャンネルID

    def __init__(self, token: str = __default_token, channel_id: str = __default_channel_id):
        self.__token = token
        self.__channel_id = channel_id

    def send_discord_message(self, file_path: str = None, message: str = ""):
        url = f"https://discord.com/api/v10/channels/{self.__channel_id}/messages"
        headers = {
            "Authorization": f"Bot {self.__token}"
        }

        # ファイルが指定されていない or 存在しない場合は、メッセージのみ送信
        if not file_path or not os.path.isfile(file_path):
            headers["Content-Type"] = "application/json"
            data = {
                "content": message
            }
            response = requests.post(url, headers=headers, json=data)
            if response.status_code == 200:
                print("メッセージのみ送信完了")
            else:
                print(f"メッセージ送信失敗: {response.status_code}, {response.text}")
            return

        # ファイルが存在する場合は、ファイル + メッセージを送信
        try:
            with open(file_path, 'rb') as file:
                files = {
                    'file': (os.path.basename(file_path), file)
                }
                data = {
                    "content": message
                }
                response = requests.post(url, headers=headers, data=data, files=files)

            if response.status_code == 200:
                print(f"ファイル送信完了: {file_path}")
            else:
                print(f"ファイル送信失敗: {response.status_code}, {response.text}")
        except Exception as e:
            print(f"ファイル送信中にエラーが発生しました: {e}")
            # 送信失敗しても、メッセージだけ送る
            self.send_file(file_path=None, message=message)

if __name__ == "__main__":
    discord_bot = DiscordSendMessage()
    file_path = r'C:\Users\***\***.jpg'
    message = 'abcdefg'
    discord_bot.send_discord_message(file_path=file_path,message=message)

別のプログラム(main.py)で使用するコードです。
わかりやすいように、discord_send_message.pyとmain.pyは同じ階層に保存してください。

import requests
import os

import discord_send_message

discord_bot = discord_send_message.DiscordSendMessage() # インスタンス化
file_path = 'C:\***\***\***\***.jpg' # 送信したいファイルパス
message = 'abcdef' # 送信したい文字列
discord_bot.send_discord_message(file_path=file_path,message=message)

メッセージを特定の人にメンションしたい場合は、以下のようにするとうまくいきます。
<@{ユーザID}> です

discord_bot.send_discord_message(file_path=url_images_data+"kaime.jpg", message=f'<@{******}>'+comment)

まとめ

botほどの機能が不要な場合はウェブフックがとても簡単です。是非試してみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次