I need my Bot to move members between Channels. I recently upgraded to Discord.js Version 14 from Version 12.
My discord.js Version: 14.7.1
My node.js Version: 18.12.1
My main.js
const { Client, Events, GatewayIntentBits, Collection, ActivityType } = require("discord.js");
const fs = require("node:fs");
const path = require("node:path");
const { token } = require("./config.json");
const botIntents = [
GatewayIntentBits.Guilds,
GatewayIntentBits.DirectMessages,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildVoiceStates
];
const client = new Client({ intents: botIntents, partials: ["CHANNEL"] });
client.commands = new Collection();
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);
if ("data" in command && "execute" in command) {
client.commands.set(command.data.name, command);
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
// Bot ready event
client.once(Events.ClientReady, (c) => {
console.log(`Logged in as ${c.user.tag}`);
c.user.setActivity("/help", { type: ActivityType.Watching });
});
// Message input to command
client.on(Events.InteractionCreate, async (interaction) => {
if (!(interaction.isChatInputCommand())) return;
const command = interaction.client.commands.get(interaction.commandName);
if (!(command)) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
// ephemeral: true / private message, only visible to message sender (user)
await interaction.reply({ content: "There was an error while executing this command!", ephemeral: true });
}
});
client.login(token);
My working Code in Version 12.
module.exports = {
name: "my_name",
description: "my_description",
execute(message, args) {
const member = message.mentions.members.first();
if (!(args[1])) {
const embed = new Discord.MessageEmbed()
.setTitle("my_command")
.setColor(0x992d22)
.setDescription("my_description")
.setFooter(`Requested by ${message.author.tag}.`, message.author.displayAvatarURL);
message.channel.send(embed);
}
if (!member) return message.reply("enter a member name.")
if (!member.voice.channel) return message.reply("the member is not in a voice channel.");
if (!message.member.voice.channel) return message.reply("you need to join a voice channel first.");
message.channel.send("my_message");
member.voice.setChannel("my_channel_id");
}
}
I tried to get it to work in Version 14 like so.
module.exports = {
data: new SlashCommandBuilder()
.setName("my_name")
.setDescription("my_description")
.addUserOption((option) =>
option
.setName("member")
.setDescription("my_description")
.setRequired(true)
)
.setDMPermission(false),
async execute(interaction) {
const master = interaction.user.username;
const target = interaction.options.getUser("member");
const cageId = "my_channel_id";
if (!(interaction.member.voice.channel)) {
return await interaction.reply({ content: "You need to join a Voice-Channel first.", ephemeral: true });
}
if (!(target.voice.channelId)) {
return await interaction.reply({ content: "The Member is currently not in a Voice-Channel.", ephemeral: true });
}
await target.voice.setChannel(cageId);
const embed = new EmbedBuilder()
.setColor(0x992d22)
.setTitle("my_title")
.setDescription("my_description")
.setFooter({ text: `Requested by ${master}` })
.setTimestamp();
return await interaction.reply({ embeds: [embed] });
},
}
Problem
TypeError: Cannot read properties of undefined (reading 'setChannel')
TypeError: Cannot read properties of undefined (reading 'channelId')
I tried to Google it for quite some time, but i was not able to find a fitting solution.
CodePudding user response:
Just a couple of little tweaks and you should have what you're looking for.
First, make sure that when you're starting your bot you are requesting the needed Intent GatewayIntentBits.GuildVoiceStates
. Gateway Intents Documentation
Make certain that the option collected is the GuildMember:
const target = interaction.options.getUser("member");
to
const target = interaction.options.getMember("member");
Then when you are referencing the guild member, you need to specify that you're talking about the VoiceState:
if (!(target.channelId)) {
becomes
if (!(target.voice.channelId)) {
and
await target.setChannel(cageId);
becomes
await target.voice.setChannel(cageId);