matrix-react-sdk
Version:
SDK for matrix.org using React
278 lines (271 loc) • 58.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _StyledRadioGroup = _interopRequireDefault(require("../elements/StyledRadioGroup"));
var _languageHandler = require("../../../languageHandler");
var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton"));
var _RoomAvatar = _interopRequireDefault(require("../avatars/RoomAvatar"));
var _SpaceStore = _interopRequireDefault(require("../../../stores/spaces/SpaceStore"));
var _Modal = _interopRequireDefault(require("../../../Modal"));
var _ManageRestrictedJoinRuleDialog = _interopRequireDefault(require("../dialogs/ManageRestrictedJoinRuleDialog"));
var _RoomUpgradeWarningDialog = _interopRequireDefault(require("../dialogs/RoomUpgradeWarningDialog"));
var _RoomUpgrade = require("../../../utils/RoomUpgrade");
var _arrays = require("../../../utils/arrays");
var _useLocalEcho = require("../../../hooks/useLocalEcho");
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _RoomSettingsDialog = require("../dialogs/RoomSettingsDialog");
var _actions = require("../../../dispatcher/actions");
var _PreferredRoomVersions = require("../../../utils/PreferredRoomVersions");
var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore"));
var _LabelledCheckbox = _interopRequireDefault(require("../elements/LabelledCheckbox"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const JoinRuleSettings = ({
room,
promptUpgrade,
aliasWarning,
onError,
beforeChange,
closeSettingsFn
}) => {
const cli = room.client;
const askToJoinEnabled = _SettingsStore.default.getValue("feature_ask_to_join");
const roomSupportsKnock = (0, _PreferredRoomVersions.doesRoomVersionSupport)(room.getVersion(), _PreferredRoomVersions.PreferredRoomVersions.KnockRooms);
const preferredKnockVersion = !roomSupportsKnock && promptUpgrade ? _PreferredRoomVersions.PreferredRoomVersions.KnockRooms : undefined;
const roomSupportsRestricted = (0, _PreferredRoomVersions.doesRoomVersionSupport)(room.getVersion(), _PreferredRoomVersions.PreferredRoomVersions.RestrictedRooms);
const preferredRestrictionVersion = !roomSupportsRestricted && promptUpgrade ? _PreferredRoomVersions.PreferredRoomVersions.RestrictedRooms : undefined;
const disabled = !room.currentState.mayClientSendStateEvent(_matrix.EventType.RoomJoinRules, cli);
const [content, setContent] = (0, _useLocalEcho.useLocalEcho)(() => room.currentState.getStateEvents(_matrix.EventType.RoomJoinRules, "")?.getContent(), content => cli.sendStateEvent(room.roomId, _matrix.EventType.RoomJoinRules, content, ""), onError);
const {
join_rule: joinRule = _matrix.JoinRule.Invite
} = content || {};
const restrictedAllowRoomIds = joinRule === _matrix.JoinRule.Restricted ? content?.allow?.filter(o => o.type === _matrix.RestrictedAllowType.RoomMembership).map(o => o.room_id) : undefined;
const [isPublicKnockRoom, setIsPublicKnockRoom] = (0, _react.useState)(false);
(0, _react.useEffect)(() => {
if (joinRule === _matrix.JoinRule.Knock) {
cli.getRoomDirectoryVisibility(room.roomId).then(({
visibility
}) => setIsPublicKnockRoom(visibility === _matrix.Visibility.Public)).catch(onError);
}
}, [cli, joinRule, onError, room.roomId]);
const onIsPublicKnockRoomChange = checked => {
cli.setRoomDirectoryVisibility(room.roomId, checked ? _matrix.Visibility.Public : _matrix.Visibility.Private).then(() => setIsPublicKnockRoom(checked)).catch(onError);
};
const editRestrictedRoomIds = async () => {
let selected = restrictedAllowRoomIds;
if (!selected?.length && _SpaceStore.default.instance.activeSpaceRoom) {
selected = [_SpaceStore.default.instance.activeSpaceRoom.roomId];
}
const {
finished
} = _Modal.default.createDialog(_ManageRestrictedJoinRuleDialog.default, {
room,
selected
}, "mx_ManageRestrictedJoinRuleDialog_wrapper");
const [roomIds] = await finished;
return roomIds;
};
const upgradeRequiredDialog = (targetVersion, description) => {
_Modal.default.createDialog(_RoomUpgradeWarningDialog.default, {
roomId: room.roomId,
targetVersion,
description,
doUpgrade: async (opts, fn) => {
const roomId = await (0, _RoomUpgrade.upgradeRoom)(room, targetVersion, opts.invite, true, true, true, progress => {
const total = 2 + progress.updateSpacesTotal + progress.inviteUsersTotal;
if (!progress.roomUpgraded) {
fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_upgrading_room"), 0, total);
} else if (!progress.roomSynced) {
fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_awaiting_room"), 1, total);
} else if (progress.inviteUsersProgress !== undefined && progress.inviteUsersProgress < progress.inviteUsersTotal) {
fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_sending_invites", {
progress: progress.inviteUsersProgress,
count: progress.inviteUsersTotal
}), 2 + progress.inviteUsersProgress, total);
} else if (progress.updateSpacesProgress !== undefined && progress.updateSpacesProgress < progress.updateSpacesTotal) {
fn((0, _languageHandler._t)("room_settings|security|join_rule_upgrade_updating_spaces", {
progress: progress.updateSpacesProgress,
count: progress.updateSpacesTotal
}), 2 + (progress.inviteUsersProgress ?? 0) + progress.updateSpacesProgress, total);
}
});
closeSettingsFn();
// switch to the new room in the background
_dispatcher.default.dispatch({
action: _actions.Action.ViewRoom,
room_id: roomId,
metricsTrigger: undefined // other
});
// open new settings on this tab
_dispatcher.default.dispatch({
action: "open_room_settings",
initial_tab_id: _RoomSettingsDialog.RoomSettingsTab.Security
});
}
});
};
const upgradeRequiredPill = /*#__PURE__*/_react.default.createElement("span", {
className: "mx_JoinRuleSettings_upgradeRequired"
}, (0, _languageHandler._t)("room_settings|security|join_rule_upgrade_required"));
const definitions = [{
value: _matrix.JoinRule.Invite,
label: (0, _languageHandler._t)("room_settings|security|join_rule_invite"),
description: (0, _languageHandler._t)("room_settings|security|join_rule_invite_description"),
checked: joinRule === _matrix.JoinRule.Invite || joinRule === _matrix.JoinRule.Restricted && !restrictedAllowRoomIds?.length
}, {
value: _matrix.JoinRule.Public,
label: (0, _languageHandler._t)("common|public"),
description: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_public_description"), aliasWarning)
}];
if (roomSupportsRestricted || preferredRestrictionVersion || joinRule === _matrix.JoinRule.Restricted) {
let description;
if (joinRule === _matrix.JoinRule.Restricted && restrictedAllowRoomIds?.length) {
// only show the first 4 spaces we know about, so that the UI doesn't grow out of proportion there are lots.
const shownSpaces = restrictedAllowRoomIds.map(roomId => cli.getRoom(roomId)).filter(room => room?.isSpaceRoom()).slice(0, 4);
let moreText;
if (shownSpaces.length < restrictedAllowRoomIds.length) {
if (shownSpaces.length > 0) {
moreText = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_n_more", {
count: restrictedAllowRoomIds.length - shownSpaces.length
});
} else {
moreText = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_summary", {
count: restrictedAllowRoomIds.length
});
}
}
const onRestrictedRoomIdsChange = newAllowRoomIds => {
if (!(0, _arrays.arrayHasDiff)(restrictedAllowRoomIds || [], newAllowRoomIds)) return;
if (!newAllowRoomIds.length) {
setContent({
join_rule: _matrix.JoinRule.Invite
});
return;
}
setContent({
join_rule: _matrix.JoinRule.Restricted,
allow: newAllowRoomIds.map(roomId => ({
type: _matrix.RestrictedAllowType.RoomMembership,
room_id: roomId
}))
});
};
const onEditRestrictedClick = async () => {
const restrictedAllowRoomIds = await editRestrictedRoomIds();
if (!Array.isArray(restrictedAllowRoomIds)) return;
if (restrictedAllowRoomIds.length > 0) {
onRestrictedRoomIdsChange(restrictedAllowRoomIds);
} else {
onChange(_matrix.JoinRule.Invite);
}
};
description = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description", {}, {
a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, {
disabled: disabled,
onClick: onEditRestrictedClick,
kind: "link_inline"
}, sub)
})), /*#__PURE__*/_react.default.createElement("div", {
className: "mx_JoinRuleSettings_spacesWithAccess"
}, /*#__PURE__*/_react.default.createElement("h4", null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description_spaces")), shownSpaces.map(room => {
return /*#__PURE__*/_react.default.createElement("span", {
key: room.roomId
}, /*#__PURE__*/_react.default.createElement(_RoomAvatar.default, {
room: room,
size: "32px"
}), room.name);
}), moreText && /*#__PURE__*/_react.default.createElement("span", null, moreText)));
} else if (_SpaceStore.default.instance.activeSpaceRoom) {
description = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description_active_space", {}, {
spaceName: () => /*#__PURE__*/_react.default.createElement("strong", null, _SpaceStore.default.instance.activeSpaceRoom.name)
});
} else {
description = (0, _languageHandler._t)("room_settings|security|join_rule_restricted_description_prompt");
}
definitions.splice(1, 0, {
value: _matrix.JoinRule.Restricted,
label: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted"), preferredRestrictionVersion && upgradeRequiredPill),
description,
// if there are 0 allowed spaces then render it as invite only instead
checked: joinRule === _matrix.JoinRule.Restricted && !!restrictedAllowRoomIds?.length
});
}
if (askToJoinEnabled && (roomSupportsKnock || preferredKnockVersion)) {
definitions.push({
value: _matrix.JoinRule.Knock,
label: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_knock"), preferredKnockVersion && upgradeRequiredPill),
description: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_knock_description"), /*#__PURE__*/_react.default.createElement(_LabelledCheckbox.default, {
className: "mx_JoinRuleSettings_labelledCheckbox",
disabled: joinRule !== _matrix.JoinRule.Knock,
label: room.isSpaceRoom() ? (0, _languageHandler._t)("room_settings|security|publish_space") : (0, _languageHandler._t)("room_settings|security|publish_room"),
onChange: onIsPublicKnockRoomChange,
value: isPublicKnockRoom
}))
});
}
const onChange = async joinRule => {
const beforeJoinRule = content?.join_rule;
let restrictedAllowRoomIds;
if (joinRule === _matrix.JoinRule.Restricted) {
if (beforeJoinRule === _matrix.JoinRule.Restricted || roomSupportsRestricted) {
// Have the user pick which spaces to allow joins from
restrictedAllowRoomIds = await editRestrictedRoomIds();
if (!Array.isArray(restrictedAllowRoomIds)) return;
} else if (preferredRestrictionVersion) {
// Block this action on a room upgrade otherwise it'd make their room unjoinable
const targetVersion = preferredRestrictionVersion;
let warning;
const userId = cli.getUserId();
const unableToUpdateSomeParents = Array.from(_SpaceStore.default.instance.getKnownParents(room.roomId)).some(roomId => !cli.getRoom(roomId)?.currentState.maySendStateEvent(_matrix.EventType.SpaceChild, userId));
if (unableToUpdateSomeParents) {
warning = /*#__PURE__*/_react.default.createElement("strong", null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_upgrade_warning"));
}
upgradeRequiredDialog(targetVersion, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (0, _languageHandler._t)("room_settings|security|join_rule_restricted_upgrade_description"), warning));
return;
}
// when setting to 0 allowed rooms/spaces set to invite only instead as per the note
if (!restrictedAllowRoomIds?.length) {
joinRule = _matrix.JoinRule.Invite;
}
} else if (joinRule === _matrix.JoinRule.Knock) {
if (preferredKnockVersion) {
upgradeRequiredDialog(preferredKnockVersion);
return;
}
}
if (beforeJoinRule === joinRule && !restrictedAllowRoomIds) return;
if (beforeChange && !(await beforeChange(joinRule))) return;
const newContent = {
join_rule: joinRule
};
// pre-set the accepted spaces with the currently viewed one as per the microcopy
if (joinRule === _matrix.JoinRule.Restricted) {
newContent.allow = restrictedAllowRoomIds?.map(roomId => ({
type: _matrix.RestrictedAllowType.RoomMembership,
room_id: roomId
}));
}
setContent(newContent);
};
return /*#__PURE__*/_react.default.createElement(_StyledRadioGroup.default, {
name: "joinRule",
value: joinRule,
onChange: onChange,
definitions: definitions,
disabled: disabled,
className: "mx_JoinRuleSettings_radioButton"
});
};
var _default = exports.default = JoinRuleSettings;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX1N0eWxlZFJhZGlvR3JvdXAiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2xhbmd1YWdlSGFuZGxlciIsIl9BY2Nlc3NpYmxlQnV0dG9uIiwiX1Jvb21BdmF0YXIiLCJfU3BhY2VTdG9yZSIsIl9Nb2RhbCIsIl9NYW5hZ2VSZXN0cmljdGVkSm9pblJ1bGVEaWFsb2ciLCJfUm9vbVVwZ3JhZGVXYXJuaW5nRGlhbG9nIiwiX1Jvb21VcGdyYWRlIiwiX2FycmF5cyIsIl91c2VMb2NhbEVjaG8iLCJfZGlzcGF0Y2hlciIsIl9Sb29tU2V0dGluZ3NEaWFsb2ciLCJfYWN0aW9ucyIsIl9QcmVmZXJyZWRSb29tVmVyc2lvbnMiLCJfU2V0dGluZ3NTdG9yZSIsIl9MYWJlbGxlZENoZWNrYm94IiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiSm9pblJ1bGVTZXR0aW5ncyIsInJvb20iLCJwcm9tcHRVcGdyYWRlIiwiYWxpYXNXYXJuaW5nIiwib25FcnJvciIsImJlZm9yZUNoYW5nZSIsImNsb3NlU2V0dGluZ3NGbiIsImNsaSIsImNsaWVudCIsImFza1RvSm9pbkVuYWJsZWQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJyb29tU3VwcG9ydHNLbm9jayIsImRvZXNSb29tVmVyc2lvblN1cHBvcnQiLCJnZXRWZXJzaW9uIiwiUHJlZmVycmVkUm9vbVZlcnNpb25zIiwiS25vY2tSb29tcyIsInByZWZlcnJlZEtub2NrVmVyc2lvbiIsInVuZGVmaW5lZCIsInJvb21TdXBwb3J0c1Jlc3RyaWN0ZWQiLCJSZXN0cmljdGVkUm9vbXMiLCJwcmVmZXJyZWRSZXN0cmljdGlvblZlcnNpb24iLCJkaXNhYmxlZCIsImN1cnJlbnRTdGF0ZSIsIm1heUNsaWVudFNlbmRTdGF0ZUV2ZW50IiwiRXZlbnRUeXBlIiwiUm9vbUpvaW5SdWxlcyIsImNvbnRlbnQiLCJzZXRDb250ZW50IiwidXNlTG9jYWxFY2hvIiwiZ2V0U3RhdGVFdmVudHMiLCJnZXRDb250ZW50Iiwic2VuZFN0YXRlRXZlbnQiLCJyb29tSWQiLCJqb2luX3J1bGUiLCJqb2luUnVsZSIsIkpvaW5SdWxlIiwiSW52aXRlIiwicmVzdHJpY3RlZEFsbG93Um9vbUlkcyIsIlJlc3RyaWN0ZWQiLCJhbGxvdyIsImZpbHRlciIsIm8iLCJ0eXBlIiwiUmVzdHJpY3RlZEFsbG93VHlwZSIsIlJvb21NZW1iZXJzaGlwIiwibWFwIiwicm9vbV9pZCIsImlzUHVibGljS25vY2tSb29tIiwic2V0SXNQdWJsaWNLbm9ja1Jvb20iLCJ1c2VTdGF0ZSIsInVzZUVmZmVjdCIsIktub2NrIiwiZ2V0Um9vbURpcmVjdG9yeVZpc2liaWxpdHkiLCJ0aGVuIiwidmlzaWJpbGl0eSIsIlZpc2liaWxpdHkiLCJQdWJsaWMiLCJjYXRjaCIsIm9uSXNQdWJsaWNLbm9ja1Jvb21DaGFuZ2UiLCJjaGVja2VkIiwic2V0Um9vbURpcmVjdG9yeVZpc2liaWxpdHkiLCJQcml2YXRlIiwiZWRpdFJlc3RyaWN0ZWRSb29tSWRzIiwic2VsZWN0ZWQiLCJsZW5ndGgiLCJTcGFjZVN0b3JlIiwiaW5zdGFuY2UiLCJhY3RpdmVTcGFjZVJvb20iLCJmaW5pc2hlZCIsIk1vZGFsIiwiY3JlYXRlRGlhbG9nIiwiTWFuYWdlUmVzdHJpY3RlZEpvaW5SdWxlRGlhbG9nIiwicm9vbUlkcyIsInVwZ3JhZGVSZXF1aXJlZERpYWxvZyIsInRhcmdldFZlcnNpb24iLCJkZXNjcmlwdGlvbiIsIlJvb21VcGdyYWRlV2FybmluZ0RpYWxvZyIsImRvVXBncmFkZSIsIm9wdHMiLCJmbiIsInVwZ3JhZGVSb29tIiwiaW52aXRlIiwicHJvZ3Jlc3MiLCJ0b3RhbCIsInVwZGF0ZVNwYWNlc1RvdGFsIiwiaW52aXRlVXNlcnNUb3RhbCIsInJvb21VcGdyYWRlZCIsIl90Iiwicm9vbVN5bmNlZCIsImludml0ZVVzZXJzUHJvZ3Jlc3MiLCJjb3VudCIsInVwZGF0ZVNwYWNlc1Byb2dyZXNzIiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJBY3Rpb24iLCJWaWV3Um9vbSIsIm1ldHJpY3NUcmlnZ2VyIiwiaW5pdGlhbF90YWJfaWQiLCJSb29tU2V0dGluZ3NUYWIiLCJTZWN1cml0eSIsInVwZ3JhZGVSZXF1aXJlZFBpbGwiLCJjcmVhdGVFbGVtZW50IiwiY2xhc3NOYW1lIiwiZGVmaW5pdGlvbnMiLCJ2YWx1ZSIsImxhYmVsIiwiRnJhZ21lbnQiLCJzaG93blNwYWNlcyIsImdldFJvb20iLCJpc1NwYWNlUm9vbSIsInNsaWNlIiwibW9yZVRleHQiLCJvblJlc3RyaWN0ZWRSb29tSWRzQ2hhbmdlIiwibmV3QWxsb3dSb29tSWRzIiwiYXJyYXlIYXNEaWZmIiwib25FZGl0UmVzdHJpY3RlZENsaWNrIiwiQXJyYXkiLCJpc0FycmF5Iiwib25DaGFuZ2UiLCJzdWIiLCJvbkNsaWNrIiwia2luZCIsImtleSIsInNpemUiLCJuYW1lIiwic3BhY2VOYW1lIiwic3BsaWNlIiwicHVzaCIsImJlZm9yZUpvaW5SdWxlIiwid2FybmluZyIsInVzZXJJZCIsImdldFVzZXJJZCIsInVuYWJsZVRvVXBkYXRlU29tZVBhcmVudHMiLCJmcm9tIiwiZ2V0S25vd25QYXJlbnRzIiwic29tZSIsIm1heVNlbmRTdGF0ZUV2ZW50IiwiU3BhY2VDaGlsZCIsIm5ld0NvbnRlbnQiLCJfZGVmYXVsdCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy92aWV3cy9zZXR0aW5ncy9Kb2luUnVsZVNldHRpbmdzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgUmVhY3ROb2RlLCB1c2VFZmZlY3QsIHVzZVN0YXRlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBKb2luUnVsZSwgUmVzdHJpY3RlZEFsbG93VHlwZSwgUm9vbSwgRXZlbnRUeXBlLCBWaXNpYmlsaXR5IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgUm9vbUpvaW5SdWxlc0V2ZW50Q29udGVudCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiO1xuXG5pbXBvcnQgU3R5bGVkUmFkaW9Hcm91cCwgeyBJRGVmaW5pdGlvbiB9IGZyb20gXCIuLi9lbGVtZW50cy9TdHlsZWRSYWRpb0dyb3VwXCI7XG5pbXBvcnQgeyBfdCB9IGZyb20gXCIuLi8uLi8uLi9sYW5ndWFnZUhhbmRsZXJcIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uIGZyb20gXCIuLi9lbGVtZW50cy9BY2Nlc3NpYmxlQnV0dG9uXCI7XG5pbXBvcnQgUm9vbUF2YXRhciBmcm9tIFwiLi4vYXZhdGFycy9Sb29tQXZhdGFyXCI7XG5pbXBvcnQgU3BhY2VTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc3RvcmVzL3NwYWNlcy9TcGFjZVN0b3JlXCI7XG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4uLy4uLy4uL01vZGFsXCI7XG5pbXBvcnQgTWFuYWdlUmVzdHJpY3RlZEpvaW5SdWxlRGlhbG9nIGZyb20gXCIuLi9kaWFsb2dzL01hbmFnZVJlc3RyaWN0ZWRKb2luUnVsZURpYWxvZ1wiO1xuaW1wb3J0IFJvb21VcGdyYWRlV2FybmluZ0RpYWxvZywgeyBJRmluaXNoZWRPcHRzIH0gZnJvbSBcIi4uL2RpYWxvZ3MvUm9vbVVwZ3JhZGVXYXJuaW5nRGlhbG9nXCI7XG5pbXBvcnQgeyB1cGdyYWRlUm9vbSB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9Sb29tVXBncmFkZVwiO1xuaW1wb3J0IHsgYXJyYXlIYXNEaWZmIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL2FycmF5c1wiO1xuaW1wb3J0IHsgdXNlTG9jYWxFY2hvIH0gZnJvbSBcIi4uLy4uLy4uL2hvb2tzL3VzZUxvY2FsRWNob1wiO1xuaW1wb3J0IGRpcyBmcm9tIFwiLi4vLi4vLi4vZGlzcGF0Y2hlci9kaXNwYXRjaGVyXCI7XG5pbXBvcnQgeyBSb29tU2V0dGluZ3NUYWIgfSBmcm9tIFwiLi4vZGlhbG9ncy9Sb29tU2V0dGluZ3NEaWFsb2dcIjtcbmltcG9ydCB7IEFjdGlvbiB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2FjdGlvbnNcIjtcbmltcG9ydCB7IFZpZXdSb29tUGF5bG9hZCB9IGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL3BheWxvYWRzL1ZpZXdSb29tUGF5bG9hZFwiO1xuaW1wb3J0IHsgZG9lc1Jvb21WZXJzaW9uU3VwcG9ydCwgUHJlZmVycmVkUm9vbVZlcnNpb25zIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL1ByZWZlcnJlZFJvb21WZXJzaW9uc1wiO1xuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCBMYWJlbGxlZENoZWNrYm94IGZyb20gXCIuLi9lbGVtZW50cy9MYWJlbGxlZENoZWNrYm94XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSm9pblJ1bGVTZXR0aW5nc1Byb3BzIHtcbiAgICByb29tOiBSb29tO1xuICAgIHByb21wdFVwZ3JhZGU/OiBib29sZWFuO1xuICAgIGNsb3NlU2V0dGluZ3NGbigpOiB2b2lkO1xuICAgIG9uRXJyb3IoZXJyb3I6IHVua25vd24pOiB2b2lkO1xuICAgIGJlZm9yZUNoYW5nZT8oam9pblJ1bGU6IEpvaW5SdWxlKTogUHJvbWlzZTxib29sZWFuPjsgLy8gaWYgcmV0dXJucyBmYWxzZSB0aGVuIGFib3J0cyB0aGUgY2hhbmdlXG4gICAgYWxpYXNXYXJuaW5nPzogUmVhY3ROb2RlO1xufVxuXG5jb25zdCBKb2luUnVsZVNldHRpbmdzOiBSZWFjdC5GQzxKb2luUnVsZVNldHRpbmdzUHJvcHM+ID0gKHtcbiAgICByb29tLFxuICAgIHByb21wdFVwZ3JhZGUsXG4gICAgYWxpYXNXYXJuaW5nLFxuICAgIG9uRXJyb3IsXG4gICAgYmVmb3JlQ2hhbmdlLFxuICAgIGNsb3NlU2V0dGluZ3NGbixcbn0pID0+IHtcbiAgICBjb25zdCBjbGkgPSByb29tLmNsaWVudDtcblxuICAgIGNvbnN0IGFza1RvSm9pbkVuYWJsZWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiZmVhdHVyZV9hc2tfdG9fam9pblwiKTtcbiAgICBjb25zdCByb29tU3VwcG9ydHNLbm9jayA9IGRvZXNSb29tVmVyc2lvblN1cHBvcnQocm9vbS5nZXRWZXJzaW9uKCksIFByZWZlcnJlZFJvb21WZXJzaW9ucy5Lbm9ja1Jvb21zKTtcbiAgICBjb25zdCBwcmVmZXJyZWRLbm9ja1ZlcnNpb24gPSAhcm9vbVN1cHBvcnRzS25vY2sgJiYgcHJvbXB0VXBncmFkZSA/IFByZWZlcnJlZFJvb21WZXJzaW9ucy5Lbm9ja1Jvb21zIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3Qgcm9vbVN1cHBvcnRzUmVzdHJpY3RlZCA9IGRvZXNSb29tVmVyc2lvblN1cHBvcnQocm9vbS5nZXRWZXJzaW9uKCksIFByZWZlcnJlZFJvb21WZXJzaW9ucy5SZXN0cmljdGVkUm9vbXMpO1xuICAgIGNvbnN0IHByZWZlcnJlZFJlc3RyaWN0aW9uVmVyc2lvbiA9XG4gICAgICAgICFyb29tU3VwcG9ydHNSZXN0cmljdGVkICYmIHByb21wdFVwZ3JhZGUgPyBQcmVmZXJyZWRSb29tVmVyc2lvbnMuUmVzdHJpY3RlZFJvb21zIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgZGlzYWJsZWQgPSAhcm9vbS5jdXJyZW50U3RhdGUubWF5Q2xpZW50U2VuZFN0YXRlRXZlbnQoRXZlbnRUeXBlLlJvb21Kb2luUnVsZXMsIGNsaSk7XG5cbiAgICBjb25zdCBbY29udGVudCwgc2V0Q29udGVudF0gPSB1c2VMb2NhbEVjaG88Um9vbUpvaW5SdWxlc0V2ZW50Q29udGVudCB8IHVuZGVmaW5lZCwgUm9vbUpvaW5SdWxlc0V2ZW50Q29udGVudD4oXG4gICAgICAgICgpID0+IHJvb20uY3VycmVudFN0YXRlLmdldFN0YXRlRXZlbnRzKEV2ZW50VHlwZS5Sb29tSm9pblJ1bGVzLCBcIlwiKT8uZ2V0Q29udGVudCgpLFxuICAgICAgICAoY29udGVudCkgPT4gY2xpLnNlbmRTdGF0ZUV2ZW50KHJvb20ucm9vbUlkLCBFdmVudFR5cGUuUm9vbUpvaW5SdWxlcywgY29udGVudCwgXCJcIiksXG4gICAgICAgIG9uRXJyb3IsXG4gICAgKTtcblxuICAgIGNvbnN0IHsgam9pbl9ydWxlOiBqb2luUnVsZSA9IEpvaW5SdWxlLkludml0ZSB9ID0gY29udGVudCB8fCB7fTtcbiAgICBjb25zdCByZXN0cmljdGVkQWxsb3dSb29tSWRzID1cbiAgICAgICAgam9pblJ1bGUgPT09IEpvaW5SdWxlLlJlc3RyaWN0ZWRcbiAgICAgICAgICAgID8gY29udGVudD8uYWxsb3c/LmZpbHRlcigobykgPT4gby50eXBlID09PSBSZXN0cmljdGVkQWxsb3dUeXBlLlJvb21NZW1iZXJzaGlwKS5tYXAoKG8pID0+IG8ucm9vbV9pZClcbiAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgW2lzUHVibGljS25vY2tSb29tLCBzZXRJc1B1YmxpY0tub2NrUm9vbV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoam9pblJ1bGUgPT09IEpvaW5SdWxlLktub2NrKSB7XG4gICAgICAgICAgICBjbGkuZ2V0Um9vbURpcmVjdG9yeVZpc2liaWxpdHkocm9vbS5yb29tSWQpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHsgdmlzaWJpbGl0eSB9KSA9PiBzZXRJc1B1YmxpY0tub2NrUm9vbSh2aXNpYmlsaXR5ID09PSBWaXNpYmlsaXR5LlB1YmxpYykpXG4gICAgICAgICAgICAgICAgLmNhdGNoKG9uRXJyb3IpO1xuICAgICAgICB9XG4gICAgfSwgW2NsaSwgam9pblJ1bGUsIG9uRXJyb3IsIHJvb20ucm9vbUlkXSk7XG5cbiAgICBjb25zdCBvbklzUHVibGljS25vY2tSb29tQ2hhbmdlID0gKGNoZWNrZWQ6IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICAgICAgY2xpLnNldFJvb21EaXJlY3RvcnlWaXNpYmlsaXR5KHJvb20ucm9vbUlkLCBjaGVja2VkID8gVmlzaWJpbGl0eS5QdWJsaWMgOiBWaXNpYmlsaXR5LlByaXZhdGUpXG4gICAgICAgICAgICAudGhlbigoKSA9PiBzZXRJc1B1YmxpY0tub2NrUm9vbShjaGVja2VkKSlcbiAgICAgICAgICAgIC5jYXRjaChvbkVycm9yKTtcbiAgICB9O1xuXG4gICAgY29uc3QgZWRpdFJlc3RyaWN0ZWRSb29tSWRzID0gYXN5bmMgKCk6IFByb21pc2U8c3RyaW5nW10gfCB1bmRlZmluZWQ+ID0+IHtcbiAgICAgICAgbGV0IHNlbGVjdGVkID0gcmVzdHJpY3RlZEFsbG93Um9vbUlkcztcbiAgICAgICAgaWYgKCFzZWxlY3RlZD8ubGVuZ3RoICYmIFNwYWNlU3RvcmUuaW5zdGFuY2UuYWN0aXZlU3BhY2VSb29tKSB7XG4gICAgICAgICAgICBzZWxlY3RlZCA9IFtTcGFjZVN0b3JlLmluc3RhbmNlLmFjdGl2ZVNwYWNlUm9vbS5yb29tSWRdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgeyBmaW5pc2hlZCB9ID0gTW9kYWwuY3JlYXRlRGlhbG9nKFxuICAgICAgICAgICAgTWFuYWdlUmVzdHJpY3RlZEpvaW5SdWxlRGlhbG9nLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJvb20sXG4gICAgICAgICAgICAgICAgc2VsZWN0ZWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgXCJteF9NYW5hZ2VSZXN0cmljdGVkSm9pblJ1bGVEaWFsb2dfd3JhcHBlclwiLFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IFtyb29tSWRzXSA9IGF3YWl0IGZpbmlzaGVkO1xuICAgICAgICByZXR1cm4gcm9vbUlkcztcbiAgICB9O1xuXG4gICAgY29uc3QgdXBncmFkZVJlcXVpcmVkRGlhbG9nID0gKHRhcmdldFZlcnNpb246IHN0cmluZywgZGVzY3JpcHRpb24/OiBSZWFjdE5vZGUpOiB2b2lkID0+IHtcbiAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nKFJvb21VcGdyYWRlV2FybmluZ0RpYWxvZywge1xuICAgICAgICAgICAgcm9vbUlkOiByb29tLnJvb21JZCxcbiAgICAgICAgICAgIHRhcmdldFZlcnNpb24sXG4gICAgICAgICAgICBkZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGRvVXBncmFkZTogYXN5bmMgKFxuICAgICAgICAgICAgICAgIG9wdHM6IElGaW5pc2hlZE9wdHMsXG4gICAgICAgICAgICAgICAgZm46IChwcm9ncmVzc1RleHQ6IHN0cmluZywgcHJvZ3Jlc3M6IG51bWJlciwgdG90YWw6IG51bWJlcikgPT4gdm9pZCxcbiAgICAgICAgICAgICk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJvb21JZCA9IGF3YWl0IHVwZ3JhZGVSb29tKHJvb20sIHRhcmdldFZlcnNpb24sIG9wdHMuaW52aXRlLCB0cnVlLCB0cnVlLCB0cnVlLCAocHJvZ3Jlc3MpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG90YWwgPSAyICsgcHJvZ3Jlc3MudXBkYXRlU3BhY2VzVG90YWwgKyBwcm9ncmVzcy5pbnZpdGVVc2Vyc1RvdGFsO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXByb2dyZXNzLnJvb21VcGdyYWRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV91cGdyYWRlX3VwZ3JhZGluZ19yb29tXCIpLCAwLCB0b3RhbCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIXByb2dyZXNzLnJvb21TeW5jZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZuKF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfdXBncmFkZV9hd2FpdGluZ19yb29tXCIpLCAxLCB0b3RhbCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy5pbnZpdGVVc2Vyc1Byb2dyZXNzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzLmludml0ZVVzZXJzUHJvZ3Jlc3MgPCBwcm9ncmVzcy5pbnZpdGVVc2Vyc1RvdGFsXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV91cGdyYWRlX3NlbmRpbmdfaW52aXRlc1wiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiBwcm9ncmVzcy5pbnZpdGVVc2Vyc1Byb2dyZXNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogcHJvZ3Jlc3MuaW52aXRlVXNlcnNUb3RhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAyICsgcHJvZ3Jlc3MuaW52aXRlVXNlcnNQcm9ncmVzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy51cGRhdGVTcGFjZXNQcm9ncmVzcyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmVzcy51cGRhdGVTcGFjZXNQcm9ncmVzcyA8IHByb2dyZXNzLnVwZGF0ZVNwYWNlc1RvdGFsXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV91cGdyYWRlX3VwZGF0aW5nX3NwYWNlc1wiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiBwcm9ncmVzcy51cGRhdGVTcGFjZXNQcm9ncmVzcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnQ6IHByb2dyZXNzLnVwZGF0ZVNwYWNlc1RvdGFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgKyAocHJvZ3Jlc3MuaW52aXRlVXNlcnNQcm9ncmVzcyA/PyAwKSArIHByb2dyZXNzLnVwZGF0ZVNwYWNlc1Byb2dyZXNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgY2xvc2VTZXR0aW5nc0ZuKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBzd2l0Y2ggdG8gdGhlIG5ldyByb29tIGluIHRoZSBiYWNrZ3JvdW5kXG4gICAgICAgICAgICAgICAgZGlzLmRpc3BhdGNoPFZpZXdSb29tUGF5bG9hZD4oe1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IEFjdGlvbi5WaWV3Um9vbSxcbiAgICAgICAgICAgICAgICAgICAgcm9vbV9pZDogcm9vbUlkLFxuICAgICAgICAgICAgICAgICAgICBtZXRyaWNzVHJpZ2dlcjogdW5kZWZpbmVkLCAvLyBvdGhlclxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgLy8gb3BlbiBuZXcgc2V0dGluZ3Mgb24gdGhpcyB0YWJcbiAgICAgICAgICAgICAgICBkaXMuZGlzcGF0Y2goe1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IFwib3Blbl9yb29tX3NldHRpbmdzXCIsXG4gICAgICAgICAgICAgICAgICAgIGluaXRpYWxfdGFiX2lkOiBSb29tU2V0dGluZ3NUYWIuU2VjdXJpdHksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgY29uc3QgdXBncmFkZVJlcXVpcmVkUGlsbCA9IChcbiAgICAgICAgPHNwYW4gY2xhc3NOYW1lPVwibXhfSm9pblJ1bGVTZXR0aW5nc191cGdyYWRlUmVxdWlyZWRcIj5cbiAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3VwZ3JhZGVfcmVxdWlyZWRcIil9XG4gICAgICAgIDwvc3Bhbj5cbiAgICApO1xuXG4gICAgY29uc3QgZGVmaW5pdGlvbnM6IElEZWZpbml0aW9uPEpvaW5SdWxlPltdID0gW1xuICAgICAgICB7XG4gICAgICAgICAgICB2YWx1ZTogSm9pblJ1bGUuSW52aXRlLFxuICAgICAgICAgICAgbGFiZWw6IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfaW52aXRlXCIpLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfaW52aXRlX2Rlc2NyaXB0aW9uXCIpLFxuICAgICAgICAgICAgY2hlY2tlZDpcbiAgICAgICAgICAgICAgICBqb2luUnVsZSA9PT0gSm9pblJ1bGUuSW52aXRlIHx8IChqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCAmJiAhcmVzdHJpY3RlZEFsbG93Um9vbUlkcz8ubGVuZ3RoKSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgdmFsdWU6IEpvaW5SdWxlLlB1YmxpYyxcbiAgICAgICAgICAgIGxhYmVsOiBfdChcImNvbW1vbnxwdWJsaWNcIiksXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogKFxuICAgICAgICAgICAgICAgIDw+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3B1YmxpY19kZXNjcmlwdGlvblwiKX1cbiAgICAgICAgICAgICAgICAgICAge2FsaWFzV2FybmluZ31cbiAgICAgICAgICAgICAgICA8Lz5cbiAgICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgXTtcblxuICAgIGlmIChyb29tU3VwcG9ydHNSZXN0cmljdGVkIHx8IHByZWZlcnJlZFJlc3RyaWN0aW9uVmVyc2lvbiB8fCBqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCkge1xuICAgICAgICBsZXQgZGVzY3JpcHRpb247XG4gICAgICAgIGlmIChqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCAmJiByZXN0cmljdGVkQWxsb3dSb29tSWRzPy5sZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIG9ubHkgc2hvdyB0aGUgZmlyc3QgNCBzcGFjZXMgd2Uga25vdyBhYm91dCwgc28gdGhhdCB0aGUgVUkgZG9lc24ndCBncm93IG91dCBvZiBwcm9wb3J0aW9uIHRoZXJlIGFyZSBsb3RzLlxuICAgICAgICAgICAgY29uc3Qgc2hvd25TcGFjZXMgPSByZXN0cmljdGVkQWxsb3dSb29tSWRzXG4gICAgICAgICAgICAgICAgLm1hcCgocm9vbUlkKSA9PiBjbGkuZ2V0Um9vbShyb29tSWQpKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoKHJvb20pID0+IHJvb20/LmlzU3BhY2VSb29tKCkpXG4gICAgICAgICAgICAgICAgLnNsaWNlKDAsIDQpIGFzIFJvb21bXTtcblxuICAgICAgICAgICAgbGV0IG1vcmVUZXh0O1xuICAgICAgICAgICAgaWYgKHNob3duU3BhY2VzLmxlbmd0aCA8IHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNob3duU3BhY2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbW9yZVRleHQgPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3Jlc3RyaWN0ZWRfbl9tb3JlXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiByZXN0cmljdGVkQWxsb3dSb29tSWRzLmxlbmd0aCAtIHNob3duU3BhY2VzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbW9yZVRleHQgPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3Jlc3RyaWN0ZWRfc3VtbWFyeVwiLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogcmVzdHJpY3RlZEFsbG93Um9vbUlkcy5sZW5ndGgsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3Qgb25SZXN0cmljdGVkUm9vbUlkc0NoYW5nZSA9IChuZXdBbGxvd1Jvb21JZHM6IHN0cmluZ1tdKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFhcnJheUhhc0RpZmYocmVzdHJpY3RlZEFsbG93Um9vbUlkcyB8fCBbXSwgbmV3QWxsb3dSb29tSWRzKSkgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFuZXdBbGxvd1Jvb21JZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldENvbnRlbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgam9pbl9ydWxlOiBKb2luUnVsZS5JbnZpdGUsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc2V0Q29udGVudCh7XG4gICAgICAgICAgICAgICAgICAgIGpvaW5fcnVsZTogSm9pblJ1bGUuUmVzdHJpY3RlZCxcbiAgICAgICAgICAgICAgICAgICAgYWxsb3c6IG5ld0FsbG93Um9vbUlkcy5tYXAoKHJvb21JZCkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IFJlc3RyaWN0ZWRBbGxvd1R5cGUuUm9vbU1lbWJlcnNoaXAsXG4gICAgICAgICAgICAgICAgICAgICAgICByb29tX2lkOiByb29tSWQsXG4gICAgICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGNvbnN0IG9uRWRpdFJlc3RyaWN0ZWRDbGljayA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN0cmljdGVkQWxsb3dSb29tSWRzID0gYXdhaXQgZWRpdFJlc3RyaWN0ZWRSb29tSWRzKCk7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMpKSByZXR1cm47XG4gICAgICAgICAgICAgICAgaWYgKHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBvblJlc3RyaWN0ZWRSb29tSWRzQ2hhbmdlKHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlKEpvaW5SdWxlLkludml0ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgZGVzY3JpcHRpb24gPSAoXG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICB7X3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkX2Rlc2NyaXB0aW9uXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhOiAoc3ViKSA9PiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8QWNjZXNzaWJsZUJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXtvbkVkaXRSZXN0cmljdGVkQ2xpY2t9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2luZD1cImxpbmtfaW5saW5lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9BY2Nlc3NpYmxlQnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9Kb2luUnVsZVNldHRpbmdzX3NwYWNlc1dpdGhBY2Nlc3NcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxoND57X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkX2Rlc2NyaXB0aW9uX3NwYWNlc1wiKX08L2g0PlxuICAgICAgICAgICAgICAgICAgICAgICAge3Nob3duU3BhY2VzLm1hcCgocm9vbSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGtleT17cm9vbS5yb29tSWR9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPFJvb21BdmF0YXIgcm9vbT17cm9vbX0gc2l6ZT1cIjMycHhcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3Jvb20ubmFtZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHttb3JlVGV4dCAmJiA8c3Bhbj57bW9yZVRleHR9PC9zcGFuPn1cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2UgaWYgKFNwYWNlU3RvcmUuaW5zdGFuY2UuYWN0aXZlU3BhY2VSb29tKSB7XG4gICAgICAgICAgICBkZXNjcmlwdGlvbiA9IF90KFxuICAgICAgICAgICAgICAgIFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfcmVzdHJpY3RlZF9kZXNjcmlwdGlvbl9hY3RpdmVfc3BhY2VcIixcbiAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHNwYWNlTmFtZTogKCkgPT4gPHN0cm9uZz57U3BhY2VTdG9yZS5pbnN0YW5jZS5hY3RpdmVTcGFjZVJvb20hLm5hbWV9PC9zdHJvbmc+LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVzY3JpcHRpb24gPSBfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX3Jlc3RyaWN0ZWRfZGVzY3JpcHRpb25fcHJvbXB0XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZGVmaW5pdGlvbnMuc3BsaWNlKDEsIDAsIHtcbiAgICAgICAgICAgIHZhbHVlOiBKb2luUnVsZS5SZXN0cmljdGVkLFxuICAgICAgICAgICAgbGFiZWw6IChcbiAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkXCIpfVxuICAgICAgICAgICAgICAgICAgICB7cHJlZmVycmVkUmVzdHJpY3Rpb25WZXJzaW9uICYmIHVwZ3JhZGVSZXF1aXJlZFBpbGx9XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAvLyBpZiB0aGVyZSBhcmUgMCBhbGxvd2VkIHNwYWNlcyB0aGVuIHJlbmRlciBpdCBhcyBpbnZpdGUgb25seSBpbnN0ZWFkXG4gICAgICAgICAgICBjaGVja2VkOiBqb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCAmJiAhIXJlc3RyaWN0ZWRBbGxvd1Jvb21JZHM/Lmxlbmd0aCxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGFza1RvSm9pbkVuYWJsZWQgJiYgKHJvb21TdXBwb3J0c0tub2NrIHx8IHByZWZlcnJlZEtub2NrVmVyc2lvbikpIHtcbiAgICAgICAgZGVmaW5pdGlvbnMucHVzaCh7XG4gICAgICAgICAgICB2YWx1ZTogSm9pblJ1bGUuS25vY2ssXG4gICAgICAgICAgICBsYWJlbDogKFxuICAgICAgICAgICAgICAgIDw+XG4gICAgICAgICAgICAgICAgICAgIHtfdChcInJvb21fc2V0dGluZ3N8c2VjdXJpdHl8am9pbl9ydWxlX2tub2NrXCIpfVxuICAgICAgICAgICAgICAgICAgICB7cHJlZmVycmVkS25vY2tWZXJzaW9uICYmIHVwZ3JhZGVSZXF1aXJlZFBpbGx9XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IChcbiAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICB7X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9rbm9ja19kZXNjcmlwdGlvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgPExhYmVsbGVkQ2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0pvaW5SdWxlU2V0dGluZ3NfbGFiZWxsZWRDaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17am9pblJ1bGUgIT09IEpvaW5SdWxlLktub2NrfVxuICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWw9e1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb20uaXNTcGFjZVJvb20oKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IF90KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxwdWJsaXNoX3NwYWNlXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogX3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fHB1Ymxpc2hfcm9vbVwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25DaGFuZ2U9e29uSXNQdWJsaWNLbm9ja1Jvb21DaGFuZ2V9XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17aXNQdWJsaWNLbm9ja1Jvb219XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBvbkNoYW5nZSA9IGFzeW5jIChqb2luUnVsZTogSm9pblJ1bGUpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgICAgICAgY29uc3QgYmVmb3JlSm9pblJ1bGUgPSBjb250ZW50Py5qb2luX3J1bGU7XG5cbiAgICAgICAgbGV0IHJlc3RyaWN0ZWRBbGxvd1Jvb21JZHM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAoam9pblJ1bGUgPT09IEpvaW5SdWxlLlJlc3RyaWN0ZWQpIHtcbiAgICAgICAgICAgIGlmIChiZWZvcmVKb2luUnVsZSA9PT0gSm9pblJ1bGUuUmVzdHJpY3RlZCB8fCByb29tU3VwcG9ydHNSZXN0cmljdGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gSGF2ZSB0aGUgdXNlciBwaWNrIHdoaWNoIHNwYWNlcyB0byBhbGxvdyBqb2lucyBmcm9tXG4gICAgICAgICAgICAgICAgcmVzdHJpY3RlZEFsbG93Um9vbUlkcyA9IGF3YWl0IGVkaXRSZXN0cmljdGVkUm9vbUlkcygpO1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShyZXN0cmljdGVkQWxsb3dSb29tSWRzKSkgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChwcmVmZXJyZWRSZXN0cmljdGlvblZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAvLyBCbG9jayB0aGlzIGFjdGlvbiBvbiBhIHJvb20gdXBncmFkZSBvdGhlcndpc2UgaXQnZCBtYWtlIHRoZWlyIHJvb20gdW5qb2luYWJsZVxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldFZlcnNpb24gPSBwcmVmZXJyZWRSZXN0cmljdGlvblZlcnNpb247XG5cbiAgICAgICAgICAgICAgICBsZXQgd2FybmluZzogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgY29uc3QgdXNlcklkID0gY2xpLmdldFVzZXJJZCgpITtcbiAgICAgICAgICAgICAgICBjb25zdCB1bmFibGVUb1VwZGF0ZVNvbWVQYXJlbnRzID0gQXJyYXkuZnJvbShTcGFjZVN0b3JlLmluc3RhbmNlLmdldEtub3duUGFyZW50cyhyb29tLnJvb21JZCkpLnNvbWUoXG4gICAgICAgICAgICAgICAgICAgIChyb29tSWQpID0+ICFjbGkuZ2V0Um9vbShyb29tSWQpPy5jdXJyZW50U3RhdGUubWF5U2VuZFN0YXRlRXZlbnQoRXZlbnRUeXBlLlNwYWNlQ2hpbGQsIHVzZXJJZCksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBpZiAodW5hYmxlVG9VcGRhdGVTb21lUGFyZW50cykge1xuICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gPHN0cm9uZz57X3QoXCJyb29tX3NldHRpbmdzfHNlY3VyaXR5fGpvaW5fcnVsZV9yZXN0cmljdGVkX3VwZ3JhZGVfd2FybmluZ1wiKX08L3N0cm9uZz47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdXBncmFkZVJlcXVpcmVkRGlhbG9nKFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRWZXJzaW9uLFxuICAgICAgICAgICAgICAgICAgICA8PlxuICAgICAgICAgICAgICAgICAgICAgICAge190KFwicm9vbV9zZXR0aW5nc3xzZWN1cml0eXxqb2luX3J1bGVfcmVzdHJpY3RlZF91cGdyYWRlX2Rlc2NyaXB0aW9uXCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAge3dhcm5pbmd9XG4gICAgICAgICAgICAgICAgICAgIDwvPixcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB3aGVuIHNldHRpbmcgdG8gMCBhbGxvd2VkIHJvb21zL3NwYWNlcyBzZXQgdG8gaW52aXRlIG9ubHkgaW5zdGVhZCBhcyBwZXIgdGhlIG5vdGVcbiAgICAgICAgICAgIGlmICghcmVzdHJpY3RlZEFsbG93Um9vbUlkcz8ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgam9pblJ1bGUgPSBKb2luUnVsZS5JbnZpdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoam9pblJ1bGUgPT09IEpvaW5SdWxlLktub2NrKSB7XG4gICAgICAgICAgICBpZiAocHJlZmVycmVkS25vY2tWZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgdXBncmFkZVJlcXVpcmVkRGlhbG9nKHByZWZlcnJlZEtub2NrVmVyc2lvbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJlZm9yZUpvaW5SdWxlID09PSBqb2luUnVsZSAmJiAhcmVzdHJpY3RlZEFsbG93Um9vbUlkcykgcmV0dXJuO1xuICAgICAgICBpZiAoYmVmb3JlQ2hhbmdlICYmICEoYXdhaXQgYmVmb3JlQ2hhbmdlKGpvaW5SdWxlKSkpIHJldHVybjtcblxuICAgICAgICBjb25zdCBuZXdDb250ZW50OiBSb29tSm9pblJ1bGVzRXZlbnRDb250ZW50ID0ge1xuICAgICAgICAgICAgam9pbl9ydWxlOiBqb2luUnVsZSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBwcmUtc2V0IHRoZSBhY2NlcHRlZCBzcGFjZXMgd2l0aCB0aGUgY3VycmVudGx5IHZpZXdlZCBvbmUgYXMgcGVyIHRoZSBtaWNyb2NvcHlcbiAgICAgICAgaWYgKGpvaW5SdWxlID09PSBKb2luUnVsZS5SZXN0cmljdGVkKSB7XG4gICAgICAgICAgICBuZXdDb250ZW50LmFsbG93ID0gcmVzdHJpY3RlZEFsbG93Um9vbUlkcz8ubWFwKChyb29tSWQpID0+ICh7XG4gICAgICAgICAgICAgICAgdHlwZTogUmVzdHJpY3RlZEFsbG93VHlwZS5Sb29tTWVtYmVyc2hpcCxcbiAgICAgICAgICAgICAgICByb29tX2lkOiByb29tSWQsXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRDb250ZW50KG5ld0NvbnRlbnQpO1xuICAgIH07XG5cbiAgICByZXR1cm4gKFxuICAgICAgICA8U3R5bGVkUmFkaW9Hcm91cFxuICAgICAgICAgICAgbmFtZT1cImpvaW5SdWxlXCJcbiAgICAgICAgICAgIHZhbHVlPXtqb2luUnVsZX1cbiAgICAgICAgICAgIG9uQ2hhbmdlPXtvbkNoYW5nZX1cbiAgICAgICAgICAgIGRlZmluaXRpb25zPXtkZWZpbml0aW9uc31cbiAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0pvaW5SdWxlU2V0dGluZ3NfcmFkaW9CdXR0b25cIlxuICAgICAgICAvPlxuICAgICk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBKb2luUnVsZVNldHRpbmdzO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBUUEsSUFBQUEsTUFBQSxHQUFBQyx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBR0EsSUFBQUUsaUJBQUEsR0FBQUMsc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFJLGdCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxpQkFBQSxHQUFBRixzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQU0sV0FBQSxHQUFBSCxzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQU8sV0FBQSxHQUFBSixzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQVEsTUFBQSxHQUFBTCxzQkFBQSxDQUFBSCxPQUFBO0FBQ0EsSUFBQVMsK0JBQUEsR0FBQU4sc0JBQUEsQ0FBQUgsT0FBQTtBQUNBLElBQUFVLHlCQUFBLEdBQUFQLHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBVyxZQUFBLEdBQUFYLE9BQUE7QUFDQSxJQUFBWSxPQUFBLEdBQUFaLE9BQUE7QUFDQSxJQUFBYSxhQUFBLEdBQUFiLE9B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