UNPKG

matrix-react-sdk

Version:
213 lines (198 loc) 33.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrix = require("matrix-js-sdk/src/matrix"); var _utils = require("matrix-js-sdk/src/utils"); var _lodash = require("lodash"); var _MatrixClientBackedSettingsHandler = _interopRequireDefault(require("./MatrixClientBackedSettingsHandler")); var _objects = require("../../utils/objects"); var _SettingLevel = require("../SettingLevel"); /* Copyright 2024 New Vector Ltd. Copyright 2019, 2020 The Matrix.org Foundation C.I.C. Copyright 2017 Travis Ralston SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const BREADCRUMBS_LEGACY_EVENT_TYPE = "im.vector.riot.breadcrumb_rooms"; const BREADCRUMBS_EVENT_TYPE = "im.vector.setting.breadcrumbs"; const BREADCRUMBS_EVENT_TYPES = [BREADCRUMBS_LEGACY_EVENT_TYPE, BREADCRUMBS_EVENT_TYPE]; const RECENT_EMOJI_EVENT_TYPE = "io.element.recent_emoji"; const INTEG_PROVISIONING_EVENT_TYPE = "im.vector.setting.integration_provisioning"; const ANALYTICS_EVENT_TYPE = "im.vector.analytics"; const DEFAULT_SETTINGS_EVENT_TYPE = "im.vector.web.settings"; /** * Gets and sets settings at the "account" level for the current user. * This handler does not make use of the roomId parameter. */ class AccountSettingsHandler extends _MatrixClientBackedSettingsHandler.default { constructor(watchers) { super(); (0, _defineProperty2.default)(this, "onAccountData", (event, prevEvent) => { if (event.getType() === "org.matrix.preview_urls") { let val = event.getContent()["disable"]; if (typeof val !== "boolean") { val = null; } else { val = !val; } this.watchers.notifyUpdate("urlPreviewsEnabled", null, _SettingLevel.SettingLevel.ACCOUNT, val); } else if (event.getType() === DEFAULT_SETTINGS_EVENT_TYPE || event.getType() === ANALYTICS_EVENT_TYPE) { // Figure out what changed and fire those updates const prevContent = prevEvent?.getContent() ?? {}; const changedSettings = (0, _objects.objectKeyChanges)(prevContent, event.getContent()); for (const settingName of changedSettings) { const val = event.getContent()[settingName]; this.watchers.notifyUpdate(settingName, null, _SettingLevel.SettingLevel.ACCOUNT, val); } } else if (BREADCRUMBS_EVENT_TYPES.includes(event.getType())) { this.notifyBreadcrumbsUpdate(event); } else if (event.getType() === INTEG_PROVISIONING_EVENT_TYPE) { const val = event.getContent()["enabled"]; this.watchers.notifyUpdate("integrationProvisioning", null, _SettingLevel.SettingLevel.ACCOUNT, val); } else if (event.getType() === RECENT_EMOJI_EVENT_TYPE) { const val = event.getContent()["enabled"]; this.watchers.notifyUpdate("recent_emoji", null, _SettingLevel.SettingLevel.ACCOUNT, val); } }); this.watchers = watchers; } get level() { return _SettingLevel.SettingLevel.ACCOUNT; } initMatrixClient(oldClient, newClient) { oldClient?.removeListener(_matrix.ClientEvent.AccountData, this.onAccountData); newClient.on(_matrix.ClientEvent.AccountData, this.onAccountData); } getValue(settingName, roomId) { // Special case URL previews if (settingName === "urlPreviewsEnabled") { const content = this.getSettings("org.matrix.preview_urls") || {}; // Check to make sure that we actually got a boolean if (typeof content["disable"] !== "boolean") return null; return !content["disable"]; } // Special case for breadcrumbs if (settingName === "breadcrumb_rooms") { let content = this.getSettings(BREADCRUMBS_EVENT_TYPE); if (!content || !content["recent_rooms"]) { content = this.getSettings(BREADCRUMBS_LEGACY_EVENT_TYPE); // This is a bit of a hack, but it makes things slightly easier if (content) content["recent_rooms"] = content["rooms"]; } return content && content["recent_rooms"] ? content["recent_rooms"] : []; } // Special case recent emoji if (settingName === "recent_emoji") { const content = this.getSettings(RECENT_EMOJI_EVENT_TYPE); return content ? content["recent_emoji"] : null; } // Special case integration manager provisioning if (settingName === "integrationProvisioning") { const content = this.getSettings(INTEG_PROVISIONING_EVENT_TYPE); return content ? content["enabled"] : null; } if (settingName === "pseudonymousAnalyticsOptIn") { const content = this.getSettings(ANALYTICS_EVENT_TYPE) || {}; // Check to make sure that we actually got a boolean if (typeof content[settingName] !== "boolean") return null; return content[settingName]; } if (settingName === "MessageComposerInput.insertTrailingColon") { const content = this.getSettings() || {}; const value = content[settingName]; if (value === null || value === undefined) { // Write true as it is the default. This will give us the option // of making this opt-in in the future, without affecting old // users this.setValue(settingName, roomId, true); return true; } return value; } const settings = this.getSettings() || {}; let preferredValue = settings[settingName]; if (preferredValue === null || preferredValue === undefined) { // Honour the old setting on read only if (settingName === "hideAvatarChanges" || settingName === "hideDisplaynameChanges") { preferredValue = settings["hideAvatarDisplaynameChanges"]; } } return preferredValue; } // helper function to set account data then await it being echoed back async setAccountData(eventType, field, value, legacyEventType) { let content = this.getSettings(eventType); if (legacyEventType && !content?.[field]) { content = this.getSettings(legacyEventType); } if (!content) { content = {}; } content[field] = value; // Attach a deferred *before* setting the account data to ensure we catch any requests // which race between different lines. const deferred = (0, _utils.defer)(); const handler = event => { if (event.getType() !== eventType || !(0, _lodash.isEqual)(event.getContent()[field], value)) return; this.client.off(_matrix.ClientEvent.AccountData, handler); deferred.resolve(); }; this.client.on(_matrix.ClientEvent.AccountData, handler); await this.client.setAccountData(eventType, content); await deferred.promise; } setValue(settingName, roomId, newValue) { switch (settingName) { // Special case URL previews case "urlPreviewsEnabled": return this.setAccountData("org.matrix.preview_urls", "disable", !newValue); // Special case for breadcrumbs case "breadcrumb_rooms": return this.setAccountData(BREADCRUMBS_EVENT_TYPE, "recent_rooms", newValue, BREADCRUMBS_LEGACY_EVENT_TYPE); // Special case recent emoji case "recent_emoji": return this.setAccountData(RECENT_EMOJI_EVENT_TYPE, "recent_emoji", newValue); // Special case integration manager provisioning case "integrationProvisioning": return this.setAccountData(INTEG_PROVISIONING_EVENT_TYPE, "enabled", newValue); // Special case analytics case "pseudonymousAnalyticsOptIn": return this.setAccountData(ANALYTICS_EVENT_TYPE, "pseudonymousAnalyticsOptIn", newValue); default: return this.setAccountData(DEFAULT_SETTINGS_EVENT_TYPE, settingName, newValue); } } canSetValue(settingName, roomId) { return true; // It's their account, so they should be able to } isSupported() { return this.client && !this.client.isGuest(); } getSettings(eventType = "im.vector.web.settings") { // TODO: [TS] Types on return if (!this.client) return null; const event = this.client.getAccountData(eventType); if (!event || !event.getContent()) return null; return (0, _objects.objectClone)(event.getContent()); // clone to prevent mutation } notifyBreadcrumbsUpdate(event) { let val = []; if (event.getType() === BREADCRUMBS_LEGACY_EVENT_TYPE) { // This seems fishy - try and get the event for the new rooms const newType = this.getSettings(BREADCRUMBS_EVENT_TYPE); if (newType) val = newType["recent_rooms"];else val = event.getContent()["rooms"]; } else if (event.getType() === BREADCRUMBS_EVENT_TYPE) { val = event.getContent()["recent_rooms"]; } else { return; // for sanity, not because we expect to be here. } this.watchers.notifyUpdate("breadcrumb_rooms", null, _SettingLevel.SettingLevel.ACCOUNT, val || []); } } exports.default = AccountSettingsHandler; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl91dGlscyIsIl9sb2Rhc2giLCJfTWF0cml4Q2xpZW50QmFja2VkU2V0dGluZ3NIYW5kbGVyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9vYmplY3RzIiwiX1NldHRpbmdMZXZlbCIsIkJSRUFEQ1JVTUJTX0xFR0FDWV9FVkVOVF9UWVBFIiwiQlJFQURDUlVNQlNfRVZFTlRfVFlQRSIsIkJSRUFEQ1JVTUJTX0VWRU5UX1RZUEVTIiwiUkVDRU5UX0VNT0pJX0VWRU5UX1RZUEUiLCJJTlRFR19QUk9WSVNJT05JTkdfRVZFTlRfVFlQRSIsIkFOQUxZVElDU19FVkVOVF9UWVBFIiwiREVGQVVMVF9TRVRUSU5HU19FVkVOVF9UWVBFIiwiQWNjb3VudFNldHRpbmdzSGFuZGxlciIsIk1hdHJpeENsaWVudEJhY2tlZFNldHRpbmdzSGFuZGxlciIsImNvbnN0cnVjdG9yIiwid2F0Y2hlcnMiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsImV2ZW50IiwicHJldkV2ZW50IiwiZ2V0VHlwZSIsInZhbCIsImdldENvbnRlbnQiLCJub3RpZnlVcGRhdGUiLCJTZXR0aW5nTGV2ZWwiLCJBQ0NPVU5UIiwicHJldkNvbnRlbnQiLCJjaGFuZ2VkU2V0dGluZ3MiLCJvYmplY3RLZXlDaGFuZ2VzIiwic2V0dGluZ05hbWUiLCJpbmNsdWRlcyIsIm5vdGlmeUJyZWFkY3J1bWJzVXBkYXRlIiwibGV2ZWwiLCJpbml0TWF0cml4Q2xpZW50Iiwib2xkQ2xpZW50IiwibmV3Q2xpZW50IiwicmVtb3ZlTGlzdGVuZXIiLCJDbGllbnRFdmVudCIsIkFjY291bnREYXRhIiwib25BY2NvdW50RGF0YSIsIm9uIiwiZ2V0VmFsdWUiLCJyb29tSWQiLCJjb250ZW50IiwiZ2V0U2V0dGluZ3MiLCJ2YWx1ZSIsInVuZGVmaW5lZCIsInNldFZhbHVlIiwic2V0dGluZ3MiLCJwcmVmZXJyZWRWYWx1ZSIsInNldEFjY291bnREYXRhIiwiZXZlbnRUeXBlIiwiZmllbGQiLCJsZWdhY3lFdmVudFR5cGUiLCJkZWZlcnJlZCIsImRlZmVyIiwiaGFuZGxlciIsImlzRXF1YWwiLCJjbGllbnQiLCJvZmYiLCJyZXNvbHZlIiwicHJvbWlzZSIsIm5ld1ZhbHVlIiwiY2FuU2V0VmFsdWUiLCJpc1N1cHBvcnRlZCIsImlzR3Vlc3QiLCJnZXRBY2NvdW50RGF0YSIsIm9iamVjdENsb25lIiwibmV3VHlwZSIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2V0dGluZ3MvaGFuZGxlcnMvQWNjb3VudFNldHRpbmdzSGFuZGxlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxOSwgMjAyMCBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuQ29weXJpZ2h0IDIwMTcgVHJhdmlzIFJhbHN0b25cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHsgQ2xpZW50RXZlbnQsIE1hdHJpeENsaWVudCwgTWF0cml4RXZlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBkZWZlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy91dGlsc1wiO1xuaW1wb3J0IHsgaXNFcXVhbCB9IGZyb20gXCJsb2Rhc2hcIjtcblxuaW1wb3J0IE1hdHJpeENsaWVudEJhY2tlZFNldHRpbmdzSGFuZGxlciBmcm9tIFwiLi9NYXRyaXhDbGllbnRCYWNrZWRTZXR0aW5nc0hhbmRsZXJcIjtcbmltcG9ydCB7IG9iamVjdENsb25lLCBvYmplY3RLZXlDaGFuZ2VzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL29iamVjdHNcIjtcbmltcG9ydCB7IFNldHRpbmdMZXZlbCB9IGZyb20gXCIuLi9TZXR0aW5nTGV2ZWxcIjtcbmltcG9ydCB7IFdhdGNoTWFuYWdlciB9IGZyb20gXCIuLi9XYXRjaE1hbmFnZXJcIjtcblxuY29uc3QgQlJFQURDUlVNQlNfTEVHQUNZX0VWRU5UX1RZUEUgPSBcImltLnZlY3Rvci5yaW90LmJyZWFkY3J1bWJfcm9vbXNcIjtcbmNvbnN0IEJSRUFEQ1JVTUJTX0VWRU5UX1RZUEUgPSBcImltLnZlY3Rvci5zZXR0aW5nLmJyZWFkY3J1bWJzXCI7XG5jb25zdCBCUkVBRENSVU1CU19FVkVOVF9UWVBFUyA9IFtCUkVBRENSVU1CU19MRUdBQ1lfRVZFTlRfVFlQRSwgQlJFQURDUlVNQlNfRVZFTlRfVFlQRV07XG5jb25zdCBSRUNFTlRfRU1PSklfRVZFTlRfVFlQRSA9IFwiaW8uZWxlbWVudC5yZWNlbnRfZW1vamlcIjtcbmNvbnN0IElOVEVHX1BST1ZJU0lPTklOR19FVkVOVF9UWVBFID0gXCJpbS52ZWN0b3Iuc2V0dGluZy5pbnRlZ3JhdGlvbl9wcm92aXNpb25pbmdcIjtcbmNvbnN0IEFOQUxZVElDU19FVkVOVF9UWVBFID0gXCJpbS52ZWN0b3IuYW5hbHl0aWNzXCI7XG5jb25zdCBERUZBVUxUX1NFVFRJTkdTX0VWRU5UX1RZUEUgPSBcImltLnZlY3Rvci53ZWIuc2V0dGluZ3NcIjtcblxuLyoqXG4gKiBHZXRzIGFuZCBzZXRzIHNldHRpbmdzIGF0IHRoZSBcImFjY291bnRcIiBsZXZlbCBmb3IgdGhlIGN1cnJlbnQgdXNlci5cbiAqIFRoaXMgaGFuZGxlciBkb2VzIG5vdCBtYWtlIHVzZSBvZiB0aGUgcm9vbUlkIHBhcmFtZXRlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWNjb3VudFNldHRpbmdzSGFuZGxlciBleHRlbmRzIE1hdHJpeENsaWVudEJhY2tlZFNldHRpbmdzSGFuZGxlciB7XG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB3YXRjaGVyczogV2F0Y2hNYW5hZ2VyKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBsZXZlbCgpOiBTZXR0aW5nTGV2ZWwge1xuICAgICAgICByZXR1cm4gU2V0dGluZ0xldmVsLkFDQ09VTlQ7XG4gICAgfVxuXG4gICAgcHVibGljIGluaXRNYXRyaXhDbGllbnQob2xkQ2xpZW50OiBNYXRyaXhDbGllbnQsIG5ld0NsaWVudDogTWF0cml4Q2xpZW50KTogdm9pZCB7XG4gICAgICAgIG9sZENsaWVudD8ucmVtb3ZlTGlzdGVuZXIoQ2xpZW50RXZlbnQuQWNjb3VudERhdGEsIHRoaXMub25BY2NvdW50RGF0YSk7XG4gICAgICAgIG5ld0NsaWVudC5vbihDbGllbnRFdmVudC5BY2NvdW50RGF0YSwgdGhpcy5vbkFjY291bnREYXRhKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uQWNjb3VudERhdGEgPSAoZXZlbnQ6IE1hdHJpeEV2ZW50LCBwcmV2RXZlbnQ/OiBNYXRyaXhFdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuZ2V0VHlwZSgpID09PSBcIm9yZy5tYXRyaXgucHJldmlld191cmxzXCIpIHtcbiAgICAgICAgICAgIGxldCB2YWwgPSBldmVudC5nZXRDb250ZW50KClbXCJkaXNhYmxlXCJdO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWwgIT09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICAgICAgdmFsID0gbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFsID0gIXZhbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy53YXRjaGVycy5ub3RpZnlVcGRhdGUoXCJ1cmxQcmV2aWV3c0VuYWJsZWRcIiwgbnVsbCwgU2V0dGluZ0xldmVsLkFDQ09VTlQsIHZhbCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQuZ2V0VHlwZSgpID09PSBERUZBVUxUX1NFVFRJTkdTX0VWRU5UX1RZUEUgfHwgZXZlbnQuZ2V0VHlwZSgpID09PSBBTkFMWVRJQ1NfRVZFTlRfVFlQRSkge1xuICAgICAgICAgICAgLy8gRmlndXJlIG91dCB3aGF0IGNoYW5nZWQgYW5kIGZpcmUgdGhvc2UgdXBkYXRlc1xuICAgICAgICAgICAgY29uc3QgcHJldkNvbnRlbnQgPSBwcmV2RXZlbnQ/LmdldENvbnRlbnQoKSA/PyB7fTtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZWRTZXR0aW5ncyA9IG9iamVjdEtleUNoYW5nZXM8UmVjb3JkPHN0cmluZywgYW55Pj4ocHJldkNvbnRlbnQsIGV2ZW50LmdldENvbnRlbnQoKSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHNldHRpbmdOYW1lIG9mIGNoYW5nZWRTZXR0aW5ncykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbCA9IGV2ZW50LmdldENvbnRlbnQoKVtzZXR0aW5nTmFtZV07XG4gICAgICAgICAgICAgICAgdGhpcy53YXRjaGVycy5ub3RpZnlVcGRhdGUoc2V0dGluZ05hbWUsIG51bGwsIFNldHRpbmdMZXZlbC5BQ0NPVU5ULCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKEJSRUFEQ1JVTUJTX0VWRU5UX1RZUEVTLmluY2x1ZGVzKGV2ZW50LmdldFR5cGUoKSkpIHtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5QnJlYWRjcnVtYnNVcGRhdGUoZXZlbnQpO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmdldFR5cGUoKSA9PT0gSU5URUdfUFJPVklTSU9OSU5HX0VWRU5UX1RZUEUpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbCA9IGV2ZW50LmdldENvbnRlbnQoKVtcImVuYWJsZWRcIl07XG4gICAgICAgICAgICB0aGlzLndhdGNoZXJzLm5vdGlmeVVwZGF0ZShcImludGVncmF0aW9uUHJvdmlzaW9uaW5nXCIsIG51bGwsIFNldHRpbmdMZXZlbC5BQ0NPVU5ULCB2YWwpO1xuICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LmdldFR5cGUoKSA9PT0gUkVDRU5UX0VNT0pJX0VWRU5UX1RZUEUpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbCA9IGV2ZW50LmdldENvbnRlbnQoKVtcImVuYWJsZWRcIl07XG4gICAgICAgICAgICB0aGlzLndhdGNoZXJzLm5vdGlmeVVwZGF0ZShcInJlY2VudF9lbW9qaVwiLCBudWxsLCBTZXR0aW5nTGV2ZWwuQUNDT1VOVCwgdmFsKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBwdWJsaWMgZ2V0VmFsdWUoc2V0dGluZ05hbWU6IHN0cmluZywgcm9vbUlkOiBzdHJpbmcpOiBhbnkge1xuICAgICAgICAvLyBTcGVjaWFsIGNhc2UgVVJMIHByZXZpZXdzXG4gICAgICAgIGlmIChzZXR0aW5nTmFtZSA9PT0gXCJ1cmxQcmV2aWV3c0VuYWJsZWRcIikge1xuICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoXCJvcmcubWF0cml4LnByZXZpZXdfdXJsc1wiKSB8fCB7fTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgdG8gbWFrZSBzdXJlIHRoYXQgd2UgYWN0dWFsbHkgZ290IGEgYm9vbGVhblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZW50W1wiZGlzYWJsZVwiXSAhPT0gXCJib29sZWFuXCIpIHJldHVybiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuICFjb250ZW50W1wiZGlzYWJsZVwiXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgYnJlYWRjcnVtYnNcbiAgICAgICAgaWYgKHNldHRpbmdOYW1lID09PSBcImJyZWFkY3J1bWJfcm9vbXNcIikge1xuICAgICAgICAgICAgbGV0IGNvbnRlbnQgPSB0aGlzLmdldFNldHRpbmdzKEJSRUFEQ1JVTUJTX0VWRU5UX1RZUEUpO1xuICAgICAgICAgICAgaWYgKCFjb250ZW50IHx8ICFjb250ZW50W1wicmVjZW50X3Jvb21zXCJdKSB7XG4gICAgICAgICAgICAgICAgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoQlJFQURDUlVNQlNfTEVHQUNZX0VWRU5UX1RZUEUpO1xuXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIGJpdCBvZiBhIGhhY2ssIGJ1dCBpdCBtYWtlcyB0aGluZ3Mgc2xpZ2h0bHkgZWFzaWVyXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRlbnQpIGNvbnRlbnRbXCJyZWNlbnRfcm9vbXNcIl0gPSBjb250ZW50W1wicm9vbXNcIl07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjb250ZW50ICYmIGNvbnRlbnRbXCJyZWNlbnRfcm9vbXNcIl0gPyBjb250ZW50W1wicmVjZW50X3Jvb21zXCJdIDogW107XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTcGVjaWFsIGNhc2UgcmVjZW50IGVtb2ppXG4gICAgICAgIGlmIChzZXR0aW5nTmFtZSA9PT0gXCJyZWNlbnRfZW1vamlcIikge1xuICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoUkVDRU5UX0VNT0pJX0VWRU5UX1RZUEUpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnQgPyBjb250ZW50W1wicmVjZW50X2Vtb2ppXCJdIDogbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwZWNpYWwgY2FzZSBpbnRlZ3JhdGlvbiBtYW5hZ2VyIHByb3Zpc2lvbmluZ1xuICAgICAgICBpZiAoc2V0dGluZ05hbWUgPT09IFwiaW50ZWdyYXRpb25Qcm92aXNpb25pbmdcIikge1xuICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoSU5URUdfUFJPVklTSU9OSU5HX0VWRU5UX1RZUEUpO1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnQgPyBjb250ZW50W1wiZW5hYmxlZFwiXSA6IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2V0dGluZ05hbWUgPT09IFwicHNldWRvbnltb3VzQW5hbHl0aWNzT3B0SW5cIikge1xuICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoQU5BTFlUSUNTX0VWRU5UX1RZUEUpIHx8IHt9O1xuICAgICAgICAgICAgLy8gQ2hlY2sgdG8gbWFrZSBzdXJlIHRoYXQgd2UgYWN0dWFsbHkgZ290IGEgYm9vbGVhblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZW50W3NldHRpbmdOYW1lXSAhPT0gXCJib29sZWFuXCIpIHJldHVybiBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRlbnRbc2V0dGluZ05hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNldHRpbmdOYW1lID09PSBcIk1lc3NhZ2VDb21wb3NlcklucHV0Lmluc2VydFRyYWlsaW5nQ29sb25cIikge1xuICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoKSB8fCB7fTtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY29udGVudFtzZXR0aW5nTmFtZV07XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIC8vIFdyaXRlIHRydWUgYXMgaXQgaXMgdGhlIGRlZmF1bHQuIFRoaXMgd2lsbCBnaXZlIHVzIHRoZSBvcHRpb25cbiAgICAgICAgICAgICAgICAvLyBvZiBtYWtpbmcgdGhpcyBvcHQtaW4gaW4gdGhlIGZ1dHVyZSwgd2l0aG91dCBhZmZlY3Rpbmcgb2xkXG4gICAgICAgICAgICAgICAgLy8gdXNlcnNcbiAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKHNldHRpbmdOYW1lLCByb29tSWQsIHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLmdldFNldHRpbmdzKCkgfHwge307XG4gICAgICAgIGxldCBwcmVmZXJyZWRWYWx1ZSA9IHNldHRpbmdzW3NldHRpbmdOYW1lXTtcblxuICAgICAgICBpZiAocHJlZmVycmVkVmFsdWUgPT09IG51bGwgfHwgcHJlZmVycmVkVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gSG9ub3VyIHRoZSBvbGQgc2V0dGluZyBvbiByZWFkIG9ubHlcbiAgICAgICAgICAgIGlmIChzZXR0aW5nTmFtZSA9PT0gXCJoaWRlQXZhdGFyQ2hhbmdlc1wiIHx8IHNldHRpbmdOYW1lID09PSBcImhpZGVEaXNwbGF5bmFtZUNoYW5nZXNcIikge1xuICAgICAgICAgICAgICAgIHByZWZlcnJlZFZhbHVlID0gc2V0dGluZ3NbXCJoaWRlQXZhdGFyRGlzcGxheW5hbWVDaGFuZ2VzXCJdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHByZWZlcnJlZFZhbHVlO1xuICAgIH1cblxuICAgIC8vIGhlbHBlciBmdW5jdGlvbiB0byBzZXQgYWNjb3VudCBkYXRhIHRoZW4gYXdhaXQgaXQgYmVpbmcgZWNob2VkIGJhY2tcbiAgICBwcml2YXRlIGFzeW5jIHNldEFjY291bnREYXRhKFxuICAgICAgICBldmVudFR5cGU6IHN0cmluZyxcbiAgICAgICAgZmllbGQ6IHN0cmluZyxcbiAgICAgICAgdmFsdWU6IGFueSxcbiAgICAgICAgbGVnYWN5RXZlbnRUeXBlPzogc3RyaW5nLFxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBsZXQgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MoZXZlbnRUeXBlKTtcbiAgICAgICAgaWYgKGxlZ2FjeUV2ZW50VHlwZSAmJiAhY29udGVudD8uW2ZpZWxkXSkge1xuICAgICAgICAgICAgY29udGVudCA9IHRoaXMuZ2V0U2V0dGluZ3MobGVnYWN5RXZlbnRUeXBlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghY29udGVudCkge1xuICAgICAgICAgICAgY29udGVudCA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGVudFtmaWVsZF0gPSB2YWx1ZTtcblxuICAgICAgICAvLyBBdHRhY2ggYSBkZWZlcnJlZCAqYmVmb3JlKiBzZXR0aW5nIHRoZSBhY2NvdW50IGRhdGEgdG8gZW5zdXJlIHdlIGNhdGNoIGFueSByZXF1ZXN0c1xuICAgICAgICAvLyB3aGljaCByYWNlIGJldHdlZW4gZGlmZmVyZW50IGxpbmVzLlxuICAgICAgICBjb25zdCBkZWZlcnJlZCA9IGRlZmVyPHZvaWQ+KCk7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSAoZXZlbnQ6IE1hdHJpeEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuZ2V0VHlwZSgpICE9PSBldmVudFR5cGUgfHwgIWlzRXF1YWwoZXZlbnQuZ2V0Q29udGVudCgpW2ZpZWxkXSwgdmFsdWUpKSByZXR1cm47XG4gICAgICAgICAgICB0aGlzLmNsaWVudC5vZmYoQ2xpZW50RXZlbnQuQWNjb3VudERhdGEsIGhhbmRsZXIpO1xuICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZSgpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLmNsaWVudC5vbihDbGllbnRFdmVudC5BY2NvdW50RGF0YSwgaGFuZGxlcik7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuc2V0QWNjb3VudERhdGEoZXZlbnRUeXBlLCBjb250ZW50KTtcblxuICAgICAgICBhd2FpdCBkZWZlcnJlZC5wcm9taXNlO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRWYWx1ZShzZXR0aW5nTmFtZTogc3RyaW5nLCByb29tSWQ6IHN0cmluZywgbmV3VmFsdWU6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBzd2l0Y2ggKHNldHRpbmdOYW1lKSB7XG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgVVJMIHByZXZpZXdzXG4gICAgICAgICAgICBjYXNlIFwidXJsUHJldmlld3NFbmFibGVkXCI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0QWNjb3VudERhdGEoXCJvcmcubWF0cml4LnByZXZpZXdfdXJsc1wiLCBcImRpc2FibGVcIiwgIW5ld1ZhbHVlKTtcblxuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIGZvciBicmVhZGNydW1ic1xuICAgICAgICAgICAgY2FzZSBcImJyZWFkY3J1bWJfcm9vbXNcIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXRBY2NvdW50RGF0YShcbiAgICAgICAgICAgICAgICAgICAgQlJFQURDUlVNQlNfRVZFTlRfVFlQRSxcbiAgICAgICAgICAgICAgICAgICAgXCJyZWNlbnRfcm9vbXNcIixcbiAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIEJSRUFEQ1JVTUJTX0xFR0FDWV9FVkVOVF9UWVBFLFxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSByZWNlbnQgZW1vamlcbiAgICAgICAgICAgIGNhc2UgXCJyZWNlbnRfZW1vamlcIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXRBY2NvdW50RGF0YShSRUNFTlRfRU1PSklfRVZFTlRfVFlQRSwgXCJyZWNlbnRfZW1vamlcIiwgbmV3VmFsdWUpO1xuXG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgaW50ZWdyYXRpb24gbWFuYWdlciBwcm92aXNpb25pbmdcbiAgICAgICAgICAgIGNhc2UgXCJpbnRlZ3JhdGlvblByb3Zpc2lvbmluZ1wiOlxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnNldEFjY291bnREYXRhKElOVEVHX1BST1ZJU0lPTklOR19FVkVOVF9UWVBFLCBcImVuYWJsZWRcIiwgbmV3VmFsdWUpO1xuXG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgYW5hbHl0aWNzXG4gICAgICAgICAgICBjYXNlIFwicHNldWRvbnltb3VzQW5hbHl0aWNzT3B0SW5cIjpcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXRBY2NvdW50RGF0YShBTkFMWVRJQ1NfRVZFTlRfVFlQRSwgXCJwc2V1ZG9ueW1vdXNBbmFseXRpY3NPcHRJblwiLCBuZXdWYWx1ZSk7XG5cbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0QWNjb3VudERhdGEoREVGQVVMVF9TRVRUSU5HU19FVkVOVF9UWVBFLCBzZXR0aW5nTmFtZSwgbmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNhblNldFZhbHVlKHNldHRpbmdOYW1lOiBzdHJpbmcsIHJvb21JZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0cnVlOyAvLyBJdCdzIHRoZWlyIGFjY291bnQsIHNvIHRoZXkgc2hvdWxkIGJlIGFibGUgdG9cbiAgICB9XG5cbiAgICBwdWJsaWMgaXNTdXBwb3J0ZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsaWVudCAmJiAhdGhpcy5jbGllbnQuaXNHdWVzdCgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0U2V0dGluZ3MoZXZlbnRUeXBlID0gXCJpbS52ZWN0b3Iud2ViLnNldHRpbmdzXCIpOiBhbnkge1xuICAgICAgICAvLyBUT0RPOiBbVFNdIFR5cGVzIG9uIHJldHVyblxuICAgICAgICBpZiAoIXRoaXMuY2xpZW50KSByZXR1cm4gbnVsbDtcblxuICAgICAgICBjb25zdCBldmVudCA9IHRoaXMuY2xpZW50LmdldEFjY291bnREYXRhKGV2ZW50VHlwZSk7XG4gICAgICAgIGlmICghZXZlbnQgfHwgIWV2ZW50LmdldENvbnRlbnQoKSkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiBvYmplY3RDbG9uZShldmVudC5nZXRDb250ZW50KCkpOyAvLyBjbG9uZSB0byBwcmV2ZW50IG11dGF0aW9uXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBub3RpZnlCcmVhZGNydW1ic1VwZGF0ZShldmVudDogTWF0cml4RXZlbnQpOiB2b2lkIHtcbiAgICAgICAgbGV0IHZhbCA9IFtdO1xuICAgICAgICBpZiAoZXZlbnQuZ2V0VHlwZSgpID09PSBCUkVBRENSVU1CU19MRUdBQ1lfRVZFTlRfVFlQRSkge1xuICAgICAgICAgICAgLy8gVGhpcyBzZWVtcyBmaXNoeSAtIHRyeSBhbmQgZ2V0IHRoZSBldmVudCBmb3IgdGhlIG5ldyByb29tc1xuICAgICAgICAgICAgY29uc3QgbmV3VHlwZSA9IHRoaXMuZ2V0U2V0dGluZ3MoQlJFQURDUlVNQlNfRVZFTlRfVFlQRSk7XG4gICAgICAgICAgICBpZiAobmV3VHlwZSkgdmFsID0gbmV3VHlwZVtcInJlY2VudF9yb29tc1wiXTtcbiAgICAgICAgICAgIGVsc2UgdmFsID0gZXZlbnQuZ2V0Q29udGVudCgpW1wicm9vbXNcIl07XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQuZ2V0VHlwZSgpID09PSBCUkVBRENSVU1CU19FVkVOVF9UWVBFKSB7XG4gICAgICAgICAgICB2YWwgPSBldmVudC5nZXRDb250ZW50KClbXCJyZWNlbnRfcm9vbXNcIl07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm47IC8vIGZvciBzYW5pdHksIG5vdCBiZWNhdXNlIHdlIGV4cGVjdCB0byBiZSBoZXJlLlxuICAgICAgICB9XG4gICAgICAgIHRoaXMud2F0Y2hlcnMubm90aWZ5VXBkYXRlKFwiYnJlYWRjcnVtYl9yb29tc1wiLCBudWxsLCBTZXR0aW5nTGV2ZWwuQUNDT1VOVCwgdmFsIHx8IFtdKTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0EsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsTUFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsT0FBQSxHQUFBRixPQUFBO0FBRUEsSUFBQUcsa0NBQUEsR0FBQUMsc0JBQUEsQ0FBQUosT0FBQTtBQUNBLElBQUFLLFFBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLGFBQUEsR0FBQU4sT0FBQTtBQWZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBV0EsTUFBTU8sNkJBQTZCLEdBQUcsaUNBQWlDO0FBQ3ZFLE1B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