Time Counter Script discord.js - discord

I sucessfully did a time count script. The only problem i ran into is when two people are starting the time count (not at the same time) that the script ignores the time from the first person and it's only counting the time for the second person. When either one of them stops the time count it only shows the time from the last person that started the count and i wanna change that but i don't know how.
case 'start':
date = new Date();
message.channel.send(`<#!${message.author.id}> started the time count, don't forget to stop it! `)
break;
case 'stop':
let result = require('pretty-ms')(date ? (new Date() - date) : 0);
message.channel.send(`<#!${message.author.id}> stopped the time. His time was ` + result)
break;

You have to save the property to the User itself. Whenever the cached user is accessed, that property will be accessed with it. Simply change date to message.author.date
case 'start':
message.author.date = new Date();
message.channel.send(`<#!${message.author.id}> started the time count, don't forget to stop it! `)
break;
case 'stop':
let result = require('pretty-ms')(message.author.date ? (new Date() - message.author.date) : 0);
message.channel.send(`<#!${message.author.id}> stopped the time. His time was ` + result)
break;
This can also be done to the GuildMember object (message.member) to let the same user do this in different guilds!

To save different time for different users and make counter work for both you have to change date to message.author.date and get such code:
case 'start':
message.author.date = new Date();
message.channel.send(`<#!${message.author.id}> started the time count, don't forget to stop it! `)
break;
case 'stop':
let result = require('pretty-ms')(message.author.date ? (new Date() - message.author.date) : 0);
message.channel.send(`<#!${message.author.id}> stopped the time. His time was ` + result)
break;

Related

I am receiving a TypeError: cannot read properties of null (reading 'push') for a clock in/out schedule

I am a new dev taking over for another developer at work and I am also a solo dev as they were, I am using react as my code base and we had 6 weeks worth of turnover before they left and as time goes on, I realize how little knowledge was passed along to me. This is my first job but I am not looking for sympathy points, just the best way to ask questions and how to find the right questions I am looking for.
The code has not been touched for after I completed it, but now I keep getting this errors where it worked before. I dont currently know if its because my Twilio trial period has ended or if its another issue. I have troubleshot this code from my knowledge (which isnt much) but I am not sure where else to get answers from.
the code I am currently getting the error from
SendTextMessage(_type, _work_time, _notes, _week, _month) {
debugger;
let month = ["Jan.", "Feb.", "Mar.", "Apr.", "May.", "Jun.", "Jul.", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."];
let msgList = JSON.parse((this.props.lists).MsgTo);
msgList.push(this.props.user.phoneNumber);
let date = "";
let mobileModeSend = msgList;
let workTime = `Last Worked ${_work_time}.`;
if(this.state.fridayTime !== null){
date = FormatDateTime(new Date());
if (_type === "Punching Out") {
workTime = `Worked for ${_work_time}. \n` +
`Total time worked this week: (${_week}). \n` +
`Total time worked since ${month[(new Date()).getMonth()]} 1st (${_month}).`;
}
} else {
date = FormatDateTime(new Date());
if (_type === "Punching Out") {
workTime = `Worked for ${_work_time}. \n` +
`Total time worked this week: (${_week}). \n` +
`Total time worked since ${month[(new Date()).getMonth()]} 1st (${_month}).`;
}
}
`Total time worked this week: (${_week}). \n`
let msg = `${this.props.user.fullName} \n` +
`${_type} \n` +
`${ date } \n` +
`${workTime} \n\n` +
`${_notes} \n`;
for (let i = 0; i < mobileModeSend.length; i++) {
const mobileModeMsg = {
body: `Time Entry \n ${msg}`,
to: mobileModeSend[i],
from: `Auto Msg`,
time: CurrentTime(),
type: 'admin'
};
$.post('/api/send_message_async',{messages: mobileModeMsg},(response) => {})
}
}
I have ran the debugger to test all of the following that I am aware of how to do.
ran the debugger for the line it said it was having the issue.
1-1. it returns null when I step over the line and when I console log the data
added an empty array with the msgList name to pull from to see if it needed that first, but that returned the same issue and I didnt need it when it was working from before.
I restarted the servers and FTP instances that have been connected to see if the upload had an issue, I reset the instance and launched it again. This cleared some other issues up but this one still remains.
before the " let msgList = JSON.parse((this.props.lists).MsgTo);" line, if you console out this.props.lists what do you get?
Where is lists populated?

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.

React function generating available time slots doesn't generate the correct time slots

Hi I want to make a function that generates available time slots. It should generate the time slots while keeping in mind that the time slot can't overlap with an already made appointment.Before the time slots are generated a user can specify which kind of appointment to schedule. Each appointment sort has a duration. So it should also check if the time slot added with the duration doesn't overlap.
I'm struggling to make this all working so far I get time slots but it seems to only checks the start of an already made appointment. I'm kind of running in circles here and would love for some advice or part solutions that I can implement to make my idea work
const GenerateAvailableTimeSlots = (start, serviceObject, allAppointments) => {
const moment = extendMoment(Moment);
var x = {
nextSlot: 15,
appointmentsOfThatDay: [],
startTime: '8:00',
endTime: '20:00'
};
// function to filter only the appointment that occur on specified day --> ( start )
let filterAppointments = (allAppointments, start) => {
let results = [];
let filterAppoinments = allAppointments.filter(appoinment => appoinment.date === start.format('MMMM Do YYYY'));
filterAppoinments.map(appoinment => results.push([appoinment.start.format('HH:mm'), appoinment.end.format('HH:mm')]))
console.log("results", results);
return results;
};
x.appointmentsOfThatDay = filterAppointments(allAppointments, start)
console.log("appointmentsOfThatDay", x.appointmentsOfThatDay)
var slotTime = moment(x.startTime, "HH:mm");
var endTime = moment(x.endTime, "HH:mm");
// function to check time slot overlaps with already made appointments
function OverlapsScheduledAppointment(slotTime, appointments) {
//added duration to timeslot so I could check if a suggested timeslot + the duration also doesn't overlap with already made appointment
var slotTimeWithDuration = slotTime.clone().add(serviceObject.hours, 'hours').add(serviceObject.minutes, 'minutes');
// I don't know where I also could check for slotTimeWithDuration overlap
return appointments.some((br) => {
console.log(slotTime >= moment(br[0], "HH:mm") && slotTime < moment(br[1], "HH:mm"));
return (slotTime >= moment(br[0], "HH:mm") && slotTime < moment(br[1], "HH:mm"));
});
}
let times = [];
while (slotTime < endTime) {
if (!OverlapsScheduledAppointment(slotTime, x.appointmentsOfThatDay)) {
times.push(slotTime.format("HH:mm"));
}
slotTime = slotTime.add(x.nextSlot, 'minutes');
}
return times;
};
I've found the answer to my question.
I was going in the right direction with the above code but in order for generating available time slots that keep in mind the duration of the service you want to schedule and the appointment that are already scheduled.
I had to change this line of code:
// this line just pushes the filtered appointment for a specific day
filterAppoinments.map(appoinment => results.push([appoinment.start.format('HH:mm'), appoinment.end.format('HH:mm')]))
To this
// this line filters the appointment for a specific day and also adds the duration of a service to the start time of an already scheduled appointment. This way when I check if a generated time slot for a service will overlap with an already scheduled appointment it filters out the ones that will overlap
filterAppoinments.map(appoinment => results.push([appoinment.start.clone().subtract(serviceObject.hours, 'hours').subtract(serviceObject.minutes, 'minutes').format('HH:mm'), appoinment.end.format('HH:mm')]))

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

Enable a button everyday at particular time(2 am) in angular js

I have a todo list with a 'done' button with each todo. Once the 'done' button is clicked by the user, it will be disabled. The button should be enabled at 2 am everyday.
I could disable the button, but i am unable to enable it at 2 am. Here is my code.
$scope.doneItem = function(todo) {
todo.stopSpam = true;
$interval(callAtInterval, 3000);
function callAtInterval(){
var date = new Date();
if (date.getHours() === 2 && date.getMinutes() ===0){
todo.stopSpam = false;
}
}
};
Based on the fact that you're trying to do this with intervals, I'm going to assume you're going to be leaving the page with your app up. What you do in your example technically can work, but only if the interval falls exactly on 2 AM (ignoring seconds and milliseconds). The easiest accurate way I can think of is to just do a quick calculation of the interval between "now" and 2 AM.
var date = new Date(); //This gets the current date and time
var timeInterval = new Date(date.getFullYear(), date.getMonth(), date.getDate()+1,2)-date;
//This gets the difference between the time and 2 AM the next day.
//Now you can make an accurate interval call
$interval(callAtInterval, timeInterval);
This way will limit it to 2:00 AM the next day. If, however, for 1 AM you didn't want to skip that day's 2 AM to enable it, you'd make one more quick check.
var timeInterval;
if(date.getHours()>2)
timeInterval = new Date(date.getFullYear(), date.getMonth(), date.getDate(),2)-date;
else
timeInterval = new Date(date.getFullYear(), date.getMonth(), date.getDate()+1,2)-date;

Resources