UNPKG

matrix-react-sdk

Version:
177 lines (161 loc) 20.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.Media = void 0; exports.mediaFromContent = mediaFromContent; exports.mediaFromMxc = mediaFromMxc; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrix = require("matrix-js-sdk/src/matrix"); var _MatrixClientPeg = require("../MatrixClientPeg"); var _IMediaEventContent = require("./models/IMediaEventContent"); var _languageHandler = require("../languageHandler"); /* * Copyright 2024 New Vector Ltd. * Copyright 2021 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. */ // Populate this class with the details of your customisations when copying it. // Implementation note: The Media class must complete the contract as shown here, though // the constructor can be whatever is relevant to your implementation. The mediaForX // functions below create an instance of the Media class and are used throughout the // project. /** * A media object is a representation of a "source media" and an optional * "thumbnail media", derived from event contents or external sources. */ class Media { // Per above, this constructor signature can be whatever is helpful for you. constructor(prepared, client) { (0, _defineProperty2.default)(this, "client", void 0); this.prepared = prepared; this.client = client ?? _MatrixClientPeg.MatrixClientPeg.safeGet(); if (!this.client) { throw new Error("No possible MatrixClient for media resolution. Please provide one or log in."); } } /** * True if the media appears to be encrypted. Actual file contents may vary. */ get isEncrypted() { return !!this.prepared.file; } /** * The MXC URI of the source media. */ get srcMxc() { return this.prepared.mxc; } /** * The MXC URI of the thumbnail media, if a thumbnail is recorded. Null/undefined * otherwise. */ get thumbnailMxc() { return this.prepared.thumbnail?.mxc; } /** * Whether or not a thumbnail is recorded for this media. */ get hasThumbnail() { return !!this.thumbnailMxc; } /** * The HTTP URL for the source media. */ get srcHttp() { // eslint-disable-next-line no-restricted-properties return this.client.mxcUrlToHttp(this.srcMxc, undefined, undefined, undefined, false, true) || null; } /** * The HTTP URL for the thumbnail media (without any specified width, height, etc). Null/undefined * if no thumbnail media recorded. */ get thumbnailHttp() { if (!this.hasThumbnail) return null; // eslint-disable-next-line no-restricted-properties return this.client.mxcUrlToHttp(this.thumbnailMxc, undefined, undefined, undefined, false, true); } /** * Gets the HTTP URL for the thumbnail media with the requested characteristics, if a thumbnail * is recorded for this media. Returns null/undefined otherwise. * @param {number} width The desired width of the thumbnail. * @param {number} height The desired height of the thumbnail. * @param {"scale"|"crop"} mode The desired thumbnailing mode. Defaults to scale. * @returns {string} The HTTP URL which points to the thumbnail. */ getThumbnailHttp(width, height, mode = "scale") { if (!this.hasThumbnail) return null; // scale using the device pixel ratio to keep images clear width = Math.floor(width * window.devicePixelRatio); height = Math.floor(height * window.devicePixelRatio); // eslint-disable-next-line no-restricted-properties return this.client.mxcUrlToHttp(this.thumbnailMxc, width, height, mode, false, true); } /** * Gets the HTTP URL for a thumbnail of the source media with the requested characteristics. * @param {number} width The desired width of the thumbnail. * @param {number} height The desired height of the thumbnail. * @param {"scale"|"crop"} mode The desired thumbnailing mode. Defaults to scale. * @returns {string} The HTTP URL which points to the thumbnail. */ getThumbnailOfSourceHttp(width, height, mode = "scale") { // scale using the device pixel ratio to keep images clear width = Math.floor(width * window.devicePixelRatio); height = Math.floor(height * window.devicePixelRatio); // eslint-disable-next-line no-restricted-properties return this.client.mxcUrlToHttp(this.srcMxc, width, height, mode, false, true); } /** * Creates a square thumbnail of the media. If the media has a thumbnail recorded, that MXC will * be used, otherwise the source media will be used. * @param {number} dim The desired width and height. * @returns {string} An HTTP URL for the thumbnail. */ getSquareThumbnailHttp(dim) { dim = Math.floor(dim * window.devicePixelRatio); // scale using the device pixel ratio to keep images clear if (this.hasThumbnail) { return this.getThumbnailHttp(dim, dim, "crop"); } return this.getThumbnailOfSourceHttp(dim, dim, "crop"); } /** * Downloads the source media. * @returns {Promise<Response>} Resolves to the server's response for chaining. */ async downloadSource() { const src = this.srcHttp; if (!src) { throw new _languageHandler.UserFriendlyError("error|download_media"); } const res = await fetch(src); if (!res.ok) { throw (0, _matrix.parseErrorResponse)(res, await res.text()); } return res; } } /** * Creates a media object from event content. * @param {MediaEventContent} content The event content. * @param {MatrixClient} client? Optional client to use. * @returns {Media} The media object. */ exports.Media = Media; function mediaFromContent(content, client) { return new Media((0, _IMediaEventContent.prepEventContentAsMedia)(content), client); } /** * Creates a media object from an MXC URI. * @param {string} mxc The MXC URI. * @param {MatrixClient} client? Optional client to use. * @returns {Media} The media object. */ function mediaFromMxc(mxc, client) { return mediaFromContent({ url: mxc }, client); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9NYXRyaXhDbGllbnRQZWciLCJfSU1lZGlhRXZlbnRDb250ZW50IiwiX2xhbmd1YWdlSGFuZGxlciIsIk1lZGlhIiwiY29uc3RydWN0b3IiLCJwcmVwYXJlZCIsImNsaWVudCIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsIkVycm9yIiwiaXNFbmNyeXB0ZWQiLCJmaWxlIiwic3JjTXhjIiwibXhjIiwidGh1bWJuYWlsTXhjIiwidGh1bWJuYWlsIiwiaGFzVGh1bWJuYWlsIiwic3JjSHR0cCIsIm14Y1VybFRvSHR0cCIsInVuZGVmaW5lZCIsInRodW1ibmFpbEh0dHAiLCJnZXRUaHVtYm5haWxIdHRwIiwid2lkdGgiLCJoZWlnaHQiLCJtb2RlIiwiTWF0aCIsImZsb29yIiwid2luZG93IiwiZGV2aWNlUGl4ZWxSYXRpbyIsImdldFRodW1ibmFpbE9mU291cmNlSHR0cCIsImdldFNxdWFyZVRodW1ibmFpbEh0dHAiLCJkaW0iLCJkb3dubG9hZFNvdXJjZSIsInNyYyIsIlVzZXJGcmllbmRseUVycm9yIiwicmVzIiwiZmV0Y2giLCJvayIsInBhcnNlRXJyb3JSZXNwb25zZSIsInRleHQiLCJleHBvcnRzIiwibWVkaWFGcm9tQ29udGVudCIsImNvbnRlbnQiLCJwcmVwRXZlbnRDb250ZW50QXNNZWRpYSIsIm1lZGlhRnJvbU14YyIsInVybCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jdXN0b21pc2F0aW9ucy9NZWRpYS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG4gKiBDb3B5cmlnaHQgMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuICpcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuICogUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiAqL1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnQsIHBhcnNlRXJyb3JSZXNwb25zZSwgUmVzaXplTWV0aG9kIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgTWVkaWFFdmVudENvbnRlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvdHlwZXNcIjtcbmltcG9ydCB7IE9wdGlvbmFsIH0gZnJvbSBcIm1hdHJpeC1ldmVudHMtc2RrXCI7XG5cbmltcG9ydCB7IE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCB7IElQcmVwYXJlZE1lZGlhLCBwcmVwRXZlbnRDb250ZW50QXNNZWRpYSB9IGZyb20gXCIuL21vZGVscy9JTWVkaWFFdmVudENvbnRlbnRcIjtcbmltcG9ydCB7IFVzZXJGcmllbmRseUVycm9yIH0gZnJvbSBcIi4uL2xhbmd1YWdlSGFuZGxlclwiO1xuXG4vLyBQb3B1bGF0ZSB0aGlzIGNsYXNzIHdpdGggdGhlIGRldGFpbHMgb2YgeW91ciBjdXN0b21pc2F0aW9ucyB3aGVuIGNvcHlpbmcgaXQuXG5cbi8vIEltcGxlbWVudGF0aW9uIG5vdGU6IFRoZSBNZWRpYSBjbGFzcyBtdXN0IGNvbXBsZXRlIHRoZSBjb250cmFjdCBhcyBzaG93biBoZXJlLCB0aG91Z2hcbi8vIHRoZSBjb25zdHJ1Y3RvciBjYW4gYmUgd2hhdGV2ZXIgaXMgcmVsZXZhbnQgdG8geW91ciBpbXBsZW1lbnRhdGlvbi4gVGhlIG1lZGlhRm9yWFxuLy8gZnVuY3Rpb25zIGJlbG93IGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiB0aGUgTWVkaWEgY2xhc3MgYW5kIGFyZSB1c2VkIHRocm91Z2hvdXQgdGhlXG4vLyBwcm9qZWN0LlxuXG4vKipcbiAqIEEgbWVkaWEgb2JqZWN0IGlzIGEgcmVwcmVzZW50YXRpb24gb2YgYSBcInNvdXJjZSBtZWRpYVwiIGFuZCBhbiBvcHRpb25hbFxuICogXCJ0aHVtYm5haWwgbWVkaWFcIiwgZGVyaXZlZCBmcm9tIGV2ZW50IGNvbnRlbnRzIG9yIGV4dGVybmFsIHNvdXJjZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBNZWRpYSB7XG4gICAgcHJpdmF0ZSBjbGllbnQ6IE1hdHJpeENsaWVudDtcblxuICAgIC8vIFBlciBhYm92ZSwgdGhpcyBjb25zdHJ1Y3RvciBzaWduYXR1cmUgY2FuIGJlIHdoYXRldmVyIGlzIGhlbHBmdWwgZm9yIHlvdS5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgcHJlcGFyZWQ6IElQcmVwYXJlZE1lZGlhLFxuICAgICAgICBjbGllbnQ/OiBNYXRyaXhDbGllbnQsXG4gICAgKSB7XG4gICAgICAgIHRoaXMuY2xpZW50ID0gY2xpZW50ID8/IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG4gICAgICAgIGlmICghdGhpcy5jbGllbnQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIHBvc3NpYmxlIE1hdHJpeENsaWVudCBmb3IgbWVkaWEgcmVzb2x1dGlvbi4gUGxlYXNlIHByb3ZpZGUgb25lIG9yIGxvZyBpbi5cIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcnVlIGlmIHRoZSBtZWRpYSBhcHBlYXJzIHRvIGJlIGVuY3J5cHRlZC4gQWN0dWFsIGZpbGUgY29udGVudHMgbWF5IHZhcnkuXG4gICAgICovXG4gICAgcHVibGljIGdldCBpc0VuY3J5cHRlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5wcmVwYXJlZC5maWxlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBNWEMgVVJJIG9mIHRoZSBzb3VyY2UgbWVkaWEuXG4gICAgICovXG4gICAgcHVibGljIGdldCBzcmNNeGMoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJlcGFyZWQubXhjO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBNWEMgVVJJIG9mIHRoZSB0aHVtYm5haWwgbWVkaWEsIGlmIGEgdGh1bWJuYWlsIGlzIHJlY29yZGVkLiBOdWxsL3VuZGVmaW5lZFxuICAgICAqIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHRodW1ibmFpbE14YygpOiBPcHRpb25hbDxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucHJlcGFyZWQudGh1bWJuYWlsPy5teGM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciBvciBub3QgYSB0aHVtYm5haWwgaXMgcmVjb3JkZWQgZm9yIHRoaXMgbWVkaWEuXG4gICAgICovXG4gICAgcHVibGljIGdldCBoYXNUaHVtYm5haWwoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMudGh1bWJuYWlsTXhjO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBIVFRQIFVSTCBmb3IgdGhlIHNvdXJjZSBtZWRpYS5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHNyY0h0dHAoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLXByb3BlcnRpZXNcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50Lm14Y1VybFRvSHR0cCh0aGlzLnNyY014YywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgZmFsc2UsIHRydWUpIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIEhUVFAgVVJMIGZvciB0aGUgdGh1bWJuYWlsIG1lZGlhICh3aXRob3V0IGFueSBzcGVjaWZpZWQgd2lkdGgsIGhlaWdodCwgZXRjKS4gTnVsbC91bmRlZmluZWRcbiAgICAgKiBpZiBubyB0aHVtYm5haWwgbWVkaWEgcmVjb3JkZWQuXG4gICAgICovXG4gICAgcHVibGljIGdldCB0aHVtYm5haWxIdHRwKCk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICBpZiAoIXRoaXMuaGFzVGh1bWJuYWlsKSByZXR1cm4gbnVsbDtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtcHJvcGVydGllc1xuICAgICAgICByZXR1cm4gdGhpcy5jbGllbnQubXhjVXJsVG9IdHRwKHRoaXMudGh1bWJuYWlsTXhjISwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgZmFsc2UsIHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIEhUVFAgVVJMIGZvciB0aGUgdGh1bWJuYWlsIG1lZGlhIHdpdGggdGhlIHJlcXVlc3RlZCBjaGFyYWN0ZXJpc3RpY3MsIGlmIGEgdGh1bWJuYWlsXG4gICAgICogaXMgcmVjb3JkZWQgZm9yIHRoaXMgbWVkaWEuIFJldHVybnMgbnVsbC91bmRlZmluZWQgb3RoZXJ3aXNlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCBUaGUgZGVzaXJlZCB3aWR0aCBvZiB0aGUgdGh1bWJuYWlsLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgVGhlIGRlc2lyZWQgaGVpZ2h0IG9mIHRoZSB0aHVtYm5haWwuXG4gICAgICogQHBhcmFtIHtcInNjYWxlXCJ8XCJjcm9wXCJ9IG1vZGUgVGhlIGRlc2lyZWQgdGh1bWJuYWlsaW5nIG1vZGUuIERlZmF1bHRzIHRvIHNjYWxlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBIVFRQIFVSTCB3aGljaCBwb2ludHMgdG8gdGhlIHRodW1ibmFpbC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VGh1bWJuYWlsSHR0cCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgbW9kZTogUmVzaXplTWV0aG9kID0gXCJzY2FsZVwiKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIGlmICghdGhpcy5oYXNUaHVtYm5haWwpIHJldHVybiBudWxsO1xuICAgICAgICAvLyBzY2FsZSB1c2luZyB0aGUgZGV2aWNlIHBpeGVsIHJhdGlvIHRvIGtlZXAgaW1hZ2VzIGNsZWFyXG4gICAgICAgIHdpZHRoID0gTWF0aC5mbG9vcih3aWR0aCAqIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvKTtcbiAgICAgICAgaGVpZ2h0ID0gTWF0aC5mbG9vcihoZWlnaHQgKiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLXByb3BlcnRpZXNcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xpZW50Lm14Y1VybFRvSHR0cCh0aGlzLnRodW1ibmFpbE14YyEsIHdpZHRoLCBoZWlnaHQsIG1vZGUsIGZhbHNlLCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBIVFRQIFVSTCBmb3IgYSB0aHVtYm5haWwgb2YgdGhlIHNvdXJjZSBtZWRpYSB3aXRoIHRoZSByZXF1ZXN0ZWQgY2hhcmFjdGVyaXN0aWNzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCBUaGUgZGVzaXJlZCB3aWR0aCBvZiB0aGUgdGh1bWJuYWlsLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgVGhlIGRlc2lyZWQgaGVpZ2h0IG9mIHRoZSB0aHVtYm5haWwuXG4gICAgICogQHBhcmFtIHtcInNjYWxlXCJ8XCJjcm9wXCJ9IG1vZGUgVGhlIGRlc2lyZWQgdGh1bWJuYWlsaW5nIG1vZGUuIERlZmF1bHRzIHRvIHNjYWxlLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBIVFRQIFVSTCB3aGljaCBwb2ludHMgdG8gdGhlIHRodW1ibmFpbC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0VGh1bWJuYWlsT2ZTb3VyY2VIdHRwKHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyLCBtb2RlOiBSZXNpemVNZXRob2QgPSBcInNjYWxlXCIpOiBzdHJpbmcgfCBudWxsIHtcbiAgICAgICAgLy8gc2NhbGUgdXNpbmcgdGhlIGRldmljZSBwaXhlbCByYXRpbyB0byBrZWVwIGltYWdlcyBjbGVhclxuICAgICAgICB3aWR0aCA9IE1hdGguZmxvb3Iod2lkdGggKiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyk7XG4gICAgICAgIGhlaWdodCA9IE1hdGguZmxvb3IoaGVpZ2h0ICogd2luZG93LmRldmljZVBpeGVsUmF0aW8pO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1wcm9wZXJ0aWVzXG4gICAgICAgIHJldHVybiB0aGlzLmNsaWVudC5teGNVcmxUb0h0dHAodGhpcy5zcmNNeGMsIHdpZHRoLCBoZWlnaHQsIG1vZGUsIGZhbHNlLCB0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgc3F1YXJlIHRodW1ibmFpbCBvZiB0aGUgbWVkaWEuIElmIHRoZSBtZWRpYSBoYXMgYSB0aHVtYm5haWwgcmVjb3JkZWQsIHRoYXQgTVhDIHdpbGxcbiAgICAgKiBiZSB1c2VkLCBvdGhlcndpc2UgdGhlIHNvdXJjZSBtZWRpYSB3aWxsIGJlIHVzZWQuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGRpbSBUaGUgZGVzaXJlZCB3aWR0aCBhbmQgaGVpZ2h0LlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEFuIEhUVFAgVVJMIGZvciB0aGUgdGh1bWJuYWlsLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTcXVhcmVUaHVtYm5haWxIdHRwKGRpbTogbnVtYmVyKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgICAgIGRpbSA9IE1hdGguZmxvb3IoZGltICogd2luZG93LmRldmljZVBpeGVsUmF0aW8pOyAvLyBzY2FsZSB1c2luZyB0aGUgZGV2aWNlIHBpeGVsIHJhdGlvIHRvIGtlZXAgaW1hZ2VzIGNsZWFyXG4gICAgICAgIGlmICh0aGlzLmhhc1RodW1ibmFpbCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VGh1bWJuYWlsSHR0cChkaW0sIGRpbSwgXCJjcm9wXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmdldFRodW1ibmFpbE9mU291cmNlSHR0cChkaW0sIGRpbSwgXCJjcm9wXCIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERvd25sb2FkcyB0aGUgc291cmNlIG1lZGlhLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPFJlc3BvbnNlPn0gUmVzb2x2ZXMgdG8gdGhlIHNlcnZlcidzIHJlc3BvbnNlIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZG93bmxvYWRTb3VyY2UoKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICAgICAgICBjb25zdCBzcmMgPSB0aGlzLnNyY0h0dHA7XG4gICAgICAgIGlmICghc3JjKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVXNlckZyaWVuZGx5RXJyb3IoXCJlcnJvcnxkb3dubG9hZF9tZWRpYVwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaChzcmMpO1xuICAgICAgICBpZiAoIXJlcy5vaykge1xuICAgICAgICAgICAgdGhyb3cgcGFyc2VFcnJvclJlc3BvbnNlKHJlcywgYXdhaXQgcmVzLnRleHQoKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1lZGlhIG9iamVjdCBmcm9tIGV2ZW50IGNvbnRlbnQuXG4gKiBAcGFyYW0ge01lZGlhRXZlbnRDb250ZW50fSBjb250ZW50IFRoZSBldmVudCBjb250ZW50LlxuICogQHBhcmFtIHtNYXRyaXhDbGllbnR9IGNsaWVudD8gT3B0aW9uYWwgY2xpZW50IHRvIHVzZS5cbiAqIEByZXR1cm5zIHtNZWRpYX0gVGhlIG1lZGlhIG9iamVjdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lZGlhRnJvbUNvbnRlbnQoY29udGVudDogUGFydGlhbDxNZWRpYUV2ZW50Q29udGVudD4sIGNsaWVudD86IE1hdHJpeENsaWVudCk6IE1lZGlhIHtcbiAgICByZXR1cm4gbmV3IE1lZGlhKHByZXBFdmVudENvbnRlbnRBc01lZGlhKGNvbnRlbnQpLCBjbGllbnQpO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBtZWRpYSBvYmplY3QgZnJvbSBhbiBNWEMgVVJJLlxuICogQHBhcmFtIHtzdHJpbmd9IG14YyBUaGUgTVhDIFVSSS5cbiAqIEBwYXJhbSB7TWF0cml4Q2xpZW50fSBjbGllbnQ/IE9wdGlvbmFsIGNsaWVudCB0byB1c2UuXG4gKiBAcmV0dXJucyB7TWVkaWF9IFRoZSBtZWRpYSBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZWRpYUZyb21NeGMobXhjPzogc3RyaW5nLCBjbGllbnQ/OiBNYXRyaXhDbGllbnQpOiBNZWRpYSB7XG4gICAgcmV0dXJuIG1lZGlhRnJvbUNvbnRlbnQoeyB1cmw6IG14YyB9LCBjbGllbnQpO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBUUEsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBSUEsSUFBQUMsZ0JBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLG1CQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxnQkFBQSxHQUFBSCxPQUFBO0FBZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBVUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDTyxNQUFNSSxLQUFLLENBQUM7RUFHZjtFQUNPQyxXQUFXQSxDQUNOQyxRQUF3QixFQUNoQ0MsTUFBcUIsRUFDdkI7SUFBQSxJQUFBQyxnQkFBQSxDQUFBQyxPQUFBO0lBQUEsS0FGVUgsUUFBd0IsR0FBeEJBLFFBQXdCO0lBR2hDLElBQUksQ0FBQ0MsTUFBTSxHQUFHQSxNQUFNLElBQUlHLGdDQUFlLENBQUNDLE9BQU8sQ0FBQyxDQUFDO0lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUNKLE1BQU0sRUFBRTtNQUNkLE1BQU0sSUFBSUssS0FBSyxDQUFDLDhFQUE4RSxDQUFDO0lBQ25HO0VBQ0o7O0VBRUE7QUFDSjtBQUNBO0VBQ0ksSUFBV0MsV0FBV0EsQ0FBQSxFQUFZO0lB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