How do I fix DiscordAPIError: Unknown Message? - javascript

I made a bot that deletes text messages in an image channel, but when I use it it's logs this error.
client.on("message", async message => {
if (message.author.bot) return;
const users = ['853248522563485717'];
if (message.channel.id === '841260660960395287') {
if (users.includes(message.author.id)) return;
if (message.attachments.size !== 0) return;
message.member.send("You can't send text in 'images' channel")
await message.delete();
} else return;
});
(this is different from the other questions with the same topic)
how do I fix it?

The most likely problem is that you are running multiple instances of the Discord bot. Check if you have multiple command lines open, if so, check if they are running the bot. Apart from that, if users spam, Discord API tends to get confused about which messages to delete, making it try to delete the same message more than 1 time. You can try adding an if statement checking if the message is undefined.
client.on("message", async (message) => {
if (!message) return; // ADDED THIS LINE OF CODE
if (message.author.bot) return;
const users = ["853248522563485717"];
if (message.channel.id === "841260660960395287") {
if (users.includes(message.author.id)) return;
if (message.attachments.size !== 0) return;
message.member.send("You can't send text in 'images' channel");
await message.delete();
} else {
return;
}
});

From your error above, you are seemingly using a message event listener for every command or function you want your bot to perform. The maximum for this is 11 (of the same type). This is not the correct way to do this.
What is an event listener?
//the 'client.on' function is called every time a 'message' is sent
client.on("message", async (message) => {
//do code
});
How to fix this:
Instead of using 1 event listener per command, use 1 for the whole client. You could solve this a multitude of ways, with command handlers or such, however I will keep it simple.
This is the basic setup you should see in your index.js or main.js file:
// require the discord.js module
const Discord = require('discord.js');
// create a new Discord client
const client = new Discord.Client();
// on message, run this
client.on('message', (message) => {
if (!message) return;
console.log(`message sent in ${message.channel.name}. message content: ${message.content}`);
//this event will fire every time a message is sent, for example.
});
// login to Discord with your app's token
client.login('your-token-goes-here');
So what do you do if you want to do multiple functions with your bot? (for example deleting text in an images only channel and logging messages to console)
Command handling. It is the only way. I linked an official Discord.js guide above, read through it and see what you can do. I would highly recommend trying this with an entirely different bot and clean index file, as it would be easier than trying to fit in code you dont understand between your already problematic code.

Related

How can I make a discord bot check the contents of a message and reply with a different message depending on the author?

How can I make a discord bot check the contents of a message and reply with a different message depending on the author?
This is my code so far, I found it in a tutorial but it doesn't work. (no error messages for some reason)
client.on('message', function (userID, channelID, message) {
const thisWord = "i'm so cool";
if(message.content.includes(thisWord)) {
if(userID === '<#ID>'){
client.sendMessage({
to: channelID,
message: "agreed"
})
}}
else {
client.sendMessage({
to: channelID,
message: "disagreed"
})
}
})
First of all you must be using a later version of DJS. Please update to the newest stable version v12.5.3. Second, the message event only accepts one parameter whereas you gave three parameters. Third, if you want to send different replies to different messages, then you need to handle the message content. That is, split the message content by space and then handle them.
This might guide you on working with user input commands.
The issue here looks like you're using the old version of DJS. use the latest one.
This would be the correct usage for discord.js v 12.5.3
// the id should be like this '429493473259814923' :)
client.on('message', async message => {
const thisWord = 'i\'m so cool';
if (message.content.toLowerCase().includes(thisWord)) {
if (message.author.id === 'ID') message.reply('disagreed');
else message.reply('disagreed');
}
});

Reaction event discord.js

I'm trying to make a starboard code with my bot, and everything else is working good. But I'm trying to make it to where the bot ignores reactions from the author of the actual message.
This is my current code:
client.on('messageReactionAdd', (reaction_orig, message, user) => {
if (message.author.id === reaction_orig.users.id) return
manageBoard(reaction_orig)
})
It returns the following error:
if (message.author.id === reaction_orig.users.id) return;
^
TypeError: Cannot read property 'id' of undefined
The problem is that messageReactionAdd takes two parameters; the message reaction as the first one, and the user that applied the emoji as the second one. When you write reaction_orig, message, user, reaction_orig is the reaction (which is correct), but message is the user who reacted as it's the second parameter. The user variable will be undefined.
Another issue is that reaction_orig.users returns a ReactionUserManager that doesn't have an id property. Luckily, the user is already passed down to your callback so you can use its ID.
Also, reaction_orig has a message property, the original message that this reaction refers to so you can get its authors' ID from it.
You can change your code to this to work:
client.on('messageReactionAdd', (reaction_orig, user) => {
if (reaction_orig.message.author.id === user.id) {
// the reaction is coming from the same user who posted the message
return;
}
manageBoard(reaction_orig);
});
However, the code above only works on cached messages, ones posted after the bot is connected. Reacting on older messages won't fire the messageReactionAdd event. If you also want to listen to reactions on old messages you need to enable partial structures for MESSAGE, CHANNEL and REACTION when instantiating your client, like this:
const client = new Discord.Client({
partials: ['MESSAGE', 'CHANNEL', 'REACTION'],
});
You can check if the message is cached by e.g. checking if its author property is not null. If it's null, you can fetch the message. Now, you have both the message author and the user who reacted, so you can compare their IDs:
// make sure it's an async function
client.on('messageReactionAdd', async (reaction_orig, user) => {
// fetch the message if it's not cached
const message = !reaction_orig.message.author
? await reaction_orig.message.fetch()
: reaction_orig.message;
if (message.author.id === user.id) {
// the reaction is coming from the same user who posted the message
return;
}
// the reaction is coming from a different user
manageBoard(reaction_orig);
});
Try doing this :
client.on('messageReactionAdd', (reaction, user) => {
if (!reaction.message.author.id === user.id){
//Do whatever you like with it
console.log(reaction.name)
}
});
Note: The message must be cached. For that you'll need to do this
Client.channels.cache.get("ChannelID").messages.fetch("MessageID");
I'm guessing you're using discord.js v12

How to make discord.js bots check if the channel is NSFW and reply?

I want to make my discord bot send different messages when anyone types a command in a normal channel or NSFW channels.
I followed the documentation, which I didn't quite get it. I wrote the testing commands below:
client.on('message', message => {
if (command === 'testnsfw') {
if (this.nsfw = Boolean(true.nsfw)) {
return message.channel.send('yes NSFW');
} else return message.channel.send('no NSFW');
}
})
I think it is not working. The bot only responds "no NSFW" on both channels.
You cannot refer to the TextChannel using this in the anonymous function. (Also, this is always undefined in an arrow function) You can access the TextChannel using the Message class, stored in the message variable.
client.on("message", message => {
// Making the sure the author of the message is not a bot.
// Without this line, the code will create an infinite loop of messages, because even if a message is sent by a bot account, the client will emit the message event.
if (message.author.bot) return false;
// message.content is a String, containing the entire content of the message.
// Before checking if it equals to "testnsfw", I would suggest to transform it to lowercase first.
// So "testNSFW", "testnsfw", "TeStNsFw", etc.. will pass the if statement.
if (message.content.toLowerCase() == "testnsfw") {
// You can get the Channel class (which contains the nsfw property) using the Message class.
if (message.channel.nsfw) {
message.channel.send("This channel is NSFW.");
} else {
message.channel.send("This channel is SFW.");
}
}
});
What I encourage you to read:
Message
TextChannel
now you can just do this instead
if(!message.channel.nsfw) return message.channel.send('a message to send to channel')
this is using
discord.js verson 13.6.0

Error when wanting to read the messages of a specific channel

I'm trying to "moderate" a channel, in this one should only be able to send certain commands, and when they send a command or message different from the one allowed, then I would send a message warning about it. The logic of moderation I have with the conditions, but my problem is that I can not get the messages that are sent on that channel (of anyone who writes on that specific channel)
When executing the code it does not show me anything in the console, which means that it is not recognizing the messages that they send in that channel :(
Code:
client.on("message", (message) => {
if (message.author.tag === "NAME#1234") {
if (message.content.startsWith(prefix + "on")) {
console.log(message.channel.id)
if (message.channel.id == "361344824500289538") {
//If the channel where they send the message has the id that I have set, then show me the messages that are sent
console.log(message.content)
} else {
console.log(message.content)
}
}
}
});
Let’s say you want to have a command only to be used in one channel (this could be /meme for a channel called “memes”). If the command is used elsewhere the bot will say “Command Not Allowed Here!”
Here Is The Code:
client.on("message", message => {
if (message.content.startsWith('/meme') {
if (message.channels.find(c => c.name ===! 'memes') {
message.reply("Command Not Allowed Here!")
} else {rest of meme command script}
}
}

Referencing a DM channel

I'm trying to create a command that allows users to create their password following prompts through DM. I'm able to send a message to the user, but not able to read a message sent back with a MessageCollector because I cannot find a way to reference the DM channel.
I have tried using another instance of bot.on("message", message) here, but that creates a leak in the system causing the second instance to never disappear.
I also can't let users use a command say !CreatePassword *** because this function is linked with many others in a strict order.
Maybe I'm doing something fundamentally wrong, or approaching the problem in a bad way, but I need a way to reference a DM channel.
This is the best iteration of my code so far.
function createAccount(receivedMessage, embedMessage)
{
const chan = new Discord.DMChannel(bot, receivedMessage.author);
const msgCollector = new Discord.MessageCollector(chan , m => m.author.id == receivedMessage.author.id);
msgCollector.on("collect", (message) =>
{
// Other Code
msgCollector.stop();
// Removing an embed message on the server, which doesn't have a problem.
embedMessage.delete();
})
}
I can show the rest of my code if necessary.
Thank you for your time. I've lost an entire night of sleep over this.
I would do it like this (I'll assume that receivedMessage is the message that triggered the command, correct me if I'm wrong)
async function createAccount(receivedMessage, embedMessage) {
// first send a message to the user, so that you're sure that the DM channel exists.
let firstMsg = await receivedMessage.author.send("Type your password here");
let filter = () => true; // you don't need it, since it's a DM.
let collected = await firstMsg.channel.awaitMessages(filter, {
maxMatches: 1, // you only need one message
time: 60000 // the time you want it to run for
}).catch(console.log);
if (collected && collected.size > 0) {
let password = collected.first().content.split(' ')[0]; // grab the password
collected.forEach(msg => msg.delete()); // delete every collected message (and so the password)
await firstMsg.edit("Password saved!"); // edit the first message you sent
} else await firstMsg.edit("Command timed out :("); // no message has been received
firstMsg.delete(30000); // delete it after 30 seconds
}

Categories