I've been working on this code recently which I found here:
Discord.js reply to message then wait for reply
I'd like to know if there is any way for the script to run a command when the timer goes off without any answer.
I've tried putting the command outside the code block of the collector
I've tried putting an if (timer > 10000), which didn't work.
if (command === 'spec') {
message.author.send("See or Change?");
const collector = new Discord.MessageCollector(message.channel, m => m.author.id === message.author.id, {
time: 10000
});
console.log(collector);
collector.on('collect', message => {
if (message.content == "See") {
message.channel.send("You Want To See Someones Spec OK!");
} else if (message.content == "Change") {
message.channel.send("You Want To Change Your Spec OK!");
}
});
}
When time ends I expect the script to change the nickname of the user who used it.
You could listen to the end event of the Collector and check the size of the collected messages.
collector.on('end', collected => {
if (collected.size === 0) {
// do something
}
});
Related
client.on("message", message =>{
if(message.channeltype = 'dm')
if (message.content === "confess")
message.channel.send("OOOOOOoooooo A SECRET??!?!?! WHAT IS IT?!??!")
message.channel.awaitMessages("response", message =>{
C = message.content
message.reply("Um.... theres two servers that this bot works on. 1: Loves in the snow or 2:๐Moomins and Shep's Therapy Service๐. Pick a number to send it to one of them")
client.on("message", message => { //////// SWITCH THIS LINE OUT FOR THE THING THAT WAITS FOR NEW MESSAGES
if (message.content === "2")
WDI = message.author
WDID = message.author.id
message.channel.get(WDIC2).send("Ok ok so who did it is" + WDI + "and their id is" + WDID)
message.channel.get(CC2).send(C)
if (message.content === "1")
WDI = message.author
WDID = message.author.id
message.channel.get(WDIC1).send("Ok ok so who did it is" + WDI + "and their id is" + WDID)
message.channel.get(CC1).send(C)
})
})})
Why does my bot not reply to my message?
I first put in confess then it would say the message but it doesnt detect that I continue and reply to that. WHat do I do?
Okay first off, try to be a lot more specific when asking questions there is a stackoverflow guide on how you should ask them effectively. Right now you are being unclear and I'm going to have to assume some stuff. Also, include a stack trace whenever possible, which there should have been as you provide some invalid properties, if you don't have one please include that there is not a stack trace in the question.
There is a lot of things wrong with this code. First off, the reason your bot isn't responding to you at all is because message.channeltype is not a property. Use message.channel.type instead. There is also something wrong with your message.channel.awaitMessages(). You are passing in a "response" string as a parameter, where there should be a filter. Since you don't need a filter since it is a dm channel you can just pass it in as null message.channel.awaitMessages(null, msg => { });. And awaitMessages is not the right call here. Await messages takes in messages in a certain time period, then resolving a promise with all of the collected messages. You should be using a discord.js collector. You should also not be using client.on("message") here. I'm assuming that you want to wait for messages in any channel after somebody "shared their secret". You can do that with a collector. If you want to collect messages all over the bot, or in just one discord server channel (using the filter which can be found on the docs) you can use a collector. This will wait for, in a number of milliseconds, for any event and filter out event triggers that aren't allowed. And when it gets it, it will run a lambda. Like this:
const filter = m => m.channel === message.channel && m.author = message.author); // The filter that will sort out the messages
const collector = message.channel.createMessageCollector(filter, { time: 30000 }); // creates a collector that will wait for 30 seconds
collector.on('collect', m => { // When somebody sends a message
// ...
if (message.content === '2') {
// ...
} else if (message.content === '1') {
// ...
} else {
message.reply('you need to say either 1 or 2. Please try again.');
return;
}
collector.stop(); // Makes sure that the collector no longer will receive anymore messages.
});
Final code (fill in the gaps I'm not going to code it all for you)
client.on("message", message => {
if(message.channel.type = 'dm')
if (message.content === "confess")
const filter = m => m.channel === message.channel && m.author = message.author; // The filter that will sort out the messages
const collector = message.channel.createMessageCollector(filter, {time: 30000})
collector.on('collect', message => {
const otherCollector = message.channel.createMessageCollector(filter, { time: 30000})
otherCollector.on('collect', message => {
if (message.content === '2') {
// ...
} else if (message.content === '1') {
// ...
} else {
message.reply('you need to say either 1 or 2. Please try again.');
return;
}
collector.stop(); // Makes sure that the collector no longer will receive anymore messages.
})
})
})
Also, before asking on any forum or discord server, always look up the documentation. It helps out 99% of cases, unless the docs is absolutely garbage.
Please read the docs. I'd say that the Discord.JS docs are a pretty handy reference.
For the first part, message.channeltype is not a real property, and do not use =. That is for setting variables, use == or === instead (What is the difference?). You can use message.channel.type or you can use instanceof as followed: message.channel instanceof Discord.DMChannel. Replace Discord with whatever your Discord.JS import variable is called.
Your ifs are missing some {}, they should be used as followed.:
if(message.channel instanceof Discord.DMChannel) {
//If the channel IS a DMChannel
} else return;
FYI, if you're planning to make multiple commands, I'd use a switch, and a way to convert message.content to arguments (string array).
message.channel.get is not a thing, use client.channels.cache.get. The variables C, and WDI / WDID need to have var before them.
Then you need to add a filter plus maximum messages, time limit, and minimum messages for your awaitMessages function. Plus you need then and catch, so now your code might look like this
if(message.channel instanceof Discord.DMChannel) {
if (message.content === "confess") {
message.channel.send("OOOOOOoooooo A SECRET??!?!?! WHAT IS IT?!??!")
message.reply("Um.... theres two servers that this bot works on. 1: Loves in the snow or 2:๐Moomins and Shep's Therapy Service๐. Pick a number to send it to one of them")
const filter = m => m.author == message.author;
message.channel.awaitMessages(filter, {/* whatever your parameters/limits are */})
.then(col => {
if (col.content === "2") {
/** Add in code */
} else if (col.content === "1") {
/** Add in code */
}
})
.catch(col => {/** Whatever you want to do if times up. */})
}
}
You may want to tweak the filter on this.
So i started to make a discord bot using discord.js which has a command for tic tac toe.
I tried using a message collector, like this in a while loop. After it enters the loop nothing happens. I added a console.log to see if the totalRouds variable is modifying and it was, so the loop somehow passed over the message collector code and executed just the last line.
while(numberOfrounds < 9){
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
message.channel.awaitMessages(filter, {max: 1, time: 3000, errors: ['time']}).then(collected => {
// code for drawing a canvas
}).catch(err => {
console.log(err);
});
console.log(totalRouds);
numberOfrounds ++;
}
.awaitMessages() returns a Promise that resolves into your collected message data asynchronously. That means that while your last log statement runs immediately after you start collecting messages, the collected messages are only available and thus processed at a later time.
To illustrate that, let me tidy your code a little and add some logs in the order that your code would normally run:
while (numberOfrounds < 9) {
console.log("1");
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
console.log("2");
message.channel.awaitMessages(
filter,
{ max: 1, time: 3000, errors: ['time'] }
).then(collected => {
console.log("5, after resolving, the collected data is only now avaiable");
}).catch(err => {
console.log(err);
});
console.log("3");
console.log(totalRouds);
numberOfrounds++;
console.log("4, immediately starts the next loop, back to #1 again");
}
I presume that your totalRouds variable is defined within the callback function passed into .then(). So other than the typo (let's fix that), your variable would be defined in the wrong scope and thus totalRounds would always remain undefined, even after the Promise resolves with your collected messages, you process those messages, you set totalRounds within the callback function etc. So here is our updated snippet:
while (numberOfrounds < 9) {
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
message.channel.awaitMessages(
filter,
{ max: 1, time: 3000, errors: ['time'] }
).then(collected => {
let totalRounds = 1 // Do your processing here
console.log(totalRounds); // This should log as expected
}).catch(err => {
console.log(err);
});
numberOfrounds++;
}
But this is still probably not the behaviour you are looking for. Why? Your bot will attempt to send all 9 replies (assuming your numberOfRounds starts at 0 earlier) at once, at which point Discord.js will automatically send them in batches to avoid spamming the API, and all message collectors would be waiting concurrently. You probably intend to "pause" or suspend processing until the Promise returned by .awaitMessages() resolves and you have finished processing the returned data, causing synchronous behaviour whilst using an asynchronous method call (therefore you say "the loop somehow passed over the message collector code and executed just the last line"). To do this, we can use async-await:
/*
You have not provided your full code,
so what you need to do is mark your message event's
callback function as async.
Refer to the linked article on MDN.
*/
while (numberOfrounds < 9) {
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
/*
Then, wait for the Promise returned by
this promise chain to resolve
before resuming operation
and moving on to the next iteration.
*/
await message.channel.awaitMessages(
filter,
{ max: 1, time: 3000, errors: ['time'] }
).then(collected => {
let totalRounds = 1
console.log(totalRounds);
}).catch(err => {
console.log(err);
});
numberOfrounds++;
}
My terminology may not be 100% correct, but this is my understanding. Feel free to comment if improvements can be made.
const prefixtest = ">>"
msg = message.content.toLowerCase();
if(msg.startsWith(prefixtest + "test")) {
message.delete();
setTimeout(function() {
if{message.channel.author.id == "240254129333731328"}{ //this is the bots id
message.delete();
}, 3000);
}
Sorry if my english is bad. But I can't solve this problem, i'm trying to find it on internet but nothing. How can I delete other bot messages by using their Bot ID?
There is an issue in your code, you are trying to get .author property on a Channel instead of a Message.
So you have to modify your if statement as following :
if (message.author.id === "240254129333731328")
Also, you can delay the deletion of a Message by adding .delete() method first parameter an object with a .timeout property in it that will represent the delay in milliseconds before the message being deleted. (See docs)
message.delete({ timeout: 3000 });
So you can modify your code this way :
if(msg.startsWith(prefixtest + "test")) {
if (message.author.id === "240254129333731328") {
message.delete({ timeout: 3000 });
}
}
msg.guild.channels.find(c => c.id == "693088078168064051").send(tempVars("absence_review"))
.then(function(message) {
const approved = message.react("โ
")
.then(() => message.react("โ"))
.catch(error => {});
const filter = (reaction, user) => {
return ['โ
', 'โ'].includes(reaction.emoji.name) && user.id === message.author.id;
};
message.awaitReactions(filter, {
max: 1
})
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === 'โ
', reaction.user.bot === false) {
message.reply('reacted with yee.');
} else if (reaction.emoji.name === 'โ', reaction.user.bot === false) {
message.reply('reacted with nah dude.');
}
})
.catch(collected => {
message.reply('you didnt react idiot');
});
That is the code I am currently using for the command. What I am making this command to do is to record an absence, send it to another channel with reactions, have someone react to it and if they react with the checkmark, it will send it back to the channel where the command was originally sent, but if they react to the cross, the person who originally made the command gets DM'd by the bot. Those last few things are easy, but my main issue is the reactions. I have made the reactions appear, but the last bit of the code seems to break it. Everything after the 'const filter' bit. If I remove all that, then it will just send the embed message with the reactions, but the reactions won't do anything. However, if I keep that in. It won't even send the message, I get an error stating "SyntaxError: Unexpected end of input" Now I have googled for this for around an hour, getting friends to help but unfortunately nothing is helping. If anyone could help it would be greatly appreciated, thanks in advance.
Although I cannot see the whole code, I believe your error is thrown not from the code above. The syntax error 'unexpected end of input' is usually caused by not finishing a bracket or brackets i.e )}; in somewhere in your code - commonly after the 'client on' function in your main.js file. Go through your whole code and make sure every bracket is properly represented. Maybe put your code into code.vb - it detects and points out syntax errors like the one you have above.
Let me know of progress.
I have spent yet another 3 hours in my mini dungeon figuring this out and got something to somewhat work.
msg.guild.channels.find(c => c.id == "693088078168064051")
.send(tempVars("absence_review")).then(function(message){
message.react("โ
")
.then(() => message.react("โ"))
.catch(error => {});
});
const filter = (reaction, user) => {
return ['โ
', 'โ'].includes(reaction.emoji.name) && user.id === message.author.id;
};
message.awaitReactions(filter, {
max: 1
})
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === 'โ
', reaction.user.bot === false) {
message.reply('reacted with yee.');
} else if (reaction.emoji.name === 'โ', reaction.user.bot === false) {
message.reply('reacted with nah dude.');
}
})
.catch(collected => {
message.reply('you didnt react idiot');
});
This is a fixed version of it, although the last bit doesn't necessarily work, I will try figure the rest out by myself.
I'm writing a discord bot using discord.js, and I've recently added a //translate command that utilizes the Google Translate API to translate between all the languages supported by Google Translate. I want to add the ability to quickly re-translate the translation back into English using reactions, and I want the bot to check if 1 person has reacted to the post with the provided reaction, and if they have, re-translate the translation back to English.
I'm really close, but I've run into the problem that I can't get the bot to check if it itself sent the reaction, so it auto-retranslates back to English because it's detecting it's own reaction. I want for it to only re-translate when A PERSON reacts, and only ONCE.
I'm not super familiar with this area of discord.js yet, so I can't really figure out how to do it.
Here is the code:
if (msg.content.startsWith(`${prefix}translate`) || msg.content.startsWith(`${prefix}t`)) {
const text = args.slice(1).join(` `);
if (!text) return msg.channel.send(`Nothing to translate provided! Languages codes are at https://cloud.google.com/translate/docs/languages !\n Command syntax: \`${prefix}translate\` or \`${prefix}t\` [text] [language code]`);
const text1 = text.substring(0, text.length - 2)
const target = text.substring(text.length - 2, text.length) || languages
translate
.translate(text1, target)
.then(results => {
const translation = results[0];
msg.channel.send(`Translation: ${translation}`).then(sentText => {
sentText.react(`๐`);
const filter = (reaction, user) => {
return ['๐'].includes(reaction.emoji.name);
};
sentText.awaitReactions(filter, { max: 2, time: 5000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.name === '๐' && sentText.react.me === false) {
const target = `en`
translate
.translate(text1, target)
.then(results => {
const translation = results[0];
msg.channel.send(`Translation: ${translation}`);
})
.catch(err => {
console.log(err);
})
}
})
})
})
//code for command continues below this line, but it is irrelevant to what I'm trying to achieve
Expected result: Bot re-translates back to English if a user reacts with the provided reaction, and only once.
Actual result: Bot does nothing, or, if I remove the && sentText.react.me === false, the bot re-translates back to English because it's detecting its own reaction.
Any help would be appreciated!
In your filter, you can check to make sure the user isn't the client, like so...
const filter = (reaction, user) => reaction.emoji.name === '๐' && user.id !== client.user.id;
That way, only reactions that are not added by the client are collected.
You'll have to change your max option in the collector to 1, since the client's own reaction won't be collected. You can also remove the if statement comparing reaction.emoji.name.