0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Discord.js V14】2つのBOTを別々のVCに参加させてみる

Last updated at Posted at 2023-01-29

皆さん初めまして。Morichanと申します。
下記の※の記述を理解したうえで、記事を読んでください。

※DiscordBot開発初心者の書いた記事です。
(また、プログラミング自体、2年ほどのブランクあり)

BOTをVCに参加させるまでの流れに関しては、別の記事にまとめてあります。

関連記事:

目次

  1. 開発環境
  2. 2つ目のBOTを作成する
  3. 2つのBOTを別々のVCに参加させてみる
  4. 関連記事

開発環境

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を指定してください!');
		}
	},
};
  • node deploy-commands.jsnode index.jsを行い、Discordでコマンドを入力。
    無事動きました!
    image.png

関連記事

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?