Friday, September 20, 2024 1:39:50 AM
> settings

Customize


Authenticate

> logs.js
const ESMCommand = require("../esm_command");
const Steam = require("../../code/steam");

module.exports = class ESMCommand_Logs extends ESMCommand {
    constructor(bot) {
        super(bot);
        this.permissions = {
            disabled_in_player_mode: true,
            requires_registration: true,
            requires_server: true,
            text_only: true
        };

        this.commandParams = {
            serverID: {
                regex: this.util.regex.serverID.base
            },
            search: {
                regex: /.+/
            }
        };

        this.information = {
            category: "server",
            params: "<server_id> <target_uid | @user | search_string (premium only)>",
            help: "Parses Exile's logs for the search parameter within a 5 day window. If the server has premium, the length is set to 14 days and you can parse for anything. This includes using regex."
        };

        this.configuration = {
            permissions: {
                modifiable: true,
                default: {}
            },
            allowedInTextChannels: {
                modifiable: false,
                default: true
            },
            cooldown: {
                modifiable: true,
                default: [20, "seconds"]
            },
            enabled: {
                modifiable: true,
                default: true
            }
        };
    }

    async fromDiscord() {
        let days = 5;
        let isPremium = true;

        switch (true) {
            case this.util.regex.discordTag.base.test(this.params.search):
                let discordUser = await this.ESMBot.getUser(this.params.search);
                if (discordUser == null) {
                    return this.ESMBot.send(this.message.channel, this.ESMBot.errors.format(this.message.author, "USER_NOT_FOUND"));
                }
                let isRegistered = await this.db.isRegistered(discordUser.id);
                if (!isRegistered) {
                    return this.ESMBot.send(this.message.channel, this.ESMBot.errors.format(this.message.author, "USER_NOT_REGISTERED"));
                }
                this.params.search = await this.db.getSteamUIDFromID(discordUser.id);
                if (this.params.search == null) return;
                break;
            case this.util.regex.steamUID.base.test(this.params.search):
                break;
            default:
                if (!isPremium) {
                    return this.ESMBot.send(this.message.channel, "Free plans can only parse for SteamUIDs (directly or via a Discord tag).\nIf you would like to search for anything or use Regex **plus** a 14 day search period, consider upgrading to Premium.");
                }
                days = 14;
                let validRegex = true,
                    errorMessage = "";
                try {
                    new RegExp(this.params.search);
                } catch (err) {
                    errorMessage = err.message.replace(/invalid regular expression: .*\/: /i, "");
                    validRegex = false;
                }

                if (!validRegex) {
                    return this.ESMBot.send(this.message.channel, `\`${this.params.search}\` is not valid regex. Reason: \`${errorMessage}\``);
                }
                break;
        }

        this.send({
            serverID: this.params.serverID,
            command: "logs",
            parameters: {
                search: this.params.search,
                length: days
            }
        });
    }

    async fromServer() {
        if (this.params[1] == null || this.params[1].length === 0) {
            return this.ESMBot.send(this.info.channel, `We didn't find any log entries for \`${this.params.search}\``);
        }

        let data = {};
        for (let y = 1; y < this.params.length; y++) {
            data[this.params[y].date] = {};
            for (let log in this.params[y]) {
                let entries = [];
                let logName = "";
                switch (log) {
                    case "Exile_DeathLog.log":
                        logName = "Exile Death Log";
                        break;
                    case "Exile_TerritoryLog.log":
                        logName = "Exile Territory Log";
                        break;

                    case "Exile_TradingLog.log":
                        logName = "Exile Trading Log";
                        break;
                    default:
                        continue;
                }

                for (let i = 0; i < this.params[y][log].length; i++) {
                    let entry = this.params[y][log][i];
                    let newEntry = {
                        line: entry.line
                    };
                    let match = null;

                    match = /\[(\d{2}:\d{2}:\d{2}):.+ (-?\d{2}:\d{2})\] \[thread \d+\] /i.exec(entry.entry);
                    if (match != null) {
                        newEntry.timestamp = this.ESMBot.moment.utc(`${entry.date}T${match[1]}${match[2]}`).format("MM/d/YYYY, h:mm:ss a");
                        entry.entry = entry.entry.replace(/\[(\d{2}:\d{2}:\d{2}):.+ (-?\d{2}:\d{2})\] \[thread \d+\] /i, "");
                    }

                    let regex = [
                        // Waste Dump
                        [
                            /player: \( \d{17} \) (.+ \(.+\))(?:\sremote)? sold item: (.+) with Cargo (\[.+\]) for (\d+) poptabs and (.+) respect \| player total money: (\d+)/i,
                            "$1 sold vehicle: <code>$2</code> containing <code>$3</code> for $4</code> poptabs and $5</code> respect. Total Player Money: $6</code> poptabs"
                        ],
                        // Sold item
                        [
                            /player: \( \d{17} \) (.+ \(.+\))(?:\sremote)? sold item (.+) for (\d+) poptabs and (.+) respect \| player total money: (\d+)/i,
                            "$1 sold item <code>$2</code> for <code>$3</code> poptabs and <code>$4</code> respect. Total player money: <code>$5</code> poptabs"
                        ],
                        // Vehicle skin
                        [
                            /player: \( \d{17} \) (.+ \(.+\))(?:\sremote)? purchased vehicle skin (.+) for (\d+) poptabs \| player total money: (\d+)/i,
                            "$1 purchased vehicle skin <code>$2</code> for <code>$3</code> poptabs. Total player money: <code>$4</code> poptabs"
                        ],
                        // Vehicle
                        [
                            /player: \( \d{17} \) (.+ \(.+\))(?:\sremote)? purchased vehicle (.+) for (\d+) poptabs \| player total money: (\d+)/i,
                            "$1 purchased vehicle <code>$2</code> for <code>$3</code> poptabs. Total player money: <code>$4</code> poptabs"
                        ],
                        // Purchase item
                        [
                            /player: \( \d{17} \) (.+ \(.+\))(?:\sremote)? purchased item (.+) for (\d+) poptabs \| player total money: (\d+)/i,
                            "$1 purchased item <code>$2</code> for <code>$3</code> poptabs. Total player money: <code>$4</code> poptabs"
                        ],
                        // Upgrade Territory
                        [
                            /player \( \d{17} \) (.+ \(.+\))(?:\sremote)? paid (\d+) pop tabs to upgrade territory #(\d+) to level (\d+) \| player total pop tabs: (\d+)/i,
                            "$1 paid <code>$2</code> poptabs to upgrade their territory (ID #$3) to level $4. Total player poptabs: <code>$5</code>"
                        ],
                        // Restored territory
                        [
                            /player \( \d{17} \) (.+ \(.+\))(?:\sremote)? restored the flag of territory #(\d+)/i,
                            "$1 restored the flag of territory ID #$2"
                        ],
                        // Purchased Territory
                        [
                            /player \( \d{17} \) (.+ \(.+\))(?:\sremote)? paid (\d+) pop tabs to purchase a territory flag \| player total pop tabs: (\d+)/i,
                            "$1 purchased a territory flag. Cost: <code>$2</code> poptabs. Total player poptabs: <code>$3</code>"
                        ],
                        // Base Protection Money
                        [
                            /player \( \d{17} \) (.+ \(.+\))(?:\sremote)? paid (\d+) pop tabs to protect territory #(\d+) \| player total pop tabs: (\d+)/i,
                            "$1 paid base protection for territory #$3. Cost: <code>$2</code> poptabs. Player total poptabs: <code>$4</code>"
                        ],
                        // Ransom payment
                        [
                            /player \( \d{17} \) (.+ \(.+\))(?:\sremote)? paid (\d+) pop tabs for the ransom of territory #(\d+) \| player total pop tabs: (\d+)/i,
                            "$1 paid ransom for territory #$3. Cost <code>$2</code> poptabs. Total player poptabs: <code>$4</code>"
                        ],
                        // Stole flag
                        [
                            /player \( \d{17} \) (.+ \(.+\))(?:\sremote)? stole a level (\d+) flag from territory #(\d+)/i,
                            "$1 stole a level $2 flag from territory #$3"
                        ]
                    ];

                    for (let x = 0; x < regex.length; x++) {
                        match = regex[x][0].exec(entry.entry);
                        if (match != null) {
                            newEntry.entry = entry.entry.replace(regex[x][0], regex[x][1]);
                            break;
                        }
                    }

                    if (newEntry.entry == null) {
                        newEntry.entry = entry.entry;
                    }

                    entries.push(newEntry);
                }
                data[this.params[y].date][logName] = entries;
            }
        }

        let targetInfo = {};
        if (this.util.regex.steamUID.base.test(this.params[0].search)) {
            targetInfo.uid = this.params[0].search;
            let discordIDs = await this.db.getDiscordIDsFromSteamUID(targetInfo.uid);

            if (!this.util.isEmpty(discordIDs)) {
                targetInfo.discord_users = [];

                for (let id of discordIDs) {
                    let discordUser = await this.ESMBot.getUser(id);
                    if (discordUser != null) {
                        targetInfo.discord_users.push([discordUser.username, discordUser.discriminator]);
                    }
                }

            }

            let profileData = await Steam.getSteamUserData(targetInfo.uid);
            if (profileData.response) {
                targetInfo.steam_username = profileData.data.username;
                targetInfo.steam_profile_url = profileData.data.profileurl;
            }
        }

        let requestingUser = await this.ESMBot.getUser(this.info.author.id);

        let expires = this.ESMBot.moment.utc().add("1", "d");
        let hash = await this.db.generateLinkHash({
                requested_by: {
                    username: requestingUser.username,
                    discriminator: requestingUser.discriminator,
                    avatar: requestingUser.avatarURL()
                },
                server_id: this.serverID,
                requested_at: this.ESMBot.moment.utc().format(),
                entries: data,
                target_info: targetInfo,
                search: this.params[0].search
            },
            expires.format()
        );

        this.ESMBot.send(this.info.channel, {
            title: `Log Parsing on ${this.serverID} completed`,
            description: `Search results for \`${this.params[0].search}\`: [Results](${this.ESMBot.config.DEBUG ? `http://localhost:3000/logs/${hash}` : `https://www.esmbot.com/logs/${hash}`})`,
            footer: {
                text: `Link expires on ${expires.format("MMMM Do YYYY, h:mm:ss a")}`
            },
            color: this.ESMBot.colors.GREEN
        });
    }
}
All opinions represented herein are my own
- © 2024 itsthedevman
- build 340fbb8