I recently heard of .awaitMessages in Discord.JS and I did search it up and look at some tutorials, but I'm still not really sure of how it exactly works and how to use it properly. I would really appreciate if someone could tell me how it works and how to use it. Thanks a lot!
I've got you covered my man/woman, I wrote some example code and commented on it like crazy explaining everything I put down for you :)
client.on('message', message => {
// This just converts all messages to complete lowercase for the bot to interpret.
const command = message.content.toLowerCase();
// This variable simply stores the User ID of the person who sent the message.
const messageAuthor = message.author.id;
if (command == 'what is your name?') {
// This is the filter we will use for the Message Collector we're going to use A.K.A ".awaitMessages".
const messageFilter = message.author.id == messageAuthor;
/* This is the command you asked about in all its glory. The first parameter you give it is the filter to use (although a filter isn't required if I recall correctly.).
The next parameter is "max", this purely dictates how many messages (applying to the filter if applicable) for the collector to collect before ending (unless of course the timer runs out, which we'll touch on next).
Second to last parameter is "time", this is, like max, pretty straightforward and dictates the amount of time the collector attempts to collect messages before ending (as stated above, if the collector-
reaches the max for collected messages before the timer runs out it will end prematurely, however if for whatever reason the collector doesn't receive the max amount of collected messages, it will continue to attempt collect messages-
until the timer runs out.)
Now onto the last parameter, "errors". This parameter basically tells the collector to treat the timer running out as if it was an error, that way you can then reference said error in the ".catch" method you'll see below and give the bot-
instructions on what to do if the time does end up running out.
*/
message.channel.awaitMessages(messageFilter, { max: 1, time: 10000, errors: [time] })
.then(collected => {
// Checks to see if the message we collected is a number, and if so, responds with the message in the command below.
if (isNaN(collected) == false) {
// The response for if the collected message IS a number.
message.channel.send(`${collected} is definitely not your name!`);
}
// This runs as long as the message we collected is NOT a number.
else {
// The response if the collected message is NOT a number.
message.channel.send(`${collected} is an awesome name!`);
}
})
.catch(collected => message.channel.send('You never gave me your name ):'));
// ^ This is the ".catch" method where you'll give the instructions for what to do if the timer runs out, in this case I have it just reply to the user to tell them that they never gave me their name.
}
});
Related
I started on this small project just for fun for my friend's server. She wanted to have the bot reply to her any time she said anything in her server and she wanted the bot to stop replying after an hour after saying "shut up" (no prefixes). I currently have this
client.on("message", function (message) {
const amyID = "blahblah";
const jayID = "blahblah";
if (message.author.id == (jayID)) {
if (message.content.includes("shut up")) {
message.reply("sorry...")
setTimeout(function () {
}, 60000)
} else {
client.commands.get('replyToAmy').execute(message);
}
}
})
setTimeout seems to only work with functions which I am confused on how I can apply it to the client.on bit. If I remove setTimeout the bot will start responding again. How can I make the bot stop responding for a set amount of time after "shut up" is said by the user?
One way to do that would be create a boolean variable outside the client.on('message') function. Then the bot will keep sending a message as long as the boolean variable is set to true. Once the user tells the bot to stop, the boolean variable is set to false and you can create a .setTimeout() for the specified time after which the boolean variable will turn back to true. And then all we have to do is check if the boolean variable is true or not every time we send the message. The code might look something like this:
let keepReplying = true
const userId = 'the users id'
client.on('message', message => {
if (message.author.id === userId) {
if (message.content === 'stop') {
keepReplying = false
setTimeout(() => { keepReplying = true }, 60000)
}
}
if (keepReplying) client.commands.get('replyToAmy').execute(message);
})
Maybe Create a list to contain the user who said shut up & timestamp
then function to check user from that list and compare time with timestamp?
well if user timestamp > 1 hr then delete that from the list
there's a better way tho but this is the easy route.
and not the most effective way
as it would be too much waste with many users
but from your code seem like you just made small project
for small group of users so there's no problem
For a specific channel in my server, I want to make it so that a user can't send two messages in a row.
Here's the code I got so far:
client.on('message', message => {
if(message.guild.id != '123478291364192834') return;
if(message.channel.id != '432874912364123984') return;
let messageauthor = ''
message.channel.messages.fetch({limit:2}).then(messages=>{
messages
.forEach(message=>{
messageauthor = message.author.id
})
})
if(messageauthor == message.author.id){
message.delete()
}
})
The idea was that it'd fetch two messages in a channel and if the message author of the second message is fetched is the same as the message author, it'd delete the message. But it doesn't do that, does anyone know why or have any solutions to the problem?
There are several problems with your code as-is.
Problem
First of all, you're checking if messageauthor is equal to message.author.id outside of your .then(). The code inside a .then() has its execution delayed because it executes asynchronously. In other words, it takes some time to fetch the messages in the channel, which is why you can only access messages in your .then(). Because the contents of your .then() execute after the rest of your code, including the code that proceeds it, you are checking if messageauthor is equal to message.author.id before the value of messageauthor is even set. Your if statement will always be checking if the empty string '' is equal to the ID of the message's author, which is always false, so the message will never be deleted.
Second, inside your .then() you are looping through the two messages you've fetched and are setting messageauthor to the ID of the message's author. But since you're doing this twice, since you fetched two total messages, that means that messageauthor is only set to the author ID of the second message. So why loop through both messages, when you can just immediately grab the author ID from the last message?
Finally, you're only checking if the author of the second message matches the ID of the current message's author. How that behaves depends on whether or not the current message is fetched along with the last message. If the current message is included in messages, then the second message literally is the current message, so that will delete every single message that anyone ever sends. If the current message isn't included in messages, then why are you fetching two messages with your .fetch()? From your question, it seems you do not want people to send two messages in a row. That would mean you only have to fetch 1 previous message and use just the message you fetched in your comparison. I will attempt to account for both of these possibilities below with two separate answers, as I am not sure whether the current message will be included.
Solution
Here's how I would suggest you revise your code, assuming the current message is included in the fetched messages (I'm assuming this will not be the case):
client.on('message', message => {
if(message.guild.id != '123478291364192834') return;
if(message.channel.id != '432874912364123984') return;
message.channel.messages.fetch({limit:2}).then(messages=>{
let firstauthor = messages.first().author.id;
if(firstauthor == message.author.id){
console.log("Deleting message because 2 messages in a row were sent");
message.delete();
}
});
})
Here's what I would do if this current message is not included in the fetched messages (which I assume will be the case, so this should work properly):
client.on('message', message => {
if(message.guild.id != '123478291364192834') return;
if(message.channel.id != '432874912364123984') return;
message.channel.messages.fetch({limit:1}).then(msg=>{
let firstauthor = msg.author.id;
if(firstauthor == message.author.id){
console.log("Deleting message because 2 messages in a row were sent");
message.delete();
}
});
});
In both of these fixes, what I've done is first and foremost I've moved the if statement into the end of the .then(). This ensures that the condition is only checked after the messages have been fetched. Second, I removed the forEach loop and replaced it with simple references to the first, or only, item in the fetched message collection. Third, I made sure it was the first message, and not the second message, that would have its author's ID compared to the current message author's ID. And finally, I added a simple console.log to help you debug the issue. If the console.log never occurs but you know it is supposed to, that means something is wrong in the code.
Feel free to try either solution, or both, out and find which one works for you. I have not tested either thoroughly, so if you find an issue let me know and I will fix it. This should give you a general idea of what the issue is in your code nevertheless, so you should hopefully be able to fix the issue on your own even if these solutions do not work. I am guessing the second of the above solutions will work best.
I was making this new bot and used awaitmessage function.When a user use the cmd '!gangsug', the bot is supposed to ask a question like - "Please choose a option - RP or Fight" and when the user uses an option it is supposed to give a reply. (Which is a embed one). I have given two different replies for the 2 answers given by the user.(One for the answer "RP" and the other for the answer "Fight"). In this case, by bot is giving same answer for both answer. If the user types "RP" or "Fight" same reply is being given
by the bot. I hope you understood the problem.The code will be given below (ofc only the part where the problem comes)
if (message.content === `${prefix}gangsug`) {
message.reply('Hey there! Please choose a option.\n'
+ 'Confirm with `RP` or with `Fight`.');
// First argument is a filter function - which is made of conditions
// m is a 'Message' object
message.channel.awaitMessages(m => m.author.id == message.author.id,
{max: 1, time: 30000}).then(collected => {
// only accept messages by the user who sent the command
// accept only 1 message, and return the promise after 30000ms = 30s
// first (and, in this case, only) message of the collection
if (collected.first().content.toLowerCase() == 'RP') {
message.reply(suggestgang1);
}
else
message.reply(suggestgang2);
message.reply(suggestgang3);
}).catch(() => {
message.reply('No answer after 30 seconds, req canceled.');
});
} }
);
**Yea, this is the code..It would be great of you give an answer by stating the problem and a fixed code to replace this one. Thank you :) **
I believe the problem is in this line:
if (collected.first().content.toLowerCase() == 'RP')
Since you used the .toLowerCase() method on the message content, it's physically impossible to match anything uppercase, such as 'RP'.
if (collected.first().content.toLowerCase() == 'rp')
I'm currently trying to create a Discord bot that sends a message when a user with a specified role sends the command %sticky This is a test
I want it to always be the first message in the channel and every time another user types in the channel the bot deletes its last message and posts again. I haven't had any luck online yet even finding a bot that already does this functionality, or where to even start. Here's what I kind of have so far
var lastStickyMessage;
client.on('message', message => {
if (lastStickyMessage != null) {
message.channel.fetchMessage(lastStickyMessage)
.then(retrievedMessage => retrievedMessage.delete());
}
message.reply("This is a Sticky Message").then(sent => {
let lastStickyMessage = sent.id;
}
});
There are several errors with your variable management: One one hand you create a new let with the same name. Since a let is a scoped variable, the lastStickyMessage will have a different value inside the sent callback than it has outside of it, since those are two different variables (read more on this here).
Apart from that you should save the last sent ID in a file or somewhere since the var will be reset once you restart your bot (the built in fs module could help you with that, you can find the documentation here).
One last thing: If you initialize a variable without a value it is not null but undefined. If you only check using == it will still evaluate to true (means null == undefined) but if you compare using ===, it will evaluate to false (null !== undefined). In your case this is not really a problem but this might be good to know for other cases.
This calls and retrieves a dog url from random.dog, when posting the link to log it stops at one, however when using message.channel.send below it runs an infinite loop of the call, what would be the best way to prevent this and to only send one link then stop till it is called again?
const animals = require('relevant-animals')
client.on("message", (message) => {
if(message.content.includes("dog")){
animals.dog().then(s => message.channel.send(s)) ;
animals.dog().then(s => console.log(s)) ;
};
Below is console log after one request it sends one link
Below is after it is sent to the channel, it just posts links non stop rather than just the one as shown in the console
Your bot is responding to itself. You can exclude it for replying to itself by using message.author.bot.
if(!message.author.bot) {
// Do something if message doesn't come from a bot.
}
I hope this code will help you getting on the right path, good luck!
You could just do this:
if(message.author.bot) return;
This wouldn't only stop bot from executing commands etc. on itself, it would prevent any bot from using your bot.
Since it checks for author of message if bot property returns true it would return;.
And if bot property returns false it would work as normally - only for users like you and me, and many others!
You can try this by doing the following code:
console.log(message.author.bot);
It will log the boolean value of bot property of the messages author.
You can read more about booleans (true/false) here.