How do I stop an infinite loop command on a Discord Bot? - discord

Let's say I made an infinite command for my bot, Would there be any way to stop the loop at any time? I want to be able to stop it from the server, not in the actual code.
Example:
if(msg.content === "Just Monika"){
msg.channel.send('Just Monika')
}
})
Is there any way I can type something in chat, and it stops the command? thanks.

Making your bot respond to itself infinitely probably isn't a good idea. But just for learning, it's very possible to do what you wish.
You could make a different phrase (let's call it the stop command) set a boolean variable in your code to true. Then, whenever the looping command gets triggered by a user message or by one of its own, it should check if this boolean telling it to stop is true. If it is, it should set it to false and not send that message, else it should just send that message as per usual.
// The following should be defined in the outmost scope
let loopPhrase = "Just Monika";
let stopPhrase = "Stop Spamming The API";
let triggerStop = false;
// The following should be a part of the message event
if (msg.content === loopPhrase) {
if (!triggerStop) msg.channel.send(loopPhrase);
else triggerStop = false;
} else if (msg.content === stopPhrase) triggerStop = true;

Related

How to not send bots message edit discord.js

I have a message edit log but I want to stop sending the log if a mobs message was updated, I tried a few codes like
if(bot.oldMessage.content.edit()){
return;
}
It showed and error
cannot read property 'edit' of undefined
I then removed edit then content was undefined. The code for the message update is below.
The Code
module.exports = async (bot, oldMessage, newMessage) => {
let channels = JSON.parse(
fs.readFileSync('././database/messageChannel.json', 'utf8')
);
let channelId = channels[oldMessage.guild.id].channel;
let msgChannel = bot.channels.cache.get(channelId);
if (!msgChannel) {
return console.log(`No message channel found with ID ${channelId}`);
}
if (oldMessage.content === newMessage.content){
return;
}
let mEmbed = new MessageEmbed()
.setAuthor(oldMessage.author.tag, oldMessage.author.displayAvatarURL({dynamic: true}))
.setColor(cyan)
.setDescription(`**Message Editied in <#${oldMessage.channel.id}>**`)
.addField(`Before`, `${oldMessage.content}`)
.addField(`After`, `${newMessage.content}`)
.setFooter(`UserID: ${oldMessage.author.id}`)
.setTimestamp()
msgChannel.send(mEmbed)
}
How would I stop it from sending the embed if a bots message was updated.
Making a really simple check will resolve this issue. In Discord.js there is a user field that tells you if the user is a bot or not.
In fact, it is really recommended you add this in the "onMessage" part of your code as it stops other bots from using your bot, this is to make sure things are safe and no loopbacks/feedbacks happen, either way, you don't want a malicious bot taking advantage of your bot, which can get your bot in trouble too.
Here is what you want to do;
if (message.author.bot) return;
What this code specifically does is check if the message's author is a bot, if it returns true, it will break the code from running, if it returns a false, the code continues running.
You can do the same if you want to listen to bots ONLY by simply adding a exclamation mark before the message.author.bot like this;
if (!message.author.bot) return;
It is also possible to see what other kinds of information something holds, you can print anything to your console. For example, if you want to view what a message object contains, you can print it into your console with;
console.log(message) // This will show everything within that object.
console.log(message.author) // This will show everything within the author object (like ID's, name, discriminators, avatars, etc.)
Go ahead and explore what you can do!
Happy developing! ^ -^
That is really easy to do. All you need to do is check if the author of the message ist a bot and then return if true. You do that like this
if (oldMessage.author.bot) return;

Discord.js - Getting multiple reactions to execute a command through awaitReactions method

I'm currently in the process of making a little game of TicTacToe, and the idea I had in mind is to make it so instead of the channel being spammed with constant embeds asking for the person's next move, is to simply make it reaction-based, where you get to pick 1 out of 9 reactions (And of course, you wont be able to pick it again if the other player has already picked it).
I have never really worked with requiring multiple reactions, therefore I'd like to ask your help on how exactly to make it so that the message command execution isn't a one-time thing, but will go on until there's eventually a winner.
So far, with the code I have written, this does work 2 times, but then it randomly stops and no longer works.
In addition, when I'm trying to declare a spot as an x or a circle, the spot turns completely blank.
Please help!
The code I have so far:
https://sourceb.in/S7cayfoYjp
Edit: I have now also found that the bot at first kind of skips the whole awaitReactions code. I used 'console.log(i)' for this, so that every time it loops it prints out 'i', and it seemed to be printing out the numbers 0-8 immediately, meaning it's not properly going through the code.
I think what you can use best there is a reactionCollector. It's a temporary reaction listener, attached to a message. A sample code for that would be:
const msg = await message.channel.send('tic tac toe test');
const acceptedEmojis = ['↖️', '⬆️', '↗️', '⬅️', '⏺️', '➡️', '↙️', '⬇️', '↘️']
const filter = (reaction, user) => {
return acceptedEmojis.includes(reaction.emoji.name) && user.id === turnId;
}
//here you create the collector. It has following attributes: it stops after 10 minutes or after 2 minutes of not collecting anything.
const collector = msg.createReactionCollector(filter, { time: 600000, idle: 120000});
//here you start the listener
collector.on('collect', (reaction, user) => {
if (reaction.emoji.name === '↖️') {
//remove the reaction
await msg.reactions.resolve('↖️')
acceptedEmojis.splice(acceptedEmojis.indexOf('↖️'), 1);
//rest of your code...
} else if (reaction.emoji.name === '⬆️') {
...
}
});

Discord js TypeError: Cannot read property members

Hello i have this code,
user = message.guild.members.fetch(id2).then((use,err)
And i have this error
TypeError: Cannot read property 'members' of null
Please can yuo help me ?
Thank you
message.guild is not initialized. You could check if it is null before use eg
if(message.guild){
user = message.guild.members.fetch(id2).then((use,err) ...
}else{
//do something when it is not initialized
}
Your error occurs because the message object refers to a message that was received as a DM. Because of how DMs work, there is no guild or member property for such message (they are left as nulls).
To avoid that, you should handle direct messages slightly differently. The easiest and most commonly used way is to completely stop direct messages from running your message event code. This can be done by adding
if (message.channel.type === 'dm') return;
at the very top of your event.
As that makes it impossible to initiate commands in DMs, even if they don't need to be executed in a guild to work (like ping command for example), this might be not what you want. In such case, you should implement a way to determine if command someone tried to run in DM is "allowed" to be executed there. Implementations for that vary depending on command handling implementation, but snippet below is basic princinple.
client.on('message', message => {
if (message.author.bot || !message.startsWith(prefix)) return;
const args = message.content.slice(prefix.length).split(/ /g);
const command = args.shift().toLowerCase();
if (command === 'memberinfo') {
if (message.channel.type === 'dm') return message.reply('this command cannot be run in DMs.');
// Actual command code
}
});

Time Delay until next message sent from Discord Bot

In the Discord bot I'm creating, I'd like to make it so that the bot waits lets say 60 seconds before sending another reply to the same command or "includes" word. For instance, if someone says ping below, I want the bot to wait a minute until the next one is sent. I do not want the bot to hold it and put it into a queue or anything of that sort, I just want it to ignore the command for a minute until the next one happens.
if (message.content.includes("ping")) {
message.reply("pong!");
}
If I understand your question correctly, you would want to make a boolean variable and use setTimeout.
The global function setTimeout waits for the provided amount of milliseconds, in this case 60000 (60 seconds), then changes the variable to true again so it can be run.
var pingEnabled = true;
if (ping command run && pingEnabled) {
reply("Pong!");
pingEnabled = false;
setTimeout(() => { pingEnabled = true }, 60000);
}
most of this is pseudocode and you may need to adapt it to your situation.

Check if message has channel mention

I don't know what method to use to check if the message contains a mention to a channel; if it does, I want to continue with the execution, if not, return an error message.
if (message.mentions.channels == true) {
console.log('Yeah, you used a channel mention');
} else {
console.log('Hey boy, you have to use a channel mention');
}
Can someone clear my doubt?
You can use Collection.first() to see if the collection has at least 1 element (that means that the message has at least 1 channel mention).
It should look like this:
if (message.mentions.channels.first()) console.log("You used a channel mention.");
else console.log("You didn't.");

Resources