How can I send a message every day at a specific hour? - javascript

I'm trying to make the bot writing messages at specific times. Example:
const Discord = require("discord.js");
const client = new Discord.Client();
client.on("ready", () => {
console.log("Online!");
});
var now = new Date();
var hour = now.getUTCHours();
var minute = now.getUTCMinutes();
client.on("message", (message) => {
if (hour === 10 && minute === 30) {
client.channels.get("ChannelID").send("Hello World!");
}
});
Unfortunately, it only works once I trigger another command like:
if (message.content.startsWith("!ping")) {
message.channel.send("pong!");
}
my message: !ping (at 10:10 o'clock)
-> pong!
-> Hello World!
I guess it needs something that constantly checks the time variables.

I would use cron: with this package you can set functions to be executed if the date matches the given pattern.
When building the pattern, you can use * to indicate that it can be executed with any value of that parameter and ranges to indicate only specific values: 1-3, 7 indicates that you accept 1, 2, 3, 7.
These are the possible ranges:
Seconds: 0-59
Minutes: 0-59
Hours: 0-23
Day of Month: 1-31
Months: 0-11 (Jan-Dec)
Day of Week: 0-6 (Sun-Sat)
Here's an example:
var cron = require("cron");
function test() {
console.log("Action executed.");
}
let job1 = new cron.CronJob('01 05 01,13 * * *', test); // fires every day, at 01:05:01 and 13:05:01
let job2 = new cron.CronJob('00 00 08-16 * * 1-5', test); // fires from Monday to Friday, every hour from 8 am to 16
// To make a job start, use job.start()
job1.start();
// If you want to pause your job, use job.stop()
job1.stop();
In your case, I would do something like this:
const cron = require('cron');
client.on('message', ...); // You don't need to add anything to the message event listener
let scheduledMessage = new cron.CronJob('00 30 10 * * *', () => {
// This runs every day at 10:30:00, you can do anything you want
let channel = yourGuild.channels.get('id');
channel.send('You message');
});
// When you want to start it, use:
scheduledMessage.start()
// You could also make a command to pause and resume the job

As Federico stated, that is the right way to solve this problem but the syntax has changed and now with the new update of discord.js (v12) it would be like:
// Getting Discord.js and Cron
const Discord = require('discord.js');
const cron = require('cron');
// Creating a discord client
const client = new Discord.Client();
// We need to run it just one time and when the client is ready
// Because then it will get undefined if the client isn't ready
client.once("ready", () => {
console.log(`Online as ${client.user.tag}`);
let scheduledMessage = new cron.CronJob('00 30 10 * * *', () => {
// This runs every day at 10:30:00, you can do anything you want
// Specifing your guild (server) and your channel
const guild = client.guilds.cache.get('id');
const channel = guild.channels.cache.get('id');
channel.send('You message');
});
// When you want to start it, use:
scheduledMessage.start()
};
// You could also make a command to pause and resume the job
But still credits to Federico, he saved my life!

Related

How to schedule a function to run at a certain date?

I have a website that allows users to send themselves a message at a date they choose, but I have no idea how to send it at that specific time. I know there exist CronJobs, but here, I'm not doing anything recurring. It's a one-time event trigger that I need.
I first tried using the native setTimeout like this:
const dueTimestamp = ...;
const timeLeft = dueTimestamp - Date().now();
const timeoutId = setTimeout(() => sendMessage(message), timeLeft);
It works perfectly for short periods, however, I'm not sure if it is reliable for long periods such as years or even decades. Moreover, it doesn't offer much control because if I'd like to modify the dueDate or the message's content, I'd have to stop the Timeout and start a new one.
Is there any package, a library, or a service that allows you to run a NodeJS function at a scheduled time? or do you have any solutions? I've heard of Google Cloud Schedule or Cronhooks, but I'm not sure.
You can use node-schedule library. for example :
you want to run a funcation at 5:30am on December 21, 2022.
const schedule = require('node-schedule');
const date = new Date(2022, 11, 21, 5, 30, 0);
const job = schedule.scheduleJob(date, function(){
console.log('The world is going to end today.');
});
As recommended by user3425506, I simply used a Cron job to fetch the messages from a database and to send the message of those whose timestamps have passed.
Dummy representation:
import { CronJob } from "cron";
import { fakeDB } from "./fakeDB";
const messages = fakeDB.messages;
const job = new CronJob("* * * * * *", () => {
const currentTimestamp = new Date().getTime();
messages.forEach((message, index) => {
if (message.timestamp > currentTimestamp) return;
console.log(message.message);
messages.splice(index, 1);
});
});
job.start();

setInterval Not Repeating Function using Discord.js

I'm trying to make a discord bot that gives you weekly reminders. Im using momentjs to get the time. As well as using discord.js-commando. I found the best way to call a function multiple times is to use setInterval.
const moment = require('moment');
const Commando = require('discord.js-commando');
const bot = new Commando.Client();
bot.on('ready', function () {
var day = moment().format('dddd');
var time = moment().format('h:mm a');
function Tuesday() {
if (day == 'Tuesday' && time == '6:30 pm') {
const channel = bot.channels.get('933047404645724234');
console.log('Sending Message');
channel.send('Reminder: You have a week to complete your To-Do List!');
} else {
console.log('Not Sending Message');
}
}
console.log('Bot is now ready!');
setInterval(Tuesday, 100);
});
I noticed the problem with the setInterval is that it is only called once. I also tried using an async function but that failed as well.
Well executing a function every 100ms is not quite optimal. I don't know what is the reason to run just once (it should run infinitely) but there is a better way to do what you need.
You will need the package called "node-schedule". It's really useful for such things.
Here's an example:
const schedule = require("node-schedule");
schedule.scheduleJob({hour: 18, minute: 30, dayOfWeek: 2}, function(){
// your code here
});
You can read more in the documentation of node-schedule here.

Auto delete messages in the specified channel by time? Discord.js

I did an automatic-channel cleaning at the time I needed (Monday 15:00)
But my program does not work as it should.
The countdown starts when a message appears in the channel.
I need the channel to be cleared without new messages in channel.id
CODE
const schedule = require("node-schedule");
client.on("message", async (message) => {
if (client.channels.cache.get("829042005236645900")) {
const job = schedule.scheduleJob('30 * * * * *', function () {
console.log('Delete');
message.channel.bulkDelete(20)
});
}
});
It looks like you're creating the schedule inside the event handler, and that may be what's causing the issue. Here's an alternative to that:
const schedule = require("node-schedule");
const channel = client.channels.cache.get("829042005236645900");
const job = schedule.scheduleJob('30 * * * * *', function () {
console.log('Delete');
channel.bulkDelete(20);
});
However, it also looks like you want to make the event fire every 30 seconds? node-schedule has a system for that called Recurrence Rule Scheduling:
const schedule = require("node-schedule");
const channel = client.channels.cache.get("829042005236645900");
const job = new schedule.scheduleJob({ second: new schedule.Range(0, 59, 30) },
function () {
console.log('Delete');
channel.bulkDelete(20);
});

Request to use token, but token was unavailable to the client. - DiscordJS Error

I'm trying to make a bot that sends a message every day at 5 am EST so I'm trying to create a Cron job. This is what I have but every time I run it, it sends a message straight away instead of the time I want it to send at. Here's my code. I have it at 5 am in the code but I change the time when I'm testing it out.
Thank you.
const e = require('express')
const client = new Discord.Client()
const config = require('./config.json')
const privateMessage = require('./private-message')
const cron = require('node-cron');
const express = require('express');
client.on('ready', () => {
console.log('running');
})
cron.schedule('0 5 * * *', function() {
console.log('cron is working');
}, {
scheduled: true,
timezone: "America/New_York"
});
client.login(config.token).then(() => {
console.log('sending');
client.users
.fetch('749097582227357839').then((user) => {
user.send(`hello`,);
})
console.log("nope");
client.destroy();
});
client.login(config.token)
You have two client.login functions for some reason, please remove the first one.
You dont seem to use cron in the correct way - the cron.schedule function is where you put the code to repeat, not below it.
That is why your bot is sending the message immediately - the code is simply doing what you are asking it to do right after it schedules a cron job.
If you have everything else correct, your bot will actually log cron is working to the console at 5am every morning with your current code - the below code should achieve what you need.
To sum up:
//declare packages here
cron.schedule('0 5 * * *', function() {
console.log('sending');
client.users.fetch('749097582227357839').send('hello');
}, {
scheduled: true,
timezone: "America/New_York"
});
client.login(config.token); //only ever use one of these events, it causes issues if you use multiple
there is also no need to do client.destroy - it shouldn't make any difference

Cool down discord.js

Here is my code, I want it to send a message if the command has been used twice within like 10 seconds. Idk but it is very wrong
var bumpEmbedTwo = new Discord.MessageEmbed()
.setTitle('Cool Down!!!')
.setColor(0xFF0000)
.setDescription('Please waitt 30 more seconds before you use this command again')
setTimeout(() => {
message.channel.send(bumpEmbedTwo)
}, 5000)
var bumpEmbed = new Discord.MessageEmbed()
.setTitle('Time to Bump!')
.setColor(0xFF0000)
.setDescription('Please use the command `!d bump` to bump the server!!!')
setTimeout(() => {
message.channel.send('<#&812133021590880316>')
message.channel.send(bumpEmbed)
}, 1000)
The code you have provided isn't correct as your doing a set timeout without an await so it would completely ignore the purpose of the timeout. Also, whenever the .on('message') function is used, it would still carry out the command, what you have to do is to create an object: const cooldowns = new Discord.Collection(); and whenever the 'message' event is triggered, you would have to add whatever amount of cool down you want.
So here's the code:
const now = Date.now();
let cooldownAmount = 5 * 1000; // In this case, it is 5 seconds
if (cooldowns.has(message.author.id)) {
const expirationTime = cooldowns.get(message.author.id) + cooldownAmount;
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
return message.channel.send(`Please wait ${timeLeft.toFixed(1)} more second(s) before using another command`);
}
}
if(!cooldowns.has(message.author.id)){
<command>.run() // Be sure to edit <command to whatever the fetched command is> and add to the (), e.g. message, args, bot, etc.
}
cooldowns.set(message.author.id, now);
setTimeout(() => cooldowns.delete(message.author.id), cooldownAmount);
PS: the client in the arrow symbols are for you to change.
If there are any extra questions, you can comment in this post! Or dm me on discord: N̷i̷g̷h̷t̷m̷a̷r̷e̷ ̷ Jeff#2616
One way to approach this problem would be to save user+command+time in DB or in some global variable.
And then perform a check.
Pseudo-code:
var storage = {
"/command": {
"user-id-123": "22/02/2021 5:27pm"
"user-id-345": "22/02/2021 3:12pm"
}
};
Chat.on("/command", (user) => {
if (!storage["/command"].hasOwnProperty(user.id)) {
storage["/command"][user.id] = Date.now();
}
if (storage["/command"][user.id] > Date.now() + 10 seconds) {
return "Please wait more";
} else {
return "I'm running your command";
}
});

Categories

Resources