How do i store data seperately for each member - discord.js

So , I wanna make a discord bot which calculates our study time and adda the study time
And makes a leaderboard out of it and some more things , but my problem here is that I want it to store seperate data for each member
For example :
If I type login it should start a stopwatch and when I type logout it should store the time I studied and same goes for the other members
Please help me with this , I gotta make it as soon as possible
Thank you

With the limited information you provided I assume something like this could be viable:
let userStartTimes = [];
//...
if(command == "login") {
// only add element if it doesnt exist already
if(!userStartTimes.some(el => el.id == message.author.id)) {
userStartTimes.add({id: message.author.id, time: Date.now()});
}
}
if(command == "logout") {
let index = userStarTimes.findIndex(el => el.id == message.author.id);
// check if user has logged in before
if(index != -1) {
let msecSpent = Date.now() - userStartTimes[index].time;
// add to leaderboard
}
}

Related

Store textbox input to an array

I want to store all the input data of the textbox to an array with unique index number each so I can control them. The problem is that it only assigns zero index for all of them.
todoField.addEventListener('keypress', function (b) {
if (b.key === 'Enter' && todoField.value != 0) {
let newtodo = todoField.value
task = [newtodo]
}
}
declear a function outside the addEventListener and push the new items to the function that will give them a unique id and store them too.
this is how you should do it.
tasks = []; // array decleartion
todoField.addEventListener('keypress', function (b) {
if (b.key === 'Enter' && todoField.value != 0) {
let newtodo = todoField.value
tasks.push(newtodo);
} }
Now tasks array will contain all your tasks.
thank you.

How do i keep taking inputs from multiple users until a specific user says a particular keyword (discord.js)?

So I've been trying to make an auction bot on discord. I've figured out how to handle a single item, but I'm having issues regarding bundles.
My goal - Let the user info any/all items when auctioning a bundle till he says the keyword 'done'. The bot stores the url of the first message (embed sent by the bot) and then does nothing till the user says done. The two users are 1. the user himself, 2. the bot who's item(s) he wants to auction.
I tried using the message collector but the bot straight up ignores it. After searching around on the web and trying to adapt to my situation, the closest thing i found is using async/await with awaitMessages while inside a for loop. After that failed too, i tried to use a chain of then() with the awaitMessages. Here's my code snippet. Any help is appreciated.
let flg =0
if(arguments[3] === 'bundle'){
message.channel.send('Say `done` when you have info-ed all your pokemons')
await message.channel.awaitMessages(m => m.author.id === '666956518511345684' || m.author.id === message.author.id, {time : 30000, errors : ['time']}).then(col1 => {
if (col1.first().author.id === '666956518511345684')
details.poke = col1.first().url
}).then(col2 => {
if (col2.first().author.id === message.author.id)
while(flg = 0){
if (col2.first().content.toLowerCase() === 'done')
flg = 1
}
})
Have the collector ignore bot messages, take multiple inputs and check for message content. Once time runs out, or the max input has been reached, the collection of messages will be returned.
if(arguments[3] === 'bundle'){
message.channel.send('Say `done` when you have info-ed all your pokemons')
const filter = m => {
return !m.user.bot && ['666956518511345684', message.author.id].includes(m.author.id) && m.content.toLowerCase() === 'done';
}
message.channel.awaitMessages(filter, {
// Take a max of 5 inputs for example
max: 5
time: 30000,
errors: ['time']
}).then(collected => {
// Your code
})
}
Documentation on TextChannel#awaitMessages()
I tried message collector once again and i made it work somehow. Here's how :
let i = 0
let filter = m => {m.author.id === '<Bot's id>' || m.author.id === message.author.id}
let collector = message.channel.createMessageCollector(filter, {time : 30000})
collector.on('collect', m => {
if (m.author.id === '<bot's id>' && i === 0){
details.poke = m.url
i = 1
}
if (m.author.id === message.author.id && m.content.toLowerCase() === 'done'){
collector.stop()
}
})
collector.on('end', col => { //code here })
The variable i is a flag, since i only want the url of the first message sent by the bot. It can be removed/more flags can be added up to your needs/requirements.
Lemme know if you need anymore help regarding this.

Read message sent after command start

I am trying to make a sort of trivia bot but the problem is that I can't get it working. I have it so that when you type "-quiz" it sends a embed with a random question. Now you might say that I need to make a separate JSON file and put the questions and answers there, the problem is, is that I need variables in those strings and when I tried it, it wouldn't work because the order or something like that. I tried to fix that but it seems like a bad solution anyway. I set it up so it looks for a message after the initial commands, problem is that it reads it's own embed and I honestly don't know how to make it skip bot messages
client.on('message', message =>{
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if(command === 'quiz'){
var TypeID = (Math.floor(Math.random() * 11))
var toLog = (Math.floor(Math.random() * 2))
{ //there is something here that is used for the variables above but it is super long
}
var question = [`Question one`, `Question two`]
var answers = [[Answer1_1, Answer1_2],[Answer1_1]]
if(toLog === 0){
const quizEmbed1 = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('quiz')
.setDescription(`${question[0]}`)
message.channel.send(quizEmbed1)
if(!message.content || message.author.bot) return;
if(message.content === [answers[0], answers[1], answers[2], answers[3], answers[4], answers[5]]){
message.channel.send('Good Job! That is right!')
}else{
message.channel.send('Oops! that is wrong.')
}
}else if(toLog == 1){
const quizEmbed2 = new Discord.MessageEmbed()
.setColor('#0099ff')
.setTitle('quiz')
.setDescription(`${question[1]}`)
message.channel.send(quizEmbed2)
if(!message.content || message.author.bot) return;
if(message.content === [answers[6]]){
message.channel.send('Good Job! That is right!')
}else{
message.channel.send('Oops! That is wrong.')
}
}
}
});
if something it wrong it is most likely because I changed it to make it smaller, I am fairly newer to coding in JavaScript
Try using a MessageCollector. There is a good guide on the discord.js guide
Or using awaitMessages. Again there is a guide on the discord.js guide
Here is the example using awaitMessages
const filter = response => {
return item.answers.some(answer => answer.toLowerCase() === response.content.toLowerCase());
};
message.channel.send(item.question).then(() => {
message.channel.awaitMessages(filter, { max: 1, time: 30000, errors: ['time'] })
.then(collected => {
message.channel.send(`${collected.first().author} got the correct answer!`);
})
.catch(collected => {
message.channel.send('Looks like nobody got the answer this time.');
});
});

Creating channel and setChannel troubles

I'm having trouble creating a discord bot, what it should do is detect whenever someone jkoins a specific voice Chat, and if a user does, the bot would have to create a new channel with, as the name, the nickname of the user who joined, then move that user to the new created channel and set that channel to private so no one can join.
Currently my problems are:
-I can't set the name of the new channel as the nickname of the user
-I can't move the user to that channel
-And I think the rest may work
Here is the part of my code:
client.on('voiceStateUpdate', (oldMember, newMember) => {
if(newMember.channelID != '693086073244483614') return;
const nick = newMember.nickname;
newMember.guild.channels.create('test', { type: 'voice' })
.then(() => {
newMember.setChannel('test');
console.log(`Hello from ${newMember.channel}!`);
const nChannel = newMember.channel;
nChannel.setParent('690292158636360032');
nChannel.overwritePermissions([
{
parent: '#690292158636360032',
id: '532236212967047169',
deny: ['CONNECT'],
},
]);
});
});
Any help would be appriciated, I'm new to both discord bots and javascript, so thanks a lot!
The Client#voiceStateUpdate event does not return a member, it returns a VoiceState. https://discord.js.org/#/docs/main/stable/class/Client?scrollTo=e-voiceStateUpdate
From the VoiceState, you can get a member with <VoiceState>.member.
So to fix your error, replace const nick = newMember.nickname to const nick = newMember.member.nickname.
client.on('voiceStateUpdate', (oldMember, newMember) => {
var oldUserChannel = oldMember.voiceChannel;
var newUserChannel = newMember.voiceChannel;
if(oldUserChannel === undefined && newUserChannel !== undefined) { //User joined the channel.
if(newMember.voiceChannel.id != '693086073244483614') return; //Check if the user join the right voice channel.
let nick = newMember.nickname;
if(nick == null){
nick = newMember.user.username; //If the member doesn't have a nickname.
}
newMember.guild.createChannel(nick, { type: 'voice' })
.then((nChannel) => {
console.log(`Hello from ${nChannel}!`);
nChannel.setParent('690292158636360032'); //Your category ID
nChannel.overwritePermissions(nChannel.guild.defaultRole.id, {
VIEW_CHANNEL: false
});
newMember.setVoiceChannel(nChannel)
});
} else if(newUserChannel === undefined){ //User left the channel.
if(oldMember.voiceChannel.parent == null) return;
if(oldMember.voiceChannel.parent.id != '690292158636360032') return; //Check if the voice channel is under the specified category.
if(oldMember.voiceChannel.members.first() == null){ //There is no more users in this channel.
oldMember.voiceChannel.delete(); //Delete the channel.
}
}
});
Here is the final result, fully working. I also add a system to automatically remove the channel if there is nobody in.
I have added some annotations, tell me if you have any questions.

Is there a way to toggle an event with command?

Is there any way to make an event toggleable with a command?
I'm trying to make a welcome/farewell event but I don't want it to be active on default.
This is how my event looks right now:
client.on("guildMemberAdd", (member) => {
const guild = member.guild;
let memberTag = member.user.tag;
guild.channels.sort(function(chan1, chan2) {
if (chan1.type !== `text`) return 1;
if (!chan1.permissionsFor(guild.me).has(`SEND_MESSAGES`)) return -1;
return chan1.position < chan2.position ? -1 : 1;
}).first().send(memberTag + " just joined <:floshed:533687801741443082>");
});
As requested here is an example of my comment:
One way to do it is to store a variable for a guild in some database which has a value of either true or false. Then you'd grab that variable and check if said guild has the option turned on or off
client.on("guildMemberAdd", (member) => {
const guild = member.guild;
let memberTag = member.user.tag;
// Code here to get the guild from database, this is just a non-working example
let dbGuild = database.get('Guild', guild.id);
// Check if the guild has the welcome command disabled
if (dbGuild.enableWelcomeCmd === false) {
// Breaks the function, no further message will be send
return;
}
guild.channels.sort(function(chan1,chan2){
if(chan1.type!==`text`) return 1;
if(!chan1.permissionsFor(guild.me).has(`SEND_MESSAGES`)) return -1;
return chan1.position < chan2.position ? -1 : 1;
}).first().send(memberTag + " just joined <:floshed:533687801741443082>");
});
client.on("message", async message => {
// Check if the msg has been send by a bot
if(message.author.bot) return;
// Check if message has correct prefix
if(message.content.indexOf(config.prefix) !== 0) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
// Code for actually changing the guild variable
if (command === 'toggleWelcome') {
// Code here to get the guild from database, this is just a non-working example
let dbGuild = database.get('Guild', message.guild.id);
dbGuild.enableWelcomeCmd = !dbGuild.enableWelcomeCmd;
// Save the new variable for the guild (also a non-working example)
database.save('Guild', message.guild.id, dbGuild);
}
});
You'll have to look into databases and such yourself, there is a wide variety of (free) options which all have a different syntax. That part is something for you to figure out but I hope this can give you a general idea.

Resources