botframework-webchat-component
Version:
React component of botframework-webchat
491 lines (405 loc) • 56.1 kB
JavaScript
"use strict";
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useTextBoxSubmit = useTextBoxSubmit;
exports.useTextBoxValue = useTextBoxValue;
exports.connectSendTextBox = exports.default = void 0;
var _botframeworkWebchatApi = require("botframework-webchat-api");
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireWildcard(require("react"));
var _AccessibleInputText = _interopRequireDefault(require("../Utils/AccessibleInputText"));
var _AutoResizeTextArea = _interopRequireDefault(require("./AutoResizeTextArea"));
var _connectToWebChat = _interopRequireDefault(require("../connectToWebChat"));
var _navigableEvent = _interopRequireDefault(require("../Utils/TypeFocusSink/navigableEvent"));
var _useFocus = _interopRequireDefault(require("../hooks/useFocus"));
var _useRegisterFocusSendBox = _interopRequireDefault(require("../hooks/internal/useRegisterFocusSendBox"));
var _useReplaceEmoticon = _interopRequireDefault(require("../hooks/internal/useReplaceEmoticon"));
var _useScrollDown = _interopRequireDefault(require("../hooks/useScrollDown"));
var _useScrollToEnd = _interopRequireDefault(require("../hooks/useScrollToEnd"));
var _useScrollUp = _interopRequireDefault(require("../hooks/useScrollUp"));
var _useStyleSet3 = _interopRequireDefault(require("../hooks/useStyleSet"));
var _useStyleToEmotionObject = _interopRequireDefault(require("../hooks/internal/useStyleToEmotionObject"));
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
var useDisabled = _botframeworkWebchatApi.hooks.useDisabled,
useLocalizer = _botframeworkWebchatApi.hooks.useLocalizer,
useSendBoxValue = _botframeworkWebchatApi.hooks.useSendBoxValue,
useStopDictate = _botframeworkWebchatApi.hooks.useStopDictate,
useStyleOptions = _botframeworkWebchatApi.hooks.useStyleOptions,
useSubmitSendBox = _botframeworkWebchatApi.hooks.useSubmitSendBox;
var ROOT_STYLE = {
'&.webchat__send-box-text-box': {
display: 'flex',
'& .webchat__send-box-text-box__input, & .webchat__send-box-text-box__text-area': {
flex: 1
}
}
};
var connectSendTextBox = function connectSendTextBox() {
for (var _len = arguments.length, selectors = new Array(_len), _key = 0; _key < _len; _key++) {
selectors[_key] = arguments[_key];
}
return _connectToWebChat.default.apply(void 0, [function (_ref) {
var disabled = _ref.disabled,
focusSendBox = _ref.focusSendBox,
language = _ref.language,
scrollToEnd = _ref.scrollToEnd,
sendBoxValue = _ref.sendBoxValue,
setSendBox = _ref.setSendBox,
stopDictate = _ref.stopDictate,
submitSendBox = _ref.submitSendBox;
return {
disabled: disabled,
language: language,
onChange: function onChange(_ref2) {
var value = _ref2.target.value;
setSendBox(value);
stopDictate();
},
onKeyPress: function onKeyPress(event) {
var key = event.key,
shiftKey = event.shiftKey;
if (key === 'Enter' && !shiftKey) {
event.preventDefault();
if (sendBoxValue) {
scrollToEnd();
submitSendBox();
focusSendBox();
}
}
},
onSubmit: function onSubmit(event) {
event.preventDefault(); // Consider clearing the send box only after we received POST_ACTIVITY_PENDING
// E.g. if the connection is bad, sending the message essentially do nothing but just clearing the send box
if (sendBoxValue) {
scrollToEnd();
submitSendBox();
}
},
value: sendBoxValue
};
}].concat(selectors));
};
exports.connectSendTextBox = connectSendTextBox;
function useTextBoxSubmit() {
var _useSendBoxValue = useSendBoxValue(),
_useSendBoxValue2 = _slicedToArray(_useSendBoxValue, 1),
sendBoxValue = _useSendBoxValue2[0];
var focus = (0, _useFocus.default)();
var scrollToEnd = (0, _useScrollToEnd.default)();
var submitSendBox = useSubmitSendBox();
return (0, _react.useCallback)(function (setFocus) {
if (sendBoxValue) {
scrollToEnd();
submitSendBox();
if (setFocus) {
if (setFocus === true) {
console.warn("\"botframework-webchat: Passing \"true\" to \"useTextBoxSubmit\" is deprecated and will be removed on or after 2022-04-23. Please pass \"sendBox\" instead.\"");
focus('sendBox');
} else {
focus(setFocus);
}
}
}
return !!sendBoxValue;
}, [focus, scrollToEnd, sendBoxValue, submitSendBox]);
}
function useTextBoxValue() {
var _useSendBoxValue3 = useSendBoxValue(),
_useSendBoxValue4 = _slicedToArray(_useSendBoxValue3, 2),
value = _useSendBoxValue4[0],
setValue = _useSendBoxValue4[1];
var replaceEmoticon = (0, _useReplaceEmoticon.default)();
var stopDictate = useStopDictate();
var setter = (0, _react.useCallback)(function (nextValue) {
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
selectionEnd = _ref3.selectionEnd,
selectionStart = _ref3.selectionStart;
if (typeof nextValue !== 'string') {
throw new Error('botframework-webchat: First argument passed to useTextBoxValue() must be a string.');
} // Currently, we cannot detect whether the change is due to clipboard paste or pressing a key on the keyboard.
// We should not change to emoji when the user is pasting text.
// We would assume, for a single character addition, the user must be pressing a key.
if (nextValue.length === value.length + 1) {
var _replaceEmoticon = replaceEmoticon({
selectionEnd: selectionEnd,
selectionStart: selectionStart,
value: nextValue
}),
nextSelectionEnd = _replaceEmoticon.selectionEnd,
nextSelectionStart = _replaceEmoticon.selectionStart,
nextValueWithEmoji = _replaceEmoticon.value;
selectionEnd = nextSelectionEnd;
selectionStart = nextSelectionStart;
nextValue = nextValueWithEmoji;
}
setValue(nextValue);
stopDictate();
return {
selectionEnd: selectionEnd,
selectionStart: selectionStart,
value: nextValue
};
}, [replaceEmoticon, setValue, stopDictate, value]);
return [value, setter];
}
var PREVENT_DEFAULT_HANDLER = function PREVENT_DEFAULT_HANDLER(event) {
return event.preventDefault();
};
var TextBox = function TextBox(_ref4) {
var className = _ref4.className;
var _useSendBoxValue5 = useSendBoxValue(),
_useSendBoxValue6 = _slicedToArray(_useSendBoxValue5, 2),
setSendBox = _useSendBoxValue6[1];
var _useStyleSet = (0, _useStyleSet3.default)(),
_useStyleSet2 = _slicedToArray(_useStyleSet, 1),
sendBoxTextBoxStyleSet = _useStyleSet2[0].sendBoxTextBox;
var _useStyleOptions = useStyleOptions(),
_useStyleOptions2 = _slicedToArray(_useStyleOptions, 1),
sendBoxTextWrap = _useStyleOptions2[0].sendBoxTextWrap;
var _useDisabled = useDisabled(),
_useDisabled2 = _slicedToArray(_useDisabled, 1),
disabled = _useDisabled2[0];
var _useTextBoxValue = useTextBoxValue(),
_useTextBoxValue2 = _slicedToArray(_useTextBoxValue, 2),
textBoxValue = _useTextBoxValue2[0],
setTextBoxValue = _useTextBoxValue2[1];
var inputElementRef = (0, _react.useRef)();
var localize = useLocalizer();
var placeCheckpointOnChangeRef = (0, _react.useRef)(false);
var prevInputStateRef = (0, _react.useRef)();
var rootClassName = (0, _useStyleToEmotionObject.default)()(ROOT_STYLE) + '';
var scrollDown = (0, _useScrollDown.default)();
var scrollUp = (0, _useScrollUp.default)();
var submitTextBox = useTextBoxSubmit();
var undoStackRef = (0, _react.useRef)([]);
var sendBoxString = localize('TEXT_INPUT_ALT');
var typeYourMessageString = localize('TEXT_INPUT_PLACEHOLDER');
var rememberInputState = (0, _react.useCallback)(function () {
var _inputElementRef$curr = inputElementRef.current,
selectionEnd = _inputElementRef$curr.selectionEnd,
selectionStart = _inputElementRef$curr.selectionStart,
value = _inputElementRef$curr.value;
prevInputStateRef.current = {
selectionEnd: selectionEnd,
selectionStart: selectionStart,
value: value
};
}, [inputElementRef, prevInputStateRef]); // This is for TypeFocusSink. When the focus in on the script, then starting press "a", without this line, it would cause errors.
// We call rememberInputState() when "onFocus" event is fired, but since this is from TypeFocusSink, we are not able to receive "onFocus" event before it happen.
(0, _react.useEffect)(rememberInputState, [rememberInputState]); // This is for moving the selection while setting the send box value.
// If we only use setSendBox, we will need to wait for the next render cycle to get the value in, before we can set selectionEnd/Start.
var setSelectionRangeAndValue = (0, _react.useCallback)(function (_ref5) {
var selectionEnd = _ref5.selectionEnd,
selectionStart = _ref5.selectionStart,
value = _ref5.value;
if (inputElementRef.current) {
// We need to set the value, before selectionStart/selectionEnd.
inputElementRef.current.value = value;
inputElementRef.current.selectionStart = selectionStart;
inputElementRef.current.selectionEnd = selectionEnd;
}
setSendBox(value);
}, [inputElementRef, setSendBox]);
var handleChange = (0, _react.useCallback)(function (event) {
var _event$target = event.target,
selectionEnd = _event$target.selectionEnd,
selectionStart = _event$target.selectionStart,
value = _event$target.value;
if (placeCheckpointOnChangeRef.current) {
undoStackRef.current.push(_objectSpread({}, prevInputStateRef.current));
placeCheckpointOnChangeRef.current = false;
}
var nextInputState = setTextBoxValue(value, {
selectionEnd: selectionEnd,
selectionStart: selectionStart
}); // If an emoticon is converted to emoji, place another checkpoint.
if (nextInputState.value !== value) {
undoStackRef.current.push({
selectionEnd: selectionEnd,
selectionStart: selectionStart,
value: value
});
placeCheckpointOnChangeRef.current = true;
setSelectionRangeAndValue(nextInputState);
}
}, [placeCheckpointOnChangeRef, prevInputStateRef, setSelectionRangeAndValue, setTextBoxValue, undoStackRef]);
var handleFocus = (0, _react.useCallback)(function () {
rememberInputState();
placeCheckpointOnChangeRef.current = true;
}, [placeCheckpointOnChangeRef, rememberInputState]);
var handleKeyDown = (0, _react.useCallback)(function (event) {
var ctrlKey = event.ctrlKey,
key = event.key,
metaKey = event.metaKey;
if ((ctrlKey || metaKey) && (key === 'Z' || key === 'z')) {
event.preventDefault();
var poppedInputState = undoStackRef.current.pop();
if (poppedInputState) {
prevInputStateRef.current = _objectSpread({}, poppedInputState);
} else {
prevInputStateRef.current = {
selectionEnd: 0,
selectionStart: 0,
value: ''
};
}
setSelectionRangeAndValue(prevInputStateRef.current);
}
}, [prevInputStateRef, setSelectionRangeAndValue, undoStackRef]);
var handleKeyPress = (0, _react.useCallback)(function (event) {
var key = event.key,
shiftKey = event.shiftKey;
if (key === 'Enter' && !shiftKey) {
event.preventDefault(); // If text box is submitted, focus on the send box
submitTextBox('sendBox'); // After submit, we will clear the undo stack.
undoStackRef.current = [];
}
}, [submitTextBox, undoStackRef]);
var handleSelect = (0, _react.useCallback)(function (_ref6) {
var _ref6$target = _ref6.target,
selectionEnd = _ref6$target.selectionEnd,
selectionStart = _ref6$target.selectionStart,
value = _ref6$target.value;
if (value === prevInputStateRef.current.value) {
// When caret move, we should push to undo stack on change.
placeCheckpointOnChangeRef.current = true;
}
prevInputStateRef.current = {
selectionEnd: selectionEnd,
selectionStart: selectionStart,
value: value
};
}, [placeCheckpointOnChangeRef, prevInputStateRef]);
var handleSubmit = (0, _react.useCallback)(function (event) {
event.preventDefault(); // Consider clearing the send box only after we received POST_ACTIVITY_PENDING
// E.g. if the connection is bad, sending the message essentially do nothing but just clearing the send box
submitTextBox(); // After submit, we will clear the undo stack.
undoStackRef.current = [];
}, [submitTextBox, undoStackRef]);
var handleKeyDownCapture = (0, _react.useCallback)(function (event) {
var ctrlKey = event.ctrlKey,
metaKey = event.metaKey,
shiftKey = event.shiftKey;
if (ctrlKey || metaKey || shiftKey) {
return;
} // Navigable event means the end-user is focusing on an inputtable element, but it is okay to capture the arrow keys.
if ((0, _navigableEvent.default)(event)) {
var handled = true;
switch (event.key) {
case 'End':
scrollDown({
displacement: Infinity
});
break;
case 'Home':
scrollUp({
displacement: Infinity
});
break;
case 'PageDown':
scrollDown();
break;
case 'PageUp':
scrollUp();
break;
default:
handled = false;
break;
}
if (handled) {
event.preventDefault();
event.stopPropagation();
}
}
}, [scrollDown, scrollUp]);
var focusCallback = (0, _react.useCallback)(function () {
var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
noKeyboard = _ref7.noKeyboard;
var current = inputElementRef.current;
if (current) {
if (noKeyboard) {
// To not activate the virtual keyboard while changing focus to an input, we will temporarily set it as read-only and flip it back.
// https://stackoverflow.com/questions/7610758/prevent-iphone-default-keyboard-when-focusing-an-input/7610923
var readOnly = current.getAttribute('readonly');
current.setAttribute('readonly', 'readonly');
setTimeout(function () {
var current = inputElementRef.current;
if (current) {
current.focus();
readOnly ? current.setAttribute('readonly', readOnly) : current.removeAttribute('readonly');
}
}, 0);
} else {
current.focus();
}
}
}, [inputElementRef]);
(0, _useRegisterFocusSendBox.default)(focusCallback);
return /*#__PURE__*/_react.default.createElement("form", {
"aria-disabled": disabled,
className: (0, _classnames.default)('webchat__send-box-text-box', rootClassName, sendBoxTextBoxStyleSet + '', (className || '') + ''),
onSubmit: disabled ? PREVENT_DEFAULT_HANDLER : handleSubmit
}, !sendBoxTextWrap ? /*#__PURE__*/_react.default.createElement(_AccessibleInputText.default, {
"aria-label": sendBoxString,
className: "webchat__send-box-text-box__input",
"data-id": "webchat-sendbox-input",
disabled: disabled,
enterKeyHint: "send",
inputMode: "text",
onChange: disabled ? undefined : handleChange,
onFocus: disabled ? undefined : handleFocus,
onKeyDown: disabled ? undefined : handleKeyDown,
onKeyDownCapture: disabled ? undefined : handleKeyDownCapture,
onKeyPress: disabled ? undefined : handleKeyPress,
onSelect: disabled ? undefined : handleSelect,
placeholder: typeYourMessageString,
readOnly: disabled,
ref: inputElementRef,
type: "text",
value: textBoxValue
}) : /*#__PURE__*/_react.default.createElement(_AutoResizeTextArea.default, {
"aria-label": sendBoxString,
className: "webchat__send-box-text-box__text-area",
"data-id": "webchat-sendbox-input",
disabled: disabled,
enterKeyHint: "send",
inputMode: "text",
onChange: disabled ? undefined : handleChange,
onFocus: disabled ? undefined : handleFocus,
onKeyDown: disabled ? undefined : handleKeyDown,
onKeyDownCapture: disabled ? undefined : handleKeyDownCapture,
onKeyPress: disabled ? undefined : handleKeyPress,
onSelect: disabled ? undefined : handleSelect,
placeholder: typeYourMessageString,
readOnly: disabled,
ref: inputElementRef,
rows: "1",
textAreaClassName: "webchat__send-box-text-box__html-text-area",
value: textBoxValue
}), disabled && /*#__PURE__*/_react.default.createElement("div", {
className: "webchat__send-box-text-box__glass"
}));
};
TextBox.defaultProps = {
className: ''
};
TextBox.propTypes = {
className: _propTypes.default.string
};
var _default = TextBox;
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TZW5kQm94L1RleHRCb3guanMiXSwibmFtZXMiOlsidXNlRGlzYWJsZWQiLCJob29rcyIsInVzZUxvY2FsaXplciIsInVzZVNlbmRCb3hWYWx1ZSIsInVzZVN0b3BEaWN0YXRlIiwidXNlU3R5bGVPcHRpb25zIiwidXNlU3VibWl0U2VuZEJveCIsIlJPT1RfU1RZTEUiLCJkaXNwbGF5IiwiZmxleCIsImNvbm5lY3RTZW5kVGV4dEJveCIsInNlbGVjdG9ycyIsImNvbm5lY3RUb1dlYkNoYXQiLCJkaXNhYmxlZCIsImZvY3VzU2VuZEJveCIsImxhbmd1YWdlIiwic2Nyb2xsVG9FbmQiLCJzZW5kQm94VmFsdWUiLCJzZXRTZW5kQm94Iiwic3RvcERpY3RhdGUiLCJzdWJtaXRTZW5kQm94Iiwib25DaGFuZ2UiLCJ2YWx1ZSIsInRhcmdldCIsIm9uS2V5UHJlc3MiLCJldmVudCIsImtleSIsInNoaWZ0S2V5IiwicHJldmVudERlZmF1bHQiLCJvblN1Ym1pdCIsInVzZVRleHRCb3hTdWJtaXQiLCJmb2N1cyIsInNldEZvY3VzIiwiY29uc29sZSIsIndhcm4iLCJ1c2VUZXh0Qm94VmFsdWUiLCJzZXRWYWx1ZSIsInJlcGxhY2VFbW90aWNvbiIsInNldHRlciIsIm5leHRWYWx1ZSIsInNlbGVjdGlvbkVuZCIsInNlbGVjdGlvblN0YXJ0IiwiRXJyb3IiLCJsZW5ndGgiLCJuZXh0U2VsZWN0aW9uRW5kIiwibmV4dFNlbGVjdGlvblN0YXJ0IiwibmV4dFZhbHVlV2l0aEVtb2ppIiwiUFJFVkVOVF9ERUZBVUxUX0hBTkRMRVIiLCJUZXh0Qm94IiwiY2xhc3NOYW1lIiwic2VuZEJveFRleHRCb3hTdHlsZVNldCIsInNlbmRCb3hUZXh0Qm94Iiwic2VuZEJveFRleHRXcmFwIiwidGV4dEJveFZhbHVlIiwic2V0VGV4dEJveFZhbHVlIiwiaW5wdXRFbGVtZW50UmVmIiwibG9jYWxpemUiLCJwbGFjZUNoZWNrcG9pbnRPbkNoYW5nZVJlZiIsInByZXZJbnB1dFN0YXRlUmVmIiwicm9vdENsYXNzTmFtZSIsInNjcm9sbERvd24iLCJzY3JvbGxVcCIsInN1Ym1pdFRleHRCb3giLCJ1bmRvU3RhY2tSZWYiLCJzZW5kQm94U3RyaW5nIiwidHlwZVlvdXJNZXNzYWdlU3RyaW5nIiwicmVtZW1iZXJJbnB1dFN0YXRlIiwiY3VycmVudCIsInNldFNlbGVjdGlvblJhbmdlQW5kVmFsdWUiLCJoYW5kbGVDaGFuZ2UiLCJwdXNoIiwibmV4dElucHV0U3RhdGUiLCJoYW5kbGVGb2N1cyIsImhhbmRsZUtleURvd24iLCJjdHJsS2V5IiwibWV0YUtleSIsInBvcHBlZElucHV0U3RhdGUiLCJwb3AiLCJoYW5kbGVLZXlQcmVzcyIsImhhbmRsZVNlbGVjdCIsImhhbmRsZVN1Ym1pdCIsImhhbmRsZUtleURvd25DYXB0dXJlIiwiaGFuZGxlZCIsImRpc3BsYWNlbWVudCIsIkluZmluaXR5Iiwic3RvcFByb3BhZ2F0aW9uIiwiZm9jdXNDYWxsYmFjayIsIm5vS2V5Ym9hcmQiLCJyZWFkT25seSIsImdldEF0dHJpYnV0ZSIsInNldEF0dHJpYnV0ZSIsInNldFRpbWVvdXQiLCJyZW1vdmVBdHRyaWJ1dGUiLCJ1bmRlZmluZWQiLCJkZWZhdWx0UHJvcHMiLCJwcm9wVHlwZXMiLCJQcm9wVHlwZXMiLCJzdHJpbmciXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBRVFBLFcsR0FBa0dDLDZCLENBQWxHRCxXO0lBQWFFLFksR0FBcUZELDZCLENBQXJGQyxZO0lBQWNDLGUsR0FBdUVGLDZCLENBQXZFRSxlO0lBQWlCQyxjLEdBQXNESCw2QixDQUF0REcsYztJQUFnQkMsZSxHQUFzQ0osNkIsQ0FBdENJLGU7SUFBaUJDLGdCLEdBQXFCTCw2QixDQUFyQkssZ0I7QUFFckYsSUFB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QVEsRUFBRWpFLFFBQVEsR0FBR2dGLFNBQUgsR0FBZWQsWUFabkM7QUFhRSxJQUFBLFdBQVcsRUFBRWQscUJBYmY7QUFjRSxJQUFBLFFBQVEsRUFBRXBELFFBZFo7QUFlRSxJQUFBLEdBQUcsRUFBRTBDLGVBZlA7QUFnQkUsSUFBQSxJQUFJLEVBQUMsR0FoQlA7QUFpQkUsSUFBQSxpQkFBaUIsRUFBQyw0Q0FqQnBCO0FBa0JFLElBQUEsS0FBSyxFQUFFRjtBQWxCVCxJQS9CSixFQW9ER3hDLFFBQVEsaUJBQUk7QUFBSyxJQUFBLFNBQVMsRUFBQztBQUFmLElBcERmLENBREY7QUF3REQsQ0FqUkQ7O0FBbVJBbUMsT0FBTyxDQUFDOEMsWUFBUixHQUF1QjtBQUNyQjdDLEVBQUFBLFNBQVMsRUFBRTtBQURVLENBQXZCO0FBSUFELE9BQU8sQ0FBQytDLFNBQVIsR0FBb0I7QUFDbEI5QyxFQUFBQSxTQUFTLEVBQUUrQyxtQkFBVUM7QUFESCxDQUFwQjtlQUllakQsTyIsInNvdXJjZVJvb3QiOiJjb21wb25lbnQ6Ly8vIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaG9va3MgfSBmcm9tICdib3RmcmFtZXdvcmstd2ViY2hhdC1hcGknO1xuaW1wb3J0IGNsYXNzTmFtZXMgZnJvbSAnY2xhc3NuYW1lcyc7XG5pbXBvcnQgUHJvcFR5cGVzIGZyb20gJ3Byb3AtdHlwZXMnO1xuaW1wb3J0IFJlYWN0LCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QsIHVzZVJlZiB9IGZyb20gJ3JlYWN0JztcblxuaW1wb3J0IEFjY2Vzc2libGVJbnB1dFRleHQgZnJvbSAnLi4vVXRpbHMvQWNjZXNzaWJsZUlucHV0VGV4dCc7XG5pbXBvcnQgQXV0b1Jlc2l6ZVRleHRBcmVhIGZyb20gJy4vQXV0b1Jlc2l6ZVRleHRBcmVhJztcbmltcG9ydCBjb25uZWN0VG9XZWJDaGF0IGZyb20gJy4uL2Nvbm5lY3RUb1dlYkNoYXQnO1xuaW1wb3J0IG5hdmlnYWJsZUV2ZW50IGZyb20gJy4uL1V0aWxzL1R5cGVGb2N1c1NpbmsvbmF2aWdhYmxlRXZlbnQnO1xuaW1wb3J0IHVzZUZvY3VzIGZyb20gJy4uL2hvb2tzL3VzZUZvY3VzJztcbmltcG9ydCB1c2VSZWdpc3RlckZvY3VzU2VuZEJveCBmcm9tICcuLi9ob29rcy9pbnRlcm5hbC91c2VSZWdpc3RlckZvY3VzU2VuZEJveCc7XG5pbXBvcnQgdXNlUmVwbGFjZUVtb3RpY29uIGZyb20gJy4uL2hvb2tzL2ludGVybmFsL3VzZVJlcGxhY2VFbW90aWNvbic7XG5pbXBvcnQgdXNlU2Nyb2xsRG93biBmcm9tICcuLi9ob29rcy91c2VTY3JvbGxEb3duJztcbmltcG9ydCB1c2VTY3JvbGxUb0VuZCBmcm9tICcuLi9ob29rcy91c2VTY3JvbGxUb0VuZCc7XG5pbXBvcnQgdXNlU2Nyb2xsVXAgZnJvbSAnLi4vaG9va3MvdXNlU2Nyb2xsVXAnO1xuaW1wb3J0IHVzZVN0eWxlU2V0IGZyb20gJy4uL2hvb2tzL3VzZVN0eWxlU2V0JztcbmltcG9ydCB1c2VTdHlsZVRvRW1vdGlvbk9iamVjdCBmcm9tICcuLi9ob29rcy9pbnRlcm5hbC91c2VTdHlsZVRvRW1vdGlvbk9iamVjdCc7XG5cbmNvbnN0IHsgdXNlRGlzYWJsZWQsIHVzZUxvY2FsaXplciwgdXNlU2VuZEJveFZhbHVlLCB1c2VTdG9wRGljdGF0ZSwgdXNlU3R5bGVPcHRpb25zLCB1c2VTdWJtaXRTZW5kQm94IH0gPSBob29rcztcblxuY29uc3QgUk9PVF9TVFlMRSA9IHtcbiAgJyYud2ViY2hhdF9fc2VuZC1ib3gtdGV4dC1ib3gnOiB7XG4gICAgZGlzcGxheTogJ2ZsZXgnLFxuXG4gICAgJyYgLndlYmNoYXRfX3NlbmQtYm94LXRleHQtYm94X19pbnB1dCwgJiAud2ViY2hhdF9fc2VuZC1ib3gtdGV4dC1ib3hfX3RleHQtYXJlYSc6IHtcbiAgICAgIGZsZXg6IDFcbiAgICB9XG4gIH1cbn07XG5cbmNvbnN0IGNvbm5lY3RTZW5kVGV4dEJveCA9ICguLi5zZWxlY3RvcnMpID0+XG4gIGNvbm5lY3RUb1dlYkNoYXQoXG4gICAgKHsgZGlzYWJsZWQsIGZvY3VzU2VuZEJveCwgbGFuZ3VhZ2UsIHNjcm9sbFRvRW5kLCBzZW5kQm94VmFsdWUsIHNldFNlbmRCb3gsIHN0b3BEaWN0YXRlLCBzdWJtaXRTZW5kQm94IH0pID0+ICh7XG4gICAgICBkaXNhYmxlZCxcbiAgICAgIGxhbmd1YWdlLFxuICAgICAgb25DaGFuZ2U6ICh7IHRhcmdldDogeyB2YWx1ZSB9IH0pID0+IHtcbiAgICAgICAgc2V0U2VuZEJveCh2YWx1ZSk7XG4gICAgICAgIHN0b3BEaWN0YXRlKCk7XG4gICAgICB9LFxuICAgICAgb25LZXlQcmVzczogZXZlbnQgPT4ge1xuICAgICAgICBjb25zdCB7IGtleSwgc2hpZnRLZXkgfSA9IGV2ZW50O1xuXG4gICAgICAgIGlmIChrZXkgPT09ICdFbnRlcicgJiYgIXNoaWZ0S2V5KSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgIGlmIChzZW5kQm94VmFsdWUpIHtcbiAgICAgICAgICAgIHNjcm9sbFRvRW5kKCk7XG4gICAgICAgICAgICBzdWJtaXRTZW5kQm94KCk7XG4gICAgICAgICAgICBmb2N1c1NlbmRCb3goKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBvblN1Ym1pdDogZXZlbnQgPT4ge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIC8vIENvbnNpZGVyIGNsZWFyaW5nIHRoZSBzZW5kIGJveCBvbmx5IGFmdGVyIHdlIHJlY2VpdmVkIFBPU1RfQUNUSVZJVFlfUEVORElOR1xuICAgICAgICAvLyBFLmcuIGlmIHRoZSBjb25uZWN0aW9uIGlzIGJhZCwgc2VuZGluZyB0aGUgbWVzc2FnZSBlc3NlbnRpYWxseSBkbyBub3RoaW5nIGJ1dCBqdXN0IGNsZWFyaW5nIHRoZSBzZW5kIGJveFxuXG4gICAgICAgIGlmIChzZW5kQm94VmFsdWUpIHtcbiAgICAgICAgICBzY3JvbGxUb0VuZCgpO1xuICAgICAgICAgIHN1Ym1pdFNlbmRCb3goKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHZhbHVlOiBzZW5kQm94VmFsdWVcbiAgICB9KSxcbiAgICAuLi5zZWxlY3RvcnNcbiAgKTtcblxuZnVuY3Rpb24gdXNlVGV4dEJveFN1Ym1pdCgpIHtcbiAgY29uc3QgW3NlbmRCb3hWYWx1ZV0gPSB1c2VTZW5kQm94VmFsdWUoKTtcbiAgY29uc3QgZm9jdXMgPSB1c2VGb2N1cygpO1xuICBjb25zdCBzY3JvbGxUb0VuZCA9IHVzZVNjcm9sbFRvRW5kKCk7XG4gIGNvbnN0IHN1Ym1pdFNlbmRCb3ggPSB1c2VTdWJtaXRTZW5kQm94KCk7XG5cbiAgcmV0dXJuIHVzZUNhbGxiYWNrKFxuICAgIHNldEZvY3VzID0+IHtcbiAgICAgIGlmIChzZW5kQm94VmFsdWUpIHtcbiAgICAgICAgc2Nyb2xsVG9FbmQoKTtcbiAgICAgICAgc3VibWl0U2VuZEJveCgpO1xuXG4gICAgICAgIGlmIChzZXRGb2N1cykge1xuICAgICAgICAgIGlmIChzZXRGb2N1cyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICBgXCJib3RmcmFtZXdvcmstd2ViY2hhdDogUGFzc2luZyBcInRydWVcIiB0byBcInVzZVRleHRCb3hTdWJtaXRcIiBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgb24gb3IgYWZ0ZXIgMjAyMi0wNC0yMy4gUGxlYXNlIHBhc3MgXCJzZW5kQm94XCIgaW5zdGVhZC5cImBcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGZvY3VzKCdzZW5kQm94Jyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvY3VzKHNldEZvY3VzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuICEhc2VuZEJveFZhbHVlO1xuICAgIH0sXG4gICAgW2ZvY3VzLCBzY3JvbGxUb0VuZCwgc2VuZEJveFZhbHVlLCBzdWJtaXRTZW5kQm94XVxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VUZXh0Qm94VmFsdWUoKSB7XG4gIGNvbnN0IFt2YWx1ZSwgc2V0VmFsdWVdID0gdXNlU2VuZEJveFZhbHVlKCk7XG4gIGNvbnN0IHJlcGxhY2VFbW90aWNvbiA9IHVzZVJlcGxhY2VFbW90aWNvbigpO1xuICBjb25zdCBzdG9wRGljdGF0ZSA9IHVzZVN0b3BEaWN0YXRlKCk7XG5cbiAgY29uc3Qgc2V0dGVyID0gdXNlQ2FsbGJhY2soXG4gICAgKG5leHRWYWx1ZSwgeyBzZWxlY3Rpb25FbmQsIHNlbGVjdGlvblN0YXJ0IH0gPSB7fSkgPT4ge1xuICAgICAgaWYgKHR5cGVvZiBuZXh0VmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYm90ZnJhbWV3b3JrLXdlYmNoYXQ6IEZpcnN0IGFyZ3VtZW50IHBhc3NlZCB0byB1c2VUZXh0Qm94VmFsdWUoKSBtdXN0IGJlIGEgc3RyaW5nLicpO1xuICAgICAgfVxuXG4gICAgICAvLyBDdXJyZW50bHksIHdlIGNhbm5vdCBkZXRlY3Qgd2hldGhlciB0aGUgY2hhbmdlIGlzIGR1ZSB0byBjbGlwYm9hcmQgcGFzdGUgb3IgcHJlc3NpbmcgYSBrZXkgb24gdGhlIGtleWJvYXJkLlxuICAgICAgLy8gV2Ugc2hvdWxkIG5vdCBjaGFuZ2UgdG8gZW1vamkgd2hlbiB0aGUgdXNlciBpcyBwYXN0aW5nIHRleHQuXG4gICAgICAvLyBXZSB3b3VsZCBhc3N1bWUsIGZvciBhIHNpbmdsZSBjaGFyYWN0ZXIgYWRkaXRpb24sIHRoZSB1c2VyIG11c3QgYmUgcHJlc3NpbmcgYSBrZXkuXG4gICAgICBpZiAobmV4dFZhbHVlLmxlbmd0aCA9PT0gdmFsdWUubGVuZ3RoICsgMSkge1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgc2VsZWN0aW9uRW5kOiBuZXh0U2VsZWN0aW9uRW5kLFxuICAgICAgICAgIHNlbGVjdGlvblN0YXJ0OiBuZXh0U2VsZWN0aW9uU3RhcnQsXG4gICAgICAgICAgdmFsdWU6IG5leHRWYWx1ZVdpdGhFbW9qaVxuICAgICAgICB9ID0gcmVwbGFjZUVtb3RpY29uKHsgc2VsZWN0aW9uRW5kLCBzZWxlY3Rpb25TdGFydCwgdmFsdWU6IG5leHRWYWx1ZSB9KTtcblxuICAgICAgICBzZWxlY3Rpb25FbmQgPSBuZXh0U2VsZWN0aW9uRW5kO1xuICAgICAgICBzZWxlY3Rpb25TdGFydCA9IG5leHRTZWxlY3Rpb25TdGFydDtcbiAgICAgICAgbmV4dFZhbHVlID0gbmV4dFZhbHVlV2l0aEVtb2ppO1xuICAgICAgfVxuXG4gICAgICBzZXRWYWx1ZShuZXh0VmFsdWUpO1xuICAgICAgc3RvcERpY3RhdGUoKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2VsZWN0aW9uRW5kLFxuICAgICAgICBzZWxlY3Rpb25TdGFydCxcbiAgICAgICAgdmFsdWU6IG5leHRWYWx1ZVxuICAgICAgfTtcbiAgICB9LFxuICAgIFtyZXBsYWNlRW1vdGljb24sIHNldFZhbHVlLCBzdG9wRGljdGF0ZSwgdmFsdWVdXG4gICk7XG5cbiAgcmV0dXJuIFt2YWx1ZSwgc2V0dGVyXTtcbn1cblxuY29uc3QgUFJFVkVOVF9ERUZBVUxUX0hBTkRMRVIgPSBldmVudCA9PiBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG5jb25zdCBUZXh0Qm94ID0gKHsgY2xhc3NOYW1lIH0pID0+IHtcbiAgY29uc3QgWywgc2V0U2VuZEJveF0gPSB1c2VTZW5kQm94VmFsdWUoKTtcbiAgY29uc3QgW3sgc2VuZEJveFRleHRCb3g6IHNlbmRCb3hUZXh0Qm94U3R5bGVTZXQgfV0gPSB1c2VTdHlsZVNldCgpO1xuICBjb25zdCBbeyBzZW5kQm94VGV4dFdyYXAgfV0gPSB1c2VTdHlsZU9wdGlvbnMoKTtcbiAgY29uc3QgW2Rpc2FibGVkXSA9IHVzZURpc2FibGVkKCk7XG4gIGNvbnN0IFt0ZXh0Qm94VmFsdWUsIHNldFRleHRCb3hWYWx1ZV0gPSB1c2VUZXh0Qm94VmFsdWUoKTtcbiAgY29uc3QgaW5wdXRFbGVtZW50UmVmID0gdXNlUmVmKCk7XG4gIGNvbnN0IGxvY2FsaXplID0gdXNlTG9jYWxpemVyKCk7XG4gIGNvbnN0IHBsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmID0gdXNlUmVmKGZhbHNlKTtcbiAgY29uc3QgcHJldklucHV0U3RhdGVSZWYgPSB1c2VSZWYoKTtcbiAgY29uc3Qgcm9vdENsYXNzTmFtZSA9IHVzZVN0eWxlVG9FbW90aW9uT2JqZWN0KCkoUk9PVF9TVFlMRSkgKyAnJztcbiAgY29uc3Qgc2Nyb2xsRG93biA9IHVzZVNjcm9sbERvd24oKTtcbiAgY29uc3Qgc2Nyb2xsVXAgPSB1c2VTY3JvbGxVcCgpO1xuICBjb25zdCBzdWJtaXRUZXh0Qm94ID0gdXNlVGV4dEJveFN1Ym1pdCgpO1xuICBjb25zdCB1bmRvU3RhY2tSZWYgPSB1c2VSZWYoW10pO1xuXG4gIGNvbnN0IHNlbmRCb3hTdHJpbmcgPSBsb2NhbGl6ZSgnVEVYVF9JTlBVVF9BTFQnKTtcbiAgY29uc3QgdHlwZVlvdXJNZXNzYWdlU3RyaW5nID0gbG9jYWxpemUoJ1RFWFRfSU5QVVRfUExBQ0VIT0xERVInKTtcblxuICBjb25zdCByZW1lbWJlcklucHV0U3RhdGUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgY29uc3Qge1xuICAgICAgY3VycmVudDogeyBzZWxlY3Rpb25FbmQsIHNlbGVjdGlvblN0YXJ0LCB2YWx1ZSB9XG4gICAgfSA9IGlucHV0RWxlbWVudFJlZjtcblxuICAgIHByZXZJbnB1dFN0YXRlUmVmLmN1cnJlbnQgPSB7IHNlbGVjdGlvbkVuZCwgc2VsZWN0aW9uU3RhcnQsIHZhbHVlIH07XG4gIH0sIFtpbnB1dEVsZW1lbnRSZWYsIHByZXZJbnB1dFN0YXRlUmVmXSk7XG5cbiAgLy8gVGhpcyBpcyBmb3IgVHlwZUZvY3VzU2luay4gV2hlbiB0aGUgZm9jdXMgaW4gb24gdGhlIHNjcmlwdCwgdGhlbiBzdGFydGluZyBwcmVzcyBcImFcIiwgd2l0aG91dCB0aGlzIGxpbmUsIGl0IHdvdWxkIGNhdXNlIGVycm9ycy5cbiAgLy8gV2UgY2FsbCByZW1lbWJlcklucHV0U3RhdGUoKSB3aGVuIFwib25Gb2N1c1wiIGV2ZW50IGlzIGZpcmVkLCBidXQgc2luY2UgdGhpcyBpcyBmcm9tIFR5cGVGb2N1c1NpbmssIHdlIGFyZSBub3QgYWJsZSB0byByZWNlaXZlIFwib25Gb2N1c1wiIGV2ZW50IGJlZm9yZSBpdCBoYXBwZW4uXG4gIHVzZUVmZmVjdChyZW1lbWJlcklucHV0U3RhdGUsIFtyZW1lbWJlcklucHV0U3RhdGVdKTtcblxuICAvLyBUaGlzIGlzIGZvciBtb3ZpbmcgdGhlIHNlbGVjdGlvbiB3aGlsZSBzZXR0aW5nIHRoZSBzZW5kIGJveCB2YWx1ZS5cbiAgLy8gSWYgd2Ugb25seSB1c2Ugc2V0U2VuZEJveCwgd2Ugd2lsbCBuZWVkIHRvIHdhaXQgZm9yIHRoZSBuZXh0IHJlbmRlciBjeWNsZSB0byBnZXQgdGhlIHZhbHVlIGluLCBiZWZvcmUgd2UgY2FuIHNldCBzZWxlY3Rpb25FbmQvU3RhcnQuXG4gIGNvbnN0IHNldFNlbGVjdGlvblJhbmdlQW5kVmFsdWUgPSB1c2VDYWxsYmFjayhcbiAgICAoeyBzZWxlY3Rpb25FbmQsIHNlbGVjdGlvblN0YXJ0LCB2YWx1ZSB9KSA9PiB7XG4gICAgICBpZiAoaW5wdXRFbGVtZW50UmVmLmN1cnJlbnQpIHtcbiAgICAgICAgLy8gV2UgbmVlZCB0byBzZXQgdGhlIHZhbHVlLCBiZWZvcmUgc2VsZWN0aW9uU3RhcnQvc2VsZWN0aW9uRW5kLlxuICAgICAgICBpbnB1dEVsZW1lbnRSZWYuY3VycmVudC52YWx1ZSA9IHZhbHVlO1xuXG4gICAgICAgIGlucHV0RWxlbWVudFJlZi5jdXJyZW50LnNlbGVjdGlvblN0YXJ0ID0gc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgIGlucHV0RWxlbWVudFJlZi5jdXJyZW50LnNlbGVjdGlvbkVuZCA9IHNlbGVjdGlvbkVuZDtcbiAgICAgIH1cblxuICAgICAgc2V0U2VuZEJveCh2YWx1ZSk7XG4gICAgfSxcbiAgICBbaW5wdXRFbGVtZW50UmVmLCBzZXRTZW5kQm94XVxuICApO1xuXG4gIGNvbnN0IGhhbmRsZUNoYW5nZSA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgdGFyZ2V0OiB7IHNlbGVjdGlvbkVuZCwgc2VsZWN0aW9uU3RhcnQsIHZhbHVlIH1cbiAgICAgIH0gPSBldmVudDtcblxuICAgICAgaWYgKHBsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgdW5kb1N0YWNrUmVmLmN1cnJlbnQucHVzaCh7IC4uLnByZXZJbnB1dFN0YXRlUmVmLmN1cnJlbnQgfSk7XG5cbiAgICAgICAgcGxhY2VDaGVja3BvaW50T25DaGFuZ2VSZWYuY3VycmVudCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBuZXh0SW5wdXRTdGF0ZSA9IHNldFRleHRCb3hWYWx1ZSh2YWx1ZSwgeyBzZWxlY3Rpb25FbmQsIHNlbGVjdGlvblN0YXJ0IH0pO1xuXG4gICAgICAvLyBJZiBhbiBlbW90aWNvbiBpcyBjb252ZXJ0ZWQgdG8gZW1vamksIHBsYWNlIGFub3RoZXIgY2hlY2twb2ludC5cbiAgICAgIGlmIChuZXh0SW5wdXRTdGF0ZS52YWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgdW5kb1N0YWNrUmVmLmN1cnJlbnQucHVzaCh7IHNlbGVjdGlvbkVuZCwgc2VsZWN0aW9uU3RhcnQsIHZhbHVlIH0pO1xuXG4gICAgICAgIHBsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmLmN1cnJlbnQgPSB0cnVlO1xuXG4gICAgICAgIHNldFNlbGVjdGlvblJhbmdlQW5kVmFsdWUobmV4dElucHV0U3RhdGUpO1xuICAgICAgfVxuICAgIH0sXG4gICAgW3BsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmLCBwcmV2SW5wdXRTdGF0ZVJlZiwgc2V0U2VsZWN0aW9uUmFuZ2VBbmRWYWx1ZSwgc2V0VGV4dEJveFZhbHVlLCB1bmRvU3RhY2tSZWZdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlRm9jdXMgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgcmVtZW1iZXJJbnB1dFN0YXRlKCk7XG5cbiAgICBwbGFjZUNoZWNrcG9pbnRPbkNoYW5nZVJlZi5jdXJyZW50ID0gdHJ1ZTtcbiAgfSwgW3BsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmLCByZW1lbWJlcklucHV0U3RhdGVdKTtcblxuICBjb25zdCBoYW5kbGVLZXlEb3duID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgY29uc3QgeyBjdHJsS2V5LCBrZXksIG1ldGFLZXkgfSA9IGV2ZW50O1xuXG4gICAgICBpZiAoKGN0cmxLZXkgfHwgbWV0YUtleSkgJiYgKGtleSA9PT0gJ1onIHx8IGtleSA9PT0gJ3onKSkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGNvbnN0IHBvcHBlZElucHV0U3RhdGUgPSB1bmRvU3RhY2tSZWYuY3VycmVudC5wb3AoKTtcblxuICAgICAgICBpZiAocG9wcGVkSW5wdXRTdGF0ZSkge1xuICAgICAgICAgIHByZXZJbnB1dFN0YXRlUmVmLmN1cnJlbnQgPSB7IC4uLnBvcHBlZElucHV0U3RhdGUgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBwcmV2SW5wdXRTdGF0ZVJlZi5jdXJyZW50ID0geyBzZWxlY3Rpb25FbmQ6IDAsIHNlbGVjdGlvblN0YXJ0OiAwLCB2YWx1ZTogJycgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldFNlbGVjdGlvblJhbmdlQW5kVmFsdWUocHJldklucHV0U3RhdGVSZWYuY3VycmVudCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBbcHJldklucHV0U3RhdGVSZWYsIHNldFNlbGVjdGlvblJhbmdlQW5kVmFsdWUsIHVuZG9TdGFja1JlZl1cbiAgKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IHsga2V5LCBzaGlmdEtleSB9ID0gZXZlbnQ7XG5cbiAgICAgIGlmIChrZXkgPT09ICdFbnRlcicgJiYgIXNoaWZ0S2V5KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgLy8gSWYgdGV4dCBib3ggaXMgc3VibWl0dGVkLCBmb2N1cyBvbiB0aGUgc2VuZCBib3hcbiAgICAgICAgc3VibWl0VGV4dEJveCgnc2VuZEJveCcpO1xuXG4gICAgICAgIC8vIEFmdGVyIHN1Ym1pdCwgd2Ugd2lsbCBjbGVhciB0aGUgdW5kbyBzdGFjay5cbiAgICAgICAgdW5kb1N0YWNrUmVmLmN1cnJlbnQgPSBbXTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtzdWJtaXRUZXh0Qm94LCB1bmRvU3RhY2tSZWZdXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlU2VsZWN0ID0gdXNlQ2FsbGJhY2soXG4gICAgKHsgdGFyZ2V0OiB7IHNlbGVjdGlvbkVuZCwgc2VsZWN0aW9uU3RhcnQsIHZhbHVlIH0gfSkgPT4ge1xuICAgICAgaWYgKHZhbHVlID09PSBwcmV2SW5wdXRTdGF0ZVJlZi5jdXJyZW50LnZhbHVlKSB7XG4gICAgICAgIC8vIFdoZW4gY2FyZXQgbW92ZSwgd2Ugc2hvdWxkIHB1c2ggdG8gdW5kbyBzdGFjayBvbiBjaGFuZ2UuXG4gICAgICAgIHBsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBwcmV2SW5wdXRTdGF0ZVJlZi5jdXJyZW50ID0geyBzZWxlY3Rpb25FbmQsIHNlbGVjdGlvblN0YXJ0LCB2YWx1ZSB9O1xuICAgIH0sXG4gICAgW3BsYWNlQ2hlY2twb2ludE9uQ2hhbmdlUmVmLCBwcmV2SW5wdXRTdGF0ZVJlZl1cbiAgKTtcblxuICBjb25zdCBoYW5kbGVTdWJtaXQgPSB1c2VDYWxsYmFjayhcbiAgICBldmVudCA9PiB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAvLyBDb25zaWRlciBjbGVhcmluZyB0aGUgc2VuZCBib3ggb25seSBhZnRlciB3ZSByZWNlaXZlZCBQT1NUX0FDVElWSVRZX1BFTkRJTkdcbiAgICAgIC8vIEUuZy4gaWYgdGhlIGNvbm5lY3Rpb24gaXMgYmFk