Discord Bot, having trouble with RichEmbeds & awaitMessages - javascript

I don't know much Javascript, so please bear with me.
So, I'm trying to make a command for my Discord Bot. Basically, what I want to happen is, when you post "!records", I want the Bot to send a RichEmbed with the 2 options you can choose.
if (message.content.startsWith(config.prefix + 'records')) {
const embed = new Discord.RichEmbed()
.setTitle('D E I C I D E Records')
.setAuthor('D E I C I D E', 'https://cdn.discordapp.com/attachments/430238345826664448/430504575502385154/logo.png')
.setColor(3447003)
.setDescription('Please select an option.')
.setTimestamp()
.addField('1. Raid Wins', 'Respond with "1" for Raid Wins.')
.addField('2. Defense Wins', 'Respond with "2" for Defense Wins.')
message.channel.send({embed})
I have that part nailed. It does exactly what I want there. It sends the RichEmbed with the two options.
What I want to happen next is, when you send either "1", or "2", I want the Bot to reply with the correct records. This is part I can't get right. Here's all the code together:
if (message.content.startsWith(config.prefix + 'records')) {
const embed = new Discord.RichEmbed()
.setTitle('D E I C I D E Records')
.setAuthor('D E I C I D E', 'https://cdn.discordapp.com/attachments/430238345826664448/430504575502385154/logo.png')
.setColor(3447003)
.setDescription('Please select an option.')
.setTimestamp()
.addField('1. Raid Wins', 'Respond with "1" for Raid Wins.')
.addField('2. Defense Wins', 'Respond with "2" for Defense Wins.')
message.channel.send({embed})
message.channel.awaitMessages(response => response.content === '1', {
max: 1,
time: 10000,
errors: ['Ran out of time!'],
})
message.channel.send(drecords.RaidWins)
message.channel.awaitMessages(response => response.content === '2', {
max: 1,
time: 10000,
errors: ['Ran out of time!']
})
message.channel.send(drecords.DefenseWins)
} else
At the moment, when you post "!records", it sends the RichEmbed, but also sends the records, instead of waiting for a reply.
Can someone outline what I'm doing wrong here please?
Also, I would like to be able to say a single command to update the records without having to go into the Bot's files and do it manually.
if (message.content.startsWith(config.prefix + 'updateraids')) {
let newRecords = message.content.split(" ").slice(1, 2)[0];
drecords.RaidWins = newRecords;
fs.writeFile('./drecords.json', JSON.stringify(drecords), (err) => console.error);
} else
if (message.content.startsWith(config.prefix + 'updatedefenses')) {
let newRecords = message.content.split(" ").slice(1, 2)[1];
drecords.DefenseWins = newRecords;
fs.writeFile('./drecords.json', JSON.stringify(drecords), (err) => console.error);
}
At the moment, when you say either one of those commands and then some text after, so for example, "!updatedefenses DefenseWin2", it replaces the first string (DefenseWin1) instead of adding another in the Bot's files. And how would I go about removing an entry instead of adding one? Sorry if there's a bit too much here, wanted to squeeze it all into one post as it's all related.
I have done quite a few hours of research, going through other Stackoverflow questions, going through Discord.js, and the An Idiot's Guide YouTube tutorials but no luck.
Any help here would be really appreciated.

You aren't using awaitMessages correctly. You only need one, not 2 or more for your case. The filter will check if the message is either a 1 or 2. Here's what your code should look like. I also fixed your "time up" error handler.
client.on("message", message => {
if (message.content.startsWith("/records")) {
const embed = new Discord.RichEmbed()
.setTitle('D E I C I D E Records')
.setAuthor('D E I C I D E', 'https://cdn.discordapp.com/attachments/430238345826664448/430504575502385154/logo.png')
.setColor(3447003)
.setDescription('Please select an option.')
.setTimestamp()
.addField('1. Raid Wins', 'Respond with "1" for Raid Wins.')
.addField('2. Defense Wins', 'Respond with "2" for Defense Wins.');
message.channel.send({embed})
message.channel.awaitMessages(response => (response.content === '1' || response.content === "2"), {
max: 1,
time: 10000,
errors: ['time']
}).then(mg => {
if (mg.first().content === "1"){ //Have to use .first() because mg is a Collection
message.channel.send(drecords.RaidWins);
}else if (mg.first().content === "2"){
message.channel.send(drecords.DefenseWins);
}
}).catch((err) => {
message.channel.send("Ran out of time!");
})
}
})
As for your second question, when you use .writeFile , you're essentially overwriting the file. You'll want to use appendFile. However, you're using JSON. You can simply import the file (require it) and update it. Might I suggest you change the json file to look like this if this is what you're going for.
{
"RaidWins": 0,
"DefenseWins": 0
}
And then importing and updating would look like this
let records = require("./drecords.json");
records.RaidWins += 1; //adding one to the wins
fs.writeFile("./drecords.json", JSON.Stringify(records), err => console.error);

If you look at the example in the awaitMessages section of the docs it appears you need to put the part of your code that sends the response in a .then.
Something like
message.channel.awaitMessages(response => response.content === '1', {
max: 1,
time: 10000,
errors: ['Ran out of time!'],
})
.then(message.channel.send(drecords.RaidWins));
message.channel.awaitMessages(response => response.content === '2', {
max: 1,
time: 10000,
errors: ['Ran out of time!']
})
.then(message.channel.send(drecords.DefenseWins));
As for the file issue, could you elaborate more on the format of the files and what the commands would look like?

Related

How to .get() from Firebase to integrate in Discord.JS

I'm a new JavaScript programmer facing a problem that I can't seem to solve. I'm trying to save data in a Cloud Firestore Database using Firebase and trying to save and take data from the database. I've successfully created saving data as per this code below:
db.collection("data").doc(message.author.id).set({
"userID": message.author.id,
"userName": message.author.tag,
"userWallet": 500,
"userItems": {
"DogeCoin": 0,
"TrollCoin": 0,
"TrollTrophy": 0
},
"lastClaim": 0,
"lastCrime": 0
}).then(() => {
message.channel.send(`${message.author.tag}, you have successfully created your account.`)
})
While the saving part works the getting data part doesn't, I've tried a few methods but it still doesn't work. Right now, this is what I've worked on.
let wallet;
let bank;
db.collection("data").doc(message.author.id).get().then((q) => {
if (q.exists){
wallet = q.data().userWallet;
} else if(!q.exists){
message.channel.send(`${message.author.tag}, please go create an account.`)
return;
}
})
let embed = new Discord.MessageEmbed()
.setTitle(`Balance for ${message.author.tag}`)
.setAuthor(`${client.user.tag}`)
.setColor("RANDOM")
.setDescription(`Created by ${client.user.tag}`)
.addFields(
{name: "Bank", value: `${wallet}`}
)
.setImage("https://c.tenor.com/iQ7AzP7EgSAAAAAM/noice.gif")
message.reply({embeds: [embed]})
return;
I want to able to get the data from Firebase and use it in my code by showing it in an embed. Your help in sincerely appreciated. Thank you.

Discord Bot won't run pass certain point in my if statement | Javascript

I can't figure out why my code doesn't run anything past the first
if statement.
I can make it run completely if I predefine the time
variable.
Although I'm not sure when I try to take the user input,
it won't continue.
I don't code much in JavaScript so I'm probably missing something
obvious. All help is appreciated.
if (msg.content === "$set") {
time = msg.content.split("$set ")[1]
if(!time)return msg.reply("how many minutes / hours will you set the alarm")
// Nothing runs past here unless I predefine the time variable
const exampleEmbed = new Discord.MessageEmbed()
.setColor('#26aaff')
.setTitle('Custom Alert Set')
.setAuthor('Temp', 'https://i.imgur.com/XX6I7Hj.jpeg', 'https://imgur.com/')
.setDescription(`Time: ${time}`)
.setThumbnail('https://i.imgur.com/XX6I7Hj.jpeg')
.addFields(
{ name: 'Regular field title', value: 'Some value here' },
{ name: '\u200B', value: '\u200B' },
)
.setTimestamp()
.setFooter('Built by', 'https://i.imgur.com/XX6I7Hj.jpeg');
msg.channel.send(exampleEmbed)
}
First of all you should use startsWith command for checking if the msg.content starts with $set. Then, the split command should have a valid parameter, so, here you can use a space " ".
if (msg.content.startsWith("$set")) {
time = msg.content.split(" ")[1]
if(!time) return msg.reply("how many minutes / hours will you set the alarm");
const exampleEmbed = new Discord.MessageEmbed()
.setColor('#26aaff')
.setTitle('Custom Alert Set')
.setAuthor('Temp', 'https://i.imgur.com/XX6I7Hj.jpeg', 'https://imgur.com/')
.setDescription(`Time: ${time}`)
.setThumbnail('https://i.imgur.com/XX6I7Hj.jpeg')
.addFields(
{ name: 'Regular field title', value: 'Some value here' },
{ name: '\u200B', value: '\u200B' },
)
.setTimestamp()
.setFooter('Built by', 'https://i.imgur.com/XX6I7Hj.jpeg');
msg.channel.send(exampleEmbed);
}
Tell me if this works!
Happy coding!
It looks like you're checking if msg.content is exactly "$set"
I think you want to be checking if msg.content contains "$set"
So try changing if (msg.content === "$set") to if (msg.content.startsWith("$set"))

If bot gets pinged

I'm trying to make my bot send a DM to the message author if the message contains the bot's mention in the message, but every time it sends a message, the message author gets a DM, instead of only getting a DM if it contains the bot's mention.
Here's my code.
if (msg.content.includes === '<#!751281320122122311>' || '<#751281320122122311>') {
msg.author.send({
embed: {
color: 3447003,
title: "Hey",
description: "Just because I'm a bot, doesn't mean I don't get annoyed when you ping me.",
}
});
}
Can anyone help?
I think this should work if you just want to check if the message contains that string or not.
if (
msg.content.includes("<#!751281320122122311>") ||
msg.content.includes("<#751281320122122311>")
) {
msg.author.send({
embed: {
color: 3447003,
title: "Hey",
description:
"Just because I'm a bot, doesn't mean I don't get annoyed when you ping me.",
},
});
}
See this for more details about the Array.prototype.includes() function.
As written, your if condition will always be true.
if (msg.content.includes === '<#!751281320122122311>' || '<#751281320122122311>') {
That says "If msg.content.includes equals '<#!751281320122122311>', or if the string value '<#751281320122122311>' is truthy, then do this thing." The string literal will always be truthy.
You probably want something more like this:
if (msg.content.includes === '<#!751281320122122311>' || msg.content.includes === '<#751281320122122311>') {
But even that is probably wrong. msg.content is likely a string or an array or something else that has an includes function that you mean to be calling. If so, you want this:
if (msg.content.includes('<#!751281320122122311>') || msg.content.includes('<#751281320122122311>')) {
this should work
if (message.mentions.has(client.user) && !message.mentions.has(message.guild.id))
{
message.author.send({
embed: {
color: 3447003,
title: "Hey",
description: "Just because I'm a bot, doesn't mean I don't get annoyed when you ping me.",
}
});
}

Ask the user questions, then user it in a discord.js embed

I want to make it so a moderator does !Host then the bot does
What time do you want it to start?
User Response 17:00 CET
Bot then does What Gamemode
User Response Normal 2v2 or something like that
Bot Response Who do you want to host
User Response #NaP
Bot Response Bot then replaces the values below
if (m == '.nap tournament' || m == '.tournament info' || m == '.nap t' || m == '.nap tourny' || m == '.ti') {
message.channel.send({
embed: {
color: 000000,
author: {
name: bot.user.username,
icon_url: bot.user.avatarURL
},
title: "**Nap Weekly Tournament**",
description: "Every Week We Have A Tournament For All The Nappies!!!",
fields: [{
name: "**Time**",
value: "Saterdays at 17:00 CET or 5:00 pm CET."
},
{
name: "**Gamemode**",
value: "Normal 2v2"
},
{
name: "**Tournament Host**",
value: "<#!" + 'Whoister#7002' +
">"
}
],
timestamp: new Date(),
footer: {
icon_url: bot.user.avatarURL,
text: "Arrara bot"
}
}
});
I'd recommend using the RichEmbed class built into discord.js as it looks cleaner and it's quite easy to use as well, here's an example:
const embed = new Discord.RichEmbed()
.setTitle("This is your title, it can hold 256 characters")
.setAuthor("Author Name", "https://i.imgur.com/lm8s41J.png")
.setColor(0x00AE86)
.setDescription("Embed description here")
message.channel.send({embed});
Here is the link to see the other things you can add to the embed: https://discord.js.org/#/docs/main/stable/class/RichEmbed
Then for dealing with a user response like you want to, I'd use a message collector, https://discord.js.org/#/docs/main/stable/class/TextChannel?scrollTo=createMessageCollector
You can find an example there as well, you can set the filter to a user ID, for example const filter = m => m.author.id === message.author.id. You can also use maxMatches to set the maximum number of messages are collected before the end event is emitted. channel.createMessageCollector(filter, { maxMatches: 2 }); //Will collect 2 messages and then emit 'end' event. The other event that is emitted is collect which is emitted everytime a response comes back matching your filter, and to get the content of that response you could use something such as collector.on('collect', m => console.log("Collected:" + m.content));. You can create multiple collectors and send a message in between to prompt the user first and then get their input.

Specify a private message to have limited answers discord.js

I have a bot asking a question to a user via private message. I would simply like the bot to only accept certain words as answers.
For example, asking a user which gender they are. I would like the options to be "Male", "Female" and "Other". If the bot receives something other than those answers, I would also like it to say "Please enter "Male", "Female" or "Other". I have tried a couple different things that don't seem to work. The code works, outside of the line I am messing with, but will accept "cat", for example, as a gender, so I obviously want it to only accept a few answers. Not sure if the if statement to specify this would work. I know how that works by itself, but in combo with await, I am confused...
Here's the code for what I last tried, with no avail (not to mention it gives a syntax error/unexpected token due to the line I was messing with)
module.exports.run = async (bot, message, args) => {
message.author.send(`THIRD QUESTION, **What is the gender of your Brawler or Character?** Please enter "Male", "Female" or "Other".`)
.then((newmsg) => { //Now newmsg is the message you send to the bot
newmsg.channel.awaitMessages(response => response.content.includes("Male", "Female", "Other") {
max: 1,
time: 300000,
errors: ['time'],
}).then((collected) => {
newmsg.channel.send(`Your brawler's gender is: **${collected.first().content}**
If you are okay with this gender, type !profilerace to continue the profile creation process!
If you would like to edit your gender, please type !profilegender`)
con.query(`UPDATE profile SET gender = '${collected.first().content}' WHERE id = ${message.author.id}`);
console.log("1 record updated!")
}).catch(() => {
newmsg.channel.send('Please submit an age for your character. To restart Profile creation, please type "!profilecreate" command in Profile Creation channel on the server.');
});
//con.query(sql, console.log);
//if (err) throw err;
//console.log("1 record inserted!")
});
}
EDIT: After getting some help in the comments below, I have resulted in something like this. I keep getting syntax errors though. I feel like I have no idea what I'm doing here. lmao
module.exports.run = async (bot, message, args) => {
message.author.send(`THIRD QUESTION, **What is the gender of your Brawler or Character?** Please enter "Male", "Female" or "Other".`)
.then((newmsg) => { //Now newmsg is the message you send to the bot
newmsg.channel.awaitMessages(response => response.content, {
max: 1,
time: 300000,
errors: ['time'],
})
.then((collected) => {
if (response.content === "Male" || response.content === "Female"|| response.content === "Other") {
return
newmsg.channel.send(`Your brawler's gender is: **${collected.first().content}**
If you are okay with this gender, type !profilerace to continue the profile creation process!
If you would like to edit your gender, please type !profilegender`)
con.query(`UPDATE profile SET gender = '${collected.first().content}' WHERE id = ${message.author.id}`);
console.log("1 record updated!")}
} else {
newmsg.channel.send("Please submit 'Male', 'Female' or 'Other'. Type !profilegender to restart the choice of gender.")
}
}).catch(() => {
newmsg.channel.send('Please submit an age for your character. To restart Profile creation, please type "!profilecreate" command in Profile Creation channel on the server.');
});
});
}
Thanks for the help!
I am not sure exactly what you mean but I would create an ArrayList and check if the content of the message matches with one of the values in the ArrayList as shown below:
const genders = ["male", "female", "other"];
if (genders.indexOf(response.content) > -1) {
// code if person chose one of the three options.
} else {
// code here if person did not choose one of the three options and put something else.
}

Categories

Resources