Discord.js Time command - discord.js

Const currentDate = new Date();
client.on('message', msg => {
if(msg.author.bot) return;
if(msg.content === `${prefix}time`) {
msg.channel.send(currentDate.toLocaleString());
}
})
This does provide the right time for MY timezone but is there anyway to make the bot send a time stamp, different regions see a different time?

Well, you can use Discord's <t:unix-timestamp:t> feature. It'll vary depending on the timezone of the user seeing the message. You can get the Unix timestamp with Date.now() (const unixTimestamp = Date.now()) but that's the timestamp in milliseconds so you will need to divide it by 1000 for seconds.
You also want to use Math.floor since dividing milliseconds will give a decimal value and Discord's timestamp thing won't work.
const unixTimestamp = Math.floor(Date.now() / 1000)
Here's the command using your command handler:
client.on('message', (msg) => {
if (msg.author.bot) return;
if (msg.content === `${prefix}time`) {
const unixTime = Math.floor(Date.now() / 1000);
// you can remove the :t in the end so it's a full date
// :t makes it only the time
msg.channel.send(`The current time is <t:${unixTime}:t>`);
}
});
Also, I recommend using messageCreate and not message as it's deprecated.

Related

Change React State based on a specific timezone

Let's imagine that a local bakery has a website that shows its working hours along with a tag "Open" or "Closed". This tag needs to change based on the hours of operation.
The solution that I thought of was to have two states:
for status of working hours (open/closed)
for current time
For the second one I used a solution that I found for online clock:
const [date, setDate] = useState(new Date());
useEffect(() => {
let timer = setInterval(() => setDate(newDate()), 1000);
return function cleanup() {
clearInterval(timer);
};
});
And for changing open/closed state I thought of using this handler:
const handleStatus = () => {
let openHour = new Date();
let closeHour = new Date();
openHour.setHours(9, 0, 0);
closeHour.setHours(18, 30, 0);
if (date > openHour) {
//CLOSED
} else {
//OPEN
}
};
The problem with this approach is that it only works for the state that I am located at and not the other timezone. The goal is to keep the state change for only a specific timezone, so the user that is located in NYC at 9pm will see that the bakery is still open since it is 6pm in LA and it closes only at 6:30pm. How do I go around that? If there is any other approach please let me know!
As of now, JavaScript standard library does not have a concept of ZonedDateTime. Until it becomes available, you can calculate the timezone offset manually and operate on the Date objects in UTC.
// Calculate timezone offset of America/Los_Angeles
utcDate = new Date();
utcDate.setHours(0, 0, 0, 0);
strDateLA = utcDate.toLocaleString("en-US", {
timeZone: "America/Los_Angeles",
});
offset = (new Date(strDateLA) - utcDate) / (1000 * 60 * 60);
console.log(offset);
Now that you have the timezone offset, you can convert the opening and closing hours into UTC date-time.
openHourUTC = new Date();
openHourUTC.setHours(9, 0, 0, 0);
// Opening hour in UTC
openHourUTC = openHourUTC - offset;
closeHourUTC = new Date();
closeHourUTC.setHours(18, 30, 0, 0);
// Closing hour in UTC
closeHourUTC = closeHourUTC - offset;
Note: If the timezone offset is negative e.g. -8, the above code snippet calculates openHourUTC = openHourUTC - (-8) => openHourUTC = openHourUTC + 8.
Now, you can do:
if (date >= openHourUTC && date < closeHourUTC) {
// OPEN
} else {
// CLOSED
}
Maybe you should try to use the browser's timezone instead of the local device's timezone. You can get the browser's timezone with the Intl.DateTimeFormat().resolvedOptions().timeZone method.
You can use this method to update the working hours status based on the browser's timezone:
const handleStatus = () => {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// Set the open and close hours based on the timezone
let openHour, closeHour;
if (timezone === 'America/Los_Angeles') {
openHour = new Date();
openHour.setHours(9, 0, 0);
closeHour = new Date();
closeHour.setHours(18, 30, 0);
} else {
// Set the open and close hours for other timezones here
}
if (date > openHour && date < closeHour) {
// The bakery is open
} else {
// The bakery is closed
}
};
This way, the working hours status will always be based on the browser's timezone, regardless of the local device's timezone.
Alternatively, you could use a server-side solution to get the correct time for the browser's timezone. This would involve making a server-side API call to get the current time in the browser's timezone, and then using that time to update the working hours status. This approach would be more accurate, as it takes into account daylight saving time and other factors that can affect the local device's time. However, it would require setting up a server and making API calls, which may not be necessary if you only need to display the working hours status on a static website.
I hope this helps you some ways.

A bot that calculates the time of members in our server logged in and send it

I'm new to node js . I want to make a bot that calculates our study time and sends it in our channel
So ,when someone from our server message !login is should start the stopwatch and when he types !logout it should stop the stopwatch and the time to the previous and show the total time
Please help me , I want it done as soon as possible
One way to do that would be to create a Collection in the client, store the time when the user sends !login and then when the user sends !logout, fetch the started date from the client, calculate the time used, and then set the Collection to null. However one disadvantage of that is the fact that once the bot restarts, all the data is lost. But since I have no idea if you have any database already set up, we can use Collections for now. The completed code might look something like this:
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, ${Math.round(seconds)}sec`) // Reply back
client.userStudyTime.set(message.author.id, null) // Set the collection to null
}
});
// ...
It would be unwise to have something like a stopwatch.
You want something that will store the user and the time they login, and then when the log out, calculate the time difference and send that.
That can be achieved with either a database, or a simple JSON file.
Something you can do is save a timestamp when using !login with the Date.now() function, whether it be in a client collection or a database. And compare it to the timestamp when they use !logout, the difference between the two would be the amount of seconds they were logged in.
Date.now() Function
Date.now(); // outputs a timestamp
Output:
1653579416
Login Command
in the logout command, you're going to want to use the Date.now() function and set it in your database or your collection under the user that used the command.
Logout Command
in the logout command you want to go back to the login timestamp, and subtract the current timestamp by the saved one, and the difference will be how many seconds they were logged in for.
Example
var loggedInStamp // 1653579416 // you'll want to get this from wherever you saved it
var loggedOutStamp = Date.now() // 1653580205 // current timestamp
// subtract 1653580205 by 1653579416 which equals 789 //
// aka logged in for 789 seconds //
let amountTime = loggedOutStamp - loggedInStamp
return amountTime
/* this is what you want to add to the total time logged in */
This will make your database save the total time logged in seconds, there are plenty of modules or algorithms to convert seconds to minutes, hours, days...
Here is a code example for converting seconds to hours and minutes:
function secondsToHms(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return hDisplay + mDisplay + sDisplay;
}
This is a better way to get the amount of time logged in instead of using a stopwatch.

(discord.js) How to set a time limit on a command?

I am trying to make a Judge bot for my server that will give the person who used the command the role "Plaintiff", and give the person that they mentioned the "Defendant" role. Everything works perfectly as intended except the fact that multiple trials can be started at the same time. Like if someone uses the command and it makes them the plaintiff and a 2nd person the defendant, if a 3rd person uses the command on a 4th person they will become a defendant and plaintiff as well. I want to make it so that while the events of the command are playing out that nobody else in the server can use the command until the 1st trial ends. I have tried to give the entire server the role "jury" and make it so that if anyone has the role "jury" they can't use the command but i couldn't ever get that to work. Also I tried to set a time limit for the command and that didn't work at all either. I have no clue how to get this working and any advice is appreciated!! Thanks!!!
client.on("message", message => {
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === "sue") {
let member1 = message.mentions.members.first();
message.member.roles.add("797738368737345536")
member1.roles.add("797738235715256331");
message.guild.members.cache.forEach(member => member.roles.add("797743010346565672"))
message.channel.send("Court is now in session.")
client.channels.cache.find(channel => channel.name === 'courtroom').send( + " **All rise.**");
client.channels.cache.find(channel => channel.name === 'courtroom').send("Plaintiff, you have 2 minutes to state your case.");
setTimeout(function(){
client.channels.cache.find(channel => channel.name === 'courtroom').send("Thank you Plaintiff. Defendant, you now have 2 minutes to defend yourself.");
}, 120000);
setTimeout(function(){
client.channels.cache.find(channel => channel.name === 'courtroom').send("Thank you. The court may be seated as we turn to the jury for their verdict.");
}, 240000);
const Responses = [
"The Jury hereby finds you.... **GUILTY!** You will be sentanced to 10 minutes in jail.",
"The Jury hereby finds you.... **NOT GUILTY!** You are free to go. The Jury is dismissed."
];
const Response = Responses[Math.floor(Math.random() * Responses.length)];
setTimeout(function(){
client.channels.cache.find(channel => channel.name === 'courtroom').send(Response)
if (Response === "The Jury hereby finds you.... **NOT GUILTY!** You are free to go. The Jury is dismissed." ) {
message.member.roles.remove("797738368737345536")
member1.roles.remove("797738235715256331");
message.guild.members.cache.forEach(member => member.roles.remove("797743010346565672"))
}
if (Response === "The Jury hereby finds you.... **GUILTY!** You will be sentanced to 10 minutes in jail.") {
message.member.roles.remove("797738368737345536")
member1.roles.add("797738617338069002")
member1.roles.remove("797738235715256331");
message.guild.members.cache.forEach(member => member.roles.remove("797743010346565672"))
}
}, 250000);
setTimeout(function(){
member1.roles.remove("797738617338069002");
}, 850000);
}
});
You could create a file, so nobody is able to use the command while the file exists.
const fs = require("fs");
if (command_gets_executed) { // If the command gets executed
if (fs.existsSync("./commandAlreadyUsed")) { // Checking if the file exists
// YOUR CODE - When the command should not be usable
} else {
fs.writeFileSync("./commandAlreadyUsed"); // Creating the file
// YOUR CODE - When nobody else used the command before
}
}
And if you want the command usable again just use fs.unlinkSync("./commandAlreadyUsed").
You can try to use a CronJob to set a time limit, I used it before for a similar case, may be it can be useful for you

Implementing a 15 minute timeout in React issues

I'm implementing a Save feature on a form I'm creating in React. When a User clicks save on a form, I want them to type the username/password. The next time that same user tries to save, if it's been under 15 minutes, I want them to not have to sign the save username/password. If it's over 15, I want them to authenticate again.
I stumbled across this code on a different stackoverflow question about timeouts.
calculateHours(date1 , expireTime){
const dateOne = date1;
const dateTwo = new Date();
const dateOneObj = new Date(dateOne);
const dateTwoObj = new Date(dateTwo);
const hours = Math.abs(dateTwoObj - dateOneObj)/ 36e5;
const minutes = hours/ 36e5;
return expireTime > hours ? true : false
}
Code for defining the 15 minute timeout currently.
if(this.calculateHours(localStore.time , 15)){
this.wrappedClickHandler()
This is for a 15 minute timeout, but the code is really sloppy and ugly and I was wondering if anyone has a better way of implementing this?
Unless you use a library to handle time, it is not so easy to get better code: You can do some better naming, but the operation is similar:
const isExpired = (startDate, minutes) => {
startDate = startDate instanceof Date ? startDate : new Date(startDate)
const diff = new Date() - new Date(startDate)
const minutesDiff = Math.floor((diff/1000)/60);
return minutesDiff >= minutes
}
You can use setTimeout. The function will execute after a given time
setTimeout(() => {
...your necessary code for requiring user to enter username & password...
}, 15 * 60 * 1000) // since time is to be written in milliseconds
When dealing with time, I always use epochMilli.new Date().getTime() then plus 15 minutes is (15*60*1000) milliseconds to be epochExpiresAt kept somewhere(redux?) And then you use the isExpired Function to check every time user click save.
const isExpired = (epochExpiresAt) => epochExpiresAt > new Date().getTime()

How to make a command time counter

My question is: how can I make a command clock (when you execute !count and after 4 minutes you type !time and it says 4 minutes!) in discord.js
const Discord = require('discord.js');
exports.run = (client, message) => {
var af = 0;
a = setInterval(function(){
console.log("Hi");
af = af+1;
if(af == 25){
clearInterval(a);
}
console.log(af);
}, 60000);
};
exports.help = {
name: 'time',
description: 'time?',
usage: 'time'
};
I would do it like this: when you execute !count you save the server time, when you execute !time you send back the difference between those two dates.
Pseudo-code:
var date;
if (command == 'count') {
date = new Date();
message.reply("Done");
}
if (command == 'time') {
let result = require('pretty-ms')(date ? (new Date() - date) : 0);
message.reply(result);
}
I'm using the pretty-ms npm package to format milliseconds: docs & live demo.
When someone calls !count, store the current Date somewhere. new Date() - date will give you the difference between the current time and the time you stored, in milliseconds.
Please note that if the commands are in different files, as it seems by the code you posted, you'll need to store the date in a location accessible to both files: one of the solutions is to store the date as a global variable.
// by '...' I mean that you can put it wherever you want in the global object
global['...'].date = new Date():
new Date() - global['...'].date
Edit: Date class explanation
When you create a new Date, it saves the time at the moment you create it. It's like saying "!count was executed at 04:20". When you want to check how much time has passed, you need to calculate the first date minus the current date: "!count was executed at 04:20. Now it's 05:40, so the difference is 05:40 - 04:20 = 01:20: it's 1 hour and 20 minutes since you first executed !count". That translates to new Date() - past_date = time_passed.
Since dates are stored in milliseconds that difference is in milliseconds: if you want to make it more readable, you can format it by using a function as the 'pretty-ms' package, or similar ones.
The key concept is:
When !count is called, you save a new Date() to lock that point in time
When !time is called, you get the difference by doing new Date() - past_date

Resources