How to perform an action after 24h? (not using setTimeout) - javascript

I have a Discord bot that has a punish command, and I want to make the bot remove the punishment after 24 hours/1 day. Don't want to use setTimeout() because the bot can go down between that period and setTimeout() consumes resources. How to do that? Thank you.

upon punishment, a variable can be assigned as Date.now()+86400000. When they log in and the current Date is greater than this value, the ban will end.

You can do this without timers. When you ban the user, just mark their user object (in whatever persistent store you use for user accounts) with a date/time that the ban ends. Then, log them out.
Then, on every login request, check the user object to see if they have a ban time and if the current time has passed the ban time. If not, fail their login (don't let them in). If so, remove the ban time from the user object as the ban is now over and they can now login in.

Related

Make setTimeout() work after closing and opening an application

So atm I'm working on a Discord.js bot and have a command to ban people. The issue is if I turn the bot off and on again all the setTimeouts reset. So say, if I were to ban someone for a week, turn the bot off and on in between there, they will never automatically be unbanned.
setTimeout(function () {
memberTarget.roles.remove(bannedRole);
}, ms(args[1]));
What other way could I use for it to remember to unban everyone after the bot has been turned on again?
You need to use database or data persist
Store bans data to database/data persist then set worker to check for unban (expiry).
Database https://www.tutorialsteacher.com/nodejs/data-access-in-nodejs
Data Persist https://www.npmjs.com/package/node-persist

How to get all users with a role in Discord.js in a array

I am trying to get all the members with a certain role. For example, there is role of gurdian in my discord server with a id of 872029521484873779. I want a list of all the users Name in a array who have gurdian as a role in my server. My code is as below
let nameList= msg.guild.roles.cache.get('role_id').members.map(m=>m.user.tag);
However, In result it only returns one user in the nameList whereas as there are 9 users with the role assigned to them. What am I doing wrong here which is bringing me only 1 user not the rest of 9 users in a list in array. I am new to discord.js
This is happening because the members aren't cached. So you only see 1 person logging because only 1 person is in the cache. To fix this, you can fetch all members by doing msg.guild.members.fetch(), then use msg.guild.roles.cache.get("roleid").members.map(m => m.user.tag) to get the real output. Please do note that you will need the GUILD_MEMBERS intent if you are on v13.
Fetching members from the guild will store them in cache. So when you do do role.members, you get the members who have this role.
If you don't fetch members, then the info won't be accurate. Discord.js stores users in cache. This happens whenever someone sends a message, updates their profile or anything about themselves WHILE the bot is online. So if you restart your bot, no one will be in the cache.
Why is fetch different from cache?
Fetch gets the info directly from discord, while cache is checking if the user is stored locally. When you fetch members, they are automatically stored in the cache as well.
Your mistake might be a simple confusion with the id numbers. The number in your code is different then the number in your question

is there a way to save reaction role data?

I've currently got reaction roles set up in my code and they work, however I have to rerun the command every time I restart the bot, which isn't optimal.
Is it possible at all to cache the data so that there is only one reaction role message and the roles are given out regardless of how many times the bot has rebooted?
Any help with this is greatly appreciated!
in order to do this you need to have a database setup and store the message's id.
Then when your bot starts you can fetch that message inside messageReactionAdd/messageReactionRemove client event(s) and track for reactions on the message id you have previously stored.

Is setTimeout the right option for scheduling tasks spanning days?

I am creating a user management system. There's an option for moderators to block users for a specific number of days. After receiving a block request, the disabled attribute for the user is set to true in the database. After the specified duration passes, the value is set back to false. The duration may range from 1 - 10 days. Is setTimeout() the right choice? Will it be cpu intensive if run for many users simultaneously?
Here's the function from my program. The complete program uses express as a server and mongoose to interact with the mongodb database.
function disableUser(req,res) {
let username = req.body.username;
let app = req.body.app;
let duration = req.body.duration;
let reason = req.body.reason;
User.find({username:username}).then((result) => {
let user = result[0];
user.disabled = true;
user.save().then((user) => {
disableMail(app, user.email, duration, reason); //send mail to user
// schedule a task to set user.disabled to false after the duration
}, (err) => {
res.status(500).send(err);
});
}, (err) => {
res.status(500).send(err);
});
}
EDIT :
Seeing all the comments and answers, I think I'll implement something like this : store the end date of the ban (calculated using something like momentjs) along with the disabled attribute. A setInterval will run separately and check the date every 12 hours for all the users with disabled set to true. If the end_date matches the current date, the disabled attribute will be set to false.
A setTimeout() set for several days from now will work and it's not hardship on the server (even if you have a lot of them), but it's still probably not the right design choice for the following reasons:
setTimeout() is only good for the duration of your server running. As soon as your server restarts for any reason (crash, planned maintenance, etc...), the setTimeout() is gone so even if you did use a setTimeout() you'd have to use a more durable means of storage anyway so you could restore all the timers on a server restart.
You don't need ms timing. A multi-day ban can be removed hourly or even daily.
My suggestion is that instead of a timer, you run some periodic process that could be run once an hour that does a query to find any banned users whose ban has expired. You will want to store the ban and the ban duration in the database in a way that makes this query efficient (perhaps in a separate table of banned users). Then, you can run this query once an hour, remove the user from the banned table and then re-enable the "disabled" user attribute for those users whose ban has expired.
This type of design should meet all your objectives, is a durable way of storing the ban and can be implemented efficiently.
Using setTimeout is probably impractical for a few reasons. First, you are correct that it would be intensive, especially if you have a lot of blocked users. Second, it wouldn't survive a server restart, which may occur because you are pushing new code.
If you go with some automated background task, then consider:
You probably want to check if the user is blocked on all API calls and form submissions at the server-side. This could be part of your general security/permission checks on write calls.
You'll need some error handling in the UI whenever a banned user's API call is rejected.
You may want some background task that executes like once a minute and checks for blocked users and expires the ban when appropriate. A chron type job, or quartz (if Java), or something similar if on Node, can run the query and perform the updates.

How can I have list of all users logged in and choose kill your cookie/session in Express/NodeJS?

how can i have a list of all users logged in my webapp ?
I have a login and need know how many people are logged, and if I want kill a cookie/session from their... What is the best way?
Kind Regards
i ll try to give you an example as simple as possible.
-> create a session table in your db
-> when the user logs in generate a new session entry it can be as simple as an object with (token, username). (for simplicity reasons i ll assume that sessions last forever until the user logs himself out)
-> now you are able to count how many entries you have in that table, this will give you the desired information of how many people are logged in.
-> now for the second part, you can request the user to send you the token with every request he makes, and you match the token against the db and verify if it checks.
-> when you want to kill a session just go into your table and delete that specific entry you are looking for, the next time the user makes a request his token will no longer be in the db and you can say "he is no longer logged in" , the same applies when the user log himself out.

Categories

Resources