UNPKG

@jsprismarine/prismarine

Version:

Dedicated Minecraft Bedrock Edition server written in TypeScript

191 lines (190 loc) • 22.7 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const require_runtime = require("../_virtual/_rolldown/runtime.cjs.cjs"); const require_events_player_PlayerToggleOperatorEvent = require("../events/player/PlayerToggleOperatorEvent.cjs.cjs"); const require_utils_cwd = require("../utils/cwd.cjs.cjs"); let node_fs = require("node:fs"); node_fs = require_runtime.__toESM(node_fs, 1); let confbox = require("confbox"); let _jsprismarine_errors = require("@jsprismarine/errors"); //#region src/permission/PermissionManager.ts var PERMISSION_FILE_NAME = "permissions.json"; var OPS_FILE_NAME = "ops.json"; /** * Permission manager. */ var PermissionManager = class { server; ops = /* @__PURE__ */ new Set(); permissions = /* @__PURE__ */ new Map(); defaultPermissions = []; defaultOperatorPermissions = []; /** * Create a new permission manager. * @param {Server} server - The server instance. */ constructor(server) { this.server = server; } /** * Enable the manager and load all permissions. * @returns {Promise<void>} A promise that resolves when the manager is enabled. * @group Lifecycle */ async enable() { await this.parseOps(); await this.parsePermissions(); } /** * Signifies that the manager is being disabled and all permissions should be unloaded. * @returns {Promise<void>} A promise that resolves when the manager is disabled. * @group Lifecycle */ async disable() { this.ops.clear(); this.permissions.clear(); this.defaultPermissions = []; } /** * Get the default permissions. * @returns {string[]} The default permissions. */ getDefaultPermissions() { return this.defaultPermissions; } /** * Get a player's permissions. * @param {Player} player - The player to get permissions for. * @returns {Promise<string[]>} A promise that resolves with the player's permissions. */ async getPermissions(player) { return [ ...this.defaultPermissions, ...this.permissions.get(player.getName()) ?? [], ...player.isOp() ? this.defaultOperatorPermissions : [] ]; } /** * Set a player's permissions. * * @remarks * This will not be saved to the permissions.json file. * * @param {Player} player - The player to set permissions for. * @param {string[]} [permissions=[]] - The permissions to set. */ setPermissions(player, permissions = []) { this.permissions.set(player.getName(), permissions); } async parsePermissions() { try { if (!node_fs.default.existsSync(require_utils_cwd.withCwd(PERMISSION_FILE_NAME))) { this.server.getLogger().warn(`Failed to load permissions list!`); node_fs.default.writeFileSync(require_utils_cwd.withCwd(PERMISSION_FILE_NAME), JSON.stringify({ defaultPermissions: [ "minecraft.command.help", "minecraft.command.list", "minecraft.command.me", "jsprismarine.command.plugins", "jsprismarine.command.version", "jsprismarine.command.tps" ], defaultOperatorPermissions: ["*"], players: [{ name: "filfat", permissions: ["*"] }] }, null, 4)); } const permissionsObject = (0, confbox.parseJSON5)((await node_fs.default.promises.readFile(require_utils_cwd.withCwd(PERMISSION_FILE_NAME))).toString()); this.defaultPermissions = permissionsObject.defaultPermissions || []; this.defaultOperatorPermissions = permissionsObject.defaultOperatorPermissions || ["*"]; permissionsObject.players?.map((player) => this.permissions.set(player.name, player.permissions.length <= 0 ? [] : player.permissions)); } catch (error) { this.server.getLogger().error(error); throw new Error(`Invalid ${PERMISSION_FILE_NAME} file.`); } } async parseOps() { try { if (!node_fs.default.existsSync(require_utils_cwd.withCwd(OPS_FILE_NAME))) { this.server.getLogger().warn(`Failed to load operators list!`); node_fs.default.writeFileSync(require_utils_cwd.withCwd(OPS_FILE_NAME), "[]"); } (0, confbox.parseJSON5)((await node_fs.default.promises.readFile(require_utils_cwd.withCwd(OPS_FILE_NAME))).toString()).map((op) => this.ops.add(op.name)); } catch (error) { this.server.getLogger().error(error); throw new Error(`Invalid ${OPS_FILE_NAME} file.`); } } /** * Set a player as an operator. * * @param {string} username - The player to set as an operator. * @param {boolean} op - Whether the player should be an operator. * @returns {Promise<boolean>} A promise that resolves with a boolean indicating whether the operation was successful. */ async setOp(username, op) { const target = this.server.getSessionManager().getPlayerByExactName(username); if (!target) throw new _jsprismarine_errors.PlayerNotFoundError(username); const event = new require_events_player_PlayerToggleOperatorEvent.default(target, op); this.server.post(["playerToggleOperator", event]); if (event.isCancelled()) return false; await target.getNetworkSession().sendAvailableCommands(); if (op) this.ops.add(username); else this.ops.delete(username); try { await node_fs.default.promises.writeFile(require_utils_cwd.withCwd(OPS_FILE_NAME), JSON.stringify(Array.from(this.ops.values()).map((name) => ({ name, level: 4 })), null, 4)); await target.sendSettings(); return true; } catch { return false; } } /** * Check if a player is an operator. * * @param {string} username - The player to check. * @returns {boolean} Whether the player is an operator. */ isOp(username) { return this.ops.has(username); } /** * Check if a player can execute a command. * * @param {Player} executer - The player to check. * @returns {object} An object with an execute method that takes a permission string and returns whether the player can execute the command. */ can(executer) { const execute = (permission) => { if (!executer) throw new Error(`Executer can't be undefined or null`); if (!permission) return true; if (executer.isConsole()) return true; if (executer.isOp()) return true; if (executer.getPermissions().includes(permission)) return true; if (executer.getPermissions().includes("*")) return true; const split = permission.split("."); let scope = ""; for (const action of split) { if (scope) scope = `${scope}.${action}`; else scope = action; if (executer.getPermissions().includes(scope)) return true; if (executer.getPermissions().includes(`${scope}.*`)) return true; } return false; }; return { execute, not: () => { return { execute: (permission) => !execute(permission) }; } }; } }; //#endregion exports.PermissionManager = PermissionManager; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVybWlzc2lvbk1hbmFnZXIuY2pzLmNqcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvcGVybWlzc2lvbi9QZXJtaXNzaW9uTWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSAnbm9kZTpmcyc7XG5cbmltcG9ydCB7IHBhcnNlSlNPTjUgfSBmcm9tICdjb25mYm94JztcblxuaW1wb3J0IHsgUGxheWVyTm90Rm91bmRFcnJvciB9IGZyb20gJ0Bqc3ByaXNtYXJpbmUvZXJyb3JzJztcbmltcG9ydCB0eXBlIHsgUGxheWVyLCBTZXJ2ZXIsIFNlcnZpY2UgfSBmcm9tICcuLi8nO1xuaW1wb3J0IHsgd2l0aEN3ZCB9IGZyb20gJy4uLyc7XG5pbXBvcnQgcGxheWVyVG9nZ2xlT3BlcmF0b3JFdmVudCBmcm9tICcuLi9ldmVudHMvcGxheWVyL1BsYXllclRvZ2dsZU9wZXJhdG9yRXZlbnQnO1xuXG5pbnRlcmZhY2UgT3BUeXBlIHtcbiAgICBuYW1lOiBzdHJpbmc7XG59XG5cbmNvbnN0IFBFUk1JU1NJT05fRklMRV9OQU1FID0gJ3Blcm1pc3Npb25zLmpzb24nO1xuY29uc3QgT1BTX0ZJTEVfTkFNRSA9ICdvcHMuanNvbic7XG5cbi8qKlxuICogUGVybWlzc2lvbiBtYW5hZ2VyLlxuICovXG5leHBvcnQgY2xhc3MgUGVybWlzc2lvbk1hbmFnZXIgaW1wbGVtZW50cyBTZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNlcnZlcjogU2VydmVyO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgb3BzOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBlcm1pc3Npb25zOiBNYXA8c3RyaW5nLCBzdHJpbmdbXT4gPSBuZXcgTWFwKCk7XG4gICAgcHJpdmF0ZSBkZWZhdWx0UGVybWlzc2lvbnM6IHN0cmluZ1tdID0gW107XG4gICAgcHJpdmF0ZSBkZWZhdWx0T3BlcmF0b3JQZXJtaXNzaW9uczogc3RyaW5nW10gPSBbXTtcblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIG5ldyBwZXJtaXNzaW9uIG1hbmFnZXIuXG4gICAgICogQHBhcmFtIHtTZXJ2ZXJ9IHNlcnZlciAtIFRoZSBzZXJ2ZXIgaW5zdGFuY2UuXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHNlcnZlcjogU2VydmVyKSB7XG4gICAgICAgIHRoaXMuc2VydmVyID0gc2VydmVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZSB0aGUgbWFuYWdlciBhbmQgbG9hZCBhbGwgcGVybWlzc2lvbnMuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG1hbmFnZXIgaXMgZW5hYmxlZC5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGVuYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5wYXJzZU9wcygpO1xuICAgICAgICBhd2FpdCB0aGlzLnBhcnNlUGVybWlzc2lvbnMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaWduaWZpZXMgdGhhdCB0aGUgbWFuYWdlciBpcyBiZWluZyBkaXNhYmxlZCBhbmQgYWxsIHBlcm1pc3Npb25zIHNob3VsZCBiZSB1bmxvYWRlZC5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbWFuYWdlciBpcyBkaXNhYmxlZC5cbiAgICAgKiBAZ3JvdXAgTGlmZWN5Y2xlXG4gICAgICovXG4gICAgcHVibGljIGFzeW5jIGRpc2FibGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMub3BzLmNsZWFyKCk7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbnMuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5kZWZhdWx0UGVybWlzc2lvbnMgPSBbXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGRlZmF1bHQgcGVybWlzc2lvbnMuXG4gICAgICogQHJldHVybnMge3N0cmluZ1tdfSBUaGUgZGVmYXVsdCBwZXJtaXNzaW9ucy5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0RGVmYXVsdFBlcm1pc3Npb25zKCk6IHN0cmluZ1tdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVmYXVsdFBlcm1pc3Npb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhIHBsYXllcidzIHBlcm1pc3Npb25zLlxuICAgICAqIEBwYXJhbSB7UGxheWVyfSBwbGF5ZXIgLSBUaGUgcGxheWVyIHRvIGdldCBwZXJtaXNzaW9ucyBmb3IuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBwbGF5ZXIncyBwZXJtaXNzaW9ucy5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZ2V0UGVybWlzc2lvbnMocGxheWVyOiBQbGF5ZXIpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAuLi50aGlzLmRlZmF1bHRQZXJtaXNzaW9ucyxcbiAgICAgICAgICAgIC4uLih0aGlzLnBlcm1pc3Npb25zLmdldChwbGF5ZXIuZ2V0TmFtZSgpKSA/PyBbXSksXG4gICAgICAgICAgICAuLi4ocGxheWVyLmlzT3AoKSA/IHRoaXMuZGVmYXVsdE9wZXJhdG9yUGVybWlzc2lvbnMgOiBbXSlcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYSBwbGF5ZXIncyBwZXJtaXNzaW9ucy5cbiAgICAgKlxuICAgICAqIEByZW1hcmtzXG4gICAgICogVGhpcyB3aWxsIG5vdCBiZSBzYXZlZCB0byB0aGUgcGVybWlzc2lvbnMuanNvbiBmaWxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtQbGF5ZXJ9IHBsYXllciAtIFRoZSBwbGF5ZXIgdG8gc2V0IHBlcm1pc3Npb25zIGZvci5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbcGVybWlzc2lvbnM9W11dIC0gVGhlIHBlcm1pc3Npb25zIHRvIHNldC5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0UGVybWlzc2lvbnMocGxheWVyOiBQbGF5ZXIsIHBlcm1pc3Npb25zOiBzdHJpbmdbXSA9IFtdKSB7XG4gICAgICAgIHRoaXMucGVybWlzc2lvbnMuc2V0KHBsYXllci5nZXROYW1lKCksIHBlcm1pc3Npb25zKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHBhcnNlUGVybWlzc2lvbnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMod2l0aEN3ZChQRVJNSVNTSU9OX0ZJTEVfTkFNRSkpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXJ2ZXIuZ2V0TG9nZ2VyKCkud2FybihgRmFpbGVkIHRvIGxvYWQgcGVybWlzc2lvbnMgbGlzdCFgKTtcbiAgICAgICAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKFxuICAgICAgICAgICAgICAgICAgICAvLyBGSVhNRTogVGhpcyBvdmVyd3JpdGVzIGNvbW1lbnRzIGluIHRoZSBmaWxlLlxuICAgICAgICAgICAgICAgICAgICB3aXRoQ3dkKFBFUk1JU1NJT05fRklMRV9OQU1FKSxcbiAgICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFBlcm1pc3Npb25zOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdtaW5lY3JhZnQuY29tbWFuZC5oZWxwJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21pbmVjcmFmdC5jb21tYW5kLmxpc3QnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbWluZWNyYWZ0LmNvbW1hbmQubWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnanNwcmlzbWFyaW5lLmNvbW1hbmQucGx1Z2lucycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdqc3ByaXNtYXJpbmUuY29tbWFuZC52ZXJzaW9uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2pzcHJpc21hcmluZS5jb21tYW5kLnRwcydcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRPcGVyYXRvclBlcm1pc3Npb25zOiBbJyonXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGF5ZXJzOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICdmaWxmYXQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVybWlzc2lvbnM6IFsnKiddXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIDRcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHBlcm1pc3Npb25zT2JqZWN0OiBQYXJ0aWFsPHtcbiAgICAgICAgICAgICAgICBkZWZhdWx0UGVybWlzc2lvbnM6IHN0cmluZ1tdO1xuICAgICAgICAgICAgICAgIGRlZmF1bHRPcGVyYXRvclBlcm1pc3Npb25zOiBzdHJpbmdbXTtcbiAgICAgICAgICAgICAgICBwbGF5ZXJzOiBBcnJheTx7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IHN0cmluZztcbiAgICAgICAgICAgICAgICAgICAgcGVybWlzc2lvbnM6IHN0cmluZ1tdO1xuICAgICAgICAgICAgICAgIH0+O1xuICAgICAgICAgICAgfT4gPSBwYXJzZUpTT041KChhd2FpdCBmcy5wcm9taXNlcy5yZWFkRmlsZSh3aXRoQ3dkKFBFUk1JU1NJT05fRklMRV9OQU1FKSkpLnRvU3RyaW5nKCkpO1xuXG4gICAgICAgICAgICB0aGlzLmRlZmF1bHRQZXJtaXNzaW9ucyA9IHBlcm1pc3Npb25zT2JqZWN0LmRlZmF1bHRQZXJtaXNzaW9ucyB8fCBbXTtcbiAgICAgICAgICAgIHRoaXMuZGVmYXVsdE9wZXJhdG9yUGVybWlzc2lvbnMgPSBwZXJtaXNzaW9uc09iamVjdC5kZWZhdWx0T3BlcmF0b3JQZXJtaXNzaW9ucyB8fCBbJyonXTtcbiAgICAgICAgICAgIHBlcm1pc3Npb25zT2JqZWN0LnBsYXllcnM/Lm1hcCgocGxheWVyKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMucGVybWlzc2lvbnMuc2V0KHBsYXllci5uYW1lLCBwbGF5ZXIucGVybWlzc2lvbnMubGVuZ3RoIDw9IDAgPyBbXSA6IHBsYXllci5wZXJtaXNzaW9ucylcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgJHtQRVJNSVNTSU9OX0ZJTEVfTkFNRX0gZmlsZS5gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcGFyc2VPcHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMod2l0aEN3ZChPUFNfRklMRV9OQU1FKSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS53YXJuKGBGYWlsZWQgdG8gbG9hZCBvcGVyYXRvcnMgbGlzdCFgKTtcbiAgICAgICAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKHdpdGhDd2QoT1BTX0ZJTEVfTkFNRSksICdbXScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb3BzOiBPcFR5cGVbXSA9IHBhcnNlSlNPTjUoKGF3YWl0IGZzLnByb21pc2VzLnJlYWRGaWxlKHdpdGhDd2QoT1BTX0ZJTEVfTkFNRSkpKS50b1N0cmluZygpKTtcblxuICAgICAgICAgICAgb3BzLm1hcCgob3ApID0+IHRoaXMub3BzLmFkZChvcC5uYW1lKSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICAgICAgICB0aGlzLnNlcnZlci5nZXRMb2dnZXIoKS5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgJHtPUFNfRklMRV9OQU1FfSBmaWxlLmApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IGEgcGxheWVyIGFzIGFuIG9wZXJhdG9yLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJuYW1lIC0gVGhlIHBsYXllciB0byBzZXQgYXMgYW4gb3BlcmF0b3IuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBvcCAtIFdoZXRoZXIgdGhlIHBsYXllciBzaG91bGQgYmUgYW4gb3BlcmF0b3IuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYSBib29sZWFuIGluZGljYXRpbmcgd2hldGhlciB0aGUgb3BlcmF0aW9uIHdhcyBzdWNjZXNzZnVsLlxuICAgICAqL1xuICAgIHB1YmxpYyBhc3luYyBzZXRPcCh1c2VybmFtZTogc3RyaW5nLCBvcDogYm9vbGVhbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBjb25zdCB0YXJnZXQgPSB0aGlzLnNlcnZlci5nZXRTZXNzaW9uTWFuYWdlcigpLmdldFBsYXllckJ5RXhhY3ROYW1lKHVzZXJuYW1lKTsgLy8gVE9ETzogYnkgbmFtZSBub3QgZXhhY3RcbiAgICAgICAgaWYgKCF0YXJnZXQpIHRocm93IG5ldyBQbGF5ZXJOb3RGb3VuZEVycm9yKHVzZXJuYW1lKTtcbiAgICAgICAgY29uc3QgZXZlbnQgPSBuZXcgcGxheWVyVG9nZ2xlT3BlcmF0b3JFdmVudCh0YXJnZXQsIG9wKTtcbiAgICAgICAgdGhpcy5zZXJ2ZXIucG9zdChbJ3BsYXllclRvZ2dsZU9wZXJhdG9yJywgZXZlbnRdKTtcbiAgICAgICAgaWYgKGV2ZW50LmlzQ2FuY2VsbGVkKCkpIHJldHVybiBmYWxzZTtcblxuICAgICAgICBhd2FpdCB0YXJnZXQuZ2V0TmV0d29ya1Nlc3Npb24oKS5zZW5kQXZhaWxhYmxlQ29tbWFuZHMoKTtcblxuICAgICAgICBpZiAob3ApIHRoaXMub3BzLmFkZCh1c2VybmFtZSk7XG4gICAgICAgIGVsc2UgdGhpcy5vcHMuZGVsZXRlKHVzZXJuYW1lKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgZnMucHJvbWlzZXMud3JpdGVGaWxlKFxuICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBUaGlzIG92ZXJ3cml0ZXMgY29tbWVudHMgaW4gdGhlIGZpbGUuXG4gICAgICAgICAgICAgICAgd2l0aEN3ZChPUFNfRklMRV9OQU1FKSxcbiAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgICAgICAgICAgQXJyYXkuZnJvbSh0aGlzLm9wcy52YWx1ZXMoKSkubWFwKChuYW1lKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldmVsOiA0XG4gICAgICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgNFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRhcmdldC5zZW5kU2V0dGluZ3MoKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgcGxheWVyIGlzIGFuIG9wZXJhdG9yLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHVzZXJuYW1lIC0gVGhlIHBsYXllciB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gV2hldGhlciB0aGUgcGxheWVyIGlzIGFuIG9wZXJhdG9yLlxuICAgICAqL1xuICAgIHB1YmxpYyBpc09wKHVzZXJuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3BzLmhhcyh1c2VybmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBwbGF5ZXIgY2FuIGV4ZWN1dGUgYSBjb21tYW5kLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtQbGF5ZXJ9IGV4ZWN1dGVyIC0gVGhlIHBsYXllciB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fSBBbiBvYmplY3Qgd2l0aCBhbiBleGVjdXRlIG1ldGhvZCB0aGF0IHRha2VzIGEgcGVybWlzc2lvbiBzdHJpbmcgYW5kIHJldHVybnMgd2hldGhlciB0aGUgcGxheWVyIGNhbiBleGVjdXRlIHRoZSBjb21tYW5kLlxuICAgICAqL1xuICAgIHB1YmxpYyBjYW4oZXhlY3V0ZXI/OiBQbGF5ZXIpIHtcbiAgICAgICAgY29uc3QgZXhlY3V0ZSA9IChwZXJtaXNzaW9uPzogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWV4ZWN1dGVyKSB0aHJvdyBuZXcgRXJyb3IoYEV4ZWN1dGVyIGNhbid0IGJlIHVuZGVmaW5lZCBvciBudWxsYCk7XG5cbiAgICAgICAgICAgIGlmICghcGVybWlzc2lvbikgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBpZiAoZXhlY3V0ZXIuaXNDb25zb2xlKCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgaWYgKGV4ZWN1dGVyLmlzT3AoKSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBpZiAoZXhlY3V0ZXIuZ2V0UGVybWlzc2lvbnMoKS5pbmNsdWRlcyhwZXJtaXNzaW9uKSkgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICBpZiAoZXhlY3V0ZXIuZ2V0UGVybWlzc2lvbnMoKS5pbmNsdWRlcygnKicpKSByZXR1cm4gdHJ1ZTtcblxuICAgICAgICAgICAgY29uc3Qgc3BsaXQgPSBwZXJtaXNzaW9uLnNwbGl0KCcuJyk7XG4gICAgICAgICAgICBsZXQgc2NvcGUgPSAnJztcbiAgICAgICAgICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIHNwbGl0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNjb3BlKSBzY29wZSA9IGAke3Njb3BlfS4ke2FjdGlvbn1gO1xuICAgICAgICAgICAgICAgIGVsc2Ugc2NvcGUgPSBhY3Rpb247XG5cbiAgICAgICAgICAgICAgICBpZiAoZXhlY3V0ZXIuZ2V0UGVybWlzc2lvbnMoKS5pbmNsdWRlcyhzY29wZSkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIGlmIChleGVjdXRlci5nZXRQZXJtaXNzaW9ucygpLmluY2x1ZGVzKGAke3Njb3BlfS4qYCkpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGV4ZWN1dGUsXG4gICAgICAgICAgICBub3Q6ICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBleGVjdXRlOiAocGVybWlzc2lvbj86IHN0cmluZykgPT4gIWV4ZWN1dGUocGVybWlzc2lvbilcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xu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