I have the below cron job scheduled to run every minute to update a time in an embed.
cron.schedule('* * * * *', function () {
con.query(`SELECT * FROM events WHERE closed = 'No'`, (err, rows) => {
if (err) throw err
rows.slice().forEach(row => {
const channel = row.channel
const messageID = row.messageID
bot.channels.cache.get(channel).messages.fetch(messageID).then(message => {
const embed = message.embeds[0]
let now = Date.now()
const targetDate = new Date(`${row.event_date} ${row.event_time}:00`)
var difference = (targetDate - now) / 1000;
var days = Math.floor(difference / (3600 * 24));
var hours = Math.floor((difference - (days * (3600 * 24))) / 3600);
var minutes = Math.floor((difference - (days * (3600 * 24)) - (hours * 3600)) / 60);
let timeTill;
if (days > 0) {
timeTill = `${days} Days ${hours} Hours ${minutes} Min`
} else if (days === 0 && hours > 0) {
timeTill = `${hours} Hours ${minutes} Min`
} else if (days === 0 && hours === 0) {
timeTill = `${minutes} Min`
} else if (difference <= 0) {
timeTill = `Event Started - get with <#!${row.hostID}> to join up in-game.`
}
embed.fields[9] = {
name: 'Starts in:',
value: `${timeTill}`,
inline: false
}
message.edit(new Discord.MessageEmbed(embed));
})
})
})
})
Works just fine but I want to take the work load off my website server and just have the bot search for the information needed. Here is what I have so far but it doesn't do anything. Doesn't error, don't update the embed. Nothing. Pretty sure I'm overlooking something and just need another set of eyes to tell me what that is.
cron.schedule('* * * * *', function () {
bot.channels.cache.filter((channel) => channel.name.endsWith('events')).forEach((channel) => {
channel.messages.cache.filter((message) => {
const embed = message.embeds[0]
let messageID;
let event_date;
let event_time;
if (!embed) {
return
} else {
if (embed.color === 65280) {
messageID = message.id
event_date = message.embeds[0].fields[0].value
event_time = message.embeds[0].fields[1].value
} else {
return
}
}
let now = Date.now()
const targetDate = new Date(`${event_date} ${event_time}:00`)
var difference = (targetDate - now) / 1000;
var days = Math.floor(difference / (3600 * 24));
var hours = Math.floor((difference - (days * (3600 * 24))) / 3600);
var minutes = Math.floor((difference - (days * (3600 * 24)) - (hours * 3600)) / 60);
let timeTill;
if (days > 0) {
timeTill = `${days} Days ${hours} Hours ${minutes} Min`
} else if (days === 0 && hours > 0) {
timeTill = `${hours} Hours ${minutes} Min`
} else if (days === 0 && hours === 0) {
timeTill = `${minutes} Min`
} else if (difference <= 0) {
timeTill = `Event Started - get with <#!${row.hostID}> to join up in-game.`
}
embed.fields[9] = {
name: 'Starts in:',
value: `${timeTill}`,
inline: false
}
message.edit(new Discord.MessageEmbed(embed))
})
})
})
The problem is that the messages you are trying to find might not be cached. The channel.messages.cache will only contain messages that were sent after the bot was started. If you want to go through older messages, you will need to fetch the messages. You might want to take a look at my post about fetching messages until a specific date.
Final code:
cron.schedule('* * * * *', function () {
bot.channels.cache.filter((channel) => channel.name.endsWith('events')).forEach((channel) => {
channel.messages.fetch({
limit: 100
}).then(messages => {
messages.forEach(message => {
if (message.embeds.length > 0) {
const embed = message.embeds[0]
let messageID;
let event_date;
let event_time;
if (embed.color === 65280) {
messageID = message.id
event_date = message.embeds[0].fields[0].value
event_time = message.embeds[0].fields[1].value.slice(0, -4)
let now = Date.now()
const targetDate = new Date(`${event_date} ${event_time}:00`)
var difference = (targetDate - now) / 1000;
var days = Math.floor(difference / (3600 * 24));
var hours = Math.floor((difference - (days * (3600 * 24))) / 3600);
var minutes = Math.floor((difference - (days * (3600 * 24)) - (hours * 3600)) / 60);
let timeTill;
if (days > 0) {
timeTill = `${days} Days ${hours} Hours ${minutes} Min`
} else if (days === 0 && hours > 0) {
timeTill = `${hours} Hours ${minutes} Min`
} else if (days === 0 && hours === 0) {
timeTill = `${minutes} Min`
} else if (difference <= 0) {
timeTill = `Event Started - get with <#!${row.hostID}> to join up in-game.`
}
embed.fields[9] = {
name: 'Starts in:',
value: `${timeTill}`,
inline: false
}
message.edit(new Discord.MessageEmbed(embed)).catch(error => {
console.error(error);
})
console.log(`Event ${message.embeds[0].author.name} has been edited. New start time is ${timeTill}.`)
} else {
return
}
} else {
return
}
})
})
})
})
Related
I'm using batch write in order to avoid 500 maximum writes limit. Even if I'm using batchArray in order to process more than 500 writes, I get this error:
Exception from a finished function: Error: 3 INVALID_ARGUMENT: maximum 500 writes allowed per request
Code: https://controlc.com/3c3a59be
exports.checkSchedine2 = functions.pubsub
.schedule('15,45 * * * *')
.onRun(async (context) => {
const batch = firestore.batch();
var currentTime = Math.floor(Date.now() / 1000);
const risultati = await firestore.collection("Risultati").doc("risultati").get();
const ref1 = await firestore.collection("Schedine").get();
let batchArray = [];
batchArray.push(batch);
let operationCounter = 0;
let batchIndex = 0;
let _notcommit = false;
await Promise.all(ref1.docs.map(async (doc) => {
const ref2 = await firestore.collection("Schedine").doc(doc.id).collection("in corso").get();
for (const doc2 of ref2.docs) {
const documentData = doc2.data();
for (matchId in doc2.data()["Match"]) {
try {
for (id in risultati.data()) {
if (matchId == id && risultati.data()[id]["status"] != 0 && doc2.data()["Match"][matchId]["status"] == 0) {
if ((doc2.data()["Match"][matchId]["Bet"] == 1 || doc2.data()["Match"][matchId]["Bet"] == 2 || doc2.data()["Match"][matchId]["Bet"] == 3) && doc2.data()["Match"][matchId]["Bet"] == risultati.data()[id].ris) {
documentData["Match"][matchId]["status"] = 1;
} else if (doc2.data()["Match"][matchId]["Bet"] == 4 && risultati.data()[id].goal == 1) {
documentData["Match"][matchId]["status"] = 1;
} else if (doc2.data()["Match"][matchId]["Bet"] == 5 && risultati.data()[id].goal == 0) {
documentData["Match"][matchId]["status"] = 1;
} else if (doc2.data()["Match"][matchId]["Bet"] == 6 && risultati.data()[id].over == 1) {
documentData["Match"][matchId]["status"] = 1;
} else if (doc2.data()["Match"][matchId]["Bet"] == 7 && risultati.data()[id].over == 0) {
documentData["Match"][matchId]["status"] = 1;
} else {
documentData["Match"][matchId]["status"] = 2;
}
}
}
} catch (e) {}
}
if (_notcommit == false) {
await batchArray[batchIndex].update(doc2.ref, documentData);
operationCounter++;
if (operationCounter > 100) {
batchArray.push(batch);
batchIndex++;
operationCounter = 0;
}
}
};
}));
Promise.all(batchArray.map(batch => batch.commit()));
});
It seems that the code launches too many commits, isn't it?
You are pushing the same batch in that batchArray in every iteration. You should be creating a new batch for every 500 operations:
let batchArray = [firestore.batch()];
// ...
if (operationCounter > 100) {
const newBatch = firestore.batch();
batchArray.push(newBatch);
batchIndex++;
operationCounter = 0;
}
Why my command still not getting a cooldown when user used it?
Here's the code:
const cooldown = new Set();
const { MessageEmbed } = require('discord.js');
const eco = require('discord-mongoose-economy');
eco.connect("mongodb://localhost/database"); //this is not the main I hide it
const work = require('../../events/casino/work.json')
if(cooldown.has(message.author.id)) {
message.reply(`You're tired! Wait for 30 seconds to work again!`)
} else {
const total = Object.keys(work).length
var random = Math.floor(Math.random() * total + 1);
var workInfo = work[random];
const min = 10;
const max = 100;
const coin = Math.floor(Math.random() * (max - min + 1) ) + min;
if(message.author.bot) return;
await eco.give(message.author.id, message.guild.id, coin);
const workembed = new MessageEmbed()
.setDescription(workInfo.description + `and recieved ` + coin + ` coins`)
.setColor('RANDOM')
.setFooter({text: `Work #${random}`})
message.channel.send({embeds: [workembed]});
}
cooldown.add(message.author.id);
setTimeout(() => {
cooldown.delete(message.author.id)
}, 30000);
Is there any misplaced codes or something? Because there's still no cooldown, I'm using discord.js v13
I've edited my codes to this:
if(cooldown.has(message.author.id)) {
message.reply(`You're tired! Wait for 30 seconds to work again!`)
} else {
const total = Object.keys(work).length
var random = Math.floor(Math.random() * total + 1);
var workInfo = work[random];
const min = 10;
const max = 100;
const coin = Math.floor(Math.random() * (max - min + 1) ) + min;
if(message.author.bot) return;
await eco.give(message.author.id, message.guild.id, coin);
const workembed = new MessageEmbed()
.setDescription(workInfo.description + `and recieved ` + coin + ` coins`)
.setColor('RANDOM')
.setFooter({text: `Work #${random}`})
message.channel.send({embeds: [workembed]});
cooldown.add(message.author.id);
setTimeout(() => {
cooldown.delete(message.author.id)
}, 30000);
}
Still not working.
Last edit for my command and its finally working, I added a package called humanize-duration here is the final code of my work:
const cooldowns = new Map();
const humanizeDuration = require('humanize-duration');
const cooldown = cooldowns.get(message.author.id);
if(cooldown) {
const remaining = humanizeDuration(cooldown - Date.now(), {units: ['s'], round: true})
const cd = new MessageEmbed()
.setAuthor({iconURL: `${message.author.avatarURL()}`,name: `${message.member.user.tag}`})
.setDescription(`You need to wait ${remaining} to do work again, take some rest!`)
.setColor('RANDOM')
return message.channel.send({embeds: [cd]})
.catch(console.error);
} else {
const total = Object.keys(work).length
var random = Math.floor(Math.random() * total + 1);
var workInfo = work[random];
const min = 80000;
const max = 120000;
const coin = Math.floor(Math.random() * (max - min + 1) ) + min;
if(message.author.bot) return;
await eco.give(message.author.id, message.guild.id, coin);
const workembed = new MessageEmbed()
.setAuthor({iconURL: `${message.author.avatarURL()}`,name: `${message.member.user.tag}`})
.setDescription(workInfo.description + `and recieved ` + coin + ` coins`)
.setColor('RANDOM')
.setFooter({text: `Work #${random}`})
message.channel.send({embeds: [workembed]});
cooldowns.set(message.author.id, Date.now() + 30000);
setTimeout(() => cooldowns.delete(message.author.id), 30000);
}
If someone need this code I hope you guys can get some tips!
I have a Discord BOT written with Node.JS using Discord.JS
There i have a function that starts when the bot becomes online
It consists in getting an array from an API: https://jacob.rede-epic.com/api/upcomingEvents
With the timestamp, it is supposed to send a message 10, 5 and 1 minute before it happens, when it happens (Exact hour + 15 minutes, e.g: 08:15/09:15/10:15 etc), and when it finishes (20 minutes later, e.g: 08:35/09:35/10:35 etc)
How can i make it to reset the whole system ?
Code:
const { MessageEmbed } = require('discord.js');
const axios = require('axios');
class Jacob {
constructor(client) {
this.client = client;
}
async start() {
const jacobContestsChannel = this.client.channels.cache.get('852596632591269968');
let nextEventObject = null;
let sentNotification = false;
let sentNotification2 = false;
let sentNotification3 = false;
let sentNotificationActive = false;
let sentNotificationFinished = false;
const cropNames = [
'Cactus',
'Carrot',
'Cocoa beans',
'Melon',
'Mushroom',
'Nether wart',
'Potato',
'Pumpkin',
'Sugar cane',
'Wheat',
];
setInterval(async () => {
let upcomingEvents = [];
let response = await axios.get('https://jacob.rede-epic.com/api/upcomingEvents');
let request = response.data;
for (let i in request) {
upcomingEvents.push(request[i]);
}
if (nextEventObject == null) {
nextEventObject = upcomingEvents[0];
} else {
let diff = nextEventObject.timestamp - Date.now();
let active = diff < 0;
setInterval(() => {
try {
diff = nextEventObject.timestamp - Date.now();
} catch {
nextEventObject = null;
}
}, 1000);
if (diff < -20 * 60 * 1000) {
sentNotification = false;
sentNotification2 = false;
sentNotification3 = false;
sentNotificationActive = false;
nextEventObject == null;
if (!sentNotificationFinished) {
jacobContestsChannel.send(new MessageEmbed()
.setColor(this.client.embedColor)
.setTitle('The current contest has ended!')
);
sentNotificationFinished = true;
}
} else if (!active && diff < 10 * 60 * 1000 && !sentNotification) {
jacobContestsChannel.send(new MessageEmbed()
.setColor(this.client.embedColor)
.setTitle('A contest is starting in 10 minutes')
.setDescription(`Crops: ${nextEventObject.crops.map(crop => cropNames[crop]).join(', ')}`)
);
sentNotification = true;
} else if (!active && diff < 5 * 60 * 1000 && sentNotification && !sentNotification2) {
jacobContestsChannel.send(new MessageEmbed()
.setColor(this.client.embedColor)
.setTitle('A contest is starting in 5 minutes')
.setDescription(`Crops: ${nextEventObject.crops.map(crop => cropNames[crop]).join(', ')}`)
);
sentNotification2 = true;
} else if (!active && diff < 60 * 1000 && sentNotification && sentNotification2 && !sentNotification3) {
jacobContestsChannel.send(new MessageEmbed()
.setColor(this.client.embedColor)
.setTitle('A contest is starting in 1 minute')
.setDescription(`Crops: ${nextEventObject.crops.map(crop => cropNames[crop]).join(', ')}`)
);
sentNotification3 = true;
} else if (active && !sentNotificationActive) {
jacobContestsChannel.send(new MessageEmbed()
.setColor(this.client.embedColor)
.setTitle('A contest has started!')
.setDescription(`Crops: ${nextEventObject.crops.map(crop => cropNames[crop]).join(', ')}`)
);
sentNotificationActive = true;
}
console.clear();
console.log(nextEventObject);
console.log(`Diff: ${diff}`);
console.log(`Active: ${active}`);
console.log(`Notification: ${sentNotification}`);
console.log(`Notification Active: ${sentNotificationActive}`);
console.log(`Notification Finished: ${sentNotificationFinished}`);
}
}, 1000);
}
async requestUpcomingEvents() {
let response = await axios.get('https://jacob.rede-epic.com/api/upcomingEvents');
return response.data;
}
}
module.exports = Jacob;
I recently added this to my bot where it checks for the roles and sends a message in the channel where it sends the claim time of the user.
module.exports = {
name: 'giveaway',
description: ':tada: the new winner is',
execute(message, args){
let winner = message.mentions.members.first();
const ouser = message.mentions.users.first();
var time = 10000;
var support = 0;
var donate = 0;
var boost = 0;
const allowedRole = winner.roles.cache.find(r => r.name === '・Supporter') || winner.roles.cache.find(r => r.name === 'Nitro・Donator') || winner.roles.cache.find(r => r.name === '・Booster')
if (!allowedRole) {
message.channel.send(`Congratulations **${ouser.username}**! You have ${time / 1000} seconds to DM the host!`)
.then(message => {
setTimeout(function() {
message.channel.send(`${time / 1000} seconds up!`)
}, time)
})
return;
}
switch (allowedRole.name) {
case '・Supporter':
support = 3000;
break;
case 'Nitro・Donator':
donate = 5000;
break;
case '・Booster':
boost = 5000;
}
var newTime = (time + support + donate + boost));
const user = message.mentions.users.first();
message.channel.send(`Congratulations **${user.username}**! You have ${newTime / 1000} seconds to DM the host!`)
.then(message => {
setTimeout(function() {
message.channel.send(`${newTime / 1000} seconds up!`)
}, newTime)
})
}
}
I'm not sure how to add the time for the total claim time since + isn't working. I tried using time - (- support) - (-donate) - (-boost)) but it only showed 13 seconds (supporter role). Any fix to this?
The problem is in this line
const allowedRole = winner.roles.cache.find(r => r.name === '・Supporter') || winner.roles.cache.find(r => r.name === 'Nitro・Donator') || winner.roles.cache.find(r => r.name === '・Booster')
allowedRole can be set to only one role but a user can have multiple roles.
You can do something like this
module.exports = {
name: "giveaway",
description: ":tada: the new winner is",
execute(message, args) {
const winner = message.mentions.members.first();
let DefaultTime = 10;
let support = 0;
let donate = 0;
let boost = 0;
//get all the roles of the winner in an array
const userRoles = winner.roles.cache.map((r) => r.name);
//Check if the user have the allowed roles and set time according to that (There might be a better way to do this instead of using if statements for each of them seperately)
if (userRoles.includes("・Supporter")) {
support = 3;
}
if (userRoles.includes("Nitro・Donator")) {
donate = 5;
}
if (userRoles.includes("・Booster")) {
boost = 5;
}
const TotalTime = DefaultTime + support + donate + boost;
message.channel
.send(
`Congratulations **${winner.user.username}**! You have ${TotalTime} seconds to DM the host!`
)
.then((message) => {
setTimeout(function () {
message.channel.send(`${TotalTime} seconds up!`);
}, TotalTime * 1000);
});
},
};
I'm unable to save the variables fine,status when the boolean variable isreturned is set to true on button click.
//api.js
router.get('/return/:id?',(req,res)=>{
var id=req.params.id;
console.log(id);
bookissue.update({_id:id},{$set:{"isreturned":true}},(error,result)=>
{
if(error){
console.log(error);
}
console.log(bookissue.status);
var date1 = new Date();
console.log(date1);
//Another error is that bookissue.returndate is returning an invalid date message.
var date2 = bookissue.returndate;
console.log(bookissue.returndate);
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
console.log(diffDays);
if (diffDays !== 0) {
const res = 50;
this.fine = res + diffDays;
}
else {this.fine = 0; }
bookissue.fine=this.fine;
console.log(bookissue.fine);
});
});
When you update the bookIssue property, you need to save/update the object again.
router.get('/return/:id?',(req,res)=>{
var id=req.params.id;
console.log(id);
bookissue.update({_id:id},{$set:{"isreturned":true}},(error,result)=>
{
if(error){
console.log(error);
}
console.log(bookissue.status);
var date1 = new Date();
console.log(date1);
//Another error is that bookissue.returndate is returning an invalid date message.
var date2 = bookissue.returndate;
console.log(bookissue.returndate);
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
console.log(diffDays);
if (diffDays !== 0) {
const res = 50;
this.fine = res + diffDays;
}
else {this.fine = 0; }
bookissue.fine=this.fine;
console.log(bookissue.fine);
bookissue.save((err, updatedBookIssue) => {
if (err) {
console.log(err);
} else {
console.log('Updated book issue');
console.log(updatedBookIssue);
}
});
});
});
Check the above code.
After assigning the fine variable, I again save the object.
I added the the following code, at the end of your code
bookissue.save((err, updatedBookIssue) => {
if (err) {
console.log(err);
} else {
console.log('Updated book issue');
console.log(updatedBookIssue);
}
});