Displaying amount of guilds as activity - javascript

I have this code to make it say "Watching (amount of servers my bot is in) servers!"
const activities_list = [
"with the &help command.",
"with the developers console",
"with some code",
"with JavaScript",
client.guilds.size + " servers!"
];
client.on('ready', () => {
setInterval(() => {
const index = Math.floor(Math.random() * (activities_list.length - 1) + 1);
client.user.setActivity(activities_list[index]);
}, 5000);
});
But it gives me this when I see it on discord
"0 servers!"
How do I fix this?

I think the problem is that you're declaring the string before the client is ready (when you type a string with a variable it's saved with that value). Try declaring it in the setInterval argument:
client.on("ready", () => {
setInterval(() => {
let activities = ["your_strings", `${client.guilds.size} servers!`],
index = Math.floor(Math.random() * (activities_list.length - 1) + 1);
client.user.setActivity(activities[index])
}, 5000);
});

Related

Discord.Js How I can get bot status with regular order from array, not random?

const activities = ['t', 'te', 'tes', 'test'];
client.on('ready', () => {
const updateDelay = 5; // in seconds
let currentIndex = 0;
setInterval(() => {
const activity = activities[currentIndex];
client.user.setActivity(activity);
// update currentIndex
// if it's the last one, get back to 0
currentIndex = currentIndex >= activities.length - 1
? 0
: currentIndex + 1;
}, updateDelay * 1000);
});
(This code from Zsolt Meszaros from an answer)
I tried to use it but it's giving T T T T T T as result in Discord.js v13. Not continued like T TE TES TEST.
Anyone can help with it? Thanks.

Discord.js DND Dice Roll Input Change Number

I've made a "working" dice roll function on my bot. Works fine for what I need, but was wondering how I could make it so depending on what is said in discord it rolls.
So saying !rolld6 would use 6 in var response instead of 20.
if (message.content.toLowerCase().includes("!rolld20")) {
const ayy = client.emojis.cache.find(emoji => emoji.name === "diceroll");
var response = [Math.floor(Math.random() * ((20 - 1) + 1) + 1)];
message.channel.send(`${ayy}` + `Rolling.`)
.then(msg => {
setTimeout(function() {
msg.edit(`${ayy}` + `Rolling..`)
}, 1000);
setTimeout(function() {
msg.edit(`${ayy}` + `Rolling...`)
}, 2000)
setTimeout(function() {
msg.edit(`${ayy}` + `Rolling....`)
}, 3000)
setTimeout(function() {
msg.edit(`${ayy}` + " Rolled... " + response + " " + `${ayy}`).then().catch(console.error)
}, 4000)
})
return;
}
Not even sure what I would search to figure this out so any help is greatly appreciated!
Use a regular expression instead of .includes, and then extract the digits after the d to randomize.
You don't need to subtract 1, then add 1 right after that - those cancel out, nor do you need to put the result into an array - interpolating just the random number generated into the message will work fine.
const match = message.content.match(/!rolld(\d+)/i);
if (match) {
const die = match[1];
const response = 1 + Math.floor(Math.random() * die);
const ayy = client.emojis.cache.find(emoji => emoji.name === "diceroll");

For-each loop in await all runs simultaneously. What loop to use?

first time making a discord bot (discord.js) and stuck in a situation in which my awaitMessage function all runs simultaneously. For example, when I call the command, it does this in a for each loop of 5.
What is this item? You have 60 seconds!
What is this item? You have 60 seconds!
What is this item? You have 60 seconds!
What is this item? You have 60 seconds!
What is this item? You have 60 seconds!
I looked on stackoverflow and I saw a thread that using a for-of loop in await functions can potentially fix this situation, but I don't know how it can apply to my code. Thanks
var i;
for(i = 0; i < 5; i++){
var random = Math.floor((Math.random() * etcList.length));
message.channel.send("What is this item? You have 60 seconds!", {files: ["./pictures/images/img"+(random+1)+".jpg"]});
const filter = m => m.content == (etcList[random].toString()) || (m.content==("skip"));
message.channel.awaitMessages(filter, {max:1, time:60000})
.then(collected => {
if(collected.first().content == ("skip")){
return message.channel.send("This question has been skipped! The answer was: " + etcList[random].toString());
}
if(collected.first().content == (etcList[random].toString())){
message.channel.send(collected.first().author + " has won! The answer was: " + etcList[random].toString());
}
})
.catch(err => {
message.channel.send("Time is up! The answer was: " + etcList[random].toString());
})
}
Instead of message.channel.awaitMessages(...).then(...).catch(...) use this in for-loop
try {
let collected = await message.channel.awaitMessages(filter, {
max: 1,
time: 60000
});
if (collected.first().content == ("skip")) {
return message.channel.send("This question has been skipped! The answer was: " + etcList[random].toString());
}
if (collected.first().content == (etcList[random].toString())) {
message.channel.send(collected.first().author + " has won! The answer was: " + etcList[random].toString());
}
} catch (e) {
message.channel.send("Time is up! The answer was: " + etcList[random].toString());
}
We use await key word here which will 'wait' for function result. You for-loop shoud be placed in function which use async keyword on its definition
Without refactoring the code you can just add await before your promises and wrap it using an async function.
Here is an Minimal, Complete, and Verifiable example:
async function func() {
var i;
for (i = 0; i < 5; i++) {
await new Promise((res, rej) => {
setTimeout(() => { console.log('x=>'); res() }, 1000)
})
.then(() => console.log('y'));
}
}
Hope this clarifies(or confuses) some things!

How to ensure invitation code is unique in Redis

I need to generate an unique user friendly code and save it into Redis either until the invited user grads it or it expires.
Since the code has to be user friendly I have decided to use 6 digit number, which the frontend will divide into two groups e.g. xxx-xxx.
Now, on the backend, I have NodeJS and node_redis.
This is how I generate the random string and save it into the Redis:
var invCode = Math.floor(Math.random() * 90000) + 100000;
var key = "invitation-code:" + invCode;
const TTL = 3 * 24 * 60 * 60; // 3 days
redis.client.existsAsync(key)
.then(res => {
if (!res) {
// ok, I can add the key, value pair
return redis.client.setAsync(key, value, 'EX', TTL);
} else {
// I have to generate new key and check it again
// how can I re-iterate the process???
return null;
}
})
.then(res => {
logger.info('InvitationCodeController::generate added <' + key + ', ' + value + '> pair');
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
});
Now, the point I cannot figure out is - in case the generated code already exists, how can I re-iterate the process, i.e. to generate another random string, format it, check in Redis and etc.
Since I have async call, I don't think any kind of loop can work for me?
Any ideas?
You could utilize a "attempts" process like the following.
You could also make a while loop similarly by removing the --n portion.
Additionally I think you should use the "NX" parameter for "SETNX" --- Set when the value does not exist. Otherwise it is possible that between the time you check redis for whether the key exists and the time you actually set it, you can overwrite some other key. You might even rewrite it at this point so rely on SETNX throwing an error on failing to set rather than checking the value each time.
const process = require('process');
const redis = require("redis");
const Bluebird = require('bluebird')
Bluebird.promisifyAll(redis.RedisClient.prototype)
Bluebird.promisifyAll(redis.Multi.prototype)
const winston = require('winston');
const logger = winston.createLogger({
level: 'silly',
format: winston.format.json(),
transports: [new winston.transports.Console({
format: winston.format.simple()
})]
});
const client = redis.createClient({
host:'redis-19141.c16.us-east-1-3.ec2.cloud.redislabs.com',
port:'19141'
});
client.auth('I6C2ISvac4suTbxSYcbsjWiz635NK8Wv');
// client.set("string key", "string val", redis.print);
var invCode = Math.floor(Math.random() * 90000) + 100000;
// test invCode being the same --- retry.
invCode = 111111;
var key = "invitation-code:" + invCode;
const TTL = 3 * 24 * 60 * 60; // 3 days
let value = "test";
const trySet = function(key,n){
const used = process.memoryUsage().heapUsed / 1024 / 1024;
logger.info(`The script uses approximately ${Math.round(used * 100) / 100} MB`);
return client.existsAsync(key)
.then(res => {
logger.info("existsAsync res",res);
if (!res) {
logger.info("Key does not exist!");
return client.setAsync(key, value, 'NX','EX', TTL)
.then(res => {
logger.info('InvitationCodeController::generate added <' + key + ', ' + value + '> pair');
return true;
})
} else {
logger.info("Key already exists!");
if(n > 0){
return trySet(key,--n);
}else{
return false;
}
}
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
return false;
});
}
trySet(key,50).then(function(res){
if(res){
logger.info('trySet::success');
}else{
logger.info('trySet::failed');
}
}).catch(error => {
logger.error('trySet::error');
});
https://repl.it/repls/ImmediateSufficientCoin
Since code generation is sync process, I figure out, I can do it other way around. Here is the code:
const TTL = 3 * 24 * 60 * 60; // 3 days
var invCode = '';
const pattern = "invitation-code:";
var prepKey = '';
redis.client.keysAsync(pattern + "*")
.then(keys => {
// these are all keys / invitation codes
var isFound = false;
do {
invCode = Math.floor(Math.random() * 90000) + 100000;
prepKey = pattern + invCode;
// traverse keys to check if the invitation code matches
keys.forEach(key => {
if (key === prepKey) {
isFound = true;
}
});
} while (isFound);
return prepKey;
})
.then(key => {
return redis.client.setAsync(key, value, 'EX', TTL);
})
.then(res => {
logger.info('InvitationCodeController::generate added <' + prepKey + ', ' + value + '> pair');
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
});
Hope this help anyone else on the topic...

How can I avoid sending two commands at once?

I'm creating a discord bot and part of its commands is to roll dice with different values (d6, d10, d20, d100). I've set it up like this:
const Discord = require('discord.js');
const client = new Discord.Client();
function commandIs (str, msg){
return msg.content.toLowerCase().startsWith("!" + str)
} //Function that shortens all response commands.
client.on ('message', message => {
if(commandIs("rolld6", message)){
var result = Math.floor(Math.random() * ((6 - 1) + 1) + 1);
message.channel.sendMessage (result);
} //rolls a d6
if(commandIs("rolld10", message)){
var result = Math.floor(Math.random() * ((10 - 1) + 1) + 1);
message.channel.sendMessage (result);
} //rolls a d10
if(commandIs("rolld20", message)){
var result = Math.floor(Math.random() * ((20 - 1) + 1) + 1);
message.channel.sendMessage (result);
} //rolls a d20
if(commandIs("rolld100", message)){
var result = Math.floor(Math.random() * ((100 - 1) + 1) + 1);
message.channel.sendMessage (result);
} //rolls a d100
})
client.login('<Discord bot token>'); //Bot token so it can login to Discord
The issue I have is when I send '!rolld100', the bot answers as if I sent '!rolld10' and '!rolld100' at the same time since 10 is in 100.
Any possible fixes? I'm also new to javascript so if you could explain what your solution does it would help me a lot.
The code seems to be a little complicated with duplicated code. You can simplify this down to a few lines of code by using a regular expression
const Discord = require('discord.js');
const client = new Discord.Client();
client.on ('message', message => {
const rollMatch = message.match(/roll(\d+)\s/)
if (rollMatch) {
const sides = Number(rollMatch)
var result = Math.floor(Math.random() * sides + 1);
message.channel.sendMessage (result);
}
})
client.login('<Discord bot token>'); //Bot token so it can login to Discord
Now if you want to do it your way. You basically would need to do
if(commandIs("rolld100", message)){ }
else if(commandIs("rolld10", message)){ }
else if(commandIs("rolld20", message)){ }
else if(commandIs("rolld6", message)){ }

Categories

Resources