Discord JS Message Leveling System - discord.js

I'm making a level system for my discord bot, I want it so if I reach level 5, it will give me a role. I want it to be so when you reach a certain level you will be given a role.
I pasted the code for the message leveling system I am using.
bot.on("message", async message => {
let xpAdd = Math.floor(Math.random() * 7) + 8;
if(!xp[message.author.id]) {
xp[message.author.id] = {
xp: 0,
level: 1
}
}
if(xp[message.author.id].level[5]) //idk if im doing this right, I want it so if level reaches a certain number, it will give out a role
{
console.log("skrt");
}
let curxp = xp[message.author.id].xp;
let curlvl = xp[message.author.id].level;
let nxtlvl = xp[message.author.id].level * 300;
let rankuplvl = xp[message.author.id].xp * 7;
xp[message.author.id].xp = curxp + xpAdd;
if(nxtlvl <= xp[message.author.id].xp) {
xp[message.author.id].level = curlvl + 1;
const lvlUp = new Discord.RichEmbed()
.setTitle("You leveled up!")
.setColor("#FFC0CB")
.addField("NEW LEVEL", curlvl + 1);
message.channel.send(lvlUp);
}
fs.writeFile("./xp.json", JSON.stringify(xp), (err) => {
if(err) console.log(error)
});
if(message.content.startsWith(prefix + "level")) {
message.channel.bulkDelete(1)
if(!xp[message.author.id]){
xp[message.author.id] = {
xp: 0,
level: 1
};
}
let curxp = xp[message.author.id].xp;
let curlvl = xp[message.author.id].level;
let nxtlvl = curlvl * 300;
let difference = nxtlvl - curxp;
const lvlEmbed = new Discord.RichEmbed()
.setAuthor(message.author.username)
.setColor("#FFC0CB")
.addField("XP", curxp, true)
.addField("Level", curlvl, true)
.setFooter(`${difference} XP until next rank!`, message.author.displayAvatarURL);
message.channel.send(lvlEmbed)
}
});

Let's break down what we need to do in order to reach your desired behavior. Assuming you're using the stable branch (most likely)...
Check if the user's level is 5.
Equality operator
Retrieve the desired role.
Guild.roles
By ID: Map.get() or use the ID as the RoleResolvable in #3.
By property: Collection.find()
Add a role to the user.
GuildMember.addRole()
Now, let's put it all together and implement it into your code.
if(nxtlvl <= xp[message.author.id].xp) {
xp[message.author.id].level = curlvl + 1;
// Check if the user's level is 5.
if (xp[message.author.id].level === 5) {
// Retrieve the desired role. Uncomment whichever line you need, as described.
// const role = message.guild.roles.get('idHere');
// const role = message.guild.roles.find(role => role.name === 'Level 5');
message.member.addRole(role) // Or simply use the role ID directly.
.catch(console.error); // Make sure to catch any rejected promises.
}
// Continue with your level-up embed.
}

Related

Firebase's onValue only get data once and does not update when placed inside a loop in React's useEffect

My goal is to get multiple data based on a list of data the customer requested so I put the codes inside useEffect. If the array contains the list of things the customer wants, then it grab those data from the server so the user can manipulate it. So far, it works fine but when the database updates, onValue is not triggered to grab the new data to update the render.
Here is my code. Thank you for helping me in advance.
// Getting data
useEffect(() => {
if (empDataArr.length > 1) {
let fromDay = parseInt(dateHandler(startDate).dateStamp);
let toDay = parseInt(dateHandler(endDate).dateStamp);
let tempLogArr = [];
empDataArr.forEach((emp) => {
let qLogEvent = query(child(shopRef(shopId), emp.id + "/log_events"), orderByChild("dateStamp"), startAt(fromDay), endAt(toDay));
// This is the part I need help
onValue(qLogEvent, (snap) => {
let logEventArr = [];
let val = snap.val();
if (val === null) {
} else {
Object.keys(val).forEach((key) => {
let id = key;
let dateStamp = val[key].dateStamp;
let direction = val[key].direction;
let time = val[key].timeStamp + "";
let timeStamp = time.substring(8, 10) + ":" + time.substring(10, 12);
logEventArr.push({ direction: direction, timeStamp: timeStamp, dateStamp: dateStamp, id: id });
});
tempLogArr.push({
id: emp.id,
logEvent: logEventArr,
});
}
});
});
setLogDataArr(tempLogArr.map((x) => x));
}
}, [empDataArr, shopId, startDate, endDate]);
useEffect(() => {
console.log(logDataArr);
}, [logDataArr]);
I have tried using return onValue() and const logData = onValue() but they do not work (and I do not expect the former one to work either).

How to check if user already sent message in channel?

I would like to block a user who want to send another message in a specific channel :
client.on("message", async message => {
if ((message.content === config.RUN) && message.member.roles.cache.has(config.ROLE_ID)) {
if (message.channel.type === 'DM') return;
let filter = m => !m.author.bot;
let destination = client.channels.cache.get(config.CHANNEL_ID);
message.author.createDM().then(dmchannel => {
dmchannel.send(textDM.FIRST_DM);
const collector = new discord.MessageCollector(dmchannel, filter);
collector.on('collect', (m, col) => {
console.log(m.content);
if (m.content.startsWith("ok")) { // here condition if user already sent msg
// Do something
}
You can use a variable to count the quantity of the message sent by the user. If it reaches 2, you can execute your desired code.
To use this for specific user, do:
var messageAmount = {}
var amount = 0
if (message.content.startsWith("ok")) {
const user = message.author.id
if(messageAmount[`${user}`] === 1) { // is 1 because it checks for 2 after it has been assigned, if(messageAmount = x-1)
// Do something
message.channel.send("You cannot say that again until (...) finishes")
// then reset it
messageAmount[`${user}`] = 0
amount = 0
} else {
++amount
messageAmount[`${user}`] = amount
}
}
To use this globally:
var messageAmount = 0
if (m.content.startsWith("ok")) {
++messageAmount
if(messageAmount === 2) {
// Do something
}
}

How can I embed the bot's reply? discord.js

I made a "funnyrate" command that is working perfectly fine. However I think it would look better if the bot's reply is embedded. may someone help me make the bots reply embedded? here is the code:
module.exports.run = async (bot, message, args) => {
var rating = Math.floor(Math.random() * 100) + 1;
var mentionedMember = message.mentions.members.first();
if (!mentionedMember) return message.reply(`according to my calculations, you are ${rating}% funny😂`);
return message.channel.send(`${mentionedMember}, according to my calculations, you are ${rating}% funny😂`);
}
module.exports.help = {
name:"funnyrate"
}
firstly if you don't know how to make embeds,you should visit: https://discord.js.org/#/docs/main/stable/class/MessageEmbed?scrollTo=setTitlelink.
This is a link to the discord.js embed documentation page.
I haven't tried it but this should work:
Have a good day!
module.exports.run = async (bot, message, args) => {
var rating = Math.floor(Math.random() * 100) + 1;
if (!args.length) {
const embed = new MessageEmbed()
.setColor("RANDOM")
.setDescription(`according to my calculations, you are ${rating}% funny😂`)
return message.channel.send(embed);
} else {
const embed = new MessageEmbed()
.setColor("RANDOM")
.setDescription(`${mentionedMember}, according to my calculations, you are ${rating}% funny😂`)
return message.channel.send(embed);
}}
module.exports.help = {
name:"funnyrate"
}

Discord.js XP System, adding roles as members level up

So I found some easy understanding XP system and I just wanted to edit this and add a feature such as adding roles on level up. Currently, nothing happens. I've tried moving few things here and there, which either ended up spamming a channel with level up embeds, or simply nothing. I get no errors.
Thanks in advance!
Code below:
// Further up are the level roles defined, etc but that's not relevant.
if (message.author.bot) return;
let xpAdd = Math.floor(Math.random() * 7) + 8;
if (!xp[message.author.id]) {
xp[message.author.id] = {
xp: 0,
level: 1
};
}
let curxp = xp[message.author.id].xp;
let curlvl = xp[message.author.id].level;
let nxtLvl = xp[message.author.id].level * 500;
xp[message.author.id].xp = curxp + xpAdd;
let lvlupRoles = new Discord.RichEmbed()
.setAuthor("Level Up!", message.author.displayAvatarURL)
.setThumbnail("https://cdn.discordapp.com/attachments/682717976771821646/705125856455950496/Levelup.png")
.setColor("RANDOM")
.setDescription(`Level: ${curlvl + 1}\nXP: ${curxp}`);
if (nxtLvl <= xp[message.author.id].xp) {
xp[message.author.id].level = curlvl + 1;
let lvlup = new Discord.RichEmbed()
.setAuthor("Level Up!", message.author.displayAvatarURL) .setThumbnail("https://cdn.discordapp.com/attachments/682717976771821646/705125856455950496/Levelup.png")
.setColor("#00703C")
.setDescription(`Level: ${curlvl + 1}\nXP: ${curxp}`);
message.channel.send(lvlup).then(message => {message.delete(10000)});
if (curlvl === "10") {
lvlupRoles.addField("Roles gained", `${Level10Role.toString()}`, true)
let addrankup = message.member;
addrankup.addRole(Level10Role.id).catch(console.error);
message.channel.send(lvlupRoles).catch(e => console.log(e))
}
if (curlvl === "20") {
lvlupRoles.addField("Roles gained", `${Level20Role.toString()}`, true)
let addrankup = message.member;
addrankup.addRole(Level20Role.id).catch(console.error);
message.channel.send(lvlupRoles).catch(e => console.log(e))
}
// ETC . . .
}
fs.writeFile("./storage/xp.json", JSON.stringify(xp), (err) => {
if (err) console.log(err)
});
I think this may be due to you storing xp[message.author.id].level in curlvl, modifying xp[message.author.id].level and still using curlvl. In JS, only objects ({}, arrays, functions etc) are passed by reference so curlvl won't be updated when xp[message.author.id].level is as it is a number.
Add this under xp[message.author.id].level = curlvl + 1;:
curlvl = xp[message.author.id].level;

How to get the specific discord bot channel with channelid?

My bot returns undefined when using bot.channels.get(channelid).
Here's a sample of my code:
//this is executed in a guild with id 416809320513011713
const Discordjs = require("discord.js");
const bot = new Discordjs.Client();
const auth = require('./auth.json');
const FileSys = require("fs");
bot.on('messageDelete', async function (message) {
console.log('message deleted')
let currentguildsettings = JSON.parse(FileSys.readFileSync('./DatStore/GuildDat/' + message.guild.id + '.dat', 'UTF8'));
if (currentguildsettings[0] == 1) {
if (currentguildsettings[1] != 0) {
let channelid = currentguildsettings[1].toString()
let channel = bot.channels.get(channelid);
console.log('settings on true, channelid ' + channelid)
if (channel) {
console.log('channel found')
}
}
}
}
bot.login(auth.token)
file ./DatStore/GuildDat/416809320513011713.dat contains:
[1,424085503361417200,0]
Here's the output:
message deleted
settings on true, channelid 424085503361417200
If the channel was found it should've logged 'channel found' in the output.
What should I change to make it return the channel?
The channel id key is a string, you must enclose it as a string in your array.
let c1 = bot.channels.get(424085503361417200); // Will produce undefined
let c2 = bot.channels.get('424085503361417200'); // Will produce a channel object (if available)
The channel wasn't available since I used the wrong id:
I saved the id's at my server settings command in int format instead of string, parseInt() broke the exact number.
if (logchannelaction == 'set') {
if (currentguildsettings[1] == message.channel.id) return message.reply("logchannel was already set to this channel");
currentguildsettings[1] = parseInt(message.channel.id);
message.reply("logchannel has set to #" + message.channel.name);
if (currentguildsettings[0] == 0) {
currentguildsettings[0] = 1
message.reply("logchannel has automatically enabled");
}
FileSys.writeFileSync(guilddatpath, JSON.stringify(currentguildsettings));
return
}
Thank you for trying to help me.

Resources