I'm able to calculate time, but it keeps resetting and does not add up time - discord.js

const { Collection } = require("discord.js");
// ...
client.userStudyTime = new Collection();
client.on("messageCreate", (message) => {
if (message.author.bot) return;
if (message.content === "!login") {
// Check if the message's content was !login
const time = new Date(); // Get the login time
client.userStudyTime.set(message.author.id, time.getTime()); // Set the time
}
if (message.content === "!logout") {
// Check if the message's content was !logout
const userTime = client.userStudyTime.get(message.author.id); // Get the user's login time
if (!userTime) return message.channel.send("You are not logged in!"); // Check if the user had logged in
const time = new Date().getTime(); // Get the logout time
const diff = time - userTime; // Calculate the difference
const hours = Math.round(diff / 1000 / 60 / 60); // Get the hours
const minutes = Math.round(diff / 1000 / 60); // Get the minutes
const seconds = Math.round(diff / 1000); // Get the seconds
message.channel.send(
`You studied for ${hours}hrs, ${minutes}min, ${seconds}sec`
); // Reply back
client.userStudyTime.set(message.author.id, null); // Set the collection to null
}
});
// .

Related

Can someone help me find what is wrong with my code?

Im trying to make a stopwatch command that when you say !duty on and then !duty off it will calculate the time took to stop it. It works like a regular stopwatch but it is for discord. I have been trying to fix the err for a week but i cant understand why it doesnt work pls help me. The err is in line 10 id where it says message.guild.id
the code:
const Discord = require('discord.js');
const StopWatch = require("timer-stopwatch-dev");
const moment = require('moment');
module.exports = {
name: 'duty',
description: "This is a stopwatch command",
async execute(client, message, args, CurrentTimers) {
try {
let guildTimers = CurrentTimers.get(message.guild.id);
let guildTimersUser = guildTimers.get(message.author.id);
if(!guildTimersUser){ guildTimers.set(message.author.id, new StopWatch()); guildTimersUser = guildTimers.get(message.author.id); };
if(!args[0] || args[0] === 'on'){
if(guildTimersUser.isRunning()) return message.channel.send('You need to stop your shift first!')
guildTimersUser.start();
message.channel.send('You have started your shift')
} else if(args[0] === 'off'){
if(!guildTimersUser.isRunning()) return message.channel.send('You need to start the Stopwatch first!')
guildTimersUser.stop();
message.channel.send(new Discord.RichEmbed().setTitle('You have stopped the Stopwatch!').setDescription('Total Time: ' + dhm(guildTimersUser.ms)).setTimestamp());
}
}
catch(err) {
console.log(err)
}
function dhm(ms){
days = Math.floor(ms / (24*60*60*1000));
daysms=ms % (24*60*60*1000);
hours = Math.floor((daysms)/(60*60*1000));
hoursms=ms % (60*60*1000);
minutes = Math.floor((hoursms)/(60*1000));
minutesms=ms % (60*1000);
sec = Math.floor((minutesms)/(1000));
return days+" days, "+hours+" hours, "+minutes+" minutes, "+sec+" seconds.";
}
}
}
my main:
require('dotenv').config();
//create cooldowns map
const cooldowns = new Map();
module.exports = (Discord, client, message) => {
const prefix = '!';
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const cmd = args.shift().toLowerCase();
const command = client.commands.get(cmd) ||
client.commands.find(a => a.aliases && a.aliases.includes(cmd));
if(command){
//If cooldowns map doesn't have a command.name key then create one.
if(!cooldowns.has(command.name)){
cooldowns.set(command.name, new Discord.Collection());
}
const current_time = Date.now();
const time_stamps = cooldowns.get(command.name);
const cooldown_amount = (command.cooldown) * 1000;
//If time_stamps has a key with the author's id then check the expiration time to send a message to a user.
if(time_stamps.has(message.author.id)){
const expiration_time = time_stamps.get(message.author.id) + cooldown_amount;
if(current_time < expiration_time){
const time_left = (expiration_time - current_time) / 1000;
return message.reply(`Please wait ${time_left.toFixed(1)} more seconds before using ${command.name}`);
}
}
//If the author's id is not in time_stamps then add them with the current time.
time_stamps.set(message.author.id, current_time);
//Delete the user's id once the cooldown is over.
setTimeout(() => time_stamps.delete(message.author.id), cooldown_amount);
}
try{
command.execute(message,args, cmd, client, Discord, CurrentTimers);
} catch (err){
message.reply("There was an error trying to execute this command!");
console.log(err);
}
}
You didn’t show the actual error but I suspect that it is something like Cannot read property 'id' of undefined. The way to fix this is to make sure of 2 things:
Make sure the message is not in DM
Make sure your execution parameters are passed in correctly.
command.execute(client, message, args, CurrentTimers)
//these may not be the same variable names, but make sure the values are correct

Command Cooldown discord.js

I have been working on updating my current command cooldown, when upadting my message.js file the cooldown does not show.
This is the current code in the command cooldown file
const botconfig = require("../../botconfig.json");
const fs = require("fs")
const Discord = require('discord.js')
const cooldowns = new Map()
module.exports = async (bot, message) => {
if(message.author.bot || message.channel.type === "dm") return;
let prefixes = JSON.parse(fs.readFileSync("././prefixes.json", "utf8"))
if(!prefixes[message.guild.id]){
prefixes[message.guild.id] = {
prefixes: botconfig.prefix
};
}
let prefix = prefixes[message.guild.id].prefixes;
let args = message.content.slice(prefix.length).trim().split(/ +/g);
let cmd = args.shift().toLowerCase();
if(!message.content.startsWith(prefix)) return;
let commandfile = bot.commands.get(cmd) || bot.commands.get(bot.aliases.get(cmd))
if(commandfile) commandfile.run(bot, message, args)
if(!cooldowns.has(commandfile.name)){
cooldowns.set(commandfile.name, new Discord.Collection());
}
const current_time = Date.now();
const time_stamps = cooldowns.get(commandfile.name);
const cooldown_amount = (commandfile.cooldown) * 1000;
if(time_stamps.has(message.author.id)){
const experation_time = time_stamps.get(message.author.id) + cooldown_amount;
if (current_time < experation_time){
const time_left = (experation_time - current_time) / 1000;
return message.reply(`Please wait ${time_left.toFixed(1)} more seconds before using this command!`)
}
}
time_stamps.set(message.author.id, current_time);
setTimeout(() => time_stamps.delete(message.author.id), cooldown_amount);
}
In the command file I have
module.exports = {
config:{
name: "beg",
aliases: [],
cooldown: 5, // current cooldown in seconds
category: "currency",
description: "Gets you money",
usage: "[command | alias]",
accessableby: "Members"
},
When I use the command the command will work but the cooldown does not work and lets me use the command again. Am I doing something wrong? I would also like to know if I stop running the bot for an update will the cooldown save for example I use the command "!!daily" then re-set the bot for an update and 24 hours did not pass that when it goes back online the cooldown save's and keeps counting.
Cooldown should be a Discord.Collection
const cooldowns = new Discord.Collection(); //that goes on top of your script
Is first time what I comment here, I hope it helps you.
It is a matter of order:
First you call if(commandfile) commandfile.run(bot, message, args) but then only you check if the Cooldown exists. You need to rearange you code like this, move the .run down.
const botconfig = require("../../botconfig.json");
const fs = require("fs")
const Discord = require('discord.js')
const cooldowns = new Discord.Collection();
// While this does not matter, we make a Collection to for consistentcy
module.exports = async (bot, message) => {
if(message.author.bot || message.channel.type === "dm") return;
let prefixes = JSON.parse(fs.readFileSync("././prefixes.json", "utf8"))
if(!prefixes[message.guild.id]){
prefixes[message.guild.id] = {
prefixes: botconfig.prefix
};
}
let prefix = prefixes[message.guild.id].prefixes;
let args = message.content.slice(prefix.length).trim().split(/ +/g);
let cmd = args.shift().toLowerCase();
if(!message.content.startsWith(prefix)) return;
let commandfile = bot.commands.get(cmd) || bot.commands.get(bot.aliases.get(cmd));
if(!commandfile) return;
// return if no command Found, if one is found, proceed to check for cooldown
if(!cooldowns.has(commandfile.name)){
cooldowns.set(commandfile.name, new Discord.Collection());
}
const current_time = Date.now();
const time_stamps = cooldowns.get(commandfile.name);
const cooldown_amount = (commandfile.cooldown) * 1000;
if(time_stamps.has(message.author.id)){
const experation_time = time_stamps.get(message.author.id) + cooldown_amount;
if (current_time < experation_time){
const time_left = (experation_time - current_time) / 1000;
return message.reply(`Please wait ${time_left.toFixed(1)} more seconds before using this command!`);
}
}
// above here is the return, if the cooldown is still active, if so it returns with the message
time_stamps.set(message.author.id, current_time);
// here we set the time_stamp and now can run the command
commandfile.run(bot, message, args);
}

Automatic Slowmode Discord.js

I've been trying to create a system that automatically sets the slowmode in a channel to a certain amount depending on how many messages have been sent. Lua is my primary language, and not Node.js, therefore I'm having quite a bit of trouble as to how I would go about this. If anyone had any suggestions, please let me know.
Two ways to go about it:
Use discord.js's <TextChannel>.setRateLimitPerUser(number)
https://discord.js.org/#/docs/main/stable/class/TextChannel?scrollTo=setRateLimitPerUser
Not sure if this actually does what you want though, the other option is creating a session storage of the text channels msgCount and compare it to time, i found setRateLimitPerUser in the middle of writing the code so didn't finish it, be here's a start:
const { Client, Collection } = require("discord.js");
const client = new Client();
client.slowdown = new Collection();
client.on("message", msg => {
const id = msg.channel.id;
const attempt = client.slowdown.get(id);
//4 messages at most per second
const ratio = 4;
//look at last how many seconds
const timeSpace = 5;
//TODO: check if channel already has cooldown
if (attempt) {
attempt.msgCount++;
const currentTime = Date.now();
const timePassed = (currentTime - attempt.time) / 1000;
if (attempt.msgCount >= ratio && attempt.msgCount / timePassed >= ratio) {
//setCoolDown
}
if (timePassed >= timeSpace) {
attempt.time = currentTime;
attempt.msgCount = 0;
}
} else {
client.slowdown.set(id, {
time: Date.now(),
msgCount: 1
});
}
});

How can I determine the time to send the message

How can I set the duration of the message Example:
if (message.content === 'test') {
message.channel.send (`he say test in 22seconds`)
}
If you're looking for the time it took to the bot to receive the message, use:
if (message.content === 'test') {
const seconds = ((Date.now()-message.createdTimestamp)/1000).toFixed(2);
message.channel.send (`he say test in ${seconds} seconds`)
}
What you are looking for is setTimeout() function.
if (message.content === 'test') {
setTimeout(function(){
message.channel.send (`it took me 22seconds to send this message.`);
}, 22000);
}
Hmm.. the question is not too clear but I'm guessing you mean once the user types a command, the bot says something and then the user can reply with test and the bot tells you how long it took you to type test? (Give the code a try and if its not what you wanted you can take parts out. :) )
The code:
const prefix = ''; //Put whatever prefix you want in the `(prefix goes here)`
var intervals;
bot.on("message", msg => {
let args = msg.content.substring(prefix.length).split(" ");
switch (args[0]) {
case "test": // You can call the command whatever you want
let timer = 3;
msg.channel.send("Get ready").then(msg => {
intervals = setInterval(function() {
msg.edit(`Type test in the chat in **${timer--}**..`);
}, 1000);
});
setTimeout(() => {
clearInterval(intervals);
msg.channel
.send(`Type test in the chat`)
.then(() => {
const time = Date.now();
msg.channel
.awaitMessages(
function(userMsg) {
if (userMsg.content === "test") return true;
},
{
max: 1,
time: 10000,
errors: ["time"]
}
)
.then(function(collected) {
const endTime = Date.now();
let successMsg = "Congratulations!\n";
let collectedArr = Array.from(collected.values());
for (let msg of collectedArr) {
let timeDiff = (endTime - msg.createdTimestamp) / 100;
successMsg += `You took ${timeDiff} seconds to type test.\n`;
}
msg.channel.send(successMsg);
})
.catch(function(collected) {
msg.channel.send(`You did not answer in time!`);
});
})
.catch(function(err) {
console.log(err);
});
}, 5000);
break;
}
});
I'm not too sure what you're asking for but hope this is it! Again, give it a try and see if it works.
Im guessing you need the bot to send that message in 22 seconds. If thats the case then do this
if (message.content === 'test') {
setTimeout(() => { // setTimeout function dalays code inside of it for a set period of time
message.channel.send (`he say test in 22seconds`); // Your code
}, 22000); // The amount of time it should be delayed for. 22000 (milliseconds) = 22 seconds
}

Exact Time Ago is not coming form moment js

I am doing my project in reactjs and i want time ago to show in table.i am using moment js to show time ago(fromNow()) but it shows the time few second only when the data comes from server.And it shows directly 6hrs ago if the data are not coming from server.Eg afer 2minutes of time interval it shows 6 hours ago.As shown in table below.
the code of my project is shown below
componentDidMount() {
let socket = new WebSocket('wss://api.example.com.np/ws');
this.setState({ socket: socket,noOfVehicle:this.state.supportInfo.length });
this.getSupportInfo();
socket.onmessage = ((message) => {
let socketData = JSON.parse(message.data);
let device_id = socketData[0].device_id;
let updatedSupportInfo = this.getUpdatedInfo(this.state.sourceName);
let flag = true;
let uSupport = updatedSupportInfo.map(function(item){
if(device_id == item.device_id){
item.current_pos = socketData[0].current_pos;
if(item.current_pos){
flag = true;
item["latlng"] = item.current_pos.x + ',' + item.current_pos.y;
}else{
flag = false;
}
let time = new Date(socketData[0].timestamp);
let now = new Date();
let timeAgoIn = moment(time).fromNow(true);
item["timeAgoIn"] = timeAgoIn;
}
getSupportInfo() {
axios({
method: 'get',
url: 'https://support.taranga.com.np/support_info'
})
.then((response) => {
for (var i = 0; i < response.data.length; i++) {
if(response.data[i].current_pos){
response.data[i]["latlng"] = response.data[i].current_pos.x + ',' + response.data[i].current_pos.y;
let time = new Date(response.data[i].timestamp)
let now = new Date();
let a = moment(time);
let b = moment(now);
let timeAgo = b.diff(a, 'hours')
let timeAgoIn = moment(time).fromNow(true)
response.data[i]["timeAgo"] = timeAgo;
response.data[i]["timeAgoIn"] = timeAgoIn;
}
}
this.setState({
supportInfo: response.data
});
})
.catch((error)=>{
throw (error);
});
}
getUpdatedInfo(name) {
let uInfo = [];
let tempSupport = this.state.supportInfo.slice();
_.map(tempSupport,(value,key) =>{
if(value.timeAgo !=0){
let time = new Date(value.timestamp)
let now = new Date();
let a = moment(time);
let b = moment(now);
let timeAgo = b.diff(a, 'minutes')
console.log(timeAgo);
//let timeAgo = moment.duration(b-a).humanize()
let timeAgoIn = moment(time).fromNow(true)
value["timeAgo"] = timeAgo;
value["timeAgoIn"] = timeAgoIn;
}
});
this.setState({
supportInfo:tempSupport
});
the code to show in table is
<TableHeaderColumn dataField="timeAgoIn" dataSort={true}>Time Ago</TableHeaderColumn>
I believe your logic is flawed, when you get the info you are storing the timeAgo once, however timeAgo is a property that changes over time, ex:
You receive a message at 12:00, you set timeAgo to 1 second (or w/e js sets it to)
You check your screen at 12:05, timeAgo for that message is still 1 second, because this is calculated once, but time has passed and timeAgo should be 5 seconds ago, right?
timeAgo property should remain as the timestamp you received from server and be calculated when you refresh your table (when you want to do this is a different topic)

Resources