How do I use readline for Discord Bots? - javascript

While trying to make my Discord Bot I ran into yet another problem. I'm trying to have a way to have the owner have the bot say something in the announcement section for me so it doesn't show up as my name.
I've tried the readline interface (though I don't know if I did it correctly) and I've tried to do different ways of making a variable (const, var).
if(message.member.roles.find(r => r.name === "Owner")){
return message.reply("What would you like to say?")
const dm = message.content;
return message.reply("$dm")
I want the bot to respond with whatever I say. So, If I put in The Server Is Going Down Soon! then the bot should say that back to me (in this case).

When you call return you're ending the execution of the function that you're writing.
In this case,
if(message.member.roles.find(r => r.name === "Owner")){
return message.reply("What would you like to say?") // the current function stops
const dm = message.content; // this line never executes
return message.reply("$dm")
You will have to wait for the response from the user who I presume is responding to a command of some sort
if (message.member.roles.find(r => r.name === "Owner")) {
await message.reply("What would you like to say?"); // Send the request
// Wait for the person who sent the original message to send another message
let userMessages = await message.channel
.awaitMessages(m => m.id === message.member.id, { max: 1 });
let userMessage = userMessages.first()
// Reply with the message they sent
return message.member.reply(userMessage.content);

Related

Discord.JS Message Edit

I want to edit the message over and over again.
So I made variable
this.msgRef = await channel.send({ embeds: [embedMessage] });
If I want to edit I use
this.msgRef.edit(...)
If the bot for some reason disconnects, he will lose msgReference.
Because of that, I saved it to DB.
How to create a message again because Message (object) in Discord.JS have a private constructor?
If you want to get the message again, you can simply fetch the channel's messages every time you bot connects (on the ready event for example) like so
client.on('ready', () =>{
const messages = await channel.messages.fetch()
client.msgRef = messages.find(msg => msg.author.id === client.user.id
&& msg.embeds[0]
// Etc.. Add as many conditions to make sure you choose the right message
);
})
This way, use client.msgRef.edit(...) whenever you want.

Message collecter spams messages, and wont start in the correct channel

So, I have been making a message collector that gets activated when "grimm!record" is sent, I have been working on this piece of code for hours, but yet the code seems to keep getting more broken.
This was the code before I started working on it
client.on('message', message => {
if (message.content === 'grimm!record') {
const filter = m => true;
const collector = message.channel.createMessageCollector(filter);
message.channel.send(Start)
const log = message.guild.channels.cache.find(ch => ch.name === 'recording-log');
collector.on('collect', collectedMessage=>{
log.send(`${message.author.username} - ${collectedMessage.content}`)
if(collectedMessage.content === "grimm!record-stop"){
collector.stop();
}
});
}})
and this is the code after I made edits, If grimm!record was sent in the channel called recording-log, the bot would send a message saying "I can't record the recording log!" and it would exit out of the collector
client.on('message', message => {
if (message.content === 'grimm!record') {
const channelID = message.guild.channels.cache.find(channel => channel.name === "recording-log").id;
if (message.channel.id === channelID)
message.channel.send('I cant record in the Recording Log!')
return;
} else {
message.channel.send(Start)
const filter = m => true;
const collector = message.channel.createMessageCollector(filter);
const log = message.guild.channels.cache.find(ch => ch.name === 'recording-log');
collector.on('collect', collectedMessage=>{
log.send(`${message.author.username} - ${collectedMessage.content}`)
if(collectedMessage.content === "grimm!record-stop"){
collector.stop();
}
});
}})
Once I made these edits, I would send grimm!record in a different channel, it does not start the collector, or even send the "Start" embed, and the collector does start as well, when I sent grimm!record in the recording-log, I got a message saying that the bot cant record the recording log, but it still starts the collector, while spamming the "Start" embed in the channel. I have been working on this for hours, I've been looking all over the internet for help, but yet I still have no clue on what I've been doing wrong, could someone tell me what's wrong with the 2nd piece of code I sent? Thanks!
EDIT - so it turns out, that anytime I use a command with my bot, or if someone says a word that is in my bots swear list, it starts the collector, and starts the message spam, so I have no clue on why that happens, so if someone could help explain that, I would appreciate that too, thanks!
Changing this line should theoretically solve your issue:
const filter = m => true;
As I stated in my comment, there is a purpose to the filter, it should not simply return true. The filter is responsible for "filtering" out the messages you do not want collected. Only messages that match the conditions of the filter will be collected. In your example, there is no filter, so any message sent by anyone will be collected by the collector, including messages sent by the bot itself. Since your bot sends a new message whenever a message is collected, this results in an infinite loop of spam.
Try changing it to this:
const filter = m => m.author.id == message.author.id;
This will ensure that the collector only collects messages sent by the user that used the command.
Alternatively, if you want to record the messages of everyone that sends a message (except your bot), try changing it to this:
const filter = m => m.author.id != message.client.user.id;
This will solve at least the spam portion of your problem.
The other problem simply appears to be an incorrect placement of your else statement. If you look at your second example, the else should come after if (message.channel.id === channelID), but instead comes after the initial if statement if (message.content === 'grimm!record').

DISCORD.JS How to get a specific channel ID by name?

Fairly newbie question, but my overall goal is to have a dedicated log channel the bot sends messages too. So it would be something like this
log = logstuff;
channel = [WAY OF GETTING CHANNEL ID BY NAME]
client.channels.get(channel).send(log)
All inside an async fucntion bc im using Commando.
The other answer will work but you can shorten it down a lot by doing the following:
let log = "Your Stuff";
message.guild.channels.find('name', 'channel-name').send(log)
Solving this means you just have to search the message.guild for your channel, then send your log;
let targetChannelName = "MY_SAMPLE_CHANNEL_NAME";
let log = "test payload";
try {
await message.guild.channels.find(channel => channel.name === targetChannelName && channel.type === "text").send(log)
} catch {console.log} // log any errors
When you pass a message to this snippet, it searches through the message.guild's channel collection, for a channel with the name value of targetChannelName and is a textChannel. When it finds the target channel, it sends the log content.

Check for the message before the last

I am trying to make my bot delete a specific number of messages, I think an if would be best for the case, but I don't know how to do this...
This is how it's supposed to work: There's a message from my bot in the channel, it's always the last one in the chat. My bot will check if the message is actually there, if it is, it will delete the message, along with the command, and then send a new message. If the message is not there, it will just delete the command and send the new message.
Here's my code for reference:
if(/* message is there */) const fetched = await message.channel.fetchMessages({limit: 2});
else const fetched = await message.channel.fetchMessages({limit: 1});
// Deletes stuff
message.channel.bulkDelete(fetched)
.catch(error => message.reply(`There was an error: ${error}`));
message.channel.send("```Open```");
How can I check if that previous message is there?
I would check if the author of the last message is your bot:
let lastTwo = await message.channel.fetchMessages({limit: 2}), // Get the last 2 messages
last = lastTwo.last(); // The last in the collection will be the last message
if (last.author.id == client.user.id) await message.channel.bulkDelete(lastTwo);
else await last.delete();
message.channel.send("```Open```");

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