'I need to apply a 24hour cooldown after use, and add to the token balance on a correct answer (discord.js v13)

Here is the challenge bot slash command:

const {
    SlashCommandBuilder
} = require('@discordjs/builders');
const {
    MessageEmbed,
    MessageAttachment,
    Role
} = require('discord.js');
const {
    $where
} = require('../../schemas/balance');
const Challenge = require('../../schemas/challenge');
const challenges = require('./challenges.json');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('challenge')
        .setDescription('Get your DAILY Fortune! Challenge and progress through the server!'),

    async execute(interaction, message) {
        const item = challenges[Math.floor(Math.random() * challenges.length)];
        const filter = response => {
            return response.author.id === interaction.user.id;
        };

        interaction.reply({
                content: `${item.question}`,
                ephemeral: true
            })
            .then(() => {
                interaction.channel.awaitMessages({
                        filter,
                        max: 1,
                        time: 30000,
                        errors: ['time']
                    })
                    .then(collected => {
                        const response = collected.first().content;
                        collected.first().delete();
                        if (item.answers.includes(response.toLowerCase())) {
                            interaction.followUp({
                                content: `${collected.first().author} got the correct answer!`,
                                ephemeral: true
                            });
                            console.log("Challenge Answered Correct");
                            var guild = message.guilds.cache.get('948892863926771722');
                            var role = guild.roles.cache.find(role => role.name === 'Fortune Hunters');
                            var member = guild.members.cache.get(collected.first().author.id);
                            member.roles.add(role);
                        } else {
                            collected.first().delete();
                            interaction.followUp({
                                content: `Looks like you missed the answer this time, come back tomorrow for another chance to find your Fortune! with our daily challenges!`,
                                ephemeral: true
                            });
                            console.log("Challenge Answered Incorrectly");
                        }
                    })
                    .catch(collected => {
                        interaction.followUp({
                            content: 'You ran out of time!',
                            ephemeral: true
                        });
                        console.log("Timed Out");
                    });
            });
    },
};

And then I have the database setup but I'm not sure how to link it up how I did for the balance command. I think I set it up right, I made clones of the balance stuff and renamed it challenge which brought me up to the implementation into the actual command.

SCHEMA:

const mongoose = require('mongoose');
const challengeSchema = new mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    guildId: String,
    memberId: String,
    amount: {type: Number, default: 0 },
    correctAnswers: {type: Number, default: 0 },
    wrongAnswers: {type: Number, default: 0 },
    dateLastAnswered: { type: Date, default: Date.now },
});

module.exports = mongoose.model('Challenge', challengeSchema, 'challenges');

And then there's the createChallenge function:

const Balance = require('../schemas/challenge');
const mongoose = require("mongoose");

module.exports = (client) => {
    client.createChallenge = async (member) => {
        let challengeProfile = await Challenge.findOne({ memberId: member.id, guildId: member.guild.id });
        if (challengeProfile) {
            return challengeProfile;
        } else {
            challengeProfile = await new Challenge({
                _id: mongoose.Types.ObjectId(),
                guildId: member.guild.id,
                memberId: member.id,
            });
            await challengeProfile.save().catch(err => console.log(err));
            return challengeProfile;
            console.log('The Challenge Database is live!');
        }
    };
};

I know the database is setup, because for the /balance command in mongo I can see the balances being updated with the user IDs and all that information. Here is what I have for the balance slash command:

const { SlashCommandBuilder } = require('@discordjs/builders');
const Balance = require('../../schemas/balance');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('balance')
        .setDescription('Returns info based on a user\'s balance.')
        .addSubcommand(subcommand =>
            subcommand
                .setName("user")
                .setDescription("Gets information of a user mentioned")
                .addUserOption(option => option.setName("target").setDescription("The user mentioned"))),
    async execute(interaction, client) {
        let user = (interaction.options.getUser("target") ? interaction.options.getUser("target") : interaction.user);
        const balanceProfile = await client.createBalance(interaction.member);
        await interaction.reply({ content: `${interaction.user.tag} has ${balanceProfile.amount}$FP.`});
    },
};

The balance schema:

const mongoose = require('mongoose');
const balanceSchema = new mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    guildId: String,
    memberId: String,
    amount: {type: Number, default: 0 }
});

module.exports = mongoose.model('Balance', balanceSchema, 'balances');

Create balance function:

const Balance = require('../schemas/balance');
const mongoose = require("mongoose");

module.exports = (client) => {
    client.createBalance = async (member) => {
        let balanceProfile = await Balance.findOne({ memberId: member.id, guildId: member.guild.id });
        if (balanceProfile) {
            return balanceProfile;
        } else {
            balanceProfile = await new Balance({
                _id: mongoose.Types.ObjectId(),
                guildId: member.guild.id,
                memberId: member.id,
            });
            await balanceProfile.save().catch(err => console.log(err));
            return balanceProfile;
        }
    };
};

I hope all this information is helpful enough for someone to help... I've been struggling with this for about 9 hours now and it's killing me. I can't figure it out and we need to have this bot live this weekend. Any assistance you can give, I would greatly greatly appreciate! Like I mentioned what I'm trying to do is use the mongoDB database to store when someone does the /challenge command so that I can limit the command to being once per day, and assign an $FP balance reward with the reward role being given after 3 correct answers instead of just the first one.



Solution 1:[1]

Hey If your looking to schedule tasks please try this npm package https://www.npmjs.com/package/cron

It will help.

const today = new Date();
  const dd = String(today.getDate()).padStart(2, "0");
  const mm = String(today.getMonth() + 1).padStart(2, "0");
  const day = today.getDay();

  cron.schedule(`30 30 23 ${dd} ${mm} ${day}`, async () => {
    await IssuesModel.markIssuesAsOverdue();
  });

There is an example how I used it to mark issues in my app as overdue at the middle of the night.

Solution 2:[2]

I have since been able to solve this issue. Here is the finished code, now I just have to create the event handler that will assign a new addition to the balance when someone gets a correct answer:

const {
    SlashCommandBuilder
} = require('@discordjs/builders');
const {
    MessageEmbed,
    MessageAttachment,
    Role
} = require('discord.js');
const {
    $where
} = require('../../schemas/balance');
const Challenge = require('../../schemas/challenge');
const challenges = require('./challenges.json');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('challenge')
        .setDescription('Get your DAILY Fortune! Challenge and progress through the server!'),

    async execute(interaction, message) {
        const item = challenges[Math.floor(Math.random() * challenges.length)];
        const filter = response => {
            return response.author.id === interaction.user.id;
        };
        let user;

        try {

            //check if user has a challenge
            user = await Challenge.findOne({
                guildId: interaction.guild.id,
                memberId: interaction.user.id
            });

            if (user) {
                if (user.dateLastAnswered >= Date.now() - 86400000) {
                    let time = 86400000 - (Date.now() - user.dateLastAnswered);
                    let timeString = "";
                    if (time > 3600000) {
                        timeString = `${Math.floor(time / 3600000)} hours, `;
                    }
                    if (time > 60000) {
                        timeString = `${timeString}${Math.floor((time % 3600000) / 60000)} minutes, `;
                    }
                    if (time > 1000) {
                        timeString = `${timeString}${Math.floor((time % 60000) / 1000)} seconds`;
                    }

                    interaction.reply({
                        content: `You have already claimed and answered your challenge for the day!\n\nBe sure to come back in ${timeString} to receive your next Fortune! Challenge!`,
                        ephemeral: true
                    });
                    return;
                }
            } else {
                if (!user) {
                    //if user doesn't exist, create new challenge
                    const newChallenge = new Challenge({
                        guildId: String(interaction.guild.id),
                        memberId: String(interaction.user.id),
                        amount: 0,
                        correctAnswers: 0,
                        wrongAnswers: 0,
                        dateLastAnswered: Date.now()
                    });
                    await newChallenge.save();

                    user = await Challenge.findOne({
                        guildId: interaction.guild.id,
                        memberId: interaction.user.id
                    });

                }
            }
        } catch (err) {
            console.log(err);
        }

        interaction.reply({
                content: `${item.question}`,
                ephemeral: true
            })
            .then(() => {
                interaction.channel.awaitMessages({
                        filter,
                        max: 1,
                        time: 1800000,
                        errors: ['time']
                    })
                    .then(async collected => {
                        const response = collected.first().content;
                        await collected.first().delete();
                        if (item.answers.includes(response.toLowerCase())) {
                            await interaction.followUp({
                                content: `${collected.first().author} has completed the challenge!`,
                                ephemeral: true
                            });
                            console.log("Challenge Answered Correct");
                            let guild = message.guilds.cache.get('948892863926771722');
                            var role = guild.roles.cache.find(role => role.name === 'Fortune Hunters');
                            var member = guild.members.cache.get(collected.first().author.id);
                            //if user exists, update their challenge
                            if (user) {
                                user.amount = user.amount + 1;
                                user.correctAnswers = user.correctAnswers + 1;
                                user.dateLastAnswered = Date.now();
                                await user.save();
                                if (user.correctAnswers >= 4) {
                                    await interaction.followUp({
                                        content: `Congratulations ${collected.first().author}, you have answered ${user.correctAnswers} challenges correct!\n\nhttps://cdn.discordapp.com/attachments/961307478790922342/974345274883457084/correct.png`,
                                        ephemeral: true
                                    });
                                    return;
                                }
                                if (user.correctAnswers === 3) {
                                    await member.roles.add(role);
                                    await interaction.followUp({
                                        content: `Congratulations ${collected.first().author}, you have answered ${user.correctAnswers} out of THREE required challenges, and have earned the Fortune Hunters role!\n\nhttps://cdn.discordapp.com/attachments/961307478790922342/974345274883457084/correct.png`,
                                        ephemeral: true
                                    });
                                } else {
                                    //show time remaining until they can do next challenge
                                    let time = 86400000 - (Date.now() - user.dateLastAnswered);
                                    let timeString = "";
                                    if (time > 3600000) {
                                        timeString = `${Math.floor(time / 3600000)} Hours, `;
                                    }
                                    if (time > 60000) {
                                        timeString = `${timeString}${Math.floor((time % 3600000) / 60000)} Minutes, `;
                                    }
                                    if (time > 1000) {
                                        timeString = `${timeString}${Math.floor((time % 60000) / 1000)} Seconds`;
                                    }

                                    await interaction.followUp({
                                        content: `${collected.first().author} has completed ${user.correctAnswers} out of THREE challenges towards opening full server access! Come back tomorrow for more challenges, and continue your journey!\n\nTime Remaining Until Next Challenge: ${timeString}`,
                                        ephemeral: true
                                    });
                                }
                            }
                        } else {
                            //if user exists, update their challenge
                            if (user) {
                                user.amount = user.amount + 1;
                                user.wrongAnswers = user.wrongAnswers + 1;
                                user.dateLastAnswered = Date.now();
                                await user.save();
                            }

                            //show time remaining until they can do next challenge
                            let time = 86400000 - (Date.now() - user.dateLastAnswered);
                            let timeString = "";
                            if (time > 3600000) {
                                timeString = `${Math.floor(time / 3600000)} Hours, `;
                            }
                            if (time > 60000) {
                                timeString = `${timeString}${Math.floor((time % 3600000) / 60000)} Minutes, `;
                            }
                            if (time > 1000) {
                                timeString = `${timeString}${Math.floor((time % 60000) / 1000)} Seconds`;
                            }

                            await interaction.followUp({
                                content: `Looks like you didn't get it right this time Fortune Hunter, but be sure to come back tomorrow for another chance to find your Fortune! with our daily challenges!\n\nTime Remaining Until Next Challenge: ${timeString}\n\nhttps://cdn.discordapp.com/attachments/961307478790922342/974345275193831424/incorrect.png`,
                                ephemeral: true
                            });
                            console.log("Challenge Answered Incorrectly");
                        }
                    })
                    .catch(async collected => {

                        //show time remaining until they can do next challenge
                        let time = 86400000 - (Date.now() - user.dateLastAnswered);
                        let timeString = "";
                        if (time > 3600000) {
                            timeString = `${Math.floor(time / 3600000)} Hours, `;
                        }
                        if (time > 60000) {
                            timeString = `${timeString}${Math.floor((time % 3600000) / 60000)} Minutes, `;
                        }
                        if (time > 1000) {
                            timeString = `${timeString}${Math.floor((time % 60000) / 1000)} Seconds`;
                        }

                        await interaction.followUp({
                            content: `You ran out of time! Please come back and try again tomorrow with another challenge.\n\nTime Remaining Until Next Challenge: ${timeString}\n\nhttps://cdn.discordapp.com/attachments/961307478790922342/974345274635980900/timed_out.png`,
                            ephemeral: true
                        });
                        console.log("Timed Out");
                    });
            });
    },
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 ZADAN.eth