UNPKG

matrix-react-sdk

Version:
248 lines (244 loc) 40.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrix = require("matrix-js-sdk/src/matrix"); var _fileSaver = require("file-saver"); var _logger = require("matrix-js-sdk/src/logger"); var _sanitizeFilename = _interopRequireDefault(require("sanitize-filename")); var _exportUtils = require("./exportUtils"); var _DecryptFile = require("../DecryptFile"); var _Media = require("../../customisations/Media"); var _DateUtils = require("../../DateUtils"); var _EventUtils = require("../EventUtils"); var _languageHandler = require("../../languageHandler"); var _SdkConfig = _interopRequireDefault(require("../../SdkConfig")); 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; } /* Copyright 2024 New Vector Ltd. Copyright 2021, 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. */ class Exporter { constructor(room, exportType, exportOptions, setProgressText) { (0, _defineProperty2.default)(this, "files", []); (0, _defineProperty2.default)(this, "cancelled", false); this.room = room; this.exportType = exportType; this.exportOptions = exportOptions; this.setProgressText = setProgressText; if (exportOptions.maxSize < 1 * 1024 * 1024 || // Less than 1 MB exportOptions.maxSize > 8000 * 1024 * 1024 || // More than 8 GB !!exportOptions.numberOfMessages && exportOptions.numberOfMessages > 10 ** 8 || exportType === _exportUtils.ExportType.LastNMessages && !exportOptions.numberOfMessages) { throw new Error("Invalid export options"); } window.addEventListener("beforeunload", this.onBeforeUnload); } get destinationFileName() { return this.makeFileNameNoExtension(_SdkConfig.default.get().brand) + ".zip"; } onBeforeUnload(e) { e.preventDefault(); return e.returnValue = (0, _languageHandler._t)("export_chat|unload_confirm"); } updateProgress(progress, log = true, show = true) { if (log) _logger.logger.log(progress); if (show) this.setProgressText(progress); } addFile(filePath, blob) { const file = { name: filePath, blob }; this.files.push(file); } makeFileNameNoExtension(brand = "matrix") { // First try to use the real name of the room, then a translated copy of a generic name, // then finally hardcoded default to guarantee we'll have a name. const safeRoomName = (0, _sanitizeFilename.default)(this.room.name ?? (0, _languageHandler._t)("common|unnamed_room")).trim() || "Unnamed Room"; const safeDate = (0, _DateUtils.formatFullDateNoDayISO)(new Date()).replace(/:/g, "-"); // ISO format automatically removes a lot of stuff for us const safeBrand = (0, _sanitizeFilename.default)(brand); return `${safeBrand} - ${safeRoomName} - Chat Export - ${safeDate}`; } async downloadZIP() { const filename = this.destinationFileName; const filenameWithoutExt = filename.substring(0, filename.lastIndexOf(".")); // take off the extension const { default: JSZip } = await Promise.resolve().then(() => _interopRequireWildcard(require("jszip"))); const zip = new JSZip(); // Create a writable stream to the directory if (!this.cancelled) this.updateProgress((0, _languageHandler._t)("export_chat|generating_zip"));else return this.cleanUp(); for (const file of this.files) zip.file(filenameWithoutExt + "/" + file.name, file.blob); const content = await zip.generateAsync({ type: "blob" }); (0, _fileSaver.saveAs)(content, filenameWithoutExt + ".zip"); } cleanUp() { _logger.logger.log("Cleaning up..."); window.removeEventListener("beforeunload", this.onBeforeUnload); return ""; } async cancelExport() { _logger.logger.log("Cancelling export..."); this.cancelled = true; } downloadPlainText(fileName, text) { const content = new Blob([text], { type: "text/plain" }); (0, _fileSaver.saveAs)(content, fileName); } setEventMetadata(event) { const roomState = this.room.currentState; const sender = event.getSender(); event.sender = !!sender && roomState?.getSentinelMember(sender) || null; if (event.getType() === "m.room.member") { event.target = roomState?.getSentinelMember(event.getStateKey()) ?? null; } return event; } getLimit() { let limit; switch (this.exportType) { case _exportUtils.ExportType.LastNMessages: // validated in constructor that numberOfMessages is defined // when export type is LastNMessages limit = this.exportOptions.numberOfMessages; break; default: limit = 10 ** 8; } return limit; } async getRequiredEvents() { const eventMapper = this.room.client.getEventMapper(); let prevToken = null; let events = []; if (this.exportType === _exportUtils.ExportType.Timeline) { events = this.room.getLiveTimeline().getEvents(); } else { let limit = this.getLimit(); while (limit) { const eventsPerCrawl = Math.min(limit, 1000); const res = await this.room.client.createMessagesRequest(this.room.roomId, prevToken, eventsPerCrawl, _matrix.Direction.Backward); if (this.cancelled) { this.cleanUp(); return []; } if (res.chunk.length === 0) break; limit -= res.chunk.length; const matrixEvents = res.chunk.map(eventMapper); for (const mxEv of matrixEvents) { // if (this.exportOptions.startDate && mxEv.getTs() < this.exportOptions.startDate) { // // Once the last message received is older than the start date, we break out of both the loops // limit = 0; // break; // } events.push(mxEv); } if (this.exportType === _exportUtils.ExportType.LastNMessages) { this.updateProgress((0, _languageHandler._t)("export_chat|fetched_n_events_with_total", { count: events.length, total: this.exportOptions.numberOfMessages })); } else { this.updateProgress((0, _languageHandler._t)("export_chat|fetched_n_events", { count: events.length })); } prevToken = res.end ?? null; } // Reverse the events so that we preserve the order events.reverse(); } const decryptionPromises = events.filter(event => event.isEncrypted()).map(event => { return this.room.client.decryptEventIfNeeded(event, { emit: false }); }); // Wait for all the events to get decrypted. await Promise.all(decryptionPromises); for (let i = 0; i < events.length; i++) this.setEventMetadata(events[i]); return events; } /** * Decrypts if necessary, and fetches media from a matrix event * @param event - matrix event with media event content * @resolves when media has been fetched * @throws if media was unable to be fetched */ async getMediaBlob(event) { let blob = undefined; try { const isEncrypted = event.isEncrypted(); const content = event.getContent(); const shouldDecrypt = isEncrypted && content.hasOwnProperty("file") && event.getType() !== "m.sticker"; if (shouldDecrypt) { blob = await (0, _DecryptFile.decryptFile)(content.file); } else { const media = (0, _Media.mediaFromContent)(content); if (!media.srcHttp) { throw new Error("Cannot fetch without srcHttp"); } const image = await fetch(media.srcHttp); blob = await image.blob(); } } catch (err) { _logger.logger.log("Error decrypting media"); } if (!blob) { throw new Error("Unable to fetch file"); } return blob; } splitFileName(file) { const lastDot = file.lastIndexOf("."); if (lastDot === -1) return [file, ""]; const fileName = file.slice(0, lastDot); const ext = file.slice(lastDot + 1); return [fileName, "." + ext]; } getFilePath(event) { const mediaType = event.getContent().msgtype; let fileDirectory; switch (mediaType) { case "m.image": fileDirectory = "images"; break; case "m.video": fileDirectory = "videos"; break; case "m.audio": fileDirectory = "audio"; break; default: fileDirectory = event.getType() === "m.sticker" ? "stickers" : "files"; } const fileDate = (0, _DateUtils.formatFullDateNoDay)(new Date(event.getTs())); let [fileName, fileExt] = this.splitFileName(event.getContent().body); if (event.getType() === "m.sticker") fileExt = ".png"; if ((0, _EventUtils.isVoiceMessage)(event)) fileExt = ".ogg"; return fileDirectory + "/" + fileName + "-" + fileDate + fileExt; } isReply(event) { const isEncrypted = event.isEncrypted(); // If encrypted, in_reply_to lies in event.event.content const content = isEncrypted ? event.event.content : event.getContent(); const relatesTo = content["m.relates_to"]; return !!(relatesTo && relatesTo["m.in_reply_to"]); } isAttachment(mxEv) { const attachmentTypes = ["m.sticker", "m.image", "m.file", "m.video", "m.audio"]; return mxEv.getType() === attachmentTypes[0] || attachmentTypes.includes(mxEv.getContent().msgtype); } } exports.default = Exporter; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9maWxlU2F2ZXIiLCJfbG9nZ2VyIiwiX3Nhbml0aXplRmlsZW5hbWUiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2V4cG9ydFV0aWxzIiwiX0RlY3J5cHRGaWxlIiwiX01lZGlhIiwiX0RhdGVVdGlscyIsIl9FdmVudFV0aWxzIiwiX2xhbmd1YWdlSGFuZGxlciIsIl9TZGtDb25maWciLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIkV4cG9ydGVyIiwiY29uc3RydWN0b3IiLCJyb29tIiwiZXhwb3J0VHlwZSIsImV4cG9ydE9wdGlvbnMiLCJzZXRQcm9ncmVzc1RleHQiLCJfZGVmaW5lUHJvcGVydHkyIiwibWF4U2l6ZSIsIm51bWJlck9mTWVzc2FnZXMiLCJFeHBvcnRUeXBlIiwiTGFzdE5NZXNzYWdlcyIsIkVycm9yIiwid2luZG93IiwiYWRkRXZlbnRMaXN0ZW5lciIsIm9uQmVmb3JlVW5sb2FkIiwiZGVzdGluYXRpb25GaWxlTmFtZSIsIm1ha2VGaWxlTmFtZU5vRXh0ZW5zaW9uIiwiU2RrQ29uZmlnIiwiYnJhbmQiLCJwcmV2ZW50RGVmYXVsdCIsInJldHVyblZhbHVlIiwiX3QiLCJ1cGRhdGVQcm9ncmVzcyIsInByb2dyZXNzIiwibG9nIiwic2hvdyIsImxvZ2dlciIsImFkZEZpbGUiLCJmaWxlUGF0aCIsImJsb2IiLCJmaWxlIiwibmFtZSIsImZpbGVzIiwicHVzaCIsInNhZmVSb29tTmFtZSIsInNhbml0aXplRmlsZW5hbWUiLCJ0cmltIiwic2FmZURhdGUiLCJmb3JtYXRGdWxsRGF0ZU5vRGF5SVNPIiwiRGF0ZSIsInJlcGxhY2UiLCJzYWZlQnJhbmQiLCJkb3dubG9hZFpJUCIsImZpbGVuYW1lIiwiZmlsZW5hbWVXaXRob3V0RXh0Iiwic3Vic3RyaW5nIiwibGFzdEluZGV4T2YiLCJKU1ppcCIsIlByb21pc2UiLCJyZXNvbHZlIiwidGhlbiIsInppcCIsImNhbmNlbGxlZCIsImNsZWFuVXAiLCJjb250ZW50IiwiZ2VuZXJhdGVBc3luYyIsInR5cGUiLCJzYXZlQXMiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiY2FuY2VsRXhwb3J0IiwiZG93bmxvYWRQbGFpblRleHQiLCJmaWxlTmFtZSIsInRleHQiLCJCbG9iIiwic2V0RXZlbnRNZXRhZGF0YSIsImV2ZW50Iiwicm9vbVN0YXRlIiwiY3VycmVudFN0YXRlIiwic2VuZGVyIiwiZ2V0U2VuZGVyIiwiZ2V0U2VudGluZWxNZW1iZXIiLCJnZXRUeXBlIiwidGFyZ2V0IiwiZ2V0U3RhdGVLZXkiLCJnZXRMaW1pdCIsImxpbWl0IiwiZ2V0UmVxdWlyZWRFdmVudHMiLCJldmVudE1hcHBlciIsImNsaWVudCIsImdldEV2ZW50TWFwcGVyIiwicHJldlRva2VuIiwiZXZlbnRzIiwiVGltZWxpbmUiLCJnZXRMaXZlVGltZWxpbmUiLCJnZXRFdmVudHMiLCJldmVudHNQZXJDcmF3bCIsIk1hdGgiLCJtaW4iLCJyZXMiLCJjcmVhdGVNZXNzYWdlc1JlcXVlc3QiLCJyb29tSWQiLCJEaXJlY3Rpb24iLCJCYWNrd2FyZCIsImNodW5rIiwibGVuZ3RoIiwibWF0cml4RXZlbnRzIiwibWFwIiwibXhFdiIsImNvdW50IiwidG90YWwiLCJlbmQiLCJyZXZlcnNlIiwiZGVjcnlwdGlvblByb21pc2VzIiwiZmlsdGVyIiwiaXNFbmNyeXB0ZWQiLCJkZWNyeXB0RXZlbnRJZk5lZWRlZCIsImVtaXQiLCJhbGwiLCJnZXRNZWRpYUJsb2IiLCJ1bmRlZmluZWQiLCJnZXRDb250ZW50Iiwic2hvdWxkRGVjcnlwdCIsImRlY3J5cHRGaWxlIiwibWVkaWEiLCJtZWRpYUZyb21Db250ZW50Iiwic3JjSHR0cCIsImltYWdlIiwiZmV0Y2giLCJlcnIiLCJzcGxpdEZpbGVOYW1lIiwibGFzdERvdCIsInNsaWNlIiwiZXh0IiwiZ2V0RmlsZVBhdGgiLCJtZWRpYVR5cGUiLCJtc2d0eXBlIiwiZmlsZURpcmVjdG9yeSIsImZpbGVEYXRlIiwiZm9ybWF0RnVsbERhdGVOb0RheSIsImdldFRzIiwiZmlsZUV4dCIsImJvZHkiLCJpc1ZvaWNlTWVzc2FnZSIsImlzUmVwbHkiLCJyZWxhdGVzVG8iLCJpc0F0dGFjaG1lbnQiLCJhdHRhY2htZW50VHlwZXMiLCJpbmNsdWRlcyIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvZXhwb3J0VXRpbHMvRXhwb3J0ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMjEsIDIwMjIgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IHsgRGlyZWN0aW9uLCBNYXRyaXhFdmVudCwgUm9vbSB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IE1lZGlhRXZlbnRDb250ZW50IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL3R5cGVzXCI7XG5pbXBvcnQgeyBzYXZlQXMgfSBmcm9tIFwiZmlsZS1zYXZlclwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuaW1wb3J0IHNhbml0aXplRmlsZW5hbWUgZnJvbSBcInNhbml0aXplLWZpbGVuYW1lXCI7XG5cbmltcG9ydCB7IEV4cG9ydFR5cGUsIElFeHBvcnRPcHRpb25zIH0gZnJvbSBcIi4vZXhwb3J0VXRpbHNcIjtcbmltcG9ydCB7IGRlY3J5cHRGaWxlIH0gZnJvbSBcIi4uL0RlY3J5cHRGaWxlXCI7XG5pbXBvcnQgeyBtZWRpYUZyb21Db250ZW50IH0gZnJvbSBcIi4uLy4uL2N1c3RvbWlzYXRpb25zL01lZGlhXCI7XG5pbXBvcnQgeyBmb3JtYXRGdWxsRGF0ZU5vRGF5LCBmb3JtYXRGdWxsRGF0ZU5vRGF5SVNPIH0gZnJvbSBcIi4uLy4uL0RhdGVVdGlsc1wiO1xuaW1wb3J0IHsgaXNWb2ljZU1lc3NhZ2UgfSBmcm9tIFwiLi4vRXZlbnRVdGlsc1wiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgU2RrQ29uZmlnIGZyb20gXCIuLi8uLi9TZGtDb25maWdcIjtcblxudHlwZSBCbG9iRmlsZSA9IHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgYmxvYjogQmxvYjtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGFic3RyYWN0IGNsYXNzIEV4cG9ydGVyIHtcbiAgICBwcm90ZWN0ZWQgZmlsZXM6IEJsb2JGaWxlW10gPSBbXTtcbiAgICBwcm90ZWN0ZWQgY2FuY2VsbGVkID0gZmFsc2U7XG5cbiAgICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgICAgIHByb3RlY3RlZCByb29tOiBSb29tLFxuICAgICAgICBwcm90ZWN0ZWQgZXhwb3J0VHlwZTogRXhwb3J0VHlwZSxcbiAgICAgICAgcHJvdGVjdGVkIGV4cG9ydE9wdGlvbnM6IElFeHBvcnRPcHRpb25zLFxuICAgICAgICBwcm90ZWN0ZWQgc2V0UHJvZ3Jlc3NUZXh0OiBSZWFjdC5EaXNwYXRjaDxSZWFjdC5TZXRTdGF0ZUFjdGlvbjxzdHJpbmc+PixcbiAgICApIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgZXhwb3J0T3B0aW9ucy5tYXhTaXplIDwgMSAqIDEwMjQgKiAxMDI0IHx8IC8vIExlc3MgdGhhbiAxIE1CXG4gICAgICAgICAgICBleHBvcnRPcHRpb25zLm1heFNpemUgPiA4MDAwICogMTAyNCAqIDEwMjQgfHwgLy8gTW9yZSB0aGFuIDggR0JcbiAgICAgICAgICAgICghIWV4cG9ydE9wdGlvbnMubnVtYmVyT2ZNZXNzYWdlcyAmJiBleHBvcnRPcHRpb25zLm51bWJlck9mTWVzc2FnZXMgPiAxMCAqKiA4KSB8fFxuICAgICAgICAgICAgKGV4cG9ydFR5cGUgPT09IEV4cG9ydFR5cGUuTGFzdE5NZXNzYWdlcyAmJiAhZXhwb3J0T3B0aW9ucy5udW1iZXJPZk1lc3NhZ2VzKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgZXhwb3J0IG9wdGlvbnNcIik7XG4gICAgICAgIH1cbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJiZWZvcmV1bmxvYWRcIiwgdGhpcy5vbkJlZm9yZVVubG9hZCk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBkZXN0aW5hdGlvbkZpbGVOYW1lKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLm1ha2VGaWxlTmFtZU5vRXh0ZW5zaW9uKFNka0NvbmZpZy5nZXQoKS5icmFuZCkgKyBcIi56aXBcIjtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgb25CZWZvcmVVbmxvYWQoZTogQmVmb3JlVW5sb2FkRXZlbnQpOiBzdHJpbmcge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHJldHVybiAoZS5yZXR1cm5WYWx1ZSA9IF90KFwiZXhwb3J0X2NoYXR8dW5sb2FkX2NvbmZpcm1cIikpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCB1cGRhdGVQcm9ncmVzcyhwcm9ncmVzczogc3RyaW5nLCBsb2cgPSB0cnVlLCBzaG93ID0gdHJ1ZSk6IHZvaWQge1xuICAgICAgICBpZiAobG9nKSBsb2dnZXIubG9nKHByb2dyZXNzKTtcbiAgICAgICAgaWYgKHNob3cpIHRoaXMuc2V0UHJvZ3Jlc3NUZXh0KHByb2dyZXNzKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYWRkRmlsZShmaWxlUGF0aDogc3RyaW5nLCBibG9iOiBCbG9iKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGZpbGUgPSB7XG4gICAgICAgICAgICBuYW1lOiBmaWxlUGF0aCxcbiAgICAgICAgICAgIGJsb2IsXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZmlsZXMucHVzaChmaWxlKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgbWFrZUZpbGVOYW1lTm9FeHRlbnNpb24oYnJhbmQgPSBcIm1hdHJpeFwiKTogc3RyaW5nIHtcbiAgICAgICAgLy8gRmlyc3QgdHJ5IHRvIHVzZSB0aGUgcmVhbCBuYW1lIG9mIHRoZSByb29tLCB0aGVuIGEgdHJhbnNsYXRlZCBjb3B5IG9mIGEgZ2VuZXJpYyBuYW1lLFxuICAgICAgICAvLyB0aGVuIGZpbmFsbHkgaGFyZGNvZGVkIGRlZmF1bHQgdG8gZ3VhcmFudGVlIHdlJ2xsIGhhdmUgYSBuYW1lLlxuICAgICAgICBjb25zdCBzYWZlUm9vbU5hbWUgPSBzYW5pdGl6ZUZpbGVuYW1lKHRoaXMucm9vbS5uYW1lID8/IF90KFwiY29tbW9ufHVubmFtZWRfcm9vbVwiKSkudHJpbSgpIHx8IFwiVW5uYW1lZCBSb29tXCI7XG4gICAgICAgIGNvbnN0IHNhZmVEYXRlID0gZm9ybWF0RnVsbERhdGVOb0RheUlTTyhuZXcgRGF0ZSgpKS5yZXBsYWNlKC86L2csIFwiLVwiKTsgLy8gSVNPIGZvcm1hdCBhdXRvbWF0aWNhbGx5IHJlbW92ZXMgYSBsb3Qgb2Ygc3R1ZmYgZm9yIHVzXG4gICAgICAgIGNvbnN0IHNhZmVCcmFuZCA9IHNhbml0aXplRmlsZW5hbWUoYnJhbmQpO1xuICAgICAgICByZXR1cm4gYCR7c2FmZUJyYW5kfSAtICR7c2FmZVJvb21OYW1lfSAtIENoYXQgRXhwb3J0IC0gJHtzYWZlRGF0ZX1gO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBkb3dubG9hZFpJUCgpOiBQcm9taXNlPHN0cmluZyB8IHZvaWQ+IHtcbiAgICAgICAgY29uc3QgZmlsZW5hbWUgPSB0aGlzLmRlc3RpbmF0aW9uRmlsZU5hbWU7XG4gICAgICAgIGNvbnN0IGZpbGVuYW1lV2l0aG91dEV4dCA9IGZpbGVuYW1lLnN1YnN0cmluZygwLCBmaWxlbmFtZS5sYXN0SW5kZXhPZihcIi5cIikpOyAvLyB0YWtlIG9mZiB0aGUgZXh0ZW5zaW9uXG4gICAgICAgIGNvbnN0IHsgZGVmYXVsdDogSlNaaXAgfSA9IGF3YWl0IGltcG9ydChcImpzemlwXCIpO1xuXG4gICAgICAgIGNvbnN0IHppcCA9IG5ldyBKU1ppcCgpO1xuICAgICAgICAvLyBDcmVhdGUgYSB3cml0YWJsZSBzdHJlYW0gdG8gdGhlIGRpcmVjdG9yeVxuICAgICAgICBpZiAoIXRoaXMuY2FuY2VsbGVkKSB0aGlzLnVwZGF0ZVByb2dyZXNzKF90KFwiZXhwb3J0X2NoYXR8Z2VuZXJhdGluZ196aXBcIikpO1xuICAgICAgICBlbHNlIHJldHVybiB0aGlzLmNsZWFuVXAoKTtcblxuICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgdGhpcy5maWxlcykgemlwLmZpbGUoZmlsZW5hbWVXaXRob3V0RXh0ICsgXCIvXCIgKyBmaWxlLm5hbWUsIGZpbGUuYmxvYik7XG5cbiAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHppcC5nZW5lcmF0ZUFzeW5jKHsgdHlwZTogXCJibG9iXCIgfSk7XG4gICAgICAgIHNhdmVBcyhjb250ZW50LCBmaWxlbmFtZVdpdGhvdXRFeHQgKyBcIi56aXBcIik7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGNsZWFuVXAoKTogc3RyaW5nIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIkNsZWFuaW5nIHVwLi4uXCIpO1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImJlZm9yZXVubG9hZFwiLCB0aGlzLm9uQmVmb3JlVW5sb2FkKTtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNhbmNlbEV4cG9ydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIkNhbmNlbGxpbmcgZXhwb3J0Li4uXCIpO1xuICAgICAgICB0aGlzLmNhbmNlbGxlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGRvd25sb2FkUGxhaW5UZXh0KGZpbGVOYW1lOiBzdHJpbmcsIHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBjb25zdCBjb250ZW50ID0gbmV3IEJsb2IoW3RleHRdLCB7IHR5cGU6IFwidGV4dC9wbGFpblwiIH0pO1xuICAgICAgICBzYXZlQXMoY29udGVudCwgZmlsZU5hbWUpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzZXRFdmVudE1ldGFkYXRhKGV2ZW50OiBNYXRyaXhFdmVudCk6IE1hdHJpeEV2ZW50IHtcbiAgICAgICAgY29uc3Qgcm9vbVN0YXRlID0gdGhpcy5yb29tLmN1cnJlbnRTdGF0ZTtcbiAgICAgICAgY29uc3Qgc2VuZGVyID0gZXZlbnQuZ2V0U2VuZGVyKCk7XG4gICAgICAgIGV2ZW50LnNlbmRlciA9ICghIXNlbmRlciAmJiByb29tU3RhdGU/LmdldFNlbnRpbmVsTWVtYmVyKHNlbmRlcikpIHx8IG51bGw7XG4gICAgICAgIGlmIChldmVudC5nZXRUeXBlKCkgPT09IFwibS5yb29tLm1lbWJlclwiKSB7XG4gICAgICAgICAgICBldmVudC50YXJnZXQgPSByb29tU3RhdGU/LmdldFNlbnRpbmVsTWVtYmVyKGV2ZW50LmdldFN0YXRlS2V5KCkhKSA/PyBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBldmVudDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0TGltaXQoKTogbnVtYmVyIHtcbiAgICAgICAgbGV0IGxpbWl0OiBudW1iZXI7XG4gICAgICAgIHN3aXRjaCAodGhpcy5leHBvcnRUeXBlKSB7XG4gICAgICAgICAgICBjYXNlIEV4cG9ydFR5cGUuTGFzdE5NZXNzYWdlczpcbiAgICAgICAgICAgICAgICAvLyB2YWxpZGF0ZWQgaW4gY29uc3RydWN0b3IgdGhhdCBudW1iZXJPZk1lc3NhZ2VzIGlzIGRlZmluZWRcbiAgICAgICAgICAgICAgICAvLyB3aGVuIGV4cG9ydCB0eXBlIGlzIExhc3ROTWVzc2FnZXNcbiAgICAgICAgICAgICAgICBsaW1pdCA9IHRoaXMuZXhwb3J0T3B0aW9ucy5udW1iZXJPZk1lc3NhZ2VzITtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgbGltaXQgPSAxMCAqKiA4O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsaW1pdDtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgYXN5bmMgZ2V0UmVxdWlyZWRFdmVudHMoKTogUHJvbWlzZTxNYXRyaXhFdmVudFtdPiB7XG4gICAgICAgIGNvbnN0IGV2ZW50TWFwcGVyID0gdGhpcy5yb29tLmNsaWVudC5nZXRFdmVudE1hcHBlcigpO1xuXG4gICAgICAgIGxldCBwcmV2VG9rZW46IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgICAgIGxldCBldmVudHM6IE1hdHJpeEV2ZW50W10gPSBbXTtcbiAgICAgICAgaWYgKHRoaXMuZXhwb3J0VHlwZSA9PT0gRXhwb3J0VHlwZS5UaW1lbGluZSkge1xuICAgICAgICAgICAgZXZlbnRzID0gdGhpcy5yb29tLmdldExpdmVUaW1lbGluZSgpLmdldEV2ZW50cygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGxpbWl0ID0gdGhpcy5nZXRMaW1pdCgpO1xuICAgICAgICAgICAgd2hpbGUgKGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXZlbnRzUGVyQ3Jhd2wgPSBNYXRoLm1pbihsaW1pdCwgMTAwMCk7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgdGhpcy5yb29tLmNsaWVudC5jcmVhdGVNZXNzYWdlc1JlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucm9vbS5yb29tSWQsXG4gICAgICAgICAgICAgICAgICAgIHByZXZUb2tlbixcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRzUGVyQ3Jhd2wsXG4gICAgICAgICAgICAgICAgICAgIERpcmVjdGlvbi5CYWNrd2FyZCxcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY2FuY2VsbGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYW5VcCgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHJlcy5jaHVuay5sZW5ndGggPT09IDApIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgbGltaXQgLT0gcmVzLmNodW5rLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG1hdHJpeEV2ZW50czogTWF0cml4RXZlbnRbXSA9IHJlcy5jaHVuay5tYXAoZXZlbnRNYXBwZXIpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBteEV2IG9mIG1hdHJpeEV2ZW50cykge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiAodGhpcy5leHBvcnRPcHRpb25zLnN0YXJ0RGF0ZSAmJiBteEV2LmdldFRzKCkgPCB0aGlzLmV4cG9ydE9wdGlvbnMuc3RhcnREYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vICAgICAvLyBPbmNlIHRoZSBsYXN0IG1lc3NhZ2UgcmVjZWl2ZWQgaXMgb2xkZXIgdGhhbiB0aGUgc3RhcnQgZGF0ZSwgd2UgYnJlYWsgb3V0IG9mIGJvdGggdGhlIGxvb3BzXG4gICAgICAgICAgICAgICAgICAgIC8vICAgICBsaW1pdCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIC8vICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgICAgICBldmVudHMucHVzaChteEV2KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5leHBvcnRUeXBlID09PSBFeHBvcnRUeXBlLkxhc3ROTWVzc2FnZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcyhcbiAgICAgICAgICAgICAgICAgICAgICAgIF90KFwiZXhwb3J0X2NoYXR8ZmV0Y2hlZF9uX2V2ZW50c193aXRoX3RvdGFsXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogZXZlbnRzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbDogdGhpcy5leHBvcnRPcHRpb25zLm51bWJlck9mTWVzc2FnZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVByb2dyZXNzKFxuICAgICAgICAgICAgICAgICAgICAgICAgX3QoXCJleHBvcnRfY2hhdHxmZXRjaGVkX25fZXZlbnRzXCIsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogZXZlbnRzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByZXZUb2tlbiA9IHJlcy5lbmQgPz8gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIFJldmVyc2UgdGhlIGV2ZW50cyBzbyB0aGF0IHdlIHByZXNlcnZlIHRoZSBvcmRlclxuICAgICAgICAgICAgZXZlbnRzLnJldmVyc2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGRlY3J5cHRpb25Qcm9taXNlcyA9IGV2ZW50c1xuICAgICAgICAgICAgLmZpbHRlcigoZXZlbnQpID0+IGV2ZW50LmlzRW5jcnlwdGVkKCkpXG4gICAgICAgICAgICAubWFwKChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJvb20uY2xpZW50LmRlY3J5cHRFdmVudElmTmVlZGVkKGV2ZW50LCB7IGVtaXQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gV2FpdCBmb3IgYWxsIHRoZSBldmVudHMgdG8gZ2V0IGRlY3J5cHRlZC5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoZGVjcnlwdGlvblByb21pc2VzKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV2ZW50cy5sZW5ndGg7IGkrKykgdGhpcy5zZXRFdmVudE1ldGFkYXRhKGV2ZW50c1tpXSk7XG5cbiAgICAgICAgcmV0dXJuIGV2ZW50cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWNyeXB0cyBpZiBuZWNlc3NhcnksIGFuZCBmZXRjaGVzIG1lZGlhIGZyb20gYSBtYXRyaXggZXZlbnRcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBtYXRyaXggZXZlbnQgd2l0aCBtZWRpYSBldmVudCBjb250ZW50XG4gICAgICogQHJlc29sdmVzIHdoZW4gbWVkaWEgaGFzIGJlZW4gZmV0Y2hlZFxuICAgICAqIEB0aHJvd3MgaWYgbWVkaWEgd2FzIHVuYWJsZSB0byBiZSBmZXRjaGVkXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGFzeW5jIGdldE1lZGlhQmxvYihldmVudDogTWF0cml4RXZlbnQpOiBQcm9taXNlPEJsb2I+IHtcbiAgICAgICAgbGV0IGJsb2I6IEJsb2IgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBpc0VuY3J5cHRlZCA9IGV2ZW50LmlzRW5jcnlwdGVkKCk7XG4gICAgICAgICAgICBjb25zdCBjb250ZW50ID0gZXZlbnQuZ2V0Q29udGVudDxNZWRpYUV2ZW50Q29udGVudD4oKTtcbiAgICAgICAgICAgIGNvbnN0IHNob3VsZERlY3J5cHQgPSBpc0VuY3J5cHRlZCAmJiBjb250ZW50Lmhhc093blByb3BlcnR5KFwiZmlsZVwiKSAmJiBldmVudC5nZXRUeXBlKCkgIT09IFwibS5zdGlja2VyXCI7XG4gICAgICAgICAgICBpZiAoc2hvdWxkRGVjcnlwdCkge1xuICAgICAgICAgICAgICAgIGJsb2IgPSBhd2FpdCBkZWNyeXB0RmlsZShjb250ZW50LmZpbGUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtZWRpYSA9IG1lZGlhRnJvbUNvbnRlbnQoY29udGVudCk7XG4gICAgICAgICAgICAgICAgaWYgKCFtZWRpYS5zcmNIdHRwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmZXRjaCB3aXRob3V0IHNyY0h0dHBcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGltYWdlID0gYXdhaXQgZmV0Y2gobWVkaWEuc3JjSHR0cCk7XG4gICAgICAgICAgICAgICAgYmxvYiA9IGF3YWl0IGltYWdlLmJsb2IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiRXJyb3IgZGVjcnlwdGluZyBtZWRpYVwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWJsb2IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBmZXRjaCBmaWxlXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBibG9iO1xuICAgIH1cblxuICAgIHB1YmxpYyBzcGxpdEZpbGVOYW1lKGZpbGU6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICAgICAgY29uc3QgbGFzdERvdCA9IGZpbGUubGFzdEluZGV4T2YoXCIuXCIpO1xuICAgICAgICBpZiAobGFzdERvdCA9PT0gLTEpIHJldHVybiBbZmlsZSwgXCJcIl07XG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gZmlsZS5zbGljZSgwLCBsYXN0RG90KTtcbiAgICAgICAgY29uc3QgZXh0ID0gZmlsZS5zbGljZShsYXN0RG90ICsgMSk7XG4gICAgICAgIHJldHVybiBbZmlsZU5hbWUsIFwiLlwiICsgZXh0XTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RmlsZVBhdGgoZXZlbnQ6IE1hdHJpeEV2ZW50KTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgbWVkaWFUeXBlID0gZXZlbnQuZ2V0Q29udGVudCgpLm1zZ3R5cGU7XG4gICAgICAgIGxldCBmaWxlRGlyZWN0b3J5OiBzdHJpbmc7XG4gICAgICAgIHN3aXRjaCAobWVkaWFUeXBlKSB7XG4gICAgICAgICAgICBjYXNlIFwibS5pbWFnZVwiOlxuICAgICAgICAgICAgICAgIGZpbGVEaXJlY3RvcnkgPSBcImltYWdlc1wiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIm0udmlkZW9cIjpcbiAgICAgICAgICAgICAgICBmaWxlRGlyZWN0b3J5ID0gXCJ2aWRlb3NcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJtLmF1ZGlvXCI6XG4gICAgICAgICAgICAgICAgZmlsZURpcmVjdG9yeSA9IFwiYXVkaW9cIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgZmlsZURpcmVjdG9yeSA9IGV2ZW50LmdldFR5cGUoKSA9PT0gXCJtLnN0aWNrZXJcIiA/IFwic3RpY2tlcnNcIiA6IFwiZmlsZXNcIjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaWxlRGF0ZSA9IGZvcm1hdEZ1bGxEYXRlTm9EYXkobmV3IERhdGUoZXZlbnQuZ2V0VHMoKSkpO1xuICAgICAgICBsZXQgW2ZpbGVOYW1lLCBmaWxlRXh0XSA9IHRoaXMuc3BsaXRGaWxlTmFtZShldmVudC5nZXRDb250ZW50KCkuYm9keSk7XG5cbiAgICAgICAgaWYgKGV2ZW50LmdldFR5cGUoKSA9PT0gXCJtLnN0aWNrZXJcIikgZmlsZUV4dCA9IFwiLnBuZ1wiO1xuICAgICAgICBpZiAoaXNWb2ljZU1lc3NhZ2UoZXZlbnQpKSBmaWxlRXh0ID0gXCIub2dnXCI7XG5cbiAgICAgICAgcmV0dXJuIGZpbGVEaXJlY3RvcnkgKyBcIi9cIiArIGZpbGVOYW1lICsgXCItXCIgKyBmaWxlRGF0ZSArIGZpbGVFeHQ7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzUmVwbHkoZXZlbnQ6IE1hdHJpeEV2ZW50KTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGlzRW5jcnlwdGVkID0gZXZlbnQuaXNFbmNyeXB0ZWQoKTtcbiAgICAgICAgLy8gSWYgZW5jcnlwdGVkLCBpbl9yZXBseV90byBsaWVzIGluIGV2ZW50LmV2ZW50LmNvbnRlbnRcbiAgICAgICAgY29uc3QgY29udGVudCA9IGlzRW5jcnlwdGVkID8gZXZlbnQuZXZlbnQuY29udGVudCEgOiBldmVudC5nZXRDb250ZW50KCk7XG4gICAgICAgIGNvbnN0IHJlbGF0ZXNUbyA9IGNvbnRlbnRbXCJtLnJlbGF0ZXNfdG9cIl07XG4gICAgICAgIHJldHVybiAhIShyZWxhdGVzVG8gJiYgcmVsYXRlc1RvW1wibS5pbl9yZXBseV90b1wiXSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGlzQXR0YWNobWVudChteEV2OiBNYXRyaXhFdmVudCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBhdHRhY2htZW50VHlwZXMgPSBbXCJtLnN0aWNrZXJcIiwgXCJtLmltYWdlXCIsIFwibS5maWxlXCIsIFwibS52aWRlb1wiLCBcIm0uYXVkaW9cIl07XG4gICAgICAgIHJldHVybiBteEV2LmdldFR5cGUoKSA9PT0gYXR0YWNobWVudFR5cGVzWzBdIHx8IGF0dGFjaG1lbnRUeXBlcy5pbmNsdWRlcyhteEV2LmdldENvbnRlbnQoKS5tc2d0eXBlISk7XG4gICAgfVxuXG4gICAgcHVibGljIGFic3RyYWN0IGV4cG9ydCgpOiBQcm9taXNlPHZvaWQ+O1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVFBLElBQUFBLE9BQUEsR0FBQUMsT0FB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