Search code examples
node.jsdiscorddiscord.jsscheduled-tasks

Discord JS Scheduled events


I am trying to make a discord bot that will scrape a group google calendar and remind people of upcoming events. I can get the calendar data no problem. Thing thing I don't understand is how to send a scheduled message on a discord server via discord js. This won't be a set time because it will change based on the start time of the calendar event. I'm trying to read the documentation for the GuildScheduledEvent here. But, I can't seem to figure it out/how to implement it.

I've already tried doing it from a cron task but that won't work because the event time is subject to change.

What I have so far is just a bot that will send messages when I run the script. I would really like to have it be automatic via a scheduled event.

let upcomingEvents = []; //array of calendar events

const gcpClient = authorize().then(listEvents); //getting the calendar data


const client = new Client({ intents: [GatewayIntentBits.Guilds]});


client.once(Events.ClientReady, c => {
    console.log('Ready! Logged in as ', c.user.tag);
    const channel = client.channels.cache.get('1049384497017266228');
    upcomingEvents.forEach(element => {
        channel.send(`${element.title} on ${element.readabledate}`);
    });
})

client.login(TOKEN);

Again, I don't really know how to implement the Scheduled event logic.

Any help would be greatly appreciated.


Solution

  • As far as I understand the class ScheduledEvent doesn't represent what you need, it's for guild events like the ones explained here: https://support.discord.com/hc/en-us/articles/4409494125719-Scheduled-Events

    What you need is the 'cron'-package from npm (https://www.npmjs.com/package/cron). I modified your code to schedule a message for each upcomingEvents entry.

    var CronJob = require('cron').CronJob;
    let upcomingEvents = []; //array of calendar events
    const gcpClient = authorize().then(listEvents);
    const channel = client.channels.cache.get('1049384497017266228');
    
    // method to convert date values to cron expressions
    const dateToCron = (date) => {
        const minutes = date.getMinutes();
        const hours = date.getHours();
        const days = date.getDate();
        const months = date.getMonth() + 1;
        const dayOfWeek = date.getDay();
    
        return `${minutes} ${hours} ${days} ${months} ${dayOfWeek}`;
    };
    
    function scheduleMessage(cronExpression, msgToSend) {
            var job = new CronJob(
            cronExpression, // cron expression that describes when the function below is executed
            function() {
              channel.send(msgToSend); //insert here what you want to do at the given time
            },
            null,
            true,
            'America/Los_Angeles' //insert your server time zone here
      );
    }
    
    client.once(Events.ClientReady, c => {
       console.log('Ready! Logged in as ', c.user.tag);
       upcomingEvents.forEach(element => { scheduleMessage(element.title, element.readabledate) });
    });
    
    client.login(TOKEN);
    

    To get the correct cron expressions for each date value you need to convert it first, as answered in this post: https://stackoverflow.com/a/67759706/11884183

    You might need to adjust some things like time zone and cronjob behavior.

    If you want to keep the created cronjobs up to date you can delete them and recreate them in intervals