Home > front end >  How to move members between channels in Discord.js V 14
How to move members between channels in Discord.js V 14

Time:12-20

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);
  • Related