UNPKG

matrix-react-sdk

Version:
183 lines (173 loc) 24.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.MARKED_UNREAD_TYPE_UNSTABLE = exports.MARKED_UNREAD_TYPE_STABLE = void 0; exports.clearAllNotifications = clearAllNotifications; exports.clearRoomNotification = clearRoomNotification; exports.createLocalNotificationSettingsIfNeeded = createLocalNotificationSettingsIfNeeded; exports.deviceNotificationSettingsKeys = void 0; exports.getLocalNotificationAccountDataEventType = getLocalNotificationAccountDataEventType; exports.getMarkedUnreadState = getMarkedUnreadState; exports.getThreadNotificationLevel = getThreadNotificationLevel; exports.localNotificationsAreSilenced = localNotificationsAreSilenced; exports.notificationLevelToIndicator = notificationLevelToIndicator; exports.setMarkedUnreadState = setMarkedUnreadState; var _matrix = require("matrix-js-sdk/src/matrix"); var _SettingsStore = _interopRequireDefault(require("../settings/SettingsStore")); var _NotificationLevel = require("../stores/notifications/NotificationLevel"); var _Unread = require("../Unread"); /* Copyright 2024 New Vector Ltd. Copyright 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. */ // MSC2867 is not yet spec at time of writing. We read from both stable // and unstable prefixes and accept the risk that the format may change, // since the stable prefix is not actually defined yet. /** * Unstable identifier for the marked_unread event, per MSC2867 */ const MARKED_UNREAD_TYPE_UNSTABLE = exports.MARKED_UNREAD_TYPE_UNSTABLE = "com.famedly.marked_unread"; /** * Stable identifier for the marked_unread event */ const MARKED_UNREAD_TYPE_STABLE = exports.MARKED_UNREAD_TYPE_STABLE = "m.marked_unread"; const deviceNotificationSettingsKeys = exports.deviceNotificationSettingsKeys = ["notificationsEnabled", "notificationBodyEnabled", "audioNotificationsEnabled"]; function getLocalNotificationAccountDataEventType(deviceId) { return `${_matrix.LOCAL_NOTIFICATION_SETTINGS_PREFIX.name}.${deviceId}`; } async function createLocalNotificationSettingsIfNeeded(cli) { if (cli.isGuest()) { return; } const eventType = getLocalNotificationAccountDataEventType(cli.deviceId); const event = cli.getAccountData(eventType); // New sessions will create an account data event to signify they support // remote toggling of push notifications on this device. Default `is_silenced=true` // For backwards compat purposes, older sessions will need to check settings value // to determine what the state of `is_silenced` if (!event) { // If any of the above is true, we fall in the "backwards compat" case, // and `is_silenced` will be set to `false` const isSilenced = !deviceNotificationSettingsKeys.some(key => _SettingsStore.default.getValue(key)); await cli.setAccountData(eventType, { is_silenced: isSilenced }); } } function localNotificationsAreSilenced(cli) { const eventType = getLocalNotificationAccountDataEventType(cli.deviceId); const event = cli.getAccountData(eventType); return event?.getContent()?.is_silenced ?? false; } /** * Mark a room as read * @param room * @param client * @returns a promise that resolves when the room has been marked as read */ async function clearRoomNotification(room, client) { const lastEvent = room.getLastLiveEvent(); await setMarkedUnreadState(room, client, false); try { if (lastEvent) { const receiptType = _SettingsStore.default.getValue("sendReadReceipts", room.roomId) ? _matrix.ReceiptType.Read : _matrix.ReceiptType.ReadPrivate; return await client.sendReadReceipt(lastEvent, receiptType, true); } else { return {}; } } finally { // We've had a lot of stuck unread notifications that in e2ee rooms // They occur on event decryption when clients try to replicate the logic // // This resets the notification on a room, even though no read receipt // has been sent, particularly useful when the clients has incorrectly // notified a user. room.setUnreadNotificationCount(_matrix.NotificationCountType.Highlight, 0); room.setUnreadNotificationCount(_matrix.NotificationCountType.Total, 0); for (const thread of room.getThreads()) { room.setThreadUnreadNotificationCount(thread.id, _matrix.NotificationCountType.Highlight, 0); room.setThreadUnreadNotificationCount(thread.id, _matrix.NotificationCountType.Total, 0); } } } /** * Marks all rooms with an unread counter as read * @param client The matrix client * @returns a promise that resolves when all rooms have been marked as read */ function clearAllNotifications(client) { const receiptPromises = client.getRooms().reduce((promises, room) => { if ((0, _Unread.doesRoomHaveUnreadMessages)(room, true)) { const promise = clearRoomNotification(room, client); promises.push(promise); } return promises; }, []); return Promise.all(receiptPromises); } /** * Gives the marked_unread state of the given room * @param room The room to check * @returns - The marked_unread state of the room, or undefined if no explicit state is set. */ function getMarkedUnreadState(room) { const currentStateStable = room.getAccountData(MARKED_UNREAD_TYPE_STABLE)?.getContent()?.unread; const currentStateUnstable = room.getAccountData(MARKED_UNREAD_TYPE_UNSTABLE)?.getContent()?.unread; return currentStateStable ?? currentStateUnstable; } /** * Sets the marked_unread state of the given room. This sets some room account data that indicates to * clients that the user considers this room to be 'unread', but without any actual notifications. * * @param room The room to set * @param client MatrixClient object to use * @param unread The new marked_unread state of the room */ async function setMarkedUnreadState(room, client, unread) { // if there's no event, treat this as false as we don't need to send the flag to clear it if the event isn't there const currentState = getMarkedUnreadState(room); if (Boolean(currentState) !== unread) { // Assuming MSC2867 passes FCP with no changes, we should update to start writing // the flag to the stable prefix (or both) and then ultimately use only the // stable prefix. await client.setRoomAccountData(room.roomId, MARKED_UNREAD_TYPE_UNSTABLE, { unread }); } } /** * A helper to transform a notification color to the what the Compound Icon Button * expects */ function notificationLevelToIndicator(level) { if (level <= _NotificationLevel.NotificationLevel.None) { return undefined; } else if (level <= _NotificationLevel.NotificationLevel.Activity) { return "default"; } else if (level <= _NotificationLevel.NotificationLevel.Notification) { return "success"; } else { return "critical"; } } /** * Return the thread notification level for a room * @param room * @returns {NotificationLevel} */ function getThreadNotificationLevel(room) { const notificationCountType = room.threadsAggregateNotificationType; switch (notificationCountType) { case _matrix.NotificationCountType.Highlight: return _NotificationLevel.NotificationLevel.Highlight; case _matrix.NotificationCountType.Total: return _NotificationLevel.NotificationLevel.Notification; default: return _NotificationLevel.NotificationLevel.Activity; } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9TZXR0aW5nc1N0b3JlIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9Ob3RpZmljYXRpb25MZXZlbCIsIl9VbnJlYWQiLCJNQVJLRURfVU5SRUFEX1RZUEVfVU5TVEFCTEUiLCJleHBvcnRzIiwiTUFSS0VEX1VOUkVBRF9UWVBFX1NUQUJMRSIsImRldmljZU5vdGlmaWNhdGlvblNldHRpbmdzS2V5cyIsImdldExvY2FsTm90aWZpY2F0aW9uQWNjb3VudERhdGFFdmVudFR5cGUiLCJkZXZpY2VJZCIsIkxPQ0FMX05PVElGSUNBVElPTl9TRVRUSU5HU19QUkVGSVgiLCJuYW1lIiwiY3JlYXRlTG9jYWxOb3RpZmljYXRpb25TZXR0aW5nc0lmTmVlZGVkIiwiY2xpIiwiaXNHdWVzdCIsImV2ZW50VHlwZSIsImV2ZW50IiwiZ2V0QWNjb3VudERhdGEiLCJpc1NpbGVuY2VkIiwic29tZSIsImtleSIsIlNldHRpbmdzU3RvcmUiLCJnZXRWYWx1ZSIsInNldEFjY291bnREYXRhIiwiaXNfc2lsZW5jZWQiLCJsb2NhbE5vdGlmaWNhdGlvbnNBcmVTaWxlbmNlZCIsImdldENvbnRlbnQiLCJjbGVhclJvb21Ob3RpZmljYXRpb24iLCJyb29tIiwiY2xpZW50IiwibGFzdEV2ZW50IiwiZ2V0TGFzdExpdmVFdmVudCIsInNldE1hcmtlZFVucmVhZFN0YXRlIiwicmVjZWlwdFR5cGUiLCJyb29tSWQiLCJSZWNlaXB0VHlwZSIsIlJlYWQiLCJSZWFkUHJpdmF0ZSIsInNlbmRSZWFkUmVjZWlwdCIsInNldFVucmVhZE5vdGlmaWNhdGlvbkNvdW50IiwiTm90aWZpY2F0aW9uQ291bnRUeXBlIiwiSGlnaGxpZ2h0IiwiVG90YWwiLCJ0aHJlYWQiLCJnZXRUaHJlYWRzIiwic2V0VGhyZWFkVW5yZWFkTm90aWZpY2F0aW9uQ291bnQiLCJpZCIsImNsZWFyQWxsTm90aWZpY2F0aW9ucyIsInJlY2VpcHRQcm9taXNlcyIsImdldFJvb21zIiwicmVkdWNlIiwicHJvbWlzZXMiLCJkb2VzUm9vbUhhdmVVbnJlYWRNZXNzYWdlcyIsInByb21pc2UiLCJwdXNoIiwiUHJvbWlzZSIsImFsbCIsImdldE1hcmtlZFVucmVhZFN0YXRlIiwiY3VycmVudFN0YXRlU3RhYmxlIiwidW5yZWFkIiwiY3VycmVudFN0YXRlVW5zdGFibGUiLCJjdXJyZW50U3RhdGUiLCJCb29sZWFuIiwic2V0Um9vbUFjY291bnREYXRhIiwibm90aWZpY2F0aW9uTGV2ZWxUb0luZGljYXRvciIsImxldmVsIiwiTm90aWZpY2F0aW9uTGV2ZWwiLCJOb25lIiwidW5kZWZpbmVkIiwiQWN0aXZpdHkiLCJOb3RpZmljYXRpb24iLCJnZXRUaHJlYWROb3RpZmljYXRpb25MZXZlbCIsIm5vdGlmaWNhdGlvbkNvdW50VHlwZSIsInRocmVhZHNBZ2dyZWdhdGVOb3RpZmljYXRpb25UeXBlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL25vdGlmaWNhdGlvbnMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHtcbiAgICBNYXRyaXhDbGllbnQsXG4gICAgTE9DQUxfTk9USUZJQ0FUSU9OX1NFVFRJTkdTX1BSRUZJWCxcbiAgICBOb3RpZmljYXRpb25Db3VudFR5cGUsXG4gICAgUm9vbSxcbiAgICBMb2NhbE5vdGlmaWNhdGlvblNldHRpbmdzLFxuICAgIFJlY2VpcHRUeXBlLFxuICAgIElNYXJrZWRVbnJlYWRFdmVudCxcbn0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgSW5kaWNhdG9ySWNvbiB9IGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLXdlYlwiO1xuXG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uTGV2ZWwgfSBmcm9tIFwiLi4vc3RvcmVzL25vdGlmaWNhdGlvbnMvTm90aWZpY2F0aW9uTGV2ZWxcIjtcbmltcG9ydCB7IGRvZXNSb29tSGF2ZVVucmVhZE1lc3NhZ2VzIH0gZnJvbSBcIi4uL1VucmVhZFwiO1xuXG4vLyBNU0MyODY3IGlzIG5vdCB5ZXQgc3BlYyBhdCB0aW1lIG9mIHdyaXRpbmcuIFdlIHJlYWQgZnJvbSBib3RoIHN0YWJsZVxuLy8gYW5kIHVuc3RhYmxlIHByZWZpeGVzIGFuZCBhY2NlcHQgdGhlIHJpc2sgdGhhdCB0aGUgZm9ybWF0IG1heSBjaGFuZ2UsXG4vLyBzaW5jZSB0aGUgc3RhYmxlIHByZWZpeCBpcyBub3QgYWN0dWFsbHkgZGVmaW5lZCB5ZXQuXG5cbi8qKlxuICogVW5zdGFibGUgaWRlbnRpZmllciBmb3IgdGhlIG1hcmtlZF91bnJlYWQgZXZlbnQsIHBlciBNU0MyODY3XG4gKi9cbmV4cG9ydCBjb25zdCBNQVJLRURfVU5SRUFEX1RZUEVfVU5TVEFCTEUgPSBcImNvbS5mYW1lZGx5Lm1hcmtlZF91bnJlYWRcIjtcbi8qKlxuICogU3RhYmxlIGlkZW50aWZpZXIgZm9yIHRoZSBtYXJrZWRfdW5yZWFkIGV2ZW50XG4gKi9cbmV4cG9ydCBjb25zdCBNQVJLRURfVU5SRUFEX1RZUEVfU1RBQkxFID0gXCJtLm1hcmtlZF91bnJlYWRcIjtcblxuZXhwb3J0IGNvbnN0IGRldmljZU5vdGlmaWNhdGlvblNldHRpbmdzS2V5cyA9IFtcbiAgICBcIm5vdGlmaWNhdGlvbnNFbmFibGVkXCIsXG4gICAgXCJub3RpZmljYXRpb25Cb2R5RW5hYmxlZFwiLFxuICAgIFwiYXVkaW9Ob3RpZmljYXRpb25zRW5hYmxlZFwiLFxuXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvY2FsTm90aWZpY2F0aW9uQWNjb3VudERhdGFFdmVudFR5cGUoZGV2aWNlSWQ6IHN0cmluZyB8IG51bGwpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHtMT0NBTF9OT1RJRklDQVRJT05fU0VUVElOR1NfUFJFRklYLm5hbWV9LiR7ZGV2aWNlSWR9YDtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUxvY2FsTm90aWZpY2F0aW9uU2V0dGluZ3NJZk5lZWRlZChjbGk6IE1hdHJpeENsaWVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChjbGkuaXNHdWVzdCgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXZlbnRUeXBlID0gZ2V0TG9jYWxOb3RpZmljYXRpb25BY2NvdW50RGF0YUV2ZW50VHlwZShjbGkuZGV2aWNlSWQhKTtcbiAgICBjb25zdCBldmVudCA9IGNsaS5nZXRBY2NvdW50RGF0YShldmVudFR5cGUpO1xuICAgIC8vIE5ldyBzZXNzaW9ucyB3aWxsIGNyZWF0ZSBhbiBhY2NvdW50IGRhdGEgZXZlbnQgdG8gc2lnbmlmeSB0aGV5IHN1cHBvcnRcbiAgICAvLyByZW1vdGUgdG9nZ2xpbmcgb2YgcHVzaCBub3RpZmljYXRpb25zIG9uIHRoaXMgZGV2aWNlLiBEZWZhdWx0IGBpc19zaWxlbmNlZD10cnVlYFxuICAgIC8vIEZvciBiYWNrd2FyZHMgY29tcGF0IHB1cnBvc2VzLCBvbGRlciBzZXNzaW9ucyB3aWxsIG5lZWQgdG8gY2hlY2sgc2V0dGluZ3MgdmFsdWVcbiAgICAvLyB0byBkZXRlcm1pbmUgd2hhdCB0aGUgc3RhdGUgb2YgYGlzX3NpbGVuY2VkYFxuICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgLy8gSWYgYW55IG9mIHRoZSBhYm92ZSBpcyB0cnVlLCB3ZSBmYWxsIGluIHRoZSBcImJhY2t3YXJkcyBjb21wYXRcIiBjYXNlLFxuICAgICAgICAvLyBhbmQgYGlzX3NpbGVuY2VkYCB3aWxsIGJlIHNldCB0byBgZmFsc2VgXG4gICAgICAgIGNvbnN0IGlzU2lsZW5jZWQgPSAhZGV2aWNlTm90aWZpY2F0aW9uU2V0dGluZ3NLZXlzLnNvbWUoKGtleSkgPT4gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShrZXkpKTtcblxuICAgICAgICBhd2FpdCBjbGkuc2V0QWNjb3VudERhdGEoZXZlbnRUeXBlLCB7XG4gICAgICAgICAgICBpc19zaWxlbmNlZDogaXNTaWxlbmNlZCxcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9jYWxOb3RpZmljYXRpb25zQXJlU2lsZW5jZWQoY2xpOiBNYXRyaXhDbGllbnQpOiBib29sZWFuIHtcbiAgICBjb25zdCBldmVudFR5cGUgPSBnZXRMb2NhbE5vdGlmaWNhdGlvbkFjY291bnREYXRhRXZlbnRUeXBlKGNsaS5kZXZpY2VJZCEpO1xuICAgIGNvbnN0IGV2ZW50ID0gY2xpLmdldEFjY291bnREYXRhKGV2ZW50VHlwZSk7XG4gICAgcmV0dXJuIGV2ZW50Py5nZXRDb250ZW50PExvY2FsTm90aWZpY2F0aW9uU2V0dGluZ3M+KCk/LmlzX3NpbGVuY2VkID8/IGZhbHNlO1xufVxuXG4vKipcbiAqIE1hcmsgYSByb29tIGFzIHJlYWRcbiAqIEBwYXJhbSByb29tXG4gKiBAcGFyYW0gY2xpZW50XG4gKiBAcmV0dXJucyBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSByb29tIGhhcyBiZWVuIG1hcmtlZCBhcyByZWFkXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbGVhclJvb21Ob3RpZmljYXRpb24ocm9vbTogUm9vbSwgY2xpZW50OiBNYXRyaXhDbGllbnQpOiBQcm9taXNlPHt9IHwgdW5kZWZpbmVkPiB7XG4gICAgY29uc3QgbGFzdEV2ZW50ID0gcm9vbS5nZXRMYXN0TGl2ZUV2ZW50KCk7XG5cbiAgICBhd2FpdCBzZXRNYXJrZWRVbnJlYWRTdGF0ZShyb29tLCBjbGllbnQsIGZhbHNlKTtcblxuICAgIHRyeSB7XG4gICAgICAgIGlmIChsYXN0RXZlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlY2VpcHRUeXBlID0gU2V0dGluZ3NTdG9yZS5nZXRWYWx1ZShcInNlbmRSZWFkUmVjZWlwdHNcIiwgcm9vbS5yb29tSWQpXG4gICAgICAgICAgICAgICAgPyBSZWNlaXB0VHlwZS5SZWFkXG4gICAgICAgICAgICAgICAgOiBSZWNlaXB0VHlwZS5SZWFkUHJpdmF0ZTtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBjbGllbnQuc2VuZFJlYWRSZWNlaXB0KGxhc3RFdmVudCwgcmVjZWlwdFR5cGUsIHRydWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgLy8gV2UndmUgaGFkIGEgbG90IG9mIHN0dWNrIHVucmVhZCBub3RpZmljYXRpb25zIHRoYXQgaW4gZTJlZSByb29tc1xuICAgICAgICAvLyBUaGV5IG9jY3VyIG9uIGV2ZW50IGRlY3J5cHRpb24gd2hlbiBjbGllbnRzIHRyeSB0byByZXBsaWNhdGUgdGhlIGxvZ2ljXG4gICAgICAgIC8vXG4gICAgICAgIC8vIFRoaXMgcmVzZXRzIHRoZSBub3RpZmljYXRpb24gb24gYSByb29tLCBldmVuIHRob3VnaCBubyByZWFkIHJlY2VpcHRcbiAgICAgICAgLy8gaGFzIGJlZW4gc2VudCwgcGFydGljdWxhcmx5IHVzZWZ1bCB3aGVuIHRoZSBjbGllbnRzIGhhcyBpbmNvcnJlY3RseVxuICAgICAgICAvLyBub3RpZmllZCBhIHVzZXIuXG4gICAgICAgIHJvb20uc2V0VW5yZWFkTm90aWZpY2F0aW9uQ291bnQoTm90aWZpY2F0aW9uQ291bnRUeXBlLkhpZ2hsaWdodCwgMCk7XG4gICAgICAgIHJvb20uc2V0VW5yZWFkTm90aWZpY2F0aW9uQ291bnQoTm90aWZpY2F0aW9uQ291bnRUeXBlLlRvdGFsLCAwKTtcbiAgICAgICAgZm9yIChjb25zdCB0aHJlYWQgb2Ygcm9vbS5nZXRUaHJlYWRzKCkpIHtcbiAgICAgICAgICAgIHJvb20uc2V0VGhyZWFkVW5yZWFkTm90aWZpY2F0aW9uQ291bnQodGhyZWFkLmlkLCBOb3RpZmljYXRpb25Db3VudFR5cGUuSGlnaGxpZ2h0LCAwKTtcbiAgICAgICAgICAgIHJvb20uc2V0VGhyZWFkVW5yZWFkTm90aWZpY2F0aW9uQ291bnQodGhyZWFkLmlkLCBOb3RpZmljYXRpb25Db3VudFR5cGUuVG90YWwsIDApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE1hcmtzIGFsbCByb29tcyB3aXRoIGFuIHVucmVhZCBjb3VudGVyIGFzIHJlYWRcbiAqIEBwYXJhbSBjbGllbnQgVGhlIG1hdHJpeCBjbGllbnRcbiAqIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIHJvb21zIGhhdmUgYmVlbiBtYXJrZWQgYXMgcmVhZFxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJBbGxOb3RpZmljYXRpb25zKGNsaWVudDogTWF0cml4Q2xpZW50KTogUHJvbWlzZTxBcnJheTx7fSB8IHVuZGVmaW5lZD4+IHtcbiAgICBjb25zdCByZWNlaXB0UHJvbWlzZXMgPSBjbGllbnQuZ2V0Um9vbXMoKS5yZWR1Y2UoKHByb21pc2VzOiBBcnJheTxQcm9taXNlPHt9IHwgdW5kZWZpbmVkPj4sIHJvb206IFJvb20pID0+IHtcbiAgICAgICAgaWYgKGRvZXNSb29tSGF2ZVVucmVhZE1lc3NhZ2VzKHJvb20sIHRydWUpKSB7XG4gICAgICAgICAgICBjb25zdCBwcm9taXNlID0gY2xlYXJSb29tTm90aWZpY2F0aW9uKHJvb20sIGNsaWVudCk7XG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHByb21pc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2VzO1xuICAgIH0sIFtdKTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbChyZWNlaXB0UHJvbWlzZXMpO1xufVxuXG4vKipcbiAqIEdpdmVzIHRoZSBtYXJrZWRfdW5yZWFkIHN0YXRlIG9mIHRoZSBnaXZlbiByb29tXG4gKiBAcGFyYW0gcm9vbSBUaGUgcm9vbSB0byBjaGVja1xuICogQHJldHVybnMgLSBUaGUgbWFya2VkX3VucmVhZCBzdGF0ZSBvZiB0aGUgcm9vbSwgb3IgdW5kZWZpbmVkIGlmIG5vIGV4cGxpY2l0IHN0YXRlIGlzIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1hcmtlZFVucmVhZFN0YXRlKHJvb206IFJvb20pOiBib29sZWFuIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGVTdGFibGUgPSByb29tLmdldEFjY291bnREYXRhKE1BUktFRF9VTlJFQURfVFlQRV9TVEFCTEUpPy5nZXRDb250ZW50PElNYXJrZWRVbnJlYWRFdmVudD4oKT8udW5yZWFkO1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZVVuc3RhYmxlID0gcm9vbVxuICAgICAgICAuZ2V0QWNjb3VudERhdGEoTUFSS0VEX1VOUkVBRF9UWVBFX1VOU1RBQkxFKVxuICAgICAgICA/LmdldENvbnRlbnQ8SU1hcmtlZFVucmVhZEV2ZW50PigpPy51bnJlYWQ7XG4gICAgcmV0dXJuIGN1cnJlbnRTdGF0ZVN0YWJsZSA/PyBjdXJyZW50U3RhdGVVbnN0YWJsZTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtYXJrZWRfdW5yZWFkIHN0YXRlIG9mIHRoZSBnaXZlbiByb29tLiBUaGlzIHNldHMgc29tZSByb29tIGFjY291bnQgZGF0YSB0aGF0IGluZGljYXRlcyB0b1xuICogY2xpZW50cyB0aGF0IHRoZSB1c2VyIGNvbnNpZGVycyB0aGlzIHJvb20gdG8gYmUgJ3VucmVhZCcsIGJ1dCB3aXRob3V0IGFueSBhY3R1YWwgbm90aWZpY2F0aW9ucy5cbiAqXG4gKiBAcGFyYW0gcm9vbSBUaGUgcm9vbSB0byBzZXRcbiAqIEBwYXJhbSBjbGllbnQgTWF0cml4Q2xpZW50IG9iamVjdCB0byB1c2VcbiAqIEBwYXJhbSB1bnJlYWQgVGhlIG5ldyBtYXJrZWRfdW5yZWFkIHN0YXRlIG9mIHRoZSByb29tXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXRNYXJrZWRVbnJlYWRTdGF0ZShyb29tOiBSb29tLCBjbGllbnQ6IE1hdHJpeENsaWVudCwgdW5yZWFkOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gaWYgdGhlcmUncyBubyBldmVudCwgdHJlYXQgdGhpcyBhcyBmYWxzZSBhcyB3ZSBkb24ndCBuZWVkIHRvIHNlbmQgdGhlIGZsYWcgdG8gY2xlYXIgaXQgaWYgdGhlIGV2ZW50IGlzbid0IHRoZXJlXG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gZ2V0TWFya2VkVW5yZWFkU3RhdGUocm9vbSk7XG5cbiAgICBpZiAoQm9vbGVhbihjdXJyZW50U3RhdGUpICE9PSB1bnJlYWQpIHtcbiAgICAgICAgLy8gQXNzdW1pbmcgTVNDMjg2NyBwYXNzZXMgRkNQIHdpdGggbm8gY2hhbmdlcywgd2Ugc2hvdWxkIHVwZGF0ZSB0byBzdGFydCB3cml0aW5nXG4gICAgICAgIC8vIHRoZSBmbGFnIHRvIHRoZSBzdGFibGUgcHJlZml4IChvciBib3RoKSBhbmQgdGhlbiB1bHRpbWF0ZWx5IHVzZSBvbmx5IHRoZVxuICAgICAgICAvLyBzdGFibGUgcHJlZml4LlxuICAgICAgICBhd2FpdCBjbGllbnQuc2V0Um9vbUFjY291bnREYXRhKHJvb20ucm9vbUlkLCBNQVJLRURfVU5SRUFEX1RZUEVfVU5TVEFCTEUsIHsgdW5yZWFkIH0pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBIGhlbHBlciB0byB0cmFuc2Zvcm0gYSBub3RpZmljYXRpb24gY29sb3IgdG8gdGhlIHdoYXQgdGhlIENvbXBvdW5kIEljb24gQnV0dG9uXG4gKiBleHBlY3RzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3RpZmljYXRpb25MZXZlbFRvSW5kaWNhdG9yKFxuICAgIGxldmVsOiBOb3RpZmljYXRpb25MZXZlbCxcbik6IFJlYWN0LkNvbXBvbmVudFByb3BzV2l0aFJlZjx0eXBlb2YgSW5kaWNhdG9ySWNvbj5bXCJpbmRpY2F0b3JcIl0ge1xuICAgIGlmIChsZXZlbCA8PSBOb3RpZmljYXRpb25MZXZlbC5Ob25lKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIGlmIChsZXZlbCA8PSBOb3RpZmljYXRpb25MZXZlbC5BY3Rpdml0eSkge1xuICAgICAgICByZXR1cm4gXCJkZWZhdWx0XCI7XG4gICAgfSBlbHNlIGlmIChsZXZlbCA8PSBOb3RpZmljYXRpb25MZXZlbC5Ob3RpZmljYXRpb24pIHtcbiAgICAgICAgcmV0dXJuIFwic3VjY2Vzc1wiO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBcImNyaXRpY2FsXCI7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHVybiB0aGUgdGhyZWFkIG5vdGlmaWNhdGlvbiBsZXZlbCBmb3IgYSByb29tXG4gKiBAcGFyYW0gcm9vbVxuICogQHJldHVybnMge05vdGlmaWNhdGlvbkxldmVsfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGhyZWFkTm90aWZpY2F0aW9uTGV2ZWwocm9vbTogUm9vbSk6IE5vdGlmaWNhdGlvbkxldmVsIHtcbiAgICBjb25zdCBub3RpZmljYXRpb25Db3VudFR5cGUgPSByb29tLnRocmVhZHNBZ2dyZWdhdGVOb3RpZmljYXRpb25UeXBlO1xuICAgIHN3aXRjaCAobm90aWZpY2F0aW9uQ291bnRUeXBlKSB7XG4gICAgICAgIGNhc2UgTm90aWZpY2F0aW9uQ291bnRUeXBlLkhpZ2hsaWdodDpcbiAgICAgICAgICAgIHJldHVybiBOb3RpZmljYXRpb25MZXZlbC5IaWdobGlnaHQ7XG4gICAgICAgIGNhc2UgTm90aWZpY2F0aW9uQ291bnRUeXBlLlRvdGFsOlxuICAgICAgICAgICAgcmV0dXJuIE5vdGlmaWNhdGlvbkxldmVsLk5vdGlmaWNhdGlvbjtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBOb3RpZmljYXRpb25MZXZlbC5BY3Rpdml0eTtcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBUUEs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