I'm working on a Discord bot that will take complaints via DMs and post them in a chat room to be seen by moderators. For some reason, the type is considered undefined. The exact error text is this:
TypeError: Cannot read property '44640...' of undefined
The error comes from this line:
if (bot.channel[channelID].type == 1)
If the channel ID itself is considered undefined, then I believe this means the channel itself is not defined.
Here is the full code of the function:
bot.on('message', function (user, userID, channelID, message, evt) {
// Our bot needs to know if it will execute a command
// It will listen for messages that will start with `s!`
if (message.substring(0, 2) == 's!') {
var args = message.substring(2).split(' ');
var cmd = args[0];
args = args.splice(2);
switch(cmd) {
// s!ping
case 'ping':
bot.sendMessage({
to: channelID,
message: 'Pong!'
});
break;
case 'problem':
if (bot.channel[channelID].type == 1)
{
var embed = new Discord.RichEmbed()
.setAuthor(message.author.username, message.author.avatarURL)
.setDescription(message.content)
.setTimestamp(new Date())
.setColor('#C735D4');
//stores the sent message, along with the sender and the time of the message
client.channels.get(446393832066514947).send(embed);
//sends message to channel
}
// Just add any case commands if you want to..
}
}
});
If that is your entire code, I am assuming this.channel is never set anywhere, which means it will be undefined when you try to access it.
Your Client object holds a collection of Channel objects, with the channel ID as the key.
So in your snippet you should be able to say
bot.channels[channelID].type
Related
I want to do a command for example eat and i want the bot ping, here is an example :D
bot.on('message', (message) => {
const parts = message.content.split('');
if (parts [0] == '!eat'){
if (parts [1] == 'The member that i want to be pinged by the bot') {
message.channel.send('The user that i pinged on command has been eated!')
}
};
}
I have made a few changes:
I have added a global prefix variable, so that the prefix can easily be changed.
I have added checks to make sure the function exits if the message was sent by a bot or doesn't start with the prefix.
I have added some code to split the message into a command and arguments.
I have replaced the if statement with a switch statement.
I highly recommend that you read the Discord.js guide, as it's very beginner friendly and will allow you to write even better code than in this answer. Much of the code in this answer is taken from the Discord.js guide.
const prefix = '!';
bot.on('message', (message) => {
if (message.author.bot || !message.content.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).trim().split(/\s+/g);
const command = args.shift().toLowerCase();
switch (command) {
case 'eat':
const member = message.mentions.members.first();
if (!member) return message.reply('Could not find the mentioned user.');
message.channel.send(`${member.user.username} has been eaten!`);
break;
default:
message.reply(`The command \`${command}\` was not recognized`);
}
});
Explanation
The command prefix is set:
const prefix = '!';
The function exits if the message was sent by a bot or doesn't start with the prefix:
if (message.author.bot || !message.content.startsWith(prefix)) return;
The prefix is removed from the start of the message, and the message is split at all whitespace gaps:
const args = message.content.slice(prefix.length).trim().split(/\s+/g);
The first argument is removed, converted to lowercase and stored in the command variable:
const command = args.shift().toLowerCase();
The first mentioned user is found:
const member = message.mentions.members.first();
If there is no mentioned user, a warning message is returned:
if (!member) return message.reply('Could not find the mentioned user.');
A message is sent to the server saying "[the user] has been eaten!":
message.channel.send(`${member.user.username} has been eaten!`);
References
Message.mentions
<#${message.member.id}> That will ping the author of the message just use (``) and not (' ') and that will ping the author
I'm basically making a counting bot where one command shows a let in a message, one increments it and sends a message, and, once I get passed this little issue, one that will let me set the let in case someone goes overboard. It's for a D&D campaign using discord and is basically just a meme bot I'm making for fun. The issue I'm having is that I can't figure out how to use the let variable in the message itself. This is what I'm working with based on youtube and my previous experience in Python, of which there is little.
const { prefix, token } = require('./Config.json');
const client = new Discord.Client();
let insight = 4;
client.once('ready', () => {
console.log("Ready!")
})
client.on('message', message => {
console.log(message.content);
if(message.content.startsWith(`${prefix}insight`)) {
return message.channel.send("Ghyger had distrusted someone ", insight, " times!")
}
if(message.content.startsWith(`${prefix}distrust`)) {
insight++;
return message.channel.send("Not again Ghyger! That's ", insight, " times now!")
}
})
client.login(token);
When this is ran and I execute either command, it throws up this, followed by a bunch of paths
options.reply = reply;
^
TypeError: Cannot create property 'reply' on number '5'
It's because reply is a function, not a variable, you should be calling it options.reply(reply);.
Fix is let option.reply = reply
I'm trying to make a bot that will delete messages with a certain amount of thumbsdown reactions. I'm having trouble identifying the count of a specific reaction on a message.
Basically, I've created a command that waits for messages and adds them to my msgarray. After each message, I want to go through the array and delete any messages with the specified amount of reactions.
This is what I have so far:
var msgarray = [];
const msgs = await message.channel.awaitMessages(msg => {
msgarray.push(msg);
for (i = 0; i < msgarray.length; i++) {
// I'm not sure where to go from here, I want to make an if statement that checks
// for a certain amount of thumbsdown reactions on the message
if (msgarray[i].reactions) {
// incomplete
}
}
});
This is my first time programming in javascript, so I apologize if this code doesn't make much sense.
TextChannel.awaitMessages() resolves with a Collection, so the msg parameter you're using is not a single message, but a Collection of multiple messages.
Also, it would be better to check messages only when they get a reaction, using the messageReactionAdd event, that fires every time someone adds a reaction.
It should look like this:
// this code is executed every time they add a reaction
client.on('messageReactionAdd', (reaction, user) => {
let limit = 10; // number of thumbsdown reactions you need
if (reaction.emoji.name == '👎' && reaction.count >= limit) reaction.message.delete();
});
I'm trying to make an announcement command for my discord bot running discord.js. For example, if I say +ann (#CHANNEL) (ANNOUNCEMENT) it will post it there. I don't have any code for this and have been looking for ages. May you please help?
Basic Command Setup
When making a basic command, the first thing you're gonna want to set up is something like this:
<Discord.Client instance here>.on("message", message => {
if(message.author.bot) return;
let messageArray = message.content.split(" ");
let command = messageArray[0];
let args = messageArray.slice(1);
}
What does this do?
First of all, the code inside those curly braces is called whenever the bot "receives" a message. This means that the code is run whenever a message is sent in any channel in any server it is a part of, including DMs. The first line in this function ensures that the user who sent the message was not a bot, as you don't want other bots triggering commands on your bot.
Then, this code does some simple splitting on the message, so that the messageArray is an array of each word in the message, as determined by a space. For example, this would mean that if I sent Hello there, Cloudy Sounds!, messageArray would contain the following:
['Hello', 'there,', 'Cloudy', 'Sounds!']
command is the first word of this message (in this case 'Hello'). This is important because when sends a command to the bot, such as the +ann command you wanted above, the standard format of a message is
<prefix><command> <arguments>
So, later on in your code, you can use command to get both the prefix and the command in one string, allowing you to see if someone wants the bot to do something, or if they're just chatting with a friend and want nothing to do with the bot.
Finally, args is an array of the rest of the words, in this case ['there,', 'Cloudy', 'Sounds!'].
By using the 3 of these variables in combination, you can easily extract all the important information out of a message.
Getting The Channel
Since the user's command will contain a mentioned channel, the first thing we're gonna want to do is get that channel as a Discord.js Channel Class, so we can later send messages to it.
To get this, we can store the result of message.mentions.channels() into channel. Since we're going to be mentioning a chanel in a guild, we're gonna want to make sure it's not a DM first, and that the command actually starts with our prefix, in this case '+'. So now, our code looks like this:
<Discord.Client instance here>.on("message", message => {
if(message.author.bot) return;
let messageArray = message.content.split(" ");
let command = messageArray[0];
let args = messageArray.slice(1);
if(message.channel.type === "dm") return;
if(!message.content.startsWith('+')) return;
if(command === '+ann') {
let channel = message.mentions.channels();
}
}
Extracting the Announcement
Now that we have out channel, we're gonna want to get our announcement out from the message. We'll do this using args.
So, how do we do this?
First of all, we know that args[1] is going to be the mention of the channel ('#channel'), so that's not a part of the command. Everything else, however, is a part of our announcement, so we combine that all into a string using the following:
let announcement = args.slice(1).join(" ");
Putting it all together
Now that we have our announcement and channel, we can finally send it.
The final code would be:
<Discord.Client instance here>.on("message", message => {
if(message.author.bot) return;
let messageArray = message.content.split(" ");
let command = messageArray[0];
let args = messageArray.slice(1);
if(message.channel.type === "dm") return;
if(!message.content.startsWith('+')) return;
if(command === '+ann') {
let channel = message.mentions.channels();
let announcement = args.slice(1).join(" ");
channel.send(announcement);
}
}
Welcome to Stack Overflow, and let me know if you have any problems with this answer, or need further clarification!
Try this:
.on("message", message => {
if(message.author.bot) return;
let messageArray = message.content.split(" ");
let command = messageArray[0];
let args = messageArray.slice(1);
if(message.channel.type === "dm") return;
if(!message.content.startsWith('+')) return;
if(command === '+ann') {
let channel = message.mentions.channels();
let announcement = args.slice(1).join(" ");
channel.send(announcement);
}
I am new to discord.js but learned that I can delete my messages using bulkDelete and it will delete them all, even if they are older than 2 weeks. I clear my messages in a server I moderate manually once a month and needless to say it takes forever. I was wondering if anyone would be able to help me make a command that will do this automatically whenever I call it?
Thanks,
K
I would set up a recursive function that checks if there are messages in the channel (100 max every time): if there are no messages it stops otherwise it deletes them and restarts.
function clean(channel, limit = 100) {
return channel.fetchMessages({limit}).then(async collected => {
let mine = collected.filter(m => m.author.id == 'your_id_here'); // this gets only your messages
if (mine.size > 0) {
await channel.bulkDelete(mine, true);
clean(channel);
} else channel.send("The channel is now empty!").delete(5000); // this message is deleted after 5 s
});
}
You can adapt this idea to your existing command parser or, if you don't know how to implement this, try:
client.on('message', msg => {
if (msg.author.bot || msg.author != YOU) return;
// with YOU i mean your User object, to check permissions
let command = 'clean', // the name of your command
args = msg.content.split(' ');
if (args[0].toLowerCase() == command)
clean(msg.channel, !isNaN(args[1]) ? args[1] : undefined); //<-- THIS is how to use the function
// used a ternary operator to check if the other arg is a number
});
This is just a very basic implementation, there are a lot of better ways to detect commands.
I've just found a way to filter messages.
You can fetch messages and then check for each message if its yours
await message.channel.fetchMessages({
limit: 100
}).then((msgCollection) => {
msgCollection.forEach((msg) => {
if(msg.author.id == message.author.id) {
msg.delete();
}
})
});