1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DiscordenoでDiscord Botを作ってみた

Last updated at Posted at 2025-02-19

はじめに

完全無料で常時稼働できる Discord Bot の公開先として Deno を試してみたので備忘録を兼ねて記事にまとめてみました。

本記事の内容は2025年2月時点での情報であることに注意してください。

Denoとは

Denoは、JavaScript および TypeScript の実行環境であり、Node.js の開発者である Ryan Dahlによって開発されました。Deno は、Node.js における10個の設計ミスを解決することを目的として開発されました。代表的なものとして以下のような特徴が挙げられます。

  • セキュリティ強化:デフォルトでファイル・ネットワーク・環境変数へのアクセスを制限
  • TypeScript の標準サポート:追加の設定なしで TypeScript を直接実行可能
  • ES モジュールの採用:import を使用し、URL から直接モジュールを取得できる

本記事の構成

本記事では、Discordeno を用いて Discord Bot を開発し、デプロイするまでの手順を解説します。
1. Discord Botの準備
2. Denoをインストールする
3. 設定ファイルの用意
4. オウム返しBot の実装
5. Denoにデプロイする

開発環境

名前 バージョン
Deno 2.1.9
TypeScripts 5.6.2
Discordeno 20.0

実装

1. Discord Bot の準備

  1. デベロッパーアカウントを作成するために以下のサイトにアクセスします

    Discord Developer Portal

  2. 右上のNew applicationをクリックします
    img_1.png

  3. Bot の名前を設定しCreateをクリックします(nameは後から変更可能)

    img_2.png

  4. BotタブのTOKENにあるReset Tokenをクリックするとトークンをコピーできるようになります

    img_3.png

  5. BotタブのPrivileged Gateway IntentsSERVER MEMBERS INTENTMESSAGE CONTENT INTENTにチェックを入れます

    img_4.png

    SERVER MEMBERS INTENT:Bot がサーバーメンバーの情報(参加・退出・ニックネーム・ロール変更など)をリアルタイムで取得できるようになります。

    MESSAGE CONTENT INTENT:Bot がサーバー内のメッセージの内容(テキスト)を読み取れるようになります。

  6. OAuth2タブのOAuth2 URL GeneratorにあるScopesbotチェックを入れることで参加させるための認証 URL を発行できます

    img_5.png

  7. 発行した URL にアクセスすると管理者権限のあるサーバに追加できるようになります

    img_6.png

  8. 必要に応じたロールを設定します。一般ユーザと同様に Discord 上で設定するか、OAuth2タブのBot Permissionsから設定できます。

    img_7.pngimg_8.png

2. Deno をインストールする

npm がインストールされているという前提で進めます。

npmのインストール確認方法
npm -v

PowerShell を管理者権限で開き以下のコマンドを実行して Deno をインストールします。

iwr https://deno.land/install.ps1 -useb | iex

以下のコマンドでインストールできているか確認します。

deno --version

# deno 2.1.9 (stable, release, x86_64-pc-windows-msvc)
# v8 13.0.245.12-rusty
# typescript 5.6.2

これで Deno のインストールは完了です。

3. 設定ファイルの用意

  1. deno.jsoncというファイルを作成します

    deno.jsonc
    {
      "lock": false, //deno.lock(モジュールのバージョン管理ファイル)を生成しないようにする
      "tasks": {
        "start": "deno run -A --watch ./main.ts" // 実行するファイルパス
      },
      "imports": {
        "$std/": "https://deno.land/std@0.224.0/",
        "@discordeno/": "https://deno.land/x/discordeno@20.0.0/" // 任意のバージョン
      }
    }
    
  2. .evnというファイルを作成し、Discord Developer Portal のBotタブに記載されているTOKENをコピーして貼り付けます

    .env
    TOKEN=Th1si5d1sc0dTok3N
    

4. オウム返し Bot

ユーザのメッセージをそのまま返すBotを実装します。

main..ts
import {
  createBot,
  getBotIdFromToken,
  startBot,
  Intents,
} from "@discordeno/mod.ts";
import "$std/dotenv/load.ts";

// .env からトークンを取得
const token = Deno.env.get("TOKEN");

const bot = createBot({
  token,
  botId: BigInt(getBotIdFromToken(token)),
  intents: Intents.Guilds | Intents.GuildMessages | Intents.MessageContent,
  events: {
    // 起動時の処理
    ready: (_bot, payload) => {
      console.log(`✅ Bot is online!`);
    },

    // メッセージ受信時の処理
    messageCreate: async (bot, message) => {
      if (message.authorId === bot.id) return; // ボット自身のメッセージを無視
      await bot.helpers.sendMessage(message.channelId, {
        content: message.content,
      });
    },
  },
});

// ボットの常時起動
Deno.cron("Continuous Request", "*/3 * * * *", () => {
  console.log("🔄 Bot is active!");
});

// ボットを起動
await startBot(bot);

Deno Deploy では、5 分間リクエストがないとスリープ状態になる仕様があります。そこでDeno.cronを用いてログを出力し、Bot を寝かさないようにします。Deno.cron は、Deno のスケジュール実行機能で、指定した間隔で定期的に関数を実行するためのものです。今回のコードでは、ボットを 3 分ごとに起動してログを出力する仕組みになっています。

*/3 * * * *の部分が corn 式で、以下のような構造になっています。

曜日
0 - 59 0 - 23(UTC 時間) 1 - 31 1 - 12 0 - 6(日曜 → 土曜)

注意したいのが、UTC(協定世界時)を用いていることです。UTC = JST - 9時間と表現されます。現在は UTC に置き換わりつつありますが、GMT と同じ時間を示します。

Bot を起動するには以下のコマンドを実行します。

deno task start

これでテキストチャンネルにメッセージを送信すると Bot が返信してくれます。

img_8.png

5. Deno にデプロイする

  1. 作成したプログラムを GitHub リポジトリにプッシュしておきます。
    トークンなどを記載したファイルは.gitignore に追加しておきましょう。

  2. Deno Deployにアクセスし、GitHub と連携する

    img_9.png

  3. 右上のNew Projectをクリックします

    img_10.png

  4. 先ほどプッシュしたリポジトリを選択します

    img_11.png

  5. Project ConfigurationPtoject Nameを設定し、Entrypointに実行ファイル名を指定します。すべて設定できたらDeploy Projectをクリックしてデプロイを開始します。

    img_12.png

  6. トークンを.envなどで管理しているとトークンを取得できずに以下のようにデプロイに失敗します。そのため Deno 側で環境変数を設定します。画面右上のSettingsをクリックします。

    img_13.png

  7. Environment VariablesAdd VariableをクリックしKEYに環境変数名、VALUE.envで設定していたトークンを入力します。Save (1 new)を押して設定完了です。

    img_14.png

    デプロイが成功すれば Bot が常時オンラインになります。

    うまくいかなかったら…

    img_15.png
    Environment Variablesでトークンを設定した後も上記のようなエラーが吐かれるなら、手動で GitHub に空コミットをプッシュしてみると良いかもしれません。

詰まったところ

  • サーバのメンバーをオフラインメンバーも含めて取得

    BotタブのPrivileged Gateway Intentsで設定できるServer Members IntentおよびPresence Intentが必要
    img_16.png

  • アバター画像の取得

    img_17.png

    Discord のアバター画像の URL は以下のように管理されています。

    https://cdn.discordapp.com/avatars/userId/avatarHash.png
    

    avatarHashの部分は 16 進数で表現されています。しかし Discordeno のmember.user.avatarで取得できるものは 10 進数で表現されていました。これを 16 進数に変換、かつ最初の一桁目を落とす必要がありました。

    `https://cdn.discordapp.com/avatars/${userId}/${member.user.avatar.toString(16).slice(1)}.png`
    
  • ユーザ-のメインプロフィールの表示名を取得

    左のユーザープロフィールの表示名(アドミン)は取得することができませんでした。右のサーバプロフィールのサーバニックネーム(Admin)はmember.nickで取得でき、自分のアカウントのユーザ名(Adm1n_d4mmyUsern4me)はmember.user.usernameで取得できました。
    img_18.png

    memberオブジェクト、userオブジェクトを見てみてもglobalNamedisplayNameなどは見つけられず、ユーザの表示名の取得はあきらめました。(どなたか取得方法を知っていたら教えてください;;)

    member {
      id: xxxx,
    	...,
      user: {
        id: xxxx,
        username: "Adm1n_d4mmyUsern4me",
        ...
      },
      nick: "Admin",
      roles: [],
      ...
    }
    

おわりに

今回、Discordeno を使って Discord Bot を作成してみました。体感ですが公式ドキュメントがあまり充実しておらず、分かりづらかったです。また、バージョン間の互換性の問題で正常に動作しないケースも多かったように感じました。しかし、Heroku が有料化した今、無料で常時稼働できる点は Deno の大きな魅力だと思います。Deno の使用感は非常に良かったです。ここまで読んでいただきありがとうございました。

参考にしたサイト等

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?