皆さん初めまして。Morichanと申します。
下記の※の記述を理解したうえで、記事を読んでください。
※DiscordBot開発初心者の書いた記事です。
(また、プログラミング自体、2年ほどのブランクあり)
BOTをVCに参加させるまでの流れに関しては、別の記事にまとめてあります。
関連記事:
- 【Windows11】Discord BOTを開発するための開発環境を整える。
- 【Discord.js V14】Discord BOTにスラッシュコマンドを実装してみる
- 【Discord.js V14】Discord BOTをVCに参加させてみる
目次
開発環境
OS (Windows11)
discord.js (14.7.1)
node.js (18.13.0)
npm (8.19.3)
@discordjs/voice (^0.14.0)
2つ目のBOTを作成する
- BOTを2つ作成する。
参考記事
名前は安直に、Listener-botとSpeaker-botにしました。
APP ICON:
今回は、いらすとやで見つけた、
よく聞いている人のイラスト(男性)
おしゃべりな女性のイラスト
の2つの画像を使いました。
DESCRIPTION:
Listener-bot ⇒ VC1の音を聞くためのBOTです。
Speaker-bot ⇒ VC1の音をVC2に送信するためのBOTです。
-
config.json
に2つ分のBOTの情報を記述する。
{
"LISTENER": {
"CLIENT_ID": "ここにListener-botのCLIENT_IDを記述",
"TOKEN": "ここにListener-botのTOKENを記述"
},
"SPEAKER": {
"CLIENT_ID": "ここにSpeaker-botのCLIENT_IDを記述",
"TOKEN": "ここにSpeaker-botのTOKENを記述"
},
"GUILD_ID": "ここにBOTを追加したサーバーのIDを記述"
}
-
index.js
にBOTを2つ動かすための記述を行う。
const fs = require('node:fs');
const path = require('node:path');
const { Client, Collection, Events, GatewayIntentBits } = require('discord.js');
const { LISTENER, SPEAKER } = require('./config.json');
const client1 = new Client({ intents: [GatewayIntentBits.Guilds] });
const client2 = new Client({ intents: [GatewayIntentBits.Guilds] });
// 今回はListenner-botに対してのみコマンドを割り当ててみる。
client1.commands = new Collection();
// commandsフォルダから、.jsで終わるファイルのみを取得
const commandsPath = path.join(__dirname, 'commands');
const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// 取得した.jsファイル内の情報から、コマンドと名前をListenner-botに対して設定
if ('data' in command && 'execute' in command) {
client1.commands.set(command.data.name, command);
} else {
console.log(`[WARNING] ${filePath} のコマンドには、必要な "data" または "execute" プロパティがありません。`);
}
}
// コマンドが送られてきた際の処理
client1.on(Events.InteractionCreate, async interaction => {
// コマンドでなかった場合は処理せずさよなら。
if (!interaction.isChatInputCommand()) return;
const command = interaction.client.commands.get(interaction.commandName);
// 一致するコマンドがなかった場合
if (!command) {
console.error(` ${interaction.commandName} というコマンドは存在しません。`);
return;
}
try {
// コマンドを実行
await command.execute(interaction);
} catch (error) {
console.error(error);
await interaction.reply({ content: 'コマンドを実行中にエラーが発生しました。', ephemeral: true });
}
});
client1.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client2.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client1.login(LISTENER.TOKEN);
client2.login(SPEAKER.TOKEN);
2つのBOTを別々のVCに参加させてみる
- VCに入るBOTを識別できるように、BOTの情報を
index.js
からjoin.js
に渡す。
(index.js)
// 以下の部分を変更
try {
// コマンドを実行
await command.execute(interaction, client1, client2);
} catch (error) {
---(以下略)---
(join.js)
// 以下の部分を変更
async execute(interaction, client1, client2) {
---(以下略)---
- 2つのBOTをVCに参加させるため、コピペして、
join.js
の中身を複数BOT時の挙動に合わせて、記述を改変する。
const { SlashCommandBuilder, ChannelType } = require('discord.js');
const { joinVoiceChannel } = require('@discordjs/voice');
module.exports = {
data: new SlashCommandBuilder()
// コマンドの名前
.setName('join')
// コマンドの説明文
.setDescription('VCに参加。')
// コマンドのオプションを追加
.addChannelOption((option) =>
option
.setName('channel1')
.setDescription('The channel that Listener-bot join')
.setRequired(true)
.addChannelTypes(ChannelType.GuildVoice),
)
.addChannelOption((option) =>
option
.setName('channel2')
.setDescription('The channel that Speaker-bot join')
.setRequired(true)
.addChannelTypes(ChannelType.GuildVoice),
),
async execute(interaction, client1, client2) {
const voiceChannel1 = interaction.options.getChannel('channel1');
const voiceChannel2 = interaction.options.getChannel('channel2');
// Listener-botがVCに参加する処理
const connection1 = joinVoiceChannel({
// なぜかはわからないが、groupの指定をしないと、先にVCに入っているBOTがVCを移動するだけになってしまうので、記述。
group: 'listener',
guildId: interaction.guildId,
channelId: voiceChannel1.id,
// どっちのBOTを動かしてあげるかの指定をしてあげる。
adapterCreator: client1.guilds.cache.get(interaction.guildId).voiceAdapterCreator,
// VC参加時にマイクミュート、スピーカーミュートにするか否か
selfMute: true,
selfDeaf: false,
});
// Speaker-botがVCに参加する処理
const connection2 = joinVoiceChannel({
group: 'speaker',
guildId: interaction.guildId,
channelId: voiceChannel2.id,
adapterCreator: client2.guilds.cache.get(interaction.guildId).voiceAdapterCreator,
selfMute: false,
selfDeaf: true,
});
await interaction.reply('参加しました!');
},
};
- 同じVCへ参加できないように、また、voiceChannel1,voiceChannel2に値が入っていないときの処理を記述する。
async execute(interaction, client1, client2) {
const voiceChannel1 = interaction.options.getChannel('channel1');
const voiceChannel2 = interaction.options.getChannel('channel2');
if (voiceChannel1 && voiceChannel2) {
if (voiceChannel1 === voiceChannel2) {
await interaction.reply('同じVCには参加できません🥺');
return;
}
// Listener-botがVCに参加する処理
const connection1 = joinVoiceChannel({
---(以下略)---
adapterCreator: client2.guilds.cache.get(interaction.guildId).voiceAdapterCreator,
selfMute: false,
selfDeaf: true,
});
await interaction.reply('VCに参加しました!');
}
else {
await interaction.reply('BOTを参加させるVCを指定してください!');
}
},
};
関連記事
- 【Windows11】Discord BOTを開発するための開発環境を整える。
- 【Discord.js V14】Discord BOTにスラッシュコマンドを実装してみる
- 【Discord.js V14】Discord BOTをVCに参加させてみる
- 【Discord.js V14】2つのBOTを別々のVCに参加させてみる
- 【Discord.js V14】スラッシュコマンドのオプションで、既に選択済みの選択肢を2つ目の引数のリストから消す。
- 【Discord.js V14】Discord BOTにVCに音楽を流す機能を実装してみる
- 【Discord.js V14】Discord BOTにVCから1人分の音声を取得して、録音する機能を実装してみる
- 【Discord.js V14】VC1からVC2に音声をStreaming(中継)するBOTを作成する。
- 【Discord.js V14】取得するVCの音声をロールによって判別する