誰でも作れる!Discord Bot 2024(カスタマイズ編/中級)

この記事では、誰でも作れる!Discord Bot 2024(初期設定編) で作成した Bot のカスタマイズ方法を紹介します!

中級では、より高度な Bot のカスタマイズや仕組みについて紹介します。
カスタマイズするというよりかは、このサンプルをもとに discord.js の活用方法を理解することがメインとなっています。
JavaScript などの知識が必要な部分もあるので、適宜 Google 検索も活用してくださいね!

※カスタマイズについて全てを紹介するのはとても時間が足りないので、少しだけ紹介して、あとは資料を読んでね!という感じなので、短めです。

リンク


資料集

・discord.js (14.14.1) | discord.js
https://discord.js.org/docs/packages/discord.js/14.14.1
discord.js 
 の公式ドキュメントです。困ったときは地道に読んでいきましょう。

・discord.js Guide
https://discordjs.guide/#before-you-begin
神サイト。いろんなサンプルが載っています。
何かやりたいことがあれば、とりあえずここを読むと大体載っています。

・Sequelize | Feature-rich ORM for modern TypeScript & JavaScript
https://sequelize.org
利用している ORM のドキュメントです。

ボイスチャット参加通知の仕組み

Discord のボイスチャンネルに入ったとき・抜けたときは、voiceStateUpdate イベントが発火します。

main.mjs では、voiceStateUpdate イベント発火時に handlers/voiceStateUpdate.mjs の関数を呼び出します。

client.on("voiceStateUpdate", async (oldState, newState) => {
  await handlers.get("voiceStateUpdate").default(oldState, newState);
});

voiceStateUpdate などのイベントの詳細は、Client クラスのドキュメントを参照しましょう。
https://discord.js.org/docs/packages/discord.js/main/Client:Class#voiceStateUpdate

import { EmbedBuilder } from "discord.js";

import Notification from "../models/notification.mjs"

export default async (oldState, newState) => {
  if (oldState.channelId === null && newState.channel?.members.size == 1){
    const notifications = await Notification.findAll({
      where: {
        guildId: newState.guild.id,
        voiceChannelId: newState.channel.id,
      },
    });
    
    const embed = new EmbedBuilder()
      .setColor(0x5cb85c)
      .setAuthor({ name: newState.member.displayName, iconURL: newState.member.displayAvatarURL()})
      .setTitle(`<#${newState.channel.id}> で通話を開始しました!`)
      .setTimestamp();
    
    await Promise.all(
      notifications.map(async n => {
        const channel = await newState.guild.channels.fetch(n.textChannelId);
        await channel.send({ embeds: [embed] });
      })
    );
  }
};

handlers/voiceStateUpdate.mjs はこのようになっています。
oldState と newState を比較して、具体的にどのような操作が行われたかを判定することができます。
判定後は、通知すべきテキストチャンネルをデータベースから取得し、Embed を利用して通知を行っています。

カスタマイズ方法

  if (oldState.channelId === null && newState.channel?.members.size == 1){

この部分で、どのような場合に通知を送信するかを判定しています。

このあたりを考えるときは、まずは discord.js のドキュメントを見ましょう。
https://discord.js.org/docs/packages/discord.js/main/VoiceState:Class

「oldState.channelId === null」は、操作が行われる前にボイスチャンネルに入っていないときに true となります。
「newState.channel?.members.size == 1」は、操作後のボイスチャンネルに入っている人数が 1 の場合に true となります。
これらを and 条件で判定すると、「ボイスチャンネルに入っていなかった人がボイスチャンネルに入り、そのボイスチャンネルに入っている人数が 1 人の場合」となります。
つまり、「ボイスチャンネルに入っていない人が、誰もいないボイスチャンネルに入った場合」のみ、if 文の内容が実行されます。

これをカスタマイズする場合、例えば以下のようにすると、「誰かがボイスチャンネルに入った場合や、他のボイスチャンネルから移動してきた場合」に、通知を行います。(通知量がめちゃめちゃ増えます。)

  if (newState.channelId != null){

じゃんけんコマンドなど

Bot では、押すことで Bot が反応するボタンやセレクトメニューなどをメッセージに含めることができます。
MiniPotato Bot では、/janken や /notify configure などで使用しています。

この辺りは、資料に詳細が載っているので、ドキュメントも見ながら頑張ってコマンドを作っていきましょう。

さいごに

投げやりになってしまって申し訳ないですが、網羅的に解説するのは難しいため、困った際や質問がある方は MiniPotato Bot の Discord サーバーに投稿ください!
可能な範囲でお答えします。
https://discord.gg/UDf4R5fgqr


この記事が気に入ったらサポートをしてみませんか?