How to make a command randomly fail - node.js

Okay so on my bot I have a beg command but the peoblem is I want it to sometimes fail.
For example one time it might say "Someone gave you $5" but if it fails it would say "Famous Person: NOPE"
The code below chooses a random text from a file where all the text is.
Is there anyway to mke it randomly fail so a user does not get money?
const { RichEmbed } = require("discord.js");
const { stripIndents } = require("common-tags");
const { prefix } = require("../../botconfig.json");
const db = require('quick.db')
let bal = require("../../database/balance.json");
const fs = require('fs');
const cooldowns = new Map();
const humanizeDuration = require('humanize-duration');
//Set cooldown
module.exports = {
name: "beg",
aliases: [],
category: "economy",
description: "Gets you money",
usage: "[command | alias]",
run: async (client, message, args) => {
const cooldown = cooldowns.get(message.author.id);
if (cooldown) {
const remaining = humanizeDuration(cooldown - Date.now(),{ units: ['s'],round: true });
let cEmbed = new RichEmbed()
.setColor("RANDOM")
.setTitle("Slow down, cmon!")
.setDescription(`You dont want to be like a cry baby! You will be able to beg in \`${remaining}\` just you wait!\n\nWhile you wait why not follow our [Twitter](https://twitter.com/switchoffical)`)
return message.channel.send(cEmbed)
.catch(console.error);
} else {
if(!bal[message.author.id]){
bal[message.author.id] = {
balance: 0
};
}
const Jwork = require('../../beg.json');
const JworkR = Jwork[Math.floor(Math.random() * Jwork.length)];
var random = Math.floor(Math.random() * 20) + 3;
let curBal = bal[message.author.id].balance
bal[message.author.id].balance = curBal + random;
fs.writeFile('././database/balance.json', JSON.stringify(bal, null, 2), (err) => {
let embed = new RichEmbed()
.setColor("RANDOM")
.setDescription(`**\ ${message.author.username}**, ${JworkR} 💵 **${random}**`)
message.channel.send(embed)
if (err) console.log(err)
});
//Adds the user to the set so that they can't talk for a minute
cooldowns.set(message.author.id, Date.now() + 10000);
setTimeout(() => cooldowns.delete(message.author.id), 10000);
}
}
}
I just don't know how to make it fail

So what you can do is run a Math.floor((Math.random()-0.001)*4) store it to a variable. Now you have a random number from 0 to 3 (4 different numbers/outcomes). And then check whether your new variable equals 0. if(failChance === 0) if it's true just don't do the add bal cmd.
Example:
...
} else {
var failChance = Math.floor((Math.random()-0.001)*4);
if(failChance === 0){
message.channel.send('FAILURE');
return;
}
if(!bal[message.author.id]){
...

Related

Get number of requisitions made by the user in a day

I have a POST ENDPOINT in my API where i want to register all work journals a worker made.
export const registerPoint = async (req: Request, res: Response) => {
const user = res.locals.decoded;
const {id} = user;
const ponto = new Ponto;
ponto.datePoint = new Date();
ponto.user_id = id;
//this numPoint should restart every day for that user...
ponto.numPoint = 1;
res.json({ msg: "Register point Route", user, id });
return;
}
how can i control how many times this requisition was made by a worker?
I want to control the variable numPoint, when the user makes this requisition it should increase by 01 and then in the final of the day returns it to 0.
Anyone knows about a solution or about a npm package that can handle this?
EDIT: Im storing all the data with SEQUELIZE + MYSQL.
As a starting point you could use a simple database for storing the data such as https://www.npmjs.com/package/sqlite3 or MySQL.
Running jobs daily you could consider https://www.npmjs.com/package/node-cron , for example having a daily job (outside of an API call function);
var cron = require('node-cron');
cron.schedule('0 0 1 * *', () => {
console.log('running every minute to 1 from 5');
});
From what I understand, you need a logging/audit trail mechanism. Since you are using MySQL you can create a new table with columns like (datetime, user_id, action). Every time the user does any action, it will be logged here. Then you can easily find out the count by aggregation. You won't need to reset any count for any user, if data doesn't exist for a given date then it's count will be 0.
I've made a solution that it worked for what i want.
Here is the solution below:
export const registerPoint = async (req: Request, res: Response) => {
const decodedUser = res.locals.decoded;
const user = await User.findByPk(decodedUser.id);
const TODAY_START = new Date().setHours(0, 0, 0, 0);
const NOW = new Date();
const markedPointsOfDay = await Ponto.findAll({
where: {
datePoint: {
[Op.gt]: TODAY_START,
[Op.lt]: NOW
},
}
});
const markedPointsOfDayByUser = await Ponto.findAll({
where: {
datePoint: {
[Op.gt]: TODAY_START,
[Op.lt]: NOW
},
UserId: (user !== null) ? user.id : decodedUser.id
}
})
if (!markedPointsOfDay || markedPointsOfDay.length === 0) {
const ponto = new Ponto;
ponto.datePoint = new Date();
if (user) {
console.log(user)
ponto.UserId = user.id as number;
console.log(ponto.UserId);
}
if (markedPointsOfDayByUser) {
ponto.numPoint = markedPointsOfDayByUser.length + 1;
}
const newPoint = await ponto.save();
res.json({ msg: "Ponto registrado com sucesso", msg2: "Caiu no IF de quando nao encontrou ponto do DIA", newPoint })
return;
}
if (markedPointsOfDay) {
const ponto = new Ponto;
ponto.datePoint = new Date();
if (user) {
ponto.UserId = user.id as number;
}
if (markedPointsOfDayByUser) {
ponto.numPoint = markedPointsOfDayByUser.length + 1;
}
const newPoint = await ponto.save();
res.json({ msg: "ponto registrado", markedPoint: newPoint, markedPointsOfDayByUser });
return;
}
return;
}

How to edit/replace embeds in discordjs-commando

I am making a Type racing minigame with my discord bot, the code works... but I want to change the messages it sends to embeds, im new to Commando and it wont let me use the discord.js functions im used to using
I need to change all the bots responses to embeds, and make it so when it sends a new embed it just edits the old one so it isnt spamming messages. Here is my code:
const Commando = require('discord.js-commando')
const { words } = require('../../util/fast-type-words')
const example = {
channelId: {
message: 'message object',
stage: 'string',
counter: 'number',
currentWord: 'string',
remainingWords: ['words here'],
points: {
userId: 'points',
},
},
}
const games = {}
const stages = {
STARTING: (counter) => {
return `A new "fast type" game is starting in ${counter}s!`
},
IN_GAME: (word) => {
let spacedWord = ''
for (const character of [...word]) {
spacedWord += character
spacedWord += ' '
}
return `The new word is **${spacedWord}**!`
},
ENDING: (points) => {
const sorted = Object.keys(points).sort((a, b) => {
return points[b] - points[a]
})
let results = ''
for (const key of sorted) {
const amount = points[key]
results += `<#${key}> had ${amount} point${amount === 1 ? '' : 's'}\n`
}
return `The game is now over Here's how everyone did:\n\n${results}------------------`
},
}
const selectWord = (game) => {
game.currentWord =
game.remainingWords[Math.floor(Math.random() * game.remainingWords.length)]
const index = game.remainingWords.indexOf(game.currentWord)
game.remainingWords.splice(index, 1)
}
const gameLoop = () => {
for (const key in games) {
const game = games[key]
const { message, stage } = game
if (stage === 'STARTING') {
let string = stages[stage](game.counter)
message.edit(string)
if (game.counter <= 0) {
game.stage = 'IN_GAME'
game.counter = 15
selectWord(game)
string = stages[game.stage](game.currentWord)
message.edit(string)
}
} else if (stage === 'IN_GAME') {
if (game.counter <= 0) {
game.stage = 'ENDING'
const string = stages[game.stage](game.points)
message.edit(string)
// Delete the game
delete games[key]
continue
}
}
--game.counter
}
setTimeout(gameLoop, 1000)
}
module.exports = class FastTypeGame extends Commando.Command {
constructor(client) {
super(client, {
name: 'fasttype',
group: 'games',
memberName: 'fasttype',
description: 'Starts a fast type game',
userPermissions: ['ADMINISTRATOR'],
})
client.on('message', (message) => {
const { channel, content, member } = message
const { id } = channel
const game = games[id]
if (game && game.currentWord && !member.user.bot) {
message.delete()
if (
game.stage === 'IN_GAME' &&
content.toLowerCase() === game.currentWord.toLowerCase()
) {
game.currentWord = null
const seconds = 2
const { points } = game
points[member.id] = points[member.id] || 0
message
.reply(`You won! +1 point (${++points[member.id]} total)`)
.then((newMessage) => {
newMessage.delete({
timeout: 1000 * seconds,
})
})
setTimeout(() => {
if (game.stage === 'IN_GAME') {
selectWord(game)
const string = stages[game.stage](game.currentWord)
game.message.edit(string)
}
}, 1000 * seconds)
}
}
})
gameLoop()
}
async run(message) {
const { channel } = message
message.delete()
channel.send('Preparing game...').then((message) => {
games[channel.id] = {
message,
stage: 'STARTING',
counter: 5,
remainingWords: [...words],
points: {
'719805930547445772': 4,
'723819104045105172': 1,
},
}
})
}
}
First change embeded content is not related to discord.js-commando to change the content of sended embeded message you need to get Message Object then using edit() method to pass the new embed content to it:
-Bonus: You can also edit text message into embed message.
Docs for edit method: https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=edit
Example code:
let youCurrentMessage = await channel.send(embedContent);
yourCurrentMessage.edit(newEmbedContent);
yourCurrentMessage.edit(newEmbedContent2);
// If you edit message in other command , session.You need message id
let yourCurrentMessage = await msg.channel.messages.fetch(editMessageId);
yourCurrentMessage.edit(newEmbedContent);

Command Cooldown 1 minute not working discord bot

Here I tried making a command cooldown so people wont be spamming and getting rich fast on my discord bot! The thing is though the code I wrote does not do what I want it to do! It just ignores talkRecently Here is my code:
var eco = require('discord-economy');
const editJsonFile = require("edit-json-file");
const prefix = '.';
const talkedRecently = new Set();
exports.run = async (client, message, args, ops) => {
if (talkedRecently.has(message.author.id)) {
message.channel.send("Wait 1 minute before getting typing this again. - " + message.author);
} else {
var job2 = ['actor/actress','astronaut','baker','barber','biologist','chef','doctor','dentist','farmer','nurse','jounalist','police officer','vet','vocalist','zoologist','waiter/waitress'];
const user = message.author.id;
var number = Math.floor(Math.random() * (500 + 1));
let check = eco.FetchBalance(user);
if(!check) {
eco.SetBalance(user, 0);
}
eco.AddToBalance(user, number)
var job = job2[Math.floor(Math.random() * job2.length)];
message.channel.send(`You have worked as a **${job}** and you have earned ${number}`);
}
talkedRecently.add(message.author.id);
setTimeout(() => {
// Removes the user from the set after a minute
talkedRecently.delete(message.author.id);
}, 60000);
}
Excluding boilerplate code
var arrayOfIntervalUsed = []
var arrOfIds = [];
client.on("message", (msg) => {
arrOfIds.push(msg.author.id)
if(arrOfIntervalUsed.indexOf(msg.author.id) === -1){
setInterval(() => {
arrOfIntervalUsed.push(msg.author.id) // so the bot isn't duplicating itself
if(arrOfIds.filter(() => {
return msg.author.id
}).length > 10){
msg.reply("Stop spamming")
arrOfIds = arrOfIds.filter(() => {
return !msg.author.id
})
}
}, 60000)
}
})
EDIT:
If you want none of the commands to work if they spam add a variable by default true which has to be true in your if statement for what command it is and in the code above below the message about stop spamming make it false but if you want it to come back on add another setInterval outside of that that a set amount of miliseconds it is restored.

Discord.js Command Cooldown + Time Remaining

Okay so I am looking to make it so that the cooldown shows how much longer the user needs to wait until they can work again. The cool down works butI want it to show the time remainign rather than it saying you need to wait 15 mnutes before typing this command. Is it Possible?
const { RichEmbed } = require("discord.js");
const { stripIndents } = require("common-tags");
const { prefix } = require("../../botconfig.json");
const db = require('quick.db')
let bal = require("../../database/balance.json");
let works = require('../../database/works.json');
const fs = require('fs');
const talkedRecently = new Set();
//Set cooldown
module.exports = {
name: "work",
aliases: [],
category: "economy",
description: "Gets you money",
usage: "[command | alias]",
run: async (client, message, args) => {
if (talkedRecently.has(message.author.id)) {
message.channel.send("You have to wait TIME minutes before you can work again")
} else {
if(!bal[message.author.id]){
bal[message.author.id] = {
balance: 0
};
}
if(!works[message.author.id]) {
works[message.author.id] = {
work: 0
};
}
const Jwork = require('../../work.json');
const JworkR = Jwork[Math.floor(Math.random() * Jwork.length)];
var random = Math.floor(Math.random() * 20) + 3;
let curBal = bal[message.author.id].balance
bal[message.author.id].balance = curBal + random;
let curWork = works[message.author.id].work
works[message.author.id].work = curWork + 1;
fs.writeFile('././database/works.json', JSON.stringify(works, null, 2), (err) => {
if (err) console.log(err)
})
fs.writeFile('././database/balance.json', JSON.stringify(bal, null, 2), (err) => {
let embed = new RichEmbed()
.setColor("RANDOM")
.setDescription(`
**\💼 | ${message.author.username}**, ${JworkR} 💴 **${random}**
`)
message.channel.send(embed)
if (err) console.log(err)
});
// Adds the user to the set so that they can't talk for a minute
talkedRecently.add(message.author.id);
setTimeout(() => {
// Removes the user from the set after a minute
talkedRecently.delete(message.author.id);
}, 900000);
}
}
}
Unfortunately, your current system won't be any help. You'll have to store more than just the user if you want to use the timings of their cooldown.
Let's use a Map for our variable so we can have key-value pairs. This will make it easier to keep track of the information we need
// Replace talkedRecently's declaration with this...
const cooldowns = new Map();
To put a user on cooldown, use Map.set() to add the user and the time at which their cooldown should expire to cooldowns. Then, use Map.delete() when the cooldown should run out to allow the user access to the command again.
// Replace the talkedRecently.add(...) section with this...
cooldowns.set(message.author.id, Date.now() + 900000);
setTimeout(() => cooldowns.delete(message.author.id), 900000);
In order to determine the amount of time remaining on the cooldown, we have to subtract the current time from that at which it expires. However, this will give us milliseconds, rendering the value unreadable to us. A simple, easy way to convert duration into words is by using humanize-duration (moment is also an option). Finally, we can send the desired message, letting the user know how much time they have left on their cooldown.
// Put this where you require your other dependencies...
const humanizeDuration = require('humanize-duration');
// Replace the if (talkedRecently.has(...)) part with this...
const cooldown = cooldowns.get(message.author.id);
if (cooldown) {
const remaining = humanizeDuration(cooldown - Date.now());
return message.channel.send(`You have to wait ${remaining} before you can work again`)
.catch(console.error);
}

Deleting all messages in discord.js text channel

Ok, so I searched for a while, but I couldn't find any information on how to delete all messages in a discord channel. And by all messages I mean every single message ever written in that channel. Any clues?
Try this
async () => {
let fetched;
do {
fetched = await channel.fetchMessages({limit: 100});
message.channel.bulkDelete(fetched);
}
while(fetched.size >= 2);
}
Discord does not allow bots to delete more than 100 messages, so you can't delete every message in a channel. You can delete less then 100 messages, using BulkDelete.
Example:
const Discord = require("discord.js");
const client = new Discord.Client();
const prefix = "!";
client.on("ready" () => {
console.log("Successfully logged into client.");
});
client.on("message", msg => {
if (msg.content.toLowerCase().startsWith(prefix + "clearchat")) {
async function clear() {
msg.delete();
const fetched = await msg.channel.fetchMessages({limit: 99});
msg.channel.bulkDelete(fetched);
}
clear();
}
});
client.login("BOT_TOKEN");
Note, it has to be in a async function for the await to work.
Here's my improved version that is quicker and lets you know when its done in the console but you'll have to run it for each username that you used in a channel (if you changed your username at some point):
// Turn on Developer Mode under User Settings > Appearance > Developer Mode (at the bottom)
// Then open the channel you wish to delete all of the messages (could be a DM) and click the three dots on the far right.
// Click "Copy ID" and paste that instead of LAST_MESSAGE_ID.
// Copy / paste the below script into the JavaScript console.
var before = 'LAST_MESSAGE_ID';
var your_username = ''; //your username
var your_discriminator = ''; //that 4 digit code e.g. username#1234
var foundMessages = false;
clearMessages = function(){
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const channel = window.location.href.split('/').pop();
const baseURL = `https://discordapp.com/api/channels/${channel}/messages`;
const headers = {"Authorization": authToken };
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
fetch(baseURL + '?before=' + before + '&limit=100', {headers})
.then(resp => resp.json())
.then(messages => {
return Promise.all(messages.map((message) => {
before = message.id;
foundMessages = true;
if (
message.author.username == your_username
&& message.author.discriminator == your_discriminator
) {
return delay(clock += interval).then(() => fetch(`${baseURL}/${message.id}`, {headers, method: 'DELETE'}));
}
}));
}).then(() => {
if (foundMessages) {
foundMessages = false;
clearMessages();
} else {
console.log('DONE CHECKING CHANNEL!!!')
}
});
}
clearMessages();
The previous script I found for deleting your own messages without a bot...
// Turn on Developer Mode under User Settings > Appearance > Developer Mode (at the bottom)
// Then open the channel you wish to delete all of the messages (could be a DM) and click the three dots on the far right.
// Click "Copy ID" and paste that instead of LAST_MESSAGE_ID.
// Copy / paste the below script into the JavaScript console.
// If you're in a DM you will receive a 403 error for every message the other user sent (you don't have permission to delete their messages).
var before = 'LAST_MESSAGE_ID';
clearMessages = function(){
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const channel = window.location.href.split('/').pop();
const baseURL = `https://discordapp.com/api/channels/${channel}/messages`;
const headers = {"Authorization": authToken };
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
fetch(baseURL + '?before=' + before + '&limit=100', {headers})
.then(resp => resp.json())
.then(messages => {
return Promise.all(messages.map((message) => {
before = message.id;
return delay(clock += interval).then(() => fetch(`${baseURL}/${message.id}`, {headers, method: 'DELETE'}));
}));
}).then(() => clearMessages());
}
clearMessages();
Reference: https://gist.github.com/IMcPwn/0c838a6248772c6fea1339ddad503cce
This will work on discord.js version 12.2.0
Just put this inside your client on message event
and type the command: !nuke-this-channel
Every message on channel will get wiped
then, a kim jong un meme will be posted.
if (msg.content.toLowerCase() == '!nuke-this-channel') {
async function wipe() {
var msg_size = 100;
while (msg_size == 100) {
await msg.channel.bulkDelete(100)
.then(messages => msg_size = messages.size)
.catch(console.error);
}
msg.channel.send(`<#${msg.author.id}>\n> ${msg.content}`, { files: ['http://www.quickmeme.com/img/cf/cfe8938e72eb94d41bbbe99acad77a50cb08a95e164c2b7163d50877e0f86441.jpg'] })
}
wipe()
}
This will work so long your bot has appropriate permissions.
module.exports = {
name: "clear",
description: "Clear messages from the channel.",
args: true,
usage: "<number greater than 0, less than 100>",
execute(message, args) {
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply("that doesn't seem to be a valid number.");
} else if (amount <= 1 || amount > 100) {
return message.reply("you need to input a number between 1 and 99.");
}
message.channel.bulkDelete(amount, true).catch((err) => {
console.error(err);
message.channel.send(
"there was an error trying to prune messages in this channel!"
);
});
},
};
In case you didn't read the DiscordJS docs, you should have an index.js file that looks a little something like this:
const Discord = require("discord.js");
const { prefix, token } = require("./config.json");
const client = new Discord.Client();
client.commands = new Discord.Collection();
const commandFiles = fs
.readdirSync("./commands")
.filter((file) => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
//client portion:
client.once("ready", () => {
console.log("Ready!");
});
client.on("message", (message) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
if (command.args && !args.length) {
let reply = `You didn't provide any arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply("there was an error trying to execute that command!");
}
});
client.login(token);
Another approach could be cloning the channel and deleting the one with the messages you want deleted:
// Clears all messages from a channel by cloning channel and deleting old channel
async function clearAllMessagesByCloning(channel) {
// Clone channel
const newChannel = await channel.clone()
console.log(newChannel.id) // Do with this new channel ID what you want
// Delete old channel
channel.delete()
}
I prefer this method rather than the ones listed on this thread because it most likely takes less time to process and (I'm guessing) puts the Discord API under less stress. Also, channel.bulkDelete() is only able to delete messages that are newer than two weeks, which means you won't be able to delete every channel message in case your channel has messages that are older than two weeks.
The possible downside is the channel changing id. In case you rely on storing ids in a database or such, don't forget to update those documents with the id of the newly cloned channel!
Here's #Kiyokodyele answer but with some changes from #user8690818 answer.
(async () => {
let deleted;
do {
deleted = await channel.bulkDelete(100);
} while (deleted.size != 0);
})();

Resources