Discord.js cannot read property - discord

I am trying to code a bot that will send a message when someone joins a voice channel. Code and error are below.
const Discord = require("discord.js");
const config = require("./config.json");
const bot = new Discord.Client();
bot.login(config.BOT_TOKEN);
bot.once('ready', () => {
console.log(`Bot ready, logged in as ${bot.user.tag}!`);
})
bot.on('voiceStateUpdate', (oldMember, newMember) => {
const newUserChannel = newMember.voice.channelID
const oldUserChannel = oldMember.voice.channelID
const textChannel = message.guild.channels.cache.get('766783720312537089')
if (newUserChannel === '764231813248843806') {
textChannel.send(`${newMember.user.username} (${newMember.id}) has joined the channel`)
} else if (oldUserChannel === '764231813248843806' && newUserChannel !== '764231813248843806') {
textChannel.send(`${newMember.user.username} (${newMember.id}) has left the channel`)
}
})
Error:
TypeError: Cannot read property 'channelID' of undefined

This is pretty easy to solve. The problem is that voiceStateUpdate does indeed take two variables, however they are not oldMember, newMember but oldState, newState.
As usual with functions it doesn't really matter what you call them but it makes more sense to use oldState, newState because they are a voiceState. As such they do not have a voice property.
So to fix this, all you have to do is use the correct voiceState properties.
const newUserChannel = newState.channelID;
const oldUserChannel = oldState.channelID;
Note: newState.user is also not a thing, however it does provide you with the member object so I suggest you use that instead.
EDIT: Your entire code should look a little something like this.
bot.on('voiceStateUpdate', (oldState, newState) => {
const newUserChannel = newState.channelID;
const oldUserChannel = oldState.channelID;
const textChannel = newState.guild.channels.cache.get('766783720312537089');
if (newUserChannel === '764231813248843806') {
textChannel.send(`${newState.member.user.username} (${newState.id}) has joined the channel`)
} else if (oldUserChannel === '764231813248843806' && newUserChannel !== '764231813248843806') {
textChannel.send(`${newState.member.user.username} (${newState.id}) has left the channel`)
}
});

Related

TypeError: Cannot read properties of undefined (reading 'ban')

client.on("channelCreate", async function(channel) {
const logs = await channel.guild.fetchAuditLogs({ limit: 1, type: 'CHANNEL_CREATE' });
const log = logs.entries.first();
if (!log) return;
const kanal = channel.guild.channels.cache.find(ch => ch.name === 'ticket')
const embed = new MessageEmbed()
.setTitle("🆘Protection System🆘")
.setDescription(`ο/η ${log.executor} έγινε banned επειδή έκανε αρκετά κανάλια`)
.setColor("RED")
const get = db.get(`channel2_${log.executor.id}`)
if(get === true)return channel.delete(),kanal.send({embeds: [embed]}),logs.executor.ban('Protection : Channel Created')
});
When I run this code, it returns this error:
TypeError: Cannot read properties of undefined (reading 'ban')
In your current code, the logs variable refers to GuildAuditLogs which is the collection of audit logs. It doesn't have an executor property. Instead, what you are looking for is the log variable (without an 's'). It contains the executor property. But using the executor property gives you an User object, so it still wouldn't have an .ban() property. So you would have to fetch the GuildMember who did the action. So, your fixed code would look like this:
client.on("channelCreate", async function(channel) {
const logs = await channel.guild.fetchAuditLogs({ limit: 1, type: 'CHANNEL_CREATE' });
const log = logs.entries.first();
const logExecutorMember = await channel.guild.members.fetch(log.executor.id)
if (!log) return;
const kanal = channel.guild.channels.cache.find(ch => ch.name === 'ticket')
const embed = new MessageEmbed()
.setTitle("🆘Protection System🆘")
.setDescription(`ο/η ${log.executor} έγινε banned επειδή έκανε αρκετά κανάλια`)
.setColor("RED")
const get = db.get(`channel2_${log.executor.id}`)
if(get === true)return channel.delete(),kanal.send({embeds: [embed]}),logExecutorMember.ban('Protection : Channel Created')
});

Discord music bot saying I need to send a second argument even when i do

Whats wrong with my code, I cant seem to figure it out. Followed a few tutorials before and made a few simple bots on my own, but cant seem to figure this out. Its not playing music nor connecting to the vc
Heres My Code:
const ytdl = require('ytdl-core');
const ytSearch = require('yt-search');
module.exports = {
name: 'play',
description: 'Joins and plays a video from youtube',
async execute(message, args) {
const voiceChannel = message.member.voice.channel;
if (!voiceChannel) return message.channel.send('You need to be in a channel to execute this command!');
const permissions = voiceChannel.permissionsFor(message.client.user);
if (!permissions.has('CONNECT')) return message.channel.send('You dont have the correct permissins');
if (!permissions.has('SPEAK')) return message.channel.send('You dont have the correct permissins');
if (!args.length) return message.channel.send('You need to send the second argument!');
const validURL = (str) =>{
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
if(!regex.test(str)){
return false;
} else {
return true;
}
}
if(validURL(args[0])){
const connection = await voiceChannel.join();
const stream = ytdl(args[0], {filter: 'audioonly'});
connection.play(stream, {seek: 0, volume: 1})
.on('finish', () =>{
voiceChannel.leave();
message.channel.send('leaving channel');
});
await message.reply(`:thumbsup: Now Playing ***Your Link!***`)
return
}
const connection = await voiceChannel.join();
const videoFinder = async (query) => {
const videoResult = await ytSearch(query);
return (videoResult.videos.length > 1) ? videoResult.videos[0] : null;
}
const video = await videoFinder(args.join(' '));
if(video){
const stream = ytdl(video.url, {filter: 'audioonly'});
connection.play(stream, {seek: 0, volume: 1})
.on('finish', () =>{
voiceChannel.leave();
});
await message.reply(`:thumbsup: Now Playing ***${video.title}***`)
} else {
message.channel.send('No video results found');
}
}
}
The main principle we want to focus on here is Guard Statements which you make good use of in your code.
If you aren't already familiar, a guard statement is one that resides at the top of a block of code and prevents the execution of code below it if a specific condition is met. This is really useful for making discord bots because it will allow us to stop command execution if the permission to use it is missing for example (which you use in your code provided)
The caveat here is that in your specific guard statement where you check for the number of args used, you provide this line:
if (!args.length) return message.channel.send('You need to send the second argument!');
Now, there's nothing wrong with this line, except that we're only checking if the property length doesn't exist on args which isn't what we're really trying to check.
If we want to make sure that there are exactly two arguments provided, we would want to rewrite the condition like this:
if (args.length == 2) return message.channel.send('You need to send the second argument!');
From here, you can change the condition to meet your desired requirements and it should work great!

I'm trying to make my bot send messages to a specific channel by using channel id

This is the code i used:
bot.on("message", function (message) {
if (message.content == '.shift') {
const channel01 = bot.channels.cache.find(channel => channel.id === "ChannelIDhere")
channel01.send('Text');
}
});
However it doesn't work for me, Most likely it is Outdated, after all the reference i found is a year ago, or i simply made a mistake.
Edit:
client.on('msg', msg => {
if (msg.content === '.go') {
const channel01 = client.channels.cache.get("872654795364765756");
channel01.send('Text');
}
});

discord.js not getting a users tag on mention

I have a ban command where you can either mention a user or use their id.
When mentioning the user in the embed it comes up with undefined has been banned! I want it to come up with user#0001 that was banned when mentioning the user or by banning them by their id.
Current code:
const switchc = bot.emojis.cache.find((emoji) => emoji.name === "switchcancel");
const switche = bot.emojis.cache.find((emoji) => emoji.name === "switch");
if (!message.member.hasPermission(["BAN_MEMBERS", "ADMINISTRATOR"]))
return message.channel.send(
`${switchc} **You do not have the permissions to complete this command!**`
);
let banMember =
message.mentions.members.first() ||
(await bot.users.fetch(args[0]).catch((err) => console.log(err)));
if (!banMember)
return await message.channel.send(
`${switchc} **Please supply a user to be banned!**`
);
let reason = args.slice(1).join(" ");
if (!reason) reason = "No reason was provided!";
if (!message.guild.me.hasPermission(["BAN_MEMBERS", "ADMINISTRATOR"]))
return message.channel.send(
`${switchc} **I do not have permission to complete this command!**`
);
message.guild.members
.ban(banMember, { days: 1, reason: reason })
.catch((err) => console.log(err));
const bEmbed = new MessageEmbed()
.setColor("RANDOM")
.setDescription(`**${banMember.tag}** has been banned!`);
message.channel.send(bEmbed);
Is there something I am doing wrong?
As you do not need a member object, the simplest fix would be:
let banMember = message.mentions.users.first() || await bot.users.fetch(args[0]).catch(err => console.log(err))
Using users instead of members in the mention getter.
Okay, I figured out my own issue. What I did was instead of using
${banMember.tag}
I instead defined tag by doing
let tag = banMember.tag || banMember.user.tag
The new code is as follows
const switchc = bot.emojis.cache.find(emoji => emoji.name === "switchcancel");
const switche = bot.emojis.cache.find(emoji => emoji.name === "switch");
if(!message.member.hasPermission(["BAN_MEMBERS", "ADMINISTRATOR"])) return message.channel.send(`${switchc} **You do not have the permissions to complete this command!**`)
let banMember = message.mentions.members.first() || await bot.users.fetch(args[0]).catch(err => console.log(err))
if(!banMember) return await message.channel.send(`${switchc} **Please supply a user to be banned!**`)
let tag = banMember.tag || banMember.user.tag
let reason = args.slice(1).join(" ")
if(!reason) reason = "No reason was provided!"
if (!message.guild.me.hasPermission(["BAN_MEMBERS", "ADMINISTRATOR"])) return message.channel.send(`${switchc} **I do not have permission to complete this command!**`)
message.guild.members.ban(banMember, { days: 1 , reason: reason}).catch(err => console.log(err))
const bEmbed = new MessageEmbed()
.setColor("RANDOM")
.setDescription(`**${tag}** has been banned!`)
message.channel.send(bEmbed)
}
}
This will allow for the users tag to show up when baning by ID or mention.

Discord bot role command stopped working for unknown reasons

I have a command which worked, but at some point stopped, returning to the chat message that the role does not exist. An error "(node:12228) DeprecationWarning: Collection#find: pass a function instead" is sent to the console every time I use a command, but I always had it
const Discord = require("discord.js");
module.exports.run = async (bot, message, args) => {
if(!message.member.hasPermission("MANAGE_MEMBERS")) return message.reply();
let rMember = message.guild.member(message.mentions.users.first()) || message.guild.members.get(args[0]);
if(!rMember) return message.reply("nope.");
let role = args.join(" ").slice(22);
if(!role) return message.reply("nope!");
let gRole = message.guild.roles.find(`name`, role);
if(!gRole) return message.reply("role does not exist.");
const allowed = ['some id'];
if (!allowed.includes(gRole.id)) return;
if(rMember.roles.has(gRole.id)) return message.reply("nope.");
await(rMember.removeRoles(['some id']));
await(rMember.addRole(gRole.id));
if(gRole.id == 'id') rMember.addRole('id') && rMember.removeRoles(['some id']);;
try{
await rMember.send(`you got ${gRole.name}!`)
}catch(e){
}
}
module.exports.help = {
name: "role"
}
So I need the command to work.
In order of appearance, I see these mistakes in your code...
You're not catching any rejected promises.
MANAGE_MEMBERS is not a valid permission flag.
You should pass a function into Collection.find().
No idea what you're trying to do with the declaration of role.
Your use of the && logical operator in your if statement is incorrect. Use a block statement instead.
Your catch block in the try...catch statement has been left empty.
Combining the answers provided to your other questions about this code, this is a correct, much cleaner rewrite...
const getMention = require('discord-mentions'); // Don't forget to install.
module.exports.run = async (bot, message, args) => {
if (!message.guild) return;
try {
if (!message.member.hasPermission('MANAGE_ROLES')) return;
if (!args[1]) return await message.reply('Please provide a user.');
if (!args[2]) return await message.reply('Please provide a role.');
if (args[3]) return await message.reply('Too many arguments provided.');
let member;
if (getMention(args[1])) member = getMention(args[1], message.guild).member;
else member = message.guild.members.find(m => m.user.tag === args[1] || m.id === args[1]);
if (!member) return await message.reply('Invalid user provided.');
let role;
if (getMention(args[2])) role = getMention(args[2], message.guild).role;
else role = message.guild.roles.find(r => r.name === args[2] || r.id === args[2]);
if (!role) return await message.reply('Invalid role provided.');
const allowed = ['role1ID', 'role2ID', 'role3ID'];
if (!allowed.includes(role.id)) return await message.reply('That role is not allowed.');
if (member.roles.has(role.id)) return await message.reply('That user already has that role.');
await member.removeRoles(['someID', 'someOtherID']);
await member.addRole(role.id);
if (role.id === 'anAlternateRoleID') {
await member.removeRoles(['someID', 'someOtherID']);
await member.addRole('otherRoleID');
}
await member.send(`You got the ${role.name} role.`)
.catch(() => console.log(`Couldn't send message to ${member.user.tag}.`));
} catch(err) {
console.error(err);
}
};
module.exports.help = {
name: 'role'
};
Keep in mind, if you're removing just one role from a member, you should use the singular version of the method, GuildMember.removeRole().

Resources