matrix-react-sdk
Version:
SDK for matrix.org using React
250 lines (243 loc) • 45.2 kB
JavaScript
"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 = _interopRequireWildcard(require("react"));
var _matrix = require("matrix-js-sdk/src/matrix");
var _logger = require("matrix-js-sdk/src/logger");
var _files = _interopRequireDefault(require("@vector-im/compound-design-tokens/assets/web/icons/files"));
var _MatrixClientPeg = require("../../MatrixClientPeg");
var _EventIndexPeg = _interopRequireDefault(require("../../indexing/EventIndexPeg"));
var _languageHandler = require("../../languageHandler");
var _SearchWarning = _interopRequireWildcard(require("../views/elements/SearchWarning"));
var _BaseCard = _interopRequireDefault(require("../views/right_panel/BaseCard"));
var _TimelinePanel = _interopRequireDefault(require("./TimelinePanel"));
var _Spinner = _interopRequireDefault(require("../views/elements/Spinner"));
var _Layout = require("../../settings/enums/Layout");
var _RoomContext = _interopRequireWildcard(require("../../contexts/RoomContext"));
var _Measured = _interopRequireDefault(require("../views/elements/Measured"));
var _EmptyState = _interopRequireDefault(require("../views/right_panel/EmptyState"));
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; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /*
Copyright 2024 New Vector Ltd.
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
Copyright 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.
*/
/*
* Component which shows the filtered file using a TimelinePanel
*/
class FilePanel extends _react.default.Component {
constructor(...args) {
super(...args);
// This is used to track if a decrypted event was a live event and should be
// added to the timeline.
(0, _defineProperty2.default)(this, "decryptingEvents", new Set());
(0, _defineProperty2.default)(this, "noRoom", false);
(0, _defineProperty2.default)(this, "card", /*#__PURE__*/(0, _react.createRef)());
(0, _defineProperty2.default)(this, "state", {
timelineSet: null,
narrow: false
});
(0, _defineProperty2.default)(this, "onRoomTimeline", (ev, room, toStartOfTimeline, removed, data) => {
if (room?.roomId !== this.props.roomId) return;
if (toStartOfTimeline || !data || !data.liveEvent || ev.isRedacted()) return;
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
client.decryptEventIfNeeded(ev);
if (ev.isBeingDecrypted()) {
this.decryptingEvents.add(ev.getId());
} else {
this.addEncryptedLiveEvent(ev);
}
});
(0, _defineProperty2.default)(this, "onEventDecrypted", (ev, err) => {
if (ev.getRoomId() !== this.props.roomId) return;
const eventId = ev.getId();
if (!this.decryptingEvents.delete(eventId)) return;
if (err) return;
this.addEncryptedLiveEvent(ev);
});
(0, _defineProperty2.default)(this, "onPaginationRequest", (timelineWindow, direction, limit) => {
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const eventIndex = _EventIndexPeg.default.get();
const roomId = this.props.roomId;
const room = client.getRoom(roomId);
// We override the pagination request for encrypted rooms so that we ask
// the event index to fulfill the pagination request. Asking the server
// to paginate won't ever work since the server can't correctly filter
// out events containing URLs
if (room && client.isRoomEncrypted(roomId) && eventIndex !== null) {
return eventIndex.paginateTimelineWindow(room, timelineWindow, direction, limit);
} else {
return timelineWindow.paginate(direction, limit);
}
});
(0, _defineProperty2.default)(this, "onMeasurement", narrow => {
this.setState({
narrow
});
});
}
addEncryptedLiveEvent(ev) {
if (!this.state.timelineSet) return;
const timeline = this.state.timelineSet.getLiveTimeline();
if (ev.getType() !== "m.room.message") return;
if (!["m.file", "m.image", "m.video", "m.audio"].includes(ev.getContent().msgtype)) {
return;
}
if (!this.state.timelineSet.eventIdToTimeline(ev.getId())) {
this.state.timelineSet.addEventToTimeline(ev, timeline, false);
}
}
async componentDidMount() {
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
await this.updateTimelineSet(this.props.roomId);
if (!client.isRoomEncrypted(this.props.roomId)) return;
// The timelineSets filter makes sure that encrypted events that contain
// URLs never get added to the timeline, even if they are live events.
// These methods are here to manually listen for such events and add
// them despite the filter's best efforts.
//
// We do this only for encrypted rooms and if an event index exists,
// this could be made more general in the future or the filter logic
// could be fixed.
if (_EventIndexPeg.default.get() !== null) {
client.on(_matrix.RoomEvent.Timeline, this.onRoomTimeline);
client.on(_matrix.MatrixEventEvent.Decrypted, this.onEventDecrypted);
}
}
componentWillUnmount() {
const client = _MatrixClientPeg.MatrixClientPeg.get();
if (client === null) return;
if (!client.isRoomEncrypted(this.props.roomId)) return;
if (_EventIndexPeg.default.get() !== null) {
client.removeListener(_matrix.RoomEvent.Timeline, this.onRoomTimeline);
client.removeListener(_matrix.MatrixEventEvent.Decrypted, this.onEventDecrypted);
}
}
async fetchFileEventsServer(room) {
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const filter = new _matrix.Filter(client.getSafeUserId());
filter.setDefinition({
room: {
timeline: {
contains_url: true,
types: ["m.room.message"]
}
}
});
filter.filterId = await client.getOrCreateFilter("FILTER_FILES_" + client.credentials.userId, filter);
return room.getOrCreateFilteredTimelineSet(filter);
}
async updateTimelineSet(roomId) {
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const room = client.getRoom(roomId);
const eventIndex = _EventIndexPeg.default.get();
this.noRoom = !room;
if (room) {
let timelineSet;
try {
timelineSet = await this.fetchFileEventsServer(room);
// If this room is encrypted the file panel won't be populated
// correctly since the defined filter doesn't support encrypted
// events and the server can't check if encrypted events contain
// URLs.
//
// This is where our event index comes into place, we ask the
// event index to populate the timelineSet for us. This call
// will add 10 events to the live timeline of the set. More can
// be requested using pagination.
if (client.isRoomEncrypted(roomId) && eventIndex !== null) {
const timeline = timelineSet.getLiveTimeline();
await eventIndex.populateFileTimeline(timelineSet, timeline, room, 10);
}
this.setState({
timelineSet: timelineSet
});
} catch (error) {
_logger.logger.error("Failed to get or create file panel filter", error);
}
} else {
_logger.logger.error("Failed to add filtered timelineSet for FilePanel as no room!");
}
}
render() {
if (_MatrixClientPeg.MatrixClientPeg.safeGet().isGuest()) {
return /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: "mx_FilePanel mx_RoomView_messageListWrapper",
onClose: this.props.onClose,
header: (0, _languageHandler._t)("right_panel|files_button")
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_RoomView_empty"
}, (0, _languageHandler._t)("file_panel|guest_note", {}, {
a: sub => /*#__PURE__*/_react.default.createElement("a", {
href: "#/register",
key: "sub"
}, sub)
})));
} else if (this.noRoom) {
return /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: "mx_FilePanel mx_RoomView_messageListWrapper",
onClose: this.props.onClose,
header: (0, _languageHandler._t)("right_panel|files_button")
}, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_RoomView_empty"
}, (0, _languageHandler._t)("file_panel|peek_note")));
}
// wrap a TimelinePanel with the jump-to-event bits turned off.
const emptyState = /*#__PURE__*/_react.default.createElement(_EmptyState.default, {
Icon: _files.default,
title: (0, _languageHandler._t)("file_panel|empty_heading"),
description: (0, _languageHandler._t)("file_panel|empty_description")
});
const isRoomEncrypted = this.noRoom ? false : _MatrixClientPeg.MatrixClientPeg.safeGet().isRoomEncrypted(this.props.roomId);
if (this.state.timelineSet) {
return /*#__PURE__*/_react.default.createElement(_RoomContext.default.Provider, {
value: _objectSpread(_objectSpread({}, this.context), {}, {
timelineRenderingType: _RoomContext.TimelineRenderingType.File,
narrow: this.state.narrow
})
}, /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: "mx_FilePanel",
onClose: this.props.onClose,
withoutScrollContainer: true,
ref: this.card,
header: (0, _languageHandler._t)("right_panel|files_button")
}, this.card.current && /*#__PURE__*/_react.default.createElement(_Measured.default, {
sensor: this.card.current,
onMeasurement: this.onMeasurement
}), /*#__PURE__*/_react.default.createElement(_SearchWarning.default, {
isRoomEncrypted: isRoomEncrypted,
kind: _SearchWarning.WarningKind.Files
}), /*#__PURE__*/_react.default.createElement(_TimelinePanel.default, {
manageReadReceipts: false,
manageReadMarkers: false,
timelineSet: this.state.timelineSet,
showUrlPreview: false,
onPaginationRequest: this.onPaginationRequest,
resizeNotifier: this.props.resizeNotifier,
empty: emptyState,
layout: _Layout.Layout.Group
})));
} else {
return /*#__PURE__*/_react.default.createElement(_RoomContext.default.Provider, {
value: _objectSpread(_objectSpread({}, this.context), {}, {
timelineRenderingType: _RoomContext.TimelineRenderingType.File
})
}, /*#__PURE__*/_react.default.createElement(_BaseCard.default, {
className: "mx_FilePanel",
onClose: this.props.onClose,
header: (0, _languageHandler._t)("right_panel|files_button")
}, /*#__PURE__*/_react.default.createElement(_Spinner.default, null)));
}
}
}
(0, _defineProperty2.default)(FilePanel, "contextType", _RoomContext.default);
var _default = exports.default = FilePanel;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfbWF0cml4IiwiX2xvZ2dlciIsIl9maWxlcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfTWF0cml4Q2xpZW50UGVnIiwiX0V2ZW50SW5kZXhQZWciLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX1NlYXJjaFdhcm5pbmciLCJfQmFzZUNhcmQiLCJfVGltZWxpbmVQYW5lbCIsIl9TcGlubmVyIiwiX0xheW91dCIsIl9Sb29tQ29udGV4dCIsIl9NZWFzdXJlZCIsIl9FbXB0eVN0YXRlIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0Iiwib3duS2V5cyIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJvIiwiZmlsdGVyIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiRmlsZVBhbmVsIiwiUmVhY3QiLCJDb21wb25lbnQiLCJjb25zdHJ1Y3RvciIsImFyZ3MiLCJTZXQiLCJjcmVhdGVSZWYiLCJ0aW1lbGluZVNldCIsIm5hcnJvdyIsImV2Iiwicm9vbSIsInRvU3RhcnRPZlRpbWVsaW5lIiwicmVtb3ZlZCIsImRhdGEiLCJyb29tSWQiLCJwcm9wcyIsImxpdmVFdmVudCIsImlzUmVkYWN0ZWQiLCJjbGllbnQiLCJNYXRyaXhDbGllbnRQZWciLCJzYWZlR2V0IiwiZGVjcnlwdEV2ZW50SWZOZWVkZWQiLCJpc0JlaW5nRGVjcnlwdGVkIiwiZGVjcnlwdGluZ0V2ZW50cyIsImFkZCIsImdldElkIiwiYWRkRW5jcnlwdGVkTGl2ZUV2ZW50IiwiZXJyIiwiZ2V0Um9vbUlkIiwiZXZlbnRJZCIsImRlbGV0ZSIsInRpbWVsaW5lV2luZG93IiwiZGlyZWN0aW9uIiwibGltaXQiLCJldmVudEluZGV4IiwiRXZlbnRJbmRleFBlZyIsImdldFJvb20iLCJpc1Jvb21FbmNyeXB0ZWQiLCJwYWdpbmF0ZVRpbWVsaW5lV2luZG93IiwicGFnaW5hdGUiLCJzZXRTdGF0ZSIsInN0YXRlIiwidGltZWxpbmUiLCJnZXRMaXZlVGltZWxpbmUiLCJnZXRUeXBlIiwiaW5jbHVkZXMiLCJnZXRDb250ZW50IiwibXNndHlwZSIsImV2ZW50SWRUb1RpbWVsaW5lIiwiYWRkRXZlbnRUb1RpbWVsaW5lIiwiY29tcG9uZW50RGlkTW91bnQiLCJ1cGRhdGVUaW1lbGluZVNldCIsIm9uIiwiUm9vbUV2ZW50IiwiVGltZWxpbmUiLCJvblJvb21UaW1lbGluZSIsIk1hdHJpeEV2ZW50RXZlbnQiLCJEZWNyeXB0ZWQiLCJvbkV2ZW50RGVjcnlwdGVkIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJyZW1vdmVMaXN0ZW5lciIsImZldGNoRmlsZUV2ZW50c1NlcnZlciIsIkZpbHRlciIsImdldFNhZmVVc2VySWQiLCJzZXREZWZpbml0aW9uIiwiY29udGFpbnNfdXJsIiwidHlwZXMiLCJmaWx0ZXJJZCIsImdldE9yQ3JlYXRlRmlsdGVyIiwiY3JlZGVudGlhbHMiLCJ1c2VySWQiLCJnZXRPckNyZWF0ZUZpbHRlcmVkVGltZWxpbmVTZXQiLCJub1Jvb20iLCJwb3B1bGF0ZUZpbGVUaW1lbGluZSIsImVycm9yIiwibG9nZ2VyIiwicmVuZGVyIiwiaXNHdWVzdCIsImNyZWF0ZUVsZW1lbnQiLCJjbGFzc05hbWUiLCJvbkNsb3NlIiwiaGVhZGVyIiwiX3QiLCJzdWIiLCJocmVmIiwia2V5IiwiZW1wdHlTdGF0ZSIsIkljb24iLCJGaWxlc0ljb24iLCJ0aXRsZSIsImRlc2NyaXB0aW9uIiwiUHJvdmlkZXIiLCJ2YWx1ZSIsImNvbnRleHQiLCJ0aW1lbGluZVJlbmRlcmluZ1R5cGUiLCJUaW1lbGluZVJlbmRlcmluZ1R5cGUiLCJGaWxlIiwid2l0aG91dFNjcm9sbENvbnRhaW5lciIsInJlZiIsImNhcmQiLCJjdXJyZW50Iiwic2Vuc29yIiwib25NZWFzdXJlbWVudCIsImtpbmQiLCJXYXJuaW5nS2luZCIsIkZpbGVzIiwibWFuYWdlUmVhZFJlY2VpcHRzIiwibWFuYWdlUmVhZE1hcmtlcnMiLCJzaG93VXJsUHJldmlldyIsIm9uUGFnaW5hdGlvblJlcXVlc3QiLCJyZXNpemVOb3RpZmllciIsImVtcHR5IiwibGF5b3V0IiwiTGF5b3V0IiwiR3JvdXAiLCJSb29tQ29udGV4dCIsIl9kZWZhdWx0IiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3N0cnVjdHVyZXMvRmlsZVBhbmVsLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxOS0yMDIyIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxNiBPcGVuTWFya2V0IEx0ZFxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgY3JlYXRlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQge1xuICAgIEZpbHRlcixcbiAgICBFdmVudFRpbWVsaW5lU2V0LFxuICAgIElSb29tVGltZWxpbmVEYXRhLFxuICAgIERpcmVjdGlvbixcbiAgICBNYXRyaXhFdmVudCxcbiAgICBNYXRyaXhFdmVudEV2ZW50LFxuICAgIFJvb20sXG4gICAgUm9vbUV2ZW50LFxuICAgIFRpbWVsaW5lV2luZG93LFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgRmlsZXNJY29uIGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLWRlc2lnbi10b2tlbnMvYXNzZXRzL3dlYi9pY29ucy9maWxlc1wiO1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgRXZlbnRJbmRleFBlZyBmcm9tIFwiLi4vLi4vaW5kZXhpbmcvRXZlbnRJbmRleFBlZ1wiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgU2VhcmNoV2FybmluZywgeyBXYXJuaW5nS2luZCB9IGZyb20gXCIuLi92aWV3cy9lbGVtZW50cy9TZWFyY2hXYXJuaW5nXCI7XG5pbXBvcnQgQmFzZUNhcmQgZnJvbSBcIi4uL3ZpZXdzL3JpZ2h0X3BhbmVsL0Jhc2VDYXJkXCI7XG5pbXBvcnQgUmVzaXplTm90aWZpZXIgZnJvbSBcIi4uLy4uL3V0aWxzL1Jlc2l6ZU5vdGlmaWVyXCI7XG5pbXBvcnQgVGltZWxpbmVQYW5lbCBmcm9tIFwiLi9UaW1lbGluZVBhbmVsXCI7XG5pbXBvcnQgU3Bpbm5lciBmcm9tIFwiLi4vdmlld3MvZWxlbWVudHMvU3Bpbm5lclwiO1xuaW1wb3J0IHsgTGF5b3V0IH0gZnJvbSBcIi4uLy4uL3NldHRpbmdzL2VudW1zL0xheW91dFwiO1xuaW1wb3J0IFJvb21Db250ZXh0LCB7IFRpbWVsaW5lUmVuZGVyaW5nVHlwZSB9IGZyb20gXCIuLi8uLi9jb250ZXh0cy9Sb29tQ29udGV4dFwiO1xuaW1wb3J0IE1lYXN1cmVkIGZyb20gXCIuLi92aWV3cy9lbGVtZW50cy9NZWFzdXJlZFwiO1xuaW1wb3J0IEVtcHR5U3RhdGUgZnJvbSBcIi4uL3ZpZXdzL3JpZ2h0X3BhbmVsL0VtcHR5U3RhdGVcIjtcblxuaW50ZXJmYWNlIElQcm9wcyB7XG4gICAgcm9vbUlkOiBzdHJpbmc7XG4gICAgb25DbG9zZTogKCkgPT4gdm9pZDtcbiAgICByZXNpemVOb3RpZmllcjogUmVzaXplTm90aWZpZXI7XG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIHRpbWVsaW5lU2V0OiBFdmVudFRpbWVsaW5lU2V0IHwgbnVsbDtcbiAgICBuYXJyb3c6IGJvb2xlYW47XG59XG5cbi8qXG4gKiBDb21wb25lbnQgd2hpY2ggc2hvd3MgdGhlIGZpbHRlcmVkIGZpbGUgdXNpbmcgYSBUaW1lbGluZVBhbmVsXG4gKi9cbmNsYXNzIEZpbGVQYW5lbCBleHRlbmRzIFJlYWN0LkNvbXBvbmVudDxJUHJvcHMsIElTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgY29udGV4dFR5cGUgPSBSb29tQ29udGV4dDtcbiAgICBwdWJsaWMgZGVjbGFyZSBjb250ZXh0OiBSZWFjdC5Db250ZXh0VHlwZTx0eXBlb2YgUm9vbUNvbnRleHQ+O1xuXG4gICAgLy8gVGhpcyBpcyB1c2VkIHRvIHRyYWNrIGlmIGEgZGVjcnlwdGVkIGV2ZW50IHdhcyBhIGxpdmUgZXZlbnQgYW5kIHNob3VsZCBiZVxuICAgIC8vIGFkZGVkIHRvIHRoZSB0aW1lbGluZS5cbiAgICBwcml2YXRlIGRlY3J5cHRpbmdFdmVudHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBwdWJsaWMgbm9Sb29tID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBjYXJkID0gY3JlYXRlUmVmPEhUTUxEaXZFbGVtZW50PigpO1xuXG4gICAgcHVibGljIHN0YXRlOiBJU3RhdGUgPSB7XG4gICAgICAgIHRpbWVsaW5lU2V0OiBudWxsLFxuICAgICAgICBuYXJyb3c6IGZhbHNlLFxuICAgIH07XG5cbiAgICBwcml2YXRlIG9uUm9vbVRpbWVsaW5lID0gKFxuICAgICAgICBldjogTWF0cml4RXZlbnQsXG4gICAgICAgIHJvb206IFJvb20gfCB1bmRlZmluZWQsXG4gICAgICAgIHRvU3RhcnRPZlRpbWVsaW5lOiBib29sZWFuIHwgdW5kZWZpbmVkLFxuICAgICAgICByZW1vdmVkOiBib29sZWFuLFxuICAgICAgICBkYXRhOiBJUm9vbVRpbWVsaW5lRGF0YSxcbiAgICApOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHJvb20/LnJvb21JZCAhPT0gdGhpcy5wcm9wcy5yb29tSWQpIHJldHVybjtcbiAgICAgICAgaWYgKHRvU3RhcnRPZlRpbWVsaW5lIHx8ICFkYXRhIHx8ICFkYXRhLmxpdmVFdmVudCB8fCBldi5pc1JlZGFjdGVkKCkpIHJldHVybjtcblxuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICBjbGllbnQuZGVjcnlwdEV2ZW50SWZOZWVkZWQoZXYpO1xuXG4gICAgICAgIGlmIChldi5pc0JlaW5nRGVjcnlwdGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuZGVjcnlwdGluZ0V2ZW50cy5hZGQoZXYuZ2V0SWQoKSEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZGRFbmNyeXB0ZWRMaXZlRXZlbnQoZXYpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByaXZhdGUgb25FdmVudERlY3J5cHRlZCA9IChldjogTWF0cml4RXZlbnQsIGVycj86IGFueSk6IHZvaWQgPT4ge1xuICAgICAgICBpZiAoZXYuZ2V0Um9vbUlkKCkgIT09IHRoaXMucHJvcHMucm9vbUlkKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGV2ZW50SWQgPSBldi5nZXRJZCgpITtcblxuICAgICAgICBpZiAoIXRoaXMuZGVjcnlwdGluZ0V2ZW50cy5kZWxldGUoZXZlbnRJZCkpIHJldHVybjtcbiAgICAgICAgaWYgKGVycikgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuYWRkRW5jcnlwdGVkTGl2ZUV2ZW50KGV2KTtcbiAgICB9O1xuXG4gICAgcHVibGljIGFkZEVuY3J5cHRlZExpdmVFdmVudChldjogTWF0cml4RXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnRpbWVsaW5lU2V0KSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgdGltZWxpbmUgPSB0aGlzLnN0YXRlLnRpbWVsaW5lU2V0LmdldExpdmVUaW1lbGluZSgpO1xuICAgICAgICBpZiAoZXYuZ2V0VHlwZSgpICE9PSBcIm0ucm9vbS5tZXNzYWdlXCIpIHJldHVybjtcbiAgICAgICAgaWYgKCFbXCJtLmZpbGVcIiwgXCJtLmltYWdlXCIsIFwibS52aWRlb1wiLCBcIm0uYXVkaW9cIl0uaW5jbHVkZXMoZXYuZ2V0Q29udGVudCgpLm1zZ3R5cGUhKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLnRpbWVsaW5lU2V0LmV2ZW50SWRUb1RpbWVsaW5lKGV2LmdldElkKCkhKSkge1xuICAgICAgICAgICAgdGhpcy5zdGF0ZS50aW1lbGluZVNldC5hZGRFdmVudFRvVGltZWxpbmUoZXYsIHRpbWVsaW5lLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgY29tcG9uZW50RGlkTW91bnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy51cGRhdGVUaW1lbGluZVNldCh0aGlzLnByb3BzLnJvb21JZCk7XG5cbiAgICAgICAgaWYgKCFjbGllbnQuaXNSb29tRW5jcnlwdGVkKHRoaXMucHJvcHMucm9vbUlkKSkgcmV0dXJuO1xuXG4gICAgICAgIC8vIFRoZSB0aW1lbGluZVNldHMgZmlsdGVyIG1ha2VzIHN1cmUgdGhhdCBlbmNyeXB0ZWQgZXZlbnRzIHRoYXQgY29udGFpblxuICAgICAgICAvLyBVUkxzIG5ldmVyIGdldCBhZGRlZCB0byB0aGUgdGltZWxpbmUsIGV2ZW4gaWYgdGhleSBhcmUgbGl2ZSBldmVudHMuXG4gICAgICAgIC8vIFRoZXNlIG1ldGhvZHMgYXJlIGhlcmUgdG8gbWFudWFsbHkgbGlzdGVuIGZvciBzdWNoIGV2ZW50cyBhbmQgYWRkXG4gICAgICAgIC8vIHRoZW0gZGVzcGl0ZSB0aGUgZmlsdGVyJ3MgYmVzdCBlZmZvcnRzLlxuICAgICAgICAvL1xuICAgICAgICAvLyBXZSBkbyB0aGlzIG9ubHkgZm9yIGVuY3J5cHRlZCByb29tcyBhbmQgaWYgYW4gZXZlbnQgaW5kZXggZXhpc3RzLFxuICAgICAgICAvLyB0aGlzIGNvdWxkIGJlIG1hZGUgbW9yZSBnZW5lcmFsIGluIHRoZSBmdXR1cmUgb3IgdGhlIGZpbHRlciBsb2dpY1xuICAgICAgICAvLyBjb3VsZCBiZSBmaXhlZC5cbiAgICAgICAgaWYgKEV2ZW50SW5kZXhQZWcuZ2V0KCkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNsaWVudC5vbihSb29tRXZlbnQuVGltZWxpbmUsIHRoaXMub25Sb29tVGltZWxpbmUpO1xuICAgICAgICAgICAgY2xpZW50Lm9uKE1hdHJpeEV2ZW50RXZlbnQuRGVjcnlwdGVkLCB0aGlzLm9uRXZlbnREZWNyeXB0ZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG4gICAgICAgIGlmIChjbGllbnQgPT09IG51bGwpIHJldHVybjtcblxuICAgICAgICBpZiAoIWNsaWVudC5pc1Jvb21FbmNyeXB0ZWQodGhpcy5wcm9wcy5yb29tSWQpKSByZXR1cm47XG5cbiAgICAgICAgaWYgKEV2ZW50SW5kZXhQZWcuZ2V0KCkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNsaWVudC5yZW1vdmVMaXN0ZW5lcihSb29tRXZlbnQuVGltZWxpbmUsIHRoaXMub25Sb29tVGltZWxpbmUpO1xuICAgICAgICAgICAgY2xpZW50LnJlbW92ZUxpc3RlbmVyKE1hdHJpeEV2ZW50RXZlbnQuRGVjcnlwdGVkLCB0aGlzLm9uRXZlbnREZWNyeXB0ZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGZldGNoRmlsZUV2ZW50c1NlcnZlcihyb29tOiBSb29tKTogUHJvbWlzZTxFdmVudFRpbWVsaW5lU2V0PiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG5cbiAgICAgICAgY29uc3QgZmlsdGVyID0gbmV3IEZpbHRlcihjbGllbnQuZ2V0U2FmZVVzZXJJZCgpKTtcbiAgICAgICAgZmlsdGVyLnNldERlZmluaXRpb24oe1xuICAgICAgICAgICAgcm9vbToge1xuICAgICAgICAgICAgICAgIHRpbWVsaW5lOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5zX3VybDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgdHlwZXM6IFtcIm0ucm9vbS5tZXNzYWdlXCJdLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICBmaWx0ZXIuZmlsdGVySWQgPSBhd2FpdCBjbGllbnQuZ2V0T3JDcmVhdGVGaWx0ZXIoXCJGSUxURVJfRklMRVNfXCIgKyBjbGllbnQuY3JlZGVudGlhbHMudXNlcklkLCBmaWx0ZXIpO1xuICAgICAgICByZXR1cm4gcm9vbS5nZXRPckNyZWF0ZUZpbHRlcmVkVGltZWxpbmVTZXQoZmlsdGVyKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uUGFnaW5hdGlvblJlcXVlc3QgPSAoXG4gICAgICAgIHRpbWVsaW5lV2luZG93OiBUaW1lbGluZVdpbmRvdyxcbiAgICAgICAgZGlyZWN0aW9uOiBEaXJlY3Rpb24sXG4gICAgICAgIGxpbWl0OiBudW1iZXIsXG4gICAgKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG4gICAgICAgIGNvbnN0IGV2ZW50SW5kZXggPSBFdmVudEluZGV4UGVnLmdldCgpO1xuICAgICAgICBjb25zdCByb29tSWQgPSB0aGlzLnByb3BzLnJvb21JZDtcblxuICAgICAgICBjb25zdCByb29tID0gY2xpZW50LmdldFJvb20ocm9vbUlkKTtcblxuICAgICAgICAvLyBXZSBvdmVycmlkZSB0aGUgcGFnaW5hdGlvbiByZXF1ZXN0IGZvciBlbmNyeXB0ZWQgcm9vbXMgc28gdGhhdCB3ZSBhc2tcbiAgICAgICAgLy8gdGhlIGV2ZW50IGluZGV4IHRvIGZ1bGZpbGwgdGhlIHBhZ2luYXRpb24gcmVxdWVzdC4gQXNraW5nIHRoZSBzZXJ2ZXJcbiAgICAgICAgLy8gdG8gcGFnaW5hdGUgd29uJ3QgZXZlciB3b3JrIHNpbmNlIHRoZSBzZXJ2ZXIgY2FuJ3QgY29ycmVjdGx5IGZpbHRlclxuICAgICAgICAvLyBvdXQgZXZlbnRzIGNvbnRhaW5pbmcgVVJMc1xuICAgICAgICBpZiAocm9vbSAmJiBjbGllbnQuaXNSb29tRW5jcnlwdGVkKHJvb21JZCkgJiYgZXZlbnRJbmRleCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGV2ZW50SW5kZXgucGFnaW5hdGVUaW1lbGluZVdpbmRvdyhyb29tLCB0aW1lbGluZVdpbmRvdywgZGlyZWN0aW9uLCBsaW1pdCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGltZWxpbmVXaW5kb3cucGFnaW5hdGUoZGlyZWN0aW9uLCBsaW1pdCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbk1lYXN1cmVtZW50ID0gKG5hcnJvdzogYm9vbGVhbik6IHZvaWQgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgbmFycm93IH0pO1xuICAgIH07XG5cbiAgICBwdWJsaWMgYXN5bmMgdXBkYXRlVGltZWxpbmVTZXQocm9vbUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgY2xpZW50ID0gTWF0cml4Q2xpZW50UGVnLnNhZmVHZXQoKTtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaWVudC5nZXRSb29tKHJvb21JZCk7XG4gICAgICAgIGNvbnN0IGV2ZW50SW5kZXggPSBFdmVudEluZGV4UGVnLmdldCgpO1xuXG4gICAgICAgIHRoaXMubm9Sb29tID0gIXJvb207XG5cbiAgICAgICAgaWYgKHJvb20pIHtcbiAgICAgICAgICAgIGxldCB0aW1lbGluZVNldDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aW1lbGluZVNldCA9IGF3YWl0IHRoaXMuZmV0Y2hGaWxlRXZlbnRzU2VydmVyKHJvb20pO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyByb29tIGlzIGVuY3J5cHRlZCB0aGUgZmlsZSBwYW5lbCB3b24ndCBiZSBwb3B1bGF0ZWRcbiAgICAgICAgICAgICAgICAvLyBjb3JyZWN0bHkgc2luY2UgdGhlIGRlZmluZWQgZmlsdGVyIGRvZXNuJ3Qgc3VwcG9ydCBlbmNyeXB0ZWRcbiAgICAgICAgICAgICAgICAvLyBldmVudHMgYW5kIHRoZSBzZXJ2ZXIgY2FuJ3QgY2hlY2sgaWYgZW5jcnlwdGVkIGV2ZW50cyBjb250YWluXG4gICAgICAgICAgICAgICAgLy8gVVJMcy5cbiAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgd2hlcmUgb3VyIGV2ZW50IGluZGV4IGNvbWVzIGludG8gcGxhY2UsIHdlIGFzayB0aGVcbiAgICAgICAgICAgICAgICAvLyBldmVudCBpbmRleCB0byBwb3B1bGF0ZSB0aGUgdGltZWxpbmVTZXQgZm9yIHVzLiBUaGlzIGNhbGxcbiAgICAgICAgICAgICAgICAvLyB3aWxsIGFkZCAxMCBldmVudHMgdG8gdGhlIGxpdmUgdGltZWxpbmUgb2YgdGhlIHNldC4gTW9yZSBjYW5cbiAgICAgICAgICAgICAgICAvLyBiZSByZXF1ZXN0ZWQgdXNpbmcgcGFnaW5hdGlvbi5cbiAgICAgICAgICAgICAgICBpZiAoY2xpZW50LmlzUm9vbUVuY3J5cHRlZChyb29tSWQpICYmIGV2ZW50SW5kZXggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZWxpbmUgPSB0aW1lbGluZVNldC5nZXRMaXZlVGltZWxpbmUoKTtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgZXZlbnRJbmRleC5wb3B1bGF0ZUZpbGVUaW1lbGluZSh0aW1lbGluZVNldCwgdGltZWxpbmUsIHJvb20sIDEwKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgdGltZWxpbmVTZXQ6IHRpbWVsaW5lU2V0IH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGYWlsZWQgdG8gZ2V0IG9yIGNyZWF0ZSBmaWxlIHBhbmVsIGZpbHRlclwiLCBlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGYWlsZWQgdG8gYWRkIGZpbHRlcmVkIHRpbWVsaW5lU2V0IGZvciBGaWxlUGFuZWwgYXMgbm8gcm9vbSFcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGlmIChNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLmlzR3Vlc3QoKSkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8QmFzZUNhcmRcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRmlsZVBhbmVsIG14X1Jvb21WaWV3X21lc3NhZ2VMaXN0V3JhcHBlclwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xvc2U9e3RoaXMucHJvcHMub25DbG9zZX1cbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcInJpZ2h0X3BhbmVsfGZpbGVzX2J1dHRvblwiKX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfZW1wdHlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtfdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImZpbGVfcGFuZWx8Z3Vlc3Rfbm90ZVwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYTogKHN1YikgPT4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgaHJlZj1cIiMvcmVnaXN0ZXJcIiBrZXk9XCJzdWJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7c3VifVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L0Jhc2VDYXJkPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLm5vUm9vbSkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8QmFzZUNhcmRcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lPVwibXhfRmlsZVBhbmVsIG14X1Jvb21WaWV3X21lc3NhZ2VMaXN0V3JhcHBlclwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xvc2U9e3RoaXMucHJvcHMub25DbG9zZX1cbiAgICAgICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcInJpZ2h0X3BhbmVsfGZpbGVzX2J1dHRvblwiKX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwibXhfUm9vbVZpZXdfZW1wdHlcIj57X3QoXCJmaWxlX3BhbmVsfHBlZWtfbm90ZVwiKX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L0Jhc2VDYXJkPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdyYXAgYSBUaW1lbGluZVBhbmVsIHdpdGggdGhlIGp1bXAtdG8tZXZlbnQgYml0cyB0dXJuZWQgb2ZmLlxuXG4gICAgICAgIGNvbnN0IGVtcHR5U3RhdGUgPSAoXG4gICAgICAgICAgICA8RW1wdHlTdGF0ZVxuICAgICAgICAgICAgICAgIEljb249e0ZpbGVzSWNvbn1cbiAgICAgICAgICAgICAgICB0aXRsZT17X3QoXCJmaWxlX3BhbmVsfGVtcHR5X2hlYWRpbmdcIil9XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb249e190KFwiZmlsZV9wYW5lbHxlbXB0eV9kZXNjcmlwdGlvblwiKX1cbiAgICAgICAgICAgIC8+XG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgaXNSb29tRW5jcnlwdGVkID0gdGhpcy5ub1Jvb20gPyBmYWxzZSA6IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCkuaXNSb29tRW5jcnlwdGVkKHRoaXMucHJvcHMucm9vbUlkKTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0ZS50aW1lbGluZVNldCkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICA8Um9vbUNvbnRleHQuUHJvdmlkZXJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e3tcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLnRoaXMuY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVsaW5lUmVuZGVyaW5nVHlwZTogVGltZWxpbmVSZW5kZXJpbmdUeXBlLkZpbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBuYXJyb3c6IHRoaXMuc3RhdGUubmFycm93LFxuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPEJhc2VDYXJkXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9GaWxlUGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbG9zZT17dGhpcy5wcm9wcy5vbkNsb3NlfVxuICAgICAgICAgICAgICAgICAgICAgICAgd2l0aG91dFNjcm9sbENvbnRhaW5lclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVmPXt0aGlzLmNhcmR9XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXI9e190KFwicmlnaHRfcGFuZWx8ZmlsZXNfYnV0dG9uXCIpfVxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7dGhpcy5jYXJkLmN1cnJlbnQgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxNZWFzdXJlZCBzZW5zb3I9e3RoaXMuY2FyZC5jdXJyZW50fSBvbk1lYXN1cmVtZW50PXt0aGlzLm9uTWVhc3VyZW1lbnR9IC8+XG4gICAgICAgICAgICAgICAgICAgICAgICApfVxuICAgICAgICAgICAgICAgICAgICAgICAgPFNlYXJjaFdhcm5pbmcgaXNSb29tRW5jcnlwdGVkPXtpc1Jvb21FbmNyeXB0ZWR9IGtpbmQ9e1dhcm5pbmdLaW5kLkZpbGVzfSAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFRpbWVsaW5lUGFuZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYW5hZ2VSZWFkUmVjZWlwdHM9e2ZhbHNlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hbmFnZVJlYWRNYXJrZXJzPXtmYWxzZX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lbGluZVNldD17dGhpcy5zdGF0ZS50aW1lbGluZVNldH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93VXJsUHJldmlldz17ZmFsc2V9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25QYWdpbmF0aW9uUmVxdWVzdD17dGhpcy5vblBhZ2luYXRpb25SZXF1ZXN0fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2l6ZU5vdGlmaWVyPXt0aGlzLnByb3BzLnJlc2l6ZU5vdGlmaWVyfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtcHR5PXtlbXB0eVN0YXRlfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheW91dD17TGF5b3V0Lkdyb3VwfVxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9CYXNlQ2FyZD5cbiAgICAgICAgICAgICAgICA8L1Jvb21Db250ZXh0LlByb3ZpZGVyPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPFJvb21Db250ZXh0LlByb3ZpZGVyXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlPXt7XG4gICAgICAgICAgICAgICAgICAgICAgICAuLi50aGlzLmNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lbGluZVJlbmRlcmluZ1R5cGU6IFRpbWVsaW5lUmVuZGVyaW5nVHlwZS5GaWxlLFxuICAgICAgICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPEJhc2VDYXJkXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9GaWxlUGFuZWxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgb25DbG9zZT17dGhpcy5wcm9wcy5vbkNsb3NlfVxuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyPXtfdChcInJpZ2h0X3BhbmVsfGZpbGVzX2J1dHRvblwiKX1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFNwaW5uZXIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9CYXNlQ2FyZD5cbiAgICAgICAgICAgICAgICA8L1Jvb21Db250ZXh0LlByb3ZpZGVyPlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRmlsZVBhbmVsO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVNBLElBQUFBLE1BQUEsR0FBQUMsdUJBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLE9BQUEsR0FBQUQsT0FBQTtBQVdBLElBQUFFLE9BQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLE1BQUEsR0FBQUMsc0JBQUEsQ0FBQUosT0FBQTtBQUVBLElBQUFLLGdCQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxjQUFBLEdBQUFGLHNCQUFBLENBQUFKLE9BQUE7QUFDQSxJQUFBTyxnQkFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsY0FBQSxHQUFBVCx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQVMsU0FBQSxHQUFBTCxzQkFBQSxDQUFBSixPQUFBO0FBRUEsSUFBQVUsY0FBQSxHQUFBTixzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQVcsUUFBQSxHQUFBUCxzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQVksT0FBQSxHQUFBWixPQUFBO0FBQ0EsSUFBQWEsWUFBQSxHQUFBZCx1QkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQWMsU0FBQSxHQUFBVixzQkFBQSxDQUFBSixPQUFBO0FBQ0EsSUFBQWUsV0FBQSxHQUFBWCxzQkFBQSxDQUFBSixPQUFBO0FBQXlELFNBQUFnQix5QkFBQUMsQ0FBQSw2QkFBQUMsT0FBQSxtQkFBQUMsQ0FBQSxPQUFBRCxPQUFBLElBQUFFLENBQUEsT0FBQUYsT0FBQSxZQUFBRix3QkFBQSxZQUFBQSxDQUFBQyxDQUFBLFdBQUFBLENBQUEsR0FBQUcsQ0FBQSxHQUFBRCxDQUFBLEtBQUFGLENBQUE7QUFBQSxTQUFBbEIsd0JBQUFrQixDQUFBLEVBQUFFLENBQUEsU0FBQUEsQ0FBQSxJQUFBRixDQUFBLElBQUFBLENBQUEsQ0FB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