matrix-react-sdk
Version:
SDK for matrix.org using React
227 lines (219 loc) • 35.5 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MessageModerationState = void 0;
exports.canCancel = canCancel;
exports.canEditContent = canEditContent;
exports.canEditOwnEvent = canEditOwnEvent;
exports.editEvent = editEvent;
exports.fetchInitialEvent = fetchInitialEvent;
exports.findEditableEvent = findEditableEvent;
exports.getMessageModerationState = getMessageModerationState;
exports.hasThreadSummary = hasThreadSummary;
exports.highlightEvent = void 0;
exports.isContentActionable = isContentActionable;
exports.isLocationEvent = void 0;
exports.isVoiceMessage = isVoiceMessage;
var _matrix = require("matrix-js-sdk/src/matrix");
var _logger = require("matrix-js-sdk/src/logger");
var _shouldHideEvent = _interopRequireDefault(require("../shouldHideEvent"));
var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore"));
var _dispatcher = _interopRequireDefault(require("../dispatcher/dispatcher"));
var _MPollBody = require("../components/views/messages/MPollBody");
var _actions = require("../dispatcher/actions");
var _types = require("../voice-broadcast/types");
/*
Copyright 2024 New Vector Ltd.
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
/**
* Returns whether an event should allow actions like reply, reactions, edit, etc.
* which effectively checks whether it's a regular message that has been sent and that we
* can display.
*
* @param {MatrixEvent} mxEvent The event to check
* @returns {boolean} true if actionable
*/
function isContentActionable(mxEvent) {
const {
status: eventStatus
} = mxEvent;
// status is SENT before remote-echo, null after
const isSent = !eventStatus || eventStatus === _matrix.EventStatus.SENT;
if (isSent && !mxEvent.isRedacted()) {
if (mxEvent.getType() === "m.room.message") {
const content = mxEvent.getContent();
if (content.msgtype && content.msgtype !== "m.bad.encrypted" && content.hasOwnProperty("body")) {
return true;
}
} else if (mxEvent.getType() === "m.sticker" || _matrix.M_POLL_START.matches(mxEvent.getType()) || _matrix.M_POLL_END.matches(mxEvent.getType()) || _matrix.M_BEACON_INFO.matches(mxEvent.getType()) || mxEvent.getType() === _types.VoiceBroadcastInfoEventType && mxEvent.getContent()?.state === _types.VoiceBroadcastInfoState.Started) {
return true;
}
}
return false;
}
function canEditContent(matrixClient, mxEvent) {
const isCancellable = mxEvent.getType() === _matrix.EventType.RoomMessage || _matrix.M_POLL_START.matches(mxEvent.getType());
if (!isCancellable || mxEvent.status === _matrix.EventStatus.CANCELLED || mxEvent.isRedacted() || mxEvent.isRelation(_matrix.RelationType.Replace) || mxEvent.getSender() !== matrixClient.getUserId()) {
return false;
}
const {
msgtype,
body
} = mxEvent.getOriginalContent();
return _matrix.M_POLL_START.matches(mxEvent.getType()) || (msgtype === _matrix.MsgType.Text || msgtype === _matrix.MsgType.Emote) && !!body && typeof body === "string";
}
function canEditOwnEvent(matrixClient, mxEvent) {
// for now we only allow editing
// your own events. So this just call through
// In the future though, moderators will be able to
// edit other people's messages as well but we don't
// want findEditableEvent to return other people's events
// hence this method.
return canEditContent(matrixClient, mxEvent);
}
const MAX_JUMP_DISTANCE = 100;
function findEditableEvent({
matrixClient,
events,
isForward,
fromEventId
}) {
if (!events.length) return;
const maxIdx = events.length - 1;
const inc = isForward ? 1 : -1;
const beginIdx = isForward ? 0 : maxIdx;
let endIdx = isForward ? maxIdx : 0;
if (!fromEventId) {
endIdx = Math.min(Math.max(0, beginIdx + inc * MAX_JUMP_DISTANCE), maxIdx);
}
let foundFromEventId = !fromEventId;
for (let i = beginIdx; i !== endIdx + inc; i += inc) {
const e = events[i];
// find start event first
if (!foundFromEventId && e.getId() === fromEventId) {
foundFromEventId = true;
// don't look further than MAX_JUMP_DISTANCE events from `fromEventId`
// to not iterate potentially 1000nds of events on key up/down
endIdx = Math.min(Math.max(0, i + inc * MAX_JUMP_DISTANCE), maxIdx);
} else if (foundFromEventId && !(0, _shouldHideEvent.default)(e) && canEditOwnEvent(matrixClient, e)) {
// otherwise look for editable event
return e;
}
}
}
/**
* How we should render a message depending on its moderation state.
*/
let MessageModerationState = exports.MessageModerationState = /*#__PURE__*/function (MessageModerationState) {
MessageModerationState["VISIBLE_FOR_ALL"] = "VISIBLE_FOR_ALL";
MessageModerationState["HIDDEN_TO_CURRENT_USER"] = "HIDDEN_TO_CURRENT_USER";
MessageModerationState["SEE_THROUGH_FOR_CURRENT_USER"] = "SEE_THROUGH_FOR_CURRENT_USER";
return MessageModerationState;
}({}); // This is lazily initialized and cached since getMessageModerationState needs it,
// and is called on timeline rendering hot-paths
let msc3531Enabled = null;
const getMsc3531Enabled = () => {
if (msc3531Enabled === null) {
msc3531Enabled = _SettingsStore.default.getValue("feature_msc3531_hide_messages_pending_moderation");
}
return msc3531Enabled;
};
/**
* Determine whether a message should be displayed as hidden pending moderation.
*
* If MSC3531 is deactivated in settings, all messages are considered visible
* to all.
*/
function getMessageModerationState(mxEvent, client) {
if (!getMsc3531Enabled()) {
return MessageModerationState.VISIBLE_FOR_ALL;
}
const visibility = mxEvent.messageVisibility();
if (visibility.visible) {
return MessageModerationState.VISIBLE_FOR_ALL;
}
// At this point, we know that the message is marked as hidden
// pending moderation. However, if we're the author or a moderator,
// we still need to display it.
if (mxEvent.sender?.userId === client.getUserId()) {
// We're the author, show the message.
return MessageModerationState.SEE_THROUGH_FOR_CURRENT_USER;
}
const room = client.getRoom(mxEvent.getRoomId());
if (_matrix.EVENT_VISIBILITY_CHANGE_TYPE.name && room?.currentState.maySendStateEvent(_matrix.EVENT_VISIBILITY_CHANGE_TYPE.name, client.getUserId())) {
// We're a moderator (as indicated by prefixed event name), show the message.
return MessageModerationState.SEE_THROUGH_FOR_CURRENT_USER;
}
if (_matrix.EVENT_VISIBILITY_CHANGE_TYPE.altName && room?.currentState.maySendStateEvent(_matrix.EVENT_VISIBILITY_CHANGE_TYPE.altName, client.getUserId())) {
// We're a moderator (as indicated by unprefixed event name), show the message.
return MessageModerationState.SEE_THROUGH_FOR_CURRENT_USER;
}
// For everybody else, hide the message.
return MessageModerationState.HIDDEN_TO_CURRENT_USER;
}
function isVoiceMessage(mxEvent) {
const content = mxEvent.getContent();
// MSC2516 is a legacy identifier. See https://github.com/matrix-org/matrix-doc/pull/3245
return !!content["org.matrix.msc2516.voice"] || !!content["org.matrix.msc3245.voice"];
}
async function fetchInitialEvent(client, roomId, eventId) {
let initialEvent;
try {
const eventData = await client.fetchRoomEvent(roomId, eventId);
initialEvent = new _matrix.MatrixEvent(eventData);
} catch (e) {
_logger.logger.warn("Could not find initial event: " + eventId);
initialEvent = null;
}
if (client.supportsThreads() && initialEvent?.isRelation(_matrix.THREAD_RELATION_TYPE.name) && !initialEvent.getThread()) {
const threadId = initialEvent.threadRootId;
const room = client.getRoom(roomId);
const mapper = client.getEventMapper();
const rootEvent = room?.findEventById(threadId) ?? mapper(await client.fetchRoomEvent(roomId, threadId));
try {
room?.createThread(threadId, rootEvent, [initialEvent], true);
} catch (e) {
_logger.logger.warn("Could not find root event: " + threadId);
}
}
return initialEvent;
}
function editEvent(matrixClient, mxEvent, timelineRenderingType, getRelationsForEvent) {
if (!canEditContent(matrixClient, mxEvent)) return;
if (_matrix.M_POLL_START.matches(mxEvent.getType())) {
(0, _MPollBody.launchPollEditor)(mxEvent, getRelationsForEvent);
} else {
_dispatcher.default.dispatch({
action: _actions.Action.EditEvent,
event: mxEvent,
timelineRenderingType: timelineRenderingType
});
}
}
function canCancel(status) {
return status === _matrix.EventStatus.QUEUED || status === _matrix.EventStatus.NOT_SENT || status === _matrix.EventStatus.ENCRYPTING;
}
const isLocationEvent = event => {
const eventType = event.getType();
return _matrix.M_LOCATION.matches(eventType) || eventType === _matrix.EventType.RoomMessage && _matrix.M_LOCATION.matches(event.getContent().msgtype);
};
exports.isLocationEvent = isLocationEvent;
function hasThreadSummary(event) {
return event.isThreadRoot && !!event.getThread()?.length && !!event.getThread().replyToEvent;
}
const highlightEvent = (roomId, eventId) => {
_dispatcher.default.dispatch({
action: _actions.Action.ViewRoom,
event_id: eventId,
highlighted: true,
room_id: roomId,
metricsTrigger: undefined // room doesn't change
});
};
exports.highlightEvent = highlightEvent;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfc2hvdWxkSGlkZUV2ZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9TZXR0aW5nc1N0b3JlIiwiX2Rpc3BhdGNoZXIiLCJfTVBvbGxCb2R5IiwiX2FjdGlvbnMiLCJfdHlwZXMiLCJpc0NvbnRlbnRBY3Rpb25hYmxlIiwibXhFdmVudCIsInN0YXR1cyIsImV2ZW50U3RhdHVzIiwiaXNTZW50IiwiRXZlbnRTdGF0dXMiLCJTRU5UIiwiaXNSZWRhY3RlZCIsImdldFR5cGUiLCJjb250ZW50IiwiZ2V0Q29udGVudCIsIm1zZ3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsIk1fUE9MTF9TVEFSVCIsIm1hdGNoZXMiLCJNX1BPTExfRU5EIiwiTV9CRUFDT05fSU5GTyIsIlZvaWNlQnJvYWRjYXN0SW5mb0V2ZW50VHlwZSIsInN0YXRlIiwiVm9pY2VCcm9hZGNhc3RJbmZvU3RhdGUiLCJTdGFydGVkIiwiY2FuRWRpdENvbnRlbnQiLCJtYXRyaXhDbGllbnQiLCJpc0NhbmNlbGxhYmxlIiwiRXZlbnRUeXBlIiwiUm9vbU1lc3NhZ2UiLCJDQU5DRUxMRUQiLCJpc1JlbGF0aW9uIiwiUmVsYXRpb25UeXBlIiwiUmVwbGFjZSIsImdldFNlbmRlciIsImdldFVzZXJJZCIsImJvZHkiLCJnZXRPcmlnaW5hbENvbnRlbnQiLCJNc2dUeXBlIiwiVGV4dCIsIkVtb3RlIiwiY2FuRWRpdE93bkV2ZW50IiwiTUFYX0pVTVBfRElTVEFOQ0UiLCJmaW5kRWRpdGFibGVFdmVudCIsImV2ZW50cyIsImlzRm9yd2FyZCIsImZyb21FdmVudElkIiwibGVuZ3RoIiwibWF4SWR4IiwiaW5jIiwiYmVnaW5JZHgiLCJlbmRJZHgiLCJNYXRoIiwibWluIiwibWF4IiwiZm91bmRGcm9tRXZlbnRJZCIsImkiLCJlIiwiZ2V0SWQiLCJzaG91bGRIaWRlRXZlbnQiLCJNZXNzYWdlTW9kZXJhdGlvblN0YXRlIiwiZXhwb3J0cyIsIm1zYzM1MzFFbmFibGVkIiwiZ2V0TXNjMzUzMUVuYWJsZWQiLCJTZXR0aW5nc1N0b3JlIiwiZ2V0VmFsdWUiLCJnZXRNZXNzYWdlTW9kZXJhdGlvblN0YXRlIiwiY2xpZW50IiwiVklTSUJMRV9GT1JfQUxMIiwidmlzaWJpbGl0eSIsIm1lc3NhZ2VWaXNpYmlsaXR5IiwidmlzaWJsZSIsInNlbmRlciIsInVzZXJJZCIsIlNFRV9USFJPVUdIX0ZPUl9DVVJSRU5UX1VTRVIiLCJyb29tIiwiZ2V0Um9vbSIsImdldFJvb21JZCIsIkVWRU5UX1ZJU0lCSUxJVFlfQ0hBTkdFX1RZUEUiLCJuYW1lIiwiY3VycmVudFN0YXRlIiwibWF5U2VuZFN0YXRlRXZlbnQiLCJhbHROYW1lIiwiSElEREVOX1RPX0NVUlJFTlRfVVNFUiIsImlzVm9pY2VNZXNzYWdlIiwiZmV0Y2hJbml0aWFsRXZlbnQiLCJyb29tSWQiLCJldmVudElkIiwiaW5pdGlhbEV2ZW50IiwiZXZlbnREYXRhIiwiZmV0Y2hSb29tRXZlbnQiLCJNYXRyaXhFdmVudCIsImxvZ2dlciIsIndhcm4iLCJzdXBwb3J0c1RocmVhZHMiLCJUSFJFQURfUkVMQVRJT05fVFlQRSIsImdldFRocmVhZCIsInRocmVhZElkIiwidGhyZWFkUm9vdElkIiwibWFwcGVyIiwiZ2V0RXZlbnRNYXBwZXIiLCJyb290RXZlbnQiLCJmaW5kRXZlbnRCeUlkIiwiY3JlYXRlVGhyZWFkIiwiZWRpdEV2ZW50IiwidGltZWxpbmVSZW5kZXJpbmdUeXBlIiwiZ2V0UmVsYXRpb25zRm9yRXZlbnQiLCJsYXVuY2hQb2xsRWRpdG9yIiwiZGVmYXVsdERpc3BhdGNoZXIiLCJkaXNwYXRjaCIsImFjdGlvbiIsIkFjdGlvbiIsIkVkaXRFdmVudCIsImV2ZW50IiwiY2FuQ2FuY2VsIiwiUVVFVUVEIiwiTk9UX1NFTlQiLCJFTkNSWVBUSU5HIiwiaXNMb2NhdGlvbkV2ZW50IiwiZXZlbnRUeXBlIiwiTV9MT0NBVElPTiIsImhhc1RocmVhZFN1bW1hcnkiLCJpc1RocmVhZFJvb3QiLCJyZXBseVRvRXZlbnQiLCJoaWdobGlnaHRFdmVudCIsIlZpZXdSb29tIiwiZXZlbnRfaWQiLCJoaWdobGlnaHRlZCIsInJvb21faWQiLCJtZXRyaWNzVHJpZ2dlciIsInVuZGVmaW5lZCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9FdmVudFV0aWxzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAyNCBOZXcgVmVjdG9yIEx0ZC5cbkNvcHlyaWdodCAyMDE5LTIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHtcbiAgICBFdmVudFN0YXR1cyxcbiAgICBNYXRyaXhFdmVudCxcbiAgICBFdmVudFR5cGUsXG4gICAgRVZFTlRfVklTSUJJTElUWV9DSEFOR0VfVFlQRSxcbiAgICBNc2dUeXBlLFxuICAgIFJlbGF0aW9uVHlwZSxcbiAgICBNYXRyaXhDbGllbnQsXG4gICAgVEhSRUFEX1JFTEFUSU9OX1RZUEUsXG4gICAgTV9QT0xMX0VORCxcbiAgICBNX1BPTExfU1RBUlQsXG4gICAgTV9MT0NBVElPTixcbiAgICBNX0JFQUNPTl9JTkZPLFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5cbmltcG9ydCBzaG91bGRIaWRlRXZlbnQgZnJvbSBcIi4uL3Nob3VsZEhpZGVFdmVudFwiO1xuaW1wb3J0IHsgR2V0UmVsYXRpb25zRm9yRXZlbnQgfSBmcm9tIFwiLi4vY29tcG9uZW50cy92aWV3cy9yb29tcy9FdmVudFRpbGVcIjtcbmltcG9ydCBTZXR0aW5nc1N0b3JlIGZyb20gXCIuLi9zZXR0aW5ncy9TZXR0aW5nc1N0b3JlXCI7XG5pbXBvcnQgZGVmYXVsdERpc3BhdGNoZXIgZnJvbSBcIi4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgVGltZWxpbmVSZW5kZXJpbmdUeXBlIH0gZnJvbSBcIi4uL2NvbnRleHRzL1Jvb21Db250ZXh0XCI7XG5pbXBvcnQgeyBsYXVuY2hQb2xsRWRpdG9yIH0gZnJvbSBcIi4uL2NvbXBvbmVudHMvdmlld3MvbWVzc2FnZXMvTVBvbGxCb2R5XCI7XG5pbXBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9hY3Rpb25zXCI7XG5pbXBvcnQgeyBWaWV3Um9vbVBheWxvYWQgfSBmcm9tIFwiLi4vZGlzcGF0Y2hlci9wYXlsb2Fkcy9WaWV3Um9vbVBheWxvYWRcIjtcbmltcG9ydCB7IFZvaWNlQnJvYWRjYXN0SW5mb0V2ZW50VHlwZSwgVm9pY2VCcm9hZGNhc3RJbmZvU3RhdGUgfSBmcm9tIFwiLi4vdm9pY2UtYnJvYWRjYXN0L3R5cGVzXCI7XG5cbi8qKlxuICogUmV0dXJucyB3aGV0aGVyIGFuIGV2ZW50IHNob3VsZCBhbGxvdyBhY3Rpb25zIGxpa2UgcmVwbHksIHJlYWN0aW9ucywgZWRpdCwgZXRjLlxuICogd2hpY2ggZWZmZWN0aXZlbHkgY2hlY2tzIHdoZXRoZXIgaXQncyBhIHJlZ3VsYXIgbWVzc2FnZSB0aGF0IGhhcyBiZWVuIHNlbnQgYW5kIHRoYXQgd2VcbiAqIGNhbiBkaXNwbGF5LlxuICpcbiAqIEBwYXJhbSB7TWF0cml4RXZlbnR9IG14RXZlbnQgVGhlIGV2ZW50IHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBhY3Rpb25hYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbnRlbnRBY3Rpb25hYmxlKG14RXZlbnQ6IE1hdHJpeEV2ZW50KTogYm9vbGVhbiB7XG4gICAgY29uc3QgeyBzdGF0dXM6IGV2ZW50U3RhdHVzIH0gPSBteEV2ZW50O1xuXG4gICAgLy8gc3RhdHVzIGlzIFNFTlQgYmVmb3JlIHJlbW90ZS1lY2hvLCBudWxsIGFmdGVyXG4gICAgY29uc3QgaXNTZW50ID0gIWV2ZW50U3RhdHVzIHx8IGV2ZW50U3RhdHVzID09PSBFdmVudFN0YXR1cy5TRU5UO1xuXG4gICAgaWYgKGlzU2VudCAmJiAhbXhFdmVudC5pc1JlZGFjdGVkKCkpIHtcbiAgICAgICAgaWYgKG14RXZlbnQuZ2V0VHlwZSgpID09PSBcIm0ucm9vbS5tZXNzYWdlXCIpIHtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBteEV2ZW50LmdldENvbnRlbnQoKTtcbiAgICAgICAgICAgIGlmIChjb250ZW50Lm1zZ3R5cGUgJiYgY29udGVudC5tc2d0eXBlICE9PSBcIm0uYmFkLmVuY3J5cHRlZFwiICYmIGNvbnRlbnQuaGFzT3duUHJvcGVydHkoXCJib2R5XCIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICBteEV2ZW50LmdldFR5cGUoKSA9PT0gXCJtLnN0aWNrZXJcIiB8fFxuICAgICAgICAgICAgTV9QT0xMX1NUQVJULm1hdGNoZXMobXhFdmVudC5nZXRUeXBlKCkpIHx8XG4gICAgICAgICAgICBNX1BPTExfRU5ELm1hdGNoZXMobXhFdmVudC5nZXRUeXBlKCkpIHx8XG4gICAgICAgICAgICBNX0JFQUNPTl9JTkZPLm1hdGNoZXMobXhFdmVudC5nZXRUeXBlKCkpIHx8XG4gICAgICAgICAgICAobXhFdmVudC5nZXRUeXBlKCkgPT09IFZvaWNlQnJvYWRjYXN0SW5mb0V2ZW50VHlwZSAmJlxuICAgICAgICAgICAgICAgIG14RXZlbnQuZ2V0Q29udGVudCgpPy5zdGF0ZSA9PT0gVm9pY2VCcm9hZGNhc3RJbmZvU3RhdGUuU3RhcnRlZClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbkVkaXRDb250ZW50KG1hdHJpeENsaWVudDogTWF0cml4Q2xpZW50LCBteEV2ZW50OiBNYXRyaXhFdmVudCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGlzQ2FuY2VsbGFibGUgPSBteEV2ZW50LmdldFR5cGUoKSA9PT0gRXZlbnRUeXBlLlJvb21NZXNzYWdlIHx8IE1fUE9MTF9TVEFSVC5tYXRjaGVzKG14RXZlbnQuZ2V0VHlwZSgpKTtcblxuICAgIGlmIChcbiAgICAgICAgIWlzQ2FuY2VsbGFibGUgfHxcbiAgICAgICAgbXhFdmVudC5zdGF0dXMgPT09IEV2ZW50U3RhdHVzLkNBTkNFTExFRCB8fFxuICAgICAgICBteEV2ZW50LmlzUmVkYWN0ZWQoKSB8fFxuICAgICAgICBteEV2ZW50LmlzUmVsYXRpb24oUmVsYXRpb25UeXBlLlJlcGxhY2UpIHx8XG4gICAgICAgIG14RXZlbnQuZ2V0U2VuZGVyKCkgIT09IG1hdHJpeENsaWVudC5nZXRVc2VySWQoKVxuICAgICkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgeyBtc2d0eXBlLCBib2R5IH0gPSBteEV2ZW50LmdldE9yaWdpbmFsQ29udGVudCgpO1xuICAgIHJldHVybiAoXG4gICAgICAgIE1fUE9MTF9TVEFSVC5tYXRjaGVzKG14RXZlbnQuZ2V0VHlwZSgpKSB8fFxuICAgICAgICAoKG1zZ3R5cGUgPT09IE1zZ1R5cGUuVGV4dCB8fCBtc2d0eXBlID09PSBNc2dUeXBlLkVtb3RlKSAmJiAhIWJvZHkgJiYgdHlwZW9mIGJvZHkgPT09IFwic3RyaW5nXCIpXG4gICAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbkVkaXRPd25FdmVudChtYXRyaXhDbGllbnQ6IE1hdHJpeENsaWVudCwgbXhFdmVudDogTWF0cml4RXZlbnQpOiBib29sZWFuIHtcbiAgICAvLyBmb3Igbm93IHdlIG9ubHkgYWxsb3cgZWRpdGluZ1xuICAgIC8vIHlvdXIgb3duIGV2ZW50cy4gU28gdGhpcyBqdXN0IGNhbGwgdGhyb3VnaFxuICAgIC8vIEluIHRoZSBmdXR1cmUgdGhvdWdoLCBtb2RlcmF0b3JzIHdpbGwgYmUgYWJsZSB0b1xuICAgIC8vIGVkaXQgb3RoZXIgcGVvcGxlJ3MgbWVzc2FnZXMgYXMgd2VsbCBidXQgd2UgZG9uJ3RcbiAgICAvLyB3YW50IGZpbmRFZGl0YWJsZUV2ZW50IHRvIHJldHVybiBvdGhlciBwZW9wbGUncyBldmVudHNcbiAgICAvLyBoZW5jZSB0aGlzIG1ldGhvZC5cbiAgICByZXR1cm4gY2FuRWRpdENvbnRlbnQobWF0cml4Q2xpZW50LCBteEV2ZW50KTtcbn1cblxuY29uc3QgTUFYX0pVTVBfRElTVEFOQ0UgPSAxMDA7XG5leHBvcnQgZnVuY3Rpb24gZmluZEVkaXRhYmxlRXZlbnQoe1xuICAgIG1hdHJpeENsaWVudCxcbiAgICBldmVudHMsXG4gICAgaXNGb3J3YXJkLFxuICAgIGZyb21FdmVudElkLFxufToge1xuICAgIG1hdHJpeENsaWVudDogTWF0cml4Q2xpZW50O1xuICAgIGV2ZW50czogTWF0cml4RXZlbnRbXTtcbiAgICBpc0ZvcndhcmQ6IGJvb2xlYW47XG4gICAgZnJvbUV2ZW50SWQ/OiBzdHJpbmc7XG59KTogTWF0cml4RXZlbnQgfCB1bmRlZmluZWQge1xuICAgIGlmICghZXZlbnRzLmxlbmd0aCkgcmV0dXJuO1xuICAgIGNvbnN0IG1heElkeCA9IGV2ZW50cy5sZW5ndGggLSAxO1xuICAgIGNvbnN0IGluYyA9IGlzRm9yd2FyZCA/IDEgOiAtMTtcbiAgICBjb25zdCBiZWdpbklkeCA9IGlzRm9yd2FyZCA/IDAgOiBtYXhJZHg7XG4gICAgbGV0IGVuZElkeCA9IGlzRm9yd2FyZCA/IG1heElkeCA6IDA7XG4gICAgaWYgKCFmcm9tRXZlbnRJZCkge1xuICAgICAgICBlbmRJZHggPSBNYXRoLm1pbihNYXRoLm1heCgwLCBiZWdpbklkeCArIGluYyAqIE1BWF9KVU1QX0RJU1RBTkNFKSwgbWF4SWR4KTtcbiAgICB9XG4gICAgbGV0IGZvdW5kRnJvbUV2ZW50SWQgPSAhZnJvbUV2ZW50SWQ7XG4gICAgZm9yIChsZXQgaSA9IGJlZ2luSWR4OyBpICE9PSBlbmRJZHggKyBpbmM7IGkgKz0gaW5jKSB7XG4gICAgICAgIGNvbnN0IGUgPSBldmVudHNbaV07XG4gICAgICAgIC8vIGZpbmQgc3RhcnQgZXZlbnQgZmlyc3RcbiAgICAgICAgaWYgKCFmb3VuZEZyb21FdmVudElkICYmIGUuZ2V0SWQoKSA9PT0gZnJvbUV2ZW50SWQpIHtcbiAgICAgICAgICAgIGZvdW5kRnJvbUV2ZW50SWQgPSB0cnVlO1xuICAgICAgICAgICAgLy8gZG9uJ3QgbG9vayBmdXJ0aGVyIHRoYW4gTUFYX0pVTVBfRElTVEFOQ0UgZXZlbnRzIGZyb20gYGZyb21FdmVudElkYFxuICAgICAgICAgICAgLy8gdG8gbm90IGl0ZXJhdGUgcG90ZW50aWFsbHkgMTAwMG5kcyBvZiBldmVudHMgb24ga2V5IHVwL2Rvd25cbiAgICAgICAgICAgIGVuZElkeCA9IE1hdGgubWluKE1hdGgubWF4KDAsIGkgKyBpbmMgKiBNQVhfSlVNUF9ESVNUQU5DRSksIG1heElkeCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZm91bmRGcm9tRXZlbnRJZCAmJiAhc2hvdWxkSGlkZUV2ZW50KGUpICYmIGNhbkVkaXRPd25FdmVudChtYXRyaXhDbGllbnQsIGUpKSB7XG4gICAgICAgICAgICAvLyBvdGhlcndpc2UgbG9vayBmb3IgZWRpdGFibGUgZXZlbnRcbiAgICAgICAgICAgIHJldHVybiBlO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIEhvdyB3ZSBzaG91bGQgcmVuZGVyIGEgbWVzc2FnZSBkZXBlbmRpbmcgb24gaXRzIG1vZGVyYXRpb24gc3RhdGUuXG4gKi9cbmV4cG9ydCBlbnVtIE1lc3NhZ2VNb2RlcmF0aW9uU3RhdGUge1xuICAgIC8qKlxuICAgICAqIFRoZSBtZXNzYWdlIGlzIHZpc2libGUgdG8gYWxsLlxuICAgICAqL1xuICAgIFZJU0lCTEVfRk9SX0FMTCA9IFwiVklTSUJMRV9GT1JfQUxMXCIsXG4gICAgLyoqXG4gICAgICogVGhlIG1lc3NhZ2UgaXMgaGlkZGVuIHBlbmRpbmcgbW9kZXJhdGlvbiBhbmQgd2UncmUgbm90IGEgdXNlciB3aG8gc2hvdWxkXG4gICAgICogc2VlIGl0IG5ldmVydGhlbGVzcy5cbiAgICAgKi9cbiAgICBISURERU5fVE9fQ1VSUkVOVF9VU0VSID0gXCJISURERU5fVE9fQ1VSUkVOVF9VU0VSXCIsXG4gICAgLyoqXG4gICAgICogVGhlIG1lc3NhZ2UgaXMgaGlkZGVuIHBlbmRpbmcgbW9kZXJhdGlvbiBhbmQgd2UncmUgZWl0aGVyIHRoZSBhdXRob3Igb2ZcbiAgICAgKiB0aGUgbWVzc2FnZSBvciBhIG1vZGVyYXRvci4gSW4gZWl0aGVyIGNhc2UsIHdlIG5lZWQgdG8gc2VlIHRoZSBtZXNzYWdlXG4gICAgICogd2l0aCBhIG1hcmtlci5cbiAgICAgKi9cbiAgICBTRUVfVEhST1VHSF9GT1JfQ1VSUkVOVF9VU0VSID0gXCJTRUVfVEhST1VHSF9GT1JfQ1VSUkVOVF9VU0VSXCIsXG59XG5cbi8vIFRoaXMgaXMgbGF6aWx5IGluaXRpYWxpemVkIGFuZCBjYWNoZWQgc2luY2UgZ2V0TWVzc2FnZU1vZGVyYXRpb25TdGF0ZSBuZWVkcyBpdCxcbi8vIGFuZCBpcyBjYWxsZWQgb24gdGltZWxpbmUgcmVuZGVyaW5nIGhvdC1wYXRoc1xubGV0IG1zYzM1MzFFbmFibGVkOiBib29sZWFuIHwgbnVsbCA9IG51bGw7XG5jb25zdCBnZXRNc2MzNTMxRW5hYmxlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgICBpZiAobXNjMzUzMUVuYWJsZWQgPT09IG51bGwpIHtcbiAgICAgICAgbXNjMzUzMUVuYWJsZWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiZmVhdHVyZV9tc2MzNTMxX2hpZGVfbWVzc2FnZXNfcGVuZGluZ19tb2RlcmF0aW9uXCIpO1xuICAgIH1cbiAgICByZXR1cm4gbXNjMzUzMUVuYWJsZWQhO1xufTtcblxuLyoqXG4gKiBEZXRlcm1pbmUgd2hldGhlciBhIG1lc3NhZ2Ugc2hvdWxkIGJlIGRpc3BsYXllZCBhcyBoaWRkZW4gcGVuZGluZyBtb2RlcmF0aW9uLlxuICpcbiAqIElmIE1TQzM1MzEgaXMgZGVhY3RpdmF0ZWQgaW4gc2V0dGluZ3MsIGFsbCBtZXNzYWdlcyBhcmUgY29uc2lkZXJlZCB2aXNpYmxlXG4gKiB0byBhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNZXNzYWdlTW9kZXJhdGlvblN0YXRlKG14RXZlbnQ6IE1hdHJpeEV2ZW50LCBjbGllbnQ6IE1hdHJpeENsaWVudCk6IE1lc3NhZ2VNb2RlcmF0aW9uU3RhdGUge1xuICAgIGlmICghZ2V0TXNjMzUzMUVuYWJsZWQoKSkge1xuICAgICAgICByZXR1cm4gTWVzc2FnZU1vZGVyYXRpb25TdGF0ZS5WSVNJQkxFX0ZPUl9BTEw7XG4gICAgfVxuICAgIGNvbnN0IHZpc2liaWxpdHkgPSBteEV2ZW50Lm1lc3NhZ2VWaXNpYmlsaXR5KCk7XG4gICAgaWYgKHZpc2liaWxpdHkudmlzaWJsZSkge1xuICAgICAgICByZXR1cm4gTWVzc2FnZU1vZGVyYXRpb25TdGF0ZS5WSVNJQkxFX0ZPUl9BTEw7XG4gICAgfVxuXG4gICAgLy8gQXQgdGhpcyBwb2ludCwgd2Uga25vdyB0aGF0IHRoZSBtZXNzYWdlIGlzIG1hcmtlZCBhcyBoaWRkZW5cbiAgICAvLyBwZW5kaW5nIG1vZGVyYXRpb24uIEhvd2V2ZXIsIGlmIHdlJ3JlIHRoZSBhdXRob3Igb3IgYSBtb2RlcmF0b3IsXG4gICAgLy8gd2Ugc3RpbGwgbmVlZCB0byBkaXNwbGF5IGl0LlxuXG4gICAgaWYgKG14RXZlbnQuc2VuZGVyPy51c2VySWQgPT09IGNsaWVudC5nZXRVc2VySWQoKSkge1xuICAgICAgICAvLyBXZSdyZSB0aGUgYXV0aG9yLCBzaG93IHRoZSBtZXNzYWdlLlxuICAgICAgICByZXR1cm4gTWVzc2FnZU1vZGVyYXRpb25TdGF0ZS5TRUVfVEhST1VHSF9GT1JfQ1VSUkVOVF9VU0VSO1xuICAgIH1cblxuICAgIGNvbnN0IHJvb20gPSBjbGllbnQuZ2V0Um9vbShteEV2ZW50LmdldFJvb21JZCgpKTtcbiAgICBpZiAoXG4gICAgICAgIEVWRU5UX1ZJU0lCSUxJVFlfQ0hBTkdFX1RZUEUubmFtZSAmJlxuICAgICAgICByb29tPy5jdXJyZW50U3RhdGUubWF5U2VuZFN0YXRlRXZlbnQoRVZFTlRfVklTSUJJTElUWV9DSEFOR0VfVFlQRS5uYW1lLCBjbGllbnQuZ2V0VXNlcklkKCkhKVxuICAgICkge1xuICAgICAgICAvLyBXZSdyZSBhIG1vZGVyYXRvciAoYXMgaW5kaWNhdGVkIGJ5IHByZWZpeGVkIGV2ZW50IG5hbWUpLCBzaG93IHRoZSBtZXNzYWdlLlxuICAgICAgICByZXR1cm4gTWVzc2FnZU1vZGVyYXRpb25TdGF0ZS5TRUVfVEhST1VHSF9GT1JfQ1VSUkVOVF9VU0VSO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICAgIEVWRU5UX1ZJU0lCSUxJVFlfQ0hBTkdFX1RZUEUuYWx0TmFtZSAmJlxuICAgICAgICByb29tPy5jdXJyZW50U3RhdGUubWF5U2VuZFN0YXRlRXZlbnQoRVZFTlRfVklTSUJJTElUWV9DSEFOR0VfVFlQRS5hbHROYW1lLCBjbGllbnQuZ2V0VXNlcklkKCkhKVxuICAgICkge1xuICAgICAgICAvLyBXZSdyZSBhIG1vZGVyYXRvciAoYXMgaW5kaWNhdGVkIGJ5IHVucHJlZml4ZWQgZXZlbnQgbmFtZSksIHNob3cgdGhlIG1lc3NhZ2UuXG4gICAgICAgIHJldHVybiBNZXNzYWdlTW9kZXJhdGlvblN0YXRlLlNFRV9USFJPVUdIX0ZPUl9DVVJSRU5UX1VTRVI7XG4gICAgfVxuICAgIC8vIEZvciBldmVyeWJvZHkgZWxzZSwgaGlkZSB0aGUgbWVzc2FnZS5cbiAgICByZXR1cm4gTWVzc2FnZU1vZGVyYXRpb25TdGF0ZS5ISURERU5fVE9fQ1VSUkVOVF9VU0VSO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNWb2ljZU1lc3NhZ2UobXhFdmVudDogTWF0cml4RXZlbnQpOiBib29sZWFuIHtcbiAgICBjb25zdCBjb250ZW50ID0gbXhFdmVudC5nZXRDb250ZW50KCk7XG4gICAgLy8gTVNDMjUxNiBpcyBhIGxlZ2FjeSBpZGVudGlmaWVyLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL21hdHJpeC1vcmcvbWF0cml4LWRvYy9wdWxsLzMyNDVcbiAgICByZXR1cm4gISFjb250ZW50W1wib3JnLm1hdHJpeC5tc2MyNTE2LnZvaWNlXCJdIHx8ICEhY29udGVudFtcIm9yZy5tYXRyaXgubXNjMzI0NS52b2ljZVwiXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZldGNoSW5pdGlhbEV2ZW50KFxuICAgIGNsaWVudDogTWF0cml4Q2xpZW50LFxuICAgIHJvb21JZDogc3RyaW5nLFxuICAgIGV2ZW50SWQ6IHN0cmluZyxcbik6IFByb21pc2U8TWF0cml4RXZlbnQgfCBudWxsPiB7XG4gICAgbGV0IGluaXRpYWxFdmVudDogTWF0cml4RXZlbnQgfCBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZXZlbnREYXRhID0gYXdhaXQgY2xpZW50LmZldGNoUm9vbUV2ZW50KHJvb21JZCwgZXZlbnRJZCk7XG4gICAgICAgIGluaXRpYWxFdmVudCA9IG5ldyBNYXRyaXhFdmVudChldmVudERhdGEpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXCJDb3VsZCBub3QgZmluZCBpbml0aWFsIGV2ZW50OiBcIiArIGV2ZW50SWQpO1xuICAgICAgICBpbml0aWFsRXZlbnQgPSBudWxsO1xuICAgIH1cblxuICAgIGlmIChjbGllbnQuc3VwcG9ydHNUaHJlYWRzKCkgJiYgaW5pdGlhbEV2ZW50Py5pc1JlbGF0aW9uKFRIUkVBRF9SRUxBVElPTl9UWVBFLm5hbWUpICYmICFpbml0aWFsRXZlbnQuZ2V0VGhyZWFkKCkpIHtcbiAgICAgICAgY29uc3QgdGhyZWFkSWQgPSBpbml0aWFsRXZlbnQudGhyZWFkUm9vdElkITtcbiAgICAgICAgY29uc3Qgcm9vbSA9IGNsaWVudC5nZXRSb29tKHJvb21JZCk7XG4gICAgICAgIGNvbnN0IG1hcHBlciA9IGNsaWVudC5nZXRFdmVudE1hcHBlcigpO1xuICAgICAgICBjb25zdCByb290RXZlbnQgPSByb29tPy5maW5kRXZlbnRCeUlkKHRocmVhZElkKSA/PyBtYXBwZXIoYXdhaXQgY2xpZW50LmZldGNoUm9vbUV2ZW50KHJvb21JZCwgdGhyZWFkSWQpKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJvb20/LmNyZWF0ZVRocmVhZCh0aHJlYWRJZCwgcm9vdEV2ZW50LCBbaW5pdGlhbEV2ZW50XSwgdHJ1ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiQ291bGQgbm90IGZpbmQgcm9vdCBldmVudDogXCIgKyB0aHJlYWRJZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaW5pdGlhbEV2ZW50O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZWRpdEV2ZW50KFxuICAgIG1hdHJpeENsaWVudDogTWF0cml4Q2xpZW50LFxuICAgIG14RXZlbnQ6IE1hdHJpeEV2ZW50LFxuICAgIHRpbWVsaW5lUmVuZGVyaW5nVHlwZTogVGltZWxpbmVSZW5kZXJpbmdUeXBlLFxuICAgIGdldFJlbGF0aW9uc0ZvckV2ZW50PzogR2V0UmVsYXRpb25zRm9yRXZlbnQsXG4pOiB2b2lkIHtcbiAgICBpZiAoIWNhbkVkaXRDb250ZW50KG1hdHJpeENsaWVudCwgbXhFdmVudCkpIHJldHVybjtcblxuICAgIGlmIChNX1BPTExfU1RBUlQubWF0Y2hlcyhteEV2ZW50LmdldFR5cGUoKSkpIHtcbiAgICAgICAgbGF1bmNoUG9sbEVkaXRvcihteEV2ZW50LCBnZXRSZWxhdGlvbnNGb3JFdmVudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZGVmYXVsdERpc3BhdGNoZXIuZGlzcGF0Y2goe1xuICAgICAgICAgICAgYWN0aW9uOiBBY3Rpb24uRWRpdEV2ZW50LFxuICAgICAgICAgICAgZXZlbnQ6IG14RXZlbnQsXG4gICAgICAgICAgICB0aW1lbGluZVJlbmRlcmluZ1R5cGU6IHRpbWVsaW5lUmVuZGVyaW5nVHlwZSxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FuQ2FuY2VsKHN0YXR1cz86IEV2ZW50U3RhdHVzIHwgbnVsbCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzdGF0dXMgPT09IEV2ZW50U3RhdHVzLlFVRVVFRCB8fCBzdGF0dXMgPT09IEV2ZW50U3RhdHVzLk5PVF9TRU5UIHx8IHN0YXR1cyA9PT0gRXZlbnRTdGF0dXMuRU5DUllQVElORztcbn1cblxuZXhwb3J0IGNvbnN0IGlzTG9jYXRpb25FdmVudCA9IChldmVudDogTWF0cml4RXZlbnQpOiBib29sZWFuID0+IHtcbiAgICBjb25zdCBldmVudFR5cGUgPSBldmVudC5nZXRUeXBlKCk7XG4gICAgcmV0dXJuIChcbiAgICAgICAgTV9MT0NBVElPTi5tYXRjaGVzKGV2ZW50VHlwZSkgfHxcbiAgICAgICAgKGV2ZW50VHlwZSA9PT0gRXZlbnRUeXBlLlJvb21NZXNzYWdlICYmIE1fTE9DQVRJT04ubWF0Y2hlcyhldmVudC5nZXRDb250ZW50KCkubXNndHlwZSEpKVxuICAgICk7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gaGFzVGhyZWFkU3VtbWFyeShldmVudDogTWF0cml4RXZlbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZXZlbnQuaXNUaHJlYWRSb290ICYmICEhZXZlbnQuZ2V0VGhyZWFkKCk/Lmxlbmd0aCAmJiAhIWV2ZW50LmdldFRocmVhZCgpIS5yZXBseVRvRXZlbnQ7XG59XG5cbmV4cG9ydCBjb25zdCBoaWdobGlnaHRFdmVudCA9IChyb29tSWQ6IHN0cmluZywgZXZlbnRJZDogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgZGVmYXVsdERpc3BhdGNoZXIuZGlzcGF0Y2g8Vmlld1Jvb21QYXlsb2FkPih7XG4gICAgICAgIGFjdGlvbjogQWN0aW9uLlZpZXdSb29tLFxuICAgICAgICBldmVudF9pZDogZXZlbnRJZCxcbiAgICAgICAgaGlnaGxpZ2h0ZWQ6IHRydWUsXG4gICAgICAgIHJvb21faWQ6IHJvb21JZCxcbiAgICAgICAgbWV0cmljc1RyaWdnZXI6IHVuZGVmaW5lZCwgLy8gcm9vbSBkb2Vzbid0IGNoYW5nZVxuICAgIH0pO1xufTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVFBLElBQUFBLE9BQUEsR0FBQUMsT0FBQTtBQWNBLElBQUFDLE9BQUEsR0FBQUQsT0FBQTtBQUVBLElBQUFFLGdCQUFBLEdBQUFDLHNCQUFBLENBQUFILE9BQUE7QUFFQSxJQUFBSSxjQUFBLEdBQUFELHNCQUFBLENBQUFILE9BQUE7QUFDQSxJQUFBSyxXQUFBLEdBQUFGLHNCQUFBLENBQUFILE9BQUE7QUFFQSxJQUFBTSxVQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxRQUFBLEdBQUFQLE9BQUE7QUFFQSxJQUFBUSxNQUFBLEdBQUFSLE9BQUE7QUFoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBNEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTyxTQUFTUyxtQkFBbUJBLENBQUNDLE9BQW9CLEVBQVc7RUFDL0QsTUFBTTtJQUFFQyxNQUFNLEVBQUVDO0VBQVksQ0FBQyxHQUFHRixPQUFPOztFQUV2QztFQUNBLE1BQU1HLE1BQU0sR0FBRyxDQUFDRCxXQUFXLElBQUlBLFdBQVcsS0FBS0UsbUJBQVcsQ0FBQ0MsSUFBSTtFQUUvRCxJQUFJRixNQUFNLElBQUksQ0FBQ0gsT0FBTyxDQUFDTSxVQUFVLENBQUMsQ0FBQyxFQUFFO0lBQ2pDLElBQUlOLE9BQU8sQ0FBQ08sT0FBTyxDQUFDLENBQUMsS0FBSyxnQkFBZ0IsRUFBRTtNQUN4QyxNQUFNQyxPQUFPLEdBQUdSLE9BQU8sQ0FBQ1MsVUFBVSxDQUFDLENBQUM7TUFDcEMsSUFBSUQsT0FBTyxDQUFDRSxPQUFPLElBQUlGLE9BQU8sQ0FBQ0UsT0FBTyxLQUFLLGlCQUFpQixJQUFJRixPQUFPLENBQUNHLGNBQWMsQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUM1RixPQUFPLElBQUk7TUFDZjtJQUNKLENBQUMs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