LoginSignup
6
2

More than 1 year has passed since last update.

DenoでDiscordのBOTを作ってみた - discordeno

Posted at

discordenoの記事が1つしか見つからなかったから初めて記事を書いてみる…

導入

ある日いつものように身内のDiscordでワイワイゲームをしていた時、VCに入ってきた男がこう言ったのである…

とも「俺、毎日愛してるって言われたいからBOT作ってくれない?」
ぼく「......??」

と、いうことでBOTを作ることになったので、せっかくだからと前々から気になっていたDenoを使用してDiscordのBOTを制作することにしたのです......

(実話)

注意

この記事では、Denoのインストール方法やDiscordのBOTの登録方法などは説明しません、調べたらいっぱい出てくるし...

自分が参考にした記事を貼っておくのでそちらを参考にしてください!

まずは最小構成

import { createBot, startBot } from "https://deno.land/x/discordeno@13.0.0-rc18/mod.ts"
import { enableCachePlugin, enableCacheSweepers } from "https://deno.land/x/discordeno_cache_plugin@0.0.21/mod.ts"

const baseBot = createBot({
  token: Deno.env.get("DISCORD_TOKEN")!,
  intents: ["Guilds", "GuildMessages"],
  botId: BigInt(Deno.env.get("BOT_ID")!),
  events: {
    ready() {
      console.log("Successfully connected to gateway")
    },
    messageCreate(bot, message) {
      if(message.content.startsWith("!ping")) {
        bot.helpers.sendMessage(message.channelId, { content: "pong!" })
      }
    }
  }
})

const bot = enableCachePlugin(baseBot)
enableCacheSweepers(bot)

await startBot(bot)

とりあえず上のコードで最低限動作するBOTは作ることができます、簡単!

bigInt型に注意

botId: BigInt(Deno.env.get("BOT_ID")!)

公式のGitHubに載っている最小構成と違う部分としては、CreateBot()関数内のbotIdが最近のバージョンでbigInt型で定義されているので、BigInt()関数で囲ってあげて型変換を行う必要があります。
他にもメッセージを送る際に必要になるチャンネルIDなどもbigInt型になっているので、その都度変換を行いましょう!

Cache Plugin

他にもdiscordeno公式のプラグインとして Cache Plugin が用意されています。

import { enableCachePlugin, enableCacheSweepers } from "https://deno.land/x/discordeno_cache_plugin@0.0.21/mod.ts"

~~~省略~~~

const bot = enableCachePlugin(baseBot)
enableCacheSweepers(bot)

discordeno単体ではキャッシュを行わないため、こういった個人で作る規模のBOTではプラグインを導入して自動的にキャッシュを行うようにしましょう。おまじない!!

よく使いそうな機能

最小構成のコードを見れば大体はわかると思いますが、以下のコードはすべてcreateBot()関数events内に記述するものです。

特定の単語が送信されたチャンネルにメッセージを送信する

messageCreate(bot, message) {
  if(message.content.includes("こんにちは")) {
    bot.helpers.sendMessage(message.channelId, { content: "やっほ〜" })
  }
}

スクリーンショット

メンションされたらリアクションを追加する

messageCreate(bot, message) {
  if(message.mentionedUserIds.includes(bot.id)) {
    bot.helpers.addReaction(message.channelId, message.id, "🤧")
  }
}

スクリーンショット 2022-06-03 1.07.16.png

ダイレクトメッセージの送信

import { sendDirectMessage } from "https://deno.land/x/discordeno_helpers_plugin@0.0.8/mod.ts"

messageCreate(bot, message) {
  // はろ が送信されたらDMを送る
  if(message.content.includes("はろ")) {
    sendDirectMessage(bot, message.authorId, "DMだよ〜")
  }
}

スクリーンショット
スクリーンショット

ダイレクトメッセージを送る場合、discordeno公式のプラグインである Helpers Plugin をimportして sendDirectMessage 関数を使用すると簡単にDMを送信することができます。

リアクションイベントを取得する

const baseBot = createBot({
  token: 
  // intentsに GuildMessageReactions を追加してあげる
  intents: ["Guilds", "GuildMessages", "GuildMessageReactions"],
  botId: 
  events: {
    reactionAdd(bot, payload){
      // bot自身が追加したリアクションは早期リターンしてあげる
      if(payload.userId == bot.id) return

      bot.helpers.sendMessage(payload.channelId, { content: payload.emoji.name })
    }
  }
})

スクリーンショット

上で紹介したものを組み合わせるとこんなこともできる...

import { createBot, startBot } from "https://deno.land/x/discordeno@13.0.0-rc18/mod.ts"
import { enableCachePlugin, enableCacheSweepers } from "https://deno.land/x/discordeno_cache_plugin@0.0.21/mod.ts"
import { sendDirectMessage } from "https://deno.land/x/discordeno_helpers_plugin@0.0.8/mod.ts"

let messageId = BigInt(0)

const baseBot = createBot({
  token: Deno.env.get("DISCORD_TOKEN")!,
  intents: ["Guilds", "GuildMessages", "GuildMessageReactions"],
  botId: BigInt(Deno.env.get("BOT_ID")!),
  events: {
    messageCreate(bot, message) {
      // !help が送信されたらヘルプのメッセージを送信し
      // そのメッセージに追加されたリアクションをクリックすることでDMにヘルプの詳細が送られてくる
      if(message.content.startsWith("!help")) {
        (async() => {
          const result = await bot.helpers.sendMessage(message.channelId, { content: "これはヘルプです\n詳細はチェックマークをクリックしてください" })
          bot.helpers.addReaction(result.channelId, result.id, "")
          messageId = result.id
        })()
      }
    },
    reactionAdd(bot, payload) {
      if(payload.userId == bot.id) return

      if(payload.messageId == messageId && payload.emoji.name == "") {
        sendDirectMessage(bot, payload.userId, "これはヘルプの詳細です")
      }
    }
  }
})

const bot = enableCachePlugin(baseBot)
enableCacheSweepers(bot)

await startBot(bot)

スクリーンショット
スクリーンショット

今回紹介した、ready, messageCreate, reactionAdd 以外にもたくさんのイベントがあるので、ぜひソースコードを覗いて触ってみてください!

さいごに

今回記事で紹介したコードはGitHubで公開してるので全体を見たい場合は覗いてみてください。

冒頭に出てきた友達は喜んでくれたのでよかったです。
スクリーンショット

6
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
6
2