Source

classes/stamps-manager.js

const { Collection, MessageEmbed, GuildMember } = require('discord.js');
const winston = require('winston');
const { addRoleToMember, sendEmbedToMember, replaceRoleToMember, sendMessageToMember } = require('../discord-services');
const BotGuildModel = require('./bot-guild');
const Activity = require('./activities/activity');

/**
 * @class
 * 
 */
class StampsManager {
    /**
     * Will let hackers get a stamp for attending the activity.
     * @param {Activity} activity - activity to use
     * @param {Number} [time] - time to wait till collector closes, in seconds
     * @param {BotGuildModel} botGuild
     * @async
     */
    static async distributeStamp(activity, botGuild, time = 60) {

        winston.loggers.get(activity.guild.id).event(`Activity named ${activity.name} is distributing stamps.`, {event: 'Activity Manager'});
        
        // The users already seen by this stamp distribution.
        let seenUsers = new Collection();

        const promptEmbed = new MessageEmbed()
            .setColor(botGuild.colors.embedColor)
            .setTitle('React within ' + time + ' seconds of the posting of this message to get a stamp for ' + activity.name + '!');

        let promptMsg = await activity.generalText.send(promptEmbed);
        promptMsg.react('👍');

        // reaction collector, time is needed in milliseconds, we have it in seconds
        const collector = promptMsg.createReactionCollector((reaction, user) => !user.bot, { time: (1000 * time) });

        collector.on('collect', async (reaction, user) => {
            // grab the member object of the reacted user
            const member = activity.generalText.guild.member(user);

            if (!seenUsers.has(user.id)) {
                this.parseRole(member, activity.name, botGuild);
                seenUsers.set(user.id, user.username);
            }
        });

        // edit the message to closed when the collector ends
        collector.on('end', collected => {
            winston.loggers.get(activity.guild.id).event(`Activity named ${activity.name} stamp distribution has stopped.`, {event: 'Activity Manager'});
            if (!promptMsg.deleted) {
                promptMsg.edit(promptEmbed.setTitle('Time\'s up! No more responses are being collected. Thanks for participating in ' + activity.name + '!'));
            }
        });
    }


    /**
     * Upgrade the stamp role of a member.
     * @param {GuildMember} member - the member to add the new role to
     * @param {String} activityName - the name of the activity
     * @param {BotGuildModel} botGuild
     * @throws Error if the botGuild has stamps disabled
     */
    static parseRole(member, activityName, botGuild) {
        if (!botGuild.stamps.isEnabled) {
            winston.loggers.get(botGuild._id).error(`Stamp system is turned off for guild ${botGuild._id} but I was asked to parse a role for member ${member.id} for activity ${activityName}.`, { event: 'Activity Manager' });
            throw Error(`Stamp system is turned of for guild ${botGuild._id} but I was asked to parse a role for member ${member.id} for activity ${activityName}.`);
        }

        let role = member.roles.cache.find(role => botGuild.stamps.stampRoleIDs.has(role.id));

        if (role === undefined) {
            addRoleToMember(member, botGuild.stamps.stamp0thRoleId);
            sendEmbedToMember(member, 'I did not find an existing stamp role for you so I gave you one for attending '
                + activityName + '. Please contact an admin if there was a problem.', true);
            winston.loggers.get(botGuild._id).userStats(`Activity named ${activityName} tried to give a stamp to the user with id ${member.id} but he has no stamp, I gave them the first stamp!`, {event: 'Activity Manager'});
            return;
        }

        let stampNumber = botGuild.stamps.stampRoleIDs.get(role.id);
        if (stampNumber === botGuild.stamps.stampRoleIDs.size - 1) {
            sendMessageToMember(member, 'You already have the maximum allowed number of stamps!', true);
            winston.loggers.get(botGuild._id).userStats(`Activity named ${activityName} tried to give a stamp to the user with id ${member.id} but he is already in the max stamp ${stampNumber}`, {event: 'Activity Manager'});
            return;
        }
        let newRoleID;

        botGuild.stamps.stampRoleIDs.forEach((num, key, map) => {
            if (num === stampNumber + 1) newRoleID = key;
        });

        if (newRoleID != undefined) {
            replaceRoleToMember(member, role.id, newRoleID);
            sendMessageToMember(member, 'You have received a higher stamp for attending ' + activityName + '!', true);
            winston.loggers.get(botGuild._id).userStats(`Activity named ${activityName} gave a stamp to the user with id ${member.id} going from stamp number ${stampNumber} to ${stampNumber + 1}`, {event: 'Activity Manager'});
        }
    }
}
module.exports = StampsManager;