UNPKG

matrix-react-sdk

Version:
362 lines (357 loc) 59.7 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 _react = _interopRequireDefault(require("react")); var _matrix = require("matrix-js-sdk/src/matrix"); var _types = require("matrix-js-sdk/src/types"); var _lodash = require("lodash"); var _compoundWeb = require("@vector-im/compound-web"); var _userAddSolid = _interopRequireDefault(require("@vector-im/compound-design-tokens/assets/web/icons/user-add-solid")); var _languageHandler = require("../../../languageHandler"); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _RoomInvite = require("../../../RoomInvite"); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _BaseCard = _interopRequireDefault(require("../right_panel/BaseCard")); var _TruncatedList = _interopRequireDefault(require("../elements/TruncatedList")); var _Spinner = _interopRequireDefault(require("../elements/Spinner")); var _SearchBox = _interopRequireDefault(require("../../structures/SearchBox")); var _EntityTile = _interopRequireDefault(require("./EntityTile")); var _MemberTile = _interopRequireDefault(require("./MemberTile")); var _BaseAvatar = _interopRequireDefault(require("../avatars/BaseAvatar")); var _UIComponents = require("../../../customisations/helpers/UIComponents"); var _UIFeature = require("../../../settings/UIFeature"); var _PosthogTrackers = _interopRequireDefault(require("../../../PosthogTrackers")); var _SDKContext = require("../../../contexts/SDKContext"); var _canInviteTo = require("../../../utils/room/canInviteTo"); var _inviteToRoom = require("../../../utils/room/inviteToRoom"); var _actions = require("../../../dispatcher/actions"); /* Copyright 2024 New Vector Ltd. Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com> Copyright 2017, 2018 New Vector Ltd Copyright 2017 Vector Creations Ltd Copyright 2015, 2016 OpenMarket Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const INITIAL_LOAD_NUM_MEMBERS = 30; const INITIAL_LOAD_NUM_INVITED = 5; const SHOW_MORE_INCREMENT = 100; class MemberList extends _react.default.Component { constructor(props, context) { super(props, context); (0, _defineProperty2.default)(this, "showPresence", void 0); (0, _defineProperty2.default)(this, "mounted", false); (0, _defineProperty2.default)(this, "tiles", new Map()); (0, _defineProperty2.default)(this, "onUserPresenceChange", (event, user) => { // Attach a SINGLE listener for global presence changes then locate the // member tile and re-render it. This is more efficient than every tile // ever attaching their own listener. const tile = this.tiles.get(user.userId); if (tile) { this.updateList(); // reorder the membership list } }); (0, _defineProperty2.default)(this, "onRoom", room => { if (room.roomId !== this.props.roomId) { return; } // We listen for room events because when we accept an invite // we need to wait till the room is fully populated with state // before refreshing the member list else we get a stale list. this.updateListNow(true); }); (0, _defineProperty2.default)(this, "onMyMembership", (room, membership, oldMembership) => { if (room.roomId === this.props.roomId && membership === _types.KnownMembership.Join && oldMembership !== _types.KnownMembership.Join) { // we just joined the room, load the member list this.updateListNow(true); } }); (0, _defineProperty2.default)(this, "onRoomStateUpdate", state => { if (state.roomId !== this.props.roomId) return; this.updateList(); }); (0, _defineProperty2.default)(this, "onRoomMemberName", (ev, member) => { if (member.roomId !== this.props.roomId) { return; } this.updateList(); }); (0, _defineProperty2.default)(this, "onRoomStateEvent", event => { if (event.getRoomId() === this.props.roomId && event.getType() === _matrix.EventType.RoomThirdPartyInvite) { this.updateList(); } if (this.canInvite !== this.state.canInvite) this.setState({ canInvite: this.canInvite }); }); (0, _defineProperty2.default)(this, "updateList", (0, _lodash.throttle)(() => { this.updateListNow(false); }, 500, { leading: true, trailing: true })); (0, _defineProperty2.default)(this, "createOverflowTileJoined", (overflowCount, totalCount) => { return this.createOverflowTile(overflowCount, totalCount, this.showMoreJoinedMemberList); }); (0, _defineProperty2.default)(this, "createOverflowTileInvited", (overflowCount, totalCount) => { return this.createOverflowTile(overflowCount, totalCount, this.showMoreInvitedMemberList); }); (0, _defineProperty2.default)(this, "createOverflowTile", (overflowCount, totalCount, onClick) => { // For now we'll pretend this is any entity. It should probably be a separate tile. const text = (0, _languageHandler._t)("common|and_n_others", { count: overflowCount }); return /*#__PURE__*/_react.default.createElement(_EntityTile.default, { className: "mx_EntityTile_ellipsis", avatarJsx: /*#__PURE__*/_react.default.createElement(_BaseAvatar.default, { url: require("@vector-im/compound-design-tokens/icons/overflow-horizontal.svg").default, name: "...", size: "36px" }), name: text, showPresence: false, onClick: onClick }); }); (0, _defineProperty2.default)(this, "showMoreJoinedMemberList", () => { this.setState({ truncateAtJoined: this.state.truncateAtJoined + SHOW_MORE_INCREMENT }); }); (0, _defineProperty2.default)(this, "showMoreInvitedMemberList", () => { this.setState({ truncateAtInvited: this.state.truncateAtInvited + SHOW_MORE_INCREMENT }); }); (0, _defineProperty2.default)(this, "onSearchQueryChanged", searchQuery => { this.props.onSearchQueryChanged(searchQuery); }); (0, _defineProperty2.default)(this, "onPending3pidInviteClick", inviteEvent => { _dispatcher.default.dispatch({ action: _actions.Action.View3pidInvite, event: inviteEvent }); }); (0, _defineProperty2.default)(this, "getChildrenJoined", (start, end) => { return this.makeMemberTiles(this.state.filteredJoinedMembers.slice(start, end)); }); (0, _defineProperty2.default)(this, "getChildCountJoined", () => this.state.filteredJoinedMembers.length); (0, _defineProperty2.default)(this, "getChildrenInvited", (start, end) => { let targets = this.state.filteredInvitedMembers; if (end > this.state.filteredInvitedMembers.length) { targets = targets.concat(this.getPending3PidInvites()); } return this.makeMemberTiles(targets.slice(start, end)); }); (0, _defineProperty2.default)(this, "getChildCountInvited", () => { return this.state.filteredInvitedMembers.length + (this.getPending3PidInvites() || []).length; }); (0, _defineProperty2.default)(this, "onInviteButtonClick", ev => { _PosthogTrackers.default.trackInteraction("WebRightPanelMemberListInviteButton", ev); const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); const room = cli.getRoom(this.props.roomId); (0, _inviteToRoom.inviteToRoom)(room); }); this.state = this.getMembersState([], []); this.showPresence = context?.memberListStore.isPresenceEnabled() ?? true; this.mounted = true; this.listenForMembersChanges(); } listenForMembersChanges() { const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); cli.on(_matrix.RoomStateEvent.Update, this.onRoomStateUpdate); cli.on(_matrix.RoomMemberEvent.Name, this.onRoomMemberName); cli.on(_matrix.RoomStateEvent.Events, this.onRoomStateEvent); // We listen for changes to the lastPresenceTs which is essentially // listening for all presence events (we display most of not all of // the information contained in presence events). cli.on(_matrix.UserEvent.LastPresenceTs, this.onUserPresenceChange); cli.on(_matrix.UserEvent.Presence, this.onUserPresenceChange); cli.on(_matrix.UserEvent.CurrentlyActive, this.onUserPresenceChange); cli.on(_matrix.ClientEvent.Room, this.onRoom); // invites & joining after peek cli.on(_matrix.RoomEvent.MyMembership, this.onMyMembership); } componentDidMount() { this.updateListNow(true); } componentWillUnmount() { this.mounted = false; const cli = _MatrixClientPeg.MatrixClientPeg.get(); if (cli) { cli.removeListener(_matrix.RoomStateEvent.Update, this.onRoomStateUpdate); cli.removeListener(_matrix.RoomMemberEvent.Name, this.onRoomMemberName); cli.removeListener(_matrix.RoomEvent.MyMembership, this.onMyMembership); cli.removeListener(_matrix.RoomStateEvent.Events, this.onRoomStateEvent); cli.removeListener(_matrix.ClientEvent.Room, this.onRoom); cli.removeListener(_matrix.UserEvent.LastPresenceTs, this.onUserPresenceChange); cli.removeListener(_matrix.UserEvent.Presence, this.onUserPresenceChange); cli.removeListener(_matrix.UserEvent.CurrentlyActive, this.onUserPresenceChange); } // cancel any pending calls to the rate_limited_funcs this.updateList.cancel(); } get canInvite() { const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); const room = cli.getRoom(this.props.roomId); return !!room && (0, _canInviteTo.canInviteTo)(room); } getMembersState(invitedMembers, joinedMembers) { return { loading: false, filteredJoinedMembers: joinedMembers, filteredInvitedMembers: invitedMembers, canInvite: this.canInvite, // ideally we'd size this to the page height, but // in practice I find that a little constraining truncateAtJoined: INITIAL_LOAD_NUM_MEMBERS, truncateAtInvited: INITIAL_LOAD_NUM_INVITED }; } // XXX: exported for tests async updateListNow(showLoadingSpinner) { if (!this.mounted) { return; } if (showLoadingSpinner) { this.setState({ loading: true }); } const { joined, invited } = await this.context.memberListStore.loadMemberList(this.props.roomId, this.props.searchQuery); if (!this.mounted) { return; } this.setState({ loading: false, filteredJoinedMembers: joined, filteredInvitedMembers: invited }); } componentDidUpdate(prevProps, prevState, snapshot) { if (prevProps.searchQuery !== this.props.searchQuery) { this.updateListNow(false); } } getPending3PidInvites() { // include 3pid invites (m.room.third_party_invite) state events. // The HS may have already converted these into m.room.member invites so // we shouldn't add them if the 3pid invite state key (token) is in the // member invite (content.third_party_invite.signed.token) const room = _MatrixClientPeg.MatrixClientPeg.safeGet().getRoom(this.props.roomId); if (room) { return room.currentState.getStateEvents("m.room.third_party_invite").filter(function (e) { if (!(0, _RoomInvite.isValid3pidInvite)(e)) return false; // discard all invites which have a m.room.member event since we've // already added them. const memberEvent = room.currentState.getInviteForThreePidToken(e.getStateKey()); if (memberEvent) return false; return true; }); } return []; } makeMemberTiles(members) { return members.map(m => { if (m instanceof _matrix.RoomMember) { // Is a Matrix invite return /*#__PURE__*/_react.default.createElement(_MemberTile.default, { key: m.userId, member: m, ref: tile => { if (tile) this.tiles.set(m.userId, tile);else this.tiles.delete(m.userId); }, showPresence: this.showPresence }); } else { // Is a 3pid invite return /*#__PURE__*/_react.default.createElement(_EntityTile.default, { key: m.getStateKey(), name: m.getContent().display_name, showPresence: false, onClick: () => this.onPending3pidInviteClick(m) }); } }); } render() { if (this.state.loading) { return /*#__PURE__*/_react.default.createElement(_BaseCard.default, { id: "memberlist-panel", className: "mx_MemberList", ariaLabelledBy: "memberlist-panel-tab", role: "tabpanel", header: (0, _languageHandler._t)("common|people"), onClose: this.props.onClose }, /*#__PURE__*/_react.default.createElement(_Spinner.default, null)); } const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); const room = cli.getRoom(this.props.roomId); let inviteButton; if (room?.getMyMembership() === _types.KnownMembership.Join && (0, _UIComponents.shouldShowComponent)(_UIFeature.UIComponent.InviteUsers)) { const inviteButtonText = room.isSpaceRoom() ? (0, _languageHandler._t)("space|invite_this_space") : (0, _languageHandler._t)("room|invite_this_room"); const button = /*#__PURE__*/_react.default.createElement(_compoundWeb.Button, { size: "sm", kind: "secondary", className: "mx_MemberList_invite", onClick: this.onInviteButtonClick, disabled: !this.state.canInvite }, /*#__PURE__*/_react.default.createElement(_userAddSolid.default, { width: "1em", height: "1em" }), inviteButtonText); if (this.state.canInvite) { inviteButton = button; } else { inviteButton = /*#__PURE__*/_react.default.createElement(_compoundWeb.Tooltip, { label: (0, _languageHandler._t)("member_list|invite_button_no_perms_tooltip") }, button); } } let invitedHeader; let invitedSection; if (this.getChildCountInvited() > 0) { invitedHeader = /*#__PURE__*/_react.default.createElement("h2", null, (0, _languageHandler._t)("member_list|invited_list_heading")); invitedSection = /*#__PURE__*/_react.default.createElement(_TruncatedList.default, { className: "mx_MemberList_section mx_MemberList_invited", truncateAt: this.state.truncateAtInvited, createOverflowElement: this.createOverflowTileInvited, getChildren: this.getChildrenInvited, getChildCount: this.getChildCountInvited }); } const footer = /*#__PURE__*/_react.default.createElement(_SearchBox.default, { className: "mx_MemberList_query mx_textinput_icon mx_textinput_search", placeholder: (0, _languageHandler._t)("member_list|filter_placeholder"), onSearch: this.onSearchQueryChanged, initialValue: this.props.searchQuery }); return /*#__PURE__*/_react.default.createElement(_BaseCard.default, { id: "memberlist-panel", className: "mx_MemberList", ariaLabelledBy: "memberlist-panel-tab", role: "tabpanel", header: (0, _languageHandler._t)("common|people"), footer: footer, onClose: this.props.onClose }, inviteButton, /*#__PURE__*/_react.default.createElement("div", { className: "mx_MemberList_wrapper" }, /*#__PURE__*/_react.default.createElement(_TruncatedList.default, { className: "mx_MemberList_section mx_MemberList_joined", truncateAt: this.state.truncateAtJoined, createOverflowElement: this.createOverflowTileJoined, getChildren: this.getChildrenJoined, getChildCount: this.getChildCountJoined }), invitedHeader, invitedSection)); } } exports.default = MemberList; (0, _defineProperty2.default)(MemberList, "contextType", _SDKContext.SDKContext); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9tYXRyaXgiLCJfdHlwZXMiLCJfbG9kYXNoIiwiX2NvbXBvdW5kV2ViIiwiX3VzZXJBZGRTb2xpZCIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfZGlzcGF0Y2hlciIsIl9Sb29tSW52aXRlIiwiX01hdHJpeENsaWVudFBlZyIsIl9CYXNlQ2FyZCIsIl9UcnVuY2F0ZWRMaXN0IiwiX1NwaW5uZXIiLCJfU2VhcmNoQm94IiwiX0VudGl0eVRpbGUiLCJfTWVtYmVyVGlsZSIsIl9CYXNlQXZhdGFyIiwiX1VJQ29tcG9uZW50cyIsIl9VSUZlYXR1cmUiLCJfUG9zdGhvZ1RyYWNrZXJzIiwiX1NES0NvbnRleHQiLCJfY2FuSW52aXRlVG8iLCJfaW52aXRlVG9Sb29tIiwiX2FjdGlvbnMiLCJJTklUSUFMX0xPQURfTlVNX01FTUJFUlMiLCJJTklUSUFMX0xPQURfTlVNX0lOVklURUQiLCJTSE9XX01PUkVfSU5DUkVNRU5UIiwiTWVtYmVyTGlzdCIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsImNvbnRleHQiLCJfZGVmaW5lUHJvcGVydHkyIiwiZGVmYXVsdCIsIk1hcCIsImV2ZW50IiwidXNlciIsInRpbGUiLCJ0aWxlcyIsImdldCIsInVzZXJJZCIsInVwZGF0ZUxpc3QiLCJyb29tIiwicm9vbUlkIiwidXBkYXRlTGlzdE5vdyIsIm1lbWJlcnNoaXAiLCJvbGRNZW1iZXJzaGlwIiwiS25vd25NZW1iZXJzaGlwIiwiSm9pbiIsInN0YXRlIiwiZXYiLCJtZW1iZXIiLCJnZXRSb29tSWQiLCJnZXRUeXBlIiwiRXZlbnRUeXBlIiwiUm9vbVRoaXJkUGFydHlJbnZpdGUiLCJjYW5JbnZpdGUiLCJzZXRTdGF0ZSIsInRocm90dGxlIiwibGVhZGluZyIsInRyYWlsaW5nIiwib3ZlcmZsb3dDb3VudCIsInRvdGFsQ291bnQiLCJjcmVhdGVPdmVyZmxvd1RpbGUiLCJzaG93TW9yZUpvaW5lZE1lbWJlckxpc3QiLCJzaG93TW9yZUludml0ZWRNZW1iZXJMaXN0Iiwib25DbGljayIsInRleHQiLCJfdCIsImNvdW50IiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsImF2YXRhckpzeCIsInVybCIsIm5hbWUiLCJzaXplIiwic2hvd1ByZXNlbmNlIiwidHJ1bmNhdGVBdEpvaW5lZCIsInRydW5jYXRlQXRJbnZpdGVkIiwic2VhcmNoUXVlcnkiLCJvblNlYXJjaFF1ZXJ5Q2hhbmdlZCIsImludml0ZUV2ZW50IiwiZGlzIiwiZGlzcGF0Y2giLCJhY3Rpb24iLCJBY3Rpb24iLCJWaWV3M3BpZEludml0ZSIsInN0YXJ0IiwiZW5kIiwibWFrZU1lbWJlclRpbGVzIiwiZmlsdGVyZWRKb2luZWRNZW1iZXJzIiwic2xpY2UiLCJsZW5ndGgiLCJ0YXJnZXRzIiwiZmlsdGVyZWRJbnZpdGVkTWVtYmVycyIsImNvbmNhdCIsImdldFBlbmRpbmczUGlkSW52aXRlcyIsIlBvc3Rob2dUcmFja2VycyIsInRyYWNrSW50ZXJhY3Rpb24iLCJjbGkiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwiZ2V0Um9vbSIsImludml0ZVRvUm9vbSIsImdldE1lbWJlcnNTdGF0ZSIsIm1lbWJlckxpc3RTdG9yZSIsImlzUHJlc2VuY2VFbmFibGVkIiwibW91bnRlZCIsImxpc3RlbkZvck1lbWJlcnNDaGFuZ2VzIiwib24iLCJSb29tU3RhdGVFdmVudCIsIlVwZGF0ZSIsIm9uUm9vbVN0YXRlVXBkYXRlIiwiUm9vbU1lbWJlckV2ZW50IiwiTmFtZSIsIm9uUm9vbU1lbWJlck5hbWUiLCJFdmVudHMiLCJvblJvb21TdGF0ZUV2ZW50IiwiVXNlckV2ZW50IiwiTGFzdFByZXNlbmNlVHMiLCJvblVzZXJQcmVzZW5jZUNoYW5nZSIsIlByZXNlbmNlIiwiQ3VycmVudGx5QWN0aXZlIiwiQ2xpZW50RXZlbnQiLCJSb29tIiwib25Sb29tIiwiUm9vbUV2ZW50IiwiTXlNZW1iZXJzaGlwIiwib25NeU1lbWJlcnNoaXAiLCJjb21wb25lbnREaWRNb3VudCIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwicmVtb3ZlTGlzdGVuZXIiLCJjYW5jZWwiLCJjYW5JbnZpdGVUbyIsImludml0ZWRNZW1iZXJzIiwiam9pbmVkTWVtYmVycyIsImxvYWRpbmciLCJzaG93TG9hZGluZ1NwaW5uZXIiLCJqb2luZWQiLCJpbnZpdGVkIiwibG9hZE1lbWJlckxpc3QiLCJjb21wb25lbnREaWRVcGRhdGUiLCJwcmV2UHJvcHMiLCJwcmV2U3RhdGUiLCJzbmFwc2hvdCIsImN1cnJlbnRTdGF0ZSIsImdldFN0YXRlRXZlbnRzIiwiZmlsdGVyIiwiZSIsImlzVmFsaWQzcGlkSW52aXRlIiwibWVtYmVyRXZlbnQiLCJnZXRJbnZpdGVGb3JUaHJlZVBpZFRva2VuIiwiZ2V0U3RhdGVLZXkiLCJtZW1iZXJzIiwibWFwIiwibSIsIlJvb21NZW1iZXIiLCJrZXkiLCJyZWYiLCJzZXQiLCJkZWxldGUiLCJnZXRDb250ZW50IiwiZGlzcGxheV9uYW1lIiwib25QZW5kaW5nM3BpZEludml0ZUNsaWNrIiwicmVuZGVyIiwiaWQiLCJhcmlhTGFiZWxsZWRCeSIsInJvbGUiLCJoZWFkZXIiLCJvbkNsb3NlIiwiaW52aXRlQnV0dG9uIiwiZ2V0TXlNZW1iZXJzaGlwIiwic2hvdWxkU2hvd0NvbXBvbmVudCIsIlVJQ29tcG9uZW50IiwiSW52aXRlVXNlcnMiLCJpbnZpdGVCdXR0b25UZXh0IiwiaXNTcGFjZVJvb20iLCJidXR0b24iLCJCdXR0b24iLCJraW5kIiwib25JbnZpdGVCdXR0b25DbGljayIsImRpc2FibGVkIiwid2lkdGgiLCJoZWlnaHQiLCJUb29sdGlwIiwibGFiZWwiLCJpbnZpdGVkSGVhZGVyIiwiaW52aXRlZFNlY3Rpb24iLCJnZXRDaGlsZENvdW50SW52aXRlZCIsInRydW5jYXRlQXQiLCJjcmVhdGVPdmVyZmxvd0VsZW1lbnQiLCJjcmVhdGVPdmVyZmxvd1RpbGVJbnZpdGVkIiwiZ2V0Q2hpbGRyZW4iLCJnZXRDaGlsZHJlbkludml0ZWQiLCJnZXRDaGlsZENvdW50IiwiZm9vdGVyIiwicGxhY2Vob2xkZXIiLCJvblNlYXJjaCIsImluaXRpYWxWYWx1ZSIsImNyZWF0ZU92ZXJmbG93VGlsZUpvaW5lZCIsImdldENoaWxkcmVuSm9pbmVkIiwiZ2V0Q2hpbGRDb3VudEpvaW5lZCIsImV4cG9ydHMiLCJTREtDb250ZXh0Il0sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdmlld3Mvcm9vbXMvTWVtYmVyTGlzdC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjEgxaBpbW9uIEJyYW5kbmVyIDxzaW1vbi5icmEuYWdAZ21haWwuY29tPlxuQ29weXJpZ2h0IDIwMTcsIDIwMTggTmV3IFZlY3RvciBMdGRcbkNvcHlyaWdodCAyMDE3IFZlY3RvciBDcmVhdGlvbnMgTHRkXG5Db3B5cmlnaHQgMjAxNSwgMjAxNiBPcGVuTWFya2V0IEx0ZFxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICAgIE1hdHJpeEV2ZW50LFxuICAgIFJvb20sXG4gICAgUm9vbUV2ZW50LFxuICAgIFJvb21NZW1iZXIsXG4gICAgUm9vbU1lbWJlckV2ZW50LFxuICAgIFJvb21TdGF0ZSxcbiAgICBSb29tU3RhdGVFdmVudCxcbiAgICBVc2VyLFxuICAgIFVzZXJFdmVudCxcbiAgICBFdmVudFR5cGUsXG4gICAgQ2xpZW50RXZlbnQsXG59IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IEtub3duTWVtYmVyc2hpcCB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy90eXBlc1wiO1xuaW1wb3J0IHsgdGhyb3R0bGUgfSBmcm9tIFwibG9kYXNoXCI7XG5pbXBvcnQgeyBCdXR0b24sIFRvb2x0aXAgfSBmcm9tIFwiQHZlY3Rvci1pbS9jb21wb3VuZC13ZWJcIjtcbmltcG9ydCBVc2VyQWRkSWNvbiBmcm9tIFwiQHZlY3Rvci1pbS9jb21wb3VuZC1kZXNpZ24tdG9rZW5zL2Fzc2V0cy93ZWIvaWNvbnMvdXNlci1hZGQtc29saWRcIjtcblxuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgZGlzIGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCB7IGlzVmFsaWQzcGlkSW52aXRlIH0gZnJvbSBcIi4uLy4uLy4uL1Jvb21JbnZpdGVcIjtcbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBCYXNlQ2FyZCBmcm9tIFwiLi4vcmlnaHRfcGFuZWwvQmFzZUNhcmRcIjtcbmltcG9ydCBUcnVuY2F0ZWRMaXN0IGZyb20gXCIuLi9lbGVtZW50cy9UcnVuY2F0ZWRMaXN0XCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IFNlYXJjaEJveCBmcm9tIFwiLi4vLi4vc3RydWN0dXJlcy9TZWFyY2hCb3hcIjtcbmltcG9ydCB7IEJ1dHRvbkV2ZW50IH0gZnJvbSBcIi4uL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCBFbnRpdHlUaWxlIGZyb20gXCIuL0VudGl0eVRpbGVcIjtcbmltcG9ydCBNZW1iZXJUaWxlIGZyb20gXCIuL01lbWJlclRpbGVcIjtcbmltcG9ydCBCYXNlQXZhdGFyIGZyb20gXCIuLi9hdmF0YXJzL0Jhc2VBdmF0YXJcIjtcbmltcG9ydCB7IHNob3VsZFNob3dDb21wb25lbnQgfSBmcm9tIFwiLi4vLi4vLi4vY3VzdG9taXNhdGlvbnMvaGVscGVycy9VSUNvbXBvbmVudHNcIjtcbmltcG9ydCB7IFVJQ29tcG9uZW50IH0gZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1VJRmVhdHVyZVwiO1xuaW1wb3J0IFBvc3Rob2dUcmFja2VycyBmcm9tIFwiLi4vLi4vLi4vUG9zdGhvZ1RyYWNrZXJzXCI7XG5pbXBvcnQgeyBTREtDb250ZXh0IH0gZnJvbSBcIi4uLy4uLy4uL2NvbnRleHRzL1NES0NvbnRleHRcIjtcbmltcG9ydCB7IGNhbkludml0ZVRvIH0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL3Jvb20vY2FuSW52aXRlVG9cIjtcbmltcG9ydCB7IGludml0ZVRvUm9vbSB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9yb29tL2ludml0ZVRvUm9vbVwiO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSBcIi4uLy4uLy4uL2Rpc3BhdGNoZXIvYWN0aW9uc1wiO1xuXG5jb25zdCBJTklUSUFMX0xPQURfTlVNX01FTUJFUlMgPSAzMDtcbmNvbnN0IElOSVRJQUxfTE9BRF9OVU1fSU5WSVRFRCA9IDU7XG5jb25zdCBTSE9XX01PUkVfSU5DUkVNRU5UID0gMTAwO1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICByb29tSWQ6IHN0cmluZztcbiAgICBzZWFyY2hRdWVyeTogc3RyaW5nO1xuICAgIG9uQ2xvc2UoKTogdm9pZDtcbiAgICBvblNlYXJjaFF1ZXJ5Q2hhbmdlZDogKHF1ZXJ5OiBzdHJpbmcpID0+IHZvaWQ7XG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIGxvYWRpbmc6IGJvb2xlYW47XG4gICAgZmlsdGVyZWRKb2luZWRNZW1iZXJzOiBBcnJheTxSb29tTWVtYmVyPjtcbiAgICBmaWx0ZXJlZEludml0ZWRNZW1iZXJzOiBBcnJheTxSb29tTWVtYmVyIHwgTWF0cml4RXZlbnQ+O1xuICAgIGNhbkludml0ZTogYm9vbGVhbjtcbiAgICB0cnVuY2F0ZUF0Sm9pbmVkOiBudW1iZXI7XG4gICAgdHJ1bmNhdGVBdEludml0ZWQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWVtYmVyTGlzdCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgc2hvd1ByZXNlbmNlOiBib29sZWFuO1xuICAgIHByaXZhdGUgbW91bnRlZCA9IGZhbHNlO1xuXG4gICAgcHVibGljIHN0YXRpYyBjb250ZXh0VHlwZSA9IFNES0NvbnRleHQ7XG4gICAgcHVibGljIGRlY2xhcmUgY29udGV4dDogUmVhY3QuQ29udGV4dFR5cGU8dHlwZW9mIFNES0NvbnRleHQ+O1xuICAgIHByaXZhdGUgdGlsZXM6IE1hcDxzdHJpbmcsIE1lbWJlclRpbGU+ID0gbmV3IE1hcCgpO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMsIGNvbnRleHQ6IFJlYWN0LkNvbnRleHRUeXBlPHR5cGVvZiBTREtDb250ZXh0Pikge1xuICAgICAgICBzdXBlcihwcm9wcywgY29udGV4dCk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSB0aGlzLmdldE1lbWJlcnNTdGF0ZShbXSwgW10pO1xuICAgICAgICB0aGlzLnNob3dQcmVzZW5jZSA9IGNvbnRleHQ/Lm1lbWJlckxpc3RTdG9yZS5pc1ByZXNlbmNlRW5hYmxlZCgpID8/IHRydWU7XG4gICAgICAgIHRoaXMubW91bnRlZCA9IHRydWU7XG4gICAgICAgIHRoaXMubGlzdGVuRm9yTWVtYmVyc0NoYW5nZXMoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxpc3RlbkZvck1lbWJlcnNDaGFuZ2VzKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICBjbGkub24oUm9vbVN0YXRlRXZlbnQuVXBkYXRlLCB0aGlzLm9uUm9vbVN0YXRlVXBkYXRlKTtcbiAgICAgICAgY2xpLm9uKFJvb21NZW1iZXJFdmVudC5OYW1lLCB0aGlzLm9uUm9vbU1lbWJlck5hbWUpO1xuICAgICAgICBjbGkub24oUm9vbVN0YXRlRXZlbnQuRXZlbnRzLCB0aGlzLm9uUm9vbVN0YXRlRXZlbnQpO1xuICAgICAgICAvLyBXZSBsaXN0ZW4gZm9yIGNoYW5nZXMgdG8gdGhlIGxhc3RQcmVzZW5jZVRzIHdoaWNoIGlzIGVzc2VudGlhbGx5XG4gICAgICAgIC8vIGxpc3RlbmluZyBmb3IgYWxsIHByZXNlbmNlIGV2ZW50cyAod2UgZGlzcGxheSBtb3N0IG9mIG5vdCBhbGwgb2ZcbiAgICAgICAgLy8gdGhlIGluZm9ybWF0aW9uIGNvbnRhaW5lZCBpbiBwcmVzZW5jZSBldmVudHMpLlxuICAgICAgICBjbGkub24oVXNlckV2ZW50Lkxhc3RQcmVzZW5jZVRzLCB0aGlzLm9uVXNlclByZXNlbmNlQ2hhbmdlKTtcbiAgICAgICAgY2xpLm9uKFVzZXJFdmVudC5QcmVzZW5jZSwgdGhpcy5vblVzZXJQcmVzZW5jZUNoYW5nZSk7XG4gICAgICAgIGNsaS5vbihVc2VyRXZlbnQuQ3VycmVudGx5QWN0aXZlLCB0aGlzLm9uVXNlclByZXNlbmNlQ2hhbmdlKTtcbiAgICAgICAgY2xpLm9uKENsaWVudEV2ZW50LlJvb20sIHRoaXMub25Sb29tKTsgLy8gaW52aXRlcyAmIGpvaW5pbmcgYWZ0ZXIgcGVla1xuICAgICAgICBjbGkub24oUm9vbUV2ZW50Lk15TWVtYmVyc2hpcCwgdGhpcy5vbk15TWVtYmVyc2hpcCk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudERpZE1vdW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnVwZGF0ZUxpc3ROb3codHJ1ZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm1vdW50ZWQgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgY2xpID0gTWF0cml4Q2xpZW50UGVnLmdldCgpO1xuICAgICAgICBpZiAoY2xpKSB7XG4gICAgICAgICAgICBjbGkucmVtb3ZlTGlzdGVuZXIoUm9vbVN0YXRlRXZlbnQuVXBkYXRlLCB0aGlzLm9uUm9vbVN0YXRlVXBkYXRlKTtcbiAgICAgICAgICAgIGNsaS5yZW1vdmVMaXN0ZW5lcihSb29tTWVtYmVyRXZlbnQuTmFtZSwgdGhpcy5vblJvb21NZW1iZXJOYW1lKTtcbiAgICAgICAgICAgIGNsaS5yZW1vdmVMaXN0ZW5lcihSb29tRXZlbnQuTXlNZW1iZXJzaGlwLCB0aGlzLm9uTXlNZW1iZXJzaGlwKTtcbiAgICAgICAgICAgIGNsaS5yZW1vdmVMaXN0ZW5lcihSb29tU3RhdGVFdmVudC5FdmVudHMsIHRoaXMub25Sb29tU3RhdGVFdmVudCk7XG4gICAgICAgICAgICBjbGkucmVtb3ZlTGlzdGVuZXIoQ2xpZW50RXZlbnQuUm9vbSwgdGhpcy5vblJvb20pO1xuICAgICAgICAgICAgY2xpLnJlbW92ZUxpc3RlbmVyKFVzZXJFdmVudC5MYXN0UHJlc2VuY2VUcywgdGhpcy5vblVzZXJQcmVzZW5jZUNoYW5nZSk7XG4gICAgICAgICAgICBjbGkucmVtb3ZlTGlzdGVuZXIoVXNlckV2ZW50LlByZXNlbmNlLCB0aGlzLm9uVXNlclByZXNlbmNlQ2hhbmdlKTtcbiAgICAgICAgICAgIGNsaS5yZW1vdmVMaXN0ZW5lcihVc2VyRXZlbnQuQ3VycmVudGx5QWN0aXZlLCB0aGlzLm9uVXNlclByZXNlbmNlQ2hhbmdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNhbmNlbCBhbnkgcGVuZGluZyBjYWxscyB0byB0aGUgcmF0ZV9saW1pdGVkX2Z1bmNzXG4gICAgICAgIHRoaXMudXBkYXRlTGlzdC5jYW5jZWwoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldCBjYW5JbnZpdGUoKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGNsaSA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG4gICAgICAgIGNvbnN0IHJvb20gPSBjbGkuZ2V0Um9vbSh0aGlzLnByb3BzLnJvb21JZCk7XG5cbiAgICAgICAgcmV0dXJuICEhcm9vbSAmJiBjYW5JbnZpdGVUbyhyb29tKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldE1lbWJlcnNTdGF0ZShpbnZpdGVkTWVtYmVyczogQXJyYXk8Um9vbU1lbWJlcj4sIGpvaW5lZE1lbWJlcnM6IEFycmF5PFJvb21NZW1iZXI+KTogSVN0YXRlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGxvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgICAgZmlsdGVyZWRKb2luZWRNZW1iZXJzOiBqb2luZWRNZW1iZXJzLFxuICAgICAgICAgICAgZmlsdGVyZWRJbnZpdGVkTWVtYmVyczogaW52aXRlZE1lbWJlcnMsXG4gICAgICAgICAgICBjYW5JbnZpdGU6IHRoaXMuY2FuSW52aXRlLFxuXG4gICAgICAgICAgICAvLyBpZGVhbGx5IHdlJ2Qgc2l6ZSB0aGlzIHRvIHRoZSBwYWdlIGhlaWdodCwgYnV0XG4gICAgICAgICAgICAvLyBpbiBwcmFjdGljZSBJIGZpbmQgdGhhdCBhIGxpdHRsZSBjb25zdHJhaW5pbmdcbiAgICAgICAgICAgIHRydW5jYXRlQXRKb2luZWQ6IElOSVRJQUxfTE9BRF9OVU1fTUVNQkVSUyxcbiAgICAgICAgICAgIHRydW5jYXRlQXRJbnZpdGVkOiBJTklUSUFMX0xPQURfTlVNX0lOVklURUQsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvblVzZXJQcmVzZW5jZUNoYW5nZSA9IChldmVudDogTWF0cml4RXZlbnQgfCB1bmRlZmluZWQsIHVzZXI6IFVzZXIpOiB2b2lkID0+IHtcbiAgICAgICAgLy8gQXR0YWNoIGEgU0lOR0xFIGxpc3RlbmVyIGZvciBnbG9iYWwgcHJlc2VuY2UgY2hhbmdlcyB0aGVuIGxvY2F0ZSB0aGVcbiAgICAgICAgLy8gbWVtYmVyIHRpbGUgYW5kIHJlLXJlbmRlciBpdC4gVGhpcyBpcyBtb3JlIGVmZmljaWVudCB0aGFuIGV2ZXJ5IHRpbGVcbiAgICAgICAgLy8gZXZlciBhdHRhY2hpbmcgdGhlaXIgb3duIGxpc3RlbmVyLlxuICAgICAgICBjb25zdCB0aWxlID0gdGhpcy50aWxlcy5nZXQodXNlci51c2VySWQpO1xuICAgICAgICBpZiAodGlsZSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVMaXN0KCk7IC8vIHJlb3JkZXIgdGhlIG1lbWJlcnNoaXAgbGlzdFxuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Sb29tID0gKHJvb206IFJvb20pOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHJvb20ucm9vbUlkICE9PSB0aGlzLnByb3BzLnJvb21JZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdlIGxpc3RlbiBmb3Igcm9vbSBldmVudHMgYmVjYXVzZSB3aGVuIHdlIGFjY2VwdCBhbiBpbnZpdGVcbiAgICAgICAgLy8gd2UgbmVlZCB0byB3YWl0IHRpbGwgdGhlIHJvb20gaXMgZnVsbHkgcG9wdWxhdGVkIHdpdGggc3RhdGVcbiAgICAgICAgLy8gYmVmb3JlIHJlZnJlc2hpbmcgdGhlIG1lbWJlciBsaXN0IGVsc2Ugd2UgZ2V0IGEgc3RhbGUgbGlzdC5cbiAgICAgICAgdGhpcy51cGRhdGVMaXN0Tm93KHRydWUpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uTXlNZW1iZXJzaGlwID0gKHJvb206IFJvb20sIG1lbWJlcnNoaXA6IHN0cmluZywgb2xkTWVtYmVyc2hpcD86IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICByb29tLnJvb21JZCA9PT0gdGhpcy5wcm9wcy5yb29tSWQgJiZcbiAgICAgICAgICAgIG1lbWJlcnNoaXAgPT09IEtub3duTWVtYmVyc2hpcC5Kb2luICYmXG4gICAgICAgICAgICBvbGRNZW1iZXJzaGlwICE9PSBLbm93bk1lbWJlcnNoaXAuSm9pblxuICAgICAgICApIHtcbiAgICAgICAgICAgIC8vIHdlIGp1c3Qgam9pbmVkIHRoZSByb29tLCBsb2FkIHRoZSBtZW1iZXIgbGlzdFxuICAgICAgICAgICAgdGhpcy51cGRhdGVMaXN0Tm93KHRydWUpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25Sb29tU3RhdGVVcGRhdGUgPSAoc3RhdGU6IFJvb21TdGF0ZSk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoc3RhdGUucm9vbUlkICE9PSB0aGlzLnByb3BzLnJvb21JZCkgcmV0dXJuO1xuICAgICAgICB0aGlzLnVwZGF0ZUxpc3QoKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblJvb21NZW1iZXJOYW1lID0gKGV2OiBNYXRyaXhFdmVudCwgbWVtYmVyOiBSb29tTWVtYmVyKTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChtZW1iZXIucm9vbUlkICE9PSB0aGlzLnByb3BzLnJvb21JZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlTGlzdCgpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm9vbVN0YXRlRXZlbnQgPSAoZXZlbnQ6IE1hdHJpeEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGlmIChldmVudC5nZXRSb29tSWQoKSA9PT0gdGhpcy5wcm9wcy5yb29tSWQgJiYgZXZlbnQuZ2V0VHlwZSgpID09PSBFdmVudFR5cGUuUm9vbVRoaXJkUGFydHlJbnZpdGUpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuY2FuSW52aXRlICE9PSB0aGlzLnN0YXRlLmNhbkludml0ZSkgdGhpcy5zZXRTdGF0ZSh7IGNhbkludml0ZTogdGhpcy5jYW5JbnZpdGUgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgdXBkYXRlTGlzdCA9IHRocm90dGxlKFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUxpc3ROb3coZmFsc2UpO1xuICAgICAgICB9LFxuICAgICAgICA1MDAsXG4gICAgICAgIHsgbGVhZGluZzogdHJ1ZSwgdHJhaWxpbmc6IHRydWUgfSxcbiAgICApO1xuXG4gICAgLy8gWFhYOiBleHBvcnRlZCBmb3IgdGVzdHNcbiAgICBwdWJsaWMgYXN5bmMgdXBkYXRlTGlzdE5vdyhzaG93TG9hZGluZ1NwaW5uZXI/OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICghdGhpcy5tb3VudGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNob3dMb2FkaW5nU3Bpbm5lcikge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGxvYWRpbmc6IHRydWUgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyBqb2luZWQsIGludml0ZWQgfSA9IGF3YWl0IHRoaXMuY29udGV4dC5tZW1iZXJMaXN0U3RvcmUubG9hZE1lbWJlckxpc3QoXG4gICAgICAgICAgICB0aGlzLnByb3BzLnJvb21JZCxcbiAgICAgICAgICAgIHRoaXMucHJvcHMuc2VhcmNoUXVlcnksXG4gICAgICAgICk7XG4gICAgICAgIGlmICghdGhpcy5tb3VudGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIGZpbHRlcmVkSm9pbmVkTWVtYmVyczogam9pbmVkLFxuICAgICAgICAgICAgZmlsdGVyZWRJbnZpdGVkTWVtYmVyczogaW52aXRlZCxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjcmVhdGVPdmVyZmxvd1RpbGVKb2luZWQgPSAob3ZlcmZsb3dDb3VudDogbnVtYmVyLCB0b3RhbENvdW50OiBudW1iZXIpOiBKU1guRWxlbWVudCA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU92ZXJmbG93VGlsZShvdmVyZmxvd0NvdW50LCB0b3RhbENvdW50LCB0aGlzLnNob3dNb3JlSm9pbmVkTWVtYmVyTGlzdCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgY3JlYXRlT3ZlcmZsb3dUaWxlSW52aXRlZCA9IChvdmVyZmxvd0NvdW50OiBudW1iZXIsIHRvdGFsQ291bnQ6IG51bWJlcik6IEpTWC5FbGVtZW50ID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlT3ZlcmZsb3dUaWxlKG92ZXJmbG93Q291bnQsIHRvdGFsQ291bnQsIHRoaXMuc2hvd01vcmVJbnZpdGVkTWVtYmVyTGlzdCk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgY3JlYXRlT3ZlcmZsb3dUaWxlID0gKG92ZXJmbG93Q291bnQ6IG51bWJlciwgdG90YWxDb3VudDogbnVtYmVyLCBvbkNsaWNrOiAoKSA9PiB2b2lkKTogSlNYLkVsZW1lbnQgPT4ge1xuICAgICAgICAvLyBGb3Igbm93IHdlJ2xsIHByZXRlbmQgdGhpcyBpcyBhbnkgZW50aXR5LiBJdCBzaG91bGQgcHJvYmFibHkgYmUgYSBzZXBhcmF0ZSB0aWxlLlxuICAgICAgICBjb25zdCB0ZXh0ID0gX3QoXCJjb21tb258YW5kX25fb3RoZXJzXCIsIHsgY291bnQ6IG92ZXJmbG93Q291bnQgfSk7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8RW50aXR5VGlsZVxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0VudGl0eVRpbGVfZWxsaXBzaXNcIlxuICAgICAgICAgICAgICAgIGF2YXRhckpzeD17XG4gICAgICAgICAgICAgICAgICAgIDxCYXNlQXZhdGFyXG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw9e3JlcXVpcmUoXCJAdmVjdG9yLWltL2NvbXBvdW5kLWRlc2lnbi10b2tlbnMvaWNvbnMvb3ZlcmZsb3ctaG9yaXpvbnRhbC5zdmdcIikuZGVmYXVsdH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9XCIuLi5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT1cIjM2cHhcIlxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBuYW1lPXt0ZXh0fVxuICAgICAgICAgICAgICAgIHNob3dQcmVzZW5jZT17ZmFsc2V9XG4gICAgICAgICAgICAgICAgb25DbGljaz17b25DbGlja31cbiAgICAgICAgICAgIC8+XG4gICAgICAgICk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgc2hvd01vcmVKb2luZWRNZW1iZXJMaXN0ID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHRydW5jYXRlQXRKb2luZWQ6IHRoaXMuc3RhdGUudHJ1bmNhdGVBdEpvaW5lZCArIFNIT1dfTU9SRV9JTkNSRU1FTlQsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwcml2YXRlIHNob3dNb3JlSW52aXRlZE1lbWJlckxpc3QgPSAoKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgdHJ1bmNhdGVBdEludml0ZWQ6IHRoaXMuc3RhdGUudHJ1bmNhdGVBdEludml0ZWQgKyBTSE9XX01PUkVfSU5DUkVNRU5ULFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHVibGljIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHM6IFJlYWRvbmx5PElQcm9wcz4sIHByZXZTdGF0ZTogUmVhZG9ubHk8SVN0YXRlPiwgc25hcHNob3Q/OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgaWYgKHByZXZQcm9wcy5zZWFyY2hRdWVyeSAhPT0gdGhpcy5wcm9wcy5zZWFyY2hRdWVyeSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVMaXN0Tm93KGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgb25TZWFyY2hRdWVyeUNoYW5nZWQgPSAoc2VhcmNoUXVlcnk6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnByb3BzLm9uU2VhcmNoUXVlcnlDaGFuZ2VkKHNlYXJjaFF1ZXJ5KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblBlbmRpbmczcGlkSW52aXRlQ2xpY2sgPSAoaW52aXRlRXZlbnQ6IE1hdHJpeEV2ZW50KTogdm9pZCA9PiB7XG4gICAgICAgIGRpcy5kaXNwYXRjaCh7XG4gICAgICAgICAgICBhY3Rpb246IEFjdGlvbi5WaWV3M3BpZEludml0ZSxcbiAgICAgICAgICAgIGV2ZW50OiBpbnZpdGVFdmVudCxcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHByaXZhdGUgZ2V0UGVuZGluZzNQaWRJbnZpdGVzKCk6IE1hdHJpeEV2ZW50W10ge1xuICAgICAgICAvLyBpbmNsdWRlIDNwaWQgaW52aXRlcyAobS5yb29tLnRoaXJkX3BhcnR5X2ludml0ZSkgc3RhdGUgZXZlbnRzLlxuICAgICAgICAvLyBUaGUgSFMgbWF5IGhhdmUgYWxyZWFkeSBjb252ZXJ0ZWQgdGhlc2UgaW50byBtLnJvb20ubWVtYmVyIGludml0ZXMgc29cbiAgICAgICAgLy8gd2Ugc2hvdWxkbid0IGFkZCB0aGVtIGlmIHRoZSAzcGlkIGludml0ZSBzdGF0ZSBrZXkgKHRva2VuKSBpcyBpbiB0aGVcbiAgICAgICAgLy8gbWVtYmVyIGludml0ZSAoY29udGVudC50aGlyZF9wYXJ0eV9pbnZpdGUuc2lnbmVkLnRva2VuKVxuICAgICAgICBjb25zdCByb29tID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKS5nZXRSb29tKHRoaXMucHJvcHMucm9vbUlkKTtcblxuICAgICAgICBpZiAocm9vbSkge1xuICAgICAgICAgICAgcmV0dXJuIHJvb20uY3VycmVudFN0YXRlLmdldFN0YXRlRXZlbnRzKFwibS5yb29tLnRoaXJkX3BhcnR5X2ludml0ZVwiKS5maWx0ZXIoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWQzcGlkSW52aXRlKGUpKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICAvLyBkaXNjYXJkIGFsbCBpbnZpdGVzIHdoaWNoIGhhdmUgYSBtLnJvb20ubWVtYmVyIGV2ZW50IHNpbmNlIHdlJ3ZlXG4gICAgICAgICAgICAgICAgLy8gYWxyZWFkeSBhZGRlZCB0aGVtLlxuICAgICAgICAgICAgICAgIGNvbnN0IG1lbWJlckV2ZW50ID0gcm9vbS5jdXJyZW50U3RhdGUuZ2V0SW52aXRlRm9yVGhyZWVQaWRUb2tlbihlLmdldFN0YXRlS2V5KCkhKTtcbiAgICAgICAgICAgICAgICBpZiAobWVtYmVyRXZlbnQpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFrZU1lbWJlclRpbGVzKG1lbWJlcnM6IEFycmF5PFJvb21NZW1iZXIgfCBNYXRyaXhFdmVudD4pOiBKU1guRWxlbWVudFtdIHtcbiAgICAgICAgcmV0dXJuIG1lbWJlcnMubWFwKChtKSA9PiB7XG4gICAgICAgICAgICBpZiAobSBpbnN0YW5jZW9mIFJvb21NZW1iZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBJcyBhIE1hdHJpeCBpbnZpdGVcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICA8TWVtYmVyVGlsZVxuICAgICAgICAgICAgICAgICAgICAgICAga2V5PXttLnVzZXJJZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG1lbWJlcj17bX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZj17KHRpbGUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGlsZSkgdGhpcy50aWxlcy5zZXQobS51c2VySWQsIHRpbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgdGhpcy50aWxlcy5kZWxldGUobS51c2VySWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dQcmVzZW5jZT17dGhpcy5zaG93UHJlc2VuY2V9XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSXMgYSAzcGlkIGludml0ZVxuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgIDxFbnRpdHlUaWxlXG4gICAgICAgICAgICAgICAgICAgICAgICBrZXk9e20uZ2V0U3RhdGVLZXkoKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9e20uZ2V0Q29udGVudCgpLmRpc3BsYXlfbmFtZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dQcmVzZW5jZT17ZmFsc2V9XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkNsaWNrPXsoKSA9PiB0aGlzLm9uUGVuZGluZzNwaWRJbnZpdGVDbGljayhtKX1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENoaWxkcmVuSm9pbmVkID0gKHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKTogQXJyYXk8SlNYLkVsZW1lbnQ+ID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWFrZU1lbWJlclRpbGVzKHRoaXMuc3RhdGUuZmlsdGVyZWRKb2luZWRNZW1iZXJzLnNsaWNlKHN0YXJ0LCBlbmQpKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBnZXRDaGlsZENvdW50Sm9pbmVkID0gKCk6IG51bWJlciA9PiB0aGlzLnN0YXRlLmZpbHRlcmVkSm9pbmVkTWVtYmVycy5sZW5ndGg7XG5cbiAgICBwcml2YXRlIGdldENoaWxkcmVuSW52aXRlZCA9IChzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IEFycmF5PEpTWC5FbGVtZW50PiA9PiB7XG4gICAgICAgIGxldCB0YXJnZXRzID0gdGhpcy5zdGF0ZS5maWx0ZXJlZEludml0ZWRNZW1iZXJzO1xuICAgICAgICBpZiAoZW5kID4gdGhpcy5zdGF0ZS5maWx0ZXJlZEludml0ZWRNZW1iZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGFyZ2V0cyA9IHRhcmdldHMuY29uY2F0KHRoaXMuZ2V0UGVuZGluZzNQaWRJbnZpdGVzKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMubWFrZU1lbWJlclRpbGVzKHRhcmdldHMuc2xpY2Uoc3RhcnQsIGVuZCkpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIGdldENoaWxkQ291bnRJbnZpdGVkID0gKCk6IG51bWJlciA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlLmZpbHRlcmVkSW52aXRlZE1lbWJlcnMubGVuZ3RoICsgKHRoaXMuZ2V0UGVuZGluZzNQaWRJbnZpdGVzKCkgfHwgW10pLmxlbmd0aDtcbiAgICB9O1xuXG4gICAgcHVibGljIHJlbmRlcigpOiBSZWFjdC5SZWFjdE5vZGUge1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5sb2FkaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIDxCYXNlQ2FyZFxuICAgICAgICAgICAgICAgICAgICBpZD1cIm1lbWJlcmxpc3QtcGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9NZW1iZXJMaXN0XCJcbiAgICAgICAgICAgICAgICAgICAgYXJpYUxhYmVsbGVkQnk9XCJtZW1iZXJsaXN0LXBhbmVsLXRhYlwiXG4gICAgICAgICAgICAgICAgICAgIHJvbGU9XCJ0YWJwYW5lbFwiXG4gICAgICAgICAgICAgICAgICAgIGhlYWRlcj17X3QoXCJjb21tb258cGVvcGxlXCIpfVxuICAgICAgICAgICAgICAgICAgICBvbkNsb3NlPXt0aGlzLnByb3BzLm9uQ2xvc2V9XG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICA8U3Bpbm5lciAvPlxuICAgICAgICAgICAgICAgIDwvQmFzZUNhcmQ+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xpID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKTtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaS5nZXRSb29tKHRoaXMucHJvcHMucm9vbUlkKTtcbiAgICAgICAgbGV0IGludml0ZUJ1dHRvbjogSlNYLkVsZW1lbnQgfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKHJvb20/LmdldE15TWVtYmVyc2hpcCgpID09PSBLbm93bk1lbWJlcnNoaXAuSm9pbiAmJiBzaG91bGRTaG93Q29tcG9uZW50KFVJQ29tcG9uZW50Lkludml0ZVVzZXJzKSkge1xuICAgICAgICAgICAgY29uc3QgaW52aXRlQnV0dG9uVGV4dCA9IHJvb20uaXNTcGFjZVJvb20oKSA/IF90KFwic3BhY2V8aW52aXRlX3RoaXNfc3BhY2VcIikgOiBfdChcInJvb218aW52aXRlX3RoaXNfcm9vbVwiKTtcblxuICAgICAgICAgICAgY29uc3QgYnV0dG9uID0gKFxuICAgICAgICAgICAgICAgIDxCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgc2l6ZT1cInNtXCJcbiAgICAgICAgICAgICAgICAgICAga2luZD1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lbWJlckxpc3RfaW52aXRlXCJcbiAgICAgICAgICAgICAgICAgICAgb25DbGljaz17dGhpcy5vbkludml0ZUJ1dHRvbkNsaWNrfVxuICAgICAgICAgICAgICAgICAgICBkaXNhYmxlZD17IXRoaXMuc3RhdGUuY2FuSW52aXRlfVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPFVzZXJBZGRJY29uIHdpZHRoPVwiMWVtXCIgaGVpZ2h0PVwiMWVtXCIgLz5cbiAgICAgICAgICAgICAgICAgICAge2ludml0ZUJ1dHRvblRleHR9XG4gICAgICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zdGF0ZS5jYW5JbnZpdGUpIHtcbiAgICAgICAgICAgICAgICBpbnZpdGVCdXR0b24gPSBidXR0b247XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGludml0ZUJ1dHRvbiA9IDxUb29sdGlwIGxhYmVsPXtfdChcIm1lbWJlcl9saXN0fGludml0ZV9idXR0b25fbm9fcGVybXNfdG9vbHRpcFwiKX0+e2J1dHRvbn08L1Rvb2x0aXA+O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGludml0ZWRIZWFkZXI7XG4gICAgICAgIGxldCBpbnZpdGVkU2VjdGlvbjtcbiAgICAgICAgaWYgKHRoaXMuZ2V0Q2hpbGRDb3VudEludml0ZWQoKSA+IDApIHtcbiAgICAgICAgICAgIGludml0ZWRIZWFkZXIgPSA8aDI+e190KFwibWVtYmVyX2xpc3R8aW52aXRlZF9saXN0X2hlYWRpbmdcIil9PC9oMj47XG4gICAgICAgICAgICBpbnZpdGVkU2VjdGlvbiA9IChcbiAgICAgICAgICAgICAgICA8VHJ1bmNhdGVkTGlzdFxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9NZW1iZXJMaXN0X3NlY3Rpb24gbXhfTWVtYmVyTGlzdF9pbnZpdGVkXCJcbiAgICAgICAgICAgICAgICAgICAgdHJ1bmNhdGVBdD17dGhpcy5zdGF0ZS50cnVuY2F0ZUF0SW52aXRlZH1cbiAgICAgICAgICAgICAgICAgICAgY3JlYXRlT3ZlcmZsb3dFbGVtZW50PXt0aGlzLmNyZWF0ZU92ZXJmbG93VGlsZUludml0ZWR9XG4gICAgICAgICAgICAgICAgICAgIGdldENoaWxkcmVuPXt0aGlzLmdldENoaWxkcmVuSW52aXRlZH1cbiAgICAgICAgICAgICAgICAgICAgZ2V0Q2hpbGRDb3VudD17dGhpcy5nZXRDaGlsZENvdW50SW52aXRlZH1cbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZvb3RlciA9IChcbiAgICAgICAgICAgIDxTZWFyY2hCb3hcbiAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9NZW1iZXJMaXN0X3F1ZXJ5IG14X3RleHRpbnB1dF9pY29uIG14X3RleHRpbnB1dF9zZWFyY2hcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPXtfdChcIm1lbWJlcl9saXN0fGZpbHRlcl9wbGFjZWhvbGRlclwiKX1cbiAgICAgICAgICAgICAgICBvblNlYXJjaD17dGhpcy5vblNlYXJjaFF1ZXJ5Q2hhbmdlZH1cbiAgICAgICAgICAgICAgICBpbml0aWFsVmFsdWU9e3RoaXMucHJvcHMuc2VhcmNoUXVlcnl9XG4gICAgICAgICAgICAvPlxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8QmFzZUNhcmRcbiAgICAgICAgICAgICAgICBpZD1cIm1lbWJlcmxpc3QtcGFuZWxcIlxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lbWJlckxpc3RcIlxuICAgICAgICAgICAgICAgIGFyaWFMYWJlbGxlZEJ5PVwibWVtYmVybGlzdC1wYW5lbC10YWJcIlxuICAgICAgICAgICAgICAgIHJvbGU9XCJ0YWJwYW5lbFwiXG4gICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcImNvbW1vbnxwZW9wbGVcIil9XG4gICAgICAgICAgICAgICAgZm9vdGVyPXtmb290ZXJ9XG4gICAgICAgICAgICAgICAgb25DbG9zZT17dGhpcy5wcm9wcy5vbkNsb3NlfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHtpbnZpdGVCdXR0b259XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9NZW1iZXJMaXN0X3dyYXBwZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgPFRydW5jYXRlZExpc3RcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X01lbWJlckxpc3Rfc2VjdGlvbiBteF9NZW1iZXJMaXN0X2pvaW5lZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnVuY2F0ZUF0PXt0aGlzLnN0YXRlLnRydW5jYXRlQXRKb2luZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVPdmVyZmxvd0VsZW1lbnQ9e3RoaXMuY3JlYXRlT3ZlcmZsb3dUaWxlSm9pbmVkfVxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0Q2hpbGRyZW49e3RoaXMuZ2V0Q2hpbGRyZW5Kb2luZWR9XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRDaGlsZENvdW50PXt0aGlzLmdldENoaWxkQ291bnRKb2luZWR9XG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIHtpbnZpdGVkSGVhZGVyfVxuICAgICAgICAgICAgICAgICAgICB7aW52aXRlZFNlY3Rpb259XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L0Jhc2VDYXJkPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25JbnZpdGVCdXR0b25DbGljayA9IChldjogQnV0dG9uRXZlbnQpOiB2b2lkID0+IHtcbiAgICAgICAgUG9zdGhvZ1RyYWNrZXJzLnRyYWNrSW50ZXJhY3Rpb24oXCJXZWJSaWdodFBhbmVsTWVtYmVyTGlzdEludml0ZUJ1dHRvblwiLCBldik7XG5cbiAgICAgICAgY29uc3QgY2xpID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKTtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaS5nZXRSb29tKHRoaXMucHJvcHMucm9vbUlkKSE7XG5cbiAgICAgICAgaW52aXRlVG9Sb29tKHJvb20pO1xuICAgIH07XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBV0EsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBYUEsSUFBQUUsTUFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsT0FBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksWUFBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssYUFBQSxHQUFBTixzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQU0sZ0JBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLFdBQUEsR0FBQVIsc0JBQUEsQ0FBQUMsT0FBQTtBQUNB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