Discordeno を使って Deno で Discord BOT を動かす
Discordeno
Deno で Discord の BOT を扱うことができるライブラリです。
ドキュメントはまだあまり充実していないのですが、比較的頻繁に更新されており、結構イイ感じのライブラリです。
JS の Discord API ライブラリといえば Discord.js がありますが、それとは操作感がかなり異なるので少し注意が必要です。
Deno で Discord BOT を動かす利点として大きいのが無料で使える Deno Deploy の存在で、Heroku が有料となった今、無料で常に BOT を動かせるのはかなり嬉しいです。
サンプルコード
今回作成した BOT のコードは以下のレポで公開しています。
解説が意味不明なときはこっちを丸写しすれば動くと思います。
必要なもの
Node.jsやPythonなど、他の言語で Discord BOT を動かしたことがあることが望ましいです。Denoの知識も多少あるとよいです。
- Deno 1.28
また、この記事では VSCode 上で進めることを想定しています
BOT の準備
注意点だけ書いておきます。
Discord の BOT の設定画面に Privileged Gateway Intents
という項目がありますが、少なくともこの下2つのチェックは入れておくとよいです。
プロジェクト作成
新しく Deno プロジェクトを作成します。VSCode 上で Deno の拡張機能を有効にし、Deno: Initialize Workspace Configuration
を選んでエンターキーを三回連打します。
以下のファイルを作成します
{
"tasks": {
"dev": "deno run -A --watch ./main.ts",
"start": "deno run -A --watch ./main.ts"
}
}
main.ts
、deps.ts
も作成しておきます。
deps.ts
以下のようにします
// discordeno
export * from "https://deno.land/x/discordeno@17.1.0/mod.ts"
// dotenv
export * as dotenv from "https://deno.land/std@0.167.0/dotenv/mod.ts"
discordenoはバージョンによって破壊的な変更が多いので注意が必要です。
dotenvはトークンの読み込みに使います。
BOT のコードを書いていく
機密情報
BOT のトークンを .env.local
に書きます。
DISCORD_TOKEN=hogehoge
トークンを読み取るのはBOT本体とは別の場所にしたいので、 secret.ts
を作成して、以下のようにします。
import { dotenv } from "./deps.ts"
dotenv.configSync({
export: true,
path: "./.env.local",
})
export const Secret = {
DISCORD_TOKEN: Deno.env.get("DISCORD_TOKEN")!,
}
configSync
の export
を true
にしないと、Deno.env.get
で取得できないので注意です。
BOT のコードを書く
main.ts
に BOT のコードを書いていきます。
import { createBot, Intents, startBot } from "./deps.ts"
import { Secret } from "./secret.ts"
const bot = createBot({
token: Secret.DISCORD_TOKEN,
intents: Intents.Guilds | Intents.GuildMessages | Intents.MessageContent,
events: {
ready: (_bot, payload) => {
console.log(`${payload.user.username} is ready!`)
},
},
})
bot.events.messageCreate = (b, message) => {
if (message.content === "!neko") {
b.helpers.sendMessage(message.channelId, {
content: "にゃーん",
})
}
}
await startBot(bot)
ここまで書いて、以下を実行すると BOT が起動します
deno task dev
--watch
フラグがついているので、コードを保存すると自動で再実行されます。便利です。
うまく動いていれば、BOT のいるサーバーで !neko
と発言すると にゃーん
と返ってきます。
Discord.js を触ったことがある人は違和感があるかもしれませんが、送られたメッセージのあるチャンネルにメッセージを返すには、 Bot
に用意されている helpers.sendMessage()
を利用する形になります。
スラッシュコマンドを使う
スラッシュコマンドを作成してみます。
今回は、反映が早いので自分のサーバーに対してコマンドを作成します。
自分のサーバー ID を GUILD_ID
として .env.local
や secret.ts
に保存します。
DISCORD_TOKEN=hogehoge
GUILD_ID=1234
import { dotenv } from "./deps.ts"
dotenv.configSync({
export: true,
path: "./.env.local",
})
export const Secret = {
DISCORD_TOKEN: Deno.env.get("DISCORD_TOKEN")!,
GUILD_ID: Deno.env.get("GUILD_ID")!,
}
main.ts
を以下のようにします
- import { createBot, Intents, startBot } from "./deps.ts"
+ import { createBot, Intents, startBot, CreateSlashApplicationCommand, InteractionResponseTypes } from "./deps.ts"
import { Secret } from "./secret.ts"
const bot = createBot({
token: Secret.DISCORD_TOKEN,
intents: Intents.Guilds | Intents.GuildMessages | Intents.MessageContent,
events: {
ready: (_bot, payload) => {
console.log(`${payload.user.username} is ready!`)
},
},
})
+ const nekoCommand: CreateSlashApplicationCommand = {
+ name: "neko",
+ description: "にゃーんと返します",
+ }
+ await bot.helpers.upsertGuildApplicationCommands(Secret.GUILD_ID, [nekoCommand])
bot.events.messageCreate = (b, message) => {
if (message.content === "!neko") {
b.helpers.sendMessage(message.channelId, {
content: "にゃーん",
})
}
}
+ bot.events.interactionCreate = (b, interaction) => {
+ console.log(interaction.data?.name)
+ }
await startBot(bot)
これらを追加すると、BOT のいるサーバーで neko
のスラッシュコマンドが追加されたと思います。
このまま実行しても何も反応はありませんが、deno の方で neko
と出力されます。
bot.events.interactionCreate
を次のように書き換えてみます。
// 略
bot.events.interactionCreate = (b, interaction) => {
switch (interaction.data?.name) {
case "neko": {
b.helpers.sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ChannelMessageWithSource,
data: {
content: "にゃーん!!",
},
})
break
}
default: {
break
}
}
}
すると、/neko
を実行すると にゃーん!!
が返ってくるようになります。
Deno Deploy にデプロイする
.gitignore を作成
.gitignore
を作成します。
gitignore.io にアクセスして以下の用な条件で生成し、.gitignore
として保存します。
git を設定
git init
git add .
git commit -m "initial commit"
します。
お好みで
git branch -m main
します。
GitHub に上げる
適当に GitHub のレポを作成して上げます。
git remote add origin レポのURL
git push -u origin master
Deploy
Secret の修正
Deno Deploy ではREAD権限がないため、dotenv の configSync
でクラッシュします。
なので、簡易的な対策として try catch で囲みます。多分このやり方はあんまり良くないので、ちゃんとしたプロジェクトでやるなら、開発環境と本番環境を区別するコードを書いたほうがいいです。
// 略
try {
dotenv.configSync({
export: true,
path: "./.env.local",
})
} catch {}
// 略
Deno Deploy にアクセスし、アカウントがない場合は作り、サインインします。
New Project を選択し、
Deploy from GitHub repository で作成したレポと main.ts
を選択し、イイ感じの名前を付けます。
Link を押すと紐付けられ、デプロイが開始されます。10秒程度でデプロイが終わります。爆速です。
環境変数の設定
Discordのトークンなどを設定します。
Settings > Environment Variables から Add Variable します。
環境変数が更新されると自動で再実行されるはずですので、これで動くようになったと思います。
(もし動かない場合は、Deno Deploy で与えられた URL に一度アクセスすると起きるはずです。)
おわり
なぜか Discordeno の記事が全然なかったので、とりあえず簡単な BOT の解説記事を書きました。Discordeno の仕様は他の Discord ライブラリとは少し異なるのでそのまま移行するのは難しいかもしれませんが、 Deno も Deno Deploy も非常に便利なので一つの選択肢として覚えておくとよいかと思います。
Discordeno はドキュメントが充実していないのですが、コードにコメントが付いてるのと、いくつかのテンプレート があるので、そちらを参考にするとよいです。ドキュメントのコード例は古くてそのままだと全然動かないことがあるので気をつけてください。
今回作成したサンプルコードのレポ
Discussion