Thursday, September 19, 2024 11:52:56 PM
> settings

Customize


Authenticate

> cooldown_service.js
module.exports = class CooldownService {
    constructor(database, command) {
        this.database = database;
        this.ESMBot = database.ESMBot;
        this.util = this.ESMBot.util;
        this.r = database.r;
        this.command = command;
        this.message = command.message;

        this.CLIENT_PROFILE = {
            id: "",
            steam_uid: "",
            preferences: {}
        };
    }

    async addCooldown() {
        // Preinit these variables
        let defaults = [2, "seconds"];
        let communityID = null;

        // Get the user from the database based on the ID
        let user = await this.r.table("users").get(this.message.author.id).run();

        // We didn't find the user, create the user in our database (first time running a command)
        if (user == null) {
            user = _.cloneDeep(this.CLIENT_PROFILE);
            user.id = this.message.author.id;
            await this.r.table("users").insert(user).run();
        }

        // Check to see if our command has configuration for cooldown
        if (this.util.hasOwnPropertyTree(this.command.configuration, "cooldown")) {
            defaults = this.command.configuration.cooldown.default;
            communityID = this.getCommunityIDFromParams();

            // Check to see if the community is valid
            if (await this.database.isValidCommunity(communityID)) {
                // Get the configurations for this community
                let community = await this.r.table("communities").get(communityID).run();

                // If we have configuration for this command, take the cooldown information from the community
                if (this.util.hasOwnPropertyTree(community, "command_configuration", this.command.name)) {
                    if (!this.util.isEmpty(community.command_configuration[this.command.name].cooldown)) {
                        defaults = community.command_configuration[this.command.name].cooldown;
                    }
                }
            }
        }

        // Start building our cooldown query
        let query = {
            command_name: this.command.name
        };

        // If the user has a steam_uid on their account, go ahead and add it to the cooldown
        if (!_.isEmpty(user.steam_uid)) {
            query.steam_uid = user.steam_uid;
        } else {
            query.user_id = user.id;
        }

        // If we previously got a community ID, go ahead and use that for the query.
        if (!this.util.isEmpty(communityID)) {
            query.community_id = communityID;

            // Same thing with server_id
            if (this.command.params.serverID) {
                query.server_id = this.command.params.serverID;
            }
        }

        // Check to see if we have a cooldown already
        let cooldown = _.first(await this.r.table("cooldowns").filter(query).run());

        // If we don't have a cooldown for this query yet, use the query as a starting point for the new cooldown
        if (cooldown == null) {
            cooldown = query;
        }

        // Store these values for future checking
        cooldown.quantity = defaults[0];
        cooldown.type = defaults[1];

        if (cooldown.type === "times") {
            // Since the cooldown is a quantity cooldown, increment the previous value or start it off at 1
            cooldown.amount = (cooldown.amount || 0) + 1;

            // Cleanup if we've switched
            if (cooldown.hasOwnProperty("expires_at")) {
                delete cooldown.expires_at;
            }
        } else {
            // Since the cooldown is some sort of time (hour, min, sec, etc), set the new cooldown
            cooldown.expires_at = moment.utc().add(cooldown.quantity, cooldown.type).toDate();

            // Cleanup if we've switched
            if (cooldown.hasOwnProperty("amount")) {
                delete cooldown.amount;
            }
        }

        // Insert it into the DB
        await this.r.table("cooldowns").insert(cooldown, {
            conflict: "replace"
        }).run();
    }

    async getCooldown() {
        // Get the user from the DB
        let user = await this.r.table("users").get(this.message.author.id).run();

        // We didn't find the user, create the user in our database (first time running a command)
        if (user == null) {
            user = _.cloneDeep(this.CLIENT_PROFILE);
            user.id = this.message.author.id;
            await this.r.table("users").insert(user).run();
        }

        // Lets start building our query
        let query = {
            command_name: this.command.name
        };

        let community = null;
        let communityID = this.getCommunityIDFromParams();

        // Check to see if our command has configuration for cooldown
        if (this.util.hasOwnPropertyTree(this.command.configuration, "cooldown")) {
            // Check to see if the community is valid
            if (await this.database.isValidCommunity(communityID)) {
                // Get the community we are using
                community = await this.r.table("communities").get(communityID).run();

                // Add the community ID to the query since we have one
                query.community_id = community.id

                // Add the server ID if we have it
                if (this.command.params.serverID) {
                    query.server_id = this.command.params.serverID;
                }
            }
        }

        // We are requiring registration for this command, use the steam_uid instead of user_id
        if (this.command.permissions.requires_registration) {
            query.steam_uid = user.steam_uid;
        } else {
            query.user_id = user.id;
        }

        // Go get our cooldown based on our query
        let cooldown = _.first(await this.r.table("cooldowns").filter(query).run());

        // If we don't have a cooldown, it's more than likely we've never used this command (let them through)
        if (cooldown == null) return {};

        // If we have a community, we may need to adjust the cooldown if the values have changed
        if (community != null) {
            // If we have configuration for this command, take the cooldown information from the community
            if (this.util.hasOwnPropertyTree(community, "command_configuration", this.command.name, "cooldown")) {
                let cooldownInfo = community.command_configuration[this.command.name].cooldown;
                let times = {
                    "seconds": 1,
                    "minutes": 60,
                    "hours": 3600,
                    "days": 86400,
                    "times": 99999999
                };

                // Normal time cooldown, check if the values have changed
                if (cooldownInfo[1] !== "times" && this.hasCooldownChanged(cooldownInfo, cooldown)) {
                    // Calculate each time into seconds
                    let originalTime = cooldown.quantity * times[cooldown.type];
                    let newTime = cooldownInfo[0] * times[cooldownInfo[1]];

                    // Looks like our times have changed, we need to update our expires_at
                    if (originalTime > newTime) {
                        cooldown.expires_at = moment.utc(cooldown.expires_at).subtract(originalTime - newTime, "s").toDate();
                    }
                }

                // Ensure the data is correct
                cooldown.quantity = cooldownInfo[0];
                cooldown.type = cooldownInfo[1];
            }
        }

        return cooldown;
    }

    async resetCooldown(communityID, commandName, userID) {
        // Get the user, we need the steam UID
        let user = await this.r.table("users").get(userID).run();

        // Create the user in case they aren't?
        if (user == null) {
            user = _.cloneDeep(this.CLIENT_PROFILE);
            user.id = userID;
            await this.r.table("users").insert(user).run();
        }

        // Go and delete any cooldowns that match the following SQL
        // DELETE FROM cooldowns WHERE community_id = communityID AND command_name = commandName AND (steam_uid = user.steam_uid OR user_id = user.id)
        let ret = await this.r.table("cooldowns").filter((cooldown) => {
            return cooldown("community_id").eq(communityID).and(
                cooldown("command_name").eq(commandName)
            ).and(
                cooldown("steam_uid").eq(user.steam_uid).or(cooldown("user_id").eq(user.id))
            );
        }).delete().run();

        return ret.errors === 0;
    }

    async resetCooldownForCommand() {
        let userID = this.message ? this.message.author.id : this.info.author.id;

        // Get the user, we need the steam UID
        let user = await this.r.table("users").get(userID).run();

        // Create the user in case they aren't?
        if (user == null) {
            user = _.cloneDeep(this.CLIENT_PROFILE);
            user.id = userID;
            await this.r.table("users").insert(user).run();
        }

        // Go and delete any cooldowns
        let ret = await this.r.table("cooldowns").filter((cooldown) => {
            return cooldown("community_id").eq(this.command.communityID || null).and(
                cooldown("command_name").eq(this.command.name)
            ).and(
                cooldown("server_id").eq(this.command.params.serverID || null).default(true)
            ).and(
                cooldown("steam_uid").eq(user.steam_uid || null).or(cooldown("user_id").eq(user.id))
            );
        }).delete().run();

        return ret.errors === 0;
    }

    getCommunityIDFromParams() {
        return this.util.getCommunityID(
            this.command.params.serverID || this.command.params.communityID
        );
    }

    hasCooldownChanged(communityCooldown, userCooldown) {
        return (communityCooldown[0] !== userCooldown.quantity) || (communityCooldown[1] !== userCooldown.type);
    }
}
All opinions represented herein are my own
- © 2024 itsthedevman
- build 3c15a1b