無料でDiscordBotを運用できる「Discord Hono」を使ってみた 【初学者向け】
常時稼働は出来ませんが、Cloudflare WorkersでDiscordBotを運用できるライブラリ「Discord Hono」を紹介します。
目次
- はじめに
- 従来のDiscord Botはどう動いているか
- サーバーレスとCloudflare Workers
- サーバーレスとは
- Cloudflare Workersとは
- できること・できないこと
- 前提
- 事前準備:Developer Portalでの設定
- 1. アプリケーションの作成
- 2. 各種キーの取得
- 3. Botトークンの発行
- テスト用Discordサーバーの準備
- プロジェクトのセットアップ
- Cloudflare Workersプロジェクトの作成
- 環境変数の設定
- wrangler.jsonc確認・編集
- package.jsonにスクリプトを追加する
- Botを実装する
- src/index.ts を作成する
- src/register.ts を作成する
- コマンドの登録とデプロイ
- コマンドをDiscordに登録する
- 本番環境の環境変数を設定する
- Cloudflare Workersへデプロイする
- INTERACTIONS ENDPOINT URLを設定する
- BotをサーバーへInviteする
- 実践:ボタンインタラクション付きのダイスコマンド
- register.ts にコマンドを追加する
- index.ts を更新する
- 再登録してデプロイする
- おわりに
- Footnotes
#はじめに
Discord Botを運用しようとすると、サーバーの用意をしなければならず、コスト面などで非常にハードルが高いと感じます。無料枠で運用することも可能ですが、どこまでのスケールが無料なのかや、自動スリープ対策等ハック的なことをしなければならなかったりと下調べも簡単ではありません。
そこで、Cloudflare Workersで動かせるDiscord Botライブラリである、Discord Honoを紹介します。
#従来のDiscord Botはどう動いているか
まず、一般的なDiscord Botがどのように動作しているかを簡単に説明します。
従来のBotはWebSocket1と呼ばれる仕組みを使って、Discordのサーバーと常時接続しています。ユーザーがメッセージを送ったり、コマンドを使ったりすると、その情報がリアルタイムでBotに届き、Botが反応します。
この方式だと、Botは24時間常にプログラムを起動し続けるサーバー2が必要です。これがコストや管理の手間がかかる原因です。
#サーバーレスとCloudflare Workers
#サーバーレスとは
サーバーレス3とは、「サーバーを自分で管理しない」仕組みのことです。サーバーが存在しないわけではなく、クラウドサービス側がサーバーを管理してくれます。プログラムは「リクエストが来たときだけ起動」し、処理が終わると停止します。そのため待機中のコストがかからず、スケーリングも自動で行われます。
#Cloudflare Workersとは
Cloudflare Workers4は、Cloudflareが提供するサーバーレス実行環境です。世界中に分散したエッジサーバー5上でコードが実行されるため、ユーザーの近くで高速に動作します。無料プランでは1日10万リクエストまで使用できます。
Discord HonoはこのCloudflare Workersで動作するDiscord Botライブラリです。WebSocketによる常時接続の代わりに、HTTP6を使ってDiscordからのイベントを受け取ります。
#できること・できないこと
サーバーレス型BotであるDiscord Honoと、従来のサーバー型Botではできることに違いがあります。
| サーバー型Bot | Discord Hono(サーバーレス) | |
|---|---|---|
| スラッシュコマンドへの返答 | ✅ | ✅ |
| ボタン・モーダル等のインタラクション | ✅ | ✅ |
| REST API7の利用 | ✅ | ✅ |
| Cron8による定期実行 | ✅ | ✅ |
| VCへの接続(音楽Botなど) | ✅ | ❌ |
| メッセージ監視・自動返答 | ✅ | ❌ |
| 無料でダウンタイムなし | ❌(対策が必要) | ✅ |
| 大規模スケーリング | コストがかかりやすい | ✅ |
最大のデメリットは、WebSocketを使った常時接続が必要な機能が使えないことです。具体的には以下ができません。
- ボイスチャンネルへの接続(音楽Bot、会話Botなど)
- メッセージの監視・自動返答(特定ワードへの反応など)
- Botのステータス表示のリアルタイム更新
逆に、スラッシュコマンドへの応答・ボタンやモーダルなどのインタラクション・定期実行が中心のBotであれば、Discord Honoで十分実用的に運用できます。
💡 どんなBotに向いている?
「ユーザーがコマンドを打ったら何かしてくれる」という用途がメインのBotに最適です。情報検索・翻訳・ランダム抽選・ゲームサポートなどが挙げられます。
上記のことがしたい場合は素直にサーバーを借りるのが正解です。
#前提
本記事を進めるに当たって、以下のことが必要です。
- Discordのアカウントがあること
- Cloudflareのアカウントがあること
bun9がインストールされていること - bunでなくても、node(npm/pnpm) や deno等でも問題ありません。- VSCodeがインストールされていること - エディタであれば何でも良いです。
#事前準備:Developer Portalでの設定
Discord Botを作るには、まずDiscord Developer Portalでアプリケーションを作成し、トークン10などを取得する必要があります。
#1. アプリケーションの作成
- Discord Developer Portal にアクセスする
- 右上の「New Application」をクリックする
- Botの名前を入力して「Create」をクリックする

#2. 各種キーの取得
アプリケーション作成後、左メニューの「General Information」を開き、以下の2つを控えておきます。
- APPLICATION ID:BotのアプリケーションID
- PUBLIC KEY:リクエストの署名検証11に使用するキー
#3. Botトークンの発行
- 左メニューの「Bot」タブを開く
- 「Reset Token」をクリックしてトークンを発行する
- 表示されたトークンをコピーして控えておく
⚠️ 注意
トークンは一度しか表示されません。ページを閉じた後は再確認できないので、必ずコピーして安全な場所に保存してください。
#テスト用Discordサーバーの準備
事前にBotをテストするサーバーを用意してください。そして、そのサーバーのIDをコピーします。
サーバーIDは、ブラウザであればdiscord.com/channels/[server-id]/[channel-id] の形式なので、server-idの部分をコピーしてください。
デスクトップアプリであれば、設定画面から、開発者モードをONにしたうえで、サーバー設定などを確認する場所の一番下にサーバーIDをコピーがあります。

#プロジェクトのセットアップ
#Cloudflare Workersプロジェクトの作成
bunx create-cloudflare@latest discord-hono-botcd discord-hono-botいくつか質問されます。以下のように選択してください。
What would you like to start with?→ Hello World exampleWhich template would you like to use?→ Worker onlyWhich language do you want to use?→ TypeScriptDo you want to use git for version control?→ Yes(任意)Do you want to deploy your application?→ No(後で手動でデプロイします)
続いて、discord-hono と、DiscordのAPIの型を提供してくれるライブラリをインストールします。
bun add discord-honobun add -D discord-api-types#環境変数の設定
プロジェクトルートに .env ファイルを作成し、Developer Portalで控えた値を設定します。このファイルはローカルでのコマンド登録スクリプト実行時に使用します。
DISCORD_APPLICATION_ID=your_application_idDISCORD_PUBLIC_KEY=your_public_keyDISCORD_TOKEN=your_bot_tokenDISCORD_TEST_GUILD_ID=your_test_server_id.gitignore に .env が含まれているか確認し、含まれていない場合は追記してください。
#wrangler.jsonc確認・編集
wrangler.jsonc12を開き、以下のようになっているか確認します。
{ "$schema": "node_modules/wrangler/config-schema.json", "name": "discord-hono-bot", "main": "src/index.ts", "compatibility_date": "2026-04-15", // 今日の日付でおk! "observability": { "enabled": true }, "upload_source_maps": true, "compatibility_flags": [ "nodejs_compat" ]}#package.jsonにスクリプトを追加する
package.json の scripts セクションを以下のように編集します。
{ "scripts": { "dev": "wrangler dev", "deploy": "wrangler deploy", "register": "bun --env-file=.env src/register.ts" }}#Botを実装する
#src/index.ts を作成する
src/index.ts がBotのメインハンドラーです。Cloudflare Workersへのリクエストをここで受け取り、コマンドに応じて処理します。まずは /ping に「Pong! 🏓」と返すだけのシンプルな実装から始めます。
import { DiscordHono } from 'discord-hono'
// Cloudflare Workersの環境変数の型定義type Env = { Bindings: { DISCORD_TOKEN: string DISCORD_PUBLIC_KEY: string DISCORD_APPLICATION_ID: string }}
const app = new DiscordHono<Env>() .command('ping', (c) => c.res('Pong! 🏓'))
export default appc.res() はコマンドへの返答メソッドです。文字列を渡すと、その内容がDiscordにメッセージとして送信されます。
名前の通り、かなりhonoに近い書き方なので、honoを知っていれば学習コストも低いでしょう。
#src/register.ts を作成する
Discordのスラッシュコマンドは、Discord APIに事前に登録しておく必要があります13。src/register.ts として登録用スクリプトを作成します。
import { Command, register } from 'discord-hono'
const commands = [ new Command('ping', 'Pongと返答します'),]
register( commands, process.env.DISCORD_APPLICATION_ID, process.env.DISCORD_TOKEN,)#コマンドの登録とデプロイ
#コマンドをDiscordに登録する
bun run registerコマンドの登録はDiscord APIへのリクエストです。登録自体はすぐ完了しますが、Discordのクライアントに反映されるまで最大1時間かかる場合があります。
#本番環境の環境変数を設定する
Cloudflare Workersに .env ファイルはそのまま使えません。本番用のシークレット14は、wrangler secret put コマンドで設定します。
bunx wrangler secret put DISCORD_APPLICATION_IDbunx wrangler secret put DISCORD_PUBLIC_KEYbunx wrangler secret put DISCORD_TOKENそれぞれのコマンドを実行すると、対話的に値の入力を求められます。.env に記載した対応する値を入力してください。
#Cloudflare Workersへデプロイする
bun run deployデプロイ15が完了すると、以下のようなURLが発行されます。
https://discord-hono-bot.your-subdomain.workers.dev#INTERACTIONS ENDPOINT URLを設定する
Discordはコマンドが実行されると、事前に登録したURL(エンドポイント16)にHTTPリクエストを送信します。このURLをDeveloper Portalに設定します。
- Discord Developer Portalの「General Information」タブを開く
- 「INTERACTIONS ENDPOINT URL」にデプロイで発行されたWorkerのURLを入力する
- 「Save Changes」をクリックする
Discordがエンドポイントの疎通確認を行うため、この時点でWorkerが正常に動いていることが重要です。保存に成功すれば、BotがDiscordからのインタラクションを受け取れる状態になります。
#BotをサーバーへInviteする
- Discord Developer Portalの「OAuth2」タブを開く
- 「OAuth2 URL Generator」を選択する
- SCOPES で
botとapplications.commandsにチェックを入れる - 生成されたURLをブラウザで開き、招待するサーバーを選択する
招待後、Discordのチャットで /ping と入力すると「Pong! 🏓」と返ってくるはずです 🎉
#実践:ボタンインタラクション付きのダイスコマンド
Discord Honoはボタン等のコンポーネントインタラクション17にも対応しています。ここでは、「もう一度振る」ボタン付きのダイスロールコマンドを実装してみます。ゲームサーバーなどで実用的に活用できるコマンドです。
#register.ts にコマンドを追加する
import { Command, register } from 'discord-hono'
const commands = [ new Command('ping', 'Pongと返答します'), new Command('dice', 'サイコロを振ります'), // 追加]
register( commands, process.env.DISCORD_APPLICATION_ID, process.env.DISCORD_TOKEN,)#index.ts を更新する
src/index.ts をボタンインタラクションに対応するよう更新します。
import { DiscordHono, Components, Button } from 'discord-hono'
type Env = { Bindings: { DISCORD_TOKEN: string DISCORD_PUBLIC_KEY: string DISCORD_APPLICATION_ID: string }}
// 1〜6のランダムな整数を返すconst rollDice = () => Math.floor(Math.random() * 6) + 1
// ダイス結果のメッセージ(ボタン付き)を生成する関数const diceResponse = (result: number) => ({ content: `🎲 **${result}** が出ました!`, components: new Components().row( new Button('reroll', 'もう一度振る 🎲'), ),})
const app = new DiscordHono<Env>() // /ping コマンド .command('ping', (c) => c.res('Pong! 🏓')) // /dice コマンド:初回はコマンドとして返答 .command('dice', (c) => c.res(diceResponse(rollDice()))) // 「もう一度振る」ボタンが押されたとき:メッセージを更新 .component('reroll', (c) => c.resUpdate(diceResponse(rollDice())))
export default app実装のポイントは2つあります。
.component()の第1引数('reroll')をnew Button()の第1引数(カスタムID)と一致させることで、ボタン押下時のハンドラーを紐付けていますc.resUpdate()を使うことで、ボタンを押したとき元のメッセージを新しい結果で上書きできます。c.res()だと新しいメッセージが追加されてしまうため、resUpdateを使うと「結果が更新される」自然なUXを実現できます
#再登録してデプロイする
bun run registerbun run deploy/dice を実行するとサイコロが振られ、「もう一度振る 🎲」ボタンを押すたびに結果が更新されます。
#おわりに
Discord Honoを使うことで、サーバーの管理不要・無料ダウンタイムなしでDiscord Botを運用できました。常時接続が不要なBotであれば、Discord Honoは非常に優れた選択肢です。
今回紹介したボタン以外にも、モーダル(入力フォーム)・セレクトメニュー・オートコンプリート・Cronトリガーによる定期実行など豊富な機能が揃っています。当然、Cloudflareエコシステム(D1,R2,KV等)もそのまま使用できるので、実践的なアプリケーションも作成することも可能です。ぜひ公式ドキュメントも参照しながら、機能を拡張してみてください。
間違っている箇所があればXのDMまでお知らせください!即座に修正いたします。
#Footnotes
-
WebSocketとは、サーバーとクライアントが一度接続を確立したあと、どちら側からでも好きなタイミングでデータを送受信できる通信方式です。通常のHTTPが「リクエストしたら返事が来る」一方通行の会話なのに対し、WebSocketは「いつでも話しかけられる」電話のようなイメージです。チャットアプリやリアルタイムゲームで広く使われています。 ↩
-
ここでのサーバーとは、プログラムを常時動かし続けるコンピューターのことです。VPSやクラウドVM(AWS EC2、Google Compute Engineなど)が該当します。無料枠があるサービスも存在しますが、自動スリープや時間制限があることが多いです。 ↩
-
サーバーレスとは、開発者がサーバーの管理・調達を気にせず、コードの実行だけに集中できるクラウドの仕組みです。「関数」としてコードを登録しておくと、リクエストが来たときだけ自動で起動します。AWS LambdaやCloudflare Workersが代表例です。 ↩
-
Cloudflare Workersは、Cloudflareが提供するサーバーレスプラットフォームです。無料プランでは1日10万リクエストまで利用できます。Botのコマンド応答程度であれば無料枠で十分運用できます。 ↩
-
エッジサーバーとは、ユーザーの地理的に近い場所に配置されたサーバーのことです。遠くの中央サーバーと通信するより遅延が少なく、高速なレスポンスが実現できます。 ↩
-
HTTP(HyperText Transfer Protocol) とは、WebブラウザがWebサーバーとデータをやり取りするための基本的な通信プロトコルです。「リクエスト(お願い)」を送ると「レスポンス(返答)」が返ってきます。 ↩
-
REST APIとは、HTTPを使ってデータのやり取りを行うWebサービスの設計方式のことです。Discord APIもREST APIとして提供されており、メッセージの送信やユーザー情報の取得などをHTTPリクエストで行えます。 ↩
-
Cronとは、指定した時刻や間隔でプログラムを自動実行する仕組みです。「毎日9時に天気予報を送信する」といった定期実行Botに活用できます。 ↩
-
Bunとは、Node.jsの代替として登場した高速なJavaScript/TypeScriptランタイムです。パッケージのインストール(
npm install相当)もbun addで行えます。TypeScriptをそのまま実行できる点が特徴で、別途コンパイル用ツールは不要です。 ↩ -
トークンとは、BotがどのアカウントとしてDiscordで動作するかを認証するための「合言葉」のようなものです。これが流出すると第三者がBotを乗っ取れてしまうため、厳重に管理する必要があります。 ↩
-
署名検証とは、Discordから届いたリクエストが本物かどうかを確認する仕組みです。悪意のある第三者が偽のリクエストを送り込むのを防ぎます。Discord Honoが内部で自動的に処理してくれるため、開発者が特別なコードを書く必要はありません。 ↩
-
wrangler.jsoncは、Cloudflare Workersプロジェクトの設定ファイルです。プロジェクト名や使用するファイルのパスなどを定義します。コメント付きJSON形式で記述します。 ↩
-
Discord Botのスラッシュコマンドは、Discordのサーバーに「このコマンドが使えますよ」と申告することで、ユーザーが
/を入力したときの補完リストに表示されるようになります。コードを変更しただけではコマンドは増えないため、この登録スクリプトの実行が必要です。 ↩ -
Cloudflare Workersにおけるシークレットとは、本番環境でのみ使用する暗号化された環境変数のことです。コードとは分離して管理され、Cloudflareのダッシュボードから管理できますが、値そのものは暗号化されて保護されています。 ↩
-
デプロイとは、作成したプログラムを実際にサーバー(今回はCloudflare Workers)に配置して、外部からアクセスできる状態にすることです。 ↩
-
エンドポイントとは、APIやWebサービスへのアクセス先となるURLのことです。ここでは「DiscordがBotにリクエストを送る宛先」を意味します。 ↩
-
コンポーネントインタラクションとは、Discordのメッセージに埋め込まれたボタン・セレクトメニュー・モーダル(入力フォーム)などのUI要素をユーザーが操作したときに発生するイベントのことです。 ↩