"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __typeError = (msg) => { throw TypeError(msg); }; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method); // src/index.ts var src_exports = {}; __export(src_exports, { AF_NIGHTCORE_RATE: () => import_equalizer3.AF_NIGHTCORE_RATE, AF_VAPORWAVE_RATE: () => import_equalizer3.AF_VAPORWAVE_RATE, AFilterGraph: () => AFilterGraph, AsyncQueue: () => AsyncQueue, AsyncQueueEntry: () => AsyncQueueEntry, AudioFilters: () => AudioFilters, AudioPlayer: () => import_discord_voip6.AudioPlayer, BASS_EQ_BANDS: () => import_equalizer3.BASS_EQ_BANDS, BaseExtractor: () => BaseExtractor, BiquadFilterType: () => import_equalizer3.FilterType, Context: () => Context, DependencyReportGenerator: () => DependencyReportGenerator, DiscordPlayerQueryResultCache: () => DiscordPlayerQueryResultCache, EqualizerConfigurationPreset: () => EqualizerConfigurationPreset, ExtractorExecutionContext: () => ExtractorExecutionContext, FFMPEG_ARGS_PIPED: () => FFMPEG_ARGS_PIPED, FFMPEG_ARGS_STRING: () => FFMPEG_ARGS_STRING, FFMPEG_SRATE_REGEX: () => FFMPEG_SRATE_REGEX, FFmpegFilterer: () => FFmpegFilterer, FiltersChain: () => import_equalizer3.FiltersChain, GuildNodeManager: () => GuildNodeManager, GuildQueue: () => GuildQueue5, GuildQueueAudioFilters: () => GuildQueueAudioFilters, GuildQueueEvent: () => GuildQueueEvent, GuildQueueHistory: () => GuildQueueHistory, GuildQueuePlayerNode: () => GuildQueuePlayerNode, GuildQueueStatistics: () => GuildQueueStatistics, InterceptedStream: () => InterceptedStream, LrcLib: () => LrcLib, PCMAudioFilters: () => import_equalizer3.AudioFilters, Player: () => Player, PlayerEvent: () => PlayerEvent, PlayerEventsEmitter: () => PlayerEventsEmitter, PlayerStreamInterceptor: () => PlayerStreamInterceptor, Playlist: () => Playlist, Q_BUTTERWORTH: () => import_equalizer3.Q_BUTTERWORTH, QueryCache: () => QueryCache, QueryResolver: () => QueryResolver, QueryType: () => QueryType, QueueRepeatMode: () => QueueRepeatMode, SearchResult: () => SearchResult, SequentialBucket: () => SequentialBucket, SerializedType: () => SerializedType, StreamDispatcher: () => StreamDispatcher, StreamType: () => import_discord_voip6.StreamType, Track: () => Track, TrackSkipReason: () => TrackSkipReason, TypeUtil: () => TypeUtil, Util: () => Util, VALIDATE_QUEUE_CAP: () => VALIDATE_QUEUE_CAP, VoiceUtils: () => VoiceUtils, VolumeTransformer: () => import_equalizer3.VolumeTransformer, createAudioPlayer: () => import_discord_voip6.createAudioPlayer, createAudioResource: () => import_discord_voip6.createAudioResource, createContext: () => createContext, createErisCompat: () => createErisCompat, createFFmpegStream: () => createFFmpegStream, createOceanicCompat: () => createOceanicCompat, decode: () => decode, deserialize: () => deserialize, encode: () => encode, getVoiceConnection: () => import_discord_voip6.getVoiceConnection, getVoiceConnections: () => import_discord_voip6.getVoiceConnections, isErisProxy: () => isErisProxy, isOceanicProxy: () => isOceanicProxy, joinVoiceChannel: () => import_discord_voip6.joinVoiceChannel, onAfterCreateStream: () => onAfterCreateStream, onBeforeCreateStream: () => onBeforeCreateStream, onStreamExtracted: () => onStreamExtracted, serialize: () => serialize, tryIntoThumbnailString: () => tryIntoThumbnailString, useContext: () => useContext, useHistory: () => useHistory, useMainPlayer: () => useMainPlayer, useMetadata: () => useMetadata, usePlayer: () => usePlayer, useQueue: () => useQueue, useTimeline: () => useTimeline, useVolume: () => useVolume, version: () => version }); module.exports = __toCommonJS(src_exports); // src/compat/createErisCompat.ts var import_v10 = require("discord-api-types/v10"); // src/compat/common.ts var DiscordPlayerClientSymbol = Symbol("DiscordPlayerClient"); function createCompatClient(client, provider) { Reflect.set(client, DiscordPlayerClientSymbol, provider); return { provider, client }; } __name(createCompatClient, "createCompatClient"); function isClientProxy(client) { return Reflect.get(client, DiscordPlayerClientSymbol) != null; } __name(isClientProxy, "isClientProxy"); function getCompatName(client) { return Reflect.get(client, DiscordPlayerClientSymbol) ?? null; } __name(getCompatName, "getCompatName"); function isErisProxy(client) { return getCompatName(client) === "Eris"; } __name(isErisProxy, "isErisProxy"); function isOceanicProxy(client) { return getCompatName(client) === "Oceanic"; } __name(isOceanicProxy, "isOceanicProxy"); // src/utils/Util.ts var import_promises = require("timers/promises"); // src/fabric/Track.ts var import_discord = require("discord.js"); // src/errors/index.ts var _DiscordPlayerError = class _DiscordPlayerError extends Error { constructor(code, message) { super(message); __publicField(this, "code"); __publicField(this, "timestamp", Date.now()); this.name = this.constructor.name; this.code = code; if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } toJSON() { return { name: this.constructor.name, code: this.code, message: this.message, timestamp: this.timestamp }; } }; __name(_DiscordPlayerError, "DiscordPlayerError"); var DiscordPlayerError = _DiscordPlayerError; var _OutOfSpaceError = class _OutOfSpaceError extends DiscordPlayerError { constructor(target, capacity, total) { super( ErrorCodes.ERR_OUT_OF_SPACE, `Max capacity reached for ${target} (Capacity ${capacity}/Total ${total})` ); } }; __name(_OutOfSpaceError, "OutOfSpaceError"); var OutOfSpaceError = _OutOfSpaceError; var _InvalidArgTypeError = class _InvalidArgTypeError extends DiscordPlayerError { constructor(target, expectation, found) { super( ErrorCodes.ERR_INVALID_ARG_TYPE, `Expected ${target} to be "${expectation}", received "${found}"` ); } }; __name(_InvalidArgTypeError, "InvalidArgTypeError"); var InvalidArgTypeError = _InvalidArgTypeError; var _NoResultError = class _NoResultError extends DiscordPlayerError { constructor(message) { super(ErrorCodes.ERR_NO_RESULT, message); } }; __name(_NoResultError, "NoResultError"); var NoResultError = _NoResultError; var _NotImplementedError = class _NotImplementedError extends DiscordPlayerError { constructor(target) { super(ErrorCodes.ERR_NOT_IMPLEMENTED, `${target} is not yet implemented`); } }; __name(_NotImplementedError, "NotImplementedError"); var NotImplementedError = _NotImplementedError; var _NotExistingError = class _NotExistingError extends DiscordPlayerError { constructor(target) { super(ErrorCodes.ERR_NOT_EXISTING, `${target} does not exist`); } }; __name(_NotExistingError, "NotExistingError"); var NotExistingError = _NotExistingError; var _OutOfRangeError = class _OutOfRangeError extends DiscordPlayerError { constructor(target, value, minimum, maximum) { super( ErrorCodes.ERR_OUT_OF_RANGE, `${target} is out of range (Expected minimum ${minimum} and maximum ${maximum}, got ${value})` ); } }; __name(_OutOfRangeError, "OutOfRangeError"); var OutOfRangeError = _OutOfRangeError; var _NoVoiceConnectionError = class _NoVoiceConnectionError extends DiscordPlayerError { constructor(message) { super( ErrorCodes.ERR_NO_VOICE_CONNECTION, message || "No voice connection available, maybe connect to a voice channel first?" ); } }; __name(_NoVoiceConnectionError, "NoVoiceConnectionError"); var NoVoiceConnectionError = _NoVoiceConnectionError; var _VoiceConnectionDestroyedError = class _VoiceConnectionDestroyedError extends DiscordPlayerError { constructor() { super( ErrorCodes.ERR_VOICE_CONNECTION_DESTROYED, "Cannot use destroyed voice connection" ); } }; __name(_VoiceConnectionDestroyedError, "VoiceConnectionDestroyedError"); var VoiceConnectionDestroyedError = _VoiceConnectionDestroyedError; var _NoVoiceChannelError = class _NoVoiceChannelError extends DiscordPlayerError { constructor() { super(ErrorCodes.ERR_NO_VOICE_CHANNEL, "Could not get the voice channel"); } }; __name(_NoVoiceChannelError, "NoVoiceChannelError"); var NoVoiceChannelError = _NoVoiceChannelError; var _NoAudioResourceError = class _NoAudioResourceError extends DiscordPlayerError { constructor(message) { super( ErrorCodes.ERR_NO_AUDIO_RESOURCE, message || "Expected an audio resource" ); } }; __name(_NoAudioResourceError, "NoAudioResourceError"); var NoAudioResourceError = _NoAudioResourceError; var _NoGuildQueueError = class _NoGuildQueueError extends DiscordPlayerError { constructor(message) { super(ErrorCodes.ERR_NO_GUILD_QUEUE, message || "Expected a guild queue"); } }; __name(_NoGuildQueueError, "NoGuildQueueError"); var NoGuildQueueError = _NoGuildQueueError; var _NoGuildError = class _NoGuildError extends DiscordPlayerError { constructor(message) { super(ErrorCodes.ERR_NO_GUILD, message || "Expected a guild"); } }; __name(_NoGuildError, "NoGuildError"); var NoGuildError = _NoGuildError; var _InfoRequiredError = class _InfoRequiredError extends DiscordPlayerError { constructor(target, actual) { super( ErrorCodes.ERR_INFO_REQUIRED, `Expected ${target}, found "${actual}"` ); } }; __name(_InfoRequiredError, "InfoRequiredError"); var InfoRequiredError = _InfoRequiredError; var _SerializationError = class _SerializationError extends DiscordPlayerError { constructor() { super( ErrorCodes.ERR_SERIALIZATION_FAILED, "Don't know how to serialize this data" ); } }; __name(_SerializationError, "SerializationError"); var SerializationError = _SerializationError; var _DeserializationError = class _DeserializationError extends DiscordPlayerError { constructor() { super( ErrorCodes.ERR_DESERIALIZATION_FAILED, "Don't know how to deserialize this data" ); } }; __name(_DeserializationError, "DeserializationError"); var DeserializationError = _DeserializationError; var _IllegalHookInvocationError = class _IllegalHookInvocationError extends DiscordPlayerError { constructor(target, message) { super( ErrorCodes.ERR_ILLEGAL_HOOK_INVOCATION, `Illegal invocation of ${target} hook.${message ? ` ${message}` : ""}` ); } }; __name(_IllegalHookInvocationError, "IllegalHookInvocationError"); var IllegalHookInvocationError = _IllegalHookInvocationError; var _BridgeFailedError = class _BridgeFailedError extends DiscordPlayerError { constructor(id, error) { super( ErrorCodes.ERR_BRIDGE_FAILED, `${id ? `(Extractor Execution Context ID is ${id})` : ""}Failed to bridge this query: ${error}` ); } }; __name(_BridgeFailedError, "BridgeFailedError"); var BridgeFailedError = _BridgeFailedError; var ErrorCodes = { ERR_OUT_OF_SPACE: "ERR_OUT_OF_SPACE", ERR_INVALID_ARG_TYPE: "ERR_INVALID_ARG_TYPE", ERR_NO_RESULT: "ERR_NO_RESULT", ERR_NOT_IMPLEMENTED: "ERR_NOT_IMPLEMENTED", ERR_NOT_EXISTING: "ERR_NOT_EXISTING", ERR_OUT_OF_RANGE: "ERR_OUT_OF_RANGE", ERR_NO_VOICE_CONNECTION: "ERR_NO_VOICE_CONNECTION", ERR_VOICE_CONNECTION_DESTROYED: "ERR_VOICE_CONNECTION_DESTROYED", ERR_NO_VOICE_CHANNEL: "ERR_NO_VOICE_CHANNEL", ERR_INVALID_VOICE_CHANNEL: "ERR_INVALID_VOICE_CHANNEL", ERR_NO_RECEIVER: "ERR_NO_RECEIVER", ERR_FFMPEG_LOCATOR: "ERR_FFMPEG_LOCATOR", ERR_NO_AUDIO_RESOURCE: "ERR_NO_AUDIO_RESOURCE", ERR_NO_GUILD_QUEUE: "ERR_NO_GUILD_QUEUE", ERR_NO_GUILD: "ERR_NO_GUILD", ERR_INFO_REQUIRED: "ERR_INFO_REQUIRED", ERR_SERIALIZATION_FAILED: "ERR_SERIALIZATION_FAILED", ERR_DESERIALIZATION_FAILED: "ERR_DESERIALIZATION_FAILED", ERR_ILLEGAL_HOOK_INVOCATION: "ERR_ILLEGAL_HOOK_INVOCATION", ERR_NOT_EXISTING_MODULE: "ERR_NOT_EXISTING_MODULE", ERR_BRIDGE_FAILED: "ERR_BRIDGE_FAILED" }; function isDiscordPlayerError(error) { return error != null && error instanceof DiscordPlayerError; } __name(isDiscordPlayerError, "isDiscordPlayerError"); // src/utils/TypeUtil.ts var _TypeUtil = class _TypeUtil { constructor() { return _TypeUtil; } // eslint-disable-next-line @typescript-eslint/ban-types static isFunction(t) { return typeof t === "function"; } static isNumber(t) { return typeof t === "number" && !isNaN(t); } static isString(t) { return typeof t === "string"; } static isBoolean(t) { return typeof t === "boolean"; } static isNullish(t) { return t == null; } static isArray(t) { return Array.isArray(t); } static isError(t) { return t instanceof Error; } static isDiscordPlayerError(t) { return isDiscordPlayerError(t); } }; __name(_TypeUtil, "TypeUtil"); var TypeUtil = _TypeUtil; // src/utils/serde.ts var import_buffer = require("buffer"); var SerializedType = /* @__PURE__ */ ((SerializedType2) => { SerializedType2["Track"] = "track"; SerializedType2["Playlist"] = "playlist"; return SerializedType2; })(SerializedType || {}); var isTrack = /* @__PURE__ */ __name((data) => data.$type === "track" /* Track */, "isTrack"); var isPlaylist = /* @__PURE__ */ __name((data) => data.$type === "playlist" /* Playlist */, "isPlaylist"); function serialize(data) { if (data instanceof Track) return data.serialize(); if (data instanceof Playlist) return data.serialize(); try { return data.toJSON(); } catch { throw new SerializationError(); } } __name(serialize, "serialize"); function deserialize(player, data) { if (isTrack(data)) return Track.fromSerialized(player, data); if (isPlaylist(data)) return Playlist.fromSerialized(player, data); throw new DeserializationError(); } __name(deserialize, "deserialize"); function encode(data) { const str = JSON.stringify(data); return import_buffer.Buffer.from(str).toString("base64"); } __name(encode, "encode"); function decode(data) { const str = import_buffer.Buffer.from(data, "base64").toString(); return JSON.parse(str); } __name(decode, "decode"); function tryIntoThumbnailString(data) { if (!data) return null; try { if (TypeUtil.isString(data)) return data; return data?.url ?? data?.thumbnail?.url ?? null; } catch { return null; } } __name(tryIntoThumbnailString, "tryIntoThumbnailString"); // src/fabric/Track.ts var _onSeek, _resource; var _Track = class _Track { /** * Track constructor * @param player The player that instantiated this Track * @param data Track data */ constructor(player, data) { this.player = player; __publicField(this, "title"); __publicField(this, "description"); __publicField(this, "author"); __publicField(this, "url"); __publicField(this, "thumbnail"); __publicField(this, "duration"); __publicField(this, "views"); __publicField(this, "requestedBy", null); __publicField(this, "playlist"); __publicField(this, "queryType", null); // eslint-disable-next-line @typescript-eslint/no-explicit-any __publicField(this, "raw"); __publicField(this, "extractor", null); __publicField(this, "id", import_discord.SnowflakeUtil.generate().toString()); __publicField(this, "__metadata", null); __publicField(this, "__reqMetadataFn"); __publicField(this, "cleanTitle"); __publicField(this, "live", false); __publicField(this, "bridgedExtractor", null); __publicField(this, "bridgedTrack", null); __privateAdd(this, _onSeek, null); __privateAdd(this, _resource, null); this.title = (0, import_discord.escapeMarkdown)(data.title ?? ""); this.author = data.author ?? ""; this.url = data.url ?? ""; this.thumbnail = data.thumbnail ?? ""; this.duration = data.duration ?? ""; this.views = data.views ?? 0; this.queryType = data.queryType; this.requestedBy = data.requestedBy || null; this.playlist = data.playlist; this.description = `${this.title} by ${this.author}`; this.raw = Object.assign( {}, { source: data.raw?.source ?? data.source }, data.raw ?? data ); this.__metadata = data.metadata ?? null; this.__reqMetadataFn = data.requestMetadata || (() => Promise.resolve(null)); this.cleanTitle = data.cleanTitle ?? Util.cleanTitle(this.title, this.source); this.live = data.live ?? false; } /** * Whether this track can be seeked */ get seekable() { return __privateGet(this, _onSeek) !== null; } /** * Set the onSeek event * @param fn The onSeek event */ handleSeek(fn) { __privateSet(this, _onSeek, fn); } /** * Request seek * @param event The seek event */ async seek(event) { if (__privateGet(this, _onSeek)) return __privateGet(this, _onSeek).call(this, event); } /** * Sets audio resource for this track. This is not useful outside of the library. * @param resource Audio resource */ setResource(resource) { __privateSet(this, _resource, resource); } /** * Gets audio resource for this track */ get resource() { return __privateGet(this, _resource); } /** * Whether this track has an audio resource */ get hasResource() { return __privateGet(this, _resource) != null; } /** * Request metadata for this track */ async requestMetadata() { const res = await this.__reqMetadataFn(); this.setMetadata(res); return res; } /** * Set metadata for this track */ setMetadata(m) { this.__metadata = m; } /** * Metadata of this track */ get metadata() { return this.__metadata; } /** * If this track has metadata */ get hasMetadata() { return this.metadata != null; } /** * The queue in which this track is located */ get queue() { return this.player.nodes.cache.find( (q) => q.tracks.some((ab) => ab.id === this.id) ); } /** * The track duration in millisecond */ get durationMS() { const times = /* @__PURE__ */ __name((n, t) => { let tn = 1; for (let i = 0; i < t; i++) tn *= n; return t <= 0 ? 1e3 : tn * 1e3; }, "times"); return this.duration.split(":").reverse().map((m, i) => parseInt(m) * times(60, i)).reduce((a, c) => a + c, 0); } /** * Discord hyperlink representation of this track */ toHyperlink() { return `[${this.title}](${this.url})`; } /** * Returns source of this track */ get source() { return this.raw?.source ?? "arbitrary"; } /** * String representation of this track */ toString() { return `${this.title} by ${this.author}`; } /** * Raw JSON representation of this track */ toJSON(hidePlaylist) { return { id: this.id, title: this.title, description: this.description, author: this.author, url: this.url, thumbnail: this.thumbnail, duration: this.duration, durationMS: this.durationMS, views: this.views, requestedBy: this.requestedBy?.id || null, playlist: hidePlaylist ? null : this.playlist?.toJSON() ?? null }; } /** * Serialized track data that can be reconstructed */ serialize() { return { title: this.title, description: this.description, author: this.author, url: this.url, thumbnail: TypeUtil.isString(this.thumbnail) ? this.thumbnail : tryIntoThumbnailString(this.thumbnail), duration: this.duration, views: this.views ?? 0, requested_by: this.requestedBy?.toJSON() ?? null, source: this.source, live: false, query_type: this.queryType, extractor: this.extractor?.identifier ?? null, metadata: this.metadata, $type: "track" /* Track */, $encoder_version: this.player.version }; } /** * Construct a track from serialized data * @param player Player instance * @param data Serialized data */ static fromSerialized(player, data) { if (data.$type !== "track" /* Track */) throw new InvalidArgTypeError( "data", "SerializedTrack", "malformed data" ); const track = new _Track(player, { ...data, requestedBy: data.requested_by ? (() => { const res = data.requested_by; try { const resolved = player.client.users.resolve(res.id); if (resolved) return resolved; if (player.client.users.cache.has(res.id)) return player.client.users.cache.get(res.id); const user = new import_discord.User(player.client, res); return user; } catch { return null; } })() : null, queryType: data.query_type ?? void 0 }); track.setMetadata(data.metadata); return track; } /** * Get belonging queues of this track */ getBelongingQueues() { const nodes = this.player.nodes.cache.filter( (node) => node.tracks.some((t) => t.id === this.id) ); return nodes; } /** * Play this track to the given voice channel. If queue exists and another track is being played, this track will be added to the queue. * @param channel Voice channel on which this track shall be played * @param options Node initialization options */ async play(channel, options) { const fn = this.player.play.bind(this.player); return await fn(channel, this, options); } }; _onSeek = new WeakMap(); _resource = new WeakMap(); __name(_Track, "Track"); var Track = _Track; // src/fabric/Playlist.ts var _Playlist = class _Playlist { // eslint-disable-line @typescript-eslint/no-explicit-any /** * Playlist constructor * @param {Player} player The player * @param {PlaylistInitData} data The data */ constructor(player, data) { __publicField(this, "player"); __publicField(this, "tracks"); __publicField(this, "title"); __publicField(this, "description"); __publicField(this, "thumbnail"); __publicField(this, "type"); __publicField(this, "source"); __publicField(this, "author"); __publicField(this, "id"); __publicField(this, "url"); __publicField(this, "rawPlaylist"); this.player = player; this.tracks = data.tracks ?? []; this.author = data.author; this.description = data.description; this.thumbnail = data.thumbnail; this.type = data.type; this.source = data.source; this.id = data.id; this.url = data.url; this.title = data.title; } *[Symbol.iterator]() { yield* this.tracks; } /** * Estimated duration of this playlist */ get estimatedDuration() { return this.tracks.reduce((p, c) => p + c.durationMS, 0); } /** * Formatted estimated duration of this playlist */ get durationFormatted() { return Util.buildTimeCode(Util.parseMS(this.estimatedDuration)); } /** * JSON representation of this playlist * @param {boolean} [withTracks=true] If it should build json with tracks * @returns {PlaylistJSON} */ toJSON(withTracks = true) { const payload = { id: this.id, url: this.url, title: this.title, description: this.description, thumbnail: this.thumbnail, type: this.type, source: this.source, author: this.author, tracks: [] }; if (withTracks) payload.tracks = this.tracks.map((m) => m.toJSON(true)); return payload; } /** * Serialize this playlist into reconstructable data */ serialize() { return { tracks: this.tracks.map((m) => m.serialize()), title: this.title, description: this.description, thumbnail: TypeUtil.isString(this.thumbnail) ? this.thumbnail : tryIntoThumbnailString(this.thumbnail), type: this.type, source: this.source, author: this.author, id: this.id, url: this.url, $type: "playlist" /* Playlist */, $encoder_version: this.player.version }; } /** * Deserialize this playlist from serialized data * @param player Player instance * @param data Serialized data */ static fromSerialized(player, data) { if (data.$type !== "playlist" /* Playlist */) throw new InvalidArgTypeError( "data", "SerializedPlaylist", "malformed data" ); return new _Playlist(player, { ...data, tracks: data.tracks.map((m) => Track.fromSerialized(player, m)) }); } /** * Play this playlist to the given voice channel. If queue exists and another track is being played, this playlist will be added to the queue. * @param channel Voice channel on which this playlist shall be played * @param options Node initialization options */ async play(channel, options) { const fn = this.player.play.bind(this.player); return await fn(channel, this, options); } }; __name(_Playlist, "Playlist"); var Playlist = _Playlist; // src/utils/QueryResolver.ts var import_undici = require("undici"); var spotifySongRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:track\/|\?uri=spotify:track:)((\w|-){22})(\?si=.+)?$/; var spotifyPlaylistRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})(\?si=.+)?$/; var spotifyAlbumRegex = /^https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(intl-([a-z]|[A-Z])+\/)?(?:album\/|\?uri=spotify:album:)((\w|-){22})(\?si=.+)?$/; var vimeoRegex = /^(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)$/; var reverbnationRegex = /^https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)$/; var attachmentRegex = /^https?:\/\/.+$/; var appleMusicSongRegex = /^https?:\/\/music\.apple\.com\/.+?\/(song|album)\/.+?(\/.+?\?i=|\/)([0-9]+)$/; var appleMusicPlaylistRegex = /^https?:\/\/music\.apple\.com\/.+?\/playlist\/.+\/pl\.(u-|pm-)?[a-zA-Z0-9]+$/; var appleMusicAlbumRegex = /^https?:\/\/music\.apple\.com\/.+?\/album\/.+\/([0-9]+)$/; var soundcloudTrackRegex = /^https?:\/\/(m.|www.)?soundcloud.com\/(\w|-)+\/(\w|-)+(.+)?$/; var soundcloudPlaylistRegex = /^https?:\/\/(m.|www.)?soundcloud.com\/(\w|-)+\/sets\/(\w|-)+(.+)?$/; var youtubePlaylistRegex = /^https?:\/\/(www.)?youtube.com\/playlist\?list=((PL|FL|UU|LL|RD|OL)[a-zA-Z0-9-_]{16,41})$/; var youtubeVideoURLRegex = /^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube\.com|youtu.be))(\/(?:[\w-]+\?v=|embed\/|v\/)?)([\w-]+)(\S+)?$/; var youtubeVideoIdRegex = /^[a-zA-Z0-9-_]{11}$/; var discordPlayerBlobRegex = /^discord-player:\/\/blob\/\d+$/; var DomainsMap = { DiscordPlayer: ["discord-player"], YouTube: [ "youtube.com", "youtu.be", "music.youtube.com", "gaming.youtube.com", "www.youtube.com", "m.youtube.com" ], Spotify: ["open.spotify.com", "embed.spotify.com"], Vimeo: ["vimeo.com", "player.vimeo.com"], ReverbNation: ["reverbnation.com"], SoundCloud: ["soundcloud.com"], AppleMusic: ["music.apple.com"] }; var redirectDomains = /* @__PURE__ */ new Set( [ /^https?:\/\/spotify.link\/[A-Za-z0-9]+$/, /^https:\/\/on\.soundcloud\.com\/[a-zA-Z1-9]{0,17}$/ ] ); var QueryType = { AUTO: "auto", YOUTUBE: "youtube", YOUTUBE_PLAYLIST: "youtubePlaylist", SOUNDCLOUD_TRACK: "soundcloudTrack", SOUNDCLOUD_PLAYLIST: "soundcloudPlaylist", SOUNDCLOUD: "soundcloud", SPOTIFY_SONG: "spotifySong", SPOTIFY_ALBUM: "spotifyAlbum", SPOTIFY_PLAYLIST: "spotifyPlaylist", SPOTIFY_SEARCH: "spotifySearch", FACEBOOK: "facebook", VIMEO: "vimeo", ARBITRARY: "arbitrary", REVERBNATION: "reverbnation", YOUTUBE_SEARCH: "youtubeSearch", YOUTUBE_VIDEO: "youtubeVideo", SOUNDCLOUD_SEARCH: "soundcloudSearch", APPLE_MUSIC_SONG: "appleMusicSong", APPLE_MUSIC_ALBUM: "appleMusicAlbum", APPLE_MUSIC_PLAYLIST: "appleMusicPlaylist", APPLE_MUSIC_SEARCH: "appleMusicSearch", FILE: "file", AUTO_SEARCH: "autoSearch", DISCORD_PLAYER_BLOB: "discordPlayerBlob" }; var _QueryResolver = class _QueryResolver { /** * Query resolver */ constructor() { } // eslint-disable-line @typescript-eslint/no-empty-function static get regex() { return { spotifyAlbumRegex, spotifyPlaylistRegex, spotifySongRegex, vimeoRegex, reverbnationRegex, attachmentRegex, appleMusicAlbumRegex, appleMusicPlaylistRegex, appleMusicSongRegex, soundcloudTrackRegex, soundcloudPlaylistRegex, youtubePlaylistRegex, discordPlayerBlobRegex }; } /** * Pre-resolve redirect urls */ static async preResolve(query, maxDepth = 5) { if (!TypeUtil.isString(query)) throw new InvalidArgTypeError(query, "string", typeof query); for (const domain of redirectDomains) { if (domain.test(query)) { try { const res = await (0, import_undici.fetch)(query, { method: "GET", redirect: "follow" }); if (!res.ok) break; if (/^https?:\/\/spotify.app.link\/(.+)$/.test(res.url)) { const body = await res.text(); const target = body.split("https://open.spotify.com/track/")[1].split("?si=")[0]; if (!target) break; return `https://open.spotify.com/track/${target}`; } return maxDepth < 1 ? res.url : this.preResolve(res.url, maxDepth - 1); } catch { break; } } } return query; } /** * Resolves the given search query * @param {string} query The query */ static resolve(query, fallbackSearchEngine = QueryType.AUTO_SEARCH) { if (!TypeUtil.isString(query)) throw new InvalidArgTypeError(query, "string", typeof query); if (!query.length) throw new InfoRequiredError("query", String(query)); const resolver = /* @__PURE__ */ __name((type, query2) => ({ type, query: query2 }), "resolver"); if (discordPlayerBlobRegex.test(query)) return resolver(QueryType.DISCORD_PLAYER_BLOB, query); try { const url = new URL(query); if (DomainsMap.YouTube.includes(url.host)) { query = query.replace(/(m(usic)?|gaming)\./, "").trim(); const playlistId = url.searchParams.get("list"); if (playlistId) return resolver( QueryType.YOUTUBE_PLAYLIST, `https://www.youtube.com/${url.searchParams.size === 1 ? "playlist" : "watch"}${url.search}` ); if (_QueryResolver.validateId(query) || _QueryResolver.validateURL(query)) return resolver(QueryType.YOUTUBE_VIDEO, query); return resolver(fallbackSearchEngine, query); } else if (DomainsMap.Spotify.includes(url.host)) { query = query.replace(/intl-([a-zA-Z]+)\//, ""); if (spotifyPlaylistRegex.test(query)) return resolver(QueryType.SPOTIFY_PLAYLIST, query); if (spotifyAlbumRegex.test(query)) return resolver(QueryType.SPOTIFY_ALBUM, query); if (spotifySongRegex.test(query)) return resolver(QueryType.SPOTIFY_SONG, query); return resolver(fallbackSearchEngine, query); } else if (DomainsMap.Vimeo.includes(url.host)) { if (vimeoRegex.test(query)) return resolver(QueryType.VIMEO, query); return resolver(fallbackSearchEngine, query); } else if (DomainsMap.ReverbNation.includes(url.host)) { if (reverbnationRegex.test(query)) return resolver(QueryType.REVERBNATION, query); return resolver(fallbackSearchEngine, query); } else if (DomainsMap.SoundCloud.includes(url.host)) { if (soundcloudPlaylistRegex.test(query)) return resolver(QueryType.SOUNDCLOUD_PLAYLIST, query); if (soundcloudTrackRegex.test(query)) return resolver(QueryType.SOUNDCLOUD_TRACK, query); return resolver(fallbackSearchEngine, query); } else if (DomainsMap.AppleMusic.includes(url.host)) { if (appleMusicAlbumRegex.test(query)) return resolver(QueryType.APPLE_MUSIC_ALBUM, query); if (appleMusicPlaylistRegex.test(query)) return resolver(QueryType.APPLE_MUSIC_PLAYLIST, query); if (appleMusicSongRegex.test(query)) return resolver(QueryType.APPLE_MUSIC_SONG, query); return resolver(fallbackSearchEngine, query); } else { return resolver(QueryType.ARBITRARY, query); } } catch { return resolver(fallbackSearchEngine, query); } } /** * Parses vimeo id from url * @param {string} query The query * @returns {string} */ static getVimeoID(query) { return _QueryResolver.resolve(query).type === QueryType.VIMEO ? query.split("/").filter(Boolean).pop() : null; } static validateId(q) { return youtubeVideoIdRegex.test(q); } static validateURL(q) { return youtubeVideoURLRegex.test(q); } }; __name(_QueryResolver, "QueryResolver"); var QueryResolver = _QueryResolver; // src/fabric/SearchResult.ts var _SearchResult = class _SearchResult { constructor(player, _data) { this.player = player; this._data = _data; this._data.tracks?.forEach((track) => { track.extractor ?? (track.extractor = this._data.extractor || null); track.requestedBy ?? (track.requestedBy = _data.requestedBy || null); }); } setQueryType(type) { this._data.queryType = type; return this; } setRequestedBy(user) { this._data.requestedBy = user; this._data.tracks?.forEach((track) => { track.requestedBy = user; }); return this; } setExtractor(extractor) { this._data.extractor = extractor; this._data.tracks?.forEach((track) => { track.extractor = extractor; }); return this; } setTracks(tracks) { this._data.tracks = tracks; return this; } setQuery(query) { this._data.query = query; return this; } setPlaylist(playlist) { this._data.playlist = playlist; return this; } /** * The search query */ get query() { return this._data.query; } /** * The search query type */ get queryType() { return this._data.queryType || QueryType.AUTO; } /** * The extractor */ get extractor() { return this._data.extractor || null; } /** * Playlist result */ get playlist() { return this._data.playlist; } /** * Tracks result */ get tracks() { return this._data.tracks || []; } /** * Requested by */ get requestedBy() { return this._data.requestedBy || null; } /** * Re-execute this search */ async execute() { return this.player.search(this.query, { searchEngine: this.queryType, requestedBy: this.requestedBy }); } /** * If this search result is empty */ isEmpty() { return !this.tracks.length; } /** * If this search result has playlist */ hasPlaylist() { return this.playlist != null; } /** * If this search result has tracks */ hasTracks() { return this.tracks.length > 0; } /** * JSON representation of this search */ toJSON() { return { query: this.query, queryType: this.queryType, playlist: this.playlist?.toJSON(false) || null, tracks: this.tracks.map((m) => m.toJSON(true)), extractor: this.extractor?.identifier || null, requestedBy: this.requestedBy?.toJSON() || null }; } }; __name(_SearchResult, "SearchResult"); var SearchResult = _SearchResult; // src/utils/AudioFilters.ts var bass = /* @__PURE__ */ __name((g) => `bass=g=${g}:f=110:w=0.3`, "bass"); var _AudioFilters = class _AudioFilters { constructor() { return _AudioFilters; } static get(name) { return this.filters[name] ?? name; } static has(name) { return name in this.filters; } static *[Symbol.iterator]() { for (const [k, v] of Object.entries(this.filters)) { yield { name: k, value: v }; } } static get names() { return Object.keys(this.filters); } // @ts-ignore static get length() { return this.names.length; } static toString() { return this.names.map((m) => this[m]).join(","); } /** * Create ffmpeg args from the specified filters name * @param filter The filter name * @returns */ static create(filters) { if (!filters || !Array.isArray(filters)) return this.toString(); return filters.filter((predicate) => typeof predicate === "string").map((m) => this.get(m)).join(","); } /** * Defines audio filter * @param filterName The name of the filter * @param value The ffmpeg args */ static define(filterName, value) { this.filters[filterName] = value; } /** * Defines multiple audio filters * @param filtersArray Array of filters containing the filter name and ffmpeg args */ static defineBulk(filtersArray) { filtersArray.forEach((arr) => this.define(arr.name, arr.value)); } }; __name(_AudioFilters, "AudioFilters"); __publicField(_AudioFilters, "filters", { bassboost_low: bass(15), bassboost: bass(20), bassboost_high: bass(30), "8D": "apulsator=hz=0.09", vaporwave: "aresample=48000,asetrate=48000*0.8", nightcore: "aresample=48000,asetrate=48000*1.25", lofi: "aresample=48000,asetrate=48000*0.9,extrastereo=m=2.5:c=disabled", phaser: "aphaser=in_gain=0.4", tremolo: "tremolo", vibrato: "vibrato=f=6.5", reverse: "areverse", treble: "treble=g=5", normalizer2: "dynaudnorm=g=101", normalizer: "acompressor", surrounding: "surround", pulsator: "apulsator=hz=1", subboost: "asubboost", karaoke: "stereotools=mlev=0.03", flanger: "flanger", gate: "agate", haas: "haas", mcompand: "mcompand", mono: "pan=mono|c0=.5*c0+.5*c1", mstlr: "stereotools=mode=ms>lr", mstrr: "stereotools=mode=ms>rr", compressor: "compand=points=-80/-105|-62/-80|-15.4/-15.4|0/-12|20/-7.6", expander: "compand=attacks=0:points=-80/-169|-54/-80|-49.5/-64.6|-41.1/-41.1|-25.8/-15|-10.8/-4.5|0/0|20/8.3", softlimiter: "compand=attacks=0:points=-80/-80|-12.4/-12.4|-6/-8|0/-6.8|20/-2.8", chorus: "chorus=0.7:0.9:55:0.4:0.25:2", chorus2d: "chorus=0.6:0.9:50|60:0.4|0.32:0.25|0.4:2|1.3", chorus3d: "chorus=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3", fadein: "afade=t=in:ss=0:d=10", dim: `afftfilt="'real=re * (1-clip((b/nb)*b,0,1))':imag='im * (1-clip((b/nb)*b,0,1))'"`, earrape: "channelsplit,sidechaingate=level_in=64", silenceremove: "silenceremove=1:0:-50dB" }); var AudioFilters = _AudioFilters; // src/utils/Util.ts var import_node_crypto = require("crypto"); var import_metadata_filter = require("@web-scrobbler/metadata-filter"); var _Util = class _Util { /** * Utils */ constructor() { } // eslint-disable-line @typescript-eslint/no-empty-function /** * Gets the runtime information */ static getRuntime() { const version2 = typeof navigator !== "undefined" ? navigator.userAgent : null; if (typeof Deno !== "undefined" && Deno.version) { return { name: "deno", version: Deno.version.deno }; } if (typeof Bun !== "undefined" && Bun.version) { return { name: "bun", version: Bun.version }; } if (typeof process !== "undefined" && process.version) return { name: "node", version: process.version }; return { name: "unknown", version: version2 ?? "unknown" }; } /** * Creates duration string * @param {object} durObj The duration object * @returns {string} */ static durationString(durObj) { return Object.values(durObj).map((m) => isNaN(m) ? 0 : m).join(":"); } /** * Parses milliseconds to consumable time object * @param {number} milliseconds The time in ms * @returns {TimeData} */ static parseMS(milliseconds) { if (isNaN(milliseconds)) milliseconds = 0; const round = milliseconds > 0 ? Math.floor : Math.ceil; return { days: round(milliseconds / 864e5), hours: round(milliseconds / 36e5) % 24, minutes: round(milliseconds / 6e4) % 60, seconds: round(milliseconds / 1e3) % 60 }; } /** * Builds time code * @param {TimeData} duration The duration object * @returns {string} */ static buildTimeCode(duration) { const items = Object.keys(duration); const required = ["days", "hours", "minutes", "seconds"]; const parsed = items.filter((x) => required.includes(x)).map((m) => duration[m]); const final = parsed.slice(parsed.findIndex((x) => x !== 0)).map((x) => x.toString().padStart(2, "0")).join(":"); return final.length <= 3 ? `0:${final.padStart(2, "0") || 0}` : final; } /** * Formats duration * @param {number} duration The duration in ms */ static formatDuration(duration) { return this.buildTimeCode(this.parseMS(duration)); } /** * Picks last item of the given array * @param {any[]} arr The array * @returns {any} */ // eslint-disable-next-line @typescript-eslint/no-explicit-any static last(arr) { if (!Array.isArray(arr)) return arr; return arr[arr.length - 1]; } /** * Checks if the voice channel is empty * @param {VoiceChannel|StageChannel} channel The voice channel * @returns {boolean} */ static isVoiceEmpty(channel) { return channel && channel.members.filter((member) => !member.user.bot).size === 0; } /** * Cleans the track title * @param title The title * @param source The source * @returns Cleaned title */ static cleanTitle(title, source) { try { const filterOpts = { // prettier-ignore track: [ import_metadata_filter.removeRemastered, import_metadata_filter.removeLive, import_metadata_filter.fixTrackSuffix, import_metadata_filter.removeZeroWidth, import_metadata_filter.replaceNbsp, import_metadata_filter.replaceSmartQuotes, import_metadata_filter.removeCleanExplicit ] }; const spotifyFilter = (0, import_metadata_filter.createFilter)(filterOpts); spotifyFilter.extend((0, import_metadata_filter.createSpotifyFilter)()); const defaultFilter = (0, import_metadata_filter.createFilter)(filterOpts); switch (source) { case "youtube": return (0, import_metadata_filter.youtube)(title); case "spotify": return spotifyFilter.filterField("track", title); default: return defaultFilter.filterField("track", title); } } catch { return title; } } /** * Safer require * @param {string} id Node require id * @returns {any} */ static require(id) { try { return { module: require(id), error: null }; } catch (error) { return { module: null, error }; } } static async import(id) { try { const mod = await import(id); return { module: mod, error: null }; } catch (error) { return { module: null, error }; } } /** * Asynchronous timeout * @param {number} time The time in ms to wait * @returns {Promise} */ static wait(time) { return (0, import_promises.setTimeout)(time, void 0, { ref: false }); } static noop() { } // eslint-disable-line @typescript-eslint/no-empty-function static async getFetch() { if ("fetch" in globalThis) return globalThis.fetch; for (const lib of ["node-fetch", "undici"]) { try { return await import(lib).then( (res) => res.fetch || res.default?.fetch || res.default ); } catch { try { const res = require(lib); if (res) return res.fetch || res.default?.fetch || res.default; } catch { } } } } static warn(message, code = "DeprecationWarning", detail) { process.emitWarning(message, { code, detail }); } static randomChoice(src) { return src[(0, import_node_crypto.randomInt)(src.length)]; } static arrayCloneShuffle(src) { const arr = src.slice(); let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; } return arr; } }; __name(_Util, "Util"); var Util = _Util; var VALIDATE_QUEUE_CAP = /* @__PURE__ */ __name((queue, items) => { if (queue.maxSize < 1 || queue.maxSize === Infinity) return; const tracks = typeof items === "number" ? items : (items instanceof Playlist ? items.tracks : Array.isArray(items) ? items : [items]).length; const maxCap = queue.getCapacity(); if (maxCap < tracks) { throw new OutOfSpaceError("tracks queue", maxCap, tracks); } }, "VALIDATE_QUEUE_CAP"); // src/compat/createErisCompat.ts var DiscordPlayerClientSymbol2 = Symbol("DiscordPlayerClient"); function declareProperty(target, key, value) { Reflect.set(target, key, value); } __name(declareProperty, "declareProperty"); function getProperty(target, key) { return Reflect.get(target, key); } __name(getProperty, "getProperty"); function createErisCompat(client) { const { module: module2, error } = Util.require("eris"); if (error) throw error; const eris = module2; erisVoiceEventsHandler(client); const erisProxy = new Proxy(client, { get(target, p) { switch (p) { case "users": return erisUsersProxy(target, eris); case "guilds": return erisGuildsProxy(target, eris); case "channels": return erisChannelsProxy(target, eris); case "__dp_voiceStateUpdate_proxy": return (handler) => erisVoiceStateUpdateProxy(target, erisProxy, handler); case "incrementMaxListeners": return () => { client.setMaxListeners(client.getMaxListeners() + 1); }; case "decrementMaxListeners": return () => { const listeners = client.getMaxListeners() - 1; client.setMaxListeners(listeners < 0 ? 1 : listeners); }; default: return target[p]; } } }); Reflect.set(erisProxy, DiscordPlayerClientSymbol2, "Eris"); return createCompatClient(erisProxy, "Eris").client; } __name(createErisCompat, "createErisCompat"); function erisVoiceStateUpdateProxy(client, proxy, handler) { client.on("voiceStateUpdate", (member, oldState) => { try { const proxiedOldState = { channelId: oldState.channelID, serverMute: oldState.mute, suppress: oldState.suppress, guild: { id: oldState.guild.id }, member: { id: oldState.user.id } }; const me = member.guild.members.get(client.user.id); const resolvedChannel = member.guild.channels.get( member.voiceState.channelID ); const proxiedNewState = { channelId: member.voiceState.channelID, serverMute: member.voiceState.mute, suppress: member.voiceState.suppress, channel: erisResolvedChannelProxy(resolvedChannel, client), member: { id: member.id }, guild: { id: member.guild.id, members: { me: { id: me?.id, voice: { async setRequestToSpeak(value) { return me?.voiceState; } } } } } }; return handler(proxiedNewState, proxiedOldState); } catch { } }); } __name(erisVoiceStateUpdateProxy, "erisVoiceStateUpdateProxy"); function erisVoiceEventsHandler(client) { let adapters = getProperty(client, "adapters"); if (!adapters) { const collection = /* @__PURE__ */ new Map(); adapters = collection; declareProperty(client, "adapters", collection); } client.on("shardDisconnect", (_, shardId) => { for (const [guildId, adapter] of adapters.entries()) { if (client.guilds.get(guildId)?.shard.id === shardId) { adapter.destroy(); } } }); client.on("rawWS", (packet) => { switch (packet.t) { case import_v10.GatewayDispatchEvents.VoiceServerUpdate: { const payload = packet.d; adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload); return; } case import_v10.GatewayDispatchEvents.VoiceStateUpdate: { const payload = packet.d; if (payload.guild_id && payload.session_id && payload.user_id === client.user.id) { adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload); } return; } default: break; } }); } __name(erisVoiceEventsHandler, "erisVoiceEventsHandler"); function erisChannelsProxy(client, eris) { const handler = { client, get cache() { return { get(id) { return client.getChannel(id); }, has(id) { return id in client.channelGuildMap; } }; }, resolve(resolvable) { if (typeof resolvable === "string") { return erisResolvedChannelProxy( this.client.getChannel(resolvable), client ); } if (resolvable instanceof eris.GuildChannel) { return erisResolvedChannelProxy(resolvable, client); } }, resolveId(resolvable) { const channel = this.resolve(resolvable); return channel?.id; } }; return handler; } __name(erisChannelsProxy, "erisChannelsProxy"); function erisResolvedChannelProxy(channel, client) { if (!channel) return; return new Proxy(channel, { get(target, p) { switch (p) { case "guild": return erisVoiceAdapterProxy(target.guild, client); case "members": return target.voiceMembers; case "isVoiceBased": return () => target.type === import_v10.ChannelType.GuildVoice || target.type === import_v10.ChannelType.GuildStageVoice; case "isVoice": return () => target.type === import_v10.ChannelType.GuildVoice; case "isStage": return () => target.type === import_v10.ChannelType.GuildStageVoice; default: return target[p]; } } }); } __name(erisResolvedChannelProxy, "erisResolvedChannelProxy"); function erisVoiceAdapterProxy(guild, client) { if (!guild) return; return new Proxy(guild, { get(target, p) { if (p === "voiceAdapterCreator") { return erisVoiceAdapterCreator(target, client); } return target[p]; } }); } __name(erisVoiceAdapterProxy, "erisVoiceAdapterProxy"); function erisVoiceAdapterCreator(guild, client) { return (methods) => { let adapters = getProperty(client, "adapters"); if (!adapters) { const collection = /* @__PURE__ */ new Map(); adapters = collection; declareProperty(client, "adapters", collection); } adapters.set(guild.id, methods); return { sendPayload(payload) { if (guild.shard.status !== "ready") return false; guild.shard.sendWS(payload.op, payload.d); return true; }, destroy() { adapters.delete(guild.id); } }; }; } __name(erisVoiceAdapterCreator, "erisVoiceAdapterCreator"); function erisGuildsProxy(client, eris) { return new Proxy(client.guilds, { get(target, p) { if (p === "cache") { return target; } if (p === "resolve" || p === "resolveId") { const resolver = /* @__PURE__ */ __name(function(resolvable) { if (typeof resolvable === "string") { return target.get(resolvable); } if (resolvable instanceof eris.Guild) { return resolvable; } if (resolvable instanceof eris.Member || resolvable instanceof eris.Guild || resolvable instanceof eris.GuildChannel || resolvable instanceof eris.Role) { return resolvable.guild; } }, "resolver"); if (p === "resolve") { return resolver; } return (resolvable) => { const guild = resolver(resolvable); return guild?.id; }; } return target[p]; } }); } __name(erisGuildsProxy, "erisGuildsProxy"); function erisUsersProxy(client, eris) { return new Proxy(client.users, { get(target, p) { if (p === "cache") { return target; } if (p === "resolve" || p === "resolveId") { const resolver = /* @__PURE__ */ __name(function(resolvable) { if (typeof resolvable === "string") { return target.get(resolvable); } if (resolvable instanceof eris.User) { return resolvable; } if (resolvable instanceof eris.Member) { return resolvable.user; } }, "resolver"); if (p === "resolve") { return resolver; } return (resolvable) => { const user = resolver(resolvable); return user?.id; }; } return target[p]; } }); } __name(erisUsersProxy, "erisUsersProxy"); // src/compat/createOceanicCompat.ts var import_v102 = require("discord-api-types/v10"); var DiscordPlayerClientSymbol3 = Symbol("DiscordPlayerClient"); function declareProperty2(target, key, value) { Reflect.set(target, key, value); } __name(declareProperty2, "declareProperty"); function getProperty2(target, key) { return Reflect.get(target, key); } __name(getProperty2, "getProperty"); function createOceanicCompat(client) { const { module: module2, error } = Util.require("oceanic.js"); if (error) throw error; const oceanic = module2; oceanicVoiceEventsHandler(client); const oceanicProxy = new Proxy(client, { get(target, p) { switch (p) { case "users": return oceanicUsersProxy(target, oceanic); case "guilds": return oceanicGuildsProxy(target, oceanic); case "channels": return oceanicChannelsProxy(target, oceanic); case "__dp_voiceStateUpdate_proxy": return (handler) => oceanicVoiceStateUpdateProxy(target, oceanicProxy, handler); case "incrementMaxListeners": return () => { client.setMaxListeners(client.getMaxListeners() + 1); }; case "decrementMaxListeners": return () => { const listeners = client.getMaxListeners() - 1; client.setMaxListeners(listeners < 0 ? 1 : listeners); }; default: return target[p]; } } }); Reflect.set(oceanicProxy, DiscordPlayerClientSymbol3, "Oceanic"); return createCompatClient(oceanicProxy, "Oceanic").client; } __name(createOceanicCompat, "createOceanicCompat"); function oceanicVoiceStateUpdateProxy(client, proxy, handler) { client.on("voiceStateUpdate", (member, oldState) => { try { const proxiedOldState = { channelId: oldState.channelID, serverMute: oldState.mute, suppress: oldState.suppress, guild: { id: oldState.guild.id }, member: { id: oldState.user.id } }; const me = member.guild.members.get(client.user.id); const resolvedChannel = member.guild.channels.get( member.voiceState.channelID ); const proxiedNewState = { channelId: member.voiceState.channelID, serverMute: member.voiceState.mute, suppress: member.voiceState.suppress, channel: oceanicResolvedChannelProxy(resolvedChannel, client), member: { id: member.id }, guild: { id: member.guild.id, members: { me: { id: me?.id, voice: { async setRequestToSpeak(value) { return me?.voiceState; } } } } } }; return handler(proxiedNewState, proxiedOldState); } catch { } }); } __name(oceanicVoiceStateUpdateProxy, "oceanicVoiceStateUpdateProxy"); function oceanicVoiceEventsHandler(client) { let adapters = getProperty2(client, "adapters"); if (!adapters) { const collection = /* @__PURE__ */ new Map(); adapters = collection; declareProperty2(client, "adapters", collection); } client.on("shardDisconnect", (_, shardId) => { for (const [guildId, adapter] of adapters.entries()) { if (client.guilds.get(guildId)?.shard.id === shardId) { adapter.destroy(); } } }); client.on("packet", (packet) => { switch (packet.t) { case import_v102.GatewayDispatchEvents.VoiceServerUpdate: { const payload = packet.d; adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload); return; } case import_v102.GatewayDispatchEvents.VoiceStateUpdate: { const payload = packet.d; if (payload.guild_id && payload.session_id && payload.user_id === client.user.id) { adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload); } return; } default: break; } }); } __name(oceanicVoiceEventsHandler, "oceanicVoiceEventsHandler"); function oceanicChannelsProxy(client, oceanic) { const handler = { client, get cache() { return { get(id) { return client.getChannel(id); }, has(id) { return id in client.channelGuildMap; } }; }, resolve(resolvable) { if (typeof resolvable === "string") { return oceanicResolvedChannelProxy( this.client.getChannel(resolvable), client ); } if (resolvable instanceof oceanic.GuildChannel) { return oceanicResolvedChannelProxy(resolvable, client); } }, resolveId(resolvable) { const channel = this.resolve(resolvable); return channel?.id; } }; return handler; } __name(oceanicChannelsProxy, "oceanicChannelsProxy"); function oceanicResolvedChannelProxy(channel, client) { if (!channel) return; return new Proxy(channel, { get(target, p) { switch (p) { case "guild": return oceanicVoiceAdapterProxy(target.guild, client); case "members": return target.voiceMembers; case "isVoiceBased": return () => target.type === import_v102.ChannelType.GuildVoice || target.type === import_v102.ChannelType.GuildStageVoice; case "isVoice": return () => target.type === import_v102.ChannelType.GuildVoice; case "isStage": return () => target.type === import_v102.ChannelType.GuildStageVoice; default: return target[p]; } } }); } __name(oceanicResolvedChannelProxy, "oceanicResolvedChannelProxy"); function oceanicVoiceAdapterProxy(guild, client) { if (!guild) return; return new Proxy(guild, { get(target, p) { if (p === "voiceAdapterCreator") { return oceanicVoiceAdapterCreator(target, client); } return target[p]; } }); } __name(oceanicVoiceAdapterProxy, "oceanicVoiceAdapterProxy"); function oceanicVoiceAdapterCreator(guild, client) { return (methods) => { let adapters = getProperty2(client, "adapters"); if (!adapters) { const collection = /* @__PURE__ */ new Map(); adapters = collection; declareProperty2(client, "adapters", collection); } adapters.set(guild.id, methods); return { sendPayload(payload) { if (guild.shard.status !== "ready") return false; guild.shard.send(payload.op, payload.d); return true; }, destroy() { adapters.delete(guild.id); } }; }; } __name(oceanicVoiceAdapterCreator, "oceanicVoiceAdapterCreator"); function oceanicGuildsProxy(client, oceanic) { return new Proxy(client.guilds, { get(target, p) { if (p === "cache") { return target; } if (p === "resolve" || p === "resolveId") { const resolver = /* @__PURE__ */ __name(function(resolvable) { if (typeof resolvable === "string") { return target.get(resolvable); } if (resolvable instanceof oceanic.Guild) { return resolvable; } if (resolvable instanceof oceanic.Member || resolvable instanceof oceanic.Guild || resolvable instanceof oceanic.GuildChannel || resolvable instanceof oceanic.Role) { return resolvable.guild; } }, "resolver"); if (p === "resolve") { return resolver; } return (resolvable) => { const guild = resolver(resolvable); return guild?.id; }; } return target[p]; } }); } __name(oceanicGuildsProxy, "oceanicGuildsProxy"); function oceanicUsersProxy(client, oceanic) { return new Proxy(client.users, { get(target, p) { if (p === "cache") { return target; } if (p === "resolve" || p === "resolveId") { const resolver = /* @__PURE__ */ __name(function(resolvable) { if (typeof resolvable === "string") { return target.get(resolvable); } if (resolvable instanceof oceanic.User) { return resolvable; } if (resolvable instanceof oceanic.Member) { return resolvable.user; } }, "resolver"); if (p === "resolve") { return resolver; } return (resolvable) => { const user = resolver(resolvable); return user?.id; }; } return target[p]; } }); } __name(oceanicUsersProxy, "oceanicUsersProxy"); // src/utils/PlayerEventsEmitter.ts var import_utils = require("@discord-player/utils"); var _hasDebugger; var _PlayerEventsEmitter = class _PlayerEventsEmitter extends import_utils.EventEmitter { constructor(requiredEvents = []) { super(); this.requiredEvents = requiredEvents; __privateAdd(this, _hasDebugger, false); } on(name, listener) { if (name === "debug") { __privateSet(this, _hasDebugger, true); } return super.on(name, listener); } once(name, listener) { if (name === "debug") { __privateSet(this, _hasDebugger, true); } return super.once(name, listener); } addListener(name, listener) { if (name === "debug") { __privateSet(this, _hasDebugger, true); } return super.addListener(name, listener); } off(name, listener) { __privateSet(this, _hasDebugger, this.listenerCount("debug") > 0); return super.off(name, listener); } removeListener(name, listener) { __privateSet(this, _hasDebugger, this.listenerCount("debug") > 0); return super.removeListener(name, listener); } removeAllListeners(name) { __privateSet(this, _hasDebugger, this.listenerCount("debug") > 0); return super.removeAllListeners(name); } emit(name, ...args) { if (this.requiredEvents.includes(name) && !this.eventNames().includes(name)) { console.error(...args); Util.warn( `No event listener found for event "${String( name )}". Events ${this.requiredEvents.map((m) => `"${String(m)}"`).join(", ")} must have event listeners.`, "UnhandledEventsWarning" ); return false; } return super.emit(name, ...args); } get hasDebugger() { return __privateGet(this, _hasDebugger); } }; _hasDebugger = new WeakMap(); __name(_PlayerEventsEmitter, "PlayerEventsEmitter"); var PlayerEventsEmitter = _PlayerEventsEmitter; // src/extractors/BaseExtractor.ts var _BaseExtractor = class _BaseExtractor { /** * Extractor constructor * @param context Context that instantiated this extractor * @param options Initialization options for this extractor */ constructor(context, options = {}) { this.context = context; this.options = options; /** * Priority of this extractor. Higher value means higher priority (will be executed first). */ __publicField(this, "priority", 1); /** * A list of query protocols that this extractor supports. */ __publicField(this, "protocols", []); /** * Handle bridge query creation * @param track The track to build query for */ __publicField(this, "createBridgeQuery", /* @__PURE__ */ __name((track) => `${track.title} by ${track.author} official audio`, "createBridgeQuery")); } /** * Identifier of this extractor */ get identifier() { return this.constructor.identifier; } /** * Reconfigures this extractor * @param options The new options to apply */ async reconfigure(options) { this.options = options; await this.deactivate(); await this.activate(); } /** * This method will be executed when this extractor is activated */ async activate() { return; } /** * This method will be executed when this extractor is deactivated */ async deactivate() { return; } /** * Validate incoming query * @param query The query to validate */ async validate(query, type) { return false; } /** * Stream the given track * @param info The track to stream */ async stream(info) { throw new NotImplementedError(`${this.constructor.name}.stream()`); } /** * Handle the given query * @param query The query to handle */ async handle(query, context) { throw new NotImplementedError(`${this.constructor.name}.handle()`); } /** * Get related tracks for the given track * @param track The track source */ async getRelatedTracks(track, history) { throw new NotImplementedError( `${this.constructor.name}.getRelatedTracks()` ); } /** * A stream middleware to handle streams before passing it to the player * @param stream The incoming stream * @param next The next function */ handlePostStream(stream, next) { return next(null, stream); } /** * Dispatch an event to the player * @param event The event to dispatch * @param args The data to dispatch */ emit(event, ...args) { return this.context.player.emit(event, ...args); } /** * Create extractor response * @param playlist The playlist * @param tracks The track array */ createResponse(playlist, tracks = playlist?.tracks || []) { return { playlist: playlist || null, tracks }; } /** * Write debug message * @param message The debug message */ debug(message) { return this.context.player.debug(message); } /** * A flag to indicate `Demuxable` stream support for `opus`/`ogg/opus`/`webm/opus` formats. */ get supportsDemux() { return !!this.context.player.options.skipFFmpeg; } /** * Handle stream extraction for another extractor * @param track The track to bridge * @param sourceExtractor The source extractor */ async bridge(track, sourceExtractor) { return null; } }; __name(_BaseExtractor, "BaseExtractor"); /** * Identifier for this extractor */ __publicField(_BaseExtractor, "identifier", "com.discord-player.extractor"); var BaseExtractor = _BaseExtractor; // src/extractors/ExtractorExecutionContext.ts var import_utils3 = require("@discord-player/utils"); // src/hooks/context/async-context.ts var import_node_async_hooks = require("async_hooks"); var _Context = class _Context { constructor(defaultValue) { this.defaultValue = defaultValue; __publicField(this, "storage", new import_node_async_hooks.AsyncLocalStorage()); } /** * Exit out of this context */ exit(scope) { this.storage.exit(scope); } /** * Whether the context is lost */ get isLost() { return this.storage.getStore() === void 0; } /** * Get the current value of the context. If the context is lost and no default value is provided, undefined will be returned. */ consume() { const data = this.storage.getStore(); if (data === void 0 && this.defaultValue !== void 0) return this.defaultValue; return data; } /** * Run a function within the context of this provider */ provide(value, receiver) { if (value === void 0) { throw new Error("Context value may not be undefined"); } if (typeof receiver !== "function") { throw new Error("Context receiver must be a function"); } return this.storage.run(value, receiver); } }; __name(_Context, "Context"); var Context = _Context; function createContext(defaultValue) { return new Context(defaultValue); } __name(createContext, "createContext"); function useContext(context) { return context.consume(); } __name(useContext, "useContext"); // src/utils/__internal__/_container.ts var import_utils2 = require("@discord-player/utils"); var globalRegistry = new import_utils2.Collection(); // src/utils/__internal__/getGlobalRegistry.ts function getGlobalRegistry() { return globalRegistry; } __name(getGlobalRegistry, "getGlobalRegistry"); // src/hooks/common.ts var SUPER_CONTEXT = createContext(); var getFallbackContext = /* @__PURE__ */ __name(() => { return getGlobalRegistry().get("@[player]"); }, "getFallbackContext"); function useHooksContext(hookName, mainOnly = false) { let isFallback = false; let player; if (!(player = SUPER_CONTEXT.consume())) { player = getFallbackContext(); isFallback = true; } if (!player) throw new IllegalHookInvocationError( "discord-player", `Player context is not available, ${isFallback ? "did you forget to initialize the player with `new Player(client)`?" : "is it being called inside .context.provide()?"}` ); if (mainOnly) return { player, context: {}, isFallback }; let context; if (!isFallback) { context = useContext(player.context); if (!context) throw new IllegalHookInvocationError( hookName, `${hookName} must be called inside a player context created by .context.provide()` ); } else { context = { get guild() { throw new IllegalHookInvocationError( hookName, `${hookName} must be called with an explicit guild argument when not inside a player context` ); } }; } return { context, player, isFallback }; } __name(useHooksContext, "useHooksContext"); // src/hooks/useHistory.ts function useHistory(node) { const { context, player } = useHooksContext("useHistory"); const queue = player.queues.get(node ?? context.guild.id); if (!queue) return null; return queue.history; } __name(useHistory, "useHistory"); // src/hooks/usePlayer.ts function usePlayer(node) { const { context, player } = useHooksContext("usePlayer"); const queue = player.queues.get(node ?? context.guild.id); if (!queue) return null; return queue.node; } __name(usePlayer, "usePlayer"); // src/hooks/useQueue.ts function useQueue(node) { const { context, player } = useHooksContext("useQueue"); const queue = player.queues.resolve(node ?? context.guild.id); if (!queue) return null; return queue; } __name(useQueue, "useQueue"); // src/hooks/useMainPlayer.ts function useMainPlayer() { const { player } = useHooksContext("useMainPlayer", true); return player; } __name(useMainPlayer, "useMainPlayer"); // src/hooks/useMetadata.ts function useMetadata(node) { const { context, player } = useHooksContext("useMetadata"); const queue = player.queues.get(node ?? context.guild.id); const setter = /* @__PURE__ */ __name((metadata) => { if (queue) { if (TypeUtil.isFunction(metadata)) return queue.setMetadata(metadata(queue.metadata)); return queue.setMetadata(metadata); } }, "setter"); const getter = /* @__PURE__ */ __name(() => { return queue?.metadata; }, "getter"); return [getter, setter]; } __name(useMetadata, "useMetadata"); // src/hooks/useTimeline.ts function useTimeline(options) { const { context, player } = useHooksContext("useTimeline"); const queue = player.queues.get(options?.node ?? context.guild.id); if (!queue) return null; const timeline = Object.preventExtensions({ get timestamp() { return queue.node.getTimestamp(options?.ignoreFilters); }, get volume() { return queue.node.volume; }, get paused() { return queue.node.isPaused(); }, get track() { return queue.currentTrack; }, pause() { return queue.node.pause(); }, resume() { return queue.node.resume(); }, setVolume(vol) { return queue.node.setVolume(vol); }, async setPosition(time) { return queue.node.seek(time); } }); return timeline; } __name(useTimeline, "useTimeline"); // src/hooks/stream/onAfterCreateStream.ts function onAfterCreateStream(handler) { getGlobalRegistry().set("@[onAfterCreateStream]", handler); } __name(onAfterCreateStream, "onAfterCreateStream"); // src/hooks/stream/onBeforeCreateStream.ts function onBeforeCreateStream(handler) { getGlobalRegistry().set("@[onBeforeCreateStream]", handler); } __name(onBeforeCreateStream, "onBeforeCreateStream"); // src/hooks/stream/onStreamExtracted.ts function onStreamExtracted(handler) { getGlobalRegistry().set("@[onStreamExtracted]", handler); } __name(onStreamExtracted, "onStreamExtracted"); // src/hooks/useVolume.ts function useVolume(node) { const { context, player } = useHooksContext("useVolume"); const queue = player.queues.get(node ?? context.guild.id); const setter = /* @__PURE__ */ __name((volume) => { if (queue) { if (TypeUtil.isFunction(volume)) return queue.node.setVolume(volume(queue.node.volume)); return queue.node.setVolume(volume); } }, "setter"); const getter = /* @__PURE__ */ __name(() => { return queue?.node.volume; }, "getter"); return [getter, setter]; } __name(useVolume, "useVolume"); // src/extractors/ExtractorExecutionContext.ts var _ExtractorExecutionContext = class _ExtractorExecutionContext extends PlayerEventsEmitter { constructor(player) { super(["error"]); this.player = player; /** * The extractors store */ __publicField(this, "store", new import_utils3.Collection()); __publicField(this, "context", createContext()); } /** * Get the current execution id */ getExecutionId() { return this.context.consume()?.id ?? null; } /** * Get the current execution context */ getContext() { return this.context.consume() ?? null; } async loadDefault() { const sample = ` import { DefaultExtractors } from '@discord-player/extractor'; await player.extractors.loadMulti(DefaultExtractors);`; throw new Error( `extractors.loadDefault() is no longer supported. Use extractors.loadMulti instead. Example: ${sample} ` ); } /** * Load a bundle of extractors. * @example import { DefaultExtractors } from '@discord-player/extractor'; * * await player.extractors.loadMulti(DefaultExtractors); */ async loadMulti(bundle, options = {}) { bundle.forEach((ext) => { this.register(ext, options?.[ext.identifier] || {}); }); return { success: true, error: null }; } /** * Validate if the given extractor is registered * @param identifier The extractor identifier */ isRegistered(identifier) { return this.store.has(identifier); } /** * The size of registered extractors */ get size() { return this.store.size; } /** * Get single extractor * @param identifier The extractor to get */ get(identifier) { return this.store.get(identifier); } /** * Register single extractor * @param _extractor The extractor to register * @param options Options supplied to the extractor */ async register(_extractor, options) { if (typeof _extractor.identifier !== "string" || this.store.has(_extractor.identifier)) return null; const extractor = new _extractor(this, options); try { this.store.set(_extractor.identifier, extractor); if (this.player.hasDebugger) this.player.debug(`${_extractor.identifier} extractor loaded!`); this.emit("registered", this, extractor); await extractor.activate(); if (this.player.hasDebugger) this.player.debug(`${_extractor.identifier} extractor activated!`); this.emit("activate", this, extractor); return extractor; } catch (e) { this.store.delete(_extractor.identifier); if (this.player.hasDebugger) this.player.debug( `${_extractor.identifier} extractor failed to activate! Error: ${e}` ); this.emit("error", this, extractor, e); return null; } } /** * Unregister single extractor * @param _extractor The extractor to unregister */ async unregister(_extractor) { const extractor = typeof _extractor === "string" ? this.store.get(_extractor) : this.store.find((r) => r === _extractor); if (!extractor) return; try { const key = extractor.identifier || this.store.findKey((e) => e === extractor); this.store.delete(key); if (this.player.hasDebugger) this.player.debug(`${extractor.identifier} extractor disabled!`); this.emit("unregistered", this, extractor); await extractor.deactivate(); if (this.player.hasDebugger) this.player.debug(`${extractor.identifier} extractor deactivated!`); this.emit("deactivate", this, extractor); } catch (e) { if (this.player.hasDebugger) this.player.debug( `${extractor.identifier} extractor failed to deactivate!` ); this.emit("error", this, extractor, e); } } /** * Unregister all extractors */ async unregisterAll() { try { await Promise.all(this.store.map((e) => this.unregister(e))); } catch { } } /** * Run all the extractors * @param fn The runner function * @param filterBlocked Filter blocked extractors */ async run(fn, filterBlocked = true) { const blocked = this.player.options.blockExtractors ?? []; if (!this.store.size) { Util.warn( "Skipping extractors execution since zero extractors were registered", "NoExtractors" ); return; } const extractors = this.store.sort((a, b) => b.priority - a.priority); let err = null, lastExt = null; for (const ext of extractors.values()) { if (filterBlocked && blocked.some((e) => e === ext.identifier)) continue; if (this.player.hasDebugger) this.player.debug(`Executing extractor ${ext.identifier}...`); const result = await fn(ext).then( (res) => { return res; }, (e) => { if (this.player.hasDebugger) this.player.debug( `Extractor ${ext.identifier} failed with error: ${e}` ); return TypeUtil.isError(e) ? e : new Error(`${e}`); } ); lastExt = ext; if (result && !TypeUtil.isError(result)) { if (this.player.hasDebugger) this.player.debug( `Extractor ${ext.identifier} executed successfully!` ); return { extractor: ext, error: null, result }; } else if (TypeUtil.isError(result)) { err = result; } } if (err) return { extractor: lastExt, error: err, result: false }; } /** * Request bridge for a track * @param track The track to request bridge for * @param sourceExtractor The source extractor of the track */ async requestBridge(track, sourceExtractor = track.extractor) { const previouslyAttempted = this.getContext()?.bridgeAttemptedExtractors ?? /* @__PURE__ */ new Set(); const result = await this.run(async (ext) => { if (sourceExtractor && ext.identifier === sourceExtractor.identifier) return false; if (previouslyAttempted.has(ext.identifier)) return false; previouslyAttempted.add(ext.identifier); const result2 = await ext.bridge(track, sourceExtractor); if (!result2) return false; return result2; }); if (!result?.result) throw new BridgeFailedError( this.getExecutionId(), result?.error?.stack || result?.error?.message || "No extractors available to bridge" ); track.bridgedExtractor = result.extractor; return result; } /** * Request bridge from the specified extractor * @param track The track to request bridge for * @param sourceExtractor The source extractor of the track * @param targetExtractor The target extractor to bridge to */ async requestBridgeFrom(track, sourceExtractor, targetExtractor) { const target = this.resolve(targetExtractor); if (!target) return null; return target.bridge(track, sourceExtractor); } /** * Check if extractor is disabled */ isDisabled(identifier) { return this.player.options.blockExtractors?.includes(identifier) ?? false; } /** * Check if extractor is enabled */ isEnabled(identifier) { return !this.isDisabled(identifier); } /** * Resolve extractor identifier */ resolveId(resolvable) { return typeof resolvable === "string" ? resolvable : resolvable.identifier; } /** * Resolve extractor */ resolve(resolvable) { return typeof resolvable === "string" ? this.get(resolvable) : resolvable; } }; __name(_ExtractorExecutionContext, "ExtractorExecutionContext"); var ExtractorExecutionContext = _ExtractorExecutionContext; // src/queue/GuildNodeManager.ts var import_utils7 = require("@discord-player/utils"); // src/queue/GuildQueue.ts var import_discord3 = require("discord.js"); var import_utils6 = require("@discord-player/utils"); // src/stream/StreamDispatcher.ts var import_discord_voip = require("discord-voip"); var import_utils4 = require("@discord-player/utils"); var import_equalizer = require("@discord-player/equalizer"); // src/stream/InterceptedStream.ts var import_node_stream = require("stream"); var _intercepting; var _InterceptedStream = class _InterceptedStream extends import_node_stream.Transform { constructor() { super(...arguments); __publicField(this, "interceptors", /* @__PURE__ */ new Set()); __privateAdd(this, _intercepting, true); } /** * Start intercepting the stream. This is the default state of InterceptedStream. */ startIntercepting() { __privateSet(this, _intercepting, true); } /** * Stop intercepting the stream. This will prevent the stream from being consumed by the interceptors. * This can be useful when you want to temporarily stop the interception. The stopped state can be resumed by calling startIntercepting again. */ stopIntercepting() { __privateSet(this, _intercepting, false); } /** * Whether the stream is being intercepted */ isIntercepting() { return __privateGet(this, _intercepting); } _transform(chunk, encoding, callback) { this.push(chunk, encoding); if (__privateGet(this, _intercepting) && this.interceptors.size > 0) { for (const consumer of this.interceptors) { consumer.write(chunk, encoding); } } callback(); } _final(callback) { for (const consumer of this.interceptors) { consumer.end(); } callback(); } _destroy(error, callback) { const ignoreError = String(error).includes("ERR_STREAM_PREMATURE_CLOSE"); const err = ignoreError ? void 0 : error; for (const consumer of this.interceptors) { consumer.destroy(err); } this.interceptors.clear(); callback(err); } }; _intercepting = new WeakMap(); __name(_InterceptedStream, "InterceptedStream"); var InterceptedStream = _InterceptedStream; // src/stream/StreamDispatcher.ts var _interceptor; var _StreamDispatcher = class _StreamDispatcher extends import_utils4.EventEmitter { /** * Creates new connection object * @param {VoiceConnection} connection The connection * @param {VoiceChannel|StageChannel} channel The connected channel * @private */ constructor(connection, channel, queue, connectionTimeout = 2e4, audioPlayer) { super(); this.queue = queue; this.connectionTimeout = connectionTimeout; __publicField(this, "voiceConnection"); __publicField(this, "audioPlayer"); __publicField(this, "channel"); __publicField(this, "audioResource"); __publicField(this, "dsp", new import_equalizer.FiltersChain()); __privateAdd(this, _interceptor, null); this.voiceConnection = connection; this.audioPlayer = audioPlayer || (0, import_discord_voip.createAudioPlayer)({ debug: this.queue.hasDebugger }); this.channel = channel; this.voiceConnection.on("debug", (m) => void this.emit("debug", m)); this.voiceConnection.on( "error", (error) => void this.emit("error", error) ); this.audioPlayer.on("debug", (m) => void this.emit("debug", m)); this.audioPlayer.on("error", (error) => void this.emit("error", error)); this.dsp.onUpdate = () => { if (!this.dsp) return; if (this.dsp.filters?.filters) { this.emit("dsp", this.dsp.filters?.filters); } if (this.dsp.biquad?.filters) { this.emit("biquad", this.dsp.biquad?.filters); } if (this.dsp.equalizer) { this.emit("eqBands", this.dsp.equalizer.getEQ()); } if (this.dsp.volume) { this.emit("volume", this.dsp.volume.volume); } if (this.dsp.resampler) { this.emit("sampleRate", this.dsp.resampler.getParameters()); } if (this.dsp.compressor) { this.emit("compressor", this.dsp.compressor.getParameters()); } if (this.dsp.reverb) { this.emit("reverb", this.dsp.reverb.getParameters()); } if (this.dsp.seeker) { this.emit("seeker", this.dsp.seeker.getParameters()); } }; this.dsp.onError = (e) => this.emit("error", e); this.voiceConnection.on(import_discord_voip.VoiceConnectionStatus.Disconnected, async (oldState, newState) => { if (newState.reason === import_discord_voip.VoiceConnectionDisconnectReason.Manual) { this.destroy(); return; } if (newState.reason === import_discord_voip.VoiceConnectionDisconnectReason.WebSocketClose && newState.closeCode === 4014) { try { await (0, import_discord_voip.entersState)( this.voiceConnection, import_discord_voip.VoiceConnectionStatus.Connecting, this.connectionTimeout ); } catch { try { if (this.voiceConnection.state.status !== import_discord_voip.VoiceConnectionStatus.Destroyed) this.destroy(); } catch (err) { this.emit("error", err); } } } else if (this.voiceConnection.rejoinAttempts < 5) { await Util.wait((this.voiceConnection.rejoinAttempts + 1) * 5e3); this.voiceConnection.rejoin(); } else { try { if (this.voiceConnection.state.status !== import_discord_voip.VoiceConnectionStatus.Destroyed) this.destroy(); } catch (err) { this.emit("error", err); } } }).on(import_discord_voip.VoiceConnectionStatus.Destroyed, () => { this.end(); this.queue.emit(GuildQueueEvent.ConnectionDestroyed, this.queue); }); this.audioPlayer.on("stateChange", (oldState, newState) => { if (oldState.status !== import_discord_voip.AudioPlayerStatus.Paused && newState.status === import_discord_voip.AudioPlayerStatus.Paused) { this.queue.emit(GuildQueueEvent.PlayerPause, this.queue); } if (oldState.status === import_discord_voip.AudioPlayerStatus.Paused && newState.status !== import_discord_voip.AudioPlayerStatus.Paused) { this.queue.emit(GuildQueueEvent.PlayerResume, this.queue); } if (newState.status === import_discord_voip.AudioPlayerStatus.Playing) { if (oldState.status === import_discord_voip.AudioPlayerStatus.Idle || oldState.status === import_discord_voip.AudioPlayerStatus.Buffering) { return this.emit("start", this.audioResource); } } else if (newState.status === import_discord_voip.AudioPlayerStatus.Idle && oldState.status !== import_discord_voip.AudioPlayerStatus.Idle) { this.emit("finish", this.audioResource); this.dsp.destroy(); this.audioResource = null; } }); this.voiceConnection.subscribe(this.audioPlayer); } /** * Check if the player has been paused manually */ get paused() { return this.audioPlayer.state.status === import_discord_voip.AudioPlayerStatus.Paused; } set paused(val) { val ? this.pause(true) : this.resume(); } /** * Whether or not the player is currently paused automatically or manually. */ isPaused() { return this.paused || this.audioPlayer.state.status === import_discord_voip.AudioPlayerStatus.AutoPaused; } /** * Whether or not the player is currently buffering */ isBuffering() { return this.audioPlayer.state.status === import_discord_voip.AudioPlayerStatus.Buffering; } /** * Whether or not the player is currently playing */ isPlaying() { return this.audioPlayer.state.status === import_discord_voip.AudioPlayerStatus.Playing; } /** * Whether or not the player is currently idle */ isIdle() { return this.audioPlayer.state.status === import_discord_voip.AudioPlayerStatus.Idle; } /** * Whether or not the voice connection has been destroyed */ isDestroyed() { return this.voiceConnection.state.status === import_discord_voip.VoiceConnectionStatus.Destroyed; } /** * Whether or not the voice connection has been destroyed */ isDisconnected() { return this.voiceConnection.state.status === import_discord_voip.VoiceConnectionStatus.Disconnected; } /** * Whether or not the voice connection is ready to play */ isReady() { return this.voiceConnection.state.status === import_discord_voip.VoiceConnectionStatus.Ready; } /** * Whether or not the voice connection is signalling */ isSignalling() { return this.voiceConnection.state.status === import_discord_voip.VoiceConnectionStatus.Signalling; } /** * Whether or not the voice connection is connecting */ isConnecting() { return this.voiceConnection.state.status === import_discord_voip.VoiceConnectionStatus.Connecting; } /** * Creates stream * @param {Readable} src The stream source * @param {object} [ops] Options * @returns {AudioResource} */ async createStream(src, ops) { if (!ops?.disableFilters && this.queue.hasDebugger) this.queue.debug("Initiating DSP filters pipeline..."); const stream = !ops?.disableFilters ? this.dsp.create(src, { dsp: { filters: ops?.defaultFilters, disabled: ops?.disableFilters }, biquad: ops?.biquadFilter ? { filter: ops.biquadFilter, disabled: ops?.disableBiquad } : void 0, resampler: ops?.sampleRate ? { inputSampleRate: 48e3, targetSampleRate: ops?.sampleRate, disabled: ops?.disableResampler } : void 0, equalizer: { bandMultiplier: ops?.eq, disabled: ops?.disableEqualizer }, volume: { volume: ops?.volume, disabled: ops?.disableVolume }, compressor: ops?.compressor ? { threshold: ops?.compressor.threshold, ratio: ops?.compressor.ratio, attack: ops?.compressor.attack, release: ops?.compressor.release, makeupGain: ops?.compressor.makeupGain, disabled: ops?.disableCompressor, kneeWidth: ops?.compressor.kneeWidth } : void 0, reverb: ops?.reverb ? { roomSize: ops?.reverb.roomSize, damping: ops?.reverb.damping, wetLevel: ops?.reverb.wetLevel, dryLevel: ops?.reverb.dryLevel, disabled: ops?.disableReverb } : void 0, seeker: ops?.seeker ? { disabled: ops?.disableSeeker, seekTarget: ops?.seeker.seekTarget, sampleRate: 48e3, channels: 2, totalDuration: ops?.seeker.totalDuration } : void 0 }) : src; if (this.dsp.seeker) { this.dsp.seeker.on("seek", (data) => { this.queue.node.requestSeek(data).catch(() => { }); }); } if (this.queue.hasDebugger) { this.queue.debug("Executing onAfterCreateStream hook..."); } const postStream = await this.queue.onAfterCreateStream?.(stream, this.queue, ops?.data).catch( () => ({ stream, type: ops?.type ?? import_discord_voip.StreamType.Arbitrary }) ); if (this.queue.hasDebugger) this.queue.debug("Preparing AudioResource..."); const format = postStream?.type ?? ops?.type ?? import_discord_voip.StreamType.Arbitrary; let _stream; if (this.queue.canIntercept()) { __privateSet(this, _interceptor, new InterceptedStream()); (postStream?.stream ?? stream).pipe(__privateGet(this, _interceptor)); _stream = __privateGet(this, _interceptor); await this.queue.player.handleInterceptingStream( this.queue, ops?.data, format, __privateGet(this, _interceptor) ); } else { _stream = postStream?.stream ?? stream; } this.audioResource = (0, import_discord_voip.createAudioResource)(_stream, { inputType: format, metadata: ops?.data, // volume controls happen from AudioFilter DSP utility inlineVolume: false }); return this.audioResource; } get resampler() { return this.dsp?.resampler; } get filters() { return this.dsp?.filters; } get biquad() { return this.dsp?.biquad || null; } get equalizer() { return this.dsp?.equalizer || null; } get compressor() { return this.dsp?.compressor || null; } get reverb() { return this.dsp?.reverb || null; } get seeker() { return this.dsp?.seeker || null; } /** * The player status * @type {AudioPlayerStatus} */ get status() { return this.audioPlayer.state.status; } /** * Disconnects from voice * @returns {void} */ disconnect() { try { if (this.audioPlayer) this.audioPlayer.stop(true); if (this.voiceConnection.state.status !== import_discord_voip.VoiceConnectionStatus.Destroyed) this.voiceConnection.destroy(); } catch { } } /** * Destroys this dispatcher */ destroy() { this.disconnect(); this.audioPlayer.removeAllListeners(); this.voiceConnection.removeAllListeners(); this.dsp.destroy(); this.audioResource = null; this.emit("destroyed"); } /** * Stops the player * @returns {void} */ end() { try { this.audioPlayer.stop(); this.dsp.destroy(); } catch { } } /** * Pauses the stream playback * @param {boolean} [interpolateSilence=false] If true, the player will play 5 packets of silence after pausing to prevent audio glitches. * @returns {boolean} */ pause(interpolateSilence) { const success = this.audioPlayer.pause(interpolateSilence); return success; } /** * Resumes the stream playback * @returns {boolean} */ resume() { const success = this.audioPlayer.unpause(); return success; } /** * Play stream * @param {AudioResource} [resource=this.audioResource] The audio resource to play * @param {boolean} [opus=false] Whether or not to use opus * @returns {Promise} */ async playStream(resource = this.audioResource) { if (!resource) { throw new NoAudioResourceError(); } if (resource.ended) { return void this.emit("finish", resource); } if (!this.audioResource) this.audioResource = resource; if (this.voiceConnection.state.status !== import_discord_voip.VoiceConnectionStatus.Ready) { try { await (0, import_discord_voip.entersState)( this.voiceConnection, import_discord_voip.VoiceConnectionStatus.Ready, this.connectionTimeout ); } catch (err) { return void this.emit("error", err); } } try { this.audioPlayer.play(resource); } catch (e) { this.emit("error", e); } return this; } /** * Sets playback volume * @param {number} value The volume amount * @returns {boolean} */ setVolume(value) { if (!this.dsp.volume) return false; return this.dsp.volume.setVolume(value); } /** * The current volume * @type {number} */ get volume() { if (!this.dsp.volume) return 100; return this.dsp.volume.volume; } /** * The playback time * @type {number} */ get streamTime() { if (!this.audioResource) return 0; return this.audioResource.playbackDuration; } }; _interceptor = new WeakMap(); __name(_StreamDispatcher, "StreamDispatcher"); var StreamDispatcher = _StreamDispatcher; // src/queue/GuildQueue.ts var import_discord_voip3 = require("discord-voip"); // src/queue/GuildQueueHistory.ts var import_utils5 = require("@discord-player/utils"); var _GuildQueueHistory = class _GuildQueueHistory { constructor(queue) { this.queue = queue; __publicField(this, "tracks", new import_utils5.Queue("LIFO")); } /** * Current track in the queue */ get currentTrack() { return this.queue.dispatcher?.audioResource?.metadata || // eslint-disable-next-line @typescript-eslint/no-explicit-any this.queue.__current; } /** * Next track in the queue */ get nextTrack() { return this.queue.tracks.at(0) || null; } /** * Previous track in the queue */ get previousTrack() { return this.tracks.at(0) || null; } /** * If history is disabled */ get disabled() { return this.queue.options.disableHistory; } /** * Gets the size of the queue */ get size() { return this.tracks.size; } getSize() { return this.size; } /** * If history is empty */ isEmpty() { return this.tracks.size < 1; } /** * Add track to track history * @param track The track to add */ push(track) { if (this.disabled) return false; this.tracks.add(track); this.resize(); return true; } /** * Clear history */ clear() { this.tracks.clear(); } /** * Play the next track in the queue */ async next() { const track = this.nextTrack; if (!track) { throw new NoResultError("No next track in the queue"); } this.queue.node.skip({ reason: "HISTORY_NEXT_TRACK" /* HistoryNext */, description: "Skipped by GuildQueueHistory.next()" }); } /** * Play the previous track in the queue */ async previous(preserveCurrent = true) { const track = this.tracks.dispatch(); if (!track) { throw new NoResultError("No previous track in the queue"); } const current = this.currentTrack; await this.queue.node.play(track, { queue: false }); if (current && preserveCurrent) this.queue.node.insert(current, 0); } /** * Alias to [GuildQueueHistory].previous() */ back(preserveCurrent = true) { return this.previous(preserveCurrent); } /** * Resize history store */ resize() { if (!Number.isFinite(this.queue.maxHistorySize)) return; if (this.tracks.store.length < this.queue.maxHistorySize) return; this.tracks.store.splice(this.queue.maxHistorySize); } }; __name(_GuildQueueHistory, "GuildQueueHistory"); var GuildQueueHistory = _GuildQueueHistory; // src/queue/GuildQueuePlayerNode.ts var import_discord_voip2 = require("discord-voip"); var import_stream = require("stream"); var import_promises2 = require("timers/promises"); // src/utils/AsyncQueue.ts var import_discord2 = require("discord.js"); var _AsyncQueue = class _AsyncQueue { constructor() { /** * The queued entries */ __publicField(this, "entries", []); __publicField(this, "exceptionHandler"); } /** * Clear entries queue * @param consume Whether or not to consume all entries before clearing */ clear(consume = false) { if (consume) { this.entries.forEach((entry) => entry.consume()); } this.entries = []; } /** * The total number of entries in this queue. Returns `0` if no entries are available. */ get size() { return this.entries.length; } /** * Acquire an entry. * * @example // lock the queue * const entry = asyncQueue.acquire(); * // wait until previous task is completed * await entry.getTask(); * // do something expensive * await performSomethingExpensive(); * // make sure to release the lock once done * asyncQueue.release(); * */ acquire(options) { const entry = new AsyncQueueEntry(this, options); if (this.exceptionHandler) entry.getTask().catch(this.exceptionHandler); if (this.entries.length === 0) { this.entries.push(entry); entry.consume(); return entry; } this.entries.push(entry); return entry; } /** * Release the current acquisition and move to next entry. */ release() { if (!this.entries.length) return; this.entries.shift(); this.entries[0]?.consume(); } /** * Cancel all entries */ cancelAll() { this.entries.forEach((entry) => entry.cancel()); } /** * Remove the given entry from the queue * @param entry The entry to remove */ removeEntry(entry) { const entryIdx = this.entries.indexOf(entry); if (entryIdx !== -1) { this.entries.splice(entryIdx, 1); return true; } return false; } }; __name(_AsyncQueue, "AsyncQueue"); var AsyncQueue = _AsyncQueue; var _AsyncQueueEntry = class _AsyncQueueEntry { constructor(queue, options) { this.queue = queue; this.options = options; __publicField(this, "id", import_discord2.SnowflakeUtil.generate().toString()); __publicField(this, "promise"); __publicField(this, "signal", null); __publicField(this, "onAbort", null); __publicField(this, "resolve"); __publicField(this, "reject"); this.promise = new Promise((resolve2, reject) => { this.resolve = resolve2; this.reject = reject; }); if (this.options?.signal) { this.setAbortSignal(this.options.signal); } } setAbortSignal(signal) { if (signal.aborted) return; this.signal = signal; this.onAbort = () => { this.queue.removeEntry(this); this.cancel(); }; this.signal.addEventListener("abort", this.onAbort); } consume() { this.cleanup(); this.resolve(); } release() { this.consume(); this.queue.release(); } cancel() { this.cleanup(); this.reject(new Error("Cancelled")); } cleanup() { if (this.onAbort) this.signal?.removeEventListener("abort", this.onAbort); this.signal = null; this.onAbort = null; } getTask() { return this.promise; } }; __name(_AsyncQueueEntry, "AsyncQueueEntry"); var AsyncQueueEntry = _AsyncQueueEntry; // src/queue/GuildQueuePlayerNode.ts var import_opus = require("@discord-player/opus"); var FFMPEG_SRATE_REGEX = /asetrate=\d+\*(\d(\.\d)?)/; var _progress, _hasFFmpegOptimization, _GuildQueuePlayerNode_instances, throw_fn, performPlay_fn, createGenericStream_fn, createFallbackStream_fn, createFFmpegStream_fn; var _GuildQueuePlayerNode = class _GuildQueuePlayerNode { constructor(queue) { this.queue = queue; __privateAdd(this, _GuildQueuePlayerNode_instances); __privateAdd(this, _progress, 0); __privateAdd(this, _hasFFmpegOptimization, false); __publicField(this, "tasksQueue", new AsyncQueue()); __privateSet(this, _hasFFmpegOptimization, /libopus: (yes|true)/.test( this.queue.player.scanDeps() )); } /** * If the player is currently in idle mode */ isIdle() { return !!this.queue.dispatcher?.isIdle(); } /** * If the player is currently buffering the track */ isBuffering() { return !!this.queue.dispatcher?.isBuffering(); } /** * If the player is currently playing a track */ isPlaying() { return !!this.queue.dispatcher?.isPlaying(); } /** * If the player is currently paused */ isPaused() { return !!this.queue.dispatcher?.isPaused(); } /** * Reset progress history */ resetProgress() { __privateSet(this, _progress, 0); } /** * Set player progress */ setProgress(progress) { __privateSet(this, _progress, progress); } /** * The stream time for current session */ get streamTime() { return this.queue.dispatcher?.streamTime ?? 0; } /** * Current playback duration with history included */ get playbackTime() { if (this.queue.filters.seeker) { const pos = this.queue.filters.seeker.getPosition(); if (pos > 0) return pos; } const dur = __privateGet(this, _progress) + this.streamTime; return dur; } /** * Get duration multiplier */ getDurationMultiplier() { const srateFilters = this.queue.filters.ffmpeg.toArray().filter((ff) => FFMPEG_SRATE_REGEX.test(ff)); const multipliers = srateFilters.map((m) => { return parseFloat(FFMPEG_SRATE_REGEX.exec(m)?.[1]); }).filter((f) => !isNaN(f)); return !multipliers.length ? 1 : multipliers.reduce((accumulator, current) => current + accumulator); } /** * Estimated progress of the player */ get estimatedPlaybackTime() { const dur = this.playbackTime; const val = this.getDurationMultiplier() * dur; return val; } /** * Estimated total duration of the player */ get estimatedDuration() { const dur = this.totalDuration; const val = Math.round(dur / this.getDurationMultiplier()); if (this.queue.filters.resampler) { const ratio = this.queue.filters.resampler.getRatio(); if (ratio <= 0) return val; return Math.round(val / ratio); } return val; } /** * Total duration of the current audio track */ get totalDuration() { const prefersBridgedMetadata = this.queue.options.preferBridgedMetadata; const track = this.queue.currentTrack; if (prefersBridgedMetadata) { const trackHasLegacyMetadata = track?.metadata != null && typeof track.metadata === "object" && "bridge" in track.metadata && track.metadata.bridge != null; const trackHasMetadata = track?.bridgedTrack != null; if (trackHasLegacyMetadata || trackHasMetadata) { const duration = track.bridgedTrack?.durationMS ?? track.metadata?.bridge.duration; if (TypeUtil.isNumber(duration)) return duration; } } return track?.durationMS ?? 0; } /** * Get stream progress * @param ignoreFilters Ignore filters */ getTimestamp(ignoreFilters = false) { if (!this.queue.currentTrack) return null; const current = ignoreFilters ? this.playbackTime : this.estimatedPlaybackTime; const total = ignoreFilters ? this.totalDuration : this.estimatedDuration; return { current: { label: Util.buildTimeCode(Util.parseMS(current)), value: current }, total: { label: Util.buildTimeCode(Util.parseMS(total)), value: total }, progress: Math.round(current / total * 100) }; } /** * Create progress bar for current progress * @param options Progress bar options */ createProgressBar(options) { const timestamp = this.getTimestamp(); if (!timestamp) return null; const { indicator = "\u{1F518}", leftChar = "\u25AC", rightChar = "\u25AC", length = 15, timecodes = true, separator = "\u2503" } = options || {}; if (isNaN(length) || length < 0 || !Number.isFinite(length)) { throw new OutOfRangeError( "[PlayerProgressBarOptions.length]", String(length), "0", "Finite Number" ); } const index = Math.round( timestamp.current.value / timestamp.total.value * length ); if (index >= 1 && index <= length) { const bar = leftChar.repeat(index - 1).split(""); bar.push(indicator); bar.push(rightChar.repeat(length - index)); if (timecodes) { return `${timestamp.current.label} ${separator} ${bar.join( "" )} ${separator} ${timestamp.total.label}`; } else { return `${bar.join("")}`; } } else { if (timecodes) { return `${timestamp.current.label} ${separator} ${indicator}${rightChar.repeat( length - 1 )} ${separator} ${timestamp.total.label}`; } else { return `${indicator}${rightChar.repeat(length - 1)}`; } } } /** * Seek the player * @param duration The duration to seek to */ async seek(duration) { if (!this.queue.currentTrack) return false; if (duration === this.estimatedPlaybackTime) return true; if (duration > this.totalDuration) { return this.skip({ reason: "SEEK_OVER_THRESHOLD" /* SEEK_OVER_THRESHOLD */, description: new OutOfRangeError( "[duration]", String(duration), "0", String(this.totalDuration) ).message }); } if (duration < 0) duration = 0; const seeker = this.queue.filters.seeker; if (seeker) { seeker.seek(duration); return true; } return this.queue.filters.triggerReplay(duration).then((v) => { if (v) { this.queue.emit(GuildQueueEvent.PlayerSeek, this.queue, { currentPosition: this.estimatedPlaybackTime, seekTarget: duration, totalDuration: this.estimatedDuration }); } return v; }); } /** * Current volume */ get volume() { return this.queue.dispatcher?.volume ?? 100; } /** * Set volume * @param vol Volume amount to set */ setVolume(vol) { if (!this.queue.dispatcher) return false; const res = this.queue.dispatcher.setVolume(vol); if (res) this.queue.filters._lastFiltersCache.volume = vol; return res; } /** * Set bit rate * @param rate The bit rate to set */ setBitrate(rate) { this.queue.dispatcher?.audioResource?.encoder?.setBitrate( rate === "auto" ? this.queue.channel?.bitrate ?? 64e3 : rate ); } /** * Set paused state * @param state The state */ setPaused(state) { if (state) return this.queue.dispatcher?.pause(true) || false; return this.queue.dispatcher?.resume() || false; } /** * Pause the playback */ pause() { return this.setPaused(true); } /** * Resume the playback */ resume() { return this.setPaused(false); } /** * Skip current track */ skip(options) { if (!this.queue.dispatcher) return false; const track = this.queue.currentTrack; if (!track) return false; this.queue.setTransitioning(false); this.queue.dispatcher.end(); const { reason, description } = options || { reason: "MANUAL" /* Manual */, description: "The track was skipped manually" }; this.queue.emit( GuildQueueEvent.PlayerSkip, this.queue, track, reason, description ); return true; } /** * Remove the given track from queue * @param track The track to remove * @param emitEvent Whether or not to emit the event @defaultValue true */ remove(track, emitEvent = true) { const foundTrack = this.queue.tracks.find((t, idx) => { if (track instanceof Track || typeof track === "string") { return (typeof track === "string" ? track : track.id) === t.id; } if (typeof track === "string") return track === t.id; return idx === track; }); if (!foundTrack) return null; this.queue.tracks.removeOne((t) => t.id === foundTrack.id); if (emitEvent) this.queue.emit(GuildQueueEvent.AudioTrackRemove, this.queue, foundTrack); return foundTrack; } /** * Jump to specific track on the queue * @param track The track to jump to without removing other tracks */ jump(track) { const removed = this.remove(track, false); if (!removed) return false; this.queue.tracks.store.unshift(removed); return this.skip({ reason: "JUMPED_TO_ANOTHER_TRACK" /* Jump */, description: "The track was jumped to manually" }); } /** * Get track position * @param track The track */ getTrackPosition(track) { return this.queue.tracks.toArray().findIndex((t, idx) => { if (track instanceof Track || typeof track === "string") { return (typeof track === "string" ? track : track.id) === t.id; } if (typeof track === "string") return track === t.id; return idx === track; }); } /** * Skip to the given track, removing others on the way * @param track The track to skip to */ skipTo(track) { const idx = this.getTrackPosition(track); if (idx < 0) return false; const removed = this.remove(idx); if (!removed) return false; const toRemove = this.queue.tracks.store.filter((_, i) => i <= idx); this.queue.tracks.store.splice(0, idx, removed); this.queue.emit(GuildQueueEvent.AudioTracksRemove, this.queue, toRemove); return this.skip({ reason: "SKIP_TO_ANOTHER_TRACK" /* SkipTo */, description: "The player was skipped to another track manually" }); } /** * Insert a track on the given position in queue * @param track The track to insert * @param index The position to insert to, defaults to 0. */ insert(track, index = 0) { if (!(track instanceof Track)) throw new InvalidArgTypeError( "track value", "instance of Track", String(track) ); VALIDATE_QUEUE_CAP(this.queue, track); this.queue.tracks.store.splice(index, 0, track); if (!this.queue.options.noEmitInsert) { this.queue.emit(GuildQueueEvent.AudioTrackAdd, this.queue, track); } } /** * Moves a track in the queue * @param from The track to move * @param to The position to move to */ move(from, to) { const removed = this.remove(from); if (!removed) { throw new NoResultError("invalid track to move"); } this.insert(removed, to); } /** * Copy a track in the queue * @param from The track to clone * @param to The position to clone at */ copy(from, to) { const src = this.queue.tracks.at(this.getTrackPosition(from)); if (!src) { throw new NoResultError("invalid track to copy"); } this.insert(src, to); } /** * Swap two tracks in the queue * @param first The first track to swap * @param second The second track to swap */ swap(first, second) { const src = this.getTrackPosition(first); if (src < 0) throw new NoResultError("invalid src track to swap"); const dest = this.getTrackPosition(second); if (dest < 0) throw new NoResultError("invalid dest track to swap"); const srcT = this.queue.tracks.store[src]; const destT = this.queue.tracks.store[dest]; this.queue.tracks.store[src] = destT; this.queue.tracks.store[dest] = srcT; } /** * Stop the playback * @param force Whether or not to forcefully stop the playback */ stop(force = false) { this.queue.tracks.clear(); this.queue.history.clear(); if (!this.queue.dispatcher) return false; this.queue.dispatcher.end(); if (force) { this.queue.dispatcher.destroy(); return true; } if (this.queue.options.leaveOnStop) { const tm = setTimeout(() => { if (this.isPlaying() || this.queue.tracks.size) return clearTimeout(tm); this.queue.dispatcher?.destroy(); }, this.queue.options.leaveOnStopCooldown).unref(); } return true; } /** * Request the source to seek * @param data The seek parameters */ async requestSeek(data) { const track = this.queue.currentTrack; if (!track) return false; if (track.seekable) { return track.seek(data); } return this.queue.filters.triggerReplay(data.position); } /** * Play the given track * @param res The track to play * @param options Options for playing the track */ async play(res, options) { if (!this.queue.dispatcher?.voiceConnection) { throw new NoVoiceConnectionError(); } if (this.queue.hasDebugger) this.queue.debug( `Received play request from guild ${this.queue.guild.name} (ID: ${this.queue.guild.id})` ); options = Object.assign( {}, { queue: this.queue.currentTrack != null, transitionMode: false, seek: 0 }, options ); if (res && options.queue) { if (this.queue.hasDebugger) this.queue.debug( "Requested option requires to queue the track, adding the given track to queue instead..." ); return this.queue.addTrack(res); } const track = res || this.queue.tracks.dispatch(); if (!track) { const error = new NoResultError( "Play request received but track was not provided" ); this.queue.emit(GuildQueueEvent.Error, this.queue, error); return; } if (this.queue.hasDebugger) this.queue.debug( "Requested option requires to play the track, initializing..." ); try { const assignedResource = track.resource; if (assignedResource) { if (this.queue.hasDebugger) this.queue.debug( "Track has an audio resource assigned, player will now play the resource directly..." ); this.queue.setTransitioning(!!options.transitionMode); return __privateMethod(this, _GuildQueuePlayerNode_instances, performPlay_fn).call(this, assignedResource); } if (this.queue.hasDebugger) this.queue.debug(`Initiating stream extraction process...`); const src = track.raw?.source || track.source; const qt = track.queryType || (src === "spotify" ? "spotifySong" : src === "apple_music" ? "appleMusicSong" : src); if (this.queue.hasDebugger) this.queue.debug( `Executing onBeforeCreateStream hook (QueryType: ${qt})...` ); const streamSrc = { error: null, stream: null }; await this.queue.onBeforeCreateStream?.(track, qt || "arbitrary", this.queue).then( (s) => { if (s) { streamSrc.stream = s; } }, (e) => streamSrc.error = e ); if (!streamSrc.stream && streamSrc.error) return __privateMethod(this, _GuildQueuePlayerNode_instances, throw_fn).call(this, track, streamSrc.error); if (!streamSrc.stream) { if (this.queue.hasDebugger) this.queue.debug( "Failed to get stream from onBeforeCreateStream, attempting to extract stream using extractors..." ); await this.queue.player.extractors.context.provide( { id: crypto.randomUUID(), attemptedExtractors: /* @__PURE__ */ new Set(), bridgeAttemptedExtractors: /* @__PURE__ */ new Set() }, () => __privateMethod(this, _GuildQueuePlayerNode_instances, createGenericStream_fn).call(this, track).then(async (r) => { if (r?.result) { streamSrc.stream = await this.queue.onStreamExtracted?.( r.result, track, this.queue ) ?? r.result; return; } if (r?.error) { streamSrc.error = r.error; return; } streamSrc.stream = streamSrc.error = null; }).catch((e) => streamSrc.error = e) ); } if (!streamSrc.stream) return __privateMethod(this, _GuildQueuePlayerNode_instances, throw_fn).call(this, track, streamSrc.error); if (typeof options.seek === "number" && options.seek >= 0) { __privateSet(this, _progress, options.seek); } else { __privateSet(this, _progress, 0); } const trackStreamConfig = { dispatcherConfig: { disableBiquad: this.queue.options.disableBiquad, disableEqualizer: this.queue.options.disableEqualizer, disableVolume: this.queue.options.disableVolume, disableFilters: this.queue.options.disableFilterer, disableResampler: this.queue.options.disableResampler, disableCompressor: this.queue.options.disableCompressor, disableReverb: this.queue.options.disableReverb, disableSeeker: this.queue.options.disableSeeker, compressor: this.queue.filters._lastFiltersCache.compressor ?? void 0, reverb: this.queue.filters._lastFiltersCache.reverb ?? void 0, seeker: { seekTarget: options.transitionMode && options.seek != null ? options.seek : null, totalDuration: track.durationMS ?? 0 }, sampleRate: this.queue.filters._lastFiltersCache.sampleRate ?? (typeof this.queue.options.resampler === "number" && this.queue.options.resampler > 0 ? this.queue.options.resampler : void 0), biquadFilter: this.queue.filters._lastFiltersCache.biquad || void 0, eq: this.queue.filters._lastFiltersCache.equalizer, defaultFilters: this.queue.filters._lastFiltersCache.filters, volume: this.queue.filters._lastFiltersCache.volume, data: track, type: import_discord_voip2.StreamType.Raw, skipFFmpeg: this.queue.player.options.skipFFmpeg }, playerConfig: options }; let resolver = Util.noop; const donePromise = new Promise((resolve2) => resolver = resolve2); const success = this.queue.emit( GuildQueueEvent.WillPlayTrack, this.queue, track, trackStreamConfig, resolver ); if (!success) resolver(); if (this.queue.hasDebugger) this.queue.debug("Waiting for willPlayTrack event to resolve..."); await donePromise; const daspDisabled = [ trackStreamConfig.dispatcherConfig.disableBiquad, trackStreamConfig.dispatcherConfig.disableEqualizer, trackStreamConfig.dispatcherConfig.disableFilters, trackStreamConfig.dispatcherConfig.disableResampler, trackStreamConfig.dispatcherConfig.disableVolume, trackStreamConfig.dispatcherConfig.disableCompressor, trackStreamConfig.dispatcherConfig.disableReverb, trackStreamConfig.dispatcherConfig.disableSeeker ].every((e) => !!e === true); const needsFilters = !!trackStreamConfig.playerConfig.seek || !!this.queue.filters.ffmpeg.args.length; const shouldSkipFFmpeg = !!trackStreamConfig.dispatcherConfig.skipFFmpeg && !needsFilters; let finalStream; const demuxable = /* @__PURE__ */ __name((fmt) => [ import_discord_voip2.StreamType.Opus, import_discord_voip2.StreamType.WebmOpus, import_discord_voip2.StreamType.OggOpus, import_discord_voip2.StreamType.Raw, "pcm" ].includes(fmt), "demuxable"); if (shouldSkipFFmpeg && !(streamSrc.stream instanceof import_stream.Readable) && typeof streamSrc.stream !== "string" && demuxable(streamSrc.stream.$fmt)) { const { $fmt, stream } = streamSrc.stream; const shouldPCM = !daspDisabled; if (this.queue.hasDebugger) this.queue.debug( `skipFFmpeg is set to true and stream is demuxable, creating stream with type ${shouldPCM ? "pcm" : "opus"}` ); const isRaw = $fmt === "pcm" || $fmt === import_discord_voip2.StreamType.Raw; const opusStream = isRaw || $fmt === import_discord_voip2.StreamType.Opus ? stream : $fmt === import_discord_voip2.StreamType.OggOpus ? ( // eslint-disable-next-line @typescript-eslint/no-explicit-any stream.pipe(new import_opus.OggDemuxer()) ) : ( // eslint-disable-next-line @typescript-eslint/no-explicit-any stream.pipe(new import_opus.WebmDemuxer()) ); if (shouldPCM) { if (isRaw) { finalStream = opusStream; } else { finalStream = opusStream.pipe( new import_opus.OpusDecoder({ channels: 2, frameSize: 960, rate: 48e3 }) ); trackStreamConfig.dispatcherConfig.type = import_discord_voip2.StreamType.Raw; } } else { finalStream = opusStream; trackStreamConfig.dispatcherConfig.type = import_discord_voip2.StreamType.Opus; } } else { finalStream = __privateMethod(this, _GuildQueuePlayerNode_instances, createFFmpegStream_fn).call(this, streamSrc.stream instanceof import_stream.Readable || typeof streamSrc.stream === "string" ? streamSrc.stream : streamSrc.stream.stream, track, options.seek ?? 0); trackStreamConfig.dispatcherConfig.type = import_discord_voip2.StreamType.Raw; } if (options.transitionMode) { if (this.queue.hasDebugger) this.queue.debug( `Transition mode detected, player will wait for buffering timeout to expire (Timeout: ${this.queue.options.bufferingTimeout}ms)` ); await (0, import_promises2.setTimeout)(this.queue.options.bufferingTimeout); if (this.queue.hasDebugger) this.queue.debug("Buffering timeout has expired!"); } if (this.queue.hasDebugger) this.queue.debug( `Preparing final stream config: ${JSON.stringify( trackStreamConfig, null, 2 )}` ); const dispatcher = this.queue.dispatcher; if (!dispatcher) { if (this.queue.hasDebugger) { this.queue.debug( "Dispatcher is not available, this is most likely due to the queue being deleted in the middle of operation. Cancelling the stream..." ); } finalStream.destroy(); } else { const resource = await dispatcher.createStream( finalStream, trackStreamConfig.dispatcherConfig ); this.queue.setTransitioning(!!options.transitionMode); await __privateMethod(this, _GuildQueuePlayerNode_instances, performPlay_fn).call(this, resource); } } catch (e) { if (this.queue.hasDebugger) this.queue.debug(`Failed to initialize audio player: ${e}`); throw e; } } }; _progress = new WeakMap(); _hasFFmpegOptimization = new WeakMap(); _GuildQueuePlayerNode_instances = new WeakSet(); throw_fn = /* @__PURE__ */ __name(function(track, error) { const streamDefinitelyFailedMyDearT_TPleaseTrustMeItsNotMyFault = new NoResultError(`Could not extract stream for this track${error ? ` ${error.stack || error}` : ""}`); this.queue.emit( GuildQueueEvent.PlayerSkip, this.queue, track, "ERR_NO_STREAM" /* NoStream */, streamDefinitelyFailedMyDearT_TPleaseTrustMeItsNotMyFault.message ); this.queue.emit( GuildQueueEvent.PlayerError, this.queue, streamDefinitelyFailedMyDearT_TPleaseTrustMeItsNotMyFault, track ); const nextTrack = this.queue.tracks.dispatch(); if (nextTrack) return void this.play(nextTrack, { queue: false }); this.queue.dispatcher?.emit("finish", null); }, "#throw"); performPlay_fn = /* @__PURE__ */ __name(async function(resource) { if (!this.queue.dispatcher) { if (this.queue.hasDebugger) { this.queue.debug( "Dispatcher is not available, this is most likely due to the queue being deleted in the middle of operation. Cancelling the stream..." ); } } else { if (this.queue.hasDebugger) this.queue.debug("Initializing audio player..."); await this.queue.dispatcher.playStream(resource); if (this.queue.hasDebugger) this.queue.debug("Dispatching audio..."); } }, "#performPlay"); createGenericStream_fn = /* @__PURE__ */ __name(async function(track) { if (this.queue.hasDebugger) this.queue.debug( `Attempting to extract stream for Track { title: ${track.title}, url: ${track.url} } using registered extractors` ); const attemptedExtractors = this.queue.player.extractors.getContext()?.attemptedExtractors || /* @__PURE__ */ new Set(); const streamInfo = await this.queue.player.extractors.run( async (extractor) => { if (this.queue.player.options.blockStreamFrom?.some( (ext) => ext === extractor.identifier )) return false; if (attemptedExtractors.has(extractor.identifier)) return false; attemptedExtractors.add(extractor.identifier); const canStream = await extractor.validate( track.url, track.queryType || QueryResolver.resolve(track.url).type ); if (!canStream) return false; return await extractor.stream(track); }, false ); if (!streamInfo || !streamInfo.result) { if (this.queue.hasDebugger) { this.queue.debug( `Failed to extract stream for Track { title: ${track.title}, url: ${track.url} } using registered extractors` ); } if (!this.queue.options.disableFallbackStream) { if (this.queue.hasDebugger) this.queue.debug( `Generic stream extraction failed and fallback stream extraction is enabled` ); return __privateMethod(this, _GuildQueuePlayerNode_instances, createFallbackStream_fn).call(this, track); } return streamInfo || null; } if (this.queue.hasDebugger) this.queue.debug( `Stream extraction was successful for Track { title: ${track.title}, url: ${track.url} } (Extractor: ${streamInfo.extractor?.identifier || "N/A"})` ); return streamInfo; }, "#createGenericStream"); createFallbackStream_fn = /* @__PURE__ */ __name(async function(track) { if (this.queue.hasDebugger) this.queue.debug( `Attempting to extract stream for Track { title: ${track.title}, url: ${track.url} } using fallback streaming method...` ); const verifyFallbackStream = this.queue.options.verifyFallbackStream; const fallbackStream = await this.queue.player.extractors.run( async (extractor) => { if (extractor.identifier === track.extractor?.identifier) return false; if (this.queue.player.options.blockStreamFrom?.some( (ext) => ext === extractor.identifier )) { return false; } const query = `${track.title} ${track.author}`; if (verifyFallbackStream) { if (this.queue.hasDebugger) { this.queue.debug( `Fallback stream verification is enabled, validating query for Track { title: ${track.title}, url: ${track.url} } using ${extractor.identifier}...` ); } const shouldProceed = await extractor.validate( query, track.queryType || track.source ); if (!shouldProceed) { if (this.queue.hasDebugger) this.queue.debug( `Failed to validate query for Track { title: ${track.title}, url: ${track.url} } using ${extractor.identifier}` ); return false; } else { if (this.queue.hasDebugger) this.queue.debug( `Query for Track { title: ${track.title}, url: ${track.url} } was validated using ${extractor.identifier}. Proceeding with extraction...` ); } } const fallbackTracks = await extractor.handle(query, { requestedBy: track.requestedBy }); const fallbackTrack = fallbackTracks.tracks[0]; if (!fallbackTrack) return false; const stream = await extractor.stream(fallbackTrack); if (!stream) return false; track.bridgedTrack = fallbackTrack; return stream; }, true ); if (!fallbackStream || !fallbackStream.result) { if (this.queue.hasDebugger) this.queue.debug( `Failed to extract stream for Track { title: ${track.title}, url: ${track.url} } using fallback streaming method` ); return fallbackStream || null; } track.bridgedExtractor = fallbackStream.extractor; return fallbackStream; }, "#createFallbackStream"); createFFmpegStream_fn = /* @__PURE__ */ __name(function(stream, track, seek = 0, opus) { const ffmpegStream = this.queue.filters.ffmpeg.createStream(stream, { encoderArgs: this.queue.filters.ffmpeg.args, seek: seek / 1e3, fmt: opus ? "opus" : "s16le", requestOptions: track.raw?.requestOptions }).on("error", (err) => { const m = `${err}`.toLowerCase(); if (this.queue.hasDebugger) this.queue.debug( `Stream closed due to an error from FFmpeg stream: ${err.stack || err.message || err}` ); if (m.includes("premature close") || m.includes("epipe")) return; this.queue.emit(GuildQueueEvent.PlayerError, this.queue, err, track); }); return ffmpegStream; }, "#createFFmpegStream"); __name(_GuildQueuePlayerNode, "GuildQueuePlayerNode"); var GuildQueuePlayerNode = _GuildQueuePlayerNode; // src/queue/GuildQueueAudioFilters.ts var import_equalizer2 = require("@discord-player/equalizer"); // src/utils/FFmpegStream.ts var import_ffmpeg = require("@discord-player/ffmpeg"); function FFMPEG_ARGS_STRING(stream, fmt, cookies, requestOptions) { const args = []; args.push("-reconnect", "1"); args.push("-reconnect_streamed", "1"); args.push("-reconnect_delay_max", "5"); if (requestOptions?.headers) { const userAgent = requestOptions.headers["user-agent"] || requestOptions.headers["User-Agent"]; if (userAgent) { args.push("-user_agent", String(userAgent)); } const formattedHeaders = formatFFmpegHeaders( requestOptions.headers ); if (formattedHeaders) { args.push("-headers", formattedHeaders); } } if (typeof cookies === "string") { const cookieValue = !cookies.includes(" ") ? cookies : `"${cookies}"`; args.push("-cookies", cookieValue); } args.push("-i", stream); args.push("-analyzeduration", "0"); args.push("-loglevel", "0"); args.push("-ar", "48000"); args.push("-ac", "2"); args.push("-f", typeof fmt === "string" ? fmt : "s16le"); if (fmt === "opus") { args.push("-acodec", "libopus"); } return args; } __name(FFMPEG_ARGS_STRING, "FFMPEG_ARGS_STRING"); function formatFFmpegHeaders(headers) { const headerPairs = []; for (const [name, value] of Object.entries(headers)) { if (value && name.toLowerCase() !== "user-agent") { const valueStr = Array.isArray(value) ? value.join(", ") : String(value); headerPairs.push(`${name}: ${valueStr}`); } } return headerPairs.length > 0 ? headerPairs.join("\r\n") : null; } __name(formatFFmpegHeaders, "formatFFmpegHeaders"); function FFMPEG_ARGS_PIPED(fmt) { const args = (0, import_ffmpeg.createFFmpegArgs)({ analyzeduration: 0, loglevel: 0, ar: 48e3, ac: 2, f: `${typeof fmt === "string" ? fmt : "s16le"}`, acodec: fmt === "opus" ? "libopus" : null }); return args; } __name(FFMPEG_ARGS_PIPED, "FFMPEG_ARGS_PIPED"); function createFFmpegStream(stream, options) { if (options?.skip && typeof stream !== "string") return stream; options ?? (options = {}); const args = typeof stream === "string" ? FFMPEG_ARGS_STRING( stream, options.fmt, options.cookies, options.requestOptions ) : FFMPEG_ARGS_PIPED(options.fmt); if (!Number.isNaN(options.seek)) args.unshift("-ss", String(options.seek)); if (Array.isArray(options.encoderArgs)) args.push(...options.encoderArgs); const transcoder = new import_ffmpeg.FFmpeg({ shell: false, args }); transcoder.on("close", () => transcoder.destroy()); if (typeof stream !== "string") { stream.on("error", () => transcoder.destroy()); stream.pipe(transcoder); } return transcoder; } __name(createFFmpegStream, "createFFmpegStream"); // src/queue/GuildQueueAudioFilters.ts var makeBands = /* @__PURE__ */ __name((arr) => { return Array.from( { length: import_equalizer2.Equalizer.BAND_COUNT }, (_, i) => ({ band: i, gain: arr[i] ? arr[i] / 30 : 0 }) ); }, "makeBands"); var EqualizerConfigurationPreset = Object.freeze({ Flat: makeBands([]), Classical: makeBands( [ -111022e-20, -111022e-20, -111022e-20, -111022e-20, -111022e-20, -111022e-20, -7.2, -7.2, -7.2, -9.6 ] ), Club: makeBands( [ -111022e-20, -111022e-20, 8, 5.6, 5.6, 5.6, 3.2, -111022e-20, -111022e-20, -111022e-20 ] ), Dance: makeBands( [ 9.6, 7.2, 2.4, -111022e-20, -111022e-20, -5.6, -7.2, -7.2, -111022e-20, -111022e-20 ] ), FullBass: makeBands( [ -8, 9.6, 9.6, 5.6, 1.6, -4, -8, -10.4, -11.2, -11.2 ] ), FullBassTreble: makeBands( [ 7.2, 5.6, -111022e-20, -7.2, -4.8, 1.6, 8, 11.2, 12, 12 ] ), FullTreble: makeBands( [ -9.6, -9.6, -9.6, -4, 2.4, 11.2, 16, 16, 16, 16.8 ] ), Headphones: makeBands( [ 4.8, 11.2, 5.6, -3.2, -2.4, 1.6, 4.8, 9.6, 12.8, 14.4 ] ), LargeHall: makeBands( [ 10.4, 10.4, 5.6, 5.6, -111022e-20, -4.8, -4.8, -4.8, -111022e-20, -111022e-20 ] ), Live: makeBands([-4.8, -111022e-20, 4, 5.6, 5.6, 5.6, 4, 2.4, 2.4, 2.4]), Party: makeBands( [ 7.2, 7.2, -111022e-20, -111022e-20, -111022e-20, -111022e-20, -111022e-20, -111022e-20, 7.2, 7.2 ] ), Pop: makeBands( [ -1.6, 4.8, 7.2, 8, 5.6, -111022e-20, -2.4, -2.4, -1.6, -1.6 ] ), Reggae: makeBands( [ -111022e-20, -111022e-20, -111022e-20, -5.6, -111022e-20, 6.4, 6.4, -111022e-20, -111022e-20, -111022e-20 ] ), Rock: makeBands([8, 4.8, -5.6, -8, -3.2, 4, 8.8, 11.2, 11.2, 11.2]), Ska: makeBands( [ -2.4, -4.8, -4, -111022e-20, 4, 5.6, 8.8, 9.6, 11.2, 9.6 ] ), Soft: makeBands( [ 4.8, 1.6, -111022e-20, -2.4, -111022e-20, 4, 8, 9.6, 11.2, 12 ] ), SoftRock: makeBands( [ 4, 4, 2.4, -111022e-20, -4, -5.6, -3.2, -111022e-20, 2.4, 8.8 ] ), Techno: makeBands( [ 8, 5.6, -111022e-20, -5.6, -4.8, -111022e-20, 8, 9.6, 9.6, 8.8 ] ) }); var _ffmpegFilters, _inputArgs, _FFmpegFilterer_instances, setFilters_fn; var _FFmpegFilterer = class _FFmpegFilterer { constructor(af) { this.af = af; __privateAdd(this, _FFmpegFilterer_instances); __privateAdd(this, _ffmpegFilters, []); __privateAdd(this, _inputArgs, []); } /** * Indicates whether ffmpeg may be skipped */ get skippable() { return !!this.af.queue.player.options.skipFFmpeg; } /** * Set input args for FFmpeg */ setInputArgs(args) { if (!args.every((arg) => typeof arg === "string")) throw new InvalidArgTypeError("args", "Array", "invalid item(s)"); __privateSet(this, _inputArgs, args); } /** * Get input args */ get inputArgs() { return __privateGet(this, _inputArgs); } /** * Get encoder args */ get encoderArgs() { if (!this.filters.length) return []; return ["-af", this.toString()]; } /** * Get final ffmpeg args */ get args() { return this.inputArgs.concat(this.encoderArgs); } /** * Create ffmpeg stream * @param source The stream source * @param options The stream options */ createStream(source, options) { if (__privateGet(this, _inputArgs).length) options.encoderArgs = [ ...__privateGet(this, _inputArgs), ...options.encoderArgs || [] ]; const stream = createFFmpegStream(source, options); return stream; } /** * Set ffmpeg filters * @param filters The filters */ setFilters(filters) { let _filters = []; if (typeof filters === "boolean") { _filters = !filters ? [] : Object.keys(AudioFilters.filters); } else if (Array.isArray(filters)) { _filters = filters; } else { _filters = Object.entries(filters).filter((res) => res[1] === true).map((m) => m[0]); } return __privateMethod(this, _FFmpegFilterer_instances, setFilters_fn).call(this, _filters); } /** * Currently active ffmpeg filters */ get filters() { return __privateGet(this, _ffmpegFilters); } set filters(filters) { this.setFilters(filters); } /** * Toggle given ffmpeg filter(s) * @param filters The filter(s) */ toggle(filters) { if (!Array.isArray(filters)) filters = [filters]; const fresh = []; filters.forEach((f) => { if (this.filters.includes(f)) return; fresh.push(f); }); return __privateMethod(this, _FFmpegFilterer_instances, setFilters_fn).call(this, __privateGet(this, _ffmpegFilters).filter((r) => !filters.includes(r)).concat(fresh)); } /** * Set default filters * @param ff Filters list */ setDefaults(ff) { __privateSet(this, _ffmpegFilters, ff); } /** * Get list of enabled filters */ getFiltersEnabled() { return __privateGet(this, _ffmpegFilters); } /** * Get list of disabled filters */ getFiltersDisabled() { return AudioFilters.names.filter((f) => !__privateGet(this, _ffmpegFilters).includes(f)); } /** * Check if the given filter is enabled * @param filter The filter */ isEnabled(filter) { return __privateGet(this, _ffmpegFilters).includes(filter); } /** * Check if the given filter is disabled * @param filter The filter */ isDisabled(filter) { return !this.isEnabled(filter); } /** * Check if the given filter is a valid filter * @param filter The filter to test */ isValidFilter(filter) { return AudioFilters.has(filter); } /** * Convert current filters to array */ toArray() { return this.filters.map((filter) => AudioFilters.get(filter)); } /** * Convert current filters to JSON object */ toJSON() { const obj = {}; this.filters.forEach((filter) => obj[filter] = AudioFilters.get(filter)); return obj; } /** * String representation of current filters */ toString() { return AudioFilters.create(this.filters); } }; _ffmpegFilters = new WeakMap(); _inputArgs = new WeakMap(); _FFmpegFilterer_instances = new WeakSet(); setFilters_fn = /* @__PURE__ */ __name(function(filters) { const { queue } = this.af; if (filters.every((f) => __privateGet(this, _ffmpegFilters).includes(f)) && __privateGet(this, _ffmpegFilters).every((f) => filters.includes(f))) return Promise.resolve(false); const ignoreFilters = this.filters.some((ff) => ff === "nightcore" || ff === "vaporwave") && !filters.some((ff) => ff === "nightcore" || ff === "vaporwave"); const seekTime = queue.node.getTimestamp(ignoreFilters)?.current.value || 0; const prev = __privateGet(this, _ffmpegFilters).slice(); __privateSet(this, _ffmpegFilters, [...new Set(filters)]); return this.af.triggerReplay(seekTime).then((t) => { queue.emit( GuildQueueEvent.AudioFiltersUpdate, queue, prev, __privateGet(this, _ffmpegFilters).slice() ); return t; }); }, "#setFilters"); __name(_FFmpegFilterer, "FFmpegFilterer"); var FFmpegFilterer = _FFmpegFilterer; var _GuildQueueAudioFilters = class _GuildQueueAudioFilters { constructor(queue) { this.queue = queue; __publicField(this, "graph", new AFilterGraph(this)); __publicField(this, "ffmpeg", new FFmpegFilterer(this)); __publicField(this, "equalizerPresets", EqualizerConfigurationPreset); __publicField(this, "_lastFiltersCache", { biquad: null, equalizer: [], filters: [], volume: 100, sampleRate: -1, compressor: null, reverb: null, sampleRateFilter: null }); if (typeof this.queue.options.volume === "number") { this._lastFiltersCache.volume = this.queue.options.volume; } } // TODO: enable this in the future // public get ffmpeg(): FFmpegFilterer | null { // if (this.queue.player.options.skipFFmpeg) { // if (this.#ffmpeg) this.#ffmpeg = null; // return null; // } // if (!this.#ffmpeg) { // this.#ffmpeg = new FFmpegFilterer(this); // } // return this.#ffmpeg; // } /** * Volume transformer */ get volume() { return this.queue.dispatcher?.dsp?.volume || null; } /** * 15 Band Equalizer */ get equalizer() { return this.queue.dispatcher?.equalizer || null; } /** * Digital biquad filters */ get biquad() { return this.queue.dispatcher?.biquad || null; } /** * DSP filters */ get filters() { return this.queue.dispatcher?.filters || null; } /** * Audio resampler */ get resampler() { return this.queue.dispatcher?.resampler || null; } /** * Compressor transformer */ get compressor() { return this.queue.dispatcher?.compressor || null; } /** * Reverb transformer */ get reverb() { return this.queue.dispatcher?.reverb || null; } /** * PCM Seeker transformer */ get seeker() { return this.queue.dispatcher?.seeker || null; } /** * Replay current track in transition mode * @param seek The duration to seek to */ async triggerReplay(seek = 0) { if (!this.queue.currentTrack) return false; const entry = this.queue.node.tasksQueue.acquire(); try { await entry.getTask(); await this.queue.node.play(this.queue.currentTrack, { queue: false, seek, transitionMode: true }); this.queue.node.tasksQueue.release(); return true; } catch { this.queue.node.tasksQueue.release(); return false; } } }; __name(_GuildQueueAudioFilters, "GuildQueueAudioFilters"); var GuildQueueAudioFilters = _GuildQueueAudioFilters; var _AFilterGraph = class _AFilterGraph { constructor(af) { this.af = af; } get ffmpeg() { return this.af.ffmpeg?.filters ?? []; } get equalizer() { return (this.af.equalizer?.bandMultipliers || []).map((m, i) => ({ band: i, gain: m })); } get biquad() { return this.af.biquad?.getFilterName() || null; } get filters() { return this.af.filters?.filters || []; } get volume() { return this.af.volume; } get resampler() { return this.af.resampler; } dump() { return { ffmpeg: this.ffmpeg, equalizer: this.equalizer, biquad: this.biquad, filters: this.filters, sampleRate: this.resampler?.sampleRate || 48e3, volume: this.volume?.volume ?? 100 }; } }; __name(_AFilterGraph, "AFilterGraph"); var AFilterGraph = _AFilterGraph; // src/queue/GuildQueue.ts var import_timers = require("timers"); // src/queue/GuildQueueStatistics.ts var _GuildQueueStatistics = class _GuildQueueStatistics { constructor(queue) { this.queue = queue; } /** * Generate statistics of this queue */ generate() { return { latency: { eventLoop: this.queue.player.eventLoopLag, voiceConnection: this.queue.ping }, status: { buffering: this.queue.node.isBuffering(), playing: this.queue.node.isPlaying(), paused: this.queue.node.isPaused(), idle: this.queue.node.isIdle() }, tracksCount: this.queue.tracks.size, historySize: this.queue.history.tracks.size, extractors: this.queue.player.extractors.size, listeners: this.queue.guild.members.me?.voice.channel?.members.filter( (m) => !m.user.bot ).size || 0, memoryUsage: process.memoryUsage(), versions: { node: process.version, player: this.queue.player.version } }; } }; __name(_GuildQueueStatistics, "GuildQueueStatistics"); var GuildQueueStatistics = _GuildQueueStatistics; // src/queue/SyncedLyricsProvider.ts var timestampPattern = /\[(\d{2}):(\d{2})\.(\d{2})\]/; var _loop, _callback, _onUnsubscribe, _SyncedLyricsProvider_instances, createLoop_fn; var _SyncedLyricsProvider = class _SyncedLyricsProvider { constructor(queue, raw) { this.queue = queue; this.raw = raw; __privateAdd(this, _SyncedLyricsProvider_instances); __privateAdd(this, _loop, null); __privateAdd(this, _callback, null); __privateAdd(this, _onUnsubscribe, null); __publicField(this, "interval", 100); __publicField(this, "lyrics", /* @__PURE__ */ new Map()); if (raw?.syncedLyrics) this.load(raw?.syncedLyrics); } isSubscribed() { return __privateGet(this, _callback) !== null; } load(lyrics) { if (!lyrics) throw new NotExistingError("syncedLyrics"); this.lyrics.clear(); this.unsubscribe(); const lines = lyrics.split("\n"); for (const line of lines) { const match = line.match(timestampPattern); if (match) { const [, minutes, seconds, milliseconds] = match; const timestamp = parseInt(minutes) * 60 * 1e3 + parseInt(seconds) * 1e3 + parseInt(milliseconds); this.lyrics.set(timestamp, line.replace(timestampPattern, "").trim()); } } } /** * Returns the lyrics at a specific time or at the closest time (±2 seconds) * @param time The time in milliseconds */ at(time) { const lowestTime = this.lyrics.keys().next().value; if (lowestTime == null || time < lowestTime) return null; if (this.lyrics.has(time)) return { line: this.lyrics.get(time), timestamp: time }; const keys = Array.from(this.lyrics.keys()); const closest = keys.reduce( (a, b) => Math.abs(b - time) < Math.abs(a - time) ? b : a ); if (closest > time) return null; if (Math.abs(closest - time) > 2e3) return null; const line = this.lyrics.get(closest); if (!line) return null; return { timestamp: closest, line }; } /** * Callback for the lyrics change. * @param callback The callback function */ onChange(callback) { __privateSet(this, _callback, callback); } /** * Callback to detect when the provider is unsubscribed. * @param callback The callback function */ onUnsubscribe(callback) { __privateSet(this, _onUnsubscribe, callback); } /** * Unsubscribes from the queue. */ unsubscribe() { if (__privateGet(this, _loop)) clearInterval(__privateGet(this, _loop)); if (__privateGet(this, _onUnsubscribe)) __privateGet(this, _onUnsubscribe).call(this); __privateSet(this, _callback, null); __privateSet(this, _onUnsubscribe, null); __privateSet(this, _loop, null); } /** * Subscribes to the queue to monitor the current time. * @returns The unsubscribe function */ subscribe() { if (__privateGet(this, _loop)) return () => this.unsubscribe(); __privateMethod(this, _SyncedLyricsProvider_instances, createLoop_fn).call(this); return () => this.unsubscribe(); } /** * Pauses the lyrics provider. */ pause() { const hasLoop = __privateGet(this, _loop) !== null; if (hasLoop) { clearInterval(__privateGet(this, _loop)); __privateSet(this, _loop, null); } return hasLoop; } /** * Resumes the lyrics provider. */ resume() { const hasLoop = __privateGet(this, _loop) !== null; if (!hasLoop) __privateMethod(this, _SyncedLyricsProvider_instances, createLoop_fn).call(this); return !hasLoop; } }; _loop = new WeakMap(); _callback = new WeakMap(); _onUnsubscribe = new WeakMap(); _SyncedLyricsProvider_instances = new WeakSet(); createLoop_fn = /* @__PURE__ */ __name(function() { if (!__privateGet(this, _callback)) return; if (__privateGet(this, _loop)) clearInterval(__privateGet(this, _loop)); let lastValue = null; __privateSet(this, _loop, setInterval(() => { if (this.queue.deleted) return this.unsubscribe(); if (!__privateGet(this, _callback) || !this.queue.isPlaying()) return; const time = this.queue.node.getTimestamp(); if (!time) return; const lyrics = this.at(time.current.value); if (!lyrics) return; if (lastValue !== null && lyrics.line === lastValue.line && lyrics.timestamp === lastValue.timestamp) return; lastValue = lyrics; __privateGet(this, _callback).call(this, lyrics.line, lyrics.timestamp); }, this.interval).unref()); }, "#createLoop"); __name(_SyncedLyricsProvider, "SyncedLyricsProvider"); var SyncedLyricsProvider = _SyncedLyricsProvider; // src/queue/GuildQueue.ts var GuildQueueEvent = { /** * Emitted when audio track is added to the queue */ AudioTrackAdd: "audioTrackAdd", /** * Emitted when audio tracks were added to the queue */ AudioTracksAdd: "audioTracksAdd", /** * Emitted when audio track is removed from the queue */ AudioTrackRemove: "audioTrackRemove", /** * Emitted when audio tracks are removed from the queue */ AudioTracksRemove: "audioTracksRemove", /** * Emitted when a connection is created */ Connection: "connection", /** * Emitted when a voice connection is destroyed */ ConnectionDestroyed: "connectionDestroyed", /** * Emitted when the bot is disconnected from the channel */ Disconnect: "disconnect", /** * Emitted when the queue sends a debug info */ Debug: "debug", /** * Emitted when the queue encounters error */ Error: "error", /** * Emitted when the voice channel is empty */ EmptyChannel: "emptyChannel", /** * Emitted when the queue is empty */ EmptyQueue: "emptyQueue", /** * Emitted when the audio player starts streaming audio track */ PlayerStart: "playerStart", /** * Emitted when the audio player errors while streaming audio track */ PlayerError: "playerError", /** * Emitted when the audio player finishes streaming audio track */ PlayerFinish: "playerFinish", /** * Emitted when the audio player skips current track */ PlayerSkip: "playerSkip", /** * Emitted when the audio player is triggered */ PlayerTrigger: "playerTrigger", /** * Emitted when the voice state is updated. Consuming this event may disable default voice state update handler if `Player.isVoiceStateHandlerLocked()` returns `false`. */ VoiceStateUpdate: "voiceStateUpdate", /** * Emitted when volume is updated */ VolumeChange: "volumeChange", /** * Emitted when player is paused */ PlayerPause: "playerPause", /** * Emitted when player is resumed */ PlayerResume: "playerResume", /** * Biquad Filters Update */ BiquadFiltersUpdate: "biquadFiltersUpdate", /** * Equalizer Update */ EqualizerUpdate: "equalizerUpdate", /** * DSP update */ DSPUpdate: "dspUpdate", /** * Audio Filters Update */ AudioFiltersUpdate: "audioFiltersUpdate", /** * Audio player will play next track */ WillPlayTrack: "willPlayTrack", /** * Emitted when a voice channel is repopulated */ ChannelPopulate: "channelPopulate", /** * Emitted when a queue is successfully created */ QueueCreate: "queueCreate", /** * Emitted when a queue is deleted */ QueueDelete: "queueDelete", /** * Emitted when a queue is trying to add similar track for autoplay */ WillAutoPlay: "willAutoPlay", /** * Emitted when sample rate is updated */ SampleRateUpdate: "sampleRateUpdate", /** * Emitted when a named sample rate filter is updated */ SampleRateFilterUpdate: "sampleRateFilterUpdate", /** * Emitted when reverb filter is updated */ ReverbUpdate: "reverbUpdate", /** * Emitted when compressor filter is updated */ CompressorUpdate: "compressorUpdate", /** * Emitted when seek is performed */ PlayerSeek: "playerSeek" }; var TrackSkipReason = /* @__PURE__ */ ((TrackSkipReason2) => { TrackSkipReason2["NoStream"] = "ERR_NO_STREAM"; TrackSkipReason2["Manual"] = "MANUAL"; TrackSkipReason2["SEEK_OVER_THRESHOLD"] = "SEEK_OVER_THRESHOLD"; TrackSkipReason2["Jump"] = "JUMPED_TO_ANOTHER_TRACK"; TrackSkipReason2["SkipTo"] = "SKIP_TO_ANOTHER_TRACK"; TrackSkipReason2["HistoryNext"] = "HISTORY_NEXT_TRACK"; return TrackSkipReason2; })(TrackSkipReason || {}); var QueueRepeatMode = { /** * Disable repeat mode. */ OFF: 0, /** * Repeat the current track. */ TRACK: 1, /** * Repeat the entire queue. */ QUEUE: 2, /** * When last track ends, play similar tracks in the future if queue is empty. */ AUTOPLAY: 3 }; var _transitioning, _deleted, _shuffle, _GuildQueue_instances, attachListeners_fn, removeListeners_fn, performStart_fn, getNextTrack_fn, performFinish_fn, emitEnd_fn, handleAutoplay_fn; var _GuildQueue = class _GuildQueue { constructor(player, options) { this.player = player; this.options = options; __privateAdd(this, _GuildQueue_instances); __privateAdd(this, _transitioning, false); __privateAdd(this, _deleted, false); __privateAdd(this, _shuffle, false); __publicField(this, "__current", null); __publicField(this, "tracks"); __publicField(this, "history", new GuildQueueHistory(this)); __publicField(this, "dispatcher", null); __publicField(this, "node", new GuildQueuePlayerNode(this)); __publicField(this, "filters", new GuildQueueAudioFilters(this)); __publicField(this, "onBeforeCreateStream", /* @__PURE__ */ __name(async () => null, "onBeforeCreateStream")); __publicField(this, "onAfterCreateStream", /* @__PURE__ */ __name(async (stream) => ({ stream, type: import_discord_voip3.StreamType.Raw }), "onAfterCreateStream")); __publicField(this, "onStreamExtracted", /* @__PURE__ */ __name(async (stream) => stream, "onStreamExtracted")); __publicField(this, "repeatMode", QueueRepeatMode.OFF); __publicField(this, "timeouts", new import_utils6.Collection()); __publicField(this, "stats", new GuildQueueStatistics(this)); __publicField(this, "tasksQueue", new AsyncQueue()); __publicField(this, "syncedLyricsProvider", new SyncedLyricsProvider(this)); this.tracks = new import_utils6.Queue(options.queueStrategy); if (TypeUtil.isFunction(options.onBeforeCreateStream)) this.onBeforeCreateStream = options.onBeforeCreateStream; if (TypeUtil.isFunction(options.onAfterCreateStream)) this.onAfterCreateStream = options.onAfterCreateStream; if (TypeUtil.isFunction(options.onStreamExtracted)) this.onStreamExtracted = options.onStreamExtracted; if (!TypeUtil.isNullish(options.repeatMode)) this.repeatMode = options.repeatMode; options.selfDeaf ?? (options.selfDeaf = true); options.maxSize ?? (options.maxSize = Infinity); options.maxHistorySize ?? (options.maxHistorySize = Infinity); options.pauseOnEmpty ?? (options.pauseOnEmpty = true); if (!TypeUtil.isNullish(this.options.biquad) && !TypeUtil.isBoolean(this.options.biquad)) { this.filters._lastFiltersCache.biquad = this.options.biquad; } if (Array.isArray(this.options.equalizer)) { this.filters._lastFiltersCache.equalizer = this.options.equalizer; } if (Array.isArray(this.options.filterer)) { this.filters._lastFiltersCache.filters = this.options.filterer; } if (TypeUtil.isNumber(this.options.resampler)) { this.filters._lastFiltersCache.sampleRate = this.options.resampler; } if (TypeUtil.isArray(this.options.ffmpegFilters)) { this.filters.ffmpeg.setDefaults(this.options.ffmpegFilters); } if (!TypeUtil.isNumber(options.maxSize)) { throw new InvalidArgTypeError( "[GuildNodeInit.maxSize]", "number", typeof options.maxSize ); } if (!TypeUtil.isNumber(options.maxHistorySize)) { throw new InvalidArgTypeError( "[GuildNodeInit.maxHistorySize]", "number", typeof options.maxHistorySize ); } if (options.maxSize < 1) options.maxSize = Infinity; if (options.maxHistorySize < 1) options.maxHistorySize = Infinity; if (this.hasDebugger) this.debug( `GuildQueue initialized for guild ${this.options.guild.name} (ID: ${this.options.guild.id})` ); this.emit(GuildQueueEvent.QueueCreate, this); } /** * Whether this queue can intercept streams */ canIntercept() { return this.options.enableStreamInterceptor; } /** * Estimated duration of this queue in ms */ get estimatedDuration() { return this.tracks.store.reduce((a, c) => a + c.durationMS, 0); } /** * Formatted duration of this queue */ get durationFormatted() { return Util.buildTimeCode(Util.parseMS(this.estimatedDuration)); } /** * The sync lyrics provider for this queue. * @example const lyrics = await player.lyrics.search({ q: 'Alan Walker Faded' }); * const syncedLyrics = queue.syncedLyrics(lyrics[0]); * console.log(syncedLyrics.at(10_000)); * // subscribe to lyrics change * const unsubscribe = syncedLyrics.onChange((lyrics, timestamp) => { * console.log(lyrics, timestamp); * }); * // unsubscribe from lyrics change * unsubscribe(); // or * syncedLyrics.unsubscribe(); */ syncedLyrics(lyrics) { this.syncedLyricsProvider.load(lyrics?.syncedLyrics ?? ""); return this.syncedLyricsProvider; } /** * Write a debug message to this queue * @param m The message to write */ debug(m) { this.emit(GuildQueueEvent.Debug, this, m); } /** * The metadata of this queue */ get metadata() { return this.options.metadata; } set metadata(m) { this.options.metadata = m; } /** * Set metadata for this queue * @param m Metadata to set */ setMetadata(m) { this.options.metadata = m; } /** * Indicates current track of this queue */ get currentTrack() { return this.dispatcher?.audioResource?.metadata || this.__current; } /** * Indicates if this queue was deleted previously */ get deleted() { return __privateGet(this, _deleted); } /** * The voice channel of this queue */ get channel() { return this.dispatcher?.channel || null; } set channel(c) { if (this.dispatcher) { if (c) { this.dispatcher.channel = c; } else { this.delete(); } } } /** * The voice connection of this queue */ get connection() { return this.dispatcher?.voiceConnection || null; } /** * The guild this queue belongs to */ get guild() { return this.options.guild; } /** * The id of this queue */ get id() { return this.guild.id; } /** * Set transition mode for this queue * @param state The state to set */ setTransitioning(state) { __privateSet(this, _transitioning, state); } /** * if this queue is currently under transition mode */ isTransitioning() { return __privateGet(this, _transitioning); } /** * Set repeat mode for this queue * @param mode The repeat mode to apply */ setRepeatMode(mode) { this.repeatMode = mode; } /** * Max size of this queue */ get maxSize() { return this.options.maxSize ?? Infinity; } /** * Max size of this queue */ getMaxSize() { return this.maxSize; } /** * Gets the size of the queue */ get size() { return this.tracks.size; } /** * The size of this queue */ getSize() { return this.size; } /** * Max history size of this queue */ get maxHistorySize() { return this.options.maxHistorySize ?? Infinity; } /** * Max history size of this queue */ getMaxHistorySize() { return this.maxHistorySize; } /** * Set max history size for this queue * @param size The size to set */ setMaxHistorySize(size) { if (!TypeUtil.isNumber(size)) { throw new InvalidArgTypeError("size", "number", typeof size); } if (size < 1) size = Infinity; this.options.maxHistorySize = size; } /** * Set max size for this queue * @param size The size to set */ setMaxSize(size) { if (!TypeUtil.isNumber(size)) { throw new InvalidArgTypeError("size", "number", typeof size); } if (size < 1) size = Infinity; this.options.maxSize = size; } /** * Clear this queue */ clear() { this.tracks.clear(); this.history.clear(); } /** * Check if this queue has no tracks left in it */ isEmpty() { return this.tracks.size < 1; } /** * Check if this queue is full */ isFull() { return this.tracks.size >= this.maxSize; } /** * Get queue capacity */ getCapacity() { if (this.isFull()) return 0; const cap = this.maxSize - this.size; return cap; } /** * Check if this queue currently holds active audio resource */ isPlaying() { return this.dispatcher?.audioResource != null && !this.dispatcher.audioResource.ended; } /** * Add track to the queue. This will emit `audioTracksAdd` when multiple tracks are added, otherwise `audioTrackAdd`. * @param track Track or playlist or array of tracks to add */ addTrack(track) { const toAdd = track instanceof Playlist ? track.tracks : track; const isMulti = Array.isArray(toAdd); VALIDATE_QUEUE_CAP(this, toAdd); this.tracks.add(toAdd); if (isMulti) { this.emit(GuildQueueEvent.AudioTracksAdd, this, toAdd); } else { this.emit(GuildQueueEvent.AudioTrackAdd, this, toAdd); } } /** * Remove a track from queue * @param track The track to remove */ removeTrack(track) { return this.node.remove(track); } /** * Prepends a track or track resolvable to the queue * @param track The track resolvable to insert * @param index The index to insert the track at (defaults to 0). If > 0, the inserted track will be placed before the track at the given index. */ prepend(track, index = 0) { if (index < 0 || index > this.tracks.size) { throw new OutOfRangeError( "index", `${index}`, "0", `${this.tracks.size}` ); } const count = Array.isArray(track) ? track.length : track instanceof import_utils6.Queue ? track.size : 1; VALIDATE_QUEUE_CAP(this, count); const insertionIndex = index === 0 ? 0 : index - 1; if (track instanceof Track) { this.node.insert(track, insertionIndex); this.emit(GuildQueueEvent.AudioTrackAdd, this, track); return; } const tracks = track instanceof import_utils6.Queue ? track.store : track; this.tracks.store.splice(insertionIndex, 0, ...tracks); if (!this.options.noEmitInsert) { this.emit(GuildQueueEvent.AudioTracksAdd, this, tracks); } } /** * Appends a track or track resolvable to the queue * @param track The track resolvable to insert * @param index The index to insert the track at (defaults to 0). If > 0, the inserted track will be placed after the track at the given index. */ append(track, index = 0) { if (index < 0 || index > this.tracks.size) { throw new OutOfRangeError( "index", `${index}`, "0", `${this.tracks.size}` ); } const count = Array.isArray(track) ? track.length : track instanceof import_utils6.Queue ? track.size : 1; VALIDATE_QUEUE_CAP(this, count); if (track instanceof Track) { this.node.insert(track, index); this.emit(GuildQueueEvent.AudioTrackAdd, this, track); return; } const tracks = track instanceof import_utils6.Queue ? track.store : track; this.tracks.store.splice(index, 0, ...tracks); if (!this.options.noEmitInsert) { this.emit(GuildQueueEvent.AudioTracksAdd, this, tracks); } } /** * Inserts the track to the given index * @param track The track to insert * @param index The index to insert the track at (defaults to 0) */ insertTrack(track, index = 0) { return this.node.insert(track, index); } /** * Moves a track in the queue * @param from The track to move * @param to The position to move to */ moveTrack(track, index = 0) { return this.node.move(track, index); } /** * Copy a track in the queue * @param from The track to clone * @param to The position to clone at */ copyTrack(track, index = 0) { return this.node.copy(track, index); } /** * Swap two tracks in the queue * @param src The first track to swap * @param dest The second track to swap */ swapTracks(src, dest) { return this.node.swap(src, dest); } /** * Create stream dispatcher from the given connection * @param connection The connection to use */ createDispatcher(connection, options = {}) { if (connection.state.status === import_discord_voip3.VoiceConnectionStatus.Destroyed) { throw new VoiceConnectionDestroyedError(); } const channel = this.player.client.channels.cache.get( connection.joinConfig.channelId ); if (!channel) throw new NoVoiceChannelError(); if (!channel.isVoiceBased()) throw new InvalidArgTypeError( "channel", `VoiceBasedChannel (type ${import_discord3.ChannelType.GuildVoice}/${import_discord3.ChannelType.GuildStageVoice})`, String(channel?.type) ); if (this.dispatcher) { __privateMethod(this, _GuildQueue_instances, removeListeners_fn).call(this, this.dispatcher); this.dispatcher.destroy(); this.dispatcher = null; } this.dispatcher = new StreamDispatcher( connection, channel, this, options.timeout ?? this.options.connectionTimeout, options.audioPlayer ); } /** * Connect to a voice channel * @param channelResolvable The voice channel to connect to * @param options Join config */ async connect(channelResolvable, options = {}) { const channel = this.player.client.channels.resolve(channelResolvable); if (!channel || !channel.isVoiceBased()) { throw new InvalidArgTypeError( "channel", `VoiceBasedChannel (type ${import_discord3.ChannelType.GuildVoice}/${import_discord3.ChannelType.GuildStageVoice})`, String(channel?.type) ); } if (this.hasDebugger) this.debug( `Connecting to ${channel.type === import_discord3.ChannelType.GuildStageVoice ? "stage" : "voice"} channel ${channel.name} (ID: ${channel.id})` ); if (this.dispatcher && channel.id !== this.dispatcher.channel.id) { if (this.hasDebugger) this.debug("Destroying old connection"); __privateMethod(this, _GuildQueue_instances, removeListeners_fn).call(this, this.dispatcher); this.dispatcher.destroy(); this.dispatcher = null; } this.dispatcher = await this.player.voiceUtils.connect(channel, { deaf: options.deaf ?? this.options.selfDeaf ?? true, maxTime: options?.timeout ?? this.options.connectionTimeout ?? 12e4, queue: this, audioPlayer: options?.audioPlayer, group: options.group ?? this.player.client.user?.id, daveEncryption: options.daveEncryption, decryptionFailureTolerance: options.decryptionFailureTolerance }); this.emit(GuildQueueEvent.Connection, this); if (this.channel.type === import_discord3.ChannelType.GuildStageVoice) { await this.channel.guild.members.me.voice.setSuppressed(false).catch( async () => { return await this.channel.guild.members.me.voice.setRequestToSpeak( true ).catch(Util.noop); } ); } __privateMethod(this, _GuildQueue_instances, attachListeners_fn).call(this, this.dispatcher); return this; } /** * Enable shuffle mode for this queue * @param dynamic Whether to shuffle the queue dynamically. Defaults to `true`. * Dynamic shuffling will shuffle the queue when the current track ends, without mutating the queue. * If set to `false`, the queue will be shuffled immediately in-place, which cannot be undone. */ enableShuffle(dynamic = true) { if (!dynamic) { this.tracks.shuffle(); return true; } __privateSet(this, _shuffle, true); return true; } /** * Disable shuffle mode for this queue. */ disableShuffle() { __privateSet(this, _shuffle, false); return true; } /** * Toggle shuffle mode for this queue. * @param dynamic Whether to shuffle the queue dynamically. Defaults to `true`. * @returns Whether shuffle is enabled or disabled. */ toggleShuffle(dynamic = true) { if (dynamic) { __privateSet(this, _shuffle, !__privateGet(this, _shuffle)); return __privateGet(this, _shuffle); } else { this.tracks.shuffle(); return true; } } /** * Whether shuffle mode is enabled for this queue. */ get isShuffling() { return __privateGet(this, _shuffle); } /** * The voice connection latency of this queue */ get ping() { return this.connection?.ping.udp ?? -1; } /** * Delete this queue */ delete() { if (this.player.nodes.delete(this.id)) { __privateSet(this, _deleted, true); this.player.events.emit(GuildQueueEvent.QueueDelete, this); this.node.tasksQueue.cancelAll(); this.tasksQueue.cancelAll(); } } /** * Revives this queue * @returns */ revive() { if (!this.deleted || this.player.nodes.has(this.id)) return; __privateSet(this, _deleted, false); this.setTransitioning(false); this.player.nodes.cache.set(this.id, this); this.player.events.emit(GuildQueueEvent.QueueCreate, this); } /** * Set self deaf * @param mode On/Off state * @param reason Reason */ setSelfDeaf(mode, reason) { return this.guild.members.me.voice.setDeaf(mode, reason); } /** * Set self mute * @param mode On/Off state * @param reason Reason */ setSelfMute(mode, reason) { return this.guild.members.me.voice.setMute(mode, reason); } /** * Play a track in this queue * @param track The track to be played * @param options Player node initialization options */ async play(track, options) { if (!this.channel) throw new NoVoiceConnectionError(); return this.player.play(this.channel, track, options); } /** * Emit an event on this queue * @param event The event to emit * @param args The args for the event */ emit(event, ...args) { if (this.deleted) return false; return this.player.events.emit(event, ...args); } get hasDebugger() { return this.player.events.hasDebugger; } }; _transitioning = new WeakMap(); _deleted = new WeakMap(); _shuffle = new WeakMap(); _GuildQueue_instances = new WeakSet(); attachListeners_fn = /* @__PURE__ */ __name(function(dispatcher) { dispatcher.on("error", (e) => this.emit(GuildQueueEvent.Error, this, e)); dispatcher.on( "debug", (m) => this.hasDebugger && this.emit(GuildQueueEvent.Debug, this, m) ); dispatcher.on("finish", (r) => __privateMethod(this, _GuildQueue_instances, performFinish_fn).call(this, r)); dispatcher.on("start", (r) => __privateMethod(this, _GuildQueue_instances, performStart_fn).call(this, r)); dispatcher.on("destroyed", () => { __privateMethod(this, _GuildQueue_instances, removeListeners_fn).call(this, dispatcher); this.dispatcher = null; }); dispatcher.on("dsp", (f) => { if (!Object.is(this.filters._lastFiltersCache.filters, f)) { this.emit( GuildQueueEvent.DSPUpdate, this, this.filters._lastFiltersCache.filters, f ); } this.filters._lastFiltersCache.filters = f; }); dispatcher.on("biquad", (f) => { if (this.filters._lastFiltersCache.biquad !== f) { this.emit( GuildQueueEvent.BiquadFiltersUpdate, this, this.filters._lastFiltersCache.biquad, f ); } this.filters._lastFiltersCache.biquad = f; }); dispatcher.on("eqBands", (f) => { if (!Object.is(f, this.filters._lastFiltersCache.equalizer)) { this.emit( GuildQueueEvent.EqualizerUpdate, this, this.filters._lastFiltersCache.equalizer, f ); } this.filters._lastFiltersCache.equalizer = f; }); dispatcher.on("volume", (f) => { if (this.filters._lastFiltersCache.volume !== f) this.emit( GuildQueueEvent.VolumeChange, this, this.filters._lastFiltersCache.volume, f ); this.filters._lastFiltersCache.volume = f; }); const areObjectsDifferent = /* @__PURE__ */ __name((a, b) => { if (!a && !b) return false; if (!a || !b) return true; if (Object.keys(a).length !== Object.keys(b).length) return true; return Object.keys(a).some((k) => a[k] !== b[k]); }, "areObjectsDifferent"); dispatcher.on("sampleRate", (f) => { if (this.filters._lastFiltersCache.sampleRate !== f.sampleRate) { this.emit( GuildQueueEvent.SampleRateUpdate, this, this.filters._lastFiltersCache.sampleRate, f.sampleRate ); this.filters._lastFiltersCache.sampleRate = f.sampleRate; this.filters.seeker?.setSampleRate(f.sampleRate); this.filters.seeker?.setTotalDuration(this.node.estimatedDuration); } if (f.currentFilter !== this.filters._lastFiltersCache.sampleRateFilter) { this.emit( GuildQueueEvent.SampleRateFilterUpdate, this, this.filters._lastFiltersCache.sampleRateFilter ?? null, f.currentFilter ); this.filters._lastFiltersCache.sampleRateFilter = f.currentFilter; } }); dispatcher.on("reverb", (f) => { if (areObjectsDifferent(f, this.filters._lastFiltersCache.reverb)) { this.emit( GuildQueueEvent.ReverbUpdate, this, this.filters._lastFiltersCache.reverb ?? null, f ); this.filters._lastFiltersCache.reverb = f; } }); dispatcher.on("seeker", (f) => { if (this.hasDebugger) { this.debug( `Seeker >> Seeked to ${f.seekTarget}ms for Track ${this.currentTrack?.title}` ); } if (f.seekTarget != null) this.node.setProgress(f.seekTarget); this.emit(GuildQueueEvent.PlayerSeek, this, f); }); dispatcher.on("compressor", (f) => { if (areObjectsDifferent(f, this.filters._lastFiltersCache.compressor)) { this.emit( GuildQueueEvent.CompressorUpdate, this, this.filters._lastFiltersCache.compressor ?? null, f ); this.filters._lastFiltersCache.compressor = f; } }); }, "#attachListeners"); removeListeners_fn = /* @__PURE__ */ __name(function(target) { target.removeAllListeners(); }, "#removeListeners"); performStart_fn = /* @__PURE__ */ __name(function(resource) { const track = resource?.metadata || this.currentTrack; const reason = this.isTransitioning() ? "filters" : "normal"; if (this.hasDebugger) this.debug( `Player triggered for Track ${JSON.stringify({ title: track?.title, reason })}` ); this.emit(GuildQueueEvent.PlayerTrigger, this, track, reason); if (track && !this.isTransitioning()) this.emit(GuildQueueEvent.PlayerStart, this, track); this.setTransitioning(false); }, "#performStart"); getNextTrack_fn = /* @__PURE__ */ __name(function() { if (!this.isShuffling) { return this.tracks.dispatch(); } const store = this.tracks.store; if (!store.length) return; const track = Util.randomChoice(store); this.tracks.removeOne((t) => { return t.id === track.id; }); return track; }, "#getNextTrack"); performFinish_fn = /* @__PURE__ */ __name(function(resource) { const track = resource?.metadata || this.currentTrack; if (this.hasDebugger) this.debug( `Track ${JSON.stringify({ title: track?.title, isTransitionMode: this.isTransitioning() })} was marked as finished` ); if (!this.isTransitioning()) { this.syncedLyricsProvider.unsubscribe(); this.syncedLyricsProvider.lyrics.clear(); if (this.hasDebugger) this.debug( "Adding track to history and emitting finish event since transition mode is disabled..." ); if (track) { this.history.push(track); this.node.resetProgress(); this.emit(GuildQueueEvent.PlayerFinish, this, track); } if (__privateGet(this, _deleted)) return __privateMethod(this, _GuildQueue_instances, emitEnd_fn).call(this); if (this.tracks.size < 1 && this.repeatMode === QueueRepeatMode.OFF) { if (this.hasDebugger) this.debug( "No more tracks left in the queue to play and repeat mode is off, initiating #emitEnd()" ); __privateMethod(this, _GuildQueue_instances, emitEnd_fn).call(this); } else { if (this.repeatMode === QueueRepeatMode.TRACK) { if (this.hasDebugger) this.debug( "Repeat mode is set to track, repeating last track from the history..." ); this.__current = this.history.tracks.dispatch() || track; return this.node.play(this.__current, { queue: false }); } if (this.repeatMode === QueueRepeatMode.QUEUE) { if (this.hasDebugger) this.debug( "Repeat mode is set to queue, moving last track from the history to current queue..." ); const next = this.history.tracks.dispatch() || track; if (next) this.tracks.add(next); } if (!this.tracks.size && track) { if (this.repeatMode === QueueRepeatMode.AUTOPLAY) { if (this.hasDebugger) this.debug( "Repeat mode is set to autoplay, initiating autoplay handler..." ); __privateMethod(this, _GuildQueue_instances, handleAutoplay_fn).call(this, track); return; } } else { if (this.hasDebugger) this.debug("Initializing next track of the queue..."); this.__current = __privateMethod(this, _GuildQueue_instances, getNextTrack_fn).call(this); this.node.play(this.__current, { queue: false }); } } } }, "#performFinish"); emitEnd_fn = /* @__PURE__ */ __name(function() { this.__current = null; this.emit(GuildQueueEvent.EmptyQueue, this); if (this.options.leaveOnEnd) { const tm = (0, import_timers.setTimeout)(() => { if (this.isPlaying()) return clearTimeout(tm); this.dispatcher?.disconnect(); }, this.options.leaveOnEndCooldown).unref(); } }, "#emitEnd"); handleAutoplay_fn = /* @__PURE__ */ __name(async function(track) { try { if (this.hasDebugger) this.debug( `Autoplay >> Finding related tracks for Track ${track.title} (${track.url}) [ext:${track.extractor?.identifier || "N/A"}]` ); const tracks = (await track.extractor?.getRelatedTracks(track, this.history))?.tracks || (await this.player.extractors.run(async (ext) => { if (this.hasDebugger) this.debug(`Autoplay >> Querying extractor ${ext.identifier}`); const res = await ext.getRelatedTracks(track, this.history); if (!res.tracks.length) { if (this.hasDebugger) this.debug( `Autoplay >> Extractor ${ext.identifier} failed to provide results.` ); return false; } if (this.hasDebugger) this.debug( `Autoplay >> Extractor ${ext.identifier} successfully returned results.` ); return res.tracks; }))?.result || []; let resolver = Util.noop; const donePromise = new Promise( (resolve2) => resolver = resolve2 ); const success = this.emit( GuildQueueEvent.WillAutoPlay, this, tracks, resolver ); if (!success) { resolver( tracks.length ? (() => { const unique = tracks.filter( (tr) => !this.history.tracks.find((t) => t.url === tr.url) ); return unique?.[0] ?? Util.randomChoice(tracks.slice(0, 5)); })() : null ); } const nextTrack = await donePromise; if (!nextTrack) { if (this.hasDebugger) this.debug("Autoplay >> No track was found, initiating #emitEnd()"); throw "No track was found"; } await this.node.play(nextTrack, { queue: false, seek: 0, transitionMode: false }); } catch { return __privateMethod(this, _GuildQueue_instances, emitEnd_fn).call(this); } }, "#handleAutoplay"); __name(_GuildQueue, "GuildQueue"); var GuildQueue5 = _GuildQueue; // src/queue/GuildNodeManager.ts var _GuildNodeManager = class _GuildNodeManager { constructor(player) { this.player = player; __publicField(this, "cache", new import_utils7.Collection()); } /** * Create guild queue if it does not exist * @param guild The guild which will be the owner of the queue * @param options Queue initializer options */ create(guild, options = {}) { const server = this.player.client.guilds.resolve(guild); if (!server) { throw new NoGuildError("Invalid or unknown guild"); } if (this.cache.has(server.id)) { return this.cache.get(server.id); } options.strategy ?? (options.strategy = "FIFO"); options.volume ?? (options.volume = 100); options.equalizer ?? (options.equalizer = []); options.a_filter ?? (options.a_filter = []); options.disableHistory ?? (options.disableHistory = false); options.leaveOnEmpty ?? (options.leaveOnEmpty = true); options.leaveOnEmptyCooldown ?? (options.leaveOnEmptyCooldown = 0); options.leaveOnEnd ?? (options.leaveOnEnd = true); options.leaveOnEndCooldown ?? (options.leaveOnEndCooldown = 0); options.leaveOnStop ?? (options.leaveOnStop = true); options.leaveOnStopCooldown ?? (options.leaveOnStopCooldown = 0); options.resampler ?? (options.resampler = 48e3); options.selfDeaf ?? (options.selfDeaf = true); options.connectionTimeout ?? (options.connectionTimeout = this.player.options.connectionTimeout); options.bufferingTimeout ?? (options.bufferingTimeout = 1e3); options.maxSize ?? (options.maxSize = Infinity); options.maxHistorySize ?? (options.maxHistorySize = Infinity); options.preferBridgedMetadata ?? (options.preferBridgedMetadata = true); options.pauseOnEmpty ?? (options.pauseOnEmpty = true); options.disableBiquad ?? (options.disableBiquad = false); options.disableEqualizer ?? (options.disableEqualizer = false); options.disableFilterer ?? (options.disableFilterer = false); options.disableVolume ?? (options.disableVolume = false); options.disableResampler ?? (options.disableResampler = false); options.disableCompressor ?? (options.disableCompressor = true); options.disableSeeker ?? (options.disableSeeker = true); options.disableReverb ?? (options.disableReverb = true); options.disableFallbackStream ?? (options.disableFallbackStream = false); options.enableStreamInterceptor ?? (options.enableStreamInterceptor = false); options.verifyFallbackStream ?? (options.verifyFallbackStream = false); if (getGlobalRegistry().has("@[onStreamExtracted]") && !options.onStreamExtracted) { options.onStreamExtracted = getGlobalRegistry().get( "@[onStreamExtracted]" ); } if (getGlobalRegistry().has("@[onBeforeCreateStream]") && !options.onBeforeCreateStream) { options.onBeforeCreateStream = getGlobalRegistry().get( "@[onBeforeCreateStream]" ); } if (getGlobalRegistry().has("@[onAfterCreateStream]") && !options.onAfterCreateStream) { options.onAfterCreateStream = getGlobalRegistry().get( "@[onAfterCreateStream]" ); } const queue = new GuildQueue5(this.player, { guild: server, queueStrategy: options.strategy, volume: options.volume, equalizer: options.equalizer, filterer: options.a_filter, biquad: options.biquad, resampler: options.resampler, disableHistory: options.disableHistory, onBeforeCreateStream: options.onBeforeCreateStream, onAfterCreateStream: options.onAfterCreateStream, onStreamExtracted: options.onStreamExtracted, repeatMode: options.repeatMode, leaveOnEmpty: options.leaveOnEmpty, leaveOnEmptyCooldown: options.leaveOnEmptyCooldown, leaveOnEnd: options.leaveOnEnd, leaveOnEndCooldown: options.leaveOnEndCooldown, leaveOnStop: options.leaveOnStop, leaveOnStopCooldown: options.leaveOnStopCooldown, metadata: options.metadata, connectionTimeout: options.connectionTimeout ?? 12e4, selfDeaf: options.selfDeaf, ffmpegFilters: options.defaultFFmpegFilters ?? [], bufferingTimeout: options.bufferingTimeout, noEmitInsert: options.noEmitInsert ?? false, preferBridgedMetadata: options.preferBridgedMetadata, maxHistorySize: options.maxHistorySize, maxSize: options.maxSize, pauseOnEmpty: options.pauseOnEmpty, disableBiquad: options.disableBiquad, disableEqualizer: options.disableEqualizer, disableFilterer: options.disableFilterer, disableResampler: options.disableResampler, disableVolume: options.disableVolume, disableFallbackStream: options.disableFallbackStream, enableStreamInterceptor: options.enableStreamInterceptor, verifyFallbackStream: options.verifyFallbackStream, disableCompressor: options.disableCompressor, disableSeeker: options.disableSeeker, disableReverb: options.disableReverb }); this.cache.set(server.id, queue); return queue; } /** * Get existing queue * @param node Queue resolvable */ get(node) { const queue = this.resolve(node); if (!queue) return null; return this.cache.get(queue.id) || null; } /** * Check if a queue exists * @param node Queue resolvable */ has(node) { const id = node instanceof GuildQueue5 ? node.id : this.player.client.guilds.resolveId(node); return this.cache.has(id); } /** * Delete queue * @param node Queue resolvable */ delete(node) { const queue = this.resolve(node); if (!queue) { throw new NoGuildQueueError("Cannot delete non-existing queue"); } queue.setTransitioning(true); queue.node.stop(true); queue.connection?.removeAllListeners(); queue.dispatcher?.removeAllListeners(); queue.dispatcher?.disconnect(); queue.timeouts.forEach((tm) => clearTimeout(tm)); queue.history.clear(); queue.tracks.clear(); return this.cache.delete(queue.id); } /** * Resolve queue * @param node Queue resolvable */ resolve(node) { if (node instanceof GuildQueue5) { return node; } return this.cache.get( this.player.client.guilds.resolveId(node) ); } /** * Resolve queue id * @param node Queue resolvable */ resolveId(node) { const q = this.resolve(node); return q?.id || null; } }; __name(_GuildNodeManager, "GuildNodeManager"); var GuildNodeManager = _GuildNodeManager; // src/utils/SequentialBucket.ts var import_promises3 = require("timers/promises"); var _SequentialBucket = class _SequentialBucket { constructor() { __publicField(this, "limit", 1); __publicField(this, "remaining", 1); __publicField(this, "resetAfter", 0); __publicField(this, "queue", new AsyncQueue()); __publicField(this, "MAX_RETRIES", 5); } /** * Checks if the bucket is rate limited. */ isRateLimited() { return this.remaining <= 0 && Date.now() < this.resetAfter; } /** * Enqueues a request. * @param req The request function to enqueue */ async enqueue(req) { const entry = this.queue.acquire(); await entry.getTask(); try { return this._request(req); } finally { entry.release(); } } async _request(req, retries = 0) { while (this.isRateLimited()) { const reset = this.resetAfter - Date.now(); await (0, import_promises3.setTimeout)(reset); } let pass = false; try { const res = await req(); this._patchHeaders(res); if (res.status === 429) { const reset = this.resetAfter - Date.now(); await (0, import_promises3.setTimeout)(reset); return this._request(req); } if (!res.ok) { let err; try { const body = await res.json(); const error = new Error(body.message); error.name = body.name; error.code = body.code; err = error; } catch { err = new Error(`HTTP Error: ${res.status} ${res.statusText}`); } pass = true; throw err; } return res; } catch (e) { if (pass) throw e; const badReq = e instanceof Error && /Error: 4[0-9]{2}/.test(e.message); if (!badReq && retries < this.MAX_RETRIES) { return this._request(req, ++retries); } throw e; } } _patchHeaders(res) { const limit = Number(res.headers.get("X-RateLimit-Limit")); const remaining = Number(res.headers.get("X-RateLimit-Remaining")); const resetAfter = Number(res.headers.get("X-RateLimit-Reset")) * 1e3 + Date.now(); if (!Number.isNaN(limit)) this.limit = limit; if (!Number.isNaN(remaining)) this.remaining = remaining; if (!Number.isNaN(resetAfter)) this.resetAfter = resetAfter; } }; __name(_SequentialBucket, "SequentialBucket"); var SequentialBucket = _SequentialBucket; // src/lrclib/LrcLib.ts var toSnakeCase = /* @__PURE__ */ __name((obj) => { const snakeObj = {}; for (const [key, value] of Object.entries(obj)) { if (value == null) continue; const newKey = key.replace( /[A-Z]/g, (letter) => `_${letter.toLowerCase()}` ); snakeObj[newKey] = value; } return snakeObj; }, "toSnakeCase"); var createQuery = /* @__PURE__ */ __name((params) => new URLSearchParams(toSnakeCase(params)).toString(), "createQuery"); var _LrcLib = class _LrcLib { /** * Creates a new LrcLib instance * @param {Player} player The player instance */ constructor(player) { this.player = player; /** * The API URL */ __publicField(this, "api", "https://lrclib.net/api"); /** * The request timeout. Default is 15 seconds. */ __publicField(this, "timeout", 15e3); /** * The request bucket */ __publicField(this, "bucket", new SequentialBucket()); } /** * Sets the request timeout * @param {number} timeout The timeout in milliseconds */ setRequestTimeout(timeout) { this.timeout = timeout; } /** * Sets the retry limit. Default is 5. * @param {number} limit The retry limit */ setRetryLimit(limit) { this.bucket.MAX_RETRIES = limit; } /** * Gets lyrics * @param params The get params */ get(params) { const path = `get?${createQuery(params)}`; return this.request(path); } /** * Gets lyrics by ID * @param id The lyrics ID */ getById(id) { return this.request(`get/${id}`); } /** * Gets cached lyrics * @param params The get params */ getCached(params) { const path = `get-cached?${createQuery(params)}`; return this.request(path); } /** * Searches for lyrics * @param params The search params */ search(params) { if (!params.q && !params.trackName) { throw new InvalidArgTypeError( "one of q or trackName", "string", [String(params.q), String(params.trackName)].join(", ") ); } const path = `search?${createQuery(params)}`; return this.request(path); } /** * Requests the API * @param path The path * @param options The request options */ async request(path, options) { const dispatcher = /* @__PURE__ */ __name(() => { const { name, version: version2 } = Util.getRuntime(); const runtimeVersion = name === "unknown" ? version2 : `${name}/${version2}`; const init = { method: "GET", redirect: "follow", signal: AbortSignal.timeout(this.timeout), ...options, headers: { "User-Agent": `Discord-Player/${this.player.version} ${runtimeVersion ?? ""}`.trimEnd(), "Content-Type": "application/json", ...options?.headers } }; this.player.debug(`[LrcLib] Requesting ${path}`); return fetch( `${this.api}${path.startsWith("/") ? path : "/" + path}`, init ); }, "dispatcher"); const res = await this.bucket.enqueue(dispatcher); return res.json(); } }; __name(_LrcLib, "LrcLib"); var LrcLib = _LrcLib; // src/stream/VoiceUtils.ts var import_discord_voip4 = require("discord-voip"); var import_utils8 = require("@discord-player/utils"); var _VoiceUtils = class _VoiceUtils { /** * The voice utils constructor */ constructor(player) { this.player = player; /** * Voice connection cache to store voice connections of the Player components. * This property is deprecated and will be removed in the future. * It only exists for compatibility reasons. * @deprecated */ __publicField(this, "cache", new import_utils8.Collection()); } /** * Joins a voice channel, creating basic stream dispatch manager * @param {StageChannel|VoiceChannel} channel The voice channel * @param {object} [options] Join options * @returns {Promise} */ async connect(channel, options) { if (!options?.queue) throw new NoGuildQueueError(); const conn = await this.join(channel, options); const sub = new StreamDispatcher( conn, channel, options.queue, options.maxTime, options.audioPlayer ); return sub; } /** * Joins a voice channel * @param {StageChannel|VoiceChannel} [channel] The voice/stage channel to join * @param {object} [options] Join options * @returns {VoiceConnection} */ async join(channel, options) { const existingConnection = this.getConnection( channel.guild.id, options?.group ); if (existingConnection?.joinConfig.channelId === channel?.id && existingConnection.state.status !== import_discord_voip4.VoiceConnectionStatus.Destroyed) { return existingConnection; } const conn = (0, import_discord_voip4.joinVoiceChannel)({ guildId: channel.guild.id, channelId: channel.id, adapterCreator: channel.guild.voiceAdapterCreator, selfDeaf: Boolean(options?.deaf), debug: this.player.events.listenerCount("debug") > 0, group: options?.group, daveEncryption: options?.daveEncryption ?? true, decryptionFailureTolerance: options?.decryptionFailureTolerance ?? 24 }); return conn; } /** * Disconnects voice connection * @param {VoiceConnection} connection The voice connection * @returns {void} */ disconnect(connection) { if (connection instanceof StreamDispatcher) connection = connection.voiceConnection; try { if (connection.state.status !== import_discord_voip4.VoiceConnectionStatus.Destroyed) return connection.destroy(); } catch { } } /** * Returns Discord Player voice connection * @param {Snowflake} guild The guild id * @returns {StreamDispatcher} */ getConnection(guild, group) { return (0, import_discord_voip4.getVoiceConnection)(guild, group); } }; __name(_VoiceUtils, "VoiceUtils"); var VoiceUtils = _VoiceUtils; // src/utils/QueryCache.ts var DEFAULT_EXPIRY_TIMEOUT = 18e6; var _defaultCache; var _QueryCache = class _QueryCache { constructor(player, options = { checkInterval: DEFAULT_EXPIRY_TIMEOUT }) { this.player = player; this.options = options; __privateAdd(this, _defaultCache, /* @__PURE__ */ new Map()); __publicField(this, "timer"); this.timer = setInterval( this.cleanup.bind(this), this.checkInterval ).unref(); } get checkInterval() { return this.options.checkInterval ?? DEFAULT_EXPIRY_TIMEOUT; } async cleanup() { for (const [id, value] of __privateGet(this, _defaultCache)) { if (value.hasExpired()) { __privateGet(this, _defaultCache).delete(id); } } } async clear() { __privateGet(this, _defaultCache).clear(); } async getData() { return [...__privateGet(this, _defaultCache).values()]; } async addData(data) { data.tracks.forEach((d) => { if (__privateGet(this, _defaultCache).has(d.url)) return; __privateGet(this, _defaultCache).set(d.url, new DiscordPlayerQueryResultCache(d)); }); } async resolve(context) { const result = __privateGet(this, _defaultCache).get(context.query); if (!result) return new SearchResult(this.player, { query: context.query, requestedBy: context.requestedBy, queryType: context.queryType }); return new SearchResult(this.player, { query: context.query, tracks: [result.data], playlist: null, queryType: context.queryType, requestedBy: context.requestedBy }); } }; _defaultCache = new WeakMap(); __name(_QueryCache, "QueryCache"); var QueryCache = _QueryCache; var _DiscordPlayerQueryResultCache = class _DiscordPlayerQueryResultCache { constructor(data, expireAfter = DEFAULT_EXPIRY_TIMEOUT) { this.data = data; __publicField(this, "expireAfter", DEFAULT_EXPIRY_TIMEOUT); if (typeof expireAfter === "number") { this.expireAfter = Date.now() + expireAfter; } } hasExpired() { if (typeof this.expireAfter !== "number" || isNaN(this.expireAfter) || this.expireAfter < 1) return false; return Date.now() <= this.expireAfter; } }; __name(_DiscordPlayerQueryResultCache, "DiscordPlayerQueryResultCache"); var DiscordPlayerQueryResultCache = _DiscordPlayerQueryResultCache; // src/index.ts __reExport(src_exports, require("@discord-player/ffmpeg"), module.exports); // src/Player.ts var import_ffmpeg3 = require("@discord-player/ffmpeg"); var import_discord5 = require("discord.js"); var import_discord_voip5 = require("discord-voip"); // src/DefaultVoiceStateHandler.ts var import_discord4 = require("discord.js"); function handleEmptyChannel(player, queue, guildId) { const timeout = setTimeout(() => { if (!Util.isVoiceEmpty(queue.channel) || !player.nodes.has(queue.guild.id)) return; if (queue.options.leaveOnEmpty) queue.delete(); player.events.emit(GuildQueueEvent.EmptyChannel, queue); }, queue.options.leaveOnEmptyCooldown || 0).unref(); queue.timeouts.set(`empty_${guildId}`, timeout); } __name(handleEmptyChannel, "handleEmptyChannel"); function handleChannelPopulate(player, queue, guildId) { const emptyTimeout = queue.timeouts.get(`empty_${guildId}`); if (!Util.isVoiceEmpty(queue.channel) && emptyTimeout) { clearTimeout(emptyTimeout); queue.timeouts.delete(`empty_${guildId}`); player.events.emit(GuildQueueEvent.ChannelPopulate, queue); } } __name(handleChannelPopulate, "handleChannelPopulate"); function handlePauseOnEmpty(queue) { const isEmpty = Util.isVoiceEmpty(queue.channel); const wasPausedOnEmpty = Reflect.get(queue, "__pausedOnEmpty"); if (isEmpty && !wasPausedOnEmpty) { queue.node.setPaused(true); Reflect.set(queue, "__pausedOnEmpty", true); if (queue.hasDebugger) { queue.debug( "Voice channel is empty and options#pauseOnEmpty is true, pausing..." ); } } else if (!isEmpty && wasPausedOnEmpty) { queue.node.setPaused(false); Reflect.set(queue, "__pausedOnEmpty", false); if (queue.hasDebugger) { queue.debug( "Voice channel is not empty and options#pauseOnEmpty is true, resuming..." ); } } } __name(handlePauseOnEmpty, "handlePauseOnEmpty"); function handleBotVoiceStateUpdate(queue, oldState, newState) { if (newState.serverMute != null && oldState.serverMute !== newState.serverMute) { queue.node.setPaused(newState.serverMute); return; } if (newState.channel?.type === import_discord4.ChannelType.GuildStageVoice && newState.suppress != null && oldState.suppress !== newState.suppress) { queue.node.setPaused(newState.suppress); if (newState.suppress) { newState.guild.members.me?.voice.setRequestToSpeak(true).catch(Util.noop); } } } __name(handleBotVoiceStateUpdate, "handleBotVoiceStateUpdate"); async function defaultVoiceStateHandler(player, queue, oldState, newState) { if (!queue?.connection || !queue.channel) return; const isBotState = newState.member?.id === newState.guild.members.me?.id; const guildId = oldState.guild.id; if (isBotState && oldState.channelId && !newState.channelId) { try { queue.delete(); } catch { } return void player.events.emit(GuildQueueEvent.Disconnect, queue); } if (queue.options.pauseOnEmpty) { handlePauseOnEmpty(queue); } if (isBotState && newState.channelId && (!oldState.channelId || oldState.channelId !== newState.channelId)) { if (queue.connection) queue.channel = newState.channel; handleBotVoiceStateUpdate(queue, oldState, newState); } if (!newState.channelId && oldState.channelId === queue.channel.id) { if (!Util.isVoiceEmpty(queue.channel)) return; handleEmptyChannel(player, queue, guildId); } else if (newState.channelId === queue.channel.id) { handleChannelPopulate(player, queue, guildId); } else if (oldState.channelId !== newState.channelId) { if (newState.channelId !== queue.channel.id && !Util.isVoiceEmpty(queue.channel)) return; if (!queue.timeouts.has(`empty_${guildId}`)) { handleEmptyChannel(player, queue, guildId); } } } __name(defaultVoiceStateHandler, "defaultVoiceStateHandler"); // src/utils/DependencyReportGenerator.ts var import_node_path = require("path"); var import_ffmpeg2 = require("@discord-player/ffmpeg"); // src/version.ts var version = ( /* @__MACRO__ getVersion */ "7.2.0" ); // src/utils/DependencyReportGenerator.ts var DependencyReportGenerator = { /** * Finds the package.json file of a package. * @param dir - The directory to start searching from * @param packageName - The name of the package to find * @param depth - The maximum depth to search * @returns The package.json file, or null if not found */ findPackageJSON(dir, packageName, depth) { if (depth === 0) return null; const target = (0, import_node_path.resolve)(dir, "package.json"); const next = /* @__PURE__ */ __name(() => DependencyReportGenerator.findPackageJSON( (0, import_node_path.resolve)(dir, ".."), packageName, depth - 1 ), "next"); try { const pkgJSON = require(target); if (pkgJSON.name !== packageName) { return next(); } return pkgJSON; } catch { return next(); } }, /** * Tries to find the version of a dependency. * @param name - The package to find the version of * @param maxLookupDepth - The maximum depth to search for the package.json file * @returns The version of the package, or null if not found */ version(name, maxLookupDepth = 3) { try { if (name === "discord-player") { return version; } const pkg = DependencyReportGenerator.findPackageJSON( (0, import_node_path.dirname)(require.resolve(name)), name, maxLookupDepth ); return pkg?.version ?? null; } catch { return null; } }, /** * Generates a report of the dependencies used by the discord-player module. * @returns The report object */ generate() { const ffmpegReport = {}; for (const lib of import_ffmpeg2.FFmpeg.sources) { ffmpegReport[lib.name] = null; } const ffmpeg = import_ffmpeg2.FFmpeg.resolveSafe(); if (ffmpeg) { ffmpegReport[ffmpeg.name] = { hasLibopus: ffmpeg.command.includes("--enable-libopus"), version: ffmpeg.version }; } return { core: { "discord-player": DependencyReportGenerator.version( "discord-player" ), "discord-voip": DependencyReportGenerator.version( "discord-voip" ) }, libopus: { mediaplex: DependencyReportGenerator.version("mediaplex"), "@discordjs/opus": DependencyReportGenerator.version("@discordjs/opus"), "@evan/opus": DependencyReportGenerator.version("@evan/opus"), opusscript: DependencyReportGenerator.version("opusscript"), "node-opus": DependencyReportGenerator.version("node-opus") }, libsodium: { "sodium-native": DependencyReportGenerator.version("sodium-native"), sodium: DependencyReportGenerator.version("sodium"), "libsodium-wrappers": DependencyReportGenerator.version("libsodium-wrappers"), "@stablelib/xchacha20poly1305": DependencyReportGenerator.version( "@stablelib/xchacha20poly1305" ), "sodium-javascript": DependencyReportGenerator.version("sodium-javascript"), "@noble/ciphers": DependencyReportGenerator.version("@noble/ciphers") }, DAVE: { "@snazzah/davey": DependencyReportGenerator.version("@snazzah/davey") }, ffmpeg: ffmpegReport }; }, /** * Generates a string representation of the dependencies report. * @returns The string representation */ generateString() { const report = DependencyReportGenerator.generate(); const line = "-".repeat(50); const output = []; output.push("Dependencies Report"); output.push(line); const keys = Object.keys(report); for (const _key of keys) { const key = _key; output.push(key); const subKeys = Object.keys(report[key]); for (const _subKey of subKeys) { const subKey = _subKey; const value = report[key][subKey] ?? "N/A"; output.push( `- ${subKey}: ${typeof value === "object" ? JSON.stringify(value, null, 2) : value}` ); } output.push(""); } output.push(line); return output.join("\n"); } }; // src/PlayerStreamInterceptor.ts var _onStream; var _PlayerStreamInterceptor = class _PlayerStreamInterceptor { /** * Creates a new PlayerStreamInterceptor instance. * @param player The player instance * @param options The interceptor options */ constructor(player, options) { this.player = player; this.options = options; __privateAdd(this, _onStream, /* @__PURE__ */ new Set()); } /** * Handles the intercepted stream. * @param queue The guild queue * @param track The track * @param stream The intercepted stream * @returns Whether the stream was intercepted */ async handle(queue, track, type, stream) { const filter = this.options.shouldIntercept; if (filter) { const result = await filter(queue, track, type, stream); if (!result) return false; } const hasListeners = __privateGet(this, _onStream).size; if (!hasListeners) return false; await Promise.all( [...__privateGet(this, _onStream)].map((handler) => handler(queue, track, type, stream)) ); return true; } /** * Adds a new intercepted stream listener. * @param handler The handler * @returns A function to remove the listener */ onStream(handler) { __privateGet(this, _onStream).add(handler); return () => { __privateGet(this, _onStream).delete(handler); }; } }; _onStream = new WeakMap(); __name(_PlayerStreamInterceptor, "PlayerStreamInterceptor"); var PlayerStreamInterceptor = _PlayerStreamInterceptor; // src/Player.ts var PlayerEvent = { debug: "debug", Debug: "debug", error: "error", Error: "error", voiceStateUpdate: "voiceStateUpdate", VoiceStateUpdate: "voiceStateUpdate" }; var _lastLatency, _voiceStateUpdateListener, _lagMonitorTimeout, _lagMonitorInterval, _onVoiceStateUpdate, _hooksCtx, _streamInterceptor; var _Player = class _Player extends PlayerEventsEmitter { /** * Creates new Discord Player * @param {Client} client The Discord Client * @param {PlayerInitOptions} [options] The player init options */ constructor(client, options = {}) { super([PlayerEvent.Error]); __privateAdd(this, _lastLatency, -1); __privateAdd(this, _voiceStateUpdateListener, this.handleVoiceState.bind(this)); __privateAdd(this, _lagMonitorTimeout); __privateAdd(this, _lagMonitorInterval); __privateAdd(this, _onVoiceStateUpdate, defaultVoiceStateHandler); __privateAdd(this, _hooksCtx, null); /** * The unique identifier of this player instance */ __publicField(this, "id", import_discord5.SnowflakeUtil.generate().toString()); /** * The discord.js client */ __publicField(this, "client"); /** * The player options */ __publicField(this, "options"); /** * The player nodes (queue) manager */ __publicField(this, "nodes", new GuildNodeManager(this)); /** * The voice api utilities */ __publicField(this, "voiceUtils", new VoiceUtils(this)); /** * The extractors manager */ __publicField(this, "extractors", new ExtractorExecutionContext(this)); /** * The player events channel */ __publicField(this, "events", new PlayerEventsEmitter( [ GuildQueueEvent.Error, GuildQueueEvent.PlayerError ] )); /** * The player version */ __publicField(this, "version", _Player.version); /** * The lyrics api */ __publicField(this, "lyrics", new LrcLib(this)); __privateAdd(this, _streamInterceptor, null); if (options.ffmpegPath) { if (typeof options.ffmpegPath !== "string") throw new TypeError( `Expected type "string" for options.ffmpegPath. Got ${typeof options.ffmpegPath} instead` ); process.env.FFMPEG_PATH = options.ffmpegPath; } const isCompatMode = isClientProxy(client); this.client = client; if (!isCompatMode) { try { if (!(client instanceof import_discord5.Client)) { Util.warn( `Client is not an instance of discord.js@${import_discord5.version} client, some things may not work correctly. This can happen due to corrupt dependencies or having multiple installations of discord.js.`, "InvalidClientInstance" ); } const ibf = this.client.options.intents instanceof import_discord5.IntentsBitField ? this.client.options.intents : new import_discord5.IntentsBitField(this.client.options.intents); if (!ibf.has(import_discord5.IntentsBitField.Flags.GuildVoiceStates)) { Util.warn( 'client is missing "GuildVoiceStates" intent', "InvalidIntentsBitField" ); } } catch { } } this.options = { lockVoiceStateHandler: false, blockExtractors: [], blockStreamFrom: [], connectionTimeout: 2e4, lagMonitor: 3e4, queryCache: options.queryCache === null ? null : options.queryCache || new QueryCache(this), skipFFmpeg: true, probeTimeout: 5e3, overrideFallbackContext: true, ...options }; if (!isCompatMode) { this.client.incrementMaxListeners(); this.client.on(import_discord5.Events.VoiceStateUpdate, __privateGet(this, _voiceStateUpdateListener)); } else { try { this.client.__dp_voiceStateUpdate_proxy(__privateGet(this, _voiceStateUpdateListener)); } catch (e) { Util.warn( "Failed to attach voice state update proxy, voice state handler will not work properly", "CompatModeError" ); } } if (typeof this.options.lagMonitor === "number" && this.options.lagMonitor > 0) { __privateSet(this, _lagMonitorInterval, setInterval(() => { const start = performance.now(); __privateSet(this, _lagMonitorTimeout, setTimeout(() => { __privateSet(this, _lastLatency, performance.now() - start); if (this.hasDebugger) this.debug( `[Lag Monitor] Event loop latency: ${__privateGet(this, _lastLatency)}ms` ); }, 0).unref()); }, this.options.lagMonitor).unref()); } if (this.options.overrideFallbackContext) { getGlobalRegistry().set("@[player]", this); } } /** * The hooks context for this player instance. */ get context() { if (!__privateGet(this, _hooksCtx)) { __privateSet(this, _hooksCtx, createContext()); const originalProvider = __privateGet(this, _hooksCtx).provide.bind(__privateGet(this, _hooksCtx)); __privateGet(this, _hooksCtx).provide = (value, receiver) => { return SUPER_CONTEXT.provide(this, () => { return originalProvider(value, () => { return receiver(); }); }); }; } return __privateGet(this, _hooksCtx); } /** * Override default voice state update handler * @param handler The handler callback */ onVoiceStateUpdate(handler) { __privateSet(this, _onVoiceStateUpdate, handler); } debug(m) { return this.emit("debug", m); } /** * Creates new discord-player instance. * @param client The client that instantiated player * @param options Player initializer options */ static create(client, options = {}) { return new _Player(client, options); } /** * The current query cache provider in use */ get queryCache() { return this.options.queryCache ?? null; } /** * Alias to `Player.nodes`. */ get queues() { return this.nodes; } /** * Event loop latency in ms. If your bot is laggy and this returns a number above 20ms for example, * some expensive task is being executed on the current thread which is slowing down the event loop. * @type {number} */ get eventLoopLag() { return __privateGet(this, _lastLatency); } /** * Generates statistics that could be useful. Statistics generator is still experimental. * @example ```typescript * const stats = player.generateStatistics(); * * console.log(stats); * * // outputs something like * // { * // queuesCount: number, * // queryCacheEnabled: boolean, * // queues: [ * // GuildQueueStatisticsMetadata, * // GuildQueueStatisticsMetadata, * // GuildQueueStatisticsMetadata, * // ... * // ] * // } * ``` */ generateStatistics() { return { queuesCount: this.queues.cache.size, queryCacheEnabled: this.queryCache != null, queues: this.queues.cache.map((m) => m.stats.generate()) }; } /** * Whether the player is in compatibility mode. Compatibility mode is enabled when non-discord.js client is used. */ isCompatMode() { return isClientProxy(this.client); } /** * Destroy every single queues managed by this master player instance * @example ```typescript * // use me when you want to immediately terminate every single queues in existence 🔪 * await player.destroy(); * ``` */ async destroy() { this.nodes.cache.forEach((node) => node.delete()); if (!this.isCompatMode()) { this.client.off(import_discord5.Events.VoiceStateUpdate, __privateGet(this, _voiceStateUpdateListener)); this.client.decrementMaxListeners(); } this.removeAllListeners(); this.events.removeAllListeners(); await this.extractors.unregisterAll(); if (__privateGet(this, _lagMonitorInterval)) clearInterval(__privateGet(this, _lagMonitorInterval)); if (__privateGet(this, _lagMonitorTimeout)) clearInterval(__privateGet(this, _lagMonitorTimeout)); } _handleVoiceState(oldState, newState) { const queue = this.nodes.get(oldState.guild.id); if (!queue || !queue.connection || !queue.channel) return; const wasHandled = this.events.emit( GuildQueueEvent.VoiceStateUpdate, queue, oldState, newState ); if (wasHandled && !this.options.lockVoiceStateHandler) return; return __privateGet(this, _onVoiceStateUpdate).call(this, this, queue, oldState, newState); } /** * Handles voice state update * @param {VoiceState} oldState The old voice state * @param {VoiceState} newState The new voice state * @returns {void} * @example ```typescript * // passing voice state update data to this method will trigger voice state handler * * client.on('voiceStateUpdate', (oldState, newState) => { * // this is definitely a rocket science, right here * player.handleVoiceState(oldState, newState); * }); * ``` */ handleVoiceState(oldState, newState) { this._handleVoiceState(oldState, newState); } /** * Lock voice state handler. When this method is called, discord-player will keep using the default voice state update handler, even if custom implementation exists. */ lockVoiceStateHandler() { this.options.lockVoiceStateHandler = true; } /** * Unlock voice state handler. When this method is called, discord-player will stop using the default voice state update handler if custom implementation exists. */ unlockVoiceStateHandler() { this.options.lockVoiceStateHandler = false; } /** * Checks if voice state handler is locked. */ isVoiceStateHandlerLocked() { return !!this.options.lockVoiceStateHandler; } /** * Initiate audio player * @param channel The voice channel on which the music should be played * @param query The track or source to play * @param options Options for player * @example ```typescript * // no need to worry about queue management, just use this method 😄 * const query = 'this is my super cool search query that I want to play'; * * try { * const { track } = await player.play(voiceChannel, query); * console.log(`🎉 I am playing ${track.title} 🎉`); * } catch(e) { * console.log(`😭 Failed to play error oh no:\n\n${e}`); * } * ``` */ async play(channel, query, options = {}) { const vc = this.client.channels.resolve(channel); if (!vc?.isVoiceBased()) throw new InvalidArgTypeError( "channel", "VoiceBasedChannel", !vc ? "undefined" : `channel type ${vc.type}` ); const originalResult = query instanceof SearchResult ? query : await this.search(query, options); const result = await options.afterSearch?.(originalResult) || originalResult; if (result.isEmpty()) { throw new NoResultError( `No results found for "${query}" (Extractor: ${result.extractor?.identifier || "N/A"})` ); } const queue = this.nodes.create(vc.guild, options.nodeOptions); if (this.hasDebugger) this.debug(`[AsyncQueue] Acquiring an entry...`); const entry = queue.tasksQueue.acquire({ signal: options.signal }); if (this.hasDebugger) this.debug(`[AsyncQueue] Entry ${entry.id} was acquired successfully!`); if (this.hasDebugger) this.debug(`[AsyncQueue] Waiting for the queue to resolve...`); await entry.getTask(); if (this.hasDebugger) this.debug(`[AsyncQueue] Entry ${entry.id} was resolved!`); try { if (!queue.channel) await queue.connect(vc, options.connectionOptions); if (!result.playlist) { queue.addTrack(result.tracks[0]); } else { queue.addTrack(result.playlist); } if (!queue.isPlaying()) await queue.node.play(null, options.audioPlayerOptions); } finally { if (this.hasDebugger) this.debug(`[AsyncQueue] Releasing an entry from the queue...`); queue.tasksQueue.release(); } return { track: result.tracks[0], extractor: result.extractor, searchResult: result, queue }; } /** * Search tracks * @param {string | Track | Track[] | Playlist | SearchResult} query The search query * @param {SearchOptions} options The search options * @returns {Promise} * @example ```typescript * const searchQuery = 'pass url or text or discord-player track constructable objects, we got you covered 😎'; * const result = await player.search(searchQuery); * * console.log(result); // Logs `SearchResult` object * ``` */ async search(searchQuery, options = {}) { if (searchQuery instanceof SearchResult) return searchQuery; if (searchQuery instanceof import_discord_voip5.AudioResource) { searchQuery = this.createTrackFromAudioResource(searchQuery); } if (options.requestedBy != null) options.requestedBy = this.client.users.resolve(options.requestedBy); options.blockExtractors ?? (options.blockExtractors = this.options.blockExtractors); options.fallbackSearchEngine ?? (options.fallbackSearchEngine = QueryType.AUTO_SEARCH); if (searchQuery instanceof Track) { return new SearchResult(this, { playlist: searchQuery.playlist || null, tracks: [searchQuery], query: searchQuery.title, extractor: searchQuery.extractor, queryType: searchQuery.queryType, requestedBy: options.requestedBy }); } if (searchQuery instanceof Playlist) { return new SearchResult(this, { playlist: searchQuery, tracks: searchQuery.tracks, query: searchQuery.title, extractor: searchQuery.tracks[0]?.extractor, queryType: QueryType.AUTO, requestedBy: options.requestedBy }); } if (Array.isArray(searchQuery)) { const tracks = searchQuery.filter((t) => t instanceof Track); return new SearchResult(this, { playlist: null, tracks, query: "@@#%{{UserLoadedContent}}%#@@", extractor: null, queryType: QueryType.AUTO, requestedBy: options.requestedBy }); } if (this.hasDebugger) this.debug(`Searching ${searchQuery}`); let extractor = null, protocol = null; options.searchEngine ?? (options.searchEngine = QueryType.AUTO); options.fallbackSearchEngine ?? (options.fallbackSearchEngine = QueryType.AUTO_SEARCH); if (this.hasDebugger) this.debug( `Search engine set to ${options.searchEngine}, fallback search engine set to ${options.fallbackSearchEngine}` ); if (/^\w+:/.test(searchQuery)) { const [protocolName, ...query2] = searchQuery.split(":"); if (this.hasDebugger) this.debug(`Protocol ${protocolName} detected in query`); const matchingExtractor = this.extractors.store.find( (e) => !this.extractors.isDisabled(e.identifier) && e.protocols.includes(protocolName) ); if (matchingExtractor) { if (this.hasDebugger) this.debug( `Protocol ${protocolName} is supported by ${matchingExtractor.identifier} extractor!` ); extractor = matchingExtractor; searchQuery = query2.join(":"); protocol = protocolName; } else { if (this.hasDebugger) this.debug( `Could not find an extractor that supports ${protocolName} protocol. Falling back to default behavior...` ); } } const redirected = await QueryResolver.preResolve(searchQuery); const { type: queryType, query } = options.searchEngine === QueryType.AUTO ? QueryResolver.resolve(redirected, options.fallbackSearchEngine) : { type: options.searchEngine, query: redirected }; if (this.hasDebugger) this.debug( `Query type identified as ${queryType}${extractor && protocol ? " but might not be used due to the presence of protocol" : ""}` ); if (options.searchEngine.startsWith("ext:")) { if (this.hasDebugger) this.debug(`Forcing ${options.searchEngine.substring(4)} extractor...`); extractor = this.extractors.get(options.searchEngine.substring(4)); if (!extractor) return new SearchResult(this, { query, queryType, extractor, requestedBy: options.requestedBy }); } if (!extractor) { if (!options.ignoreCache) { if (this.hasDebugger) this.debug(`Checking cache...`); const res2 = await this.queryCache?.resolve({ query, queryType, requestedBy: options.requestedBy }); if (res2?.hasTracks()) { if (this.hasDebugger) this.debug(`Cache hit for query ${query}`); return res2; } if (this.hasDebugger) this.debug(`Cache miss for query ${query}`); } if (this.hasDebugger) this.debug(`Executing extractors...`); extractor = (await this.extractors.run(async (ext) => { if (options.blockExtractors?.includes(ext.identifier)) return false; return ext.validate(query, queryType); }))?.extractor || null; } if (!extractor) { if (this.hasDebugger) this.debug("Failed to find appropriate extractor"); return new SearchResult(this, { query, queryType, requestedBy: options.requestedBy }); } if (this.hasDebugger) this.debug( `Executing metadata query using ${extractor.identifier} extractor...` ); const res = await extractor.handle(query, { type: queryType, requestedBy: options.requestedBy, requestOptions: options.requestOptions, protocol }).catch(() => null); if (res) { if (this.hasDebugger) this.debug("Metadata query was successful!"); if (options.requestOptions && res.tracks) { res.tracks.forEach((track) => { if (track.raw) { track.raw.requestOptions = options.requestOptions; } else { track.raw = { requestOptions: options.requestOptions }; } }); } const result2 = new SearchResult(this, { query, queryType, playlist: res.playlist, tracks: res.tracks, extractor, requestedBy: options.requestedBy }); if (!options.ignoreCache) { if (this.hasDebugger) this.debug(`Adding data to cache...`); await this.queryCache?.addData(result2); } return result2; } if (this.hasDebugger) this.debug( "Failed to find result using appropriate extractor. Querying all extractors..." ); const result = await this.extractors.run( async (ext) => !options.blockExtractors?.includes(ext.identifier) && await ext.validate(query) && ext.handle(query, { type: queryType, requestedBy: options.requestedBy, requestOptions: options.requestOptions, protocol }) ); if (!result?.result) { if (this.hasDebugger) this.debug( `Failed to query metadata query using ${result?.extractor.identifier || "N/A"} extractor.` ); return new SearchResult(this, { query, queryType, requestedBy: options.requestedBy, extractor: result?.extractor }); } if (this.hasDebugger) this.debug( `Metadata query was successful using ${result.extractor.identifier}!` ); if (options.requestOptions && result.result.tracks) { result.result.tracks.forEach((track) => { if (track.raw) { track.raw.requestOptions = options.requestOptions; } else { track.raw = { requestOptions: options.requestOptions }; } }); } const data = new SearchResult(this, { query, queryType, playlist: result.result.playlist, tracks: result.result.tracks, extractor: result.extractor, requestedBy: options.requestedBy }); if (!options.ignoreCache) { if (this.hasDebugger) this.debug(`Adding data to cache...`); await this.queryCache?.addData(data); } return data; } /** * Generates a report of the dependencies used by the `discord-voip` module. Useful for debugging. * @example ```typescript * console.log(player.scanDeps()); * // -> logs dependencies report * ``` * @returns {string} */ scanDeps() { const line = "-".repeat(50); const runtime = "Bun" in globalThis ? "Bun" : "Deno" in globalThis ? "Deno" : "Node"; const depsReport = [ "Discord Player", line, `- discord-player: ${_Player.version}${this.isCompatMode() ? ` (${getCompatName(this.client)} compatibility mode)` : ""}`, `- discord-voip: ${import_discord_voip5.version}`, `- discord.js: ${import_discord5.version}`, `- Node version: ${process.version} (Detected Runtime: ${runtime}, Platform: ${process.platform} [${process.arch}])`, (() => { const info = import_ffmpeg3.FFmpeg.resolveSafe(); if (!info) return "FFmpeg/Avconv not found"; return [ `- ffmpeg: ${info.version}`, `- command: ${info.command}`, `- static: ${info.module}`, `- libopus: ${info.result.includes("--enable-libopus")}` ].join("\n"); })(), "\n", "Loaded Extractors:", line, this.extractors.store.map((m) => { return m.identifier; }).join("\n") || "N/A", "\n\ndiscord-voip", DependencyReportGenerator.generateString() ]; return depsReport.join("\n"); } *[Symbol.iterator]() { yield* this.nodes.cache.values(); } /** * Creates `Playlist` instance * @param data The data to initialize a playlist */ createPlaylist(data) { return new Playlist(this, data); } /** * Creates a track from an audio resource. * @param resource The audio resource */ createTrackFromAudioResource(resource) { const metadata = resource.metadata || {}; const ref = import_discord5.SnowflakeUtil.generate().toString(); const maybeTitle = "title" in metadata ? `${metadata.title}` : `Track ${ref}`; const maybeAuthor = "author" in metadata ? `${metadata.author}` : "Unknown author"; const maybeDuration = "duration" in metadata ? `${metadata.duration}` : "00:00"; const maybeThumbnail = "thumbnail" in metadata ? `${metadata.thumbnail}` : void 0; const maybeURL = "url" in metadata ? `${metadata.url}` : `discord-player://blob/${ref}`; const maybeDescription = "description" in metadata ? `${metadata.description}` : "No description available."; const maybeViews = "views" in metadata ? Number(metadata.views) || 0 : 0; const track = new Track(this, { title: maybeTitle, author: maybeAuthor, duration: maybeDuration, thumbnail: maybeThumbnail, url: maybeURL, description: maybeDescription, queryType: QueryType.DISCORD_PLAYER_BLOB, source: "arbitrary", metadata, live: false, views: maybeViews }); resource.metadata = track; track.setResource(resource); return track; } /** * Handles intercepting streams * @param stream The stream to intercept */ async handleInterceptingStream(queue, track, format, stream) { if (!__privateGet(this, _streamInterceptor)) return; return __privateGet(this, _streamInterceptor).handle(queue, track, format, stream); } /** * Creates a global stream interceptor * @param options The stream interceptor options */ createStreamInterceptor(options) { if (__privateGet(this, _streamInterceptor)) { return __privateGet(this, _streamInterceptor); } __privateSet(this, _streamInterceptor, new PlayerStreamInterceptor(this, options)); return __privateGet(this, _streamInterceptor); } }; _lastLatency = new WeakMap(); _voiceStateUpdateListener = new WeakMap(); _lagMonitorTimeout = new WeakMap(); _lagMonitorInterval = new WeakMap(); _onVoiceStateUpdate = new WeakMap(); _hooksCtx = new WeakMap(); _streamInterceptor = new WeakMap(); __name(_Player, "Player"); /** * The version of discord-player */ __publicField(_Player, "version", version); var Player = _Player; // src/index.ts var import_equalizer3 = require("@discord-player/equalizer"); var import_discord_voip6 = require("discord-voip"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AF_NIGHTCORE_RATE, AF_VAPORWAVE_RATE, AFilterGraph, AsyncQueue, AsyncQueueEntry, AudioFilters, AudioPlayer, BASS_EQ_BANDS, BaseExtractor, BiquadFilterType, Context, DependencyReportGenerator, DiscordPlayerQueryResultCache, EqualizerConfigurationPreset, ExtractorExecutionContext, FFMPEG_ARGS_PIPED, FFMPEG_ARGS_STRING, FFMPEG_SRATE_REGEX, FFmpegFilterer, FiltersChain, GuildNodeManager, GuildQueue, GuildQueueAudioFilters, GuildQueueEvent, GuildQueueHistory, GuildQueuePlayerNode, GuildQueueStatistics, InterceptedStream, LrcLib, PCMAudioFilters, Player, PlayerEvent, PlayerEventsEmitter, PlayerStreamInterceptor, Playlist, Q_BUTTERWORTH, QueryCache, QueryResolver, QueryType, QueueRepeatMode, SearchResult, SequentialBucket, SerializedType, StreamDispatcher, StreamType, Track, TrackSkipReason, TypeUtil, Util, VALIDATE_QUEUE_CAP, VoiceUtils, VolumeTransformer, createAudioPlayer, createAudioResource, createContext, createErisCompat, createFFmpegStream, createOceanicCompat, decode, deserialize, encode, getVoiceConnection, getVoiceConnections, isErisProxy, isOceanicProxy, joinVoiceChannel, onAfterCreateStream, onBeforeCreateStream, onStreamExtracted, serialize, tryIntoThumbnailString, useContext, useHistory, useMainPlayer, useMetadata, usePlayer, useQueue, useTimeline, useVolume, version, ...require("@discord-player/ffmpeg") }); //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9jb21wYXQvY3JlYXRlRXJpc0NvbXBhdC50cyIsICIuLi9zcmMvY29tcGF0L2NvbW1vbi50cyIsICIuLi9zcmMvdXRpbHMvVXRpbC50cyIsICIuLi9zcmMvZmFicmljL1RyYWNrLnRzIiwgIi4uL3NyYy9lcnJvcnMvaW5kZXgudHMiLCAiLi4vc3JjL3V0aWxzL1R5cGVVdGlsLnRzIiwgIi4uL3NyYy91dGlscy9zZXJkZS50cyIsICIuLi9zcmMvZmFicmljL1BsYXlsaXN0LnRzIiwgIi4uL3NyYy91dGlscy9RdWVyeVJlc29sdmVyLnRzIiwgIi4uL3NyYy9mYWJyaWMvU2VhcmNoUmVzdWx0LnRzIiwgIi4uL3NyYy91dGlscy9BdWRpb0ZpbHRlcnMudHMiLCAiLi4vc3JjL2NvbXBhdC9jcmVhdGVPY2VhbmljQ29tcGF0LnRzIiwgIi4uL3NyYy91dGlscy9QbGF5ZXJFdmVudHNFbWl0dGVyLnRzIiwgIi4uL3NyYy9leHRyYWN0b3JzL0Jhc2VFeHRyYWN0b3IudHMiLCAiLi4vc3JjL2V4dHJhY3RvcnMvRXh0cmFjdG9yRXhlY3V0aW9uQ29udGV4dC50cyIsICIuLi9zcmMvaG9va3MvY29udGV4dC9hc3luYy1jb250ZXh0LnRzIiwgIi4uL3NyYy91dGlscy9fX2ludGVybmFsX18vX2NvbnRhaW5lci50cyIsICIuLi9zcmMvdXRpbHMvX19pbnRlcm5hbF9fL2dldEdsb2JhbFJlZ2lzdHJ5LnRzIiwgIi4uL3NyYy9ob29rcy9jb21tb24udHMiLCAiLi4vc3JjL2hvb2tzL3VzZUhpc3RvcnkudHMiLCAiLi4vc3JjL2hvb2tzL3VzZVBsYXllci50cyIsICIuLi9zcmMvaG9va3MvdXNlUXVldWUudHMiLCAiLi4vc3JjL2hvb2tzL3VzZU1haW5QbGF5ZXIudHMiLCAiLi4vc3JjL2hvb2tzL3VzZU1ldGFkYXRhLnRzIiwgIi4uL3NyYy9ob29rcy91c2VUaW1lbGluZS50cyIsICIuLi9zcmMvaG9va3Mvc3RyZWFtL29uQWZ0ZXJDcmVhdGVTdHJlYW0udHMiLCAiLi4vc3JjL2hvb2tzL3N0cmVhbS9vbkJlZm9yZUNyZWF0ZVN0cmVhbS50cyIsICIuLi9zcmMvaG9va3Mvc3RyZWFtL29uU3RyZWFtRXh0cmFjdGVkLnRzIiwgIi4uL3NyYy9ob29rcy91c2VWb2x1bWUudHMiLCAiLi4vc3JjL3F1ZXVlL0d1aWxkTm9kZU1hbmFnZXIudHMiLCAiLi4vc3JjL3F1ZXVlL0d1aWxkUXVldWUudHMiLCAiLi4vc3JjL3N0cmVhbS9TdHJlYW1EaXNwYXRjaGVyLnRzIiwgIi4uL3NyYy9zdHJlYW0vSW50ZXJjZXB0ZWRTdHJlYW0udHMiLCAiLi4vc3JjL3F1ZXVlL0d1aWxkUXVldWVIaXN0b3J5LnRzIiwgIi4uL3NyYy9xdWV1ZS9HdWlsZFF1ZXVlUGxheWVyTm9kZS50cyIsICIuLi9zcmMvdXRpbHMvQXN5bmNRdWV1ZS50cyIsICIuLi9zcmMvcXVldWUvR3VpbGRRdWV1ZUF1ZGlvRmlsdGVycy50cyIsICIuLi9zcmMvdXRpbHMvRkZtcGVnU3RyZWFtLnRzIiwgIi4uL3NyYy9xdWV1ZS9HdWlsZFF1ZXVlU3RhdGlzdGljcy50cyIsICIuLi9zcmMvcXVldWUvU3luY2VkTHlyaWNzUHJvdmlkZXIudHMiLCAiLi4vc3JjL3V0aWxzL1NlcXVlbnRpYWxCdWNrZXQudHMiLCAiLi4vc3JjL2xyY2xpYi9McmNMaWIudHMiLCAiLi4vc3JjL3N0cmVhbS9Wb2ljZVV0aWxzLnRzIiwgIi4uL3NyYy91dGlscy9RdWVyeUNhY2hlLnRzIiwgIi4uL3NyYy9QbGF5ZXIudHMiLCAiLi4vc3JjL0RlZmF1bHRWb2ljZVN0YXRlSGFuZGxlci50cyIsICIuLi9zcmMvdXRpbHMvRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci50cyIsICIuLi9zcmMvdmVyc2lvbi50cyIsICIuLi9zcmMvUGxheWVyU3RyZWFtSW50ZXJjZXB0b3IudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImV4cG9ydCB7IGNyZWF0ZUVyaXNDb21wYXQgfSBmcm9tICcuL2NvbXBhdC9jcmVhdGVFcmlzQ29tcGF0JztcbmV4cG9ydCB7IGNyZWF0ZU9jZWFuaWNDb21wYXQgfSBmcm9tICcuL2NvbXBhdC9jcmVhdGVPY2VhbmljQ29tcGF0JztcbmV4cG9ydCB7IGlzRXJpc1Byb3h5LCBpc09jZWFuaWNQcm94eSB9IGZyb20gJy4vY29tcGF0L2NvbW1vbic7XG5leHBvcnQgKiBmcm9tICcuL3V0aWxzL1BsYXllckV2ZW50c0VtaXR0ZXInO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscy9BdWRpb0ZpbHRlcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9leHRyYWN0b3JzL0Jhc2VFeHRyYWN0b3InO1xuZXhwb3J0ICogZnJvbSAnLi9leHRyYWN0b3JzL0V4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQnO1xuZXhwb3J0ICogZnJvbSAnLi9mYWJyaWMnO1xuZXhwb3J0ICogZnJvbSAnLi9xdWV1ZSc7XG5leHBvcnQgKiBmcm9tICcuL2xyY2xpYi9McmNMaWInO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscy9TZXF1ZW50aWFsQnVja2V0JztcbmV4cG9ydCAqIGZyb20gJy4vc3RyZWFtL1ZvaWNlVXRpbHMnO1xuZXhwb3J0ICogZnJvbSAnLi9zdHJlYW0vU3RyZWFtRGlzcGF0Y2hlcic7XG5leHBvcnQgKiBmcm9tICcuL3V0aWxzL1V0aWwnO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscy9UeXBlVXRpbCc7XG5leHBvcnQgKiBmcm9tICcuL3V0aWxzL0FzeW5jUXVldWUnO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscy9GRm1wZWdTdHJlYW0nO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscy9RdWVyeUNhY2hlJztcbmV4cG9ydCAqIGZyb20gJy4vdXRpbHMvUXVlcnlSZXNvbHZlcic7XG5leHBvcnQgKiBmcm9tICdAZGlzY29yZC1wbGF5ZXIvZmZtcGVnJztcbmV4cG9ydCAqIGZyb20gJy4vUGxheWVyJztcbmV4cG9ydCAqIGZyb20gJy4vaG9va3MnO1xuZXhwb3J0ICogZnJvbSAnLi91dGlscy9zZXJkZSc7XG5leHBvcnQgKiBmcm9tICcuL3V0aWxzL0RlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3InO1xuZXhwb3J0ICogZnJvbSAnLi9zdHJlYW0vSW50ZXJjZXB0ZWRTdHJlYW0nO1xuZXhwb3J0ICogZnJvbSAnLi9QbGF5ZXJTdHJlYW1JbnRlcmNlcHRvcic7XG5leHBvcnQge1xuICBBdWRpb0ZpbHRlcnMgYXMgUENNQXVkaW9GaWx0ZXJzLFxuICB0eXBlIEJpcXVhZEZpbHRlcnMsXG4gIEZpbHRlclR5cGUgYXMgQmlxdWFkRmlsdGVyVHlwZSxcbiAgdHlwZSBQQ01GaWx0ZXJzLFxuICBRX0JVVFRFUldPUlRILFxuICBWb2x1bWVUcmFuc2Zvcm1lcixcbiAgQkFTU19FUV9CQU5EUyxcbiAgQUZfTklHSFRDT1JFX1JBVEUsXG4gIEFGX1ZBUE9SV0FWRV9SQVRFLFxuICBGaWx0ZXJzQ2hhaW4gfSBmcm9tXG4nQGRpc2NvcmQtcGxheWVyL2VxdWFsaXplcic7XG5leHBvcnQge1xuICBjcmVhdGVBdWRpb1BsYXllcixcbiAgQXVkaW9QbGF5ZXIsXG4gIGdldFZvaWNlQ29ubmVjdGlvbixcbiAgZ2V0Vm9pY2VDb25uZWN0aW9ucyxcbiAgam9pblZvaWNlQ2hhbm5lbCxcbiAgU3RyZWFtVHlwZSxcbiAgY3JlYXRlQXVkaW9SZXNvdXJjZSxcbiAgdHlwZSBKb2luQ29uZmlnLFxuICB0eXBlIEpvaW5Wb2ljZUNoYW5uZWxPcHRpb25zLFxuICB0eXBlIENyZWF0ZUF1ZGlvUGxheWVyT3B0aW9ucyB9IGZyb21cbidkaXNjb3JkLXZvaXAnO1xuXG5leHBvcnQgeyB2ZXJzaW9uIH0gZnJvbSAnLi92ZXJzaW9uJzsiLCAiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuLy8gQHRzLW5vY2hlY2tcblxuaW1wb3J0IHsgQ2hhbm5lbFR5cGUsIEdhdGV3YXlEaXNwYXRjaEV2ZW50cyB9IGZyb20gJ2Rpc2NvcmQtYXBpLXR5cGVzL3YxMCc7XG5pbXBvcnQgeyBjcmVhdGVDb21wYXRDbGllbnQgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBVdGlsIH0gZnJvbSAnLi4vdXRpbHMvVXRpbCc7XG5cbmltcG9ydCB0eXBlIHsgRGlzY29yZEdhdGV3YXlBZGFwdGVyQ3JlYXRvciB9IGZyb20gJ2Rpc2NvcmQtdm9pcCc7XG5pbXBvcnQge1xuICBDbGllbnQsXG4gIEdhdGV3YXlWb2ljZVNlcnZlclVwZGF0ZURpc3BhdGNoRGF0YSxcbiAgR2F0ZXdheVZvaWNlU3RhdGVVcGRhdGVEaXNwYXRjaERhdGEsXG4gIFZvaWNlU3RhdGUgfSBmcm9tXG4nZGlzY29yZC5qcyc7XG5pbXBvcnQgdHlwZSBFcmlzIGZyb20gJ2VyaXMnO1xuXG50eXBlIEVyaXNVc2VyUmVzb2x2YWJsZSA9IEVyaXMuVXNlciB8IHN0cmluZyB8IEVyaXMuTWVtYmVyO1xudHlwZSBFcmlzR3VpbGRSZXNvbHZhYmxlID1cbkVyaXMuR3VpbGQgfFxuc3RyaW5nIHxcbkVyaXMuTWVtYmVyIHxcbkVyaXMuR3VpbGRDaGFubmVsIHxcbkVyaXMuUm9sZTtcbnR5cGUgRXJpc0NoYW5uZWxSZXNvbHZhYmxlID0gRXJpcy5HdWlsZENoYW5uZWwgfCBzdHJpbmc7XG5cbmNvbnN0IERpc2NvcmRQbGF5ZXJDbGllbnRTeW1ib2wgPSBTeW1ib2woJ0Rpc2NvcmRQbGF5ZXJDbGllbnQnKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzRXJpc0NsaWVudChjbGllbnQ6IGFueSk6IGNsaWVudCBpcyBFcmlzLkNsaWVudCB7XG4gIGNvbnN0IHsgbW9kdWxlLCBlcnJvciB9ID0gVXRpbC5yZXF1aXJlKCdlcmlzJyk7XG5cbiAgaWYgKGVycm9yKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3QgZXJpcyA9IG1vZHVsZSBhcyB0eXBlb2YgaW1wb3J0KCdlcmlzJyk7XG5cbiAgcmV0dXJuIGNsaWVudCBpbnN0YW5jZW9mIGVyaXMuQ2xpZW50O1xufVxuXG5mdW5jdGlvbiBkZWNsYXJlUHJvcGVydHkodGFyZ2V0OiBhbnksIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gIFJlZmxlY3Quc2V0KHRhcmdldCwga2V5LCB2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGdldFByb3BlcnR5PFQ+KHRhcmdldDogYW55LCBrZXk6IHN0cmluZyk6IFQge1xuICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBrZXkpO1xufVxuXG4vKipcbiAqIEFsbG93cyBFcmlzIGNsaWVudHMgdG8gYmUgdXNlZCB3aXRoIGRpc2NvcmQtcGxheWVyLiBXaGVuIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCwgZGlzY29yZC1wbGF5ZXIgY3JlYXRlcyBhIHByb3h5IG9iamVjdCB0aGF0IGludGVyY2VwdHMgY2VydGFpbiBtZXRob2RzIGFuZCBwcm9wZXJ0aWVzIHRvIG1ha2UgaXQgY29tcGF0aWJsZSB3aXRoIGRpc2NvcmQtcGxheWVyLlxuICogQHBhcmFtIGNsaWVudCBUaGUgRXJpcyBjbGllbnQgdG8gYmUgdXNlZC5cbiAqIEByZXR1cm5zIFRoZSBFcmlzIGNsaWVudCB3aXRoIGRpc2NvcmQtcGxheWVyIGNvbXBhdGliaWxpdHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFcmlzQ29tcGF0KGNsaWVudDogRXJpcy5DbGllbnQpOiBDbGllbnQge1xuICBjb25zdCB7IG1vZHVsZSwgZXJyb3IgfSA9IFV0aWwucmVxdWlyZSgnZXJpcycpO1xuXG4gIGlmIChlcnJvcikgdGhyb3cgZXJyb3I7XG5cbiAgY29uc3QgZXJpcyA9IG1vZHVsZSBhcyB0eXBlb2YgaW1wb3J0KCdlcmlzJyk7XG5cbiAgZXJpc1ZvaWNlRXZlbnRzSGFuZGxlcihjbGllbnQpO1xuXG4gIGNvbnN0IGVyaXNQcm94eSA9IG5ldyBQcm94eShjbGllbnQsIHtcbiAgICBnZXQodGFyZ2V0LCBwKSB7XG4gICAgICBzd2l0Y2ggKHApIHtcbiAgICAgICAgY2FzZSAndXNlcnMnOlxuICAgICAgICAgIHJldHVybiBlcmlzVXNlcnNQcm94eSh0YXJnZXQsIGVyaXMpO1xuICAgICAgICBjYXNlICdndWlsZHMnOlxuICAgICAgICAgIHJldHVybiBlcmlzR3VpbGRzUHJveHkodGFyZ2V0LCBlcmlzKTtcbiAgICAgICAgY2FzZSAnY2hhbm5lbHMnOlxuICAgICAgICAgIHJldHVybiBlcmlzQ2hhbm5lbHNQcm94eSh0YXJnZXQsIGVyaXMpO1xuICAgICAgICBjYXNlICdfX2RwX3ZvaWNlU3RhdGVVcGRhdGVfcHJveHknOlxuICAgICAgICAgIHJldHVybiAoaGFuZGxlcjogKGEsIGIpID0+IHZvaWQpID0+XG4gICAgICAgICAgZXJpc1ZvaWNlU3RhdGVVcGRhdGVQcm94eSh0YXJnZXQsIGVyaXNQcm94eSwgaGFuZGxlcik7XG4gICAgICAgIGNhc2UgJ2luY3JlbWVudE1heExpc3RlbmVycyc6XG4gICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgICAgICAgIGNsaWVudC5zZXRNYXhMaXN0ZW5lcnMoY2xpZW50LmdldE1heExpc3RlbmVycygpICsgMSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAnZGVjcmVtZW50TWF4TGlzdGVuZXJzJzpcbiAgICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBwYXRjaGluZ1xuICAgICAgICAgICAgY29uc3QgbGlzdGVuZXJzID0gY2xpZW50LmdldE1heExpc3RlbmVycygpIC0gMTtcblxuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBwYXRjaGluZ1xuICAgICAgICAgICAgY2xpZW50LnNldE1heExpc3RlbmVycyhsaXN0ZW5lcnMgPCAwID8gMSA6IGxpc3RlbmVycyk7XG4gICAgICAgICAgfTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHBhdGNoaW5nXG4gICAgICAgICAgcmV0dXJuIHRhcmdldFtwXTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIFJlZmxlY3Quc2V0KGVyaXNQcm94eSwgRGlzY29yZFBsYXllckNsaWVudFN5bWJvbCwgJ0VyaXMnKTtcblxuICByZXR1cm4gY3JlYXRlQ29tcGF0Q2xpZW50KGVyaXNQcm94eSwgJ0VyaXMnKS5jbGllbnQgYXMgdW5rbm93biBhcyBDbGllbnQ7XG59XG5cbmZ1bmN0aW9uIGVyaXNWb2ljZVN0YXRlVXBkYXRlUHJveHkoXG5jbGllbnQ6IEVyaXMuQ2xpZW50LFxucHJveHk6IEVyaXMuQ2xpZW50LFxuaGFuZGxlcjogKGEsIGIpID0+IHZvaWQpXG57XG4gIGNsaWVudC5vbigndm9pY2VTdGF0ZVVwZGF0ZScsIChtZW1iZXIsIG9sZFN0YXRlKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHByb3hpZWRPbGRTdGF0ZSA9IHtcbiAgICAgICAgY2hhbm5lbElkOiBvbGRTdGF0ZS5jaGFubmVsSUQsXG4gICAgICAgIHNlcnZlck11dGU6IG9sZFN0YXRlLm11dGUsXG4gICAgICAgIHN1cHByZXNzOiBvbGRTdGF0ZS5zdXBwcmVzcyxcbiAgICAgICAgZ3VpbGQ6IHtcbiAgICAgICAgICBpZDogb2xkU3RhdGUuZ3VpbGQuaWRcbiAgICAgICAgfSxcbiAgICAgICAgbWVtYmVyOiB7XG4gICAgICAgICAgaWQ6IG9sZFN0YXRlLnVzZXIuaWRcbiAgICAgICAgfVxuICAgICAgfSBhcyBWb2ljZVN0YXRlO1xuXG4gICAgICBjb25zdCBtZSA9IG1lbWJlci5ndWlsZC5tZW1iZXJzLmdldChjbGllbnQudXNlci5pZCk7XG4gICAgICBjb25zdCByZXNvbHZlZENoYW5uZWwgPSBtZW1iZXIuZ3VpbGQuY2hhbm5lbHMuZ2V0KFxuICAgICAgICBtZW1iZXIudm9pY2VTdGF0ZS5jaGFubmVsSURcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHByb3hpZWROZXdTdGF0ZSA9IHtcbiAgICAgICAgY2hhbm5lbElkOiBtZW1iZXIudm9pY2VTdGF0ZS5jaGFubmVsSUQsXG4gICAgICAgIHNlcnZlck11dGU6IG1lbWJlci52b2ljZVN0YXRlLm11dGUsXG4gICAgICAgIHN1cHByZXNzOiBtZW1iZXIudm9pY2VTdGF0ZS5zdXBwcmVzcyxcbiAgICAgICAgY2hhbm5lbDogZXJpc1Jlc29sdmVkQ2hhbm5lbFByb3h5KHJlc29sdmVkQ2hhbm5lbCwgY2xpZW50KSxcbiAgICAgICAgbWVtYmVyOiB7XG4gICAgICAgICAgaWQ6IG1lbWJlci5pZFxuICAgICAgICB9LFxuICAgICAgICBndWlsZDoge1xuICAgICAgICAgIGlkOiBtZW1iZXIuZ3VpbGQuaWQsXG4gICAgICAgICAgbWVtYmVyczoge1xuICAgICAgICAgICAgbWU6IHtcbiAgICAgICAgICAgICAgaWQ6IG1lPy5pZCxcbiAgICAgICAgICAgICAgdm9pY2U6IHtcbiAgICAgICAgICAgICAgICBhc3luYyBzZXRSZXF1ZXN0VG9TcGVhayh2YWx1ZTogYm9vbGVhbikge1xuICAgICAgICAgICAgICAgICAgdm9pZCB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBtZT8udm9pY2VTdGF0ZTtcbiAgICAgICAgICAgICAgICAgIC8vIGlmIChtZSkge1xuICAgICAgICAgICAgICAgICAgLy8gICByZXR1cm4gbWUudm9pY2Uuc2V0UmVxdWVzdFRvU3BlYWsodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgLy8gfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBhcyBWb2ljZVN0YXRlO1xuXG4gICAgICByZXR1cm4gaGFuZGxlcihwcm94aWVkTmV3U3RhdGUsIHByb3hpZWRPbGRTdGF0ZSk7XG4gICAgfSBjYXRjaCB7XG5cbiAgICAgIC8qIG5vb3AgKi99XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBlcmlzVm9pY2VFdmVudHNIYW5kbGVyKGNsaWVudDogRXJpcy5DbGllbnQpIHtcbiAgbGV0IGFkYXB0ZXJzID0gZ2V0UHJvcGVydHk8TWFwPHN0cmluZywgYW55Pj4oY2xpZW50LCAnYWRhcHRlcnMnKTtcblxuICBpZiAoIWFkYXB0ZXJzKSB7XG4gICAgY29uc3QgY29sbGVjdGlvbiA9IG5ldyBNYXA8c3RyaW5nLCBhbnk+KCk7XG4gICAgYWRhcHRlcnMgPSBjb2xsZWN0aW9uO1xuICAgIGRlY2xhcmVQcm9wZXJ0eShjbGllbnQsICdhZGFwdGVycycsIGNvbGxlY3Rpb24pO1xuICB9XG5cbiAgY2xpZW50Lm9uKCdzaGFyZERpc2Nvbm5lY3QnLCAoXywgc2hhcmRJZCkgPT4ge1xuICAgIGZvciAoY29uc3QgW2d1aWxkSWQsIGFkYXB0ZXJdIG9mIGFkYXB0ZXJzLmVudHJpZXMoKSkge1xuICAgICAgaWYgKGNsaWVudC5ndWlsZHMuZ2V0KGd1aWxkSWQpPy5zaGFyZC5pZCA9PT0gc2hhcmRJZCkge1xuICAgICAgICBhZGFwdGVyLmRlc3Ryb3koKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIGNsaWVudC5vbigncmF3V1MnLCAocGFja2V0KSA9PiB7XG4gICAgc3dpdGNoIChwYWNrZXQudCkge1xuICAgICAgY2FzZSBHYXRld2F5RGlzcGF0Y2hFdmVudHMuVm9pY2VTZXJ2ZXJVcGRhdGU6e1xuICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSBwYWNrZXQuZCBhcyBHYXRld2F5Vm9pY2VTZXJ2ZXJVcGRhdGVEaXNwYXRjaERhdGE7XG4gICAgICAgICAgYWRhcHRlcnMuZ2V0KHBheWxvYWQuZ3VpbGRfaWQpPy5vblZvaWNlU2VydmVyVXBkYXRlKHBheWxvYWQpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgY2FzZSBHYXRld2F5RGlzcGF0Y2hFdmVudHMuVm9pY2VTdGF0ZVVwZGF0ZTp7XG4gICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHBhY2tldC5kIGFzIEdhdGV3YXlWb2ljZVN0YXRlVXBkYXRlRGlzcGF0Y2hEYXRhO1xuXG4gICAgICAgICAgaWYgKFxuICAgICAgICAgIHBheWxvYWQuZ3VpbGRfaWQgJiZcbiAgICAgICAgICBwYXlsb2FkLnNlc3Npb25faWQgJiZcbiAgICAgICAgICBwYXlsb2FkLnVzZXJfaWQgPT09IGNsaWVudC51c2VyLmlkKVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkYXB0ZXJzLmdldChwYXlsb2FkLmd1aWxkX2lkKT8ub25Wb2ljZVN0YXRlVXBkYXRlKHBheWxvYWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZXJpc0NoYW5uZWxzUHJveHkoY2xpZW50OiBFcmlzLkNsaWVudCwgZXJpczogdHlwZW9mIGltcG9ydCgnZXJpcycpKSB7XG4gIGNvbnN0IGhhbmRsZXIgPSB7XG4gICAgY2xpZW50LFxuICAgIGdldCBjYWNoZSgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGdldChpZDogc3RyaW5nKSB7XG4gICAgICAgICAgcmV0dXJuIGNsaWVudC5nZXRDaGFubmVsKGlkKTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzKGlkOiBzdHJpbmcpIHtcbiAgICAgICAgICByZXR1cm4gaWQgaW4gY2xpZW50LmNoYW5uZWxHdWlsZE1hcDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9LFxuICAgIHJlc29sdmUocmVzb2x2YWJsZTogc3RyaW5nIHwgRXJpc0NoYW5uZWxSZXNvbHZhYmxlKSB7XG4gICAgICBpZiAodHlwZW9mIHJlc29sdmFibGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBlcmlzUmVzb2x2ZWRDaGFubmVsUHJveHkoXG4gICAgICAgICAgdGhpcy5jbGllbnQuZ2V0Q2hhbm5lbChyZXNvbHZhYmxlKSBhcyBFcmlzLkd1aWxkQ2hhbm5lbCxcbiAgICAgICAgICBjbGllbnRcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc29sdmFibGUgaW5zdGFuY2VvZiBlcmlzLkd1aWxkQ2hhbm5lbCkge1xuICAgICAgICByZXR1cm4gZXJpc1Jlc29sdmVkQ2hhbm5lbFByb3h5KHJlc29sdmFibGUsIGNsaWVudCk7XG4gICAgICB9XG4gICAgfSxcbiAgICByZXNvbHZlSWQocmVzb2x2YWJsZTogRXJpc0NoYW5uZWxSZXNvbHZhYmxlKSB7XG4gICAgICBjb25zdCBjaGFubmVsID0gdGhpcy5yZXNvbHZlKHJlc29sdmFibGUpO1xuICAgICAgcmV0dXJuIGNoYW5uZWw/LmlkO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gaGFuZGxlcjtcbn1cblxuZnVuY3Rpb24gZXJpc1Jlc29sdmVkQ2hhbm5lbFByb3h5KFxuY2hhbm5lbDogRXJpcy5HdWlsZENoYW5uZWwgfCB1bmRlZmluZWQsXG5jbGllbnQ6IEVyaXMuQ2xpZW50KVxuOiBFcmlzLkd1aWxkQ2hhbm5lbCB8IHVuZGVmaW5lZCB7XG4gIGlmICghY2hhbm5lbCkgcmV0dXJuO1xuXG4gIHJldHVybiBuZXcgUHJveHkoY2hhbm5lbCwge1xuICAgIGdldCh0YXJnZXQsIHApIHtcbiAgICAgIHN3aXRjaCAocCkge1xuICAgICAgICBjYXNlICdndWlsZCc6XG4gICAgICAgICAgcmV0dXJuIGVyaXNWb2ljZUFkYXB0ZXJQcm94eSh0YXJnZXQuZ3VpbGQsIGNsaWVudCk7XG4gICAgICAgIGNhc2UgJ21lbWJlcnMnOlxuICAgICAgICAgIHJldHVybiAodGFyZ2V0IGFzIEVyaXMuVm9pY2VDaGFubmVsKS52b2ljZU1lbWJlcnM7XG4gICAgICAgIGNhc2UgJ2lzVm9pY2VCYXNlZCc6XG4gICAgICAgICAgcmV0dXJuICgpID0+XG4gICAgICAgICAgdGFyZ2V0LnR5cGUgPT09IENoYW5uZWxUeXBlLkd1aWxkVm9pY2UgfHxcbiAgICAgICAgICB0YXJnZXQudHlwZSA9PT0gQ2hhbm5lbFR5cGUuR3VpbGRTdGFnZVZvaWNlO1xuICAgICAgICBjYXNlICdpc1ZvaWNlJzpcbiAgICAgICAgICByZXR1cm4gKCkgPT4gdGFyZ2V0LnR5cGUgPT09IENoYW5uZWxUeXBlLkd1aWxkVm9pY2U7XG4gICAgICAgIGNhc2UgJ2lzU3RhZ2UnOlxuICAgICAgICAgIHJldHVybiAoKSA9PiB0YXJnZXQudHlwZSA9PT0gQ2hhbm5lbFR5cGUuR3VpbGRTdGFnZVZvaWNlO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0W3BdO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGVyaXNWb2ljZUFkYXB0ZXJQcm94eShcbmd1aWxkOiBFcmlzLkd1aWxkIHwgdW5kZWZpbmVkLFxuY2xpZW50OiBFcmlzLkNsaWVudClcbjogRXJpcy5HdWlsZCB8IHVuZGVmaW5lZCB7XG4gIGlmICghZ3VpbGQpIHJldHVybjtcblxuICByZXR1cm4gbmV3IFByb3h5KGd1aWxkLCB7XG4gICAgZ2V0KHRhcmdldCwgcCkge1xuICAgICAgaWYgKHAgPT09ICd2b2ljZUFkYXB0ZXJDcmVhdG9yJykge1xuICAgICAgICByZXR1cm4gZXJpc1ZvaWNlQWRhcHRlckNyZWF0b3IodGFyZ2V0LCBjbGllbnQpO1xuICAgICAgfVxuXG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHBhdGNoaW5nXG4gICAgICByZXR1cm4gdGFyZ2V0W3BdO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGVyaXNWb2ljZUFkYXB0ZXJDcmVhdG9yKFxuZ3VpbGQ6IEVyaXMuR3VpbGQsXG5jbGllbnQ6IEVyaXMuQ2xpZW50KVxuOiBEaXNjb3JkR2F0ZXdheUFkYXB0ZXJDcmVhdG9yIHtcbiAgcmV0dXJuIChtZXRob2RzKSA9PiB7XG4gICAgbGV0IGFkYXB0ZXJzID0gZ2V0UHJvcGVydHk8TWFwPHN0cmluZywgdHlwZW9mIG1ldGhvZHM+PihjbGllbnQsICdhZGFwdGVycycpO1xuXG4gICAgaWYgKCFhZGFwdGVycykge1xuICAgICAgY29uc3QgY29sbGVjdGlvbiA9IG5ldyBNYXA8c3RyaW5nLCB0eXBlb2YgbWV0aG9kcz4oKTtcbiAgICAgIGFkYXB0ZXJzID0gY29sbGVjdGlvbjtcbiAgICAgIGRlY2xhcmVQcm9wZXJ0eShjbGllbnQsICdhZGFwdGVycycsIGNvbGxlY3Rpb24pO1xuICAgIH1cblxuICAgIGFkYXB0ZXJzLnNldChndWlsZC5pZCwgbWV0aG9kcyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc2VuZFBheWxvYWQocGF5bG9hZCkge1xuICAgICAgICBpZiAoZ3VpbGQuc2hhcmQuc3RhdHVzICE9PSAncmVhZHknKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGd1aWxkLnNoYXJkLnNlbmRXUyhwYXlsb2FkLm9wLCBwYXlsb2FkLmQpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgICBkZXN0cm95KCkge1xuICAgICAgICBhZGFwdGVycy5kZWxldGUoZ3VpbGQuaWQpO1xuICAgICAgfVxuICAgIH07XG4gIH07XG59XG5cbmZ1bmN0aW9uIGVyaXNHdWlsZHNQcm94eShjbGllbnQ6IEVyaXMuQ2xpZW50LCBlcmlzOiB0eXBlb2YgaW1wb3J0KCdlcmlzJykpIHtcbiAgcmV0dXJuIG5ldyBQcm94eShjbGllbnQuZ3VpbGRzLCB7XG4gICAgZ2V0KHRhcmdldCwgcCkge1xuICAgICAgaWYgKHAgPT09ICdjYWNoZScpIHtcbiAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICAgIH1cblxuICAgICAgaWYgKHAgPT09ICdyZXNvbHZlJyB8fCBwID09PSAncmVzb2x2ZUlkJykge1xuICAgICAgICBjb25zdCByZXNvbHZlciA9IGZ1bmN0aW9uIChyZXNvbHZhYmxlOiBFcmlzR3VpbGRSZXNvbHZhYmxlKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZhYmxlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5nZXQocmVzb2x2YWJsZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHJlc29sdmFibGUgaW5zdGFuY2VvZiBlcmlzLkd1aWxkKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2YWJsZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgcmVzb2x2YWJsZSBpbnN0YW5jZW9mIGVyaXMuTWVtYmVyIHx8XG4gICAgICAgICAgcmVzb2x2YWJsZSBpbnN0YW5jZW9mIGVyaXMuR3VpbGQgfHxcbiAgICAgICAgICByZXNvbHZhYmxlIGluc3RhbmNlb2YgZXJpcy5HdWlsZENoYW5uZWwgfHxcbiAgICAgICAgICByZXNvbHZhYmxlIGluc3RhbmNlb2YgZXJpcy5Sb2xlKVxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZhYmxlLmd1aWxkO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAocCA9PT0gJ3Jlc29sdmUnKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc29sdmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChyZXNvbHZhYmxlOiBFcmlzR3VpbGRSZXNvbHZhYmxlKSA9PiB7XG4gICAgICAgICAgY29uc3QgZ3VpbGQgPSByZXNvbHZlcihyZXNvbHZhYmxlKTtcbiAgICAgICAgICByZXR1cm4gZ3VpbGQ/LmlkO1xuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHBhdGNoaW5nXG4gICAgICByZXR1cm4gdGFyZ2V0W3BdO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGVyaXNVc2Vyc1Byb3h5KGNsaWVudDogRXJpcy5DbGllbnQsIGVyaXM6IHR5cGVvZiBpbXBvcnQoJ2VyaXMnKSkge1xuICByZXR1cm4gbmV3IFByb3h5KGNsaWVudC51c2Vycywge1xuICAgIGdldCh0YXJnZXQsIHApIHtcbiAgICAgIGlmIChwID09PSAnY2FjaGUnKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChwID09PSAncmVzb2x2ZScgfHwgcCA9PT0gJ3Jlc29sdmVJZCcpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSBmdW5jdGlvbiAocmVzb2x2YWJsZTogRXJpc1VzZXJSZXNvbHZhYmxlKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZhYmxlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5nZXQocmVzb2x2YWJsZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHJlc29sdmFibGUgaW5zdGFuY2VvZiBlcmlzLlVzZXIpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZhYmxlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChyZXNvbHZhYmxlIGluc3RhbmNlb2YgZXJpcy5NZW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZhYmxlLnVzZXI7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChwID09PSAncmVzb2x2ZScpIHtcbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZXI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKHJlc29sdmFibGU6IEVyaXNVc2VyUmVzb2x2YWJsZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHVzZXIgPSByZXNvbHZlcihyZXNvbHZhYmxlKTtcbiAgICAgICAgICByZXR1cm4gdXNlcj8uaWQ7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgIHJldHVybiB0YXJnZXRbcF07XG4gICAgfVxuICB9KTtcbn0iLCAiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuXG5leHBvcnQgY29uc3QgRGlzY29yZFBsYXllckNsaWVudFN5bWJvbCA9IFN5bWJvbCgnRGlzY29yZFBsYXllckNsaWVudCcpO1xuXG5leHBvcnQgdHlwZSBDb21wYXRQcm92aWRlciA9ICdFcmlzJyB8ICdPY2VhbmljJztcblxuZXhwb3J0IGludGVyZmFjZSBDb21wYXRDbGllbnQge1xuICBwcm92aWRlcjogQ29tcGF0UHJvdmlkZXI7XG4gIGNsaWVudDogYW55O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGF0Q2xpZW50KFxuY2xpZW50OiBhbnksXG5wcm92aWRlcjogQ29tcGF0UHJvdmlkZXIpXG46IENvbXBhdENsaWVudCB7XG4gIFJlZmxlY3Quc2V0KGNsaWVudCwgRGlzY29yZFBsYXllckNsaWVudFN5bWJvbCwgcHJvdmlkZXIpO1xuICByZXR1cm4ge1xuICAgIHByb3ZpZGVyLFxuICAgIGNsaWVudFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNDbGllbnRQcm94eShjbGllbnQ6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gUmVmbGVjdC5nZXQoY2xpZW50LCBEaXNjb3JkUGxheWVyQ2xpZW50U3ltYm9sKSAhPSBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29tcGF0TmFtZShjbGllbnQ6IGFueSk6IENvbXBhdFByb3ZpZGVyIHwgbnVsbCB7XG4gIHJldHVybiBSZWZsZWN0LmdldChjbGllbnQsIERpc2NvcmRQbGF5ZXJDbGllbnRTeW1ib2wpID8/IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0VyaXNQcm94eShjbGllbnQ6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0Q29tcGF0TmFtZShjbGllbnQpID09PSAnRXJpcyc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc09jZWFuaWNQcm94eShjbGllbnQ6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0Q29tcGF0TmFtZShjbGllbnQpID09PSAnT2NlYW5pYyc7XG59IiwgImltcG9ydCB7IFN0YWdlQ2hhbm5lbCwgVm9pY2VDaGFubmVsIH0gZnJvbSAnZGlzY29yZC5qcyc7XG5pbXBvcnQgeyBzZXRUaW1lb3V0IH0gZnJvbSAnbm9kZTp0aW1lcnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgR3VpbGRRdWV1ZSB9IGZyb20gJy4uL3F1ZXVlJztcbmltcG9ydCB7IFBsYXlsaXN0LCBUcmFjaywgVHJhY2tTb3VyY2UgfSBmcm9tICcuLi9mYWJyaWMnO1xuaW1wb3J0IHsgT3V0T2ZTcGFjZUVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IHJhbmRvbUludCB9IGZyb20gJ25vZGU6Y3J5cHRvJztcbmltcG9ydCB7XG4gIGNyZWF0ZUZpbHRlcixcbiAgY3JlYXRlU3BvdGlmeUZpbHRlcixcbiAgZml4VHJhY2tTdWZmaXgsXG4gIHJlbW92ZUxpdmUsXG4gIHJlbW92ZVJlbWFzdGVyZWQsXG4gIHlvdXR1YmUsXG4gIHJlbW92ZVplcm9XaWR0aCxcbiAgcmVwbGFjZU5ic3AsXG4gIHJlcGxhY2VTbWFydFF1b3RlcyxcbiAgcmVtb3ZlQ2xlYW5FeHBsaWNpdCB9IGZyb21cbidAd2ViLXNjcm9iYmxlci9tZXRhZGF0YS1maWx0ZXInO1xuXG5leHBvcnQgdHlwZSBSdW50aW1lVHlwZSA9ICdub2RlJyB8ICdkZW5vJyB8ICdidW4nIHwgJ3Vua25vd24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRpbWVEYXRhIHtcbiAgLyoqXG4gICAqIFRpbWUgaW4gZGF5c1xuICAgKi9cbiAgZGF5czogbnVtYmVyO1xuICAvKipcbiAgICogVGltZSBpbiBob3Vyc1xuICAgKi9cbiAgaG91cnM6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRpbWUgaW4gbWludXRlc1xuICAgKi9cbiAgbWludXRlczogbnVtYmVyO1xuICAvKipcbiAgICogVGltZSBpbiBzZWNvbmRzXG4gICAqL1xuICBzZWNvbmRzOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUnVudGltZSB7XG4gIG5hbWU6IFJ1bnRpbWVUeXBlO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG59XG5cbmNsYXNzIFV0aWwge1xuICAvKipcbiAgICogVXRpbHNcbiAgICovXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7fSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBydW50aW1lIGluZm9ybWF0aW9uXG4gICAqL1xuICBzdGF0aWMgZ2V0UnVudGltZSgpOiBSdW50aW1lIHtcbiAgICBjb25zdCB2ZXJzaW9uID1cbiAgICB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyA/IG5hdmlnYXRvci51c2VyQWdlbnQgOiBudWxsO1xuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGlmICh0eXBlb2YgRGVubyAhPT0gJ3VuZGVmaW5lZCcgJiYgRGVuby52ZXJzaW9uKSB7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICByZXR1cm4geyBuYW1lOiAnZGVubycsIHZlcnNpb246IERlbm8udmVyc2lvbi5kZW5vIH07XG4gICAgfVxuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGlmICh0eXBlb2YgQnVuICE9PSAndW5kZWZpbmVkJyAmJiBCdW4udmVyc2lvbikge1xuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgcmV0dXJuIHsgbmFtZTogJ2J1bicsIHZlcnNpb246IEJ1bi52ZXJzaW9uIH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJyAmJiBwcm9jZXNzLnZlcnNpb24pXG4gICAgcmV0dXJuIHsgbmFtZTogJ25vZGUnLCB2ZXJzaW9uOiBwcm9jZXNzLnZlcnNpb24gfTtcblxuICAgIHJldHVybiB7IG5hbWU6ICd1bmtub3duJywgdmVyc2lvbjogdmVyc2lvbiA/PyAndW5rbm93bicgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGR1cmF0aW9uIHN0cmluZ1xuICAgKiBAcGFyYW0ge29iamVjdH0gZHVyT2JqIFRoZSBkdXJhdGlvbiBvYmplY3RcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBkdXJhdGlvblN0cmluZyhkdXJPYmo6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4pIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhkdXJPYmopLlxuICAgIG1hcCgobSkgPT4gaXNOYU4obSkgPyAwIDogbSkuXG4gICAgam9pbignOicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyBtaWxsaXNlY29uZHMgdG8gY29uc3VtYWJsZSB0aW1lIG9iamVjdFxuICAgKiBAcGFyYW0ge251bWJlcn0gbWlsbGlzZWNvbmRzIFRoZSB0aW1lIGluIG1zXG4gICAqIEByZXR1cm5zIHtUaW1lRGF0YX1cbiAgICovXG4gIHN0YXRpYyBwYXJzZU1TKG1pbGxpc2Vjb25kczogbnVtYmVyKSB7XG4gICAgaWYgKGlzTmFOKG1pbGxpc2Vjb25kcykpIG1pbGxpc2Vjb25kcyA9IDA7XG4gICAgY29uc3Qgcm91bmQgPSBtaWxsaXNlY29uZHMgPiAwID8gTWF0aC5mbG9vciA6IE1hdGguY2VpbDtcblxuICAgIHJldHVybiB7XG4gICAgICBkYXlzOiByb3VuZChtaWxsaXNlY29uZHMgLyA4NjQwMDAwMCksXG4gICAgICBob3Vyczogcm91bmQobWlsbGlzZWNvbmRzIC8gMzYwMDAwMCkgJSAyNCxcbiAgICAgIG1pbnV0ZXM6IHJvdW5kKG1pbGxpc2Vjb25kcyAvIDYwMDAwKSAlIDYwLFxuICAgICAgc2Vjb25kczogcm91bmQobWlsbGlzZWNvbmRzIC8gMTAwMCkgJSA2MFxuICAgIH0gYXMgVGltZURhdGE7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIHRpbWUgY29kZVxuICAgKiBAcGFyYW0ge1RpbWVEYXRhfSBkdXJhdGlvbiBUaGUgZHVyYXRpb24gb2JqZWN0XG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICBzdGF0aWMgYnVpbGRUaW1lQ29kZShkdXJhdGlvbjogVGltZURhdGEpIHtcbiAgICBjb25zdCBpdGVtcyA9IE9iamVjdC5rZXlzKGR1cmF0aW9uKTtcbiAgICBjb25zdCByZXF1aXJlZCA9IFsnZGF5cycsICdob3VycycsICdtaW51dGVzJywgJ3NlY29uZHMnXTtcblxuICAgIGNvbnN0IHBhcnNlZCA9IGl0ZW1zLlxuICAgIGZpbHRlcigoeCkgPT4gcmVxdWlyZWQuaW5jbHVkZXMoeCkpLlxuICAgIG1hcCgobSkgPT4gZHVyYXRpb25bbSBhcyBrZXlvZiBUaW1lRGF0YV0pO1xuICAgIGNvbnN0IGZpbmFsID0gcGFyc2VkLlxuICAgIHNsaWNlKHBhcnNlZC5maW5kSW5kZXgoKHgpID0+IHggIT09IDApKS5cbiAgICBtYXAoKHgpID0+IHgudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAnMCcpKS5cbiAgICBqb2luKCc6Jyk7XG5cbiAgICByZXR1cm4gZmluYWwubGVuZ3RoIDw9IDMgPyBgMDoke2ZpbmFsLnBhZFN0YXJ0KDIsICcwJykgfHwgMH1gIDogZmluYWw7XG4gIH1cblxuICAvKipcbiAgICogRm9ybWF0cyBkdXJhdGlvblxuICAgKiBAcGFyYW0ge251bWJlcn0gZHVyYXRpb24gVGhlIGR1cmF0aW9uIGluIG1zXG4gICAqL1xuICBzdGF0aWMgZm9ybWF0RHVyYXRpb24oZHVyYXRpb246IG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkVGltZUNvZGUodGhpcy5wYXJzZU1TKGR1cmF0aW9uKSk7XG4gIH1cblxuICAvKipcbiAgICogUGlja3MgbGFzdCBpdGVtIG9mIHRoZSBnaXZlbiBhcnJheVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcnIgVGhlIGFycmF5XG4gICAqIEByZXR1cm5zIHthbnl9XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBzdGF0aWMgbGFzdDxUID0gYW55PihhcnI6IFRbXSk6IFQge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShhcnIpKSByZXR1cm4gYXJyO1xuICAgIHJldHVybiBhcnJbYXJyLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgdm9pY2UgY2hhbm5lbCBpcyBlbXB0eVxuICAgKiBAcGFyYW0ge1ZvaWNlQ2hhbm5lbHxTdGFnZUNoYW5uZWx9IGNoYW5uZWwgVGhlIHZvaWNlIGNoYW5uZWxcbiAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAqL1xuICBzdGF0aWMgaXNWb2ljZUVtcHR5KGNoYW5uZWw6IFZvaWNlQ2hhbm5lbCB8IFN0YWdlQ2hhbm5lbCkge1xuICAgIHJldHVybiAoXG4gICAgICBjaGFubmVsICYmIGNoYW5uZWwubWVtYmVycy5maWx0ZXIoKG1lbWJlcikgPT4gIW1lbWJlci51c2VyLmJvdCkuc2l6ZSA9PT0gMCk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbnMgdGhlIHRyYWNrIHRpdGxlXG4gICAqIEBwYXJhbSB0aXRsZSBUaGUgdGl0bGVcbiAgICogQHBhcmFtIHNvdXJjZSBUaGUgc291cmNlXG4gICAqIEByZXR1cm5zIENsZWFuZWQgdGl0bGVcbiAgICovXG4gIHN0YXRpYyBjbGVhblRpdGxlKHRpdGxlOiBzdHJpbmcsIHNvdXJjZTogVHJhY2tTb3VyY2UpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZmlsdGVyT3B0cyA9IHtcbiAgICAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgIHRyYWNrOiBbXG4gICAgICAgIHJlbW92ZVJlbWFzdGVyZWQsXG4gICAgICAgIHJlbW92ZUxpdmUsXG4gICAgICAgIGZpeFRyYWNrU3VmZml4LFxuICAgICAgICByZW1vdmVaZXJvV2lkdGgsXG4gICAgICAgIHJlcGxhY2VOYnNwLFxuICAgICAgICByZXBsYWNlU21hcnRRdW90ZXMsXG4gICAgICAgIHJlbW92ZUNsZWFuRXhwbGljaXRdXG5cbiAgICAgIH07XG4gICAgICBjb25zdCBzcG90aWZ5RmlsdGVyID0gY3JlYXRlRmlsdGVyKGZpbHRlck9wdHMpO1xuICAgICAgc3BvdGlmeUZpbHRlci5leHRlbmQoY3JlYXRlU3BvdGlmeUZpbHRlcigpKTtcbiAgICAgIGNvbnN0IGRlZmF1bHRGaWx0ZXIgPSBjcmVhdGVGaWx0ZXIoZmlsdGVyT3B0cyk7XG5cbiAgICAgIHN3aXRjaCAoc291cmNlKSB7XG4gICAgICAgIGNhc2UgJ3lvdXR1YmUnOlxuICAgICAgICAgIHJldHVybiB5b3V0dWJlKHRpdGxlKTtcbiAgICAgICAgY2FzZSAnc3BvdGlmeSc6XG4gICAgICAgICAgcmV0dXJuIHNwb3RpZnlGaWx0ZXIuZmlsdGVyRmllbGQoJ3RyYWNrJywgdGl0bGUpO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBkZWZhdWx0RmlsdGVyLmZpbHRlckZpZWxkKCd0cmFjaycsIHRpdGxlKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB0aXRsZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2FmZXIgcmVxdWlyZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgTm9kZSByZXF1aXJlIGlkXG4gICAqIEByZXR1cm5zIHthbnl9XG4gICAqL1xuICBzdGF0aWMgcmVxdWlyZShpZDogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB7IG1vZHVsZTogcmVxdWlyZShpZCksIGVycm9yOiBudWxsIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB7IG1vZHVsZTogbnVsbCwgZXJyb3IgfTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgaW1wb3J0KGlkOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbW9kID0gYXdhaXQgaW1wb3J0KGlkKTtcbiAgICAgIHJldHVybiB7IG1vZHVsZTogbW9kLCBlcnJvcjogbnVsbCB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4geyBtb2R1bGU6IG51bGwsIGVycm9yIH07XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFzeW5jaHJvbm91cyB0aW1lb3V0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lIFRoZSB0aW1lIGluIG1zIHRvIHdhaXRcbiAgICogQHJldHVybnMge1Byb21pc2U8dW5rbm93bj59XG4gICAqL1xuICBzdGF0aWMgd2FpdCh0aW1lOiBudW1iZXIpIHtcbiAgICByZXR1cm4gc2V0VGltZW91dCh0aW1lLCB1bmRlZmluZWQsIHsgcmVmOiBmYWxzZSB9KTtcbiAgfVxuXG4gIHN0YXRpYyBub29wKCkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cblxuICBzdGF0aWMgYXN5bmMgZ2V0RmV0Y2goKSB7XG4gICAgaWYgKCdmZXRjaCcgaW4gZ2xvYmFsVGhpcykgcmV0dXJuIGdsb2JhbFRoaXMuZmV0Y2g7XG4gICAgZm9yIChjb25zdCBsaWIgb2YgWydub2RlLWZldGNoJywgJ3VuZGljaSddKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgaW1wb3J0KGxpYikudGhlbihcbiAgICAgICAgICAocmVzKSA9PiByZXMuZmV0Y2ggfHwgcmVzLmRlZmF1bHQ/LmZldGNoIHx8IHJlcy5kZWZhdWx0XG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICBjb25zdCByZXMgPSByZXF1aXJlKGxpYik7XG4gICAgICAgICAgaWYgKHJlcykgcmV0dXJuIHJlcy5mZXRjaCB8fCByZXMuZGVmYXVsdD8uZmV0Y2ggfHwgcmVzLmRlZmF1bHQ7XG4gICAgICAgIH0gY2F0Y2gge1xuXG4gICAgICAgICAgLy8gbm8/XG4gICAgICAgIH19XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHdhcm4obWVzc2FnZTogc3RyaW5nLCBjb2RlID0gJ0RlcHJlY2F0aW9uV2FybmluZycsIGRldGFpbD86IHN0cmluZykge1xuICAgIHByb2Nlc3MuZW1pdFdhcm5pbmcobWVzc2FnZSwge1xuICAgICAgY29kZSxcbiAgICAgIGRldGFpbFxuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIHJhbmRvbUNob2ljZTxUPihzcmM6IFRbXSk6IFQge1xuICAgIHJldHVybiBzcmNbcmFuZG9tSW50KHNyYy5sZW5ndGgpXTtcbiAgfVxuXG4gIHN0YXRpYyBhcnJheUNsb25lU2h1ZmZsZTxUPihzcmM6IFRbXSk6IFRbXSB7XG4gICAgY29uc3QgYXJyID0gc3JjLnNsaWNlKCk7XG5cbiAgICBsZXQgbSA9IGFyci5sZW5ndGg7XG5cbiAgICB3aGlsZSAobSkge1xuICAgICAgY29uc3QgaSA9IE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIG0tLSk7XG4gICAgICBbYXJyW21dLCBhcnJbaV1dID0gW2FycltpXSwgYXJyW21dXTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJyO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBWQUxJREFURV9RVUVVRV9DQVAgPSAoXG5xdWV1ZTogR3VpbGRRdWV1ZSxcbml0ZW1zOiBQbGF5bGlzdCB8IFRyYWNrIHwgVHJhY2tbXSB8IG51bWJlcikgPT5cbntcbiAgaWYgKHF1ZXVlLm1heFNpemUgPCAxIHx8IHF1ZXVlLm1heFNpemUgPT09IEluZmluaXR5KSByZXR1cm47XG5cbiAgY29uc3QgdHJhY2tzID1cbiAgdHlwZW9mIGl0ZW1zID09PSAnbnVtYmVyJyA/XG4gIGl0ZW1zIDpcbiAgKGl0ZW1zIGluc3RhbmNlb2YgUGxheWxpc3QgP1xuICBpdGVtcy50cmFja3MgOlxuICBBcnJheS5pc0FycmF5KGl0ZW1zKSA/XG4gIGl0ZW1zIDpcbiAgW2l0ZW1zXSkuXG4gIGxlbmd0aDtcblxuICBjb25zdCBtYXhDYXAgPSBxdWV1ZS5nZXRDYXBhY2l0eSgpO1xuXG4gIGlmIChtYXhDYXAgPCB0cmFja3MpIHtcbiAgICB0aHJvdyBuZXcgT3V0T2ZTcGFjZUVycm9yKCd0cmFja3MgcXVldWUnLCBtYXhDYXAsIHRyYWNrcyk7XG4gIH1cbn07XG5cbmV4cG9ydCB7IFV0aWwgfTsiLCAiaW1wb3J0IHtcbiAgVXNlcixcbiAgZXNjYXBlTWFya2Rvd24sXG4gIFNub3dmbGFrZVV0aWwsXG4gIEd1aWxkVm9pY2VDaGFubmVsUmVzb2x2YWJsZSxcbiAgQVBJVXNlciB9IGZyb21cbidkaXNjb3JkLmpzJztcbmltcG9ydCB7XG4gIFBsYXllcixcbiAgUGxheWVyTm9kZUluaXRpYWxpemF0aW9uUmVzdWx0LFxuICBQbGF5ZXJOb2RlSW5pdGlhbGl6ZXJPcHRpb25zIH0gZnJvbVxuJy4uL1BsYXllcic7XG5pbXBvcnQgeyBQbGF5bGlzdCwgUGxheWxpc3RKU09OIH0gZnJvbSAnLi9QbGF5bGlzdCc7XG5pbXBvcnQgeyBHdWlsZFF1ZXVlIH0gZnJvbSAnLi4vcXVldWUvR3VpbGRRdWV1ZSc7XG5pbXBvcnQgeyBCYXNlRXh0cmFjdG9yIH0gZnJvbSAnLi4vZXh0cmFjdG9ycy9CYXNlRXh0cmFjdG9yJztcbmltcG9ydCB7IENvbGxlY3Rpb24gfSBmcm9tICdAZGlzY29yZC1wbGF5ZXIvdXRpbHMnO1xuaW1wb3J0IHsgVHlwZVV0aWwgfSBmcm9tICcuLi91dGlscy9UeXBlVXRpbCc7XG5pbXBvcnQgeyBTZXJpYWxpemVkVHlwZSwgdHJ5SW50b1RodW1ibmFpbFN0cmluZyB9IGZyb20gJy4uL3V0aWxzL3NlcmRlJztcbmltcG9ydCB7IEludmFsaWRBcmdUeXBlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uL3V0aWxzL1V0aWwnO1xuaW1wb3J0IHsgU2VhcmNoUXVlcnlUeXBlIH0gZnJvbSAnLi4vdXRpbHMvUXVlcnlSZXNvbHZlcic7XG5pbXBvcnQgeyBBdWRpb1Jlc291cmNlIH0gZnJvbSAnZGlzY29yZC12b2lwJztcbmltcG9ydCB7IFNlZWtFdmVudCB9IGZyb20gJ0BkaXNjb3JkLXBsYXllci9lcXVhbGl6ZXInO1xuXG5leHBvcnQgdHlwZSBUcmFja1Jlc29sdmFibGUgPSBUcmFjayB8IHN0cmluZyB8IG51bWJlcjtcblxuZXhwb3J0IHR5cGUgV2l0aE1ldGFkYXRhPFQgZXh0ZW5kcyBvYmplY3QsIE0+ID0gVCAmIHtcbiAgbWV0YWRhdGE6IE07XG4gIHJlcXVlc3RNZXRhZGF0YSgpOiBQcm9taXNlPE0+O1xufTtcblxuZXhwb3J0IHR5cGUgU2VyaWFsaXplZFRyYWNrID0gUmV0dXJuVHlwZTxUcmFja1snc2VyaWFsaXplJ10+O1xuXG4vKipcbiAqIFRoZSB0cmFjayBzb3VyY2U6XG4gKiAtIHNvdW5kY2xvdWRcbiAqIC0geW91dHViZVxuICogLSBzcG90aWZ5XG4gKiAtIGFwcGxlX211c2ljXG4gKiAtIGFyYml0cmFyeVxuICovXG5leHBvcnQgdHlwZSBUcmFja1NvdXJjZSA9XG4nc291bmRjbG91ZCcgfFxuJ3lvdXR1YmUnIHxcbidzcG90aWZ5JyB8XG4nYXBwbGVfbXVzaWMnIHxcbidhcmJpdHJhcnknO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJhd1RyYWNrRGF0YSB7XG4gIC8qKlxuICAgKiBUaGUgdGl0bGVcbiAgICovXG4gIHRpdGxlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb25cbiAgICovXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgYXV0aG9yXG4gICAqL1xuICBhdXRob3I6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSB1cmxcbiAgICovXG4gIHVybDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHRodW1ibmFpbFxuICAgKi9cbiAgdGh1bWJuYWlsOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZHVyYXRpb25cbiAgICovXG4gIGR1cmF0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZHVyYXRpb24gaW4gbXNcbiAgICovXG4gIHZpZXdzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgdXNlciB3aG8gcmVxdWVzdGVkIHRoaXMgdHJhY2tcbiAgICovXG4gIHJlcXVlc3RlZEJ5PzogVXNlciB8IG51bGw7XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3RcbiAgICovXG4gIHBsYXlsaXN0PzogUGxheWxpc3Q7XG4gIC8qKlxuICAgKiBUaGUgc291cmNlXG4gICAqL1xuICBzb3VyY2U/OiBUcmFja1NvdXJjZTtcbiAgLyoqXG4gICAqIFRoZSBlbmdpbmVcbiAgICovXG4gIGVuZ2luZT86IGFueTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gIC8qKlxuICAgKiBJZiB0aGlzIHRyYWNrIGlzIGxpdmVcbiAgICovXG4gIGxpdmU/OiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIHJhdyBkYXRhXG4gICAqL1xuICByYXc/OiBhbnk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAvKipcbiAgICogVGhlIHF1ZXJ5IHR5cGVcbiAgICovXG4gIHF1ZXJ5VHlwZT86IFNlYXJjaFF1ZXJ5VHlwZTtcbiAgLyoqXG4gICAqIFRoZSBzZXJpYWxpemVkIHRpdGxlXG4gICAqL1xuICBjbGVhblRpdGxlPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYWNrSlNPTiB7XG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgaWRcbiAgICovXG4gIGlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgdGl0bGVcbiAgICovXG4gIHRpdGxlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgZGVzY3JpcHRpb25cbiAgICovXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgYXV0aG9yXG4gICAqL1xuICBhdXRob3I6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSB0cmFjayB1cmxcbiAgICovXG4gIHVybDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHRyYWNrIHRodW1ibmFpbFxuICAgKi9cbiAgdGh1bWJuYWlsOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgZHVyYXRpb25cbiAgICovXG4gIGR1cmF0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgZHVyYXRpb24gaW4gbXNcbiAgICovXG4gIGR1cmF0aW9uTVM6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB0cmFjayB2aWV3c1xuICAgKi9cbiAgdmlld3M6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB1c2VyIGlkIHdobyByZXF1ZXN0ZWQgdGhpcyB0cmFja1xuICAgKi9cbiAgcmVxdWVzdGVkQnk6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBwbGF5bGlzdCBpbmZvIChpZiBhbnkpXG4gICAqL1xuICBwbGF5bGlzdD86IFBsYXlsaXN0SlNPTjtcbn1cblxuZXhwb3J0IGNsYXNzIFRyYWNrPFQgPSB1bmtub3duPiB7XG4gIHB1YmxpYyB0aXRsZTogc3RyaW5nO1xuICBwdWJsaWMgZGVzY3JpcHRpb246IHN0cmluZztcbiAgcHVibGljIGF1dGhvcjogc3RyaW5nO1xuICBwdWJsaWMgdXJsOiBzdHJpbmc7XG4gIHB1YmxpYyB0aHVtYm5haWw6IHN0cmluZztcbiAgcHVibGljIGR1cmF0aW9uOiBzdHJpbmc7XG4gIHB1YmxpYyB2aWV3czogbnVtYmVyO1xuICBwdWJsaWMgcmVxdWVzdGVkQnk6IFVzZXIgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIHBsYXlsaXN0PzogUGxheWxpc3Q7XG4gIHB1YmxpYyBxdWVyeVR5cGU6IFNlYXJjaFF1ZXJ5VHlwZSB8IG51bGwgfCB1bmRlZmluZWQgPSBudWxsO1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBwdWJsaWMgcmF3OiBhbnk7XG4gIHB1YmxpYyBleHRyYWN0b3I6IEJhc2VFeHRyYWN0b3IgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIHJlYWRvbmx5IGlkID0gU25vd2ZsYWtlVXRpbC5nZW5lcmF0ZSgpLnRvU3RyaW5nKCk7XG4gIHByaXZhdGUgX19tZXRhZGF0YTogVCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9fcmVxTWV0YWRhdGFGbjogKCkgPT4gUHJvbWlzZTxUIHwgbnVsbD47XG4gIHB1YmxpYyBjbGVhblRpdGxlOiBzdHJpbmc7XG4gIHB1YmxpYyBsaXZlOiBib29sZWFuID0gZmFsc2U7XG4gIHB1YmxpYyBicmlkZ2VkRXh0cmFjdG9yOiBCYXNlRXh0cmFjdG9yIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyBicmlkZ2VkVHJhY2s6IFRyYWNrIHwgbnVsbCA9IG51bGw7XG5cbiAgI29uU2VlazogKChldmVudDogU2Vla0V2ZW50KSA9PiBBd2FpdGVkPHZvaWQ+KSB8IG51bGwgPSBudWxsO1xuICAjcmVzb3VyY2U6IEF1ZGlvUmVzb3VyY2U8VHJhY2s+IHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRyYWNrIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSBwbGF5ZXIgVGhlIHBsYXllciB0aGF0IGluc3RhbnRpYXRlZCB0aGlzIFRyYWNrXG4gICAqIEBwYXJhbSBkYXRhIFRyYWNrIGRhdGFcbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgcHVibGljIHJlYWRvbmx5IHBsYXllcjogUGxheWVyLFxuICBkYXRhOiBQYXJ0aWFsPFdpdGhNZXRhZGF0YTxSYXdUcmFja0RhdGEsIFQ+PilcbiAge1xuICAgIHRoaXMudGl0bGUgPSBlc2NhcGVNYXJrZG93bihkYXRhLnRpdGxlID8/ICcnKTtcbiAgICB0aGlzLmF1dGhvciA9IGRhdGEuYXV0aG9yID8/ICcnO1xuICAgIHRoaXMudXJsID0gZGF0YS51cmwgPz8gJyc7XG4gICAgdGhpcy50aHVtYm5haWwgPSBkYXRhLnRodW1ibmFpbCA/PyAnJztcbiAgICB0aGlzLmR1cmF0aW9uID0gZGF0YS5kdXJhdGlvbiA/PyAnJztcbiAgICB0aGlzLnZpZXdzID0gZGF0YS52aWV3cyA/PyAwO1xuICAgIHRoaXMucXVlcnlUeXBlID0gZGF0YS5xdWVyeVR5cGU7XG4gICAgdGhpcy5yZXF1ZXN0ZWRCeSA9IGRhdGEucmVxdWVzdGVkQnkgfHwgbnVsbDtcbiAgICB0aGlzLnBsYXlsaXN0ID0gZGF0YS5wbGF5bGlzdDtcbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gYCR7dGhpcy50aXRsZX0gYnkgJHt0aGlzLmF1dGhvcn1gO1xuICAgIHRoaXMucmF3ID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHt9LFxuICAgICAgeyBzb3VyY2U6IGRhdGEucmF3Py5zb3VyY2UgPz8gZGF0YS5zb3VyY2UgfSxcbiAgICAgIGRhdGEucmF3ID8/IGRhdGFcbiAgICApO1xuICAgIHRoaXMuX19tZXRhZGF0YSA9IGRhdGEubWV0YWRhdGEgPz8gbnVsbDtcbiAgICB0aGlzLl9fcmVxTWV0YWRhdGFGbiA9XG4gICAgZGF0YS5yZXF1ZXN0TWV0YWRhdGEgfHwgKCgpID0+IFByb21pc2UucmVzb2x2ZTxUIHwgbnVsbD4obnVsbCkpO1xuICAgIHRoaXMuY2xlYW5UaXRsZSA9XG4gICAgZGF0YS5jbGVhblRpdGxlID8/IFV0aWwuY2xlYW5UaXRsZSh0aGlzLnRpdGxlLCB0aGlzLnNvdXJjZSk7XG4gICAgdGhpcy5saXZlID0gZGF0YS5saXZlID8/IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyB0cmFjayBjYW4gYmUgc2Vla2VkXG4gICAqL1xuICBwdWJsaWMgZ2V0IHNlZWthYmxlKCkge1xuICAgIHJldHVybiB0aGlzLiNvblNlZWsgIT09IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBvblNlZWsgZXZlbnRcbiAgICogQHBhcmFtIGZuIFRoZSBvblNlZWsgZXZlbnRcbiAgICovXG4gIHB1YmxpYyBoYW5kbGVTZWVrKGZuOiAoZXZlbnQ6IFNlZWtFdmVudCkgPT4gQXdhaXRlZDx2b2lkPikge1xuICAgIHRoaXMuI29uU2VlayA9IGZuO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3Qgc2Vla1xuICAgKiBAcGFyYW0gZXZlbnQgVGhlIHNlZWsgZXZlbnRcbiAgICovXG4gIHB1YmxpYyBhc3luYyBzZWVrKGV2ZW50OiBTZWVrRXZlbnQpIHtcbiAgICBpZiAodGhpcy4jb25TZWVrKSByZXR1cm4gdGhpcy4jb25TZWVrKGV2ZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGF1ZGlvIHJlc291cmNlIGZvciB0aGlzIHRyYWNrLiBUaGlzIGlzIG5vdCB1c2VmdWwgb3V0c2lkZSBvZiB0aGUgbGlicmFyeS5cbiAgICogQHBhcmFtIHJlc291cmNlIEF1ZGlvIHJlc291cmNlXG4gICAqL1xuICBwdWJsaWMgc2V0UmVzb3VyY2UocmVzb3VyY2U6IEF1ZGlvUmVzb3VyY2U8VHJhY2s+IHwgbnVsbCkge1xuICAgIHRoaXMuI3Jlc291cmNlID0gcmVzb3VyY2U7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhdWRpbyByZXNvdXJjZSBmb3IgdGhpcyB0cmFja1xuICAgKi9cbiAgcHVibGljIGdldCByZXNvdXJjZSgpIHtcbiAgICByZXR1cm4gdGhpcy4jcmVzb3VyY2U7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHRyYWNrIGhhcyBhbiBhdWRpbyByZXNvdXJjZVxuICAgKi9cbiAgcHVibGljIGdldCBoYXNSZXNvdXJjZSgpIHtcbiAgICByZXR1cm4gdGhpcy4jcmVzb3VyY2UgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IG1ldGFkYXRhIGZvciB0aGlzIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVxdWVzdE1ldGFkYXRhKCkge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMuX19yZXFNZXRhZGF0YUZuKCk7XG5cbiAgICB0aGlzLnNldE1ldGFkYXRhKHJlcyk7XG5cbiAgICByZXR1cm4gcmVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBtZXRhZGF0YSBmb3IgdGhpcyB0cmFja1xuICAgKi9cbiAgcHVibGljIHNldE1ldGFkYXRhKG06IFQgfCBudWxsKSB7XG4gICAgdGhpcy5fX21ldGFkYXRhID0gbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRhZGF0YSBvZiB0aGlzIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1ldGFkYXRhKCkge1xuICAgIHJldHVybiB0aGlzLl9fbWV0YWRhdGE7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhpcyB0cmFjayBoYXMgbWV0YWRhdGFcbiAgICovXG4gIHB1YmxpYyBnZXQgaGFzTWV0YWRhdGEoKSB7XG4gICAgcmV0dXJuIHRoaXMubWV0YWRhdGEgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcXVldWUgaW4gd2hpY2ggdGhpcyB0cmFjayBpcyBsb2NhdGVkXG4gICAqL1xuICBwdWJsaWMgZ2V0IHF1ZXVlKCk6IEd1aWxkUXVldWUge1xuICAgIHJldHVybiB0aGlzLnBsYXllci5ub2Rlcy5jYWNoZS5maW5kKChxKSA9PlxuICAgIHEudHJhY2tzLnNvbWUoKGFiKSA9PiBhYi5pZCA9PT0gdGhpcy5pZClcbiAgICApITtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgdHJhY2sgZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRcbiAgICovXG4gIHB1YmxpYyBnZXQgZHVyYXRpb25NUygpOiBudW1iZXIge1xuICAgIGNvbnN0IHRpbWVzID0gKG46IG51bWJlciwgdDogbnVtYmVyKSA9PiB7XG4gICAgICBsZXQgdG4gPSAxO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0OyBpKyspIHRuICo9IG47XG4gICAgICByZXR1cm4gdCA8PSAwID8gMTAwMCA6IHRuICogMTAwMDtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuZHVyYXRpb24uXG4gICAgc3BsaXQoJzonKS5cbiAgICByZXZlcnNlKCkuXG4gICAgbWFwKChtLCBpKSA9PiBwYXJzZUludChtKSAqIHRpbWVzKDYwLCBpKSkuXG4gICAgcmVkdWNlKChhLCBjKSA9PiBhICsgYywgMCk7XG4gIH1cblxuICAvKipcbiAgICogRGlzY29yZCBoeXBlcmxpbmsgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB0cmFja1xuICAgKi9cbiAgcHVibGljIHRvSHlwZXJsaW5rKCk6IHN0cmluZyAvKiBub3QgdXNpbmcgYFske3N0cmluZ31dKCR7c3RyaW5nfSlgIHlldCAqLyB7XG4gICAgcmV0dXJuIGBbJHt0aGlzLnRpdGxlfV0oJHt0aGlzLnVybH0pYDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHNvdXJjZSBvZiB0aGlzIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgZ2V0IHNvdXJjZSgpIHtcbiAgICByZXR1cm4gdGhpcy5yYXc/LnNvdXJjZSA/PyAnYXJiaXRyYXJ5JztcbiAgfVxuXG4gIC8qKlxuICAgKiBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB0cmFja1xuICAgKi9cbiAgcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMudGl0bGV9IGJ5ICR7dGhpcy5hdXRob3J9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSYXcgSlNPTiByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKGhpZGVQbGF5bGlzdD86IGJvb2xlYW4pIHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICB0aXRsZTogdGhpcy50aXRsZSxcbiAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uLFxuICAgICAgYXV0aG9yOiB0aGlzLmF1dGhvcixcbiAgICAgIHVybDogdGhpcy51cmwsXG4gICAgICB0aHVtYm5haWw6IHRoaXMudGh1bWJuYWlsLFxuICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICBkdXJhdGlvbk1TOiB0aGlzLmR1cmF0aW9uTVMsXG4gICAgICB2aWV3czogdGhpcy52aWV3cyxcbiAgICAgIHJlcXVlc3RlZEJ5OiB0aGlzLnJlcXVlc3RlZEJ5Py5pZCB8fCBudWxsLFxuICAgICAgcGxheWxpc3Q6IGhpZGVQbGF5bGlzdCA/IG51bGwgOiB0aGlzLnBsYXlsaXN0Py50b0pTT04oKSA/PyBudWxsXG4gICAgfSBhcyBUcmFja0pTT047XG4gIH1cblxuICAvKipcbiAgICogU2VyaWFsaXplZCB0cmFjayBkYXRhIHRoYXQgY2FuIGJlIHJlY29uc3RydWN0ZWRcbiAgICovXG4gIHB1YmxpYyBzZXJpYWxpemUoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRpdGxlOiB0aGlzLnRpdGxlLFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMuZGVzY3JpcHRpb24sXG4gICAgICBhdXRob3I6IHRoaXMuYXV0aG9yLFxuICAgICAgdXJsOiB0aGlzLnVybCxcbiAgICAgIHRodW1ibmFpbDogVHlwZVV0aWwuaXNTdHJpbmcodGhpcy50aHVtYm5haWwpID9cbiAgICAgIHRoaXMudGh1bWJuYWlsIDpcbiAgICAgIHRyeUludG9UaHVtYm5haWxTdHJpbmcodGhpcy50aHVtYm5haWwpLFxuICAgICAgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sXG4gICAgICB2aWV3czogdGhpcy52aWV3cyA/PyAwLFxuICAgICAgcmVxdWVzdGVkX2J5OiB0aGlzLnJlcXVlc3RlZEJ5Py50b0pTT04oKSA/PyBudWxsLFxuICAgICAgc291cmNlOiB0aGlzLnNvdXJjZSxcbiAgICAgIGxpdmU6IGZhbHNlLFxuICAgICAgcXVlcnlfdHlwZTogdGhpcy5xdWVyeVR5cGUsXG4gICAgICBleHRyYWN0b3I6IHRoaXMuZXh0cmFjdG9yPy5pZGVudGlmaWVyID8/IG51bGwsXG4gICAgICBtZXRhZGF0YTogdGhpcy5tZXRhZGF0YSxcbiAgICAgICR0eXBlOiBTZXJpYWxpemVkVHlwZS5UcmFjayxcbiAgICAgICRlbmNvZGVyX3ZlcnNpb246IHRoaXMucGxheWVyLnZlcnNpb25cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBhIHRyYWNrIGZyb20gc2VyaWFsaXplZCBkYXRhXG4gICAqIEBwYXJhbSBwbGF5ZXIgUGxheWVyIGluc3RhbmNlXG4gICAqIEBwYXJhbSBkYXRhIFNlcmlhbGl6ZWQgZGF0YVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tU2VyaWFsaXplZChcbiAgcGxheWVyOiBQbGF5ZXIsXG4gIGRhdGE6IFJldHVyblR5cGU8VHJhY2tbJ3NlcmlhbGl6ZSddPilcbiAge1xuICAgIGlmIChkYXRhLiR0eXBlICE9PSBTZXJpYWxpemVkVHlwZS5UcmFjaylcbiAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ1R5cGVFcnJvcihcbiAgICAgICdkYXRhJyxcbiAgICAgICdTZXJpYWxpemVkVHJhY2snLFxuICAgICAgJ21hbGZvcm1lZCBkYXRhJ1xuICAgICk7XG4gICAgY29uc3QgdHJhY2sgPSBuZXcgVHJhY2socGxheWVyLCB7XG4gICAgICAuLi5kYXRhLFxuICAgICAgcmVxdWVzdGVkQnk6IGRhdGEucmVxdWVzdGVkX2J5ID9cbiAgICAgICgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlcyA9IGRhdGEucmVxdWVzdGVkX2J5IGFzIEFQSVVzZXI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSBwbGF5ZXIuY2xpZW50LnVzZXJzLnJlc29sdmUocmVzLmlkKTtcbiAgICAgICAgICBpZiAocmVzb2x2ZWQpIHJldHVybiByZXNvbHZlZDtcbiAgICAgICAgICBpZiAocGxheWVyLmNsaWVudC51c2Vycy5jYWNoZS5oYXMocmVzLmlkKSlcbiAgICAgICAgICByZXR1cm4gcGxheWVyLmNsaWVudC51c2Vycy5jYWNoZS5nZXQocmVzLmlkKSE7XG4gICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICAgICAgICAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlcihwbGF5ZXIuY2xpZW50LCByZXMpO1xuICAgICAgICAgIHJldHVybiB1c2VyO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfSkoKSA6XG4gICAgICBudWxsLFxuICAgICAgcXVlcnlUeXBlOiBkYXRhLnF1ZXJ5X3R5cGUgPz8gdW5kZWZpbmVkXG4gICAgfSk7XG5cbiAgICB0cmFjay5zZXRNZXRhZGF0YShkYXRhLm1ldGFkYXRhKTtcblxuICAgIHJldHVybiB0cmFjaztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYmVsb25naW5nIHF1ZXVlcyBvZiB0aGlzIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgZ2V0QmVsb25naW5nUXVldWVzKCkge1xuICAgIGNvbnN0IG5vZGVzID0gdGhpcy5wbGF5ZXIubm9kZXMuY2FjaGUuZmlsdGVyKChub2RlKSA9PlxuICAgIG5vZGUudHJhY2tzLnNvbWUoKHQpID0+IHQuaWQgPT09IHRoaXMuaWQpXG4gICAgKTtcblxuICAgIHJldHVybiBub2RlcyBhcyBDb2xsZWN0aW9uPHN0cmluZywgR3VpbGRRdWV1ZTx1bmtub3duPj47XG4gIH1cblxuICAvKipcbiAgICogUGxheSB0aGlzIHRyYWNrIHRvIHRoZSBnaXZlbiB2b2ljZSBjaGFubmVsLiBJZiBxdWV1ZSBleGlzdHMgYW5kIGFub3RoZXIgdHJhY2sgaXMgYmVpbmcgcGxheWVkLCB0aGlzIHRyYWNrIHdpbGwgYmUgYWRkZWQgdG8gdGhlIHF1ZXVlLlxuICAgKiBAcGFyYW0gY2hhbm5lbCBWb2ljZSBjaGFubmVsIG9uIHdoaWNoIHRoaXMgdHJhY2sgc2hhbGwgYmUgcGxheWVkXG4gICAqIEBwYXJhbSBvcHRpb25zIE5vZGUgaW5pdGlhbGl6YXRpb24gb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHBsYXk8VCA9IHVua25vd24+KFxuICBjaGFubmVsOiBHdWlsZFZvaWNlQ2hhbm5lbFJlc29sdmFibGUsXG4gIG9wdGlvbnM/OiBQbGF5ZXJOb2RlSW5pdGlhbGl6ZXJPcHRpb25zPFQ+KVxuICA6IFByb21pc2U8UGxheWVyTm9kZUluaXRpYWxpemF0aW9uUmVzdWx0PFQ+PiB7XG4gICAgY29uc3QgZm4gPSB0aGlzLnBsYXllci5wbGF5LmJpbmQodGhpcy5wbGF5ZXIpO1xuXG4gICAgcmV0dXJuIGF3YWl0IGZuKGNoYW5uZWwsIHRoaXMsIG9wdGlvbnMpO1xuICB9XG59IiwgImV4cG9ydCBjbGFzcyBEaXNjb3JkUGxheWVyRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHB1YmxpYyByZWFkb25seSBjb2RlOiBFcnJvckNvZGVzO1xuICBwdWJsaWMgcmVhZG9ubHkgdGltZXN0YW1wOiBudW1iZXIgPSBEYXRlLm5vdygpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihjb2RlOiBFcnJvckNvZGVzLCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgdGhpcy5jb2RlID0gY29kZTtcblxuICAgIGlmIChFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSkge1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvcik7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHRvSlNPTigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogdGhpcy5jb25zdHJ1Y3Rvci5uYW1lLFxuICAgICAgY29kZTogdGhpcy5jb2RlLFxuICAgICAgbWVzc2FnZTogdGhpcy5tZXNzYWdlLFxuICAgICAgdGltZXN0YW1wOiB0aGlzLnRpbWVzdGFtcFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE91dE9mU3BhY2VFcnJvciBleHRlbmRzIERpc2NvcmRQbGF5ZXJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKHRhcmdldDogc3RyaW5nLCBjYXBhY2l0eTogbnVtYmVyLCB0b3RhbDogbnVtYmVyKSB7XG4gICAgc3VwZXIoXG4gICAgICBFcnJvckNvZGVzLkVSUl9PVVRfT0ZfU1BBQ0UsXG4gICAgICBgTWF4IGNhcGFjaXR5IHJlYWNoZWQgZm9yICR7dGFyZ2V0fSAoQ2FwYWNpdHkgJHtjYXBhY2l0eX0vVG90YWwgJHt0b3RhbH0pYFxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEludmFsaWRBcmdUeXBlRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IHN0cmluZywgZXhwZWN0YXRpb246IHN0cmluZywgZm91bmQ6IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfSU5WQUxJRF9BUkdfVFlQRSxcbiAgICAgIGBFeHBlY3RlZCAke3RhcmdldH0gdG8gYmUgXCIke2V4cGVjdGF0aW9ufVwiLCByZWNlaXZlZCBcIiR7Zm91bmR9XCJgXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTm9SZXN1bHRFcnJvciBleHRlbmRzIERpc2NvcmRQbGF5ZXJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIHN1cGVyKEVycm9yQ29kZXMuRVJSX05PX1JFU1VMVCwgbWVzc2FnZSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5vdEltcGxlbWVudGVkRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IHN0cmluZykge1xuICAgIHN1cGVyKEVycm9yQ29kZXMuRVJSX05PVF9JTVBMRU1FTlRFRCwgYCR7dGFyZ2V0fSBpcyBub3QgeWV0IGltcGxlbWVudGVkYCk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5vdEV4aXN0aW5nRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IHN0cmluZykge1xuICAgIHN1cGVyKEVycm9yQ29kZXMuRVJSX05PVF9FWElTVElORywgYCR7dGFyZ2V0fSBkb2VzIG5vdCBleGlzdGApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBPdXRPZlJhbmdlRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IHN0cmluZywgdmFsdWU6IHN0cmluZywgbWluaW11bTogc3RyaW5nLCBtYXhpbXVtOiBzdHJpbmcpIHtcbiAgICBzdXBlcihcbiAgICAgIEVycm9yQ29kZXMuRVJSX09VVF9PRl9SQU5HRSxcbiAgICAgIGAke3RhcmdldH0gaXMgb3V0IG9mIHJhbmdlIChFeHBlY3RlZCBtaW5pbXVtICR7bWluaW11bX0gYW5kIG1heGltdW0gJHttYXhpbXVtfSwgZ290ICR7dmFsdWV9KWBcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOb1ZvaWNlQ29ubmVjdGlvbkVycm9yIGV4dGVuZHMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZT86IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfTk9fVk9JQ0VfQ09OTkVDVElPTixcbiAgICAgIG1lc3NhZ2UgfHxcbiAgICAgICdObyB2b2ljZSBjb25uZWN0aW9uIGF2YWlsYWJsZSwgbWF5YmUgY29ubmVjdCB0byBhIHZvaWNlIGNoYW5uZWwgZmlyc3Q/J1xuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFZvaWNlQ29ubmVjdGlvbkRlc3Ryb3llZEVycm9yIGV4dGVuZHMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXG4gICAgICBFcnJvckNvZGVzLkVSUl9WT0lDRV9DT05ORUNUSU9OX0RFU1RST1lFRCxcbiAgICAgICdDYW5ub3QgdXNlIGRlc3Ryb3llZCB2b2ljZSBjb25uZWN0aW9uJ1xuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5vVm9pY2VDaGFubmVsRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihFcnJvckNvZGVzLkVSUl9OT19WT0lDRV9DSEFOTkVMLCAnQ291bGQgbm90IGdldCB0aGUgdm9pY2UgY2hhbm5lbCcpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBJbnZhbGlkVm9pY2VDaGFubmVsRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihFcnJvckNvZGVzLkVSUl9JTlZBTElEX1ZPSUNFX0NIQU5ORUwsICdFeHBlY3RlZCBhIHZvaWNlIGNoYW5uZWwnKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTm9SZWNlaXZlckVycm9yIGV4dGVuZHMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZT86IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfTk9fUkVDRUlWRVIsXG4gICAgICBtZXNzYWdlIHx8XG4gICAgICAnTm8gdm9pY2UgcmVjZWl2ZXIgaXMgYXZhaWxhYmxlLCBtYXliZSBjb25uZWN0IHRvIGEgdm9pY2UgY2hhbm5lbCBmaXJzdD8nXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgRkZtcGVnRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihFcnJvckNvZGVzLkVSUl9GRk1QRUdfTE9DQVRPUiwgbWVzc2FnZSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE5vQXVkaW9SZXNvdXJjZUVycm9yIGV4dGVuZHMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZT86IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfTk9fQVVESU9fUkVTT1VSQ0UsXG4gICAgICBtZXNzYWdlIHx8ICdFeHBlY3RlZCBhbiBhdWRpbyByZXNvdXJjZSdcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOb0d1aWxkUXVldWVFcnJvciBleHRlbmRzIERpc2NvcmRQbGF5ZXJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U/OiBzdHJpbmcpIHtcbiAgICBzdXBlcihFcnJvckNvZGVzLkVSUl9OT19HVUlMRF9RVUVVRSwgbWVzc2FnZSB8fCAnRXhwZWN0ZWQgYSBndWlsZCBxdWV1ZScpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOb0d1aWxkRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlPzogc3RyaW5nKSB7XG4gICAgc3VwZXIoRXJyb3JDb2Rlcy5FUlJfTk9fR1VJTEQsIG1lc3NhZ2UgfHwgJ0V4cGVjdGVkIGEgZ3VpbGQnKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSW5mb1JlcXVpcmVkRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IHN0cmluZywgYWN0dWFsOiBzdHJpbmcpIHtcbiAgICBzdXBlcihcbiAgICAgIEVycm9yQ29kZXMuRVJSX0lORk9fUkVRVUlSRUQsXG4gICAgICBgRXhwZWN0ZWQgJHt0YXJnZXR9LCBmb3VuZCBcIiR7YWN0dWFsfVwiYFxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNlcmlhbGl6YXRpb25FcnJvciBleHRlbmRzIERpc2NvcmRQbGF5ZXJFcnJvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfU0VSSUFMSVpBVElPTl9GQUlMRUQsXG4gICAgICBcIkRvbid0IGtub3cgaG93IHRvIHNlcmlhbGl6ZSB0aGlzIGRhdGFcIlxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIERlc2VyaWFsaXphdGlvbkVycm9yIGV4dGVuZHMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXG4gICAgICBFcnJvckNvZGVzLkVSUl9ERVNFUklBTElaQVRJT05fRkFJTEVELFxuICAgICAgXCJEb24ndCBrbm93IGhvdyB0byBkZXNlcmlhbGl6ZSB0aGlzIGRhdGFcIlxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIElsbGVnYWxIb29rSW52b2NhdGlvbkVycm9yIGV4dGVuZHMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgY29uc3RydWN0b3IodGFyZ2V0OiBzdHJpbmcsIG1lc3NhZ2U/OiBzdHJpbmcpIHtcbiAgICBzdXBlcihcbiAgICAgIEVycm9yQ29kZXMuRVJSX0lMTEVHQUxfSE9PS19JTlZPQ0FUSU9OLFxuICAgICAgYElsbGVnYWwgaW52b2NhdGlvbiBvZiAke3RhcmdldH0gaG9vay4ke21lc3NhZ2UgPyBgICR7bWVzc2FnZX1gIDogJyd9YFxuICAgICk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1vZHVsZU5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih0YXJnZXQ6IHN0cmluZywgZGVzY3JpcHRpb24gPSAnJykge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfTk9UX0VYSVNUSU5HX01PRFVMRSxcbiAgICAgIGAke3RhcmdldH0gbW9kdWxlIGRvZXMgbm90IGV4aXN0LiBJbnN0YWxsIGl0IHdpdGggXFxgbnBtIGluc3RhbGwgJHt0YXJnZXR9XFxgLiR7XG4gICAgICBkZXNjcmlwdGlvbiA/ICcgJyArIGRlc2NyaXB0aW9uIDogJyd9YFxuXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQnJpZGdlRmFpbGVkRXJyb3IgZXh0ZW5kcyBEaXNjb3JkUGxheWVyRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihpZDogc3RyaW5nIHwgbnVsbCwgZXJyb3I6IHN0cmluZykge1xuICAgIHN1cGVyKFxuICAgICAgRXJyb3JDb2Rlcy5FUlJfQlJJREdFX0ZBSUxFRCxcbiAgICAgIGAke1xuICAgICAgaWQgPyBgKEV4dHJhY3RvciBFeGVjdXRpb24gQ29udGV4dCBJRCBpcyAke2lkfSlgIDogJyd9RmFpbGVkIHRvIGJyaWRnZSB0aGlzIHF1ZXJ5OlxcbiR7XG4gICAgICBlcnJvcn1gXG4gICAgKTtcbiAgfVxufVxuXG4vLyBGb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbmV4cG9ydCBjb25zdCBFcnJvckNvZGVzID0ge1xuICBFUlJfT1VUX09GX1NQQUNFOiAnRVJSX09VVF9PRl9TUEFDRScsXG4gIEVSUl9JTlZBTElEX0FSR19UWVBFOiAnRVJSX0lOVkFMSURfQVJHX1RZUEUnLFxuICBFUlJfTk9fUkVTVUxUOiAnRVJSX05PX1JFU1VMVCcsXG4gIEVSUl9OT1RfSU1QTEVNRU5URUQ6ICdFUlJfTk9UX0lNUExFTUVOVEVEJyxcbiAgRVJSX05PVF9FWElTVElORzogJ0VSUl9OT1RfRVhJU1RJTkcnLFxuICBFUlJfT1VUX09GX1JBTkdFOiAnRVJSX09VVF9PRl9SQU5HRScsXG4gIEVSUl9OT19WT0lDRV9DT05ORUNUSU9OOiAnRVJSX05PX1ZPSUNFX0NPTk5FQ1RJT04nLFxuICBFUlJfVk9JQ0VfQ09OTkVDVElPTl9ERVNUUk9ZRUQ6ICdFUlJfVk9JQ0VfQ09OTkVDVElPTl9ERVNUUk9ZRUQnLFxuICBFUlJfTk9fVk9JQ0VfQ0hBTk5FTDogJ0VSUl9OT19WT0lDRV9DSEFOTkVMJyxcbiAgRVJSX0lOVkFMSURfVk9JQ0VfQ0hBTk5FTDogJ0VSUl9JTlZBTElEX1ZPSUNFX0NIQU5ORUwnLFxuICBFUlJfTk9fUkVDRUlWRVI6ICdFUlJfTk9fUkVDRUlWRVInLFxuICBFUlJfRkZNUEVHX0xPQ0FUT1I6ICdFUlJfRkZNUEVHX0xPQ0FUT1InLFxuICBFUlJfTk9fQVVESU9fUkVTT1VSQ0U6ICdFUlJfTk9fQVVESU9fUkVTT1VSQ0UnLFxuICBFUlJfTk9fR1VJTERfUVVFVUU6ICdFUlJfTk9fR1VJTERfUVVFVUUnLFxuICBFUlJfTk9fR1VJTEQ6ICdFUlJfTk9fR1VJTEQnLFxuICBFUlJfSU5GT19SRVFVSVJFRDogJ0VSUl9JTkZPX1JFUVVJUkVEJyxcbiAgRVJSX1NFUklBTElaQVRJT05fRkFJTEVEOiAnRVJSX1NFUklBTElaQVRJT05fRkFJTEVEJyxcbiAgRVJSX0RFU0VSSUFMSVpBVElPTl9GQUlMRUQ6ICdFUlJfREVTRVJJQUxJWkFUSU9OX0ZBSUxFRCcsXG4gIEVSUl9JTExFR0FMX0hPT0tfSU5WT0NBVElPTjogJ0VSUl9JTExFR0FMX0hPT0tfSU5WT0NBVElPTicsXG4gIEVSUl9OT1RfRVhJU1RJTkdfTU9EVUxFOiAnRVJSX05PVF9FWElTVElOR19NT0RVTEUnLFxuICBFUlJfQlJJREdFX0ZBSUxFRDogJ0VSUl9CUklER0VfRkFJTEVEJ1xufSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgRXJyb3JDb2RlcyA9ICh0eXBlb2YgRXJyb3JDb2Rlcylba2V5b2YgdHlwZW9mIEVycm9yQ29kZXNdO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpc0Rpc2NvcmRQbGF5ZXJFcnJvcihlcnJvcjogYW55KTogZXJyb3IgaXMgRGlzY29yZFBsYXllckVycm9yIHtcbiAgcmV0dXJuIGVycm9yICE9IG51bGwgJiYgZXJyb3IgaW5zdGFuY2VvZiBEaXNjb3JkUGxheWVyRXJyb3I7XG59XG5cbi8qKlxuICogSGFuZGxlIGEgYERpc2NvcmRQbGF5ZXJFcnJvcmAgZXJyb3IuXG4gKiBAcGFyYW0gZXJyb3IgVGhlIGVycm9yIHRvIGhhbmRsZVxuICogQHBhcmFtIGhhbmRsZXIgVGhlIGhhbmRsZXIgZnVuY3Rpb24uIFRoaXMgZnVuY3Rpb24gd2lsbCBvbmx5IGJlIGNhbGxlZCBpZiB0aGUgZXJyb3IgaXMgYSBgRGlzY29yZFBsYXllckVycm9yYC5cbiAqIEBwYXJhbSBhcmdzIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiB0aGUgaGFuZGxlclxuICogQGV4YW1wbGUgYGBgdHlwZXNjcmlwdFxuICogdHJ5IHtcbiAqICAgLy8gLi4uXG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogIGhhbmRsZURpc2NvcmRQbGF5ZXJFcnJvcihlcnJvciwgKGVycm9yKSA9PiB7XG4gKiAgICBjb25zb2xlLmVycm9yKGBBbiBlcnJvciBvY2N1cnJlZCBmcm9tIGRpc2NvcmQtcGxheWVyOiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gKiAgfSk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZURpc2NvcmRQbGF5ZXJFcnJvcjxcbiAgVCBleHRlbmRzIGFueVtdLFxuICBGIGV4dGVuZHMgKGVycm9yOiBEaXNjb3JkUGxheWVyRXJyb3IsIC4uLmFyZ3M6IFQpID0+IGFueSxcbiAgUiBleHRlbmRzIFJldHVyblR5cGU8Rj4+KFxuZXJyb3I6IGFueSwgaGFuZGxlcjogRiwgYXJnczogVCk6IFIge1xuICBpZiAoaXNEaXNjb3JkUGxheWVyRXJyb3IoZXJyb3IpKSB7XG4gICAgcmV0dXJuIGhhbmRsZXIoZXJyb3IsIC4uLmFyZ3MpIGFzIFI7XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkIGFzIFI7XG59XG5cbi8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqLyIsICJpbXBvcnQgeyBEaXNjb3JkUGxheWVyRXJyb3IsIGlzRGlzY29yZFBsYXllckVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuZXhwb3J0IGNsYXNzIFR5cGVVdGlsIHtcbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHtcbiAgICByZXR1cm4gVHlwZVV0aWw7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xuICBwdWJsaWMgc3RhdGljIGlzRnVuY3Rpb24odDogdW5rbm93bik6IHQgaXMgRnVuY3Rpb24ge1xuICAgIHJldHVybiB0eXBlb2YgdCA9PT0gJ2Z1bmN0aW9uJztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgaXNOdW1iZXIodDogdW5rbm93bik6IHQgaXMgbnVtYmVyIHtcbiAgICByZXR1cm4gdHlwZW9mIHQgPT09ICdudW1iZXInICYmICFpc05hTih0KTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgaXNTdHJpbmcodDogdW5rbm93bik6IHQgaXMgc3RyaW5nIHtcbiAgICByZXR1cm4gdHlwZW9mIHQgPT09ICdzdHJpbmcnO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBpc0Jvb2xlYW4odDogdW5rbm93bik6IHQgaXMgYm9vbGVhbiB7XG4gICAgcmV0dXJuIHR5cGVvZiB0ID09PSAnYm9vbGVhbic7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGlzTnVsbGlzaCh0OiB1bmtub3duKTogdCBpcyBudWxsIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdCA9PSBudWxsO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBpc0FycmF5KHQ6IHVua25vd24pOiB0IGlzIHVua25vd25bXSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkodCk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGlzRXJyb3IodDogdW5rbm93bik6IHQgaXMgRXJyb3Ige1xuICAgIHJldHVybiB0IGluc3RhbmNlb2YgRXJyb3I7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGlzRGlzY29yZFBsYXllckVycm9yKHQ6IHVua25vd24pOiB0IGlzIERpc2NvcmRQbGF5ZXJFcnJvciB7XG4gICAgcmV0dXJuIGlzRGlzY29yZFBsYXllckVycm9yKHQpO1xuICB9XG59IiwgIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cblxuaW1wb3J0IHsgRGVzZXJpYWxpemF0aW9uRXJyb3IsIFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQge1xuICBQbGF5bGlzdCxcbiAgdHlwZSBTZXJpYWxpemVkVHJhY2ssXG4gIFRyYWNrLFxuICBTZXJpYWxpemVkUGxheWxpc3QgfSBmcm9tXG4nLi4vZmFicmljJztcbmltcG9ydCB7IFR5cGVVdGlsIH0gZnJvbSAnLi9UeXBlVXRpbCc7XG5pbXBvcnQgeyBCdWZmZXIgfSBmcm9tICdidWZmZXInO1xuaW1wb3J0IHsgUGxheWVyIH0gZnJvbSAnLi4vUGxheWVyJztcblxuZXhwb3J0IGVudW0gU2VyaWFsaXplZFR5cGUge1xuICBUcmFjayA9ICd0cmFjaycsXG4gIFBsYXlsaXN0ID0gJ3BsYXlsaXN0Jyxcbn1cblxuZXhwb3J0IHR5cGUgRW5jb2RhYmxlID0gU2VyaWFsaXplZFRyYWNrIHwgU2VyaWFsaXplZFBsYXlsaXN0O1xuXG5jb25zdCBpc1RyYWNrID0gKGRhdGE6IGFueSk6IGRhdGEgaXMgU2VyaWFsaXplZFRyYWNrID0+XG5kYXRhLiR0eXBlID09PSBTZXJpYWxpemVkVHlwZS5UcmFjaztcbmNvbnN0IGlzUGxheWxpc3QgPSAoZGF0YTogYW55KTogZGF0YSBpcyBTZXJpYWxpemVkUGxheWxpc3QgPT5cbmRhdGEuJHR5cGUgPT09IFNlcmlhbGl6ZWRUeXBlLlBsYXlsaXN0O1xuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplKGRhdGE6IFRyYWNrIHwgUGxheWxpc3QgfCBhbnkpIHtcbiAgaWYgKGRhdGEgaW5zdGFuY2VvZiBUcmFjaykgcmV0dXJuIGRhdGEuc2VyaWFsaXplKCk7XG4gIGlmIChkYXRhIGluc3RhbmNlb2YgUGxheWxpc3QpIHJldHVybiBkYXRhLnNlcmlhbGl6ZSgpO1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGRhdGEudG9KU09OKCk7XG4gIH0gY2F0Y2gge1xuICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVzZXJpYWxpemUocGxheWVyOiBQbGF5ZXIsIGRhdGE6IEVuY29kYWJsZSkge1xuICBpZiAoaXNUcmFjayhkYXRhKSkgcmV0dXJuIFRyYWNrLmZyb21TZXJpYWxpemVkKHBsYXllciwgZGF0YSk7XG4gIGlmIChpc1BsYXlsaXN0KGRhdGEpKSByZXR1cm4gUGxheWxpc3QuZnJvbVNlcmlhbGl6ZWQocGxheWVyLCBkYXRhKTtcblxuICB0aHJvdyBuZXcgRGVzZXJpYWxpemF0aW9uRXJyb3IoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZShkYXRhOiBFbmNvZGFibGUpIHtcbiAgY29uc3Qgc3RyID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG5cbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKHN0cikudG9TdHJpbmcoJ2Jhc2U2NCcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlKGRhdGE6IHN0cmluZykge1xuICBjb25zdCBzdHIgPSBCdWZmZXIuZnJvbShkYXRhLCAnYmFzZTY0JykudG9TdHJpbmcoKTtcblxuICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJ5SW50b1RodW1ibmFpbFN0cmluZyhkYXRhOiBhbnkpIHtcbiAgaWYgKCFkYXRhKSByZXR1cm4gbnVsbDtcbiAgdHJ5IHtcbiAgICBpZiAoVHlwZVV0aWwuaXNTdHJpbmcoZGF0YSkpIHJldHVybiBkYXRhO1xuICAgIHJldHVybiBkYXRhPy51cmwgPz8gZGF0YT8udGh1bWJuYWlsPy51cmwgPz8gbnVsbDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn0iLCAiaW1wb3J0IHtcbiAgUGxheWVyLFxuICBQbGF5ZXJOb2RlSW5pdGlhbGl6YXRpb25SZXN1bHQsXG4gIFBsYXllck5vZGVJbml0aWFsaXplck9wdGlvbnMgfSBmcm9tXG4nLi4vUGxheWVyJztcbmltcG9ydCB7IFRyYWNrLCBUcmFja0pTT04sIFRyYWNrU291cmNlIH0gZnJvbSAnLi9UcmFjayc7XG5pbXBvcnQgeyBVdGlsIH0gZnJvbSAnLi4vdXRpbHMvVXRpbCc7XG5pbXBvcnQgeyBHdWlsZFZvaWNlQ2hhbm5lbFJlc29sdmFibGUgfSBmcm9tICdkaXNjb3JkLmpzJztcbmltcG9ydCB7IFNlcmlhbGl6ZWRUeXBlLCB0cnlJbnRvVGh1bWJuYWlsU3RyaW5nIH0gZnJvbSAnLi4vdXRpbHMvc2VyZGUnO1xuaW1wb3J0IHsgVHlwZVV0aWwgfSBmcm9tICcuLi91dGlscy9UeXBlVXRpbCc7XG5pbXBvcnQgeyBJbnZhbGlkQXJnVHlwZUVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcblxuZXhwb3J0IHR5cGUgU2VyaWFsaXplZFBsYXlsaXN0ID0gUmV0dXJuVHlwZTxQbGF5bGlzdFsnc2VyaWFsaXplJ10+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFBsYXlsaXN0SW5pdERhdGEge1xuICAvKipcbiAgICogVGhlIHRyYWNrcyBvZiB0aGlzIHBsYXlsaXN0XG4gICAqL1xuICB0cmFja3M6IFRyYWNrW107XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3QgdGl0bGVcbiAgICovXG4gIHRpdGxlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgZGVzY3JpcHRpb25cbiAgICovXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdGh1bWJuYWlsXG4gICAqL1xuICB0aHVtYm5haWw6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBwbGF5bGlzdCB0eXBlOiBgYWxidW1gIHwgYHBsYXlsaXN0YFxuICAgKi9cbiAgdHlwZTogJ2FsYnVtJyB8ICdwbGF5bGlzdCc7XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3Qgc291cmNlXG4gICAqL1xuICBzb3VyY2U6IFRyYWNrU291cmNlO1xuICAvKipcbiAgICogVGhlIHBsYXlsaXN0IGF1dGhvclxuICAgKi9cbiAgYXV0aG9yOiB7XG4gICAgLyoqXG4gICAgICogVGhlIGF1dGhvciBuYW1lXG4gICAgICovXG4gICAgbmFtZTogc3RyaW5nO1xuICAgIC8qKlxuICAgICAqIFRoZSBhdXRob3IgdXJsXG4gICAgICovXG4gICAgdXJsOiBzdHJpbmc7XG4gIH07XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3QgaWRcbiAgICovXG4gIGlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3QgdXJsXG4gICAqL1xuICB1cmw6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSByYXcgcGxheWxpc3QgZGF0YVxuICAgKi9cbiAgcmF3UGxheWxpc3Q/OiBhbnk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBsYXlsaXN0SlNPTiB7XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3QgaWRcbiAgICovXG4gIGlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3QgdXJsXG4gICAqL1xuICB1cmw6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBwbGF5bGlzdCB0aXRsZVxuICAgKi9cbiAgdGl0bGU6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBwbGF5bGlzdCBkZXNjcmlwdGlvblxuICAgKi9cbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSB0aHVtYm5haWxcbiAgICovXG4gIHRodW1ibmFpbDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHBsYXlsaXN0IHR5cGU6IGBhbGJ1bWAgfCBgcGxheWxpc3RgXG4gICAqL1xuICB0eXBlOiAnYWxidW0nIHwgJ3BsYXlsaXN0JztcbiAgLyoqXG4gICAqIFRoZSB0cmFjayBzb3VyY2VcbiAgICovXG4gIHNvdXJjZTogVHJhY2tTb3VyY2U7XG4gIC8qKlxuICAgKiBUaGUgcGxheWxpc3QgYXV0aG9yXG4gICAqL1xuICBhdXRob3I6IHtcbiAgICAvKipcbiAgICAgKiBUaGUgYXV0aG9yIG5hbWVcbiAgICAgKi9cbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogVGhlIGF1dGhvciB1cmxcbiAgICAgKi9cbiAgICB1cmw6IHN0cmluZztcbiAgfTtcbiAgLyoqXG4gICAqIFRoZSB0cmFja3MgZGF0YSAoaWYgYW55KVxuICAgKi9cbiAgdHJhY2tzOiBUcmFja0pTT05bXTtcbn1cblxuZXhwb3J0IGNsYXNzIFBsYXlsaXN0IHtcbiAgcHVibGljIHJlYWRvbmx5IHBsYXllcjogUGxheWVyO1xuICBwdWJsaWMgdHJhY2tzOiBUcmFja1tdO1xuICBwdWJsaWMgdGl0bGU6IHN0cmluZztcbiAgcHVibGljIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIHB1YmxpYyB0aHVtYm5haWw6IHN0cmluZztcbiAgcHVibGljIHR5cGU6ICdhbGJ1bScgfCAncGxheWxpc3QnO1xuICBwdWJsaWMgc291cmNlOiBUcmFja1NvdXJjZTtcbiAgcHVibGljIGF1dGhvcjoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB1cmw6IHN0cmluZztcbiAgfTtcbiAgcHVibGljIGlkOiBzdHJpbmc7XG4gIHB1YmxpYyB1cmw6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IHJhd1BsYXlsaXN0PzogYW55OyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcblxuICAvKipcbiAgICogUGxheWxpc3QgY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtQbGF5ZXJ9IHBsYXllciBUaGUgcGxheWVyXG4gICAqIEBwYXJhbSB7UGxheWxpc3RJbml0RGF0YX0gZGF0YSBUaGUgZGF0YVxuICAgKi9cbiAgY29uc3RydWN0b3IocGxheWVyOiBQbGF5ZXIsIGRhdGE6IFBsYXlsaXN0SW5pdERhdGEpIHtcbiAgICAvKipcbiAgICAgKiBUaGUgcGxheWVyXG4gICAgICogQG5hbWUgUGxheWxpc3QjcGxheWVyXG4gICAgICogQHR5cGUge1BsYXllcn1cbiAgICAgKiBAcmVhZG9ubHlcbiAgICAgKi9cbiAgICB0aGlzLnBsYXllciA9IHBsYXllcjtcblxuICAgIC8qKlxuICAgICAqIFRoZSB0cmFja3MgaW4gdGhpcyBwbGF5bGlzdFxuICAgICAqIEBuYW1lIFBsYXlsaXN0I3RyYWNrc1xuICAgICAqIEB0eXBlIHtUcmFja1tdfVxuICAgICAqL1xuICAgIHRoaXMudHJhY2tzID0gZGF0YS50cmFja3MgPz8gW107XG5cbiAgICAvKipcbiAgICAgKiBUaGUgYXV0aG9yIG9mIHRoaXMgcGxheWxpc3RcbiAgICAgKiBAbmFtZSBQbGF5bGlzdCNhdXRob3JcbiAgICAgKiBAdHlwZSB7b2JqZWN0fVxuICAgICAqL1xuICAgIHRoaXMuYXV0aG9yID0gZGF0YS5hdXRob3I7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGVzY3JpcHRpb25cbiAgICAgKiBAbmFtZSBQbGF5bGlzdCNkZXNjcmlwdGlvblxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5kZXNjcmlwdGlvbiA9IGRhdGEuZGVzY3JpcHRpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdGh1bWJuYWlsIG9mIHRoaXMgcGxheWxpc3RcbiAgICAgKiBAbmFtZSBQbGF5bGlzdCN0aHVtYm5haWxcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIHRoaXMudGh1bWJuYWlsID0gZGF0YS50aHVtYm5haWw7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxheWxpc3QgdHlwZTpcbiAgICAgKiAtIGBhbGJ1bWBcbiAgICAgKiAtIGBwbGF5bGlzdGBcbiAgICAgKiBAbmFtZSBQbGF5bGlzdCN0eXBlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLnR5cGUgPSBkYXRhLnR5cGU7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc291cmNlIG9mIHRoaXMgcGxheWxpc3Q6XG4gICAgICogLSBgeW91dHViZWBcbiAgICAgKiAtIGBzb3VuZGNsb3VkYFxuICAgICAqIC0gYHNwb3RpZnlgXG4gICAgICogLSBgYXJiaXRyYXJ5YFxuICAgICAqIEBuYW1lIFBsYXlsaXN0I3NvdXJjZVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG4gICAgdGhpcy5zb3VyY2UgPSBkYXRhLnNvdXJjZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF5bGlzdCBpZFxuICAgICAqIEBuYW1lIFBsYXlsaXN0I2lkXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cbiAgICB0aGlzLmlkID0gZGF0YS5pZDtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwbGF5bGlzdCB1cmxcbiAgICAgKiBAbmFtZSBQbGF5bGlzdCN1cmxcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIHRoaXMudXJsID0gZGF0YS51cmw7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgcGxheWxpc3QgdGl0bGVcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIHRoaXMudGl0bGUgPSBkYXRhLnRpdGxlO1xuXG4gICAgLyoqXG4gICAgICogQG5hbWUgUGxheWxpc3QjcmF3UGxheWxpc3RcbiAgICAgKiBAdHlwZSB7YW55fVxuICAgICAqIEByZWFkb25seVxuICAgICAqL1xuICB9XG5cbiAgKltTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHlpZWxkKiB0aGlzLnRyYWNrcztcbiAgfVxuXG4gIC8qKlxuICAgKiBFc3RpbWF0ZWQgZHVyYXRpb24gb2YgdGhpcyBwbGF5bGlzdFxuICAgKi9cbiAgcHVibGljIGdldCBlc3RpbWF0ZWREdXJhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy50cmFja3MucmVkdWNlKChwLCBjKSA9PiBwICsgYy5kdXJhdGlvbk1TLCAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXR0ZWQgZXN0aW1hdGVkIGR1cmF0aW9uIG9mIHRoaXMgcGxheWxpc3RcbiAgICovXG4gIHB1YmxpYyBnZXQgZHVyYXRpb25Gb3JtYXR0ZWQoKSB7XG4gICAgcmV0dXJuIFV0aWwuYnVpbGRUaW1lQ29kZShVdGlsLnBhcnNlTVModGhpcy5lc3RpbWF0ZWREdXJhdGlvbikpO1xuICB9XG5cbiAgLyoqXG4gICAqIEpTT04gcmVwcmVzZW50YXRpb24gb2YgdGhpcyBwbGF5bGlzdFxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFt3aXRoVHJhY2tzPXRydWVdIElmIGl0IHNob3VsZCBidWlsZCBqc29uIHdpdGggdHJhY2tzXG4gICAqIEByZXR1cm5zIHtQbGF5bGlzdEpTT059XG4gICAqL1xuICB0b0pTT04od2l0aFRyYWNrcyA9IHRydWUpIHtcbiAgICBjb25zdCBwYXlsb2FkID0ge1xuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICB1cmw6IHRoaXMudXJsLFxuICAgICAgdGl0bGU6IHRoaXMudGl0bGUsXG4gICAgICBkZXNjcmlwdGlvbjogdGhpcy5kZXNjcmlwdGlvbixcbiAgICAgIHRodW1ibmFpbDogdGhpcy50aHVtYm5haWwsXG4gICAgICB0eXBlOiB0aGlzLnR5cGUsXG4gICAgICBzb3VyY2U6IHRoaXMuc291cmNlLFxuICAgICAgYXV0aG9yOiB0aGlzLmF1dGhvcixcbiAgICAgIHRyYWNrczogW10gYXMgVHJhY2tKU09OW11cbiAgICB9O1xuXG4gICAgaWYgKHdpdGhUcmFja3MpIHBheWxvYWQudHJhY2tzID0gdGhpcy50cmFja3MubWFwKChtKSA9PiBtLnRvSlNPTih0cnVlKSk7XG5cbiAgICByZXR1cm4gcGF5bG9hZCBhcyBQbGF5bGlzdEpTT047XG4gIH1cblxuICAvKipcbiAgICogU2VyaWFsaXplIHRoaXMgcGxheWxpc3QgaW50byByZWNvbnN0cnVjdGFibGUgZGF0YVxuICAgKi9cbiAgcHVibGljIHNlcmlhbGl6ZSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHJhY2tzOiB0aGlzLnRyYWNrcy5tYXAoKG0pID0+IG0uc2VyaWFsaXplKCkpLFxuICAgICAgdGl0bGU6IHRoaXMudGl0bGUsXG4gICAgICBkZXNjcmlwdGlvbjogdGhpcy5kZXNjcmlwdGlvbixcbiAgICAgIHRodW1ibmFpbDogVHlwZVV0aWwuaXNTdHJpbmcodGhpcy50aHVtYm5haWwpID9cbiAgICAgIHRoaXMudGh1bWJuYWlsIDpcbiAgICAgIHRyeUludG9UaHVtYm5haWxTdHJpbmcodGhpcy50aHVtYm5haWwpLFxuICAgICAgdHlwZTogdGhpcy50eXBlLFxuICAgICAgc291cmNlOiB0aGlzLnNvdXJjZSxcbiAgICAgIGF1dGhvcjogdGhpcy5hdXRob3IsXG4gICAgICBpZDogdGhpcy5pZCxcbiAgICAgIHVybDogdGhpcy51cmwsXG4gICAgICAkdHlwZTogU2VyaWFsaXplZFR5cGUuUGxheWxpc3QsXG4gICAgICAkZW5jb2Rlcl92ZXJzaW9uOiB0aGlzLnBsYXllci52ZXJzaW9uXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXNlcmlhbGl6ZSB0aGlzIHBsYXlsaXN0IGZyb20gc2VyaWFsaXplZCBkYXRhXG4gICAqIEBwYXJhbSBwbGF5ZXIgUGxheWVyIGluc3RhbmNlXG4gICAqIEBwYXJhbSBkYXRhIFNlcmlhbGl6ZWQgZGF0YVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tU2VyaWFsaXplZChwbGF5ZXI6IFBsYXllciwgZGF0YTogU2VyaWFsaXplZFBsYXlsaXN0KSB7XG4gICAgaWYgKGRhdGEuJHR5cGUgIT09IFNlcmlhbGl6ZWRUeXBlLlBsYXlsaXN0KVxuICAgIHRocm93IG5ldyBJbnZhbGlkQXJnVHlwZUVycm9yKFxuICAgICAgJ2RhdGEnLFxuICAgICAgJ1NlcmlhbGl6ZWRQbGF5bGlzdCcsXG4gICAgICAnbWFsZm9ybWVkIGRhdGEnXG4gICAgKTtcbiAgICByZXR1cm4gbmV3IFBsYXlsaXN0KHBsYXllciwge1xuICAgICAgLi4uZGF0YSxcbiAgICAgIHRyYWNrczogZGF0YS50cmFja3MubWFwKChtKSA9PiBUcmFjay5mcm9tU2VyaWFsaXplZChwbGF5ZXIsIG0pKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBsYXkgdGhpcyBwbGF5bGlzdCB0byB0aGUgZ2l2ZW4gdm9pY2UgY2hhbm5lbC4gSWYgcXVldWUgZXhpc3RzIGFuZCBhbm90aGVyIHRyYWNrIGlzIGJlaW5nIHBsYXllZCwgdGhpcyBwbGF5bGlzdCB3aWxsIGJlIGFkZGVkIHRvIHRoZSBxdWV1ZS5cbiAgICogQHBhcmFtIGNoYW5uZWwgVm9pY2UgY2hhbm5lbCBvbiB3aGljaCB0aGlzIHBsYXlsaXN0IHNoYWxsIGJlIHBsYXllZFxuICAgKiBAcGFyYW0gb3B0aW9ucyBOb2RlIGluaXRpYWxpemF0aW9uIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBhc3luYyBwbGF5PFQgPSB1bmtub3duPihcbiAgY2hhbm5lbDogR3VpbGRWb2ljZUNoYW5uZWxSZXNvbHZhYmxlLFxuICBvcHRpb25zPzogUGxheWVyTm9kZUluaXRpYWxpemVyT3B0aW9uczxUPilcbiAgOiBQcm9taXNlPFBsYXllck5vZGVJbml0aWFsaXphdGlvblJlc3VsdDxUPj4ge1xuICAgIGNvbnN0IGZuID0gdGhpcy5wbGF5ZXIucGxheS5iaW5kKHRoaXMucGxheWVyKTtcblxuICAgIHJldHVybiBhd2FpdCBmbihjaGFubmVsLCB0aGlzLCBvcHRpb25zKTtcbiAgfVxufSIsICJpbXBvcnQgeyBUeXBlVXRpbCB9IGZyb20gJy4vVHlwZVV0aWwnO1xuaW1wb3J0IHsgSW5mb1JlcXVpcmVkRXJyb3IsIEludmFsaWRBcmdUeXBlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgZmV0Y2ggfSBmcm9tICd1bmRpY2knO1xuXG4vLyAjcmVnaW9uIHNjYXJ5IHRoaW5ncyBiZWxvdyAqc2lnaCpcbmNvbnN0IHNwb3RpZnlTb25nUmVnZXggPVxuL15odHRwcz86XFwvXFwvKD86ZW1iZWRcXC58b3BlblxcLikoPzpzcG90aWZ5XFwuY29tXFwvKShpbnRsLShbYS16XXxbQS1aXSkrXFwvKT8oPzp0cmFja1xcL3xcXD91cmk9c3BvdGlmeTp0cmFjazopKChcXHd8LSl7MjJ9KShcXD9zaT0uKyk/JC87XG5jb25zdCBzcG90aWZ5UGxheWxpc3RSZWdleCA9XG4vXmh0dHBzPzpcXC9cXC8oPzplbWJlZFxcLnxvcGVuXFwuKSg/OnNwb3RpZnlcXC5jb21cXC8pKGludGwtKFthLXpdfFtBLVpdKStcXC8pPyg/OnBsYXlsaXN0XFwvfFxcP3VyaT1zcG90aWZ5OnBsYXlsaXN0OikoKFxcd3wtKXsyMn0pKFxcP3NpPS4rKT8kLztcbmNvbnN0IHNwb3RpZnlBbGJ1bVJlZ2V4ID1cbi9eaHR0cHM/OlxcL1xcLyg/OmVtYmVkXFwufG9wZW5cXC4pKD86c3BvdGlmeVxcLmNvbVxcLykoaW50bC0oW2Etel18W0EtWl0pK1xcLyk/KD86YWxidW1cXC98XFw/dXJpPXNwb3RpZnk6YWxidW06KSgoXFx3fC0pezIyfSkoXFw/c2k9LispPyQvO1xuY29uc3QgdmltZW9SZWdleCA9XG4vXihodHRwfGh0dHBzKT86XFwvXFwvKHd3d1xcLnxwbGF5ZXJcXC4pP3ZpbWVvXFwuY29tXFwvKD86Y2hhbm5lbHNcXC8oPzpcXHcrXFwvKT98Z3JvdXBzXFwvKFteL10qKVxcL3ZpZGVvc1xcL3x2aWRlb1xcL3wpKFxcZCspKD86fFxcL1xcPykkLztcbmNvbnN0IHJldmVyYm5hdGlvblJlZ2V4ID1cbi9eaHR0cHM6XFwvXFwvKHd3dy4pP3JldmVyYm5hdGlvbi5jb21cXC8oLispXFwvc29uZ1xcLyguKykkLztcbmNvbnN0IGF0dGFjaG1lbnRSZWdleCA9IC9eaHR0cHM/OlxcL1xcLy4rJC87XG5jb25zdCBhcHBsZU11c2ljU29uZ1JlZ2V4ID1cbi9eaHR0cHM/OlxcL1xcL211c2ljXFwuYXBwbGVcXC5jb21cXC8uKz9cXC8oc29uZ3xhbGJ1bSlcXC8uKz8oXFwvLis/XFw/aT18XFwvKShbMC05XSspJC87XG5jb25zdCBhcHBsZU11c2ljUGxheWxpc3RSZWdleCA9XG4vXmh0dHBzPzpcXC9cXC9tdXNpY1xcLmFwcGxlXFwuY29tXFwvLis/XFwvcGxheWxpc3RcXC8uK1xcL3BsXFwuKHUtfHBtLSk/W2EtekEtWjAtOV0rJC87XG5jb25zdCBhcHBsZU11c2ljQWxidW1SZWdleCA9XG4vXmh0dHBzPzpcXC9cXC9tdXNpY1xcLmFwcGxlXFwuY29tXFwvLis/XFwvYWxidW1cXC8uK1xcLyhbMC05XSspJC87XG5jb25zdCBzb3VuZGNsb3VkVHJhY2tSZWdleCA9XG4vXmh0dHBzPzpcXC9cXC8obS58d3d3Lik/c291bmRjbG91ZC5jb21cXC8oXFx3fC0pK1xcLyhcXHd8LSkrKC4rKT8kLztcbmNvbnN0IHNvdW5kY2xvdWRQbGF5bGlzdFJlZ2V4ID1cbi9eaHR0cHM/OlxcL1xcLyhtLnx3d3cuKT9zb3VuZGNsb3VkLmNvbVxcLyhcXHd8LSkrXFwvc2V0c1xcLyhcXHd8LSkrKC4rKT8kLztcbmNvbnN0IHlvdXR1YmVQbGF5bGlzdFJlZ2V4ID1cbi9eaHR0cHM/OlxcL1xcLyh3d3cuKT95b3V0dWJlLmNvbVxcL3BsYXlsaXN0XFw/bGlzdD0oKFBMfEZMfFVVfExMfFJEfE9MKVthLXpBLVowLTktX117MTYsNDF9KSQvO1xuY29uc3QgeW91dHViZVZpZGVvVVJMUmVnZXggPVxuL14oKD86aHR0cHM/Oik/XFwvXFwvKT8oKD86d3d3fG0pXFwuKT8oKD86eW91dHViZVxcLmNvbXx5b3V0dS5iZSkpKFxcLyg/OltcXHctXStcXD92PXxlbWJlZFxcL3x2XFwvKT8pKFtcXHctXSspKFxcUyspPyQvO1xuY29uc3QgeW91dHViZVZpZGVvSWRSZWdleCA9IC9eW2EtekEtWjAtOS1fXXsxMX0kLztcbi8vIGRpc2NvcmQtcGxheWVyOi8vYmxvYi91dWlkLXY0XG5jb25zdCBkaXNjb3JkUGxheWVyQmxvYlJlZ2V4ID0gL15kaXNjb3JkLXBsYXllcjpcXC9cXC9ibG9iXFwvXFxkKyQvO1xuLy8gI2VuZHJlZ2lvbiBzY2FyeSB0aGluZ3MgYWJvdmUgKnNpZ2gqXG5cbmNvbnN0IERvbWFpbnNNYXAgPSB7XG4gIERpc2NvcmRQbGF5ZXI6IFsnZGlzY29yZC1wbGF5ZXInXSxcbiAgWW91VHViZTogW1xuICAneW91dHViZS5jb20nLFxuICAneW91dHUuYmUnLFxuICAnbXVzaWMueW91dHViZS5jb20nLFxuICAnZ2FtaW5nLnlvdXR1YmUuY29tJyxcbiAgJ3d3dy55b3V0dWJlLmNvbScsXG4gICdtLnlvdXR1YmUuY29tJ10sXG5cbiAgU3BvdGlmeTogWydvcGVuLnNwb3RpZnkuY29tJywgJ2VtYmVkLnNwb3RpZnkuY29tJ10sXG4gIFZpbWVvOiBbJ3ZpbWVvLmNvbScsICdwbGF5ZXIudmltZW8uY29tJ10sXG4gIFJldmVyYk5hdGlvbjogWydyZXZlcmJuYXRpb24uY29tJ10sXG4gIFNvdW5kQ2xvdWQ6IFsnc291bmRjbG91ZC5jb20nXSxcbiAgQXBwbGVNdXNpYzogWydtdXNpYy5hcHBsZS5jb20nXVxufTtcblxuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCByZWRpcmVjdERvbWFpbnMgPSBuZXcgU2V0KFtcbi9eaHR0cHM/OlxcL1xcL3Nwb3RpZnkubGlua1xcL1tBLVphLXowLTldKyQvLFxuL15odHRwczpcXC9cXC9vblxcLnNvdW5kY2xvdWRcXC5jb21cXC9bYS16QS1aMS05XXswLDE3fSQvXVxuKTtcblxuLyoqXG4gKiBUaGUgc2VhcmNoIHF1ZXJ5IHR5cGVcbiAqIFRoaXMgY2FuIGJlIG9uZSBvZjpcbiAqIC0gQVVUT1xuICogLSBZT1VUVUJFXG4gKiAtIFlPVVRVQkVfUExBWUxJU1RcbiAqIC0gU09VTkRDTE9VRF9UUkFDS1xuICogLSBTT1VORENMT1VEX1BMQVlMSVNUXG4gKiAtIFNPVU5EQ0xPVURcbiAqIC0gU1BPVElGWV9TT05HXG4gKiAtIFNQT1RJRllfQUxCVU1cbiAqIC0gU1BPVElGWV9QTEFZTElTVFxuICogLSBTUE9USUZZX1NFQVJDSFxuICogLSBGQUNFQk9PS1xuICogLSBWSU1FT1xuICogLSBBUkJJVFJBUllcbiAqIC0gUkVWRVJCTkFUSU9OXG4gKiAtIFlPVVRVQkVfU0VBUkNIXG4gKiAtIFlPVVRVQkVfVklERU9cbiAqIC0gU09VTkRDTE9VRF9TRUFSQ0hcbiAqIC0gQVBQTEVfTVVTSUNfU09OR1xuICogLSBBUFBMRV9NVVNJQ19BTEJVTVxuICogLSBBUFBMRV9NVVNJQ19QTEFZTElTVFxuICogLSBBUFBMRV9NVVNJQ19TRUFSQ0hcbiAqIC0gRklMRVxuICogLSBBVVRPX1NFQVJDSFxuICogLSBESVNDT1JEX1BMQVlFUl9CTE9CXG4gKiBAdHlwZWRlZiB7c3RyaW5nfSBRdWVyeVR5cGVcbiAqL1xuZXhwb3J0IGNvbnN0IFF1ZXJ5VHlwZSA9IHtcbiAgQVVUTzogJ2F1dG8nLFxuICBZT1VUVUJFOiAneW91dHViZScsXG4gIFlPVVRVQkVfUExBWUxJU1Q6ICd5b3V0dWJlUGxheWxpc3QnLFxuICBTT1VORENMT1VEX1RSQUNLOiAnc291bmRjbG91ZFRyYWNrJyxcbiAgU09VTkRDTE9VRF9QTEFZTElTVDogJ3NvdW5kY2xvdWRQbGF5bGlzdCcsXG4gIFNPVU5EQ0xPVUQ6ICdzb3VuZGNsb3VkJyxcbiAgU1BPVElGWV9TT05HOiAnc3BvdGlmeVNvbmcnLFxuICBTUE9USUZZX0FMQlVNOiAnc3BvdGlmeUFsYnVtJyxcbiAgU1BPVElGWV9QTEFZTElTVDogJ3Nwb3RpZnlQbGF5bGlzdCcsXG4gIFNQT1RJRllfU0VBUkNIOiAnc3BvdGlmeVNlYXJjaCcsXG4gIEZBQ0VCT09LOiAnZmFjZWJvb2snLFxuICBWSU1FTzogJ3ZpbWVvJyxcbiAgQVJCSVRSQVJZOiAnYXJiaXRyYXJ5JyxcbiAgUkVWRVJCTkFUSU9OOiAncmV2ZXJibmF0aW9uJyxcbiAgWU9VVFVCRV9TRUFSQ0g6ICd5b3V0dWJlU2VhcmNoJyxcbiAgWU9VVFVCRV9WSURFTzogJ3lvdXR1YmVWaWRlbycsXG4gIFNPVU5EQ0xPVURfU0VBUkNIOiAnc291bmRjbG91ZFNlYXJjaCcsXG4gIEFQUExFX01VU0lDX1NPTkc6ICdhcHBsZU11c2ljU29uZycsXG4gIEFQUExFX01VU0lDX0FMQlVNOiAnYXBwbGVNdXNpY0FsYnVtJyxcbiAgQVBQTEVfTVVTSUNfUExBWUxJU1Q6ICdhcHBsZU11c2ljUGxheWxpc3QnLFxuICBBUFBMRV9NVVNJQ19TRUFSQ0g6ICdhcHBsZU11c2ljU2VhcmNoJyxcbiAgRklMRTogJ2ZpbGUnLFxuICBBVVRPX1NFQVJDSDogJ2F1dG9TZWFyY2gnLFxuICBESVNDT1JEX1BMQVlFUl9CTE9COiAnZGlzY29yZFBsYXllckJsb2InXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBRdWVyeVR5cGUgPSAodHlwZW9mIFF1ZXJ5VHlwZSlba2V5b2YgdHlwZW9mIFF1ZXJ5VHlwZV07XG5cbmV4cG9ydCB0eXBlIFNlYXJjaFF1ZXJ5VHlwZSA9IGtleW9mIHR5cGVvZiBRdWVyeVR5cGUgfCBRdWVyeVR5cGU7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZWRRdWVyeSB7XG4gIHR5cGU6ICh0eXBlb2YgUXVlcnlUeXBlKVtrZXlvZiB0eXBlb2YgUXVlcnlUeXBlXTtcbiAgcXVlcnk6IHN0cmluZztcbn1cblxuY2xhc3MgUXVlcnlSZXNvbHZlciB7XG4gIC8qKlxuICAgKiBRdWVyeSByZXNvbHZlclxuICAgKi9cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG5cbiAgc3RhdGljIGdldCByZWdleCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3BvdGlmeUFsYnVtUmVnZXgsXG4gICAgICBzcG90aWZ5UGxheWxpc3RSZWdleCxcbiAgICAgIHNwb3RpZnlTb25nUmVnZXgsXG4gICAgICB2aW1lb1JlZ2V4LFxuICAgICAgcmV2ZXJibmF0aW9uUmVnZXgsXG4gICAgICBhdHRhY2htZW50UmVnZXgsXG4gICAgICBhcHBsZU11c2ljQWxidW1SZWdleCxcbiAgICAgIGFwcGxlTXVzaWNQbGF5bGlzdFJlZ2V4LFxuICAgICAgYXBwbGVNdXNpY1NvbmdSZWdleCxcbiAgICAgIHNvdW5kY2xvdWRUcmFja1JlZ2V4LFxuICAgICAgc291bmRjbG91ZFBsYXlsaXN0UmVnZXgsXG4gICAgICB5b3V0dWJlUGxheWxpc3RSZWdleCxcbiAgICAgIGRpc2NvcmRQbGF5ZXJCbG9iUmVnZXhcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFByZS1yZXNvbHZlIHJlZGlyZWN0IHVybHNcbiAgICovXG4gIHN0YXRpYyBhc3luYyBwcmVSZXNvbHZlKHF1ZXJ5OiBzdHJpbmcsIG1heERlcHRoID0gNSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgaWYgKCFUeXBlVXRpbC5pc1N0cmluZyhxdWVyeSkpXG4gICAgdGhyb3cgbmV3IEludmFsaWRBcmdUeXBlRXJyb3IocXVlcnksICdzdHJpbmcnLCB0eXBlb2YgcXVlcnkpO1xuXG4gICAgZm9yIChjb25zdCBkb21haW4gb2YgcmVkaXJlY3REb21haW5zKSB7XG4gICAgICBpZiAoZG9tYWluLnRlc3QocXVlcnkpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2gocXVlcnksIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgICAgICByZWRpcmVjdDogJ2ZvbGxvdydcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGlmICghcmVzLm9rKSBicmVhaztcblxuICAgICAgICAgIC8vIHNwb3RpZnkgZG9lcyBub3QgXCJyZWRpcmVjdFwiLCBpdCByZXR1cm5zIGEgcGFnZSB3aXRoIGpzIHRoYXQgcmVkaXJlY3RzXG4gICAgICAgICAgaWYgKC9eaHR0cHM/OlxcL1xcL3Nwb3RpZnkuYXBwLmxpbmtcXC8oLispJC8udGVzdChyZXMudXJsKSkge1xuICAgICAgICAgICAgY29uc3QgYm9keSA9IGF3YWl0IHJlcy50ZXh0KCk7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBib2R5LlxuICAgICAgICAgICAgc3BsaXQoJ2h0dHBzOi8vb3Blbi5zcG90aWZ5LmNvbS90cmFjay8nKVsxXS5cbiAgICAgICAgICAgIHNwbGl0KCc/c2k9JylbMF07XG5cbiAgICAgICAgICAgIGlmICghdGFyZ2V0KSBicmVhaztcblxuICAgICAgICAgICAgcmV0dXJuIGBodHRwczovL29wZW4uc3BvdGlmeS5jb20vdHJhY2svJHt0YXJnZXR9YDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG1heERlcHRoIDwgMSA/XG4gICAgICAgICAgcmVzLnVybCA6XG4gICAgICAgICAgdGhpcy5wcmVSZXNvbHZlKHJlcy51cmwsIG1heERlcHRoIC0gMSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSBnaXZlbiBzZWFyY2ggcXVlcnlcbiAgICogQHBhcmFtIHtzdHJpbmd9IHF1ZXJ5IFRoZSBxdWVyeVxuICAgKi9cbiAgc3RhdGljIHJlc29sdmUoXG4gIHF1ZXJ5OiBzdHJpbmcsXG4gIGZhbGxiYWNrU2VhcmNoRW5naW5lOiAodHlwZW9mIFF1ZXJ5VHlwZSlba2V5b2YgdHlwZW9mIFF1ZXJ5VHlwZV0gPSBRdWVyeVR5cGUuQVVUT19TRUFSQ0gpXG4gIDogUmVzb2x2ZWRRdWVyeSB7XG4gICAgaWYgKCFUeXBlVXRpbC5pc1N0cmluZyhxdWVyeSkpXG4gICAgdGhyb3cgbmV3IEludmFsaWRBcmdUeXBlRXJyb3IocXVlcnksICdzdHJpbmcnLCB0eXBlb2YgcXVlcnkpO1xuICAgIGlmICghcXVlcnkubGVuZ3RoKSB0aHJvdyBuZXcgSW5mb1JlcXVpcmVkRXJyb3IoJ3F1ZXJ5JywgU3RyaW5nKHF1ZXJ5KSk7XG5cbiAgICBjb25zdCByZXNvbHZlciA9ICh0eXBlOiB0eXBlb2YgZmFsbGJhY2tTZWFyY2hFbmdpbmUsIHF1ZXJ5OiBzdHJpbmcpID0+ICh7XG4gICAgICB0eXBlLFxuICAgICAgcXVlcnlcbiAgICB9KTtcblxuICAgIGlmIChkaXNjb3JkUGxheWVyQmxvYlJlZ2V4LnRlc3QocXVlcnkpKVxuICAgIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuRElTQ09SRF9QTEFZRVJfQkxPQiwgcXVlcnkpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocXVlcnkpO1xuXG4gICAgICBpZiAoRG9tYWluc01hcC5Zb3VUdWJlLmluY2x1ZGVzKHVybC5ob3N0KSkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LnJlcGxhY2UoLyhtKHVzaWMpP3xnYW1pbmcpXFwuLywgJycpLnRyaW0oKTtcbiAgICAgICAgY29uc3QgcGxheWxpc3RJZCA9IHVybC5zZWFyY2hQYXJhbXMuZ2V0KCdsaXN0Jyk7XG4gICAgICAgIGlmIChwbGF5bGlzdElkKVxuICAgICAgICByZXR1cm4gcmVzb2x2ZXIoXG4gICAgICAgICAgUXVlcnlUeXBlLllPVVRVQkVfUExBWUxJU1QsXG4gICAgICAgICAgYGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tLyR7XG4gICAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5zaXplID09PSAxID8gJ3BsYXlsaXN0JyA6ICd3YXRjaCd9JHtcbiAgICAgICAgICB1cmwuc2VhcmNofWBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKFF1ZXJ5UmVzb2x2ZXIudmFsaWRhdGVJZChxdWVyeSkgfHwgUXVlcnlSZXNvbHZlci52YWxpZGF0ZVVSTChxdWVyeSkpXG4gICAgICAgIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuWU9VVFVCRV9WSURFTywgcXVlcnkpO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZXIoZmFsbGJhY2tTZWFyY2hFbmdpbmUsIHF1ZXJ5KTtcbiAgICAgIH0gZWxzZSBpZiAoRG9tYWluc01hcC5TcG90aWZ5LmluY2x1ZGVzKHVybC5ob3N0KSkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LnJlcGxhY2UoL2ludGwtKFthLXpBLVpdKylcXC8vLCAnJyk7XG4gICAgICAgIGlmIChzcG90aWZ5UGxheWxpc3RSZWdleC50ZXN0KHF1ZXJ5KSlcbiAgICAgICAgcmV0dXJuIHJlc29sdmVyKFF1ZXJ5VHlwZS5TUE9USUZZX1BMQVlMSVNULCBxdWVyeSk7XG4gICAgICAgIGlmIChzcG90aWZ5QWxidW1SZWdleC50ZXN0KHF1ZXJ5KSlcbiAgICAgICAgcmV0dXJuIHJlc29sdmVyKFF1ZXJ5VHlwZS5TUE9USUZZX0FMQlVNLCBxdWVyeSk7XG4gICAgICAgIGlmIChzcG90aWZ5U29uZ1JlZ2V4LnRlc3QocXVlcnkpKVxuICAgICAgICByZXR1cm4gcmVzb2x2ZXIoUXVlcnlUeXBlLlNQT1RJRllfU09ORywgcXVlcnkpO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZXIoZmFsbGJhY2tTZWFyY2hFbmdpbmUsIHF1ZXJ5KTtcbiAgICAgIH0gZWxzZSBpZiAoRG9tYWluc01hcC5WaW1lby5pbmNsdWRlcyh1cmwuaG9zdCkpIHtcbiAgICAgICAgaWYgKHZpbWVvUmVnZXgudGVzdChxdWVyeSkpIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuVklNRU8sIHF1ZXJ5KTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVyKGZhbGxiYWNrU2VhcmNoRW5naW5lLCBxdWVyeSk7XG4gICAgICB9IGVsc2UgaWYgKERvbWFpbnNNYXAuUmV2ZXJiTmF0aW9uLmluY2x1ZGVzKHVybC5ob3N0KSkge1xuICAgICAgICBpZiAocmV2ZXJibmF0aW9uUmVnZXgudGVzdChxdWVyeSkpXG4gICAgICAgIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuUkVWRVJCTkFUSU9OLCBxdWVyeSk7XG4gICAgICAgIHJldHVybiByZXNvbHZlcihmYWxsYmFja1NlYXJjaEVuZ2luZSwgcXVlcnkpO1xuICAgICAgfSBlbHNlIGlmIChEb21haW5zTWFwLlNvdW5kQ2xvdWQuaW5jbHVkZXModXJsLmhvc3QpKSB7XG4gICAgICAgIGlmIChzb3VuZGNsb3VkUGxheWxpc3RSZWdleC50ZXN0KHF1ZXJ5KSlcbiAgICAgICAgcmV0dXJuIHJlc29sdmVyKFF1ZXJ5VHlwZS5TT1VORENMT1VEX1BMQVlMSVNULCBxdWVyeSk7XG4gICAgICAgIGlmIChzb3VuZGNsb3VkVHJhY2tSZWdleC50ZXN0KHF1ZXJ5KSlcbiAgICAgICAgcmV0dXJuIHJlc29sdmVyKFF1ZXJ5VHlwZS5TT1VORENMT1VEX1RSQUNLLCBxdWVyeSk7XG4gICAgICAgIHJldHVybiByZXNvbHZlcihmYWxsYmFja1NlYXJjaEVuZ2luZSwgcXVlcnkpO1xuICAgICAgfSBlbHNlIGlmIChEb21haW5zTWFwLkFwcGxlTXVzaWMuaW5jbHVkZXModXJsLmhvc3QpKSB7XG4gICAgICAgIGlmIChhcHBsZU11c2ljQWxidW1SZWdleC50ZXN0KHF1ZXJ5KSlcbiAgICAgICAgcmV0dXJuIHJlc29sdmVyKFF1ZXJ5VHlwZS5BUFBMRV9NVVNJQ19BTEJVTSwgcXVlcnkpO1xuICAgICAgICBpZiAoYXBwbGVNdXNpY1BsYXlsaXN0UmVnZXgudGVzdChxdWVyeSkpXG4gICAgICAgIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuQVBQTEVfTVVTSUNfUExBWUxJU1QsIHF1ZXJ5KTtcbiAgICAgICAgaWYgKGFwcGxlTXVzaWNTb25nUmVnZXgudGVzdChxdWVyeSkpXG4gICAgICAgIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuQVBQTEVfTVVTSUNfU09ORywgcXVlcnkpO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZXIoZmFsbGJhY2tTZWFyY2hFbmdpbmUsIHF1ZXJ5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlcihRdWVyeVR5cGUuQVJCSVRSQVJZLCBxdWVyeSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gcmVzb2x2ZXIoZmFsbGJhY2tTZWFyY2hFbmdpbmUsIHF1ZXJ5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHZpbWVvIGlkIGZyb20gdXJsXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBxdWVyeSBUaGUgcXVlcnlcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBnZXRWaW1lb0lEKHF1ZXJ5OiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gUXVlcnlSZXNvbHZlci5yZXNvbHZlKHF1ZXJ5KS50eXBlID09PSBRdWVyeVR5cGUuVklNRU8gP1xuICAgIHF1ZXJ5LnNwbGl0KCcvJykuZmlsdGVyKEJvb2xlYW4pLnBvcCgpIDpcbiAgICBudWxsO1xuICB9XG5cbiAgc3RhdGljIHZhbGlkYXRlSWQocTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHlvdXR1YmVWaWRlb0lkUmVnZXgudGVzdChxKTtcbiAgfVxuXG4gIHN0YXRpYyB2YWxpZGF0ZVVSTChxOiBzdHJpbmcpIHtcbiAgICByZXR1cm4geW91dHViZVZpZGVvVVJMUmVnZXgudGVzdChxKTtcbiAgfVxufVxuXG5leHBvcnQgeyBRdWVyeVJlc29sdmVyIH07IiwgImltcG9ydCB7IFVzZXIsIFVzZXJSZXNvbHZhYmxlIH0gZnJvbSAnZGlzY29yZC5qcyc7XG5pbXBvcnQgeyBCYXNlRXh0cmFjdG9yIH0gZnJvbSAnLi4vZXh0cmFjdG9ycy9CYXNlRXh0cmFjdG9yJztcbmltcG9ydCB7IFBsYXllciB9IGZyb20gJy4uL1BsYXllcic7XG5pbXBvcnQgeyBQbGF5bGlzdCB9IGZyb20gJy4vUGxheWxpc3QnO1xuaW1wb3J0IHsgVHJhY2sgfSBmcm9tICcuL1RyYWNrJztcbmltcG9ydCB7IFF1ZXJ5VHlwZSwgU2VhcmNoUXVlcnlUeXBlIH0gZnJvbSAnLi4vdXRpbHMvUXVlcnlSZXNvbHZlcic7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnaHR0cCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VhcmNoUmVzdWx0RGF0YSB7XG4gIHF1ZXJ5OiBzdHJpbmc7XG4gIHF1ZXJ5VHlwZT86IFNlYXJjaFF1ZXJ5VHlwZSB8IFF1ZXJ5RXh0cmFjdG9yU2VhcmNoIHwgbnVsbDtcbiAgZXh0cmFjdG9yPzogQmFzZUV4dHJhY3RvciB8IG51bGw7XG4gIHBsYXlsaXN0PzogUGxheWxpc3QgfCBudWxsO1xuICB0cmFja3M/OiBUcmFja1tdO1xuICByZXF1ZXN0ZWRCeT86IFVzZXIgfCBudWxsO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBsYXlPcHRpb25zIHtcbiAgLyoqXG4gICAqIElmIHRoaXMgcGxheSB3YXMgdHJpZ2dlcmVkIGZvciBmaWx0ZXJzIHVwZGF0ZVxuICAgKi9cbiAgZmlsdGVyc1VwZGF0ZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBGRm1wZWcgYXJncyBwYXNzZWQgdG8gZW5jb2RlclxuICAgKi9cbiAgZW5jb2RlckFyZ3M/OiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIFRpbWUgdG8gc2VlayB0byBiZWZvcmUgcGxheWluZ1xuICAgKi9cbiAgc2Vlaz86IG51bWJlcjtcbiAgLyoqXG4gICAqIElmIGl0IHNob3VsZCBzdGFydCBwbGF5aW5nIHRoZSBwcm92aWRlZCB0cmFjayBpbW1lZGlhdGVseVxuICAgKi9cbiAgaW1tZWRpYXRlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IHR5cGUgUXVlcnlFeHRyYWN0b3JTZWFyY2ggPSBgZXh0OiR7c3RyaW5nfWA7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VhcmNoT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgdXNlciB3aG8gcmVxdWVzdGVkIHRoaXMgc2VhcmNoXG4gICAqL1xuICByZXF1ZXN0ZWRCeT86IFVzZXJSZXNvbHZhYmxlO1xuICAvKipcbiAgICogVGhlIHF1ZXJ5IHNlYXJjaCBlbmdpbmUsIGNhbiBiZSBleHRyYWN0b3IgbmFtZSB0byB0YXJnZXQgc3BlY2lmaWMgb25lIChjdXN0b20pXG4gICAqL1xuICBzZWFyY2hFbmdpbmU/OiBTZWFyY2hRdWVyeVR5cGUgfCBRdWVyeUV4dHJhY3RvclNlYXJjaDtcbiAgLyoqXG4gICAqIExpc3Qgb2YgdGhlIGV4dHJhY3RvcnMgdG8gYmxvY2tcbiAgICovXG4gIGJsb2NrRXh0cmFjdG9ycz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogSWYgaXQgc2hvdWxkIGlnbm9yZSBxdWVyeSBjYWNoZSBsb29rdXBcbiAgICovXG4gIGlnbm9yZUNhY2hlPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFJlcXVlc3Qgb3B0aW9ucyB0byBiZSBwYXNzZWQgd2l0aCB0aGUgaHR0cCByZXF1ZXN0XG4gICAqL1xuICByZXF1ZXN0T3B0aW9ucz86IFJlcXVlc3RPcHRpb25zO1xuICAvKipcbiAgICogRmFsbGJhY2sgc2VhcmNoIGVuZ2luZSB0byB1c2VcbiAgICovXG4gIGZhbGxiYWNrU2VhcmNoRW5naW5lPzogKHR5cGVvZiBRdWVyeVR5cGUpW2tleW9mIHR5cGVvZiBRdWVyeVR5cGVdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBsYXllclNlYXJjaFJlc3VsdCB7XG4gIHBsYXlsaXN0OiBQbGF5bGlzdCB8IG51bGw7XG4gIHRyYWNrczogVHJhY2tbXTtcbn1cblxuZXhwb3J0IGNsYXNzIFNlYXJjaFJlc3VsdCB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcGxheWVyOiBQbGF5ZXIsIHByaXZhdGUgX2RhdGE6IFNlYXJjaFJlc3VsdERhdGEpIHtcbiAgICB0aGlzLl9kYXRhLnRyYWNrcz8uZm9yRWFjaCgodHJhY2spID0+IHtcbiAgICAgIHRyYWNrLmV4dHJhY3RvciA/Pz0gdGhpcy5fZGF0YS5leHRyYWN0b3IgfHwgbnVsbDtcbiAgICAgIHRyYWNrLnJlcXVlc3RlZEJ5ID8/PSBfZGF0YS5yZXF1ZXN0ZWRCeSB8fCBudWxsO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHNldFF1ZXJ5VHlwZSh0eXBlOiBTZWFyY2hRdWVyeVR5cGUgfCBRdWVyeUV4dHJhY3RvclNlYXJjaCkge1xuICAgIHRoaXMuX2RhdGEucXVlcnlUeXBlID0gdHlwZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBzZXRSZXF1ZXN0ZWRCeSh1c2VyOiBVc2VyKSB7XG4gICAgdGhpcy5fZGF0YS5yZXF1ZXN0ZWRCeSA9IHVzZXI7XG4gICAgdGhpcy5fZGF0YS50cmFja3M/LmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICB0cmFjay5yZXF1ZXN0ZWRCeSA9IHVzZXI7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgc2V0RXh0cmFjdG9yKGV4dHJhY3RvcjogQmFzZUV4dHJhY3Rvcikge1xuICAgIHRoaXMuX2RhdGEuZXh0cmFjdG9yID0gZXh0cmFjdG9yO1xuICAgIHRoaXMuX2RhdGEudHJhY2tzPy5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgdHJhY2suZXh0cmFjdG9yID0gZXh0cmFjdG9yO1xuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIHNldFRyYWNrcyh0cmFja3M6IFRyYWNrW10pIHtcbiAgICB0aGlzLl9kYXRhLnRyYWNrcyA9IHRyYWNrcztcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBzZXRRdWVyeShxdWVyeTogc3RyaW5nKSB7XG4gICAgdGhpcy5fZGF0YS5xdWVyeSA9IHF1ZXJ5O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIHNldFBsYXlsaXN0KHBsYXlsaXN0OiBQbGF5bGlzdCkge1xuICAgIHRoaXMuX2RhdGEucGxheWxpc3QgPSBwbGF5bGlzdDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgc2VhcmNoIHF1ZXJ5XG4gICAqL1xuICBwdWJsaWMgZ2V0IHF1ZXJ5KCkge1xuICAgIHJldHVybiB0aGlzLl9kYXRhLnF1ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzZWFyY2ggcXVlcnkgdHlwZVxuICAgKi9cbiAgcHVibGljIGdldCBxdWVyeVR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2RhdGEucXVlcnlUeXBlIHx8IFF1ZXJ5VHlwZS5BVVRPO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBleHRyYWN0b3JcbiAgICovXG4gIHB1YmxpYyBnZXQgZXh0cmFjdG9yKCkge1xuICAgIHJldHVybiB0aGlzLl9kYXRhLmV4dHJhY3RvciB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFBsYXlsaXN0IHJlc3VsdFxuICAgKi9cbiAgcHVibGljIGdldCBwbGF5bGlzdCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YS5wbGF5bGlzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgcmVzdWx0XG4gICAqL1xuICBwdWJsaWMgZ2V0IHRyYWNrcygpIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0YS50cmFja3MgfHwgW107XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdGVkIGJ5XG4gICAqL1xuICBwdWJsaWMgZ2V0IHJlcXVlc3RlZEJ5KCkge1xuICAgIHJldHVybiB0aGlzLl9kYXRhLnJlcXVlc3RlZEJ5IHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmUtZXhlY3V0ZSB0aGlzIHNlYXJjaFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGV4ZWN1dGUoKSB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVyLnNlYXJjaCh0aGlzLnF1ZXJ5LCB7XG4gICAgICBzZWFyY2hFbmdpbmU6IHRoaXMucXVlcnlUeXBlLFxuICAgICAgcmVxdWVzdGVkQnk6IHRoaXMucmVxdWVzdGVkQnkhXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhpcyBzZWFyY2ggcmVzdWx0IGlzIGVtcHR5XG4gICAqL1xuICBwdWJsaWMgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gIXRoaXMudHJhY2tzLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGlzIHNlYXJjaCByZXN1bHQgaGFzIHBsYXlsaXN0XG4gICAqL1xuICBwdWJsaWMgaGFzUGxheWxpc3QoKSB7XG4gICAgcmV0dXJuIHRoaXMucGxheWxpc3QgIT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiB0aGlzIHNlYXJjaCByZXN1bHQgaGFzIHRyYWNrc1xuICAgKi9cbiAgcHVibGljIGhhc1RyYWNrcygpIHtcbiAgICByZXR1cm4gdGhpcy50cmFja3MubGVuZ3RoID4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBKU09OIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgc2VhcmNoXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCkge1xuICAgIHJldHVybiB7XG4gICAgICBxdWVyeTogdGhpcy5xdWVyeSxcbiAgICAgIHF1ZXJ5VHlwZTogdGhpcy5xdWVyeVR5cGUsXG4gICAgICBwbGF5bGlzdDogdGhpcy5wbGF5bGlzdD8udG9KU09OKGZhbHNlKSB8fCBudWxsLFxuICAgICAgdHJhY2tzOiB0aGlzLnRyYWNrcy5tYXAoKG0pID0+IG0udG9KU09OKHRydWUpKSxcbiAgICAgIGV4dHJhY3RvcjogdGhpcy5leHRyYWN0b3I/LmlkZW50aWZpZXIgfHwgbnVsbCxcbiAgICAgIHJlcXVlc3RlZEJ5OiB0aGlzLnJlcXVlc3RlZEJ5Py50b0pTT04oKSB8fCBudWxsXG4gICAgfTtcbiAgfVxufSIsICJleHBvcnQgdHlwZSBGaWx0ZXJzTmFtZSA9IGtleW9mIFF1ZXVlRmlsdGVycztcblxuLyoqXG4gKiBSZXByZXNlbnRzIEZGbXBlZyBmaWx0ZXJzXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVldWVGaWx0ZXJzIHtcbiAgYmFzc2Jvb3N0X2xvdz86IGJvb2xlYW47XG4gIGJhc3Nib29zdD86IGJvb2xlYW47XG4gIGJhc3Nib29zdF9oaWdoPzogYm9vbGVhbjtcbiAgJzhEJz86IGJvb2xlYW47XG4gIHZhcG9yd2F2ZT86IGJvb2xlYW47XG4gIG5pZ2h0Y29yZT86IGJvb2xlYW47XG4gIHBoYXNlcj86IGJvb2xlYW47XG4gIHRyZW1vbG8/OiBib29sZWFuO1xuICB2aWJyYXRvPzogYm9vbGVhbjtcbiAgcmV2ZXJzZT86IGJvb2xlYW47XG4gIHRyZWJsZT86IGJvb2xlYW47XG4gIG5vcm1hbGl6ZXI/OiBib29sZWFuO1xuICBub3JtYWxpemVyMj86IGJvb2xlYW47XG4gIHN1cnJvdW5kaW5nPzogYm9vbGVhbjtcbiAgcHVsc2F0b3I/OiBib29sZWFuO1xuICBzdWJib29zdD86IGJvb2xlYW47XG4gIGthcmFva2U/OiBib29sZWFuO1xuICBmbGFuZ2VyPzogYm9vbGVhbjtcbiAgZ2F0ZT86IGJvb2xlYW47XG4gIGhhYXM/OiBib29sZWFuO1xuICBtY29tcGFuZD86IGJvb2xlYW47XG4gIG1vbm8/OiBib29sZWFuO1xuICBtc3Rscj86IGJvb2xlYW47XG4gIG1zdHJyPzogYm9vbGVhbjtcbiAgY29tcHJlc3Nvcj86IGJvb2xlYW47XG4gIGV4cGFuZGVyPzogYm9vbGVhbjtcbiAgc29mdGxpbWl0ZXI/OiBib29sZWFuO1xuICBjaG9ydXM/OiBib29sZWFuO1xuICBjaG9ydXMyZD86IGJvb2xlYW47XG4gIGNob3J1czNkPzogYm9vbGVhbjtcbiAgZmFkZWluPzogYm9vbGVhbjtcbiAgZGltPzogYm9vbGVhbjtcbiAgZWFycmFwZT86IGJvb2xlYW47XG4gIGxvZmk/OiBib29sZWFuO1xuICBzaWxlbmNlcmVtb3ZlPzogYm9vbGVhbjtcbn1cblxuY29uc3QgYmFzcyA9IChnOiBudW1iZXIpID0+IGBiYXNzPWc9JHtnfTpmPTExMDp3PTAuM2A7XG5cbmV4cG9ydCBjbGFzcyBBdWRpb0ZpbHRlcnMge1xuICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgcmV0dXJuIEF1ZGlvRmlsdGVycztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZmlsdGVyczogUmVjb3JkPEZpbHRlcnNOYW1lLCBzdHJpbmc+ID0ge1xuICAgIGJhc3Nib29zdF9sb3c6IGJhc3MoMTUpLFxuICAgIGJhc3Nib29zdDogYmFzcygyMCksXG4gICAgYmFzc2Jvb3N0X2hpZ2g6IGJhc3MoMzApLFxuICAgICc4RCc6ICdhcHVsc2F0b3I9aHo9MC4wOScsXG4gICAgdmFwb3J3YXZlOiAnYXJlc2FtcGxlPTQ4MDAwLGFzZXRyYXRlPTQ4MDAwKjAuOCcsXG4gICAgbmlnaHRjb3JlOiAnYXJlc2FtcGxlPTQ4MDAwLGFzZXRyYXRlPTQ4MDAwKjEuMjUnLFxuICAgIGxvZmk6ICdhcmVzYW1wbGU9NDgwMDAsYXNldHJhdGU9NDgwMDAqMC45LGV4dHJhc3RlcmVvPW09Mi41OmM9ZGlzYWJsZWQnLFxuICAgIHBoYXNlcjogJ2FwaGFzZXI9aW5fZ2Fpbj0wLjQnLFxuICAgIHRyZW1vbG86ICd0cmVtb2xvJyxcbiAgICB2aWJyYXRvOiAndmlicmF0bz1mPTYuNScsXG4gICAgcmV2ZXJzZTogJ2FyZXZlcnNlJyxcbiAgICB0cmVibGU6ICd0cmVibGU9Zz01JyxcbiAgICBub3JtYWxpemVyMjogJ2R5bmF1ZG5vcm09Zz0xMDEnLFxuICAgIG5vcm1hbGl6ZXI6ICdhY29tcHJlc3NvcicsXG4gICAgc3Vycm91bmRpbmc6ICdzdXJyb3VuZCcsXG4gICAgcHVsc2F0b3I6ICdhcHVsc2F0b3I9aHo9MScsXG4gICAgc3ViYm9vc3Q6ICdhc3ViYm9vc3QnLFxuICAgIGthcmFva2U6ICdzdGVyZW90b29scz1tbGV2PTAuMDMnLFxuICAgIGZsYW5nZXI6ICdmbGFuZ2VyJyxcbiAgICBnYXRlOiAnYWdhdGUnLFxuICAgIGhhYXM6ICdoYWFzJyxcbiAgICBtY29tcGFuZDogJ21jb21wYW5kJyxcbiAgICBtb25vOiAncGFuPW1vbm98YzA9LjUqYzArLjUqYzEnLFxuICAgIG1zdGxyOiAnc3RlcmVvdG9vbHM9bW9kZT1tcz5scicsXG4gICAgbXN0cnI6ICdzdGVyZW90b29scz1tb2RlPW1zPnJyJyxcbiAgICBjb21wcmVzc29yOiAnY29tcGFuZD1wb2ludHM9LTgwLy0xMDV8LTYyLy04MHwtMTUuNC8tMTUuNHwwLy0xMnwyMC8tNy42JyxcbiAgICBleHBhbmRlcjpcbiAgICAnY29tcGFuZD1hdHRhY2tzPTA6cG9pbnRzPS04MC8tMTY5fC01NC8tODB8LTQ5LjUvLTY0LjZ8LTQxLjEvLTQxLjF8LTI1LjgvLTE1fC0xMC44Ly00LjV8MC8wfDIwLzguMycsXG4gICAgc29mdGxpbWl0ZXI6XG4gICAgJ2NvbXBhbmQ9YXR0YWNrcz0wOnBvaW50cz0tODAvLTgwfC0xMi40Ly0xMi40fC02Ly04fDAvLTYuOHwyMC8tMi44JyxcbiAgICBjaG9ydXM6ICdjaG9ydXM9MC43OjAuOTo1NTowLjQ6MC4yNToyJyxcbiAgICBjaG9ydXMyZDogJ2Nob3J1cz0wLjY6MC45OjUwfDYwOjAuNHwwLjMyOjAuMjV8MC40OjJ8MS4zJyxcbiAgICBjaG9ydXMzZDogJ2Nob3J1cz0wLjU6MC45OjUwfDYwfDQwOjAuNHwwLjMyfDAuMzowLjI1fDAuNHwwLjM6MnwyLjN8MS4zJyxcbiAgICBmYWRlaW46ICdhZmFkZT10PWluOnNzPTA6ZD0xMCcsXG4gICAgZGltOiBgYWZmdGZpbHQ9XCIncmVhbD1yZSAqICgxLWNsaXAoKGIvbmIpKmIsMCwxKSknOmltYWc9J2ltICogKDEtY2xpcCgoYi9uYikqYiwwLDEpKSdcImAsXG4gICAgZWFycmFwZTogJ2NoYW5uZWxzcGxpdCxzaWRlY2hhaW5nYXRlPWxldmVsX2luPTY0JyxcbiAgICBzaWxlbmNlcmVtb3ZlOiAnc2lsZW5jZXJlbW92ZT0xOjA6LTUwZEInXG4gIH07XG5cbiAgcHVibGljIHN0YXRpYyBnZXQ8SyBleHRlbmRzIEZpbHRlcnNOYW1lPihuYW1lOiBLKSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyc1tuYW1lXSA/PyBuYW1lO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBoYXM8SyBleHRlbmRzIEZpbHRlcnNOYW1lPihuYW1lOiBLKSB7XG4gICAgcmV0dXJuIG5hbWUgaW4gdGhpcy5maWx0ZXJzO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyAqW1N5bWJvbC5pdGVyYXRvcl0oKTogSXRlcmFibGVJdGVyYXRvcjx7XG4gICAgbmFtZTogRmlsdGVyc05hbWU7XG4gICAgdmFsdWU6IHN0cmluZztcbiAgfT4ge1xuICAgIGZvciAoY29uc3QgW2ssIHZdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMuZmlsdGVycykpIHtcbiAgICAgIHlpZWxkIHsgbmFtZTogayBhcyBGaWx0ZXJzTmFtZSwgdmFsdWU6IHYgYXMgc3RyaW5nIH07XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZXQgbmFtZXMoKSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuZmlsdGVycykgYXMgRmlsdGVyc05hbWVbXTtcbiAgfVxuXG4gIC8vIEB0cy1pZ25vcmVcbiAgcHVibGljIHN0YXRpYyBnZXQgbGVuZ3RoKCkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmxlbmd0aDtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMubWFwKChtKSA9PiAodGhpcyBhcyBhbnkpW21dKS5qb2luKCcsJyk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBmZm1wZWcgYXJncyBmcm9tIHRoZSBzcGVjaWZpZWQgZmlsdGVycyBuYW1lXG4gICAqIEBwYXJhbSBmaWx0ZXIgVGhlIGZpbHRlciBuYW1lXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNyZWF0ZTxLIGV4dGVuZHMgRmlsdGVyc05hbWU+KGZpbHRlcnM/OiAoSyB8IHN0cmluZylbXSkge1xuICAgIGlmICghZmlsdGVycyB8fCAhQXJyYXkuaXNBcnJheShmaWx0ZXJzKSkgcmV0dXJuIHRoaXMudG9TdHJpbmcoKTtcbiAgICByZXR1cm4gZmlsdGVycy5cbiAgICBmaWx0ZXIoKHByZWRpY2F0ZSkgPT4gdHlwZW9mIHByZWRpY2F0ZSA9PT0gJ3N0cmluZycpLlxuICAgIG1hcCgobSkgPT4gdGhpcy5nZXQobSBhcyBLKSkuXG4gICAgam9pbignLCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlZmluZXMgYXVkaW8gZmlsdGVyXG4gICAqIEBwYXJhbSBmaWx0ZXJOYW1lIFRoZSBuYW1lIG9mIHRoZSBmaWx0ZXJcbiAgICogQHBhcmFtIHZhbHVlIFRoZSBmZm1wZWcgYXJnc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBkZWZpbmUoZmlsdGVyTmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5maWx0ZXJzW2ZpbHRlck5hbWUgYXMgRmlsdGVyc05hbWVdID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lcyBtdWx0aXBsZSBhdWRpbyBmaWx0ZXJzXG4gICAqIEBwYXJhbSBmaWx0ZXJzQXJyYXkgQXJyYXkgb2YgZmlsdGVycyBjb250YWluaW5nIHRoZSBmaWx0ZXIgbmFtZSBhbmQgZmZtcGVnIGFyZ3NcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZGVmaW5lQnVsayhmaWx0ZXJzQXJyYXk6IHtuYW1lOiBzdHJpbmc7dmFsdWU6IHN0cmluZzt9W10pIHtcbiAgICBmaWx0ZXJzQXJyYXkuZm9yRWFjaCgoYXJyKSA9PiB0aGlzLmRlZmluZShhcnIubmFtZSwgYXJyLnZhbHVlKSk7XG4gIH1cbn0iLCAiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuLy8gQHRzLW5vY2hlY2tcblxuaW1wb3J0IHsgQ2hhbm5lbFR5cGUsIEdhdGV3YXlEaXNwYXRjaEV2ZW50cyB9IGZyb20gJ2Rpc2NvcmQtYXBpLXR5cGVzL3YxMCc7XG5pbXBvcnQgeyBjcmVhdGVDb21wYXRDbGllbnQgfSBmcm9tICcuL2NvbW1vbic7XG5pbXBvcnQgeyBVdGlsIH0gZnJvbSAnLi4vdXRpbHMvVXRpbCc7XG5cbmltcG9ydCB0eXBlIHsgRGlzY29yZEdhdGV3YXlBZGFwdGVyQ3JlYXRvciB9IGZyb20gJ2Rpc2NvcmQtdm9pcCc7XG5pbXBvcnQge1xuICBDbGllbnQsXG4gIEdhdGV3YXlWb2ljZVNlcnZlclVwZGF0ZURpc3BhdGNoRGF0YSxcbiAgR2F0ZXdheVZvaWNlU3RhdGVVcGRhdGVEaXNwYXRjaERhdGEsXG4gIFZvaWNlU3RhdGUgfSBmcm9tXG4nZGlzY29yZC5qcyc7XG5pbXBvcnQgdHlwZSBPY2VhbmljIGZyb20gJ29jZWFuaWMuanMnO1xuXG50eXBlIE9jZWFuaWNVc2VyUmVzb2x2YWJsZSA9IE9jZWFuaWMuVXNlciB8IHN0cmluZyB8IE9jZWFuaWMuTWVtYmVyO1xudHlwZSBPY2VhbmljR3VpbGRSZXNvbHZhYmxlID1cbk9jZWFuaWMuR3VpbGQgfFxuc3RyaW5nIHxcbk9jZWFuaWMuTWVtYmVyIHxcbk9jZWFuaWMuR3VpbGRDaGFubmVsIHxcbk9jZWFuaWMuUm9sZTtcbnR5cGUgT2NlYW5pY0NoYW5uZWxSZXNvbHZhYmxlID0gT2NlYW5pYy5HdWlsZENoYW5uZWwgfCBzdHJpbmc7XG5cbmNvbnN0IERpc2NvcmRQbGF5ZXJDbGllbnRTeW1ib2wgPSBTeW1ib2woJ0Rpc2NvcmRQbGF5ZXJDbGllbnQnKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGlzT2NlYW5pY0NsaWVudChjbGllbnQ6IGFueSk6IGNsaWVudCBpcyBPY2VhbmljLkNsaWVudCB7XG4gIGNvbnN0IHsgbW9kdWxlLCBlcnJvciB9ID0gVXRpbC5yZXF1aXJlKCdvY2VhbmljLmpzJyk7XG5cbiAgaWYgKGVycm9yKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3Qgb2NlYW5pYyA9IG1vZHVsZSBhcyB0eXBlb2YgaW1wb3J0KCdvY2VhbmljLmpzJyk7XG5cbiAgcmV0dXJuIGNsaWVudCBpbnN0YW5jZW9mIG9jZWFuaWMuQ2xpZW50O1xufVxuXG5mdW5jdGlvbiBkZWNsYXJlUHJvcGVydHkodGFyZ2V0OiBhbnksIGtleTogc3RyaW5nLCB2YWx1ZTogYW55KTogVCB7XG4gIFJlZmxlY3Quc2V0KHRhcmdldCwga2V5LCB2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGdldFByb3BlcnR5PFQ+KHRhcmdldDogYW55LCBrZXk6IHN0cmluZyk6IFQge1xuICByZXR1cm4gUmVmbGVjdC5nZXQodGFyZ2V0LCBrZXkpO1xufVxuXG4vKipcbiAqIEFsbG93cyBPY2VhbmljLmpzIGNsaWVudHMgdG8gYmUgdXNlZCB3aXRoIGRpc2NvcmQtcGxheWVyLiBXaGVuIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCwgZGlzY29yZC1wbGF5ZXIgY3JlYXRlcyBhIHByb3h5IG9iamVjdCB0aGF0IGludGVyY2VwdHMgY2VydGFpbiBtZXRob2RzIGFuZCBwcm9wZXJ0aWVzIHRvIG1ha2UgaXQgY29tcGF0aWJsZSB3aXRoIGRpc2NvcmQtcGxheWVyLlxuICogQHBhcmFtIGNsaWVudCBUaGUgT2NlYW5pYy5qcyBjbGllbnQgdG8gYmUgdXNlZC5cbiAqIEByZXR1cm5zIFRoZSBPY2VhbmljLmpzIGNsaWVudCB3aXRoIGRpc2NvcmQtcGxheWVyIGNvbXBhdGliaWxpdHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPY2VhbmljQ29tcGF0KGNsaWVudDogT2NlYW5pYy5DbGllbnQpOiBDbGllbnQge1xuICBjb25zdCB7IG1vZHVsZSwgZXJyb3IgfSA9IFV0aWwucmVxdWlyZSgnb2NlYW5pYy5qcycpO1xuXG4gIGlmIChlcnJvcikgdGhyb3cgZXJyb3I7XG5cbiAgY29uc3Qgb2NlYW5pYyA9IG1vZHVsZSBhcyB0eXBlb2YgaW1wb3J0KCdvY2VhbmljLmpzJyk7XG5cbiAgb2NlYW5pY1ZvaWNlRXZlbnRzSGFuZGxlcihjbGllbnQpO1xuXG4gIGNvbnN0IG9jZWFuaWNQcm94eSA9IG5ldyBQcm94eShjbGllbnQsIHtcbiAgICBnZXQodGFyZ2V0LCBwKSB7XG4gICAgICBzd2l0Y2ggKHApIHtcbiAgICAgICAgY2FzZSAndXNlcnMnOlxuICAgICAgICAgIHJldHVybiBvY2VhbmljVXNlcnNQcm94eSh0YXJnZXQsIG9jZWFuaWMpO1xuICAgICAgICBjYXNlICdndWlsZHMnOlxuICAgICAgICAgIHJldHVybiBvY2VhbmljR3VpbGRzUHJveHkodGFyZ2V0LCBvY2VhbmljKTtcbiAgICAgICAgY2FzZSAnY2hhbm5lbHMnOlxuICAgICAgICAgIHJldHVybiBvY2VhbmljQ2hhbm5lbHNQcm94eSh0YXJnZXQsIG9jZWFuaWMpO1xuICAgICAgICBjYXNlICdfX2RwX3ZvaWNlU3RhdGVVcGRhdGVfcHJveHknOlxuICAgICAgICAgIHJldHVybiAoaGFuZGxlcjogKGEsIGIpID0+IHZvaWQpID0+XG4gICAgICAgICAgb2NlYW5pY1ZvaWNlU3RhdGVVcGRhdGVQcm94eSh0YXJnZXQsIG9jZWFuaWNQcm94eSwgaGFuZGxlcik7XG4gICAgICAgIGNhc2UgJ2luY3JlbWVudE1heExpc3RlbmVycyc6XG4gICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgICAgICAgIGNsaWVudC5zZXRNYXhMaXN0ZW5lcnMoY2xpZW50LmdldE1heExpc3RlbmVycygpICsgMSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgY2FzZSAnZGVjcmVtZW50TWF4TGlzdGVuZXJzJzpcbiAgICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBwYXRjaGluZ1xuICAgICAgICAgICAgY29uc3QgbGlzdGVuZXJzID0gY2xpZW50LmdldE1heExpc3RlbmVycygpIC0gMTtcblxuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBwYXRjaGluZ1xuICAgICAgICAgICAgY2xpZW50LnNldE1heExpc3RlbmVycyhsaXN0ZW5lcnMgPCAwID8gMSA6IGxpc3RlbmVycyk7XG4gICAgICAgICAgfTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHBhdGNoaW5nXG4gICAgICAgICAgcmV0dXJuIHRhcmdldFtwXTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIFJlZmxlY3Quc2V0KG9jZWFuaWNQcm94eSwgRGlzY29yZFBsYXllckNsaWVudFN5bWJvbCwgJ09jZWFuaWMnKTtcblxuICByZXR1cm4gY3JlYXRlQ29tcGF0Q2xpZW50KG9jZWFuaWNQcm94eSwgJ09jZWFuaWMnKS5cbiAgY2xpZW50IGFzIHVua25vd24gYXMgQ2xpZW50O1xufVxuXG5mdW5jdGlvbiBvY2VhbmljVm9pY2VTdGF0ZVVwZGF0ZVByb3h5KFxuY2xpZW50OiBPY2VhbmljLkNsaWVudCxcbnByb3h5OiBPY2VhbmljLkNsaWVudCxcbmhhbmRsZXI6IChhLCBiKSA9PiB2b2lkKVxue1xuICBjbGllbnQub24oJ3ZvaWNlU3RhdGVVcGRhdGUnLCAobWVtYmVyLCBvbGRTdGF0ZSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwcm94aWVkT2xkU3RhdGUgPSB7XG4gICAgICAgIGNoYW5uZWxJZDogb2xkU3RhdGUuY2hhbm5lbElELFxuICAgICAgICBzZXJ2ZXJNdXRlOiBvbGRTdGF0ZS5tdXRlLFxuICAgICAgICBzdXBwcmVzczogb2xkU3RhdGUuc3VwcHJlc3MsXG4gICAgICAgIGd1aWxkOiB7XG4gICAgICAgICAgaWQ6IG9sZFN0YXRlLmd1aWxkLmlkXG4gICAgICAgIH0sXG4gICAgICAgIG1lbWJlcjoge1xuICAgICAgICAgIGlkOiBvbGRTdGF0ZS51c2VyLmlkXG4gICAgICAgIH1cbiAgICAgIH0gYXMgVm9pY2VTdGF0ZTtcblxuICAgICAgY29uc3QgbWUgPSBtZW1iZXIuZ3VpbGQubWVtYmVycy5nZXQoY2xpZW50LnVzZXIuaWQpO1xuICAgICAgY29uc3QgcmVzb2x2ZWRDaGFubmVsID0gbWVtYmVyLmd1aWxkLmNoYW5uZWxzLmdldChcbiAgICAgICAgbWVtYmVyLnZvaWNlU3RhdGUuY2hhbm5lbElEXG4gICAgICApO1xuXG4gICAgICBjb25zdCBwcm94aWVkTmV3U3RhdGUgPSB7XG4gICAgICAgIGNoYW5uZWxJZDogbWVtYmVyLnZvaWNlU3RhdGUuY2hhbm5lbElELFxuICAgICAgICBzZXJ2ZXJNdXRlOiBtZW1iZXIudm9pY2VTdGF0ZS5tdXRlLFxuICAgICAgICBzdXBwcmVzczogbWVtYmVyLnZvaWNlU3RhdGUuc3VwcHJlc3MsXG4gICAgICAgIGNoYW5uZWw6IG9jZWFuaWNSZXNvbHZlZENoYW5uZWxQcm94eShyZXNvbHZlZENoYW5uZWwsIGNsaWVudCksXG4gICAgICAgIG1lbWJlcjoge1xuICAgICAgICAgIGlkOiBtZW1iZXIuaWRcbiAgICAgICAgfSxcbiAgICAgICAgZ3VpbGQ6IHtcbiAgICAgICAgICBpZDogbWVtYmVyLmd1aWxkLmlkLFxuICAgICAgICAgIG1lbWJlcnM6IHtcbiAgICAgICAgICAgIG1lOiB7XG4gICAgICAgICAgICAgIGlkOiBtZT8uaWQsXG4gICAgICAgICAgICAgIHZvaWNlOiB7XG4gICAgICAgICAgICAgICAgYXN5bmMgc2V0UmVxdWVzdFRvU3BlYWsodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgICAgICAgICAgIHZvaWQgdmFsdWU7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gbWU/LnZvaWNlU3RhdGU7XG4gICAgICAgICAgICAgICAgICAvLyBpZiAobWUpIHtcbiAgICAgICAgICAgICAgICAgIC8vICAgcmV0dXJuIG1lLnZvaWNlLnNldFJlcXVlc3RUb1NwZWFrKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gYXMgVm9pY2VTdGF0ZTtcblxuICAgICAgcmV0dXJuIGhhbmRsZXIocHJveGllZE5ld1N0YXRlLCBwcm94aWVkT2xkU3RhdGUpO1xuICAgIH0gY2F0Y2gge1xuXG4gICAgICAvKiBub29wICovfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gb2NlYW5pY1ZvaWNlRXZlbnRzSGFuZGxlcihjbGllbnQ6IE9jZWFuaWMuQ2xpZW50KSB7XG4gIGxldCBhZGFwdGVycyA9IGdldFByb3BlcnR5PE1hcDxzdHJpbmcsIGFueT4+KGNsaWVudCwgJ2FkYXB0ZXJzJyk7XG5cbiAgaWYgKCFhZGFwdGVycykge1xuICAgIGNvbnN0IGNvbGxlY3Rpb24gPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xuICAgIGFkYXB0ZXJzID0gY29sbGVjdGlvbjtcbiAgICBkZWNsYXJlUHJvcGVydHkoY2xpZW50LCAnYWRhcHRlcnMnLCBjb2xsZWN0aW9uKTtcbiAgfVxuXG4gIGNsaWVudC5vbignc2hhcmREaXNjb25uZWN0JywgKF8sIHNoYXJkSWQpID0+IHtcbiAgICBmb3IgKGNvbnN0IFtndWlsZElkLCBhZGFwdGVyXSBvZiBhZGFwdGVycy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChjbGllbnQuZ3VpbGRzLmdldChndWlsZElkKT8uc2hhcmQuaWQgPT09IHNoYXJkSWQpIHtcbiAgICAgICAgYWRhcHRlci5kZXN0cm95KCk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICBjbGllbnQub24oJ3BhY2tldCcsIChwYWNrZXQpID0+IHtcbiAgICBzd2l0Y2ggKHBhY2tldC50KSB7XG4gICAgICBjYXNlIEdhdGV3YXlEaXNwYXRjaEV2ZW50cy5Wb2ljZVNlcnZlclVwZGF0ZTp7XG4gICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHBhY2tldC5kIGFzIEdhdGV3YXlWb2ljZVNlcnZlclVwZGF0ZURpc3BhdGNoRGF0YTtcbiAgICAgICAgICBhZGFwdGVycy5nZXQocGF5bG9hZC5ndWlsZF9pZCk/Lm9uVm9pY2VTZXJ2ZXJVcGRhdGUocGF5bG9hZCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICBjYXNlIEdhdGV3YXlEaXNwYXRjaEV2ZW50cy5Wb2ljZVN0YXRlVXBkYXRlOntcbiAgICAgICAgICBjb25zdCBwYXlsb2FkID0gcGFja2V0LmQgYXMgR2F0ZXdheVZvaWNlU3RhdGVVcGRhdGVEaXNwYXRjaERhdGE7XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgcGF5bG9hZC5ndWlsZF9pZCAmJlxuICAgICAgICAgIHBheWxvYWQuc2Vzc2lvbl9pZCAmJlxuICAgICAgICAgIHBheWxvYWQudXNlcl9pZCA9PT0gY2xpZW50LnVzZXIuaWQpXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRhcHRlcnMuZ2V0KHBheWxvYWQuZ3VpbGRfaWQpPy5vblZvaWNlU3RhdGVVcGRhdGUocGF5bG9hZCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBvY2VhbmljQ2hhbm5lbHNQcm94eShcbmNsaWVudDogT2NlYW5pYy5DbGllbnQsXG5vY2VhbmljOiB0eXBlb2YgaW1wb3J0KCdvY2VhbmljLmpzJykpXG57XG4gIGNvbnN0IGhhbmRsZXIgPSB7XG4gICAgY2xpZW50LFxuICAgIGdldCBjYWNoZSgpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGdldChpZDogc3RyaW5nKSB7XG4gICAgICAgICAgcmV0dXJuIGNsaWVudC5nZXRDaGFubmVsKGlkKTtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzKGlkOiBzdHJpbmcpIHtcbiAgICAgICAgICByZXR1cm4gaWQgaW4gY2xpZW50LmNoYW5uZWxHdWlsZE1hcDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9LFxuICAgIHJlc29sdmUocmVzb2x2YWJsZTogc3RyaW5nIHwgT2NlYW5pY0NoYW5uZWxSZXNvbHZhYmxlKSB7XG4gICAgICBpZiAodHlwZW9mIHJlc29sdmFibGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBvY2VhbmljUmVzb2x2ZWRDaGFubmVsUHJveHkoXG4gICAgICAgICAgdGhpcy5jbGllbnQuZ2V0Q2hhbm5lbChyZXNvbHZhYmxlKSBhcyBPY2VhbmljLkd1aWxkQ2hhbm5lbCxcbiAgICAgICAgICBjbGllbnRcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc29sdmFibGUgaW5zdGFuY2VvZiBvY2VhbmljLkd1aWxkQ2hhbm5lbCkge1xuICAgICAgICByZXR1cm4gb2NlYW5pY1Jlc29sdmVkQ2hhbm5lbFByb3h5KHJlc29sdmFibGUsIGNsaWVudCk7XG4gICAgICB9XG4gICAgfSxcbiAgICByZXNvbHZlSWQocmVzb2x2YWJsZTogT2NlYW5pY0NoYW5uZWxSZXNvbHZhYmxlKSB7XG4gICAgICBjb25zdCBjaGFubmVsID0gdGhpcy5yZXNvbHZlKHJlc29sdmFibGUpO1xuICAgICAgcmV0dXJuIGNoYW5uZWw/LmlkO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gaGFuZGxlcjtcbn1cblxuZnVuY3Rpb24gb2NlYW5pY1Jlc29sdmVkQ2hhbm5lbFByb3h5KFxuY2hhbm5lbDogT2NlYW5pYy5HdWlsZENoYW5uZWwgfCB1bmRlZmluZWQsXG5jbGllbnQ6IE9jZWFuaWMuQ2xpZW50KVxuOiBPY2VhbmljLkd1aWxkQ2hhbm5lbCB8IHVuZGVmaW5lZCB7XG4gIGlmICghY2hhbm5lbCkgcmV0dXJuO1xuXG4gIHJldHVybiBuZXcgUHJveHkoY2hhbm5lbCwge1xuICAgIGdldCh0YXJnZXQsIHApIHtcbiAgICAgIHN3aXRjaCAocCkge1xuICAgICAgICBjYXNlICdndWlsZCc6XG4gICAgICAgICAgcmV0dXJuIG9jZWFuaWNWb2ljZUFkYXB0ZXJQcm94eSh0YXJnZXQuZ3VpbGQsIGNsaWVudCk7XG4gICAgICAgIGNhc2UgJ21lbWJlcnMnOlxuICAgICAgICAgIHJldHVybiAodGFyZ2V0IGFzIE9jZWFuaWMuVm9pY2VDaGFubmVsKS52b2ljZU1lbWJlcnM7XG4gICAgICAgIGNhc2UgJ2lzVm9pY2VCYXNlZCc6XG4gICAgICAgICAgcmV0dXJuICgpID0+XG4gICAgICAgICAgdGFyZ2V0LnR5cGUgPT09IENoYW5uZWxUeXBlLkd1aWxkVm9pY2UgfHxcbiAgICAgICAgICB0YXJnZXQudHlwZSA9PT0gQ2hhbm5lbFR5cGUuR3VpbGRTdGFnZVZvaWNlO1xuICAgICAgICBjYXNlICdpc1ZvaWNlJzpcbiAgICAgICAgICByZXR1cm4gKCkgPT4gdGFyZ2V0LnR5cGUgPT09IENoYW5uZWxUeXBlLkd1aWxkVm9pY2U7XG4gICAgICAgIGNhc2UgJ2lzU3RhZ2UnOlxuICAgICAgICAgIHJldHVybiAoKSA9PiB0YXJnZXQudHlwZSA9PT0gQ2hhbm5lbFR5cGUuR3VpbGRTdGFnZVZvaWNlO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0W3BdO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG9jZWFuaWNWb2ljZUFkYXB0ZXJQcm94eShcbmd1aWxkOiBPY2VhbmljLkd1aWxkIHwgdW5kZWZpbmVkLFxuY2xpZW50OiBPY2VhbmljLkNsaWVudClcbjogT2NlYW5pYy5HdWlsZCB8IHVuZGVmaW5lZCB7XG4gIGlmICghZ3VpbGQpIHJldHVybjtcblxuICByZXR1cm4gbmV3IFByb3h5KGd1aWxkLCB7XG4gICAgZ2V0KHRhcmdldCwgcCkge1xuICAgICAgaWYgKHAgPT09ICd2b2ljZUFkYXB0ZXJDcmVhdG9yJykge1xuICAgICAgICByZXR1cm4gb2NlYW5pY1ZvaWNlQWRhcHRlckNyZWF0b3IodGFyZ2V0LCBjbGllbnQpO1xuICAgICAgfVxuXG4gICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIHBhdGNoaW5nXG4gICAgICByZXR1cm4gdGFyZ2V0W3BdO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG9jZWFuaWNWb2ljZUFkYXB0ZXJDcmVhdG9yKFxuZ3VpbGQ6IE9jZWFuaWMuR3VpbGQsXG5jbGllbnQ6IE9jZWFuaWMuQ2xpZW50KVxuOiBEaXNjb3JkR2F0ZXdheUFkYXB0ZXJDcmVhdG9yIHtcbiAgcmV0dXJuIChtZXRob2RzKSA9PiB7XG4gICAgbGV0IGFkYXB0ZXJzID0gZ2V0UHJvcGVydHk8TWFwPHN0cmluZywgdHlwZW9mIG1ldGhvZHM+PihjbGllbnQsICdhZGFwdGVycycpO1xuXG4gICAgaWYgKCFhZGFwdGVycykge1xuICAgICAgY29uc3QgY29sbGVjdGlvbiA9IG5ldyBNYXA8c3RyaW5nLCB0eXBlb2YgbWV0aG9kcz4oKTtcbiAgICAgIGFkYXB0ZXJzID0gY29sbGVjdGlvbjtcbiAgICAgIGRlY2xhcmVQcm9wZXJ0eShjbGllbnQsICdhZGFwdGVycycsIGNvbGxlY3Rpb24pO1xuICAgIH1cblxuICAgIGFkYXB0ZXJzLnNldChndWlsZC5pZCwgbWV0aG9kcyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc2VuZFBheWxvYWQocGF5bG9hZCkge1xuICAgICAgICBpZiAoZ3VpbGQuc2hhcmQuc3RhdHVzICE9PSAncmVhZHknKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIGd1aWxkLnNoYXJkLnNlbmQocGF5bG9hZC5vcCwgcGF5bG9hZC5kKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9LFxuICAgICAgZGVzdHJveSgpIHtcbiAgICAgICAgYWRhcHRlcnMuZGVsZXRlKGd1aWxkLmlkKTtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xufVxuXG5mdW5jdGlvbiBvY2VhbmljR3VpbGRzUHJveHkoXG5jbGllbnQ6IE9jZWFuaWMuQ2xpZW50LFxub2NlYW5pYzogdHlwZW9mIGltcG9ydCgnb2NlYW5pYy5qcycpKVxue1xuICByZXR1cm4gbmV3IFByb3h5KGNsaWVudC5ndWlsZHMsIHtcbiAgICBnZXQodGFyZ2V0LCBwKSB7XG4gICAgICBpZiAocCA9PT0gJ2NhY2hlJykge1xuICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgfVxuXG4gICAgICBpZiAocCA9PT0gJ3Jlc29sdmUnIHx8IHAgPT09ICdyZXNvbHZlSWQnKSB7XG4gICAgICAgIGNvbnN0IHJlc29sdmVyID0gZnVuY3Rpb24gKHJlc29sdmFibGU6IE9jZWFuaWNHdWlsZFJlc29sdmFibGUpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHJlc29sdmFibGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGFyZ2V0LmdldChyZXNvbHZhYmxlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmVzb2x2YWJsZSBpbnN0YW5jZW9mIG9jZWFuaWMuR3VpbGQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZhYmxlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChcbiAgICAgICAgICByZXNvbHZhYmxlIGluc3RhbmNlb2Ygb2NlYW5pYy5NZW1iZXIgfHxcbiAgICAgICAgICByZXNvbHZhYmxlIGluc3RhbmNlb2Ygb2NlYW5pYy5HdWlsZCB8fFxuICAgICAgICAgIHJlc29sdmFibGUgaW5zdGFuY2VvZiBvY2VhbmljLkd1aWxkQ2hhbm5lbCB8fFxuICAgICAgICAgIHJlc29sdmFibGUgaW5zdGFuY2VvZiBvY2VhbmljLlJvbGUpXG4gICAgICAgICAge1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmFibGUuZ3VpbGQ7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChwID09PSAncmVzb2x2ZScpIHtcbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZXI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKHJlc29sdmFibGU6IE9jZWFuaWNHdWlsZFJlc29sdmFibGUpID0+IHtcbiAgICAgICAgICBjb25zdCBndWlsZCA9IHJlc29sdmVyKHJlc29sdmFibGUpO1xuICAgICAgICAgIHJldHVybiBndWlsZD8uaWQ7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgIHJldHVybiB0YXJnZXRbcF07XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gb2NlYW5pY1VzZXJzUHJveHkoXG5jbGllbnQ6IE9jZWFuaWMuQ2xpZW50LFxub2NlYW5pYzogdHlwZW9mIGltcG9ydCgnb2NlYW5pYy5qcycpKVxue1xuICByZXR1cm4gbmV3IFByb3h5KGNsaWVudC51c2Vycywge1xuICAgIGdldCh0YXJnZXQsIHApIHtcbiAgICAgIGlmIChwID09PSAnY2FjaGUnKSB7XG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChwID09PSAncmVzb2x2ZScgfHwgcCA9PT0gJ3Jlc29sdmVJZCcpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSBmdW5jdGlvbiAocmVzb2x2YWJsZTogT2NlYW5pY1VzZXJSZXNvbHZhYmxlKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZhYmxlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5nZXQocmVzb2x2YWJsZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHJlc29sdmFibGUgaW5zdGFuY2VvZiBvY2VhbmljLlVzZXIpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZhYmxlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChyZXNvbHZhYmxlIGluc3RhbmNlb2Ygb2NlYW5pYy5NZW1iZXIpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZhYmxlLnVzZXI7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChwID09PSAncmVzb2x2ZScpIHtcbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZXI7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gKHJlc29sdmFibGU6IE9jZWFuaWNVc2VyUmVzb2x2YWJsZSkgPT4ge1xuICAgICAgICAgIGNvbnN0IHVzZXIgPSByZXNvbHZlcihyZXNvbHZhYmxlKTtcbiAgICAgICAgICByZXR1cm4gdXNlcj8uaWQ7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3IgcGF0Y2hpbmdcbiAgICAgIHJldHVybiB0YXJnZXRbcF07XG4gICAgfVxuICB9KTtcbn0iLCAiaW1wb3J0IHsgRGVmYXVsdExpc3RlbmVyIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL3V0aWxzJztcbmltcG9ydCB7IExpc3RlbmVyU2lnbmF0dXJlIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL3V0aWxzJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ0BkaXNjb3JkLXBsYXllci91dGlscyc7XG5pbXBvcnQgeyBVdGlsIH0gZnJvbSAnLi9VdGlsJztcblxuZXhwb3J0IGNsYXNzIFBsYXllckV2ZW50c0VtaXR0ZXI8XG4gIEwgZXh0ZW5kcyBMaXN0ZW5lclNpZ25hdHVyZTxMPiA9IERlZmF1bHRMaXN0ZW5lcj4gZXh0ZW5kc1xuRXZlbnRFbWl0dGVyPEw+IHtcbiAgI2hhc0RlYnVnZ2VyID0gZmFsc2U7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcmVxdWlyZWRFdmVudHM6IEFycmF5PGtleW9mIEw+ID0gW10pIHtcbiAgICBzdXBlcigpO1xuICB9XG5cbiAgcHVibGljIG9uPEsgZXh0ZW5kcyBrZXlvZiBMPihuYW1lOiBLLCBsaXN0ZW5lcjogTFtLXSkge1xuICAgIGlmIChuYW1lID09PSAnZGVidWcnKSB7XG4gICAgICB0aGlzLiNoYXNEZWJ1Z2dlciA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLm9uKG5hbWUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHB1YmxpYyBvbmNlPEsgZXh0ZW5kcyBrZXlvZiBMPihuYW1lOiBLLCBsaXN0ZW5lcjogTFtLXSkge1xuICAgIGlmIChuYW1lID09PSAnZGVidWcnKSB7XG4gICAgICB0aGlzLiNoYXNEZWJ1Z2dlciA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLm9uY2UobmFtZSwgbGlzdGVuZXIpO1xuICB9XG5cbiAgcHVibGljIGFkZExpc3RlbmVyPEsgZXh0ZW5kcyBrZXlvZiBMPihuYW1lOiBLLCBsaXN0ZW5lcjogTFtLXSkge1xuICAgIGlmIChuYW1lID09PSAnZGVidWcnKSB7XG4gICAgICB0aGlzLiNoYXNEZWJ1Z2dlciA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLmFkZExpc3RlbmVyKG5hbWUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHB1YmxpYyBvZmY8SyBleHRlbmRzIGtleW9mIEw+KG5hbWU6IEssIGxpc3RlbmVyOiBMW0tdKSB7XG4gICAgdGhpcy4jaGFzRGVidWdnZXIgPSB0aGlzLmxpc3RlbmVyQ291bnQoJ2RlYnVnJyBhcyBLKSA+IDA7XG5cbiAgICByZXR1cm4gc3VwZXIub2ZmKG5hbWUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmVMaXN0ZW5lcjxLIGV4dGVuZHMga2V5b2YgTD4obmFtZTogSywgbGlzdGVuZXI6IExbS10pIHtcbiAgICB0aGlzLiNoYXNEZWJ1Z2dlciA9IHRoaXMubGlzdGVuZXJDb3VudCgnZGVidWcnIGFzIEspID4gMDtcblxuICAgIHJldHVybiBzdXBlci5yZW1vdmVMaXN0ZW5lcihuYW1lLCBsaXN0ZW5lcik7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlQWxsTGlzdGVuZXJzPEsgZXh0ZW5kcyBrZXlvZiBMPihuYW1lPzogSykge1xuICAgIHRoaXMuI2hhc0RlYnVnZ2VyID0gdGhpcy5saXN0ZW5lckNvdW50KCdkZWJ1ZycgYXMgSykgPiAwO1xuXG4gICAgcmV0dXJuIHN1cGVyLnJlbW92ZUFsbExpc3RlbmVycyhuYW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBlbWl0PEsgZXh0ZW5kcyBrZXlvZiBMPihuYW1lOiBLLCAuLi5hcmdzOiBQYXJhbWV0ZXJzPExbS10+KSB7XG4gICAgaWYgKFxuICAgIHRoaXMucmVxdWlyZWRFdmVudHMuaW5jbHVkZXMobmFtZSkgJiZcbiAgICAhdGhpcy5ldmVudE5hbWVzKCkuaW5jbHVkZXMobmFtZSkpXG4gICAge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUuZXJyb3IoLi4uYXJncyk7XG4gICAgICBVdGlsLndhcm4oXG4gICAgICAgIGBObyBldmVudCBsaXN0ZW5lciBmb3VuZCBmb3IgZXZlbnQgXCIke1N0cmluZyhcbiAgICAgICAgICBuYW1lXG4gICAgICAgICl9XCIuIEV2ZW50cyAke3RoaXMucmVxdWlyZWRFdmVudHMuXG4gICAgICAgIG1hcCgobSkgPT4gYFwiJHtTdHJpbmcobSl9XCJgKS5cbiAgICAgICAgam9pbignLCAnKX0gbXVzdCBoYXZlIGV2ZW50IGxpc3RlbmVycy5gLFxuICAgICAgICAnVW5oYW5kbGVkRXZlbnRzV2FybmluZydcbiAgICAgICk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN1cGVyLmVtaXQobmFtZSwgLi4uYXJncyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGhhc0RlYnVnZ2VyKCkge1xuICAgIHJldHVybiB0aGlzLiNoYXNEZWJ1Z2dlcjtcbiAgfVxufSIsICJpbXBvcnQgeyBVc2VyIH0gZnJvbSAnZGlzY29yZC5qcyc7XG5pbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBQbGF5bGlzdCB9IGZyb20gJy4uL2ZhYnJpYy9QbGF5bGlzdCc7XG5pbXBvcnQgeyBUcmFjayB9IGZyb20gJy4uL2ZhYnJpYy9UcmFjayc7XG5pbXBvcnQgeyBFeHRyYWN0b3JFeGVjdXRpb25Db250ZXh0IH0gZnJvbSAnLi9FeHRyYWN0b3JFeGVjdXRpb25Db250ZXh0JztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICdodHRwJztcbmltcG9ydCB7IE5vdEltcGxlbWVudGVkRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHR5cGUgeyBHdWlsZFF1ZXVlSGlzdG9yeSB9IGZyb20gJy4uL3F1ZXVlJztcbmltcG9ydCB7IFNlYXJjaFF1ZXJ5VHlwZSB9IGZyb20gJy4uL3V0aWxzL1F1ZXJ5UmVzb2x2ZXInO1xuaW1wb3J0IHsgUGxheWVyRXZlbnRzIH0gZnJvbSAnLi4vUGxheWVyJztcblxuZXhwb3J0IHR5cGUgRXh0cmFjdG9yU3RyZWFtYWJsZSA9XG5SZWFkYWJsZSB8XG5zdHJpbmcgfFxue1xuICAkZm10OiBzdHJpbmc7XG4gIHN0cmVhbTogUmVhZGFibGU7XG59O1xuXG5leHBvcnQgY2xhc3MgQmFzZUV4dHJhY3RvcjxUIGV4dGVuZHMgb2JqZWN0ID0gb2JqZWN0PiB7XG4gIC8qKlxuICAgKiBJZGVudGlmaWVyIGZvciB0aGlzIGV4dHJhY3RvclxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBpZGVudGlmaWVyID0gJ2NvbS5kaXNjb3JkLXBsYXllci5leHRyYWN0b3InO1xuXG4gIC8qKlxuICAgKiBQcmlvcml0eSBvZiB0aGlzIGV4dHJhY3Rvci4gSGlnaGVyIHZhbHVlIG1lYW5zIGhpZ2hlciBwcmlvcml0eSAod2lsbCBiZSBleGVjdXRlZCBmaXJzdCkuXG4gICAqL1xuICBwdWJsaWMgcHJpb3JpdHkgPSAxO1xuXG4gIC8qKlxuICAgKiBBIGxpc3Qgb2YgcXVlcnkgcHJvdG9jb2xzIHRoYXQgdGhpcyBleHRyYWN0b3Igc3VwcG9ydHMuXG4gICAqL1xuICBwdWJsaWMgcHJvdG9jb2xzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBIYW5kbGUgYnJpZGdlIHF1ZXJ5IGNyZWF0aW9uXG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2sgdG8gYnVpbGQgcXVlcnkgZm9yXG4gICAqL1xuICBwdWJsaWMgY3JlYXRlQnJpZGdlUXVlcnkgPSAodHJhY2s6IFRyYWNrKSA9PlxuICBgJHt0cmFjay50aXRsZX0gYnkgJHt0cmFjay5hdXRob3J9IG9mZmljaWFsIGF1ZGlvYDtcblxuICAvKipcbiAgICogRXh0cmFjdG9yIGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSBjb250ZXh0IENvbnRleHQgdGhhdCBpbnN0YW50aWF0ZWQgdGhpcyBleHRyYWN0b3JcbiAgICogQHBhcmFtIG9wdGlvbnMgSW5pdGlhbGl6YXRpb24gb3B0aW9ucyBmb3IgdGhpcyBleHRyYWN0b3JcbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgcHVibGljIGNvbnRleHQ6IEV4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQsXG4gIHB1YmxpYyBvcHRpb25zOiBUID0gPFQ+IHt9KVxuICB7fVxuXG4gIC8qKlxuICAgKiBJZGVudGlmaWVyIG9mIHRoaXMgZXh0cmFjdG9yXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlkZW50aWZpZXIoKSB7XG4gICAgcmV0dXJuICh0aGlzLmNvbnN0cnVjdG9yIGFzIHR5cGVvZiBCYXNlRXh0cmFjdG9yKS5pZGVudGlmaWVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY29uZmlndXJlcyB0aGlzIGV4dHJhY3RvclxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgbmV3IG9wdGlvbnMgdG8gYXBwbHlcbiAgICovXG4gIHB1YmxpYyBhc3luYyByZWNvbmZpZ3VyZShvcHRpb25zOiBUKSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICBhd2FpdCB0aGlzLmRlYWN0aXZhdGUoKTtcbiAgICBhd2FpdCB0aGlzLmFjdGl2YXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBleGVjdXRlZCB3aGVuIHRoaXMgZXh0cmFjdG9yIGlzIGFjdGl2YXRlZFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGFjdGl2YXRlKCkge1xuICAgIC8vIGV4ZWN1dGVkIHdoZW4gdGhpcyBleHRyYWN0b3IgaXMgYWN0aXZhdGVkXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgZXhlY3V0ZWQgd2hlbiB0aGlzIGV4dHJhY3RvciBpcyBkZWFjdGl2YXRlZFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRlYWN0aXZhdGUoKSB7XG4gICAgLy8gZXhlY3V0ZWQgd2hlbiB0aGlzIGV4dHJhY3RvciBpcyBkZWFjdGl2YXRlZFxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBpbmNvbWluZyBxdWVyeVxuICAgKiBAcGFyYW0gcXVlcnkgVGhlIHF1ZXJ5IHRvIHZhbGlkYXRlXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGUoXG4gIHF1ZXJ5OiBzdHJpbmcsXG4gIHR5cGU/OiBTZWFyY2hRdWVyeVR5cGUgfCBudWxsKVxuICA6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHZvaWQgdHlwZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogU3RyZWFtIHRoZSBnaXZlbiB0cmFja1xuICAgKiBAcGFyYW0gaW5mbyBUaGUgdHJhY2sgdG8gc3RyZWFtXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc3RyZWFtKGluZm86IFRyYWNrKTogUHJvbWlzZTxFeHRyYWN0b3JTdHJlYW1hYmxlPiB7XG4gICAgdm9pZCBpbmZvO1xuICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0uc3RyZWFtKClgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgdGhlIGdpdmVuIHF1ZXJ5XG4gICAqIEBwYXJhbSBxdWVyeSBUaGUgcXVlcnkgdG8gaGFuZGxlXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgaGFuZGxlKFxuICBxdWVyeTogc3RyaW5nLFxuICBjb250ZXh0OiBFeHRyYWN0b3JTZWFyY2hDb250ZXh0KVxuICA6IFByb21pc2U8RXh0cmFjdG9ySW5mbz4ge1xuICAgIHZvaWQgY29udGV4dDtcbiAgICB0aHJvdyBuZXcgTm90SW1wbGVtZW50ZWRFcnJvcihgJHt0aGlzLmNvbnN0cnVjdG9yLm5hbWV9LmhhbmRsZSgpYCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHJlbGF0ZWQgdHJhY2tzIGZvciB0aGUgZ2l2ZW4gdHJhY2tcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayBzb3VyY2VcbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRSZWxhdGVkVHJhY2tzKFxuICB0cmFjazogVHJhY2ssXG4gIGhpc3Rvcnk6IEd1aWxkUXVldWVIaXN0b3J5KVxuICA6IFByb21pc2U8RXh0cmFjdG9ySW5mbz4ge1xuICAgIHZvaWQgdHJhY2s7XG4gICAgdm9pZCBoaXN0b3J5O1xuICAgIHRocm93IG5ldyBOb3RJbXBsZW1lbnRlZEVycm9yKFxuICAgICAgYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfS5nZXRSZWxhdGVkVHJhY2tzKClgXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHN0cmVhbSBtaWRkbGV3YXJlIHRvIGhhbmRsZSBzdHJlYW1zIGJlZm9yZSBwYXNzaW5nIGl0IHRvIHRoZSBwbGF5ZXJcbiAgICogQHBhcmFtIHN0cmVhbSBUaGUgaW5jb21pbmcgc3RyZWFtXG4gICAqIEBwYXJhbSBuZXh0IFRoZSBuZXh0IGZ1bmN0aW9uXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlUG9zdFN0cmVhbShzdHJlYW06IFJlYWRhYmxlLCBuZXh0OiBOZXh0RnVuY3Rpb24pIHtcbiAgICByZXR1cm4gbmV4dChudWxsLCBzdHJlYW0pO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3BhdGNoIGFuIGV2ZW50IHRvIHRoZSBwbGF5ZXJcbiAgICogQHBhcmFtIGV2ZW50IFRoZSBldmVudCB0byBkaXNwYXRjaFxuICAgKiBAcGFyYW0gYXJncyBUaGUgZGF0YSB0byBkaXNwYXRjaFxuICAgKi9cbiAgcHVibGljIGVtaXQ8SyBleHRlbmRzIGtleW9mIFBsYXllckV2ZW50cz4oXG4gIGV2ZW50OiBLLFxuICAuLi5hcmdzOiBQYXJhbWV0ZXJzPFBsYXllckV2ZW50c1tLXT4pXG4gIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZXh0LnBsYXllci5lbWl0KGV2ZW50LCAuLi5hcmdzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgZXh0cmFjdG9yIHJlc3BvbnNlXG4gICAqIEBwYXJhbSBwbGF5bGlzdCBUaGUgcGxheWxpc3RcbiAgICogQHBhcmFtIHRyYWNrcyBUaGUgdHJhY2sgYXJyYXlcbiAgICovXG4gIHB1YmxpYyBjcmVhdGVSZXNwb25zZShcbiAgcGxheWxpc3Q/OiBQbGF5bGlzdCB8IG51bGwsXG4gIHRyYWNrczogVHJhY2tbXSA9IHBsYXlsaXN0Py50cmFja3MgfHwgW10pXG4gIDogRXh0cmFjdG9ySW5mbyB7XG4gICAgcmV0dXJuIHsgcGxheWxpc3Q6IHBsYXlsaXN0IHx8IG51bGwsIHRyYWNrcyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFdyaXRlIGRlYnVnIG1lc3NhZ2VcbiAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGRlYnVnIG1lc3NhZ2VcbiAgICovXG4gIHB1YmxpYyBkZWJ1ZyhtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZXh0LnBsYXllci5kZWJ1ZyhtZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGZsYWcgdG8gaW5kaWNhdGUgYERlbXV4YWJsZWAgc3RyZWFtIHN1cHBvcnQgZm9yIGBvcHVzYC9gb2dnL29wdXNgL2B3ZWJtL29wdXNgIGZvcm1hdHMuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN1cHBvcnRzRGVtdXgoKSB7XG4gICAgcmV0dXJuICEhdGhpcy5jb250ZXh0LnBsYXllci5vcHRpb25zLnNraXBGRm1wZWc7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIHN0cmVhbSBleHRyYWN0aW9uIGZvciBhbm90aGVyIGV4dHJhY3RvclxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRvIGJyaWRnZVxuICAgKiBAcGFyYW0gc291cmNlRXh0cmFjdG9yIFRoZSBzb3VyY2UgZXh0cmFjdG9yXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgYnJpZGdlKFxuICB0cmFjazogVHJhY2ssXG4gIHNvdXJjZUV4dHJhY3RvcjogQmFzZUV4dHJhY3RvciB8IG51bGwpXG4gIDogUHJvbWlzZTxFeHRyYWN0b3JTdHJlYW1hYmxlIHwgbnVsbD4ge1xuICAgIHZvaWQgc291cmNlRXh0cmFjdG9yO1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmV4cG9ydCB0eXBlIE5leHRGdW5jdGlvbiA9IChlcnJvcj86IEVycm9yIHwgbnVsbCwgc3RyZWFtPzogUmVhZGFibGUpID0+IHZvaWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXh0cmFjdG9ySW5mbyB7XG4gIHBsYXlsaXN0OiBQbGF5bGlzdCB8IG51bGw7XG4gIHRyYWNrczogVHJhY2tbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHRyYWN0b3JTZWFyY2hDb250ZXh0IHtcbiAgdHlwZT86IFNlYXJjaFF1ZXJ5VHlwZSB8IG51bGw7XG4gIHJlcXVlc3RlZEJ5PzogVXNlciB8IG51bGw7XG4gIHJlcXVlc3RPcHRpb25zPzogUmVxdWVzdE9wdGlvbnM7XG4gIHByb3RvY29sPzogc3RyaW5nIHwgbnVsbDtcbn0iLCAiaW1wb3J0IHsgUGxheWVyIH0gZnJvbSAnLi4vUGxheWVyJztcbmltcG9ydCB7IENvbGxlY3Rpb24gfSBmcm9tICdAZGlzY29yZC1wbGF5ZXIvdXRpbHMnO1xuaW1wb3J0IHsgQmFzZUV4dHJhY3RvciwgRXh0cmFjdG9yU3RyZWFtYWJsZSB9IGZyb20gJy4vQmFzZUV4dHJhY3Rvcic7XG5pbXBvcnQgeyBVdGlsIH0gZnJvbSAnLi4vdXRpbHMvVXRpbCc7XG5pbXBvcnQgeyBQbGF5ZXJFdmVudHNFbWl0dGVyIH0gZnJvbSAnLi4vdXRpbHMvUGxheWVyRXZlbnRzRW1pdHRlcic7XG5pbXBvcnQgeyBUeXBlVXRpbCB9IGZyb20gJy4uL3V0aWxzL1R5cGVVdGlsJztcbmltcG9ydCB7IFRyYWNrIH0gZnJvbSAnLi4vZmFicmljJztcbmltcG9ydCB7IGNyZWF0ZUNvbnRleHQgfSBmcm9tICcuLi9ob29rcyc7XG5pbXBvcnQgeyBCcmlkZ2VGYWlsZWRFcnJvciB9IGZyb20gJy4uL2Vycm9ycyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXh0cmFjdG9yU2Vzc2lvbiB7XG4gIGlkOiBzdHJpbmc7XG4gIGF0dGVtcHRlZEV4dHJhY3RvcnM6IFNldDxzdHJpbmc+O1xuICBicmlkZ2VBdHRlbXB0ZWRFeHRyYWN0b3JzOiBTZXQ8c3RyaW5nPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFeHRyYWN0b3JFeGVjdXRpb25FdmVudHMge1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgZXh0cmFjdG9yIGlzIHJlZ2lzdGVyZWRcbiAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlcmUgZXh0cmFjdG9yIHdhcyByZWdpc3RlcmVkXG4gICAqIEBwYXJhbSBleHRyYWN0b3IgVGhlIGV4dHJhY3RvciB0aGF0IHdhcyByZWdpc3RlcmVkXG4gICAqL1xuICByZWdpc3RlcmVkOiAoXG4gIGNvbnRleHQ6IEV4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQsXG4gIGV4dHJhY3RvcjogQmFzZUV4dHJhY3RvcilcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGV4dHJhY3RvciBpcyB1bnJlZ2lzdGVyZWRcbiAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlcmUgZXh0cmFjdG9yIHdhcyB1bnJlZ2lzdGVyZWRcbiAgICogQHBhcmFtIGV4dHJhY3RvciBUaGUgZXh0cmFjdG9yIHRoYXQgd2FzIHVucmVnaXN0ZXJlZFxuICAgKi9cbiAgdW5yZWdpc3RlcmVkOiAoXG4gIGNvbnRleHQ6IEV4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQsXG4gIGV4dHJhY3RvcjogQmFzZUV4dHJhY3RvcilcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIGV4dHJhY3RvciBpcyBhY3RpdmF0ZWRcbiAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gZXh0cmFjdG9yIFRoZSBleHRyYWN0b3Igd2hpY2ggd2FzIGFjdGl2YXRlZFxuICAgKi9cbiAgYWN0aXZhdGU6IChcbiAgY29udGV4dDogRXh0cmFjdG9yRXhlY3V0aW9uQ29udGV4dCxcbiAgZXh0cmFjdG9yOiBCYXNlRXh0cmFjdG9yKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgZXh0cmFjdG9yIGlzIGRlYWN0aXZhdGVkXG4gICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIGV4dHJhY3RvciBUaGUgZXh0cmFjdG9yIHdoaWNoIHdhcyBkZWFjdGl2YXRlZFxuICAgKi9cbiAgZGVhY3RpdmF0ZTogKFxuICBjb250ZXh0OiBFeHRyYWN0b3JFeGVjdXRpb25Db250ZXh0LFxuICBleHRyYWN0b3I6IEJhc2VFeHRyYWN0b3IpXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBleHRyYWN0b3IgZmFpbHMgdG8gYWN0aXZhdGUvZGVhY3RpdmF0ZVxuICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqIEBwYXJhbSBleHRyYWN0b3IgVGhlIGV4dHJhY3RvciB3aGljaCB3YXMgZGVhY3RpdmF0ZWRcbiAgICovXG4gIGVycm9yOiAoXG4gIGNvbnRleHQ6IEV4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQsXG4gIGV4dHJhY3RvcjogQmFzZUV4dHJhY3RvcixcbiAgZXJyb3I6IEVycm9yKVxuICA9PiB1bmtub3duO1xufVxuXG5leHBvcnQgY2xhc3MgRXh0cmFjdG9yRXhlY3V0aW9uQ29udGV4dCBleHRlbmRzIFBsYXllckV2ZW50c0VtaXR0ZXI8RXh0cmFjdG9yRXhlY3V0aW9uRXZlbnRzPiB7XG4gIC8qKlxuICAgKiBUaGUgZXh0cmFjdG9ycyBzdG9yZVxuICAgKi9cbiAgcHVibGljIHN0b3JlID0gbmV3IENvbGxlY3Rpb248c3RyaW5nLCBCYXNlRXh0cmFjdG9yPigpO1xuXG4gIHB1YmxpYyByZWFkb25seSBjb250ZXh0ID0gY3JlYXRlQ29udGV4dDxFeHRyYWN0b3JTZXNzaW9uPigpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcGxheWVyOiBQbGF5ZXIpIHtcbiAgICBzdXBlcihbJ2Vycm9yJ10pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudCBleGVjdXRpb24gaWRcbiAgICovXG4gIHB1YmxpYyBnZXRFeGVjdXRpb25JZCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZXh0LmNvbnN1bWUoKT8uaWQgPz8gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1cnJlbnQgZXhlY3V0aW9uIGNvbnRleHRcbiAgICovXG4gIHB1YmxpYyBnZXRDb250ZXh0KCkge1xuICAgIHJldHVybiB0aGlzLmNvbnRleHQuY29uc3VtZSgpID8/IG51bGw7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgbG9hZERlZmF1bHQoKSB7XG4gICAgY29uc3Qgc2FtcGxlID0gYFxcdGltcG9ydCB7IERlZmF1bHRFeHRyYWN0b3JzIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL2V4dHJhY3Rvcic7XFxuXFx0YXdhaXQgcGxheWVyLmV4dHJhY3RvcnMubG9hZE11bHRpKERlZmF1bHRFeHRyYWN0b3JzKTtgO1xuXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYGV4dHJhY3RvcnMubG9hZERlZmF1bHQoKSBpcyBubyBsb25nZXIgc3VwcG9ydGVkLiBVc2UgZXh0cmFjdG9ycy5sb2FkTXVsdGkgaW5zdGVhZC4gRXhhbXBsZTpcXG4ke3NhbXBsZX1cXG5gXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIGEgYnVuZGxlIG9mIGV4dHJhY3RvcnMuXG4gICAqIEBleGFtcGxlIGltcG9ydCB7IERlZmF1bHRFeHRyYWN0b3JzIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL2V4dHJhY3Rvcic7XG4gICAqXG4gICAqIGF3YWl0IHBsYXllci5leHRyYWN0b3JzLmxvYWRNdWx0aShEZWZhdWx0RXh0cmFjdG9ycyk7XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbG9hZE11bHRpPFxuICAgIE8gZXh0ZW5kcyBvYmplY3QsXG4gICAgVCBleHRlbmRzICh0eXBlb2YgQmFzZUV4dHJhY3RvcjxPPilbXSxcbiAgICBSIGV4dGVuZHMgUmVjb3JkPFxuICAgICAgVFtudW1iZXJdWydpZGVudGlmaWVyJ10sXG4gICAgICBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VFtudW1iZXJdPlsxXT4+KFxuXG4gIGJ1bmRsZTogVCwgb3B0aW9uczogUiA9IHt9IGFzIFIpIHtcbiAgICBidW5kbGUuZm9yRWFjaCgoZXh0KSA9PiB7XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICB0aGlzLnJlZ2lzdGVyKGV4dCwgb3B0aW9ucz8uW2V4dC5pZGVudGlmaWVyXSB8fCB7fSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCBlcnJvcjogbnVsbCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGlmIHRoZSBnaXZlbiBleHRyYWN0b3IgaXMgcmVnaXN0ZXJlZFxuICAgKiBAcGFyYW0gaWRlbnRpZmllciBUaGUgZXh0cmFjdG9yIGlkZW50aWZpZXJcbiAgICovXG4gIHB1YmxpYyBpc1JlZ2lzdGVyZWQoaWRlbnRpZmllcjogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuaGFzKGlkZW50aWZpZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzaXplIG9mIHJlZ2lzdGVyZWQgZXh0cmFjdG9yc1xuICAgKi9cbiAgcHVibGljIGdldCBzaXplKCkge1xuICAgIHJldHVybiB0aGlzLnN0b3JlLnNpemU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNpbmdsZSBleHRyYWN0b3JcbiAgICogQHBhcmFtIGlkZW50aWZpZXIgVGhlIGV4dHJhY3RvciB0byBnZXRcbiAgICovXG4gIHB1YmxpYyBnZXQoaWRlbnRpZmllcjogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmUuZ2V0KGlkZW50aWZpZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIHNpbmdsZSBleHRyYWN0b3JcbiAgICogQHBhcmFtIF9leHRyYWN0b3IgVGhlIGV4dHJhY3RvciB0byByZWdpc3RlclxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zIHN1cHBsaWVkIHRvIHRoZSBleHRyYWN0b3JcbiAgICovXG4gIHB1YmxpYyBhc3luYyByZWdpc3RlcjxPIGV4dGVuZHMgb2JqZWN0LCBUIGV4dGVuZHMgdHlwZW9mIEJhc2VFeHRyYWN0b3I8Tz4+KFxuICBfZXh0cmFjdG9yOiBULFxuICBvcHRpb25zOiBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8VD5bJzEnXSlcbiAgOiBQcm9taXNlPEluc3RhbmNlVHlwZTxUPiB8IG51bGw+IHtcbiAgICBpZiAoXG4gICAgdHlwZW9mIF9leHRyYWN0b3IuaWRlbnRpZmllciAhPT0gJ3N0cmluZycgfHxcbiAgICB0aGlzLnN0b3JlLmhhcyhfZXh0cmFjdG9yLmlkZW50aWZpZXIpKVxuXG4gICAgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgZXh0cmFjdG9yID0gbmV3IF9leHRyYWN0b3IodGhpcywgb3B0aW9ucyk7XG5cbiAgICB0cnkge1xuICAgICAgdGhpcy5zdG9yZS5zZXQoX2V4dHJhY3Rvci5pZGVudGlmaWVyLCBleHRyYWN0b3IpO1xuICAgICAgaWYgKHRoaXMucGxheWVyLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5wbGF5ZXIuZGVidWcoYCR7X2V4dHJhY3Rvci5pZGVudGlmaWVyfSBleHRyYWN0b3IgbG9hZGVkIWApO1xuICAgICAgdGhpcy5lbWl0KCdyZWdpc3RlcmVkJywgdGhpcywgZXh0cmFjdG9yKTtcbiAgICAgIGF3YWl0IGV4dHJhY3Rvci5hY3RpdmF0ZSgpO1xuICAgICAgaWYgKHRoaXMucGxheWVyLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5wbGF5ZXIuZGVidWcoYCR7X2V4dHJhY3Rvci5pZGVudGlmaWVyfSBleHRyYWN0b3IgYWN0aXZhdGVkIWApO1xuICAgICAgdGhpcy5lbWl0KCdhY3RpdmF0ZScsIHRoaXMsIGV4dHJhY3Rvcik7XG4gICAgICByZXR1cm4gZXh0cmFjdG9yIGFzIHVua25vd24gYXMgSW5zdGFuY2VUeXBlPFQ+O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRoaXMuc3RvcmUuZGVsZXRlKF9leHRyYWN0b3IuaWRlbnRpZmllcik7XG4gICAgICBpZiAodGhpcy5wbGF5ZXIuaGFzRGVidWdnZXIpXG4gICAgICB0aGlzLnBsYXllci5kZWJ1ZyhcbiAgICAgICAgYCR7X2V4dHJhY3Rvci5pZGVudGlmaWVyfSBleHRyYWN0b3IgZmFpbGVkIHRvIGFjdGl2YXRlISBFcnJvcjogJHtlfWBcbiAgICAgICk7XG4gICAgICB0aGlzLmVtaXQoJ2Vycm9yJywgdGhpcywgZXh0cmFjdG9yLCBlIGFzIEVycm9yKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVyIHNpbmdsZSBleHRyYWN0b3JcbiAgICogQHBhcmFtIF9leHRyYWN0b3IgVGhlIGV4dHJhY3RvciB0byB1bnJlZ2lzdGVyXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdW5yZWdpc3RlcjxLIGV4dGVuZHMgc3RyaW5nIHwgQmFzZUV4dHJhY3Rvcj4oX2V4dHJhY3RvcjogSykge1xuICAgIGNvbnN0IGV4dHJhY3RvciA9XG4gICAgdHlwZW9mIF9leHRyYWN0b3IgPT09ICdzdHJpbmcnID9cbiAgICB0aGlzLnN0b3JlLmdldChfZXh0cmFjdG9yKSA6XG4gICAgdGhpcy5zdG9yZS5maW5kKChyKSA9PiByID09PSBfZXh0cmFjdG9yKTtcbiAgICBpZiAoIWV4dHJhY3RvcikgcmV0dXJuO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGtleSA9XG4gICAgICBleHRyYWN0b3IuaWRlbnRpZmllciB8fCB0aGlzLnN0b3JlLmZpbmRLZXkoKGUpID0+IGUgPT09IGV4dHJhY3RvcikhO1xuICAgICAgdGhpcy5zdG9yZS5kZWxldGUoa2V5KTtcbiAgICAgIGlmICh0aGlzLnBsYXllci5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMucGxheWVyLmRlYnVnKGAke2V4dHJhY3Rvci5pZGVudGlmaWVyfSBleHRyYWN0b3IgZGlzYWJsZWQhYCk7XG4gICAgICB0aGlzLmVtaXQoJ3VucmVnaXN0ZXJlZCcsIHRoaXMsIGV4dHJhY3Rvcik7XG4gICAgICBhd2FpdCBleHRyYWN0b3IuZGVhY3RpdmF0ZSgpO1xuICAgICAgaWYgKHRoaXMucGxheWVyLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5wbGF5ZXIuZGVidWcoYCR7ZXh0cmFjdG9yLmlkZW50aWZpZXJ9IGV4dHJhY3RvciBkZWFjdGl2YXRlZCFgKTtcbiAgICAgIHRoaXMuZW1pdCgnZGVhY3RpdmF0ZScsIHRoaXMsIGV4dHJhY3Rvcik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKHRoaXMucGxheWVyLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5wbGF5ZXIuZGVidWcoXG4gICAgICAgIGAke2V4dHJhY3Rvci5pZGVudGlmaWVyfSBleHRyYWN0b3IgZmFpbGVkIHRvIGRlYWN0aXZhdGUhYFxuICAgICAgKTtcbiAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCB0aGlzLCBleHRyYWN0b3IsIGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbnJlZ2lzdGVyIGFsbCBleHRyYWN0b3JzXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdW5yZWdpc3RlckFsbCgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwodGhpcy5zdG9yZS5tYXAoKGUpID0+IHRoaXMudW5yZWdpc3RlcihlKSkpO1xuICAgIH0gY2F0Y2gge1xuXG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfX1cblxuICAvKipcbiAgICogUnVuIGFsbCB0aGUgZXh0cmFjdG9yc1xuICAgKiBAcGFyYW0gZm4gVGhlIHJ1bm5lciBmdW5jdGlvblxuICAgKiBAcGFyYW0gZmlsdGVyQmxvY2tlZCBGaWx0ZXIgYmxvY2tlZCBleHRyYWN0b3JzXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcnVuPFQgPSB1bmtub3duPihcbiAgZm46IEV4dHJhY3RvckV4ZWN1dGlvbkZOPFQ+LFxuICBmaWx0ZXJCbG9ja2VkID0gdHJ1ZSlcbiAge1xuICAgIGNvbnN0IGJsb2NrZWQgPSB0aGlzLnBsYXllci5vcHRpb25zLmJsb2NrRXh0cmFjdG9ycyA/PyBbXTtcblxuICAgIGlmICghdGhpcy5zdG9yZS5zaXplKSB7XG4gICAgICBVdGlsLndhcm4oXG4gICAgICAgICdTa2lwcGluZyBleHRyYWN0b3JzIGV4ZWN1dGlvbiBzaW5jZSB6ZXJvIGV4dHJhY3RvcnMgd2VyZSByZWdpc3RlcmVkJyxcbiAgICAgICAgJ05vRXh0cmFjdG9ycydcbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gc29ydCBieSBwcmlvcml0eSBzbyB0aGF0IGV4dHJhY3RvcnMgd2l0aCBoaWdoZXIgcHJpb3JpdHkgYXJlIGV4ZWN1dGVkIGZpcnN0XG4gICAgY29uc3QgZXh0cmFjdG9ycyA9IHRoaXMuc3RvcmUuc29ydCgoYSwgYikgPT4gYi5wcmlvcml0eSAtIGEucHJpb3JpdHkpO1xuXG4gICAgbGV0IGVycjogRXJyb3IgfCBudWxsID0gbnVsbCxcbiAgICAgIGxhc3RFeHQ6IEJhc2VFeHRyYWN0b3IgfCBudWxsID0gbnVsbDtcblxuICAgIGZvciAoY29uc3QgZXh0IG9mIGV4dHJhY3RvcnMudmFsdWVzKCkpIHtcbiAgICAgIGlmIChmaWx0ZXJCbG9ja2VkICYmIGJsb2NrZWQuc29tZSgoZSkgPT4gZSA9PT0gZXh0LmlkZW50aWZpZXIpKSBjb250aW51ZTtcbiAgICAgIGlmICh0aGlzLnBsYXllci5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMucGxheWVyLmRlYnVnKGBFeGVjdXRpbmcgZXh0cmFjdG9yICR7ZXh0LmlkZW50aWZpZXJ9Li4uYCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBmbihleHQpLnRoZW4oXG4gICAgICAgIChyZXMpID0+IHtcbiAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9LFxuICAgICAgICAoZSkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLnBsYXllci5oYXNEZWJ1Z2dlcilcbiAgICAgICAgICB0aGlzLnBsYXllci5kZWJ1ZyhcbiAgICAgICAgICAgIGBFeHRyYWN0b3IgJHtleHQuaWRlbnRpZmllcn0gZmFpbGVkIHdpdGggZXJyb3I6ICR7ZX1gXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHJldHVybiBUeXBlVXRpbC5pc0Vycm9yKGUpID8gZSA6IG5ldyBFcnJvcihgJHtlfWApO1xuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICBsYXN0RXh0ID0gZXh0O1xuXG4gICAgICBpZiAocmVzdWx0ICYmICFUeXBlVXRpbC5pc0Vycm9yKHJlc3VsdCkpIHtcbiAgICAgICAgaWYgKHRoaXMucGxheWVyLmhhc0RlYnVnZ2VyKVxuICAgICAgICB0aGlzLnBsYXllci5kZWJ1ZyhcbiAgICAgICAgICBgRXh0cmFjdG9yICR7ZXh0LmlkZW50aWZpZXJ9IGV4ZWN1dGVkIHN1Y2Nlc3NmdWxseSFgXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBleHRyYWN0b3I6IGV4dCxcbiAgICAgICAgICBlcnJvcjogbnVsbCxcbiAgICAgICAgICByZXN1bHRcbiAgICAgICAgfSBhcyBFeHRyYWN0b3JFeGVjdXRpb25SZXN1bHQ8VD47XG4gICAgICB9IGVsc2UgaWYgKFR5cGVVdGlsLmlzRXJyb3IocmVzdWx0KSkge1xuICAgICAgICBlcnIgPSByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVycilcbiAgICByZXR1cm4ge1xuICAgICAgZXh0cmFjdG9yOiBsYXN0RXh0ISxcbiAgICAgIGVycm9yOiBlcnIsXG4gICAgICByZXN1bHQ6IGZhbHNlXG4gICAgfSBhcyBFeHRyYWN0b3JFeGVjdXRpb25SZXN1bHQ8ZmFsc2U+O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgYnJpZGdlIGZvciBhIHRyYWNrXG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2sgdG8gcmVxdWVzdCBicmlkZ2UgZm9yXG4gICAqIEBwYXJhbSBzb3VyY2VFeHRyYWN0b3IgVGhlIHNvdXJjZSBleHRyYWN0b3Igb2YgdGhlIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVxdWVzdEJyaWRnZShcbiAgdHJhY2s6IFRyYWNrLFxuICBzb3VyY2VFeHRyYWN0b3I6IEJhc2VFeHRyYWN0b3IgfCBudWxsID0gdHJhY2suZXh0cmFjdG9yKVxuICB7XG4gICAgY29uc3QgcHJldmlvdXNseUF0dGVtcHRlZCA9XG4gICAgdGhpcy5nZXRDb250ZXh0KCk/LmJyaWRnZUF0dGVtcHRlZEV4dHJhY3RvcnMgPz8gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJ1bjxFeHRyYWN0b3JTdHJlYW1hYmxlPihhc3luYyAoZXh0KSA9PiB7XG4gICAgICBpZiAoc291cmNlRXh0cmFjdG9yICYmIGV4dC5pZGVudGlmaWVyID09PSBzb3VyY2VFeHRyYWN0b3IuaWRlbnRpZmllcilcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIGlmIChwcmV2aW91c2x5QXR0ZW1wdGVkLmhhcyhleHQuaWRlbnRpZmllcikpIHJldHVybiBmYWxzZTtcblxuICAgICAgcHJldmlvdXNseUF0dGVtcHRlZC5hZGQoZXh0LmlkZW50aWZpZXIpO1xuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBleHQuYnJpZGdlKHRyYWNrLCBzb3VyY2VFeHRyYWN0b3IpO1xuXG4gICAgICBpZiAoIXJlc3VsdCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gICAgaWYgKCFyZXN1bHQ/LnJlc3VsdClcbiAgICB0aHJvdyBuZXcgQnJpZGdlRmFpbGVkRXJyb3IoXG4gICAgICB0aGlzLmdldEV4ZWN1dGlvbklkKCksXG4gICAgICByZXN1bHQ/LmVycm9yPy5zdGFjayB8fFxuICAgICAgcmVzdWx0Py5lcnJvcj8ubWVzc2FnZSB8fFxuICAgICAgJ05vIGV4dHJhY3RvcnMgYXZhaWxhYmxlIHRvIGJyaWRnZSdcbiAgICApO1xuXG4gICAgdHJhY2suYnJpZGdlZEV4dHJhY3RvciA9IHJlc3VsdC5leHRyYWN0b3I7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgYnJpZGdlIGZyb20gdGhlIHNwZWNpZmllZCBleHRyYWN0b3JcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayB0byByZXF1ZXN0IGJyaWRnZSBmb3JcbiAgICogQHBhcmFtIHNvdXJjZUV4dHJhY3RvciBUaGUgc291cmNlIGV4dHJhY3RvciBvZiB0aGUgdHJhY2tcbiAgICogQHBhcmFtIHRhcmdldEV4dHJhY3RvciBUaGUgdGFyZ2V0IGV4dHJhY3RvciB0byBicmlkZ2UgdG9cbiAgICovXG4gIHB1YmxpYyBhc3luYyByZXF1ZXN0QnJpZGdlRnJvbShcbiAgdHJhY2s6IFRyYWNrLFxuICBzb3VyY2VFeHRyYWN0b3I6IEJhc2VFeHRyYWN0b3IgfCBudWxsLFxuICB0YXJnZXRFeHRyYWN0b3I6IEV4dHJhY3RvclJlc29sdmFibGUpXG4gIHtcbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzLnJlc29sdmUodGFyZ2V0RXh0cmFjdG9yKTtcbiAgICBpZiAoIXRhcmdldCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRhcmdldC5icmlkZ2UodHJhY2ssIHNvdXJjZUV4dHJhY3Rvcik7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgZXh0cmFjdG9yIGlzIGRpc2FibGVkXG4gICAqL1xuICBwdWJsaWMgaXNEaXNhYmxlZChpZGVudGlmaWVyOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXIub3B0aW9ucy5ibG9ja0V4dHJhY3RvcnM/LmluY2x1ZGVzKGlkZW50aWZpZXIpID8/IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGV4dHJhY3RvciBpcyBlbmFibGVkXG4gICAqL1xuICBwdWJsaWMgaXNFbmFibGVkKGlkZW50aWZpZXI6IHN0cmluZykge1xuICAgIHJldHVybiAhdGhpcy5pc0Rpc2FibGVkKGlkZW50aWZpZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgZXh0cmFjdG9yIGlkZW50aWZpZXJcbiAgICovXG4gIHB1YmxpYyByZXNvbHZlSWQocmVzb2x2YWJsZTogRXh0cmFjdG9yUmVzb2x2YWJsZSkge1xuICAgIHJldHVybiB0eXBlb2YgcmVzb2x2YWJsZSA9PT0gJ3N0cmluZycgPyByZXNvbHZhYmxlIDogcmVzb2x2YWJsZS5pZGVudGlmaWVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgZXh0cmFjdG9yXG4gICAqL1xuICBwdWJsaWMgcmVzb2x2ZShyZXNvbHZhYmxlOiBFeHRyYWN0b3JSZXNvbHZhYmxlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiByZXNvbHZhYmxlID09PSAnc3RyaW5nJyA/IHRoaXMuZ2V0KHJlc29sdmFibGUpIDogcmVzb2x2YWJsZTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4dHJhY3RvckV4ZWN1dGlvblJlc3VsdDxUID0gdW5rbm93bj4ge1xuICBleHRyYWN0b3I6IEJhc2VFeHRyYWN0b3I7XG4gIGVycm9yOiBFcnJvciB8IG51bGw7XG4gIHJlc3VsdDogVDtcbn1cblxuZXhwb3J0IHR5cGUgRXh0cmFjdG9yRXhlY3V0aW9uRk48VCA9IHVua25vd24+ID0gKFxuZXh0cmFjdG9yOiBCYXNlRXh0cmFjdG9yKVxuPT4gUHJvbWlzZTxUIHwgYm9vbGVhbj47XG5cbmV4cG9ydCB0eXBlIEV4dHJhY3RvclJlc29sdmFibGUgPSBzdHJpbmcgfCBCYXNlRXh0cmFjdG9yOyIsICJpbXBvcnQgeyBBc3luY0xvY2FsU3RvcmFnZSB9IGZyb20gJ25vZGU6YXN5bmNfaG9va3MnO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxudHlwZSB1bnNhZmUgPSBhbnk7XG5cbi8qKlxuICogVGhlIHJlY2VpdmVyIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBjYWxsZWQgd2hlbiB0aGUgY29udGV4dCBpcyBwcm92aWRlZFxuICovXG5leHBvcnQgdHlwZSBDb250ZXh0UmVjZWl2ZXI8Uj4gPSAoKSA9PiBSO1xuXG5leHBvcnQgY2xhc3MgQ29udGV4dDxUPiB7XG4gIHByaXZhdGUgc3RvcmFnZSA9IG5ldyBBc3luY0xvY2FsU3RvcmFnZTxUPigpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIGRlZmF1bHRWYWx1ZT86IFQpIHt9XG5cbiAgLyoqXG4gICAqIEV4aXQgb3V0IG9mIHRoaXMgY29udGV4dFxuICAgKi9cbiAgcHVibGljIGV4aXQoc2NvcGU6IENvbnRleHRSZWNlaXZlcjx2b2lkPikge1xuICAgIHRoaXMuc3RvcmFnZS5leGl0KHNjb3BlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjb250ZXh0IGlzIGxvc3RcbiAgICovXG4gIHB1YmxpYyBnZXQgaXNMb3N0KCkge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0U3RvcmUoKSA9PT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgY29udGV4dC4gSWYgdGhlIGNvbnRleHQgaXMgbG9zdCBhbmQgbm8gZGVmYXVsdCB2YWx1ZSBpcyBwcm92aWRlZCwgdW5kZWZpbmVkIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAqL1xuICBwdWJsaWMgY29uc3VtZSgpOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBkYXRhID0gdGhpcy5zdG9yYWdlLmdldFN0b3JlKCk7XG5cbiAgICBpZiAoZGF0YSA9PT0gdW5kZWZpbmVkICYmIHRoaXMuZGVmYXVsdFZhbHVlICE9PSB1bmRlZmluZWQpXG4gICAgcmV0dXJuIHRoaXMuZGVmYXVsdFZhbHVlO1xuXG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICAvKipcbiAgICogUnVuIGEgZnVuY3Rpb24gd2l0aGluIHRoZSBjb250ZXh0IG9mIHRoaXMgcHJvdmlkZXJcbiAgICovXG4gIHB1YmxpYyBwcm92aWRlPFIgPSB1bnNhZmU+KHZhbHVlOiBULCByZWNlaXZlcjogQ29udGV4dFJlY2VpdmVyPFI+KTogUiB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ29udGV4dCB2YWx1ZSBtYXkgbm90IGJlIHVuZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgcmVjZWl2ZXIgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ29udGV4dCByZWNlaXZlciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLnJ1bih2YWx1ZSwgcmVjZWl2ZXIpO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgbmV3IGNvbnRleHQuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIG9wdGlvbmFsLlxuICogQHBhcmFtIGRlZmF1bHRWYWx1ZSBUaGUgZGVmYXVsdCB2YWx1ZSBvZiB0aGUgY29udGV4dFxuICogQGV4YW1wbGUgY29uc3QgdXNlckNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCk7XG4gKlxuICogIC8vIHRoZSB2YWx1ZSB0byBwcm92aWRlXG4gKiAgY29uc3QgdXNlciA9IHtcbiAqICAgaWQ6IDEsXG4gKiAgIG5hbWU6ICdKb2huIERvZSdcbiAqICB9O1xuICpcbiAqICAvLyBwcm92aWRlIHRoZSBjb250ZXh0IHZhbHVlIHRvIHRoZSByZWNlaXZlclxuICogIGNvbnRleHQucHJvdmlkZSh1c2VyLCBoYW5kbGVyKTtcbiAqXG4gKiAgZnVuY3Rpb24gaGFuZGxlcigpIHtcbiAqICAgIC8vIGdldCB0aGUgY29udGV4dCB2YWx1ZVxuICogICAgY29uc3QgeyBpZCwgbmFtZSB9ID0gdXNlQ29udGV4dChjb250ZXh0KTtcbiAqXG4gKiAgICBjb25zb2xlLmxvZyhpZCwgbmFtZSk7IC8vIDEsIEpvaG4gRG9lXG4gKiAgfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29udGV4dDxUID0gdW5zYWZlPihkZWZhdWx0VmFsdWU/OiBUKTogQ29udGV4dDxUPiB7XG4gIHJldHVybiBuZXcgQ29udGV4dChkZWZhdWx0VmFsdWUpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgY29udGV4dC4gSWYgdGhlIGNvbnRleHQgaXMgbG9zdCBhbmQgbm8gZGVmYXVsdCB2YWx1ZSBpcyBwcm92aWRlZCwgdW5kZWZpbmVkIHdpbGwgYmUgcmV0dXJuZWQuXG4gKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB0byBnZXQgdGhlIHZhbHVlIGZyb21cbiAqIEBleGFtcGxlIGNvbnN0IHZhbHVlID0gdXNlQ29udGV4dChjb250ZXh0KTtcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUNvbnRleHQ8VCA9IHVuc2FmZT4oY29udGV4dDogQ29udGV4dDxUPik6IFQgfCB1bmRlZmluZWQge1xuICByZXR1cm4gY29udGV4dC5jb25zdW1lKCk7XG59IiwgImltcG9ydCB7IENvbGxlY3Rpb24gfSBmcm9tICdAZGlzY29yZC1wbGF5ZXIvdXRpbHMnO1xuXG5leHBvcnQgY29uc3QgZ2xvYmFsUmVnaXN0cnkgPSBuZXcgQ29sbGVjdGlvbjxzdHJpbmcsIHVua25vd24+KCk7IiwgImltcG9ydCB7IGdsb2JhbFJlZ2lzdHJ5IH0gZnJvbSAnLi9fY29udGFpbmVyJztcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEdsb2JhbFJlZ2lzdHJ5KCkge1xuICByZXR1cm4gZ2xvYmFsUmVnaXN0cnk7XG59IiwgImltcG9ydCB7IEd1aWxkIH0gZnJvbSAnZGlzY29yZC5qcyc7XG5pbXBvcnQgeyBQbGF5ZXIgfSBmcm9tICcuLi9QbGF5ZXInO1xuaW1wb3J0IHsgSWxsZWdhbEhvb2tJbnZvY2F0aW9uRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgY3JlYXRlQ29udGV4dCwgdXNlQ29udGV4dCB9IGZyb20gJy4vY29udGV4dC9hc3luYy1jb250ZXh0JztcbmltcG9ydCB7IGdldEdsb2JhbFJlZ2lzdHJ5IH0gZnJvbSAnLi4vdXRpbHMvX19pbnRlcm5hbF9fJztcblxuZXhwb3J0IGludGVyZmFjZSBIb29rc0N0eCB7XG4gIGd1aWxkOiBHdWlsZDtcbn1cblxuZXhwb3J0IGNvbnN0IFNVUEVSX0NPTlRFWFQgPSBjcmVhdGVDb250ZXh0PFBsYXllcj4oKTtcblxuY29uc3QgZ2V0RmFsbGJhY2tDb250ZXh0ID0gKCkgPT4ge1xuICByZXR1cm4gZ2V0R2xvYmFsUmVnaXN0cnkoKS5nZXQoJ0BbcGxheWVyXScpIGFzIFBsYXllciB8IHVuZGVmaW5lZDtcbn07XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUhvb2tzQ29udGV4dChob29rTmFtZTogc3RyaW5nLCBtYWluT25seSA9IGZhbHNlKSB7XG4gIGxldCBpc0ZhbGxiYWNrID0gZmFsc2U7XG5cbiAgbGV0IHBsYXllcjogUGxheWVyIHwgdW5kZWZpbmVkO1xuXG4gIGlmICghKHBsYXllciA9IFNVUEVSX0NPTlRFWFQuY29uc3VtZSgpKSkge1xuICAgIHBsYXllciA9IGdldEZhbGxiYWNrQ29udGV4dCgpO1xuICAgIGlzRmFsbGJhY2sgPSB0cnVlO1xuICB9XG5cbiAgaWYgKCFwbGF5ZXIpXG4gIHRocm93IG5ldyBJbGxlZ2FsSG9va0ludm9jYXRpb25FcnJvcihcbiAgICAnZGlzY29yZC1wbGF5ZXInLFxuICAgIGBQbGF5ZXIgY29udGV4dCBpcyBub3QgYXZhaWxhYmxlLCAke1xuICAgIGlzRmFsbGJhY2sgP1xuICAgICdkaWQgeW91IGZvcmdldCB0byBpbml0aWFsaXplIHRoZSBwbGF5ZXIgd2l0aCBgbmV3IFBsYXllcihjbGllbnQpYD8nIDpcbiAgICAnaXMgaXQgYmVpbmcgY2FsbGVkIGluc2lkZSA8UGxheWVyPi5jb250ZXh0LnByb3ZpZGUoKT8nfWBcblxuICApO1xuXG4gIGlmIChtYWluT25seSkgcmV0dXJuIHsgcGxheWVyLCBjb250ZXh0OiB7fSBhcyBIb29rc0N0eCwgaXNGYWxsYmFjayB9O1xuXG4gIGxldCBjb250ZXh0OiBIb29rc0N0eCB8IHVuZGVmaW5lZDtcblxuICBpZiAoIWlzRmFsbGJhY2spIHtcbiAgICBjb250ZXh0ID0gdXNlQ29udGV4dChwbGF5ZXIuY29udGV4dCk7XG4gICAgaWYgKCFjb250ZXh0KVxuICAgIHRocm93IG5ldyBJbGxlZ2FsSG9va0ludm9jYXRpb25FcnJvcihcbiAgICAgIGhvb2tOYW1lLFxuICAgICAgYCR7aG9va05hbWV9IG11c3QgYmUgY2FsbGVkIGluc2lkZSBhIHBsYXllciBjb250ZXh0IGNyZWF0ZWQgYnkgPFBsYXllcj4uY29udGV4dC5wcm92aWRlKClgXG4gICAgKTtcbiAgfSBlbHNlIHtcbiAgICBjb250ZXh0ID0ge1xuICAgICAgZ2V0IGd1aWxkKCkge1xuICAgICAgICB0aHJvdyBuZXcgSWxsZWdhbEhvb2tJbnZvY2F0aW9uRXJyb3IoXG4gICAgICAgICAgaG9va05hbWUsXG4gICAgICAgICAgYCR7aG9va05hbWV9IG11c3QgYmUgY2FsbGVkIHdpdGggYW4gZXhwbGljaXQgZ3VpbGQgYXJndW1lbnQgd2hlbiBub3QgaW5zaWRlIGEgcGxheWVyIGNvbnRleHRgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBhcyB1bmtub3duIGFzIEhvb2tzQ3R4O1xuICB9XG5cbiAgcmV0dXJuIHsgY29udGV4dCwgcGxheWVyLCBpc0ZhbGxiYWNrIH07XG59IiwgImltcG9ydCB7IEd1aWxkUXVldWVIaXN0b3J5LCBOb2RlUmVzb2x2YWJsZSB9IGZyb20gJy4uL3F1ZXVlJztcbmltcG9ydCB7IHVzZUhvb2tzQ29udGV4dCB9IGZyb20gJy4vY29tbW9uJztcblxuLyoqXG4gKiBGZXRjaCBndWlsZCBxdWV1ZSBoaXN0b3J5XG4gKiBAcGFyYW0gbm9kZSBndWlsZCBxdWV1ZSBub2RlIHJlc29sdmFibGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUhpc3Rvcnk8TWV0YSA9IHVua25vd24+KCk6IEd1aWxkUXVldWVIaXN0b3J5PE1ldGE+IHwgbnVsbDtcbmV4cG9ydCBmdW5jdGlvbiB1c2VIaXN0b3J5PE1ldGEgPSB1bmtub3duPihcbm5vZGU6IE5vZGVSZXNvbHZhYmxlKVxuOiBHdWlsZFF1ZXVlSGlzdG9yeTxNZXRhPiB8IG51bGw7XG5leHBvcnQgZnVuY3Rpb24gdXNlSGlzdG9yeTxNZXRhID0gdW5rbm93bj4oXG5ub2RlPzogTm9kZVJlc29sdmFibGUpXG46IEd1aWxkUXVldWVIaXN0b3J5PE1ldGE+IHwgbnVsbCB7XG4gIGNvbnN0IHsgY29udGV4dCwgcGxheWVyIH0gPSB1c2VIb29rc0NvbnRleHQoJ3VzZUhpc3RvcnknKTtcblxuICBjb25zdCBxdWV1ZSA9IHBsYXllci5xdWV1ZXMuZ2V0PE1ldGE+KG5vZGUgPz8gY29udGV4dC5ndWlsZC5pZCk7XG4gIGlmICghcXVldWUpIHJldHVybiBudWxsO1xuXG4gIHJldHVybiBxdWV1ZS5oaXN0b3J5O1xufSIsICJpbXBvcnQgeyBHdWlsZFF1ZXVlUGxheWVyTm9kZSwgTm9kZVJlc29sdmFibGUgfSBmcm9tICcuLi9xdWV1ZSc7XG5pbXBvcnQgeyB1c2VIb29rc0NvbnRleHQgfSBmcm9tICcuL2NvbW1vbic7XG5cbi8qKlxuICogRmV0Y2ggZ3VpbGQgcXVldWUgcGxheWVyIG5vZGVcbiAqIEBwYXJhbSBub2RlIEd1aWxkIHF1ZXVlIG5vZGUgcmVzb2x2YWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlUGxheWVyPE1ldGEgPSB1bmtub3duPigpOiBHdWlsZFF1ZXVlUGxheWVyTm9kZTxNZXRhPiB8IG51bGw7XG5leHBvcnQgZnVuY3Rpb24gdXNlUGxheWVyPE1ldGEgPSB1bmtub3duPihcbm5vZGU6IE5vZGVSZXNvbHZhYmxlKVxuOiBHdWlsZFF1ZXVlUGxheWVyTm9kZTxNZXRhPiB8IG51bGw7XG5leHBvcnQgZnVuY3Rpb24gdXNlUGxheWVyPE1ldGEgPSB1bmtub3duPihcbm5vZGU/OiBOb2RlUmVzb2x2YWJsZSlcbjogR3VpbGRRdWV1ZVBsYXllck5vZGU8TWV0YT4gfCBudWxsIHtcbiAgY29uc3QgeyBjb250ZXh0LCBwbGF5ZXIgfSA9IHVzZUhvb2tzQ29udGV4dCgndXNlUGxheWVyJyk7XG4gIGNvbnN0IHF1ZXVlID0gcGxheWVyLnF1ZXVlcy5nZXQ8TWV0YT4obm9kZSA/PyBjb250ZXh0Lmd1aWxkLmlkKTtcbiAgaWYgKCFxdWV1ZSkgcmV0dXJuIG51bGw7XG5cbiAgcmV0dXJuIHF1ZXVlLm5vZGU7XG59IiwgImltcG9ydCB7IEd1aWxkUXVldWUsIE5vZGVSZXNvbHZhYmxlIH0gZnJvbSAnLi4vcXVldWUnO1xuaW1wb3J0IHsgdXNlSG9va3NDb250ZXh0IH0gZnJvbSAnLi9jb21tb24nO1xuXG4vKipcbiAqIEZldGNoIGd1aWxkIHF1ZXVlLlxuICogQHBhcmFtIG5vZGUgR3VpbGQgcXVldWUgbm9kZSByZXNvbHZhYmxlLiBEZWZhdWx0cyB0byBpbmZlcnJlZCBndWlsZCBmcm9tIGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VRdWV1ZTxNZXRhID0gdW5rbm93bj4oKTogR3VpbGRRdWV1ZTxNZXRhPiB8IG51bGw7XG5leHBvcnQgZnVuY3Rpb24gdXNlUXVldWU8TWV0YSA9IHVua25vd24+KFxubm9kZTogTm9kZVJlc29sdmFibGUpXG46IEd1aWxkUXVldWU8TWV0YT4gfCBudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVF1ZXVlPE1ldGEgPSB1bmtub3duPihcbm5vZGU/OiBOb2RlUmVzb2x2YWJsZSlcbjogR3VpbGRRdWV1ZTxNZXRhPiB8IG51bGwge1xuICBjb25zdCB7IGNvbnRleHQsIHBsYXllciB9ID0gdXNlSG9va3NDb250ZXh0KCd1c2VRdWV1ZScpO1xuICBjb25zdCBxdWV1ZSA9IHBsYXllci5xdWV1ZXMucmVzb2x2ZTxNZXRhPihub2RlID8/IGNvbnRleHQuZ3VpbGQuaWQpO1xuICBpZiAoIXF1ZXVlKSByZXR1cm4gbnVsbDtcblxuICByZXR1cm4gcXVldWU7XG59IiwgImltcG9ydCB7IHVzZUhvb2tzQ29udGV4dCB9IGZyb20gJy4vY29tbW9uJztcblxuLyoqXG4gKiBGZXRjaCBtYWluIHBsYXllciBpbnN0YW5jZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlTWFpblBsYXllcigpIHtcbiAgY29uc3QgeyBwbGF5ZXIgfSA9IHVzZUhvb2tzQ29udGV4dCgndXNlTWFpblBsYXllcicsIHRydWUpO1xuXG4gIHJldHVybiBwbGF5ZXI7XG59IiwgImltcG9ydCB7IE5vZGVSZXNvbHZhYmxlIH0gZnJvbSAnLi4vcXVldWUnO1xuaW1wb3J0IHsgVHlwZVV0aWwgfSBmcm9tICcuLi91dGlscy9UeXBlVXRpbCc7XG5pbXBvcnQgeyB1c2VIb29rc0NvbnRleHQgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCB0eXBlIFNldHRlckZOPFQsIFA+ID0gKHByZXZpb3VzOiBQKSA9PiBUO1xuZXhwb3J0IHR5cGUgTWV0YWRhdGFEaXNwYXRjaDxUPiA9IHJlYWRvbmx5IFtcbiAgKCkgPT4gVCxcbiAgKG1ldGFkYXRhOiBUIHwgU2V0dGVyRk48VCwgVD4pID0+IHZvaWRdO1xuXG5cbi8qKlxuICogRmV0Y2ggb3IgbWFuaXB1bGF0ZSBndWlsZCBxdWV1ZSBtZXRhZGF0YVxuICogQHBhcmFtIG5vZGUgR3VpbGQgcXVldWUgbm9kZSByZXNvbHZhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VNZXRhZGF0YTxUID0gdW5rbm93bj4oKTogTWV0YWRhdGFEaXNwYXRjaDxUPjtcbmV4cG9ydCBmdW5jdGlvbiB1c2VNZXRhZGF0YTxUID0gdW5rbm93bj4oXG5ub2RlOiBOb2RlUmVzb2x2YWJsZSlcbjogTWV0YWRhdGFEaXNwYXRjaDxUPjtcbmV4cG9ydCBmdW5jdGlvbiB1c2VNZXRhZGF0YTxUID0gdW5rbm93bj4oXG5ub2RlPzogTm9kZVJlc29sdmFibGUpXG46IE1ldGFkYXRhRGlzcGF0Y2g8VD4ge1xuICBjb25zdCB7IGNvbnRleHQsIHBsYXllciB9ID0gdXNlSG9va3NDb250ZXh0KCd1c2VNZXRhZGF0YScpO1xuICBjb25zdCBxdWV1ZSA9IHBsYXllci5xdWV1ZXMuZ2V0PFQ+KG5vZGUgPz8gY29udGV4dC5ndWlsZC5pZCk7XG4gIGNvbnN0IHNldHRlciA9IChtZXRhZGF0YTogVCB8IFNldHRlckZOPFQsIFQ+KSA9PiB7XG4gICAgaWYgKHF1ZXVlKSB7XG4gICAgICBpZiAoVHlwZVV0aWwuaXNGdW5jdGlvbihtZXRhZGF0YSkpXG4gICAgICByZXR1cm4gcXVldWUuc2V0TWV0YWRhdGEobWV0YWRhdGEocXVldWUubWV0YWRhdGEpKTtcbiAgICAgIHJldHVybiBxdWV1ZS5zZXRNZXRhZGF0YShtZXRhZGF0YSk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGdldHRlciA9ICgpID0+IHtcbiAgICByZXR1cm4gcXVldWU/Lm1ldGFkYXRhIGFzIFQ7XG4gIH07XG5cbiAgcmV0dXJuIFtnZXR0ZXIsIHNldHRlcl0gYXMgY29uc3Q7XG59IiwgImltcG9ydCB7IFRyYWNrIH0gZnJvbSAnLi4vZmFicmljJztcbmltcG9ydCB7IE5vZGVSZXNvbHZhYmxlLCBQbGF5ZXJUaW1lc3RhbXAgfSBmcm9tICcuLi9xdWV1ZSc7XG5pbXBvcnQgeyB1c2VIb29rc0NvbnRleHQgfSBmcm9tICcuL2NvbW1vbic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGltZWxpbmVEaXNwYXRjaGVyT3B0aW9ucyB7XG4gIGlnbm9yZUZpbHRlcnM6IGJvb2xlYW47XG4gIG5vZGU6IE5vZGVSZXNvbHZhYmxlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEd1aWxkUXVldWVUaW1lbGluZSB7XG4gIHJlYWRvbmx5IHRpbWVzdGFtcDogUGxheWVyVGltZXN0YW1wO1xuICByZWFkb25seSB2b2x1bWU6IG51bWJlcjtcbiAgcmVhZG9ubHkgcGF1c2VkOiBib29sZWFuO1xuICByZWFkb25seSB0cmFjazogVHJhY2s8dW5rbm93bj4gfCBudWxsO1xuICBwYXVzZSgpOiBib29sZWFuO1xuICByZXN1bWUoKTogYm9vbGVhbjtcbiAgc2V0Vm9sdW1lKHZvbDogbnVtYmVyKTogYm9vbGVhbjtcbiAgc2V0UG9zaXRpb24odGltZTogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPjtcbn1cblxuLyoqXG4gKiBGZXRjaCBvciBtYW5pcHVsYXRlIGN1cnJlbnQgdHJhY2tcbiAqIEBwYXJhbSBvcHRpb25zIE9wdGlvbnMgZm9yIHRpbWVsaW5lIGRpc3BhdGNoZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVRpbWVsaW5lKCk6IEd1aWxkUXVldWVUaW1lbGluZSB8IG51bGw7XG5leHBvcnQgZnVuY3Rpb24gdXNlVGltZWxpbmUoXG5vcHRpb25zOiBQYXJ0aWFsPFRpbWVsaW5lRGlzcGF0Y2hlck9wdGlvbnM+KVxuOiBHdWlsZFF1ZXVlVGltZWxpbmUgfCBudWxsO1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVRpbWVsaW5lKFxub3B0aW9ucz86IFBhcnRpYWw8VGltZWxpbmVEaXNwYXRjaGVyT3B0aW9ucz4pXG46IEd1aWxkUXVldWVUaW1lbGluZSB8IG51bGwge1xuICBjb25zdCB7IGNvbnRleHQsIHBsYXllciB9ID0gdXNlSG9va3NDb250ZXh0KCd1c2VUaW1lbGluZScpO1xuICBjb25zdCBxdWV1ZSA9IHBsYXllci5xdWV1ZXMuZ2V0KG9wdGlvbnM/Lm5vZGUgPz8gY29udGV4dC5ndWlsZC5pZCk7XG4gIGlmICghcXVldWUpIHJldHVybiBudWxsO1xuXG4gIGNvbnN0IHRpbWVsaW5lID0gT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKHtcbiAgICBnZXQgdGltZXN0YW1wKCkge1xuICAgICAgcmV0dXJuIHF1ZXVlLm5vZGUuZ2V0VGltZXN0YW1wKG9wdGlvbnM/Lmlnbm9yZUZpbHRlcnMpITtcbiAgICB9LFxuICAgIGdldCB2b2x1bWUoKSB7XG4gICAgICByZXR1cm4gcXVldWUubm9kZS52b2x1bWU7XG4gICAgfSxcbiAgICBnZXQgcGF1c2VkKCkge1xuICAgICAgcmV0dXJuIHF1ZXVlLm5vZGUuaXNQYXVzZWQoKTtcbiAgICB9LFxuICAgIGdldCB0cmFjaygpIHtcbiAgICAgIHJldHVybiBxdWV1ZS5jdXJyZW50VHJhY2s7XG4gICAgfSxcbiAgICBwYXVzZSgpIHtcbiAgICAgIHJldHVybiBxdWV1ZS5ub2RlLnBhdXNlKCk7XG4gICAgfSxcbiAgICByZXN1bWUoKSB7XG4gICAgICByZXR1cm4gcXVldWUubm9kZS5yZXN1bWUoKTtcbiAgICB9LFxuICAgIHNldFZvbHVtZSh2b2w6IG51bWJlcikge1xuICAgICAgcmV0dXJuIHF1ZXVlLm5vZGUuc2V0Vm9sdW1lKHZvbCk7XG4gICAgfSxcbiAgICBhc3luYyBzZXRQb3NpdGlvbih0aW1lOiBudW1iZXIpIHtcbiAgICAgIHJldHVybiBxdWV1ZS5ub2RlLnNlZWsodGltZSk7XG4gICAgfVxuICB9IHNhdGlzZmllcyBHdWlsZFF1ZXVlVGltZWxpbmUpO1xuXG4gIHJldHVybiB0aW1lbGluZTtcbn0iLCAiaW1wb3J0IHsgT25BZnRlckNyZWF0ZVN0cmVhbUhhbmRsZXIgfSBmcm9tICcuLi8uLi9xdWV1ZSc7XG5pbXBvcnQgeyBnZXRHbG9iYWxSZWdpc3RyeSB9IGZyb20gJy4uLy4uL3V0aWxzL19faW50ZXJuYWxfXyc7XG5cbi8qKlxuICogR2xvYmFsIG9uQWZ0ZXJDcmVhdGVTdHJlYW0gaGFuZGxlclxuICogQHBhcmFtIGhhbmRsZXIgVGhlIGhhbmRsZXIgY2FsbGJhY2tcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uQWZ0ZXJDcmVhdGVTdHJlYW0oaGFuZGxlcjogT25BZnRlckNyZWF0ZVN0cmVhbUhhbmRsZXIpIHtcbiAgZ2V0R2xvYmFsUmVnaXN0cnkoKS5zZXQoJ0Bbb25BZnRlckNyZWF0ZVN0cmVhbV0nLCBoYW5kbGVyKTtcbn0iLCAiaW1wb3J0IHsgT25CZWZvcmVDcmVhdGVTdHJlYW1IYW5kbGVyIH0gZnJvbSAnLi4vLi4vcXVldWUnO1xuaW1wb3J0IHsgZ2V0R2xvYmFsUmVnaXN0cnkgfSBmcm9tICcuLi8uLi91dGlscy9fX2ludGVybmFsX18nO1xuXG4vKipcbiAqIEdsb2JhbCBvbkJlZm9yZUNyZWF0ZVN0cmVhbSBoYW5kbGVyXG4gKiBAcGFyYW0gaGFuZGxlciBUaGUgaGFuZGxlciBjYWxsYmFja1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25CZWZvcmVDcmVhdGVTdHJlYW0oaGFuZGxlcjogT25CZWZvcmVDcmVhdGVTdHJlYW1IYW5kbGVyKSB7XG4gIGdldEdsb2JhbFJlZ2lzdHJ5KCkuc2V0KCdAW29uQmVmb3JlQ3JlYXRlU3RyZWFtXScsIGhhbmRsZXIpO1xufSIsICJpbXBvcnQgeyBPblN0cmVhbUV4dHJhY3RlZEhhbmRsZXIgfSBmcm9tICcuLi8uLi9xdWV1ZSc7XG5pbXBvcnQgeyBnZXRHbG9iYWxSZWdpc3RyeSB9IGZyb20gJy4uLy4uL3V0aWxzL19faW50ZXJuYWxfXyc7XG5cbi8qKlxuICogR2xvYmFsIG9uU3RyZWFtRXh0cmFjdGVkIGhhbmRsZXJcbiAqIEBwYXJhbSBoYW5kbGVyIFRoZSBoYW5kbGVyIGNhbGxiYWNrXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvblN0cmVhbUV4dHJhY3RlZChoYW5kbGVyOiBPblN0cmVhbUV4dHJhY3RlZEhhbmRsZXIpIHtcbiAgZ2V0R2xvYmFsUmVnaXN0cnkoKS5zZXQoJ0Bbb25TdHJlYW1FeHRyYWN0ZWRdJywgaGFuZGxlcik7XG59IiwgImltcG9ydCB7IE5vZGVSZXNvbHZhYmxlIH0gZnJvbSAnLi4vcXVldWUnO1xuaW1wb3J0IHsgVHlwZVV0aWwgfSBmcm9tICcuLi91dGlscy9UeXBlVXRpbCc7XG5pbXBvcnQgeyB1c2VIb29rc0NvbnRleHQgfSBmcm9tICcuL2NvbW1vbic7XG5cbnR5cGUgU2V0dGVyRk4gPSAocHJldmlvdXM6IG51bWJlcikgPT4gbnVtYmVyO1xudHlwZSBWb2x1bWVEaXNwYXRjaCA9IHJlYWRvbmx5IFtcbiAgKCkgPT4gbnVtYmVyLFxuICAodm9sdW1lOiBudW1iZXIgfCBTZXR0ZXJGTikgPT4gYm9vbGVhbiB8IHVuZGVmaW5lZF07XG5cblxuLyoqXG4gKiBGZXRjaCBvciBtYW5pcHVsYXRlIHBsYXllciB2b2x1bWVcbiAqIEBwYXJhbSBub2RlIEd1aWxkIHF1ZXVlIG5vZGUgcmVzb2x2YWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXNlVm9sdW1lKCk6IFZvbHVtZURpc3BhdGNoO1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVZvbHVtZShub2RlOiBOb2RlUmVzb2x2YWJsZSk6IFZvbHVtZURpc3BhdGNoO1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVZvbHVtZShub2RlPzogTm9kZVJlc29sdmFibGUpOiBWb2x1bWVEaXNwYXRjaCB7XG4gIGNvbnN0IHsgY29udGV4dCwgcGxheWVyIH0gPSB1c2VIb29rc0NvbnRleHQoJ3VzZVZvbHVtZScpO1xuICBjb25zdCBxdWV1ZSA9IHBsYXllci5xdWV1ZXMuZ2V0KG5vZGUgPz8gY29udGV4dC5ndWlsZC5pZCk7XG4gIGNvbnN0IHNldHRlciA9ICh2b2x1bWU6IG51bWJlciB8IFNldHRlckZOKSA9PiB7XG4gICAgaWYgKHF1ZXVlKSB7XG4gICAgICBpZiAoVHlwZVV0aWwuaXNGdW5jdGlvbih2b2x1bWUpKVxuICAgICAgcmV0dXJuIHF1ZXVlLm5vZGUuc2V0Vm9sdW1lKHZvbHVtZShxdWV1ZS5ub2RlLnZvbHVtZSkpO1xuICAgICAgcmV0dXJuIHF1ZXVlLm5vZGUuc2V0Vm9sdW1lKHZvbHVtZSk7XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0IGdldHRlciA9ICgpID0+IHtcbiAgICByZXR1cm4gcXVldWU/Lm5vZGUudm9sdW1lIGFzIG51bWJlcjtcbiAgfTtcblxuICByZXR1cm4gW2dldHRlciwgc2V0dGVyXSBhcyBjb25zdDtcbn0iLCAiaW1wb3J0IHtcbiAgRXF1YWxpemVyQmFuZCxcbiAgUENNRmlsdGVycyxcbiAgQmlxdWFkRmlsdGVycyB9IGZyb21cbidAZGlzY29yZC1wbGF5ZXIvZXF1YWxpemVyJztcbmltcG9ydCB7IENvbGxlY3Rpb24sIFF1ZXVlU3RyYXRlZ3kgfSBmcm9tICdAZGlzY29yZC1wbGF5ZXIvdXRpbHMnO1xuaW1wb3J0IHsgR3VpbGRSZXNvbHZhYmxlIH0gZnJvbSAnZGlzY29yZC5qcyc7XG5pbXBvcnQgeyBQbGF5ZXIgfSBmcm9tICcuLi9QbGF5ZXInO1xuaW1wb3J0IHtcbiAgR3VpbGRRdWV1ZSxcbiAgT25BZnRlckNyZWF0ZVN0cmVhbUhhbmRsZXIsXG4gIE9uQmVmb3JlQ3JlYXRlU3RyZWFtSGFuZGxlcixcbiAgT25TdHJlYW1FeHRyYWN0ZWRIYW5kbGVyLFxuICBRdWV1ZVJlcGVhdE1vZGUgfSBmcm9tXG4nLi9HdWlsZFF1ZXVlJztcbmltcG9ydCB7IGdldEdsb2JhbFJlZ2lzdHJ5IH0gZnJvbSAnLi4vdXRpbHMvX19pbnRlcm5hbF9fJztcbmltcG9ydCB7IE5vR3VpbGRFcnJvciwgTm9HdWlsZFF1ZXVlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgRmlsdGVyc05hbWUgfSBmcm9tICcuLi9mYWJyaWMnO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGludGVyZmFjZSBHdWlsZE5vZGVDcmVhdGVPcHRpb25zPFQgPSBhbnk+IHtcbiAgc3RyYXRlZ3k/OiBRdWV1ZVN0cmF0ZWd5O1xuICB2b2x1bWU/OiBudW1iZXI7XG4gIGVxdWFsaXplcj86IEVxdWFsaXplckJhbmRbXTtcbiAgYV9maWx0ZXI/OiBQQ01GaWx0ZXJzW107XG4gIGJpcXVhZD86IEJpcXVhZEZpbHRlcnM7XG4gIHJlc2FtcGxlcj86IG51bWJlcjtcbiAgZGlzYWJsZUhpc3Rvcnk/OiBib29sZWFuO1xuICBvbkJlZm9yZUNyZWF0ZVN0cmVhbT86IE9uQmVmb3JlQ3JlYXRlU3RyZWFtSGFuZGxlcjtcbiAgb25BZnRlckNyZWF0ZVN0cmVhbT86IE9uQWZ0ZXJDcmVhdGVTdHJlYW1IYW5kbGVyO1xuICBvblN0cmVhbUV4dHJhY3RlZD86IE9uU3RyZWFtRXh0cmFjdGVkSGFuZGxlcjtcbiAgcmVwZWF0TW9kZT86IFF1ZXVlUmVwZWF0TW9kZTtcbiAgcGF1c2VPbkVtcHR5PzogYm9vbGVhbjtcbiAgbGVhdmVPbkVtcHR5PzogYm9vbGVhbjtcbiAgbGVhdmVPbkVtcHR5Q29vbGRvd24/OiBudW1iZXI7XG4gIGxlYXZlT25FbmQ/OiBib29sZWFuO1xuICBsZWF2ZU9uRW5kQ29vbGRvd24/OiBudW1iZXI7XG4gIGxlYXZlT25TdG9wPzogYm9vbGVhbjtcbiAgbGVhdmVPblN0b3BDb29sZG93bj86IG51bWJlcjtcbiAgbWV0YWRhdGE/OiBUIHwgbnVsbDtcbiAgc2VsZkRlYWY/OiBib29sZWFuO1xuICBjb25uZWN0aW9uVGltZW91dD86IG51bWJlcjtcbiAgZGVmYXVsdEZGbXBlZ0ZpbHRlcnM/OiBGaWx0ZXJzTmFtZVtdO1xuICBidWZmZXJpbmdUaW1lb3V0PzogbnVtYmVyO1xuICBub0VtaXRJbnNlcnQ/OiBib29sZWFuO1xuICBtYXhTaXplPzogbnVtYmVyO1xuICBtYXhIaXN0b3J5U2l6ZT86IG51bWJlcjtcbiAgcHJlZmVyQnJpZGdlZE1ldGFkYXRhPzogYm9vbGVhbjtcbiAgZGlzYWJsZVZvbHVtZT86IGJvb2xlYW47XG4gIGRpc2FibGVFcXVhbGl6ZXI/OiBib29sZWFuO1xuICBkaXNhYmxlRmlsdGVyZXI/OiBib29sZWFuO1xuICBkaXNhYmxlQmlxdWFkPzogYm9vbGVhbjtcbiAgZGlzYWJsZVJlc2FtcGxlcj86IGJvb2xlYW47XG4gIGRpc2FibGVDb21wcmVzc29yPzogYm9vbGVhbjtcbiAgZGlzYWJsZVNlZWtlcj86IGJvb2xlYW47XG4gIGRpc2FibGVSZXZlcmI/OiBib29sZWFuO1xuICBkaXNhYmxlRmFsbGJhY2tTdHJlYW0/OiBib29sZWFuO1xuICBlbmFibGVTdHJlYW1JbnRlcmNlcHRvcj86IGJvb2xlYW47XG4gIHZlcmlmeUZhbGxiYWNrU3RyZWFtPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IHR5cGUgTm9kZVJlc29sdmFibGUgPSBHdWlsZFF1ZXVlIHwgR3VpbGRSZXNvbHZhYmxlO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGNsYXNzIEd1aWxkTm9kZU1hbmFnZXI8TWV0YSA9IGFueT4ge1xuICBwdWJsaWMgY2FjaGUgPSBuZXcgQ29sbGVjdGlvbjxzdHJpbmcsIEd1aWxkUXVldWU+KCk7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcGxheWVyOiBQbGF5ZXIpIHt9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBndWlsZCBxdWV1ZSBpZiBpdCBkb2VzIG5vdCBleGlzdFxuICAgKiBAcGFyYW0gZ3VpbGQgVGhlIGd1aWxkIHdoaWNoIHdpbGwgYmUgdGhlIG93bmVyIG9mIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gb3B0aW9ucyBRdWV1ZSBpbml0aWFsaXplciBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgY3JlYXRlPFQgPSBNZXRhPihcbiAgZ3VpbGQ6IEd1aWxkUmVzb2x2YWJsZSxcbiAgb3B0aW9uczogR3VpbGROb2RlQ3JlYXRlT3B0aW9uczxUPiA9IHt9KVxuICA6IEd1aWxkUXVldWU8VD4ge1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMucGxheWVyLmNsaWVudC5ndWlsZHMucmVzb2x2ZShndWlsZCk7XG4gICAgaWYgKCFzZXJ2ZXIpIHtcbiAgICAgIHRocm93IG5ldyBOb0d1aWxkRXJyb3IoJ0ludmFsaWQgb3IgdW5rbm93biBndWlsZCcpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNhY2hlLmhhcyhzZXJ2ZXIuaWQpKSB7XG4gICAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQoc2VydmVyLmlkKSBhcyBHdWlsZFF1ZXVlPFQ+O1xuICAgIH1cblxuICAgIG9wdGlvbnMuc3RyYXRlZ3kgPz89ICdGSUZPJztcbiAgICBvcHRpb25zLnZvbHVtZSA/Pz0gMTAwO1xuICAgIG9wdGlvbnMuZXF1YWxpemVyID8/PSBbXTtcbiAgICBvcHRpb25zLmFfZmlsdGVyID8/PSBbXTtcbiAgICBvcHRpb25zLmRpc2FibGVIaXN0b3J5ID8/PSBmYWxzZTtcbiAgICBvcHRpb25zLmxlYXZlT25FbXB0eSA/Pz0gdHJ1ZTtcbiAgICBvcHRpb25zLmxlYXZlT25FbXB0eUNvb2xkb3duID8/PSAwO1xuICAgIG9wdGlvbnMubGVhdmVPbkVuZCA/Pz0gdHJ1ZTtcbiAgICBvcHRpb25zLmxlYXZlT25FbmRDb29sZG93biA/Pz0gMDtcbiAgICBvcHRpb25zLmxlYXZlT25TdG9wID8/PSB0cnVlO1xuICAgIG9wdGlvbnMubGVhdmVPblN0b3BDb29sZG93biA/Pz0gMDtcbiAgICBvcHRpb25zLnJlc2FtcGxlciA/Pz0gNDgwMDA7XG4gICAgb3B0aW9ucy5zZWxmRGVhZiA/Pz0gdHJ1ZTtcbiAgICBvcHRpb25zLmNvbm5lY3Rpb25UaW1lb3V0ID8/PSB0aGlzLnBsYXllci5vcHRpb25zLmNvbm5lY3Rpb25UaW1lb3V0O1xuICAgIG9wdGlvbnMuYnVmZmVyaW5nVGltZW91dCA/Pz0gMTAwMDtcbiAgICBvcHRpb25zLm1heFNpemUgPz89IEluZmluaXR5O1xuICAgIG9wdGlvbnMubWF4SGlzdG9yeVNpemUgPz89IEluZmluaXR5O1xuICAgIG9wdGlvbnMucHJlZmVyQnJpZGdlZE1ldGFkYXRhID8/PSB0cnVlO1xuICAgIG9wdGlvbnMucGF1c2VPbkVtcHR5ID8/PSB0cnVlO1xuXG4gICAgLy8gdG9kbyh0d2xpdGUpOiBtYXliZSBkaXNhYmxlIHRoZXNlIGJ5IGRlZmF1bHQ/XG4gICAgb3B0aW9ucy5kaXNhYmxlQmlxdWFkID8/PSBmYWxzZTtcbiAgICBvcHRpb25zLmRpc2FibGVFcXVhbGl6ZXIgPz89IGZhbHNlO1xuICAgIG9wdGlvbnMuZGlzYWJsZUZpbHRlcmVyID8/PSBmYWxzZTtcbiAgICBvcHRpb25zLmRpc2FibGVWb2x1bWUgPz89IGZhbHNlO1xuICAgIG9wdGlvbnMuZGlzYWJsZVJlc2FtcGxlciA/Pz0gZmFsc2U7XG4gICAgb3B0aW9ucy5kaXNhYmxlQ29tcHJlc3NvciA/Pz0gdHJ1ZTtcbiAgICBvcHRpb25zLmRpc2FibGVTZWVrZXIgPz89IHRydWU7XG4gICAgb3B0aW9ucy5kaXNhYmxlUmV2ZXJiID8/PSB0cnVlO1xuXG4gICAgb3B0aW9ucy5kaXNhYmxlRmFsbGJhY2tTdHJlYW0gPz89IGZhbHNlO1xuICAgIG9wdGlvbnMuZW5hYmxlU3RyZWFtSW50ZXJjZXB0b3IgPz89IGZhbHNlO1xuICAgIG9wdGlvbnMudmVyaWZ5RmFsbGJhY2tTdHJlYW0gPz89IGZhbHNlO1xuXG4gICAgaWYgKFxuICAgIGdldEdsb2JhbFJlZ2lzdHJ5KCkuaGFzKCdAW29uU3RyZWFtRXh0cmFjdGVkXScpICYmXG4gICAgIW9wdGlvbnMub25TdHJlYW1FeHRyYWN0ZWQpXG4gICAge1xuICAgICAgb3B0aW9ucy5vblN0cmVhbUV4dHJhY3RlZCA9IGdldEdsb2JhbFJlZ2lzdHJ5KCkuZ2V0KFxuICAgICAgICAnQFtvblN0cmVhbUV4dHJhY3RlZF0nXG4gICAgICApIGFzIE9uU3RyZWFtRXh0cmFjdGVkSGFuZGxlcjtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgZ2V0R2xvYmFsUmVnaXN0cnkoKS5oYXMoJ0Bbb25CZWZvcmVDcmVhdGVTdHJlYW1dJykgJiZcbiAgICAhb3B0aW9ucy5vbkJlZm9yZUNyZWF0ZVN0cmVhbSlcbiAgICB7XG4gICAgICBvcHRpb25zLm9uQmVmb3JlQ3JlYXRlU3RyZWFtID0gZ2V0R2xvYmFsUmVnaXN0cnkoKS5nZXQoXG4gICAgICAgICdAW29uQmVmb3JlQ3JlYXRlU3RyZWFtXSdcbiAgICAgICkgYXMgT25CZWZvcmVDcmVhdGVTdHJlYW1IYW5kbGVyO1xuICAgIH1cblxuICAgIGlmIChcbiAgICBnZXRHbG9iYWxSZWdpc3RyeSgpLmhhcygnQFtvbkFmdGVyQ3JlYXRlU3RyZWFtXScpICYmXG4gICAgIW9wdGlvbnMub25BZnRlckNyZWF0ZVN0cmVhbSlcbiAgICB7XG4gICAgICBvcHRpb25zLm9uQWZ0ZXJDcmVhdGVTdHJlYW0gPSBnZXRHbG9iYWxSZWdpc3RyeSgpLmdldChcbiAgICAgICAgJ0Bbb25BZnRlckNyZWF0ZVN0cmVhbV0nXG4gICAgICApIGFzIE9uQWZ0ZXJDcmVhdGVTdHJlYW1IYW5kbGVyO1xuICAgIH1cblxuICAgIGNvbnN0IHF1ZXVlID0gbmV3IEd1aWxkUXVldWU8VD4odGhpcy5wbGF5ZXIsIHtcbiAgICAgIGd1aWxkOiBzZXJ2ZXIsXG4gICAgICBxdWV1ZVN0cmF0ZWd5OiBvcHRpb25zLnN0cmF0ZWd5LFxuICAgICAgdm9sdW1lOiBvcHRpb25zLnZvbHVtZSxcbiAgICAgIGVxdWFsaXplcjogb3B0aW9ucy5lcXVhbGl6ZXIsXG4gICAgICBmaWx0ZXJlcjogb3B0aW9ucy5hX2ZpbHRlcixcbiAgICAgIGJpcXVhZDogb3B0aW9ucy5iaXF1YWQsXG4gICAgICByZXNhbXBsZXI6IG9wdGlvbnMucmVzYW1wbGVyLFxuICAgICAgZGlzYWJsZUhpc3Rvcnk6IG9wdGlvbnMuZGlzYWJsZUhpc3RvcnksXG4gICAgICBvbkJlZm9yZUNyZWF0ZVN0cmVhbTogb3B0aW9ucy5vbkJlZm9yZUNyZWF0ZVN0cmVhbSxcbiAgICAgIG9uQWZ0ZXJDcmVhdGVTdHJlYW06IG9wdGlvbnMub25BZnRlckNyZWF0ZVN0cmVhbSxcbiAgICAgIG9uU3RyZWFtRXh0cmFjdGVkOiBvcHRpb25zLm9uU3RyZWFtRXh0cmFjdGVkLFxuICAgICAgcmVwZWF0TW9kZTogb3B0aW9ucy5yZXBlYXRNb2RlLFxuICAgICAgbGVhdmVPbkVtcHR5OiBvcHRpb25zLmxlYXZlT25FbXB0eSxcbiAgICAgIGxlYXZlT25FbXB0eUNvb2xkb3duOiBvcHRpb25zLmxlYXZlT25FbXB0eUNvb2xkb3duLFxuICAgICAgbGVhdmVPbkVuZDogb3B0aW9ucy5sZWF2ZU9uRW5kLFxuICAgICAgbGVhdmVPbkVuZENvb2xkb3duOiBvcHRpb25zLmxlYXZlT25FbmRDb29sZG93bixcbiAgICAgIGxlYXZlT25TdG9wOiBvcHRpb25zLmxlYXZlT25TdG9wLFxuICAgICAgbGVhdmVPblN0b3BDb29sZG93bjogb3B0aW9ucy5sZWF2ZU9uU3RvcENvb2xkb3duLFxuICAgICAgbWV0YWRhdGE6IG9wdGlvbnMubWV0YWRhdGEsXG4gICAgICBjb25uZWN0aW9uVGltZW91dDogb3B0aW9ucy5jb25uZWN0aW9uVGltZW91dCA/PyAxMjBfMDAwLFxuICAgICAgc2VsZkRlYWY6IG9wdGlvbnMuc2VsZkRlYWYsXG4gICAgICBmZm1wZWdGaWx0ZXJzOiBvcHRpb25zLmRlZmF1bHRGRm1wZWdGaWx0ZXJzID8/IFtdLFxuICAgICAgYnVmZmVyaW5nVGltZW91dDogb3B0aW9ucy5idWZmZXJpbmdUaW1lb3V0LFxuICAgICAgbm9FbWl0SW5zZXJ0OiBvcHRpb25zLm5vRW1pdEluc2VydCA/PyBmYWxzZSxcbiAgICAgIHByZWZlckJyaWRnZWRNZXRhZGF0YTogb3B0aW9ucy5wcmVmZXJCcmlkZ2VkTWV0YWRhdGEsXG4gICAgICBtYXhIaXN0b3J5U2l6ZTogb3B0aW9ucy5tYXhIaXN0b3J5U2l6ZSxcbiAgICAgIG1heFNpemU6IG9wdGlvbnMubWF4U2l6ZSxcbiAgICAgIHBhdXNlT25FbXB0eTogb3B0aW9ucy5wYXVzZU9uRW1wdHksXG4gICAgICBkaXNhYmxlQmlxdWFkOiBvcHRpb25zLmRpc2FibGVCaXF1YWQsXG4gICAgICBkaXNhYmxlRXF1YWxpemVyOiBvcHRpb25zLmRpc2FibGVFcXVhbGl6ZXIsXG4gICAgICBkaXNhYmxlRmlsdGVyZXI6IG9wdGlvbnMuZGlzYWJsZUZpbHRlcmVyLFxuICAgICAgZGlzYWJsZVJlc2FtcGxlcjogb3B0aW9ucy5kaXNhYmxlUmVzYW1wbGVyLFxuICAgICAgZGlzYWJsZVZvbHVtZTogb3B0aW9ucy5kaXNhYmxlVm9sdW1lLFxuICAgICAgZGlzYWJsZUZhbGxiYWNrU3RyZWFtOiBvcHRpb25zLmRpc2FibGVGYWxsYmFja1N0cmVhbSxcbiAgICAgIGVuYWJsZVN0cmVhbUludGVyY2VwdG9yOiBvcHRpb25zLmVuYWJsZVN0cmVhbUludGVyY2VwdG9yLFxuICAgICAgdmVyaWZ5RmFsbGJhY2tTdHJlYW06IG9wdGlvbnMudmVyaWZ5RmFsbGJhY2tTdHJlYW0sXG4gICAgICBkaXNhYmxlQ29tcHJlc3Nvcjogb3B0aW9ucy5kaXNhYmxlQ29tcHJlc3NvcixcbiAgICAgIGRpc2FibGVTZWVrZXI6IG9wdGlvbnMuZGlzYWJsZVNlZWtlcixcbiAgICAgIGRpc2FibGVSZXZlcmI6IG9wdGlvbnMuZGlzYWJsZVJldmVyYlxuICAgIH0pO1xuXG4gICAgdGhpcy5jYWNoZS5zZXQoc2VydmVyLmlkLCBxdWV1ZSk7XG5cbiAgICByZXR1cm4gcXVldWU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGV4aXN0aW5nIHF1ZXVlXG4gICAqIEBwYXJhbSBub2RlIFF1ZXVlIHJlc29sdmFibGVcbiAgICovXG4gIHB1YmxpYyBnZXQ8VCA9IE1ldGE+KG5vZGU6IE5vZGVSZXNvbHZhYmxlKSB7XG4gICAgY29uc3QgcXVldWUgPSB0aGlzLnJlc29sdmUobm9kZSk7XG4gICAgaWYgKCFxdWV1ZSkgcmV0dXJuIG51bGw7XG5cbiAgICByZXR1cm4gdGhpcy5jYWNoZS5nZXQocXVldWUuaWQpIGFzIEd1aWxkUXVldWU8VD4gfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhIHF1ZXVlIGV4aXN0c1xuICAgKiBAcGFyYW0gbm9kZSBRdWV1ZSByZXNvbHZhYmxlXG4gICAqL1xuICBwdWJsaWMgaGFzKG5vZGU6IE5vZGVSZXNvbHZhYmxlKSB7XG4gICAgY29uc3QgaWQgPVxuICAgIG5vZGUgaW5zdGFuY2VvZiBHdWlsZFF1ZXVlID9cbiAgICBub2RlLmlkIDpcbiAgICB0aGlzLnBsYXllci5jbGllbnQuZ3VpbGRzLnJlc29sdmVJZChub2RlKSE7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGUuaGFzKGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgcXVldWVcbiAgICogQHBhcmFtIG5vZGUgUXVldWUgcmVzb2x2YWJsZVxuICAgKi9cbiAgcHVibGljIGRlbGV0ZShub2RlOiBOb2RlUmVzb2x2YWJsZSkge1xuICAgIGNvbnN0IHF1ZXVlID0gdGhpcy5yZXNvbHZlKG5vZGUpO1xuICAgIGlmICghcXVldWUpIHtcbiAgICAgIHRocm93IG5ldyBOb0d1aWxkUXVldWVFcnJvcignQ2Fubm90IGRlbGV0ZSBub24tZXhpc3RpbmcgcXVldWUnKTtcbiAgICB9XG5cbiAgICBxdWV1ZS5zZXRUcmFuc2l0aW9uaW5nKHRydWUpO1xuICAgIHF1ZXVlLm5vZGUuc3RvcCh0cnVlKTtcbiAgICAvLyBAdHMtaWdub3JlXG4gICAgcXVldWUuY29ubmVjdGlvbj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcXVldWUuZGlzcGF0Y2hlcj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgcXVldWUuZGlzcGF0Y2hlcj8uZGlzY29ubmVjdCgpO1xuICAgIHF1ZXVlLnRpbWVvdXRzLmZvckVhY2goKHRtKSA9PiBjbGVhclRpbWVvdXQodG0pKTtcbiAgICBxdWV1ZS5oaXN0b3J5LmNsZWFyKCk7XG4gICAgcXVldWUudHJhY2tzLmNsZWFyKCk7XG5cbiAgICByZXR1cm4gdGhpcy5jYWNoZS5kZWxldGUocXVldWUuaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgcXVldWVcbiAgICogQHBhcmFtIG5vZGUgUXVldWUgcmVzb2x2YWJsZVxuICAgKi9cbiAgcHVibGljIHJlc29sdmU8VCA9IE1ldGE+KG5vZGU6IE5vZGVSZXNvbHZhYmxlKTogR3VpbGRRdWV1ZTxUPiB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBHdWlsZFF1ZXVlKSB7XG4gICAgICByZXR1cm4gbm9kZSBhcyBHdWlsZFF1ZXVlPFQ+O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChcbiAgICAgIHRoaXMucGxheWVyLmNsaWVudC5ndWlsZHMucmVzb2x2ZUlkKG5vZGUpIVxuICAgICkgYXMgR3VpbGRRdWV1ZTxUPjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIHF1ZXVlIGlkXG4gICAqIEBwYXJhbSBub2RlIFF1ZXVlIHJlc29sdmFibGVcbiAgICovXG4gIHB1YmxpYyByZXNvbHZlSWQobm9kZTogTm9kZVJlc29sdmFibGUpIHtcbiAgICBjb25zdCBxID0gdGhpcy5yZXNvbHZlKG5vZGUpO1xuICAgIHJldHVybiBxPy5pZCB8fCBudWxsO1xuICB9XG59IiwgImltcG9ydCB7IFBsYXllciwgUGxheWVyTm9kZUluaXRpYWxpemVyT3B0aW9ucywgVHJhY2tMaWtlIH0gZnJvbSAnLi4vUGxheWVyJztcbmltcG9ydCB7XG4gIENoYW5uZWxUeXBlLFxuICBHdWlsZCxcbiAgR3VpbGRWb2ljZUNoYW5uZWxSZXNvbHZhYmxlLFxuICBWb2ljZUJhc2VkQ2hhbm5lbCxcbiAgVm9pY2VTdGF0ZSB9IGZyb21cbidkaXNjb3JkLmpzJztcbmltcG9ydCB7IENvbGxlY3Rpb24sIFF1ZXVlLCBRdWV1ZVN0cmF0ZWd5IH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL3V0aWxzJztcbmltcG9ydCB7XG4gIEJpcXVhZEZpbHRlcnMsXG4gIENvbW1vblJlc2FtcGxlckZpbHRlclByZXNldCxcbiAgQ29tcHJlc3NvclBhcmFtZXRlcnMsXG4gIEVxdWFsaXplckJhbmQsXG4gIFBDTUZpbHRlcnMsXG4gIFJldmVyYlBhcmFtZXRlcnMsXG4gIFNlZWtlclBhcmFtZXRlcnMgfSBmcm9tXG4nQGRpc2NvcmQtcGxheWVyL2VxdWFsaXplcic7XG5pbXBvcnQgeyBUcmFjaywgVHJhY2tSZXNvbHZhYmxlIH0gZnJvbSAnLi4vZmFicmljL1RyYWNrJztcbmltcG9ydCB7IFN0cmVhbURpc3BhdGNoZXIgfSBmcm9tICcuLi9zdHJlYW0vU3RyZWFtRGlzcGF0Y2hlcic7XG5pbXBvcnQge1xuICB0eXBlIEF1ZGlvUGxheWVyLFxuICBBdWRpb1Jlc291cmNlLFxuICBTdHJlYW1UeXBlLFxuICBWb2ljZUNvbm5lY3Rpb24sXG4gIFZvaWNlQ29ubmVjdGlvblN0YXR1cyB9IGZyb21cbidkaXNjb3JkLXZvaXAnO1xuaW1wb3J0IHsgVXRpbCwgVkFMSURBVEVfUVVFVUVfQ0FQIH0gZnJvbSAnLi4vdXRpbHMvVXRpbCc7XG5pbXBvcnQgeyBQbGF5bGlzdCB9IGZyb20gJy4uL2ZhYnJpYy9QbGF5bGlzdCc7XG5pbXBvcnQgeyBHdWlsZFF1ZXVlSGlzdG9yeSB9IGZyb20gJy4vR3VpbGRRdWV1ZUhpc3RvcnknO1xuaW1wb3J0IHsgR3VpbGRRdWV1ZVBsYXllck5vZGUsIFN0cmVhbUNvbmZpZyB9IGZyb20gJy4vR3VpbGRRdWV1ZVBsYXllck5vZGUnO1xuaW1wb3J0IHsgR3VpbGRRdWV1ZUF1ZGlvRmlsdGVycyB9IGZyb20gJy4vR3VpbGRRdWV1ZUF1ZGlvRmlsdGVycyc7XG5pbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBzZXRUaW1lb3V0IH0gZnJvbSAndGltZXJzJztcbmltcG9ydCB7IEd1aWxkUXVldWVTdGF0aXN0aWNzIH0gZnJvbSAnLi9HdWlsZFF1ZXVlU3RhdGlzdGljcyc7XG5pbXBvcnQgeyBUeXBlVXRpbCB9IGZyb20gJy4uL3V0aWxzL1R5cGVVdGlsJztcbmltcG9ydCB7IEFzeW5jUXVldWUgfSBmcm9tICcuLi91dGlscy9Bc3luY1F1ZXVlJztcbmltcG9ydCB7XG4gIEludmFsaWRBcmdUeXBlRXJyb3IsXG4gIE5vVm9pY2VDaGFubmVsRXJyb3IsXG4gIE5vVm9pY2VDb25uZWN0aW9uRXJyb3IsXG4gIE91dE9mUmFuZ2VFcnJvcixcbiAgVm9pY2VDb25uZWN0aW9uRGVzdHJveWVkRXJyb3IgfSBmcm9tXG4nLi4vZXJyb3JzJztcbmltcG9ydCB7IFN5bmNlZEx5cmljc1Byb3ZpZGVyIH0gZnJvbSAnLi9TeW5jZWRMeXJpY3NQcm92aWRlcic7XG5pbXBvcnQgeyBMcmNHZXRSZXN1bHQsIExyY1NlYXJjaFJlc3VsdCB9IGZyb20gJy4uL2xyY2xpYi9McmNMaWInO1xuaW1wb3J0IHsgRmlsdGVyc05hbWUgfSBmcm9tICcuLi9mYWJyaWMnO1xuaW1wb3J0IHsgU2VhcmNoUXVlcnlUeXBlIH0gZnJvbSAnLi4vdXRpbHMvUXVlcnlSZXNvbHZlcic7XG5pbXBvcnQgdHlwZSB7IEV4dHJhY3RvclN0cmVhbWFibGUgfSBmcm9tICcuLi9leHRyYWN0b3JzL0Jhc2VFeHRyYWN0b3InO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGludGVyZmFjZSBHdWlsZE5vZGVJbml0PE1ldGEgPSBhbnk+IHtcbiAgZ3VpbGQ6IEd1aWxkO1xuICBxdWV1ZVN0cmF0ZWd5OiBRdWV1ZVN0cmF0ZWd5O1xuICBlcXVhbGl6ZXI6IEVxdWFsaXplckJhbmRbXSB8IGJvb2xlYW47XG4gIHZvbHVtZTogbnVtYmVyIHwgYm9vbGVhbjtcbiAgYmlxdWFkOiBCaXF1YWRGaWx0ZXJzIHwgYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgcmVzYW1wbGVyOiBudW1iZXIgfCBib29sZWFuO1xuICBmaWx0ZXJlcjogUENNRmlsdGVyc1tdIHwgYm9vbGVhbjtcbiAgZmZtcGVnRmlsdGVyczogRmlsdGVyc05hbWVbXTtcbiAgZGlzYWJsZUhpc3Rvcnk6IGJvb2xlYW47XG4gIG9uQmVmb3JlQ3JlYXRlU3RyZWFtPzogT25CZWZvcmVDcmVhdGVTdHJlYW1IYW5kbGVyO1xuICBvbkFmdGVyQ3JlYXRlU3RyZWFtPzogT25BZnRlckNyZWF0ZVN0cmVhbUhhbmRsZXI7XG4gIG9uU3RyZWFtRXh0cmFjdGVkPzogT25TdHJlYW1FeHRyYWN0ZWRIYW5kbGVyO1xuICByZXBlYXRNb2RlPzogUXVldWVSZXBlYXRNb2RlO1xuICBsZWF2ZU9uRW1wdHk6IGJvb2xlYW47XG4gIGxlYXZlT25FbXB0eUNvb2xkb3duOiBudW1iZXI7XG4gIGxlYXZlT25FbmQ6IGJvb2xlYW47XG4gIGxlYXZlT25FbmRDb29sZG93bjogbnVtYmVyO1xuICBsZWF2ZU9uU3RvcDogYm9vbGVhbjtcbiAgbGVhdmVPblN0b3BDb29sZG93bjogbnVtYmVyO1xuICBjb25uZWN0aW9uVGltZW91dDogbnVtYmVyO1xuICBzZWxmRGVhZj86IGJvb2xlYW47XG4gIG1ldGFkYXRhPzogTWV0YSB8IG51bGw7XG4gIGJ1ZmZlcmluZ1RpbWVvdXQ6IG51bWJlcjtcbiAgbm9FbWl0SW5zZXJ0OiBib29sZWFuO1xuICBtYXhTaXplPzogbnVtYmVyO1xuICBtYXhIaXN0b3J5U2l6ZT86IG51bWJlcjtcbiAgcHJlZmVyQnJpZGdlZE1ldGFkYXRhOiBib29sZWFuO1xuICBwYXVzZU9uRW1wdHk/OiBib29sZWFuO1xuICBkaXNhYmxlVm9sdW1lOiBib29sZWFuO1xuICBkaXNhYmxlRXF1YWxpemVyOiBib29sZWFuO1xuICBkaXNhYmxlRmlsdGVyZXI6IGJvb2xlYW47XG4gIGRpc2FibGVCaXF1YWQ6IGJvb2xlYW47XG4gIGRpc2FibGVSZXNhbXBsZXI6IGJvb2xlYW47XG4gIGRpc2FibGVDb21wcmVzc29yOiBib29sZWFuO1xuICBkaXNhYmxlUmV2ZXJiOiBib29sZWFuO1xuICBkaXNhYmxlU2Vla2VyOiBib29sZWFuO1xuICBkaXNhYmxlRmFsbGJhY2tTdHJlYW06IGJvb2xlYW47XG4gIGVuYWJsZVN0cmVhbUludGVyY2VwdG9yOiBib29sZWFuO1xuICB2ZXJpZnlGYWxsYmFja1N0cmVhbTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWb2ljZUNvbm5lY3RDb25maWcge1xuICBkZWFmPzogYm9vbGVhbjtcbiAgdGltZW91dD86IG51bWJlcjtcbiAgZ3JvdXA/OiBzdHJpbmc7XG4gIGF1ZGlvUGxheWVyPzogQXVkaW9QbGF5ZXI7XG4gIGRhdmVFbmNyeXB0aW9uPzogYm9vbGVhbjtcbiAgZGVjcnlwdGlvbkZhaWx1cmVUb2xlcmFuY2U/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9zdFByb2Nlc3NlZFJlc3VsdCB7XG4gIHN0cmVhbTogUmVhZGFibGU7XG4gIHR5cGU6IFN0cmVhbVR5cGU7XG59XG5cbmV4cG9ydCB0eXBlIE9uQmVmb3JlQ3JlYXRlU3RyZWFtSGFuZGxlciA9IChcbnRyYWNrOiBUcmFjayxcbnF1ZXJ5VHlwZTogU2VhcmNoUXVlcnlUeXBlLFxucXVldWU6IEd1aWxkUXVldWUpXG49PiBQcm9taXNlPFJlYWRhYmxlIHwgbnVsbD47XG5cbmV4cG9ydCB0eXBlIE9uU3RyZWFtRXh0cmFjdGVkSGFuZGxlciA9IChcbnN0cmVhbTogUmVhZGFibGUgfCBFeHRyYWN0b3JTdHJlYW1hYmxlIHwgc3RyaW5nLFxudHJhY2s6IFRyYWNrLFxucXVldWU6IEd1aWxkUXVldWUpXG49PiBQcm9taXNlPFJlYWRhYmxlIHwgRXh0cmFjdG9yU3RyZWFtYWJsZSB8IHN0cmluZz47XG5cbmV4cG9ydCB0eXBlIE9uQWZ0ZXJDcmVhdGVTdHJlYW1IYW5kbGVyPFQgPSB1bmtub3duPiA9IChcbnN0cmVhbTogUmVhZGFibGUsXG5xdWV1ZTogR3VpbGRRdWV1ZSxcbnRyYWNrOiBUcmFjazxUPilcbj0+IFByb21pc2U8UG9zdFByb2Nlc3NlZFJlc3VsdCB8IG51bGw+O1xuXG5leHBvcnQgdHlwZSBQbGF5ZXJUcmlnZ2VyZWRSZWFzb24gPSAnZmlsdGVycycgfCAnbm9ybWFsJztcblxuZXhwb3J0IGNvbnN0IEd1aWxkUXVldWVFdmVudCA9IHtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhdWRpbyB0cmFjayBpcyBhZGRlZCB0byB0aGUgcXVldWVcbiAgICovXG4gIEF1ZGlvVHJhY2tBZGQ6ICdhdWRpb1RyYWNrQWRkJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhdWRpbyB0cmFja3Mgd2VyZSBhZGRlZCB0byB0aGUgcXVldWVcbiAgICovXG4gIEF1ZGlvVHJhY2tzQWRkOiAnYXVkaW9UcmFja3NBZGQnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGF1ZGlvIHRyYWNrIGlzIHJlbW92ZWQgZnJvbSB0aGUgcXVldWVcbiAgICovXG4gIEF1ZGlvVHJhY2tSZW1vdmU6ICdhdWRpb1RyYWNrUmVtb3ZlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhdWRpbyB0cmFja3MgYXJlIHJlbW92ZWQgZnJvbSB0aGUgcXVldWVcbiAgICovXG4gIEF1ZGlvVHJhY2tzUmVtb3ZlOiAnYXVkaW9UcmFja3NSZW1vdmUnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgY29ubmVjdGlvbiBpcyBjcmVhdGVkXG4gICAqL1xuICBDb25uZWN0aW9uOiAnY29ubmVjdGlvbicsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSB2b2ljZSBjb25uZWN0aW9uIGlzIGRlc3Ryb3llZFxuICAgKi9cbiAgQ29ubmVjdGlvbkRlc3Ryb3llZDogJ2Nvbm5lY3Rpb25EZXN0cm95ZWQnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBib3QgaXMgZGlzY29ubmVjdGVkIGZyb20gdGhlIGNoYW5uZWxcbiAgICovXG4gIERpc2Nvbm5lY3Q6ICdkaXNjb25uZWN0JyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgcXVldWUgc2VuZHMgYSBkZWJ1ZyBpbmZvXG4gICAqL1xuICBEZWJ1ZzogJ2RlYnVnJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgcXVldWUgZW5jb3VudGVycyBlcnJvclxuICAgKi9cbiAgRXJyb3I6ICdlcnJvcicsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIHZvaWNlIGNoYW5uZWwgaXMgZW1wdHlcbiAgICovXG4gIEVtcHR5Q2hhbm5lbDogJ2VtcHR5Q2hhbm5lbCcsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIHF1ZXVlIGlzIGVtcHR5XG4gICAqL1xuICBFbXB0eVF1ZXVlOiAnZW1wdHlRdWV1ZScsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIGF1ZGlvIHBsYXllciBzdGFydHMgc3RyZWFtaW5nIGF1ZGlvIHRyYWNrXG4gICAqL1xuICBQbGF5ZXJTdGFydDogJ3BsYXllclN0YXJ0JyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgYXVkaW8gcGxheWVyIGVycm9ycyB3aGlsZSBzdHJlYW1pbmcgYXVkaW8gdHJhY2tcbiAgICovXG4gIFBsYXllckVycm9yOiAncGxheWVyRXJyb3InLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBhdWRpbyBwbGF5ZXIgZmluaXNoZXMgc3RyZWFtaW5nIGF1ZGlvIHRyYWNrXG4gICAqL1xuICBQbGF5ZXJGaW5pc2g6ICdwbGF5ZXJGaW5pc2gnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBhdWRpbyBwbGF5ZXIgc2tpcHMgY3VycmVudCB0cmFja1xuICAgKi9cbiAgUGxheWVyU2tpcDogJ3BsYXllclNraXAnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBhdWRpbyBwbGF5ZXIgaXMgdHJpZ2dlcmVkXG4gICAqL1xuICBQbGF5ZXJUcmlnZ2VyOiAncGxheWVyVHJpZ2dlcicsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIHZvaWNlIHN0YXRlIGlzIHVwZGF0ZWQuIENvbnN1bWluZyB0aGlzIGV2ZW50IG1heSBkaXNhYmxlIGRlZmF1bHQgdm9pY2Ugc3RhdGUgdXBkYXRlIGhhbmRsZXIgaWYgYFBsYXllci5pc1ZvaWNlU3RhdGVIYW5kbGVyTG9ja2VkKClgIHJldHVybnMgYGZhbHNlYC5cbiAgICovXG4gIFZvaWNlU3RhdGVVcGRhdGU6ICd2b2ljZVN0YXRlVXBkYXRlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB2b2x1bWUgaXMgdXBkYXRlZFxuICAgKi9cbiAgVm9sdW1lQ2hhbmdlOiAndm9sdW1lQ2hhbmdlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBwbGF5ZXIgaXMgcGF1c2VkXG4gICAqL1xuICBQbGF5ZXJQYXVzZTogJ3BsYXllclBhdXNlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBwbGF5ZXIgaXMgcmVzdW1lZFxuICAgKi9cbiAgUGxheWVyUmVzdW1lOiAncGxheWVyUmVzdW1lJyxcbiAgLyoqXG4gICAqIEJpcXVhZCBGaWx0ZXJzIFVwZGF0ZVxuICAgKi9cbiAgQmlxdWFkRmlsdGVyc1VwZGF0ZTogJ2JpcXVhZEZpbHRlcnNVcGRhdGUnLFxuICAvKipcbiAgICogRXF1YWxpemVyIFVwZGF0ZVxuICAgKi9cbiAgRXF1YWxpemVyVXBkYXRlOiAnZXF1YWxpemVyVXBkYXRlJyxcbiAgLyoqXG4gICAqIERTUCB1cGRhdGVcbiAgICovXG4gIERTUFVwZGF0ZTogJ2RzcFVwZGF0ZScsXG4gIC8qKlxuICAgKiBBdWRpbyBGaWx0ZXJzIFVwZGF0ZVxuICAgKi9cbiAgQXVkaW9GaWx0ZXJzVXBkYXRlOiAnYXVkaW9GaWx0ZXJzVXBkYXRlJyxcbiAgLyoqXG4gICAqIEF1ZGlvIHBsYXllciB3aWxsIHBsYXkgbmV4dCB0cmFja1xuICAgKi9cbiAgV2lsbFBsYXlUcmFjazogJ3dpbGxQbGF5VHJhY2snLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgdm9pY2UgY2hhbm5lbCBpcyByZXBvcHVsYXRlZFxuICAgKi9cbiAgQ2hhbm5lbFBvcHVsYXRlOiAnY2hhbm5lbFBvcHVsYXRlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIHF1ZXVlIGlzIHN1Y2Nlc3NmdWxseSBjcmVhdGVkXG4gICAqL1xuICBRdWV1ZUNyZWF0ZTogJ3F1ZXVlQ3JlYXRlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIHF1ZXVlIGlzIGRlbGV0ZWRcbiAgICovXG4gIFF1ZXVlRGVsZXRlOiAncXVldWVEZWxldGUnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgcXVldWUgaXMgdHJ5aW5nIHRvIGFkZCBzaW1pbGFyIHRyYWNrIGZvciBhdXRvcGxheVxuICAgKi9cbiAgV2lsbEF1dG9QbGF5OiAnd2lsbEF1dG9QbGF5JyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBzYW1wbGUgcmF0ZSBpcyB1cGRhdGVkXG4gICAqL1xuICBTYW1wbGVSYXRlVXBkYXRlOiAnc2FtcGxlUmF0ZVVwZGF0ZScsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBuYW1lZCBzYW1wbGUgcmF0ZSBmaWx0ZXIgaXMgdXBkYXRlZFxuICAgKi9cbiAgU2FtcGxlUmF0ZUZpbHRlclVwZGF0ZTogJ3NhbXBsZVJhdGVGaWx0ZXJVcGRhdGUnLFxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHJldmVyYiBmaWx0ZXIgaXMgdXBkYXRlZFxuICAgKi9cbiAgUmV2ZXJiVXBkYXRlOiAncmV2ZXJiVXBkYXRlJyxcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBjb21wcmVzc29yIGZpbHRlciBpcyB1cGRhdGVkXG4gICAqL1xuICBDb21wcmVzc29yVXBkYXRlOiAnY29tcHJlc3NvclVwZGF0ZScsXG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gc2VlayBpcyBwZXJmb3JtZWRcbiAgICovXG4gIFBsYXllclNlZWs6ICdwbGF5ZXJTZWVrJ1xufSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgR3VpbGRRdWV1ZUV2ZW50ID1cbih0eXBlb2YgR3VpbGRRdWV1ZUV2ZW50KVtrZXlvZiB0eXBlb2YgR3VpbGRRdWV1ZUV2ZW50XTtcblxuZXhwb3J0IGVudW0gVHJhY2tTa2lwUmVhc29uIHtcbiAgTm9TdHJlYW0gPSAnRVJSX05PX1NUUkVBTScsXG4gIE1hbnVhbCA9ICdNQU5VQUwnLFxuICBTRUVLX09WRVJfVEhSRVNIT0xEID0gJ1NFRUtfT1ZFUl9USFJFU0hPTEQnLFxuICBKdW1wID0gJ0pVTVBFRF9UT19BTk9USEVSX1RSQUNLJyxcbiAgU2tpcFRvID0gJ1NLSVBfVE9fQU5PVEhFUl9UUkFDSycsXG4gIEhpc3RvcnlOZXh0ID0gJ0hJU1RPUllfTkVYVF9UUkFDSycsXG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG5leHBvcnQgaW50ZXJmYWNlIEd1aWxkUXVldWVFdmVudHM8TWV0YSA9IGFueT4ge1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGF1ZGlvIHRyYWNrIGlzIGFkZGVkIHRvIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFja1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrQWRkXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgdHJhY2s6IFRyYWNrKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGF1ZGlvIHRyYWNrcyB3ZXJlIGFkZGVkIHRvIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrcyBUaGUgdHJhY2tzIGFycmF5XG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LkF1ZGlvVHJhY2tzQWRkXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgdHJhY2s6IFRyYWNrW10pXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYXVkaW8gdHJhY2sgaXMgcmVtb3ZlZCBmcm9tIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFja1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrUmVtb3ZlXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgdHJhY2s6IFRyYWNrKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGF1ZGlvIHRyYWNrcyBhcmUgcmVtb3ZlZCBmcm9tIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFja1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrc1JlbW92ZV06IChcbiAgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4sXG4gIHRyYWNrOiBUcmFja1tdKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgY29ubmVjdGlvbiBpcyBjcmVhdGVkXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5Db25uZWN0aW9uXTogKHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+KSA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGEgY29ubmVjdGlvbiBpcyBkZXN0cm95ZWRcbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LkNvbm5lY3Rpb25EZXN0cm95ZWRdOiAocXVldWU6IEd1aWxkUXVldWU8TWV0YT4pID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIGJvdCBpcyBkaXNjb25uZWN0ZWQgZnJvbSB0aGUgY2hhbm5lbFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuRGlzY29ubmVjdF06IChxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPikgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgcXVldWUgc2VuZHMgYSBkZWJ1ZyBpbmZvXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgZGVidWcgbWVzc2FnZVxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5EZWJ1Z106IChcbiAgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4sXG4gIG1lc3NhZ2U6IHN0cmluZylcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgcXVldWUgZW5jb3VudGVycyBlcnJvclxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIGVycm9yIFRoZSBlcnJvclxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5FcnJvcl06IChxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPiwgZXJyb3I6IEVycm9yKSA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSB2b2ljZSBjaGFubmVsIGlzIGVtcHR5XG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5FbXB0eUNoYW5uZWxdOiAocXVldWU6IEd1aWxkUXVldWU8TWV0YT4pID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIHF1ZXVlIGlzIGVtcHR5XG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5FbXB0eVF1ZXVlXTogKHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+KSA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBhdWRpbyBwbGF5ZXIgc3RhcnRzIHN0cmVhbWluZyBhdWRpbyB0cmFja1xuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayB0aGF0IGlzIGJlaW5nIHN0cmVhbWVkXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LlBsYXllclN0YXJ0XTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgdHJhY2s6IFRyYWNrKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHRoZSBhdWRpbyBwbGF5ZXIgZXJyb3JzIHdoaWxlIHN0cmVhbWluZyBhdWRpbyB0cmFja1xuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIGVycm9yIFRoZSBlcnJvclxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRoYXQgaXMgYmVpbmcgc3RyZWFtZWRcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuUGxheWVyRXJyb3JdOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICBlcnJvcjogRXJyb3IsXG4gIHRyYWNrOiBUcmFjaylcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgYXVkaW8gcGxheWVyIGZpbmlzaGVzIHN0cmVhbWluZyBhdWRpbyB0cmFja1xuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayB0aGF0IHdhcyBiZWluZyBzdHJlYW1lZFxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5QbGF5ZXJGaW5pc2hdOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICB0cmFjazogVHJhY2spXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIGF1ZGlvIHBsYXllciBza2lwcyBjdXJyZW50IHRyYWNrXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRoYXQgd2FzIHNraXBwZWRcbiAgICogQHBhcmFtIHJlYXNvbiBUaGUgcmVhc29uIGZvciBza2lwcGluZ1xuICAgKiBAcGFyYW0gZGVzY3JpcHRpb24gVGhlIGRlc2NyaXB0aW9uIGZvciBza2lwcGluZ1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5QbGF5ZXJTa2lwXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgdHJhY2s6IFRyYWNrLFxuICByZWFzb246IFRyYWNrU2tpcFJlYXNvbixcbiAgZGVzY3JpcHRpb246IHN0cmluZylcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB0aGUgYXVkaW8gcGxheWVyIGlzIHRyaWdnZXJlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayB3aGljaCB3YXMgcGxheWVkIGluIHRoaXMgZXZlbnRcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuUGxheWVyVHJpZ2dlcl06IChcbiAgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4sXG4gIHRyYWNrOiBUcmFjayxcbiAgcmVhc29uOiBQbGF5ZXJUcmlnZ2VyZWRSZWFzb24pXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gdGhlIHZvaWNlIHN0YXRlIGlzIHVwZGF0ZWQuIENvbnN1bWluZyB0aGlzIGV2ZW50IG1heSBkaXNhYmxlIGRlZmF1bHQgdm9pY2Ugc3RhdGUgdXBkYXRlIGhhbmRsZXIgaWYgYFBsYXllci5pc1ZvaWNlU3RhdGVIYW5kbGVyTG9ja2VkKClgIHJldHVybnMgYGZhbHNlYC5cbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqIEBwYXJhbSBvbGRTdGF0ZSBUaGUgb2xkIHZvaWNlIHN0YXRlXG4gICAqIEBwYXJhbSBuZXdTdGF0ZSBUaGUgbmV3IHZvaWNlIHN0YXRlXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LlZvaWNlU3RhdGVVcGRhdGVdOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICBvbGRTdGF0ZTogVm9pY2VTdGF0ZSxcbiAgbmV3U3RhdGU6IFZvaWNlU3RhdGUpXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYXVkaW8gcGxheWVyIGlzIHBhdXNlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuUGxheWVyUGF1c2VdOiAocXVldWU6IEd1aWxkUXVldWU8TWV0YT4pID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYXVkaW8gcGxheWVyIGlzIHJlc3VtZWRcbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LlBsYXllclJlc3VtZV06IChxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPikgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhdWRpbyBwbGF5ZXIncyB2b2x1bWUgaXMgY2hhbmdlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIG9sZFZvbHVtZSBUaGUgb2xkIHZvbHVtZVxuICAgKiBAcGFyYW0gbmV3Vm9sdW1lIFRoZSB1cGRhdGVkIHZvbHVtZVxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5Wb2x1bWVDaGFuZ2VdOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICBvbGRWb2x1bWU6IG51bWJlcixcbiAgbmV3Vm9sdW1lOiBudW1iZXIpXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gZXF1YWxpemVyIGNvbmZpZyBpcyB1cGRhdGVkXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gb2xkRmlsdGVycyBPbGQgZmlsdGVyc1xuICAgKiBAcGFyYW0gbmV3RmlsdGVycyBOZXcgZmlsdGVyc1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5FcXVhbGl6ZXJVcGRhdGVdOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICBvbGRGaWx0ZXJzOiBFcXVhbGl6ZXJCYW5kW10sXG4gIG5ld0ZpbHRlcnM6IEVxdWFsaXplckJhbmRbXSlcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBiaXF1YWQgZmlsdGVycyBpcyB1cGRhdGVkXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gb2xkRmlsdGVycyBPbGQgZmlsdGVyc1xuICAgKiBAcGFyYW0gbmV3RmlsdGVycyBOZXcgZmlsdGVyc1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5CaXF1YWRGaWx0ZXJzVXBkYXRlXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgb2xkRmlsdGVyczogQmlxdWFkRmlsdGVycyB8IG51bGwsXG4gIG5ld0ZpbHRlcnM6IEJpcXVhZEZpbHRlcnMgfCBudWxsKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGRzcCBmaWx0ZXJzIGlzIHVwZGF0ZWRcbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqIEBwYXJhbSBvbGRGaWx0ZXJzIE9sZCBmaWx0ZXJzXG4gICAqIEBwYXJhbSBuZXdGaWx0ZXJzIE5ldyBmaWx0ZXJzXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LkRTUFVwZGF0ZV06IChcbiAgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4sXG4gIG9sZEZpbHRlcnM6IFBDTUZpbHRlcnNbXSxcbiAgbmV3RmlsdGVyczogUENNRmlsdGVyc1tdKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIGZmbXBlZyBhdWRpbyBmaWx0ZXJzIGlzIHVwZGF0ZWRcbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqIEBwYXJhbSBvbGRGaWx0ZXJzIE9sZCBmaWx0ZXJzXG4gICAqIEBwYXJhbSBuZXdGaWx0ZXJzIE5ldyBmaWx0ZXJzXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LkF1ZGlvRmlsdGVyc1VwZGF0ZV06IChcbiAgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4sXG4gIG9sZEZpbHRlcnM6IEZpbHRlcnNOYW1lW10sXG4gIG5ld0ZpbHRlcnM6IEZpbHRlcnNOYW1lW10pXG4gID0+IHVua25vd247XG5cbiAgLyoqXG4gICAqIEVtaXR0ZWQgYmVmb3JlIHN0cmVhbWluZyBhbiBhdWRpbyB0cmFjay4gVGhpcyBldmVudCBjYW4gYmUgdXNlZCB0byBtb2RpZnkgc3RyZWFtIGNvbmZpZyBiZWZvcmUgcGxheWluZyBhIHRyYWNrLlxuICAgKiBMaXN0ZW5pbmcgdG8gdGhpcyBldmVudCB3aWxsIHBhdXNlIHRoZSBleGVjdXRpb24gb2YgYXVkaW8gcGxheWVyIHVudGlsIGBkb25lKClgIGlzIGludm9rZWQuXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRoYXQgd2lsbCBiZSBzdHJlYW1lZFxuICAgKiBAcGFyYW0gY29uZmlnIENvbmZpZ3VyYXRpb25zIGZvciBzdHJlYW1pbmdcbiAgICogQHBhcmFtIGRvbmUgRG9uZSBjYWxsYmFja1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5XaWxsUGxheVRyYWNrXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgdHJhY2s6IFRyYWNrPHVua25vd24+LFxuICBjb25maWc6IFN0cmVhbUNvbmZpZyxcbiAgZG9uZTogKCkgPT4gdm9pZClcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBhIHZvaWNlIGNoYW5uZWwgaXMgcG9wdWxhdGVkXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5DaGFubmVsUG9wdWxhdGVdOiAocXVldWU6IEd1aWxkUXVldWU8TWV0YT4pID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBxdWV1ZSBpcyBzdWNjZXNzZnVsbHkgY3JlYXRlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuUXVldWVDcmVhdGVdOiAocXVldWU6IEd1aWxkUXVldWU8TWV0YT4pID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBxdWV1ZSBpcyBzdWNjZXNzZnVsbHkgZGVsZXRlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuUXVldWVEZWxldGVdOiAocXVldWU6IEd1aWxkUXVldWU8TWV0YT4pID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBxdWV1ZSBpcyB0cnlpbmcgdG8gYWRkIHNpbWlsYXIgdHJhY2sgZm9yIGF1dG9wbGF5XG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gdHJhY2tzIFRoZSBzaW1pbGFyIHRyYWNrcyB0aGF0IHdlcmUgZm91bmRcbiAgICogQHBhcmFtIGRvbmUgRG9uZSBjYWxsYmFja1xuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5XaWxsQXV0b1BsYXldOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICB0cmFja3M6IFRyYWNrW10sXG4gIGRvbmU6ICh0cmFjazogVHJhY2sgfCBudWxsKSA9PiB2b2lkKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHNhbXBsZSByYXRlIGlzIHVwZGF0ZWRcbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqIEBwYXJhbSBvbGRSYXRlIFRoZSBvbGQgc2FtcGxlIHJhdGVcbiAgICogQHBhcmFtIG5ld1JhdGUgVGhlIG5ldyBzYW1wbGUgcmF0ZVxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5TYW1wbGVSYXRlVXBkYXRlXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgb2xkUmF0ZTogbnVtYmVyLFxuICBuZXdSYXRlOiBudW1iZXIpXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gYSBuYW1lZCBzYW1wbGUgcmF0ZSBmaWx0ZXIgaXMgdXBkYXRlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIG9sZFJhdGUgVGhlIG9sZCBzYW1wbGUgcmF0ZSBmaWx0ZXJcbiAgICogQHBhcmFtIG5ld1JhdGUgVGhlIG5ldyBzYW1wbGUgcmF0ZSBmaWx0ZXJcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuU2FtcGxlUmF0ZUZpbHRlclVwZGF0ZV06IChcbiAgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4sXG4gIG9sZEZpbHRlcjogQ29tbW9uUmVzYW1wbGVyRmlsdGVyUHJlc2V0IHwgbnVsbCxcbiAgbmV3RmlsdGVyOiBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQgfCBudWxsKVxuICA9PiB1bmtub3duO1xuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHJldmVyYiBmaWx0ZXIgaXMgdXBkYXRlZFxuICAgKiBAcGFyYW0gcXVldWUgVGhlIHF1ZXVlIHdoZXJlIHRoaXMgZXZlbnQgb2NjdXJyZWRcbiAgICogQHBhcmFtIG9sZEZpbHRlciBUaGUgb2xkIHJldmVyYiBmaWx0ZXJcbiAgICogQHBhcmFtIG5ld0ZpbHRlciBUaGUgbmV3IHJldmVyYiBmaWx0ZXJcbiAgICovXG4gIFtHdWlsZFF1ZXVlRXZlbnQuUmV2ZXJiVXBkYXRlXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgb2xkRmlsdGVyOiBSZXZlcmJQYXJhbWV0ZXJzIHwgbnVsbCxcbiAgbmV3RmlsdGVyOiBSZXZlcmJQYXJhbWV0ZXJzIHwgbnVsbClcbiAgPT4gdW5rbm93bjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiBjb21wcmVzc29yIGZpbHRlciBpcyB1cGRhdGVkXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgcXVldWUgd2hlcmUgdGhpcyBldmVudCBvY2N1cnJlZFxuICAgKiBAcGFyYW0gb2xkRmlsdGVyIFRoZSBvbGQgY29tcHJlc3NvciBmaWx0ZXJcbiAgICogQHBhcmFtIG5ld0ZpbHRlciBUaGUgbmV3IGNvbXByZXNzb3IgZmlsdGVyXG4gICAqL1xuICBbR3VpbGRRdWV1ZUV2ZW50LkNvbXByZXNzb3JVcGRhdGVdOiAoXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPE1ldGE+LFxuICBvbGRGaWx0ZXI6IENvbXByZXNzb3JQYXJhbWV0ZXJzIHwgbnVsbCxcbiAgbmV3RmlsdGVyOiBDb21wcmVzc29yUGFyYW1ldGVycyB8IG51bGwpXG4gID0+IHVua25vd247XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW4gc2VlayBpcyBwZXJmb3JtZWRcbiAgICogQHBhcmFtIHF1ZXVlIFRoZSBxdWV1ZSB3aGVyZSB0aGlzIGV2ZW50IG9jY3VycmVkXG4gICAqIEBwYXJhbSBwb3NpdGlvbiBUaGUgc2VlayBwb3NpdGlvblxuICAgKi9cbiAgW0d1aWxkUXVldWVFdmVudC5QbGF5ZXJTZWVrXTogKFxuICBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPixcbiAgcGFyYW1ldGVyczogU2Vla2VyUGFyYW1ldGVycylcbiAgPT4gdW5rbm93bjtcbn1cblxuLyoqXG4gKiBUaGUgcXVldWUgcmVwZWF0IG1vZGUuIFRoaXMgY2FuIGJlIG9uZSBvZjpcbiAqIC0gT0ZGXG4gKiAtIFRSQUNLXG4gKiAtIFFVRVVFXG4gKiAtIEFVVE9QTEFZXG4gKi9cbmV4cG9ydCBjb25zdCBRdWV1ZVJlcGVhdE1vZGUgPSB7XG4gIC8qKlxuICAgKiBEaXNhYmxlIHJlcGVhdCBtb2RlLlxuICAgKi9cbiAgT0ZGOiAwLFxuICAvKipcbiAgICogUmVwZWF0IHRoZSBjdXJyZW50IHRyYWNrLlxuICAgKi9cbiAgVFJBQ0s6IDEsXG4gIC8qKlxuICAgKiBSZXBlYXQgdGhlIGVudGlyZSBxdWV1ZS5cbiAgICovXG4gIFFVRVVFOiAyLFxuICAvKipcbiAgICogV2hlbiBsYXN0IHRyYWNrIGVuZHMsIHBsYXkgc2ltaWxhciB0cmFja3MgaW4gdGhlIGZ1dHVyZSBpZiBxdWV1ZSBpcyBlbXB0eS5cbiAgICovXG4gIEFVVE9QTEFZOiAzXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBRdWV1ZVJlcGVhdE1vZGUgPVxuKHR5cGVvZiBRdWV1ZVJlcGVhdE1vZGUpW2tleW9mIHR5cGVvZiBRdWV1ZVJlcGVhdE1vZGVdO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGNsYXNzIEd1aWxkUXVldWU8TWV0YSA9IGFueT4ge1xuICAjdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAjZGVsZXRlZCA9IGZhbHNlO1xuICAjc2h1ZmZsZSA9IGZhbHNlO1xuICBwcml2YXRlIF9fY3VycmVudDogVHJhY2sgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIHRyYWNrczogUXVldWU8VHJhY2s+O1xuICBwdWJsaWMgaGlzdG9yeSA9IG5ldyBHdWlsZFF1ZXVlSGlzdG9yeTxNZXRhPih0aGlzKTtcbiAgcHVibGljIGRpc3BhdGNoZXI6IFN0cmVhbURpc3BhdGNoZXIgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIG5vZGUgPSBuZXcgR3VpbGRRdWV1ZVBsYXllck5vZGU8TWV0YT4odGhpcyk7XG4gIHB1YmxpYyBmaWx0ZXJzID0gbmV3IEd1aWxkUXVldWVBdWRpb0ZpbHRlcnM8TWV0YT4odGhpcyk7XG4gIHB1YmxpYyBvbkJlZm9yZUNyZWF0ZVN0cmVhbTogT25CZWZvcmVDcmVhdGVTdHJlYW1IYW5kbGVyID0gYXN5bmMgKCkgPT4gbnVsbDtcbiAgcHVibGljIG9uQWZ0ZXJDcmVhdGVTdHJlYW06IE9uQWZ0ZXJDcmVhdGVTdHJlYW1IYW5kbGVyID0gYXN5bmMgKHN0cmVhbSkgPT4gKHtcbiAgICBzdHJlYW0sXG4gICAgdHlwZTogU3RyZWFtVHlwZS5SYXdcbiAgfSk7XG4gIHB1YmxpYyBvblN0cmVhbUV4dHJhY3RlZDogT25TdHJlYW1FeHRyYWN0ZWRIYW5kbGVyID0gYXN5bmMgKHN0cmVhbSkgPT4gc3RyZWFtO1xuICBwdWJsaWMgcmVwZWF0TW9kZTogUXVldWVSZXBlYXRNb2RlID0gUXVldWVSZXBlYXRNb2RlLk9GRjtcbiAgcHVibGljIHRpbWVvdXRzID0gbmV3IENvbGxlY3Rpb248c3RyaW5nLCBOb2RlSlMuVGltZW91dD4oKTtcbiAgcHVibGljIHN0YXRzID0gbmV3IEd1aWxkUXVldWVTdGF0aXN0aWNzPE1ldGE+KHRoaXMpO1xuICBwdWJsaWMgdGFza3NRdWV1ZSA9IG5ldyBBc3luY1F1ZXVlKCk7XG4gIHB1YmxpYyBzeW5jZWRMeXJpY3NQcm92aWRlciA9IG5ldyBTeW5jZWRMeXJpY3NQcm92aWRlcih0aGlzKTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gIHB1YmxpYyBwbGF5ZXI6IFBsYXllcixcbiAgcHVibGljIG9wdGlvbnM6IEd1aWxkTm9kZUluaXQ8TWV0YT4pXG4gIHtcbiAgICB0aGlzLnRyYWNrcyA9IG5ldyBRdWV1ZTxUcmFjaz4ob3B0aW9ucy5xdWV1ZVN0cmF0ZWd5KTtcbiAgICBpZiAoVHlwZVV0aWwuaXNGdW5jdGlvbihvcHRpb25zLm9uQmVmb3JlQ3JlYXRlU3RyZWFtKSlcbiAgICB0aGlzLm9uQmVmb3JlQ3JlYXRlU3RyZWFtID0gb3B0aW9ucy5vbkJlZm9yZUNyZWF0ZVN0cmVhbTtcbiAgICBpZiAoVHlwZVV0aWwuaXNGdW5jdGlvbihvcHRpb25zLm9uQWZ0ZXJDcmVhdGVTdHJlYW0pKVxuICAgIHRoaXMub25BZnRlckNyZWF0ZVN0cmVhbSA9IG9wdGlvbnMub25BZnRlckNyZWF0ZVN0cmVhbTtcbiAgICBpZiAoVHlwZVV0aWwuaXNGdW5jdGlvbihvcHRpb25zLm9uU3RyZWFtRXh0cmFjdGVkKSlcbiAgICB0aGlzLm9uU3RyZWFtRXh0cmFjdGVkID0gb3B0aW9ucy5vblN0cmVhbUV4dHJhY3RlZDtcbiAgICBpZiAoIVR5cGVVdGlsLmlzTnVsbGlzaChvcHRpb25zLnJlcGVhdE1vZGUpKVxuICAgIHRoaXMucmVwZWF0TW9kZSA9IG9wdGlvbnMucmVwZWF0TW9kZTtcblxuICAgIG9wdGlvbnMuc2VsZkRlYWYgPz89IHRydWU7XG4gICAgb3B0aW9ucy5tYXhTaXplID8/PSBJbmZpbml0eTtcbiAgICBvcHRpb25zLm1heEhpc3RvcnlTaXplID8/PSBJbmZpbml0eTtcbiAgICBvcHRpb25zLnBhdXNlT25FbXB0eSA/Pz0gdHJ1ZTtcblxuICAgIGlmIChcbiAgICAhVHlwZVV0aWwuaXNOdWxsaXNoKHRoaXMub3B0aW9ucy5iaXF1YWQpICYmXG4gICAgIVR5cGVVdGlsLmlzQm9vbGVhbih0aGlzLm9wdGlvbnMuYmlxdWFkKSlcbiAgICB7XG4gICAgICB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuYmlxdWFkID0gdGhpcy5vcHRpb25zLmJpcXVhZDtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuZXF1YWxpemVyKSkge1xuICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLmVxdWFsaXplciA9IHRoaXMub3B0aW9ucy5lcXVhbGl6ZXI7XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5vcHRpb25zLmZpbHRlcmVyKSkge1xuICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLmZpbHRlcnMgPSB0aGlzLm9wdGlvbnMuZmlsdGVyZXI7XG4gICAgfVxuXG4gICAgaWYgKFR5cGVVdGlsLmlzTnVtYmVyKHRoaXMub3B0aW9ucy5yZXNhbXBsZXIpKSB7XG4gICAgICB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuc2FtcGxlUmF0ZSA9IHRoaXMub3B0aW9ucy5yZXNhbXBsZXI7XG4gICAgfVxuXG4gICAgaWYgKFR5cGVVdGlsLmlzQXJyYXkodGhpcy5vcHRpb25zLmZmbXBlZ0ZpbHRlcnMpKSB7XG4gICAgICB0aGlzLmZpbHRlcnMuZmZtcGVnLnNldERlZmF1bHRzKHRoaXMub3B0aW9ucy5mZm1wZWdGaWx0ZXJzKTtcbiAgICB9XG5cbiAgICBpZiAoIVR5cGVVdGlsLmlzTnVtYmVyKG9wdGlvbnMubWF4U2l6ZSkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJnVHlwZUVycm9yKFxuICAgICAgICAnW0d1aWxkTm9kZUluaXQubWF4U2l6ZV0nLFxuICAgICAgICAnbnVtYmVyJyxcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMubWF4U2l6ZVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIVR5cGVVdGlsLmlzTnVtYmVyKG9wdGlvbnMubWF4SGlzdG9yeVNpemUpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ1R5cGVFcnJvcihcbiAgICAgICAgJ1tHdWlsZE5vZGVJbml0Lm1heEhpc3RvcnlTaXplXScsXG4gICAgICAgICdudW1iZXInLFxuICAgICAgICB0eXBlb2Ygb3B0aW9ucy5tYXhIaXN0b3J5U2l6ZVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5tYXhTaXplIDwgMSkgb3B0aW9ucy5tYXhTaXplID0gSW5maW5pdHk7XG4gICAgaWYgKG9wdGlvbnMubWF4SGlzdG9yeVNpemUgPCAxKSBvcHRpb25zLm1heEhpc3RvcnlTaXplID0gSW5maW5pdHk7XG5cbiAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLmRlYnVnKFxuICAgICAgYEd1aWxkUXVldWUgaW5pdGlhbGl6ZWQgZm9yIGd1aWxkICR7dGhpcy5vcHRpb25zLmd1aWxkLm5hbWV9IChJRDogJHt0aGlzLm9wdGlvbnMuZ3VpbGQuaWR9KWBcbiAgICApO1xuICAgIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuUXVldWVDcmVhdGUsIHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBxdWV1ZSBjYW4gaW50ZXJjZXB0IHN0cmVhbXNcbiAgICovXG4gIHB1YmxpYyBjYW5JbnRlcmNlcHQoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5lbmFibGVTdHJlYW1JbnRlcmNlcHRvcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBFc3RpbWF0ZWQgZHVyYXRpb24gb2YgdGhpcyBxdWV1ZSBpbiBtc1xuICAgKi9cbiAgcHVibGljIGdldCBlc3RpbWF0ZWREdXJhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy50cmFja3Muc3RvcmUucmVkdWNlKChhLCBjKSA9PiBhICsgYy5kdXJhdGlvbk1TLCAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXR0ZWQgZHVyYXRpb24gb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBkdXJhdGlvbkZvcm1hdHRlZCgpIHtcbiAgICByZXR1cm4gVXRpbC5idWlsZFRpbWVDb2RlKFV0aWwucGFyc2VNUyh0aGlzLmVzdGltYXRlZER1cmF0aW9uKSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHN5bmMgbHlyaWNzIHByb3ZpZGVyIGZvciB0aGlzIHF1ZXVlLlxuICAgKiBAZXhhbXBsZSBjb25zdCBseXJpY3MgPSBhd2FpdCBwbGF5ZXIubHlyaWNzLnNlYXJjaCh7IHE6ICdBbGFuIFdhbGtlciBGYWRlZCcgfSk7XG4gICAqIGNvbnN0IHN5bmNlZEx5cmljcyA9IHF1ZXVlLnN5bmNlZEx5cmljcyhseXJpY3NbMF0pO1xuICAgKiBjb25zb2xlLmxvZyhzeW5jZWRMeXJpY3MuYXQoMTBfMDAwKSk7XG4gICAqIC8vIHN1YnNjcmliZSB0byBseXJpY3MgY2hhbmdlXG4gICAqIGNvbnN0IHVuc3Vic2NyaWJlID0gc3luY2VkTHlyaWNzLm9uQ2hhbmdlKChseXJpY3MsIHRpbWVzdGFtcCkgPT4ge1xuICAgKiAgICBjb25zb2xlLmxvZyhseXJpY3MsIHRpbWVzdGFtcCk7XG4gICAqIH0pO1xuICAgKiAvLyB1bnN1YnNjcmliZSBmcm9tIGx5cmljcyBjaGFuZ2VcbiAgICogdW5zdWJzY3JpYmUoKTsgLy8gb3JcbiAgICogc3luY2VkTHlyaWNzLnVuc3Vic2NyaWJlKCk7XG4gICAqL1xuICBwdWJsaWMgc3luY2VkTHlyaWNzKGx5cmljczogTHJjR2V0UmVzdWx0IHwgTHJjU2VhcmNoUmVzdWx0KSB7XG4gICAgdGhpcy5zeW5jZWRMeXJpY3NQcm92aWRlci5sb2FkKGx5cmljcz8uc3luY2VkTHlyaWNzID8/ICcnKTtcbiAgICByZXR1cm4gdGhpcy5zeW5jZWRMeXJpY3NQcm92aWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBXcml0ZSBhIGRlYnVnIG1lc3NhZ2UgdG8gdGhpcyBxdWV1ZVxuICAgKiBAcGFyYW0gbSBUaGUgbWVzc2FnZSB0byB3cml0ZVxuICAgKi9cbiAgcHVibGljIGRlYnVnKG06IHN0cmluZykge1xuICAgIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuRGVidWcsIHRoaXMsIG0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBtZXRhZGF0YSBvZiB0aGlzIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1ldGFkYXRhKCkge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMubWV0YWRhdGEhO1xuICB9XG5cbiAgcHVibGljIHNldCBtZXRhZGF0YShtOiBNZXRhKSB7XG4gICAgdGhpcy5vcHRpb25zLm1ldGFkYXRhID0gbTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgbWV0YWRhdGEgZm9yIHRoaXMgcXVldWVcbiAgICogQHBhcmFtIG0gTWV0YWRhdGEgdG8gc2V0XG4gICAqL1xuICBwdWJsaWMgc2V0TWV0YWRhdGEobTogTWV0YSkge1xuICAgIHRoaXMub3B0aW9ucy5tZXRhZGF0YSA9IG07XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIGN1cnJlbnQgdHJhY2sgb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBjdXJyZW50VHJhY2soKSB7XG4gICAgcmV0dXJuIHRoaXMuZGlzcGF0Y2hlcj8uYXVkaW9SZXNvdXJjZT8ubWV0YWRhdGEgfHwgdGhpcy5fX2N1cnJlbnQ7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIGlmIHRoaXMgcXVldWUgd2FzIGRlbGV0ZWQgcHJldmlvdXNseVxuICAgKi9cbiAgcHVibGljIGdldCBkZWxldGVkKCkge1xuICAgIHJldHVybiB0aGlzLiNkZWxldGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB2b2ljZSBjaGFubmVsIG9mIHRoaXMgcXVldWVcbiAgICovXG4gIHB1YmxpYyBnZXQgY2hhbm5lbCgpIHtcbiAgICByZXR1cm4gdGhpcy5kaXNwYXRjaGVyPy5jaGFubmVsIHx8IG51bGw7XG4gIH1cblxuICBwdWJsaWMgc2V0IGNoYW5uZWwoYzogVm9pY2VCYXNlZENoYW5uZWwgfCBudWxsKSB7XG4gICAgaWYgKHRoaXMuZGlzcGF0Y2hlcikge1xuICAgICAgaWYgKGMpIHtcbiAgICAgICAgdGhpcy5kaXNwYXRjaGVyLmNoYW5uZWwgPSBjO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kZWxldGUoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIHZvaWNlIGNvbm5lY3Rpb24gb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBjb25uZWN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmRpc3BhdGNoZXI/LnZvaWNlQ29ubmVjdGlvbiB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBndWlsZCB0aGlzIHF1ZXVlIGJlbG9uZ3MgdG9cbiAgICovXG4gIHB1YmxpYyBnZXQgZ3VpbGQoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5ndWlsZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaWQgb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5ndWlsZC5pZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdHJhbnNpdGlvbiBtb2RlIGZvciB0aGlzIHF1ZXVlXG4gICAqIEBwYXJhbSBzdGF0ZSBUaGUgc3RhdGUgdG8gc2V0XG4gICAqL1xuICBwdWJsaWMgc2V0VHJhbnNpdGlvbmluZyhzdGF0ZTogYm9vbGVhbikge1xuICAgIHRoaXMuI3RyYW5zaXRpb25pbmcgPSBzdGF0ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBpZiB0aGlzIHF1ZXVlIGlzIGN1cnJlbnRseSB1bmRlciB0cmFuc2l0aW9uIG1vZGVcbiAgICovXG4gIHB1YmxpYyBpc1RyYW5zaXRpb25pbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuI3RyYW5zaXRpb25pbmc7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHJlcGVhdCBtb2RlIGZvciB0aGlzIHF1ZXVlXG4gICAqIEBwYXJhbSBtb2RlIFRoZSByZXBlYXQgbW9kZSB0byBhcHBseVxuICAgKi9cbiAgcHVibGljIHNldFJlcGVhdE1vZGUobW9kZTogUXVldWVSZXBlYXRNb2RlKSB7XG4gICAgdGhpcy5yZXBlYXRNb2RlID0gbW9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXggc2l6ZSBvZiB0aGlzIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1heFNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5tYXhTaXplID8/IEluZmluaXR5O1xuICB9XG5cbiAgLyoqXG4gICAqIE1heCBzaXplIG9mIHRoaXMgcXVldWVcbiAgICovXG4gIHB1YmxpYyBnZXRNYXhTaXplKCkge1xuICAgIHJldHVybiB0aGlzLm1heFNpemU7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgc2l6ZSBvZiB0aGUgcXVldWVcbiAgICovXG4gIHB1YmxpYyBnZXQgc2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy50cmFja3Muc2l6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgc2l6ZSBvZiB0aGlzIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZ2V0U2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIE1heCBoaXN0b3J5IHNpemUgb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBtYXhIaXN0b3J5U2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLm1heEhpc3RvcnlTaXplID8/IEluZmluaXR5O1xuICB9XG5cbiAgLyoqXG4gICAqIE1heCBoaXN0b3J5IHNpemUgb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldE1heEhpc3RvcnlTaXplKCkge1xuICAgIHJldHVybiB0aGlzLm1heEhpc3RvcnlTaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBtYXggaGlzdG9yeSBzaXplIGZvciB0aGlzIHF1ZXVlXG4gICAqIEBwYXJhbSBzaXplIFRoZSBzaXplIHRvIHNldFxuICAgKi9cbiAgcHVibGljIHNldE1heEhpc3RvcnlTaXplKHNpemU6IG51bWJlcikge1xuICAgIGlmICghVHlwZVV0aWwuaXNOdW1iZXIoc2l6ZSkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJnVHlwZUVycm9yKCdzaXplJywgJ251bWJlcicsIHR5cGVvZiBzaXplKTtcbiAgICB9XG5cbiAgICBpZiAoc2l6ZSA8IDEpIHNpemUgPSBJbmZpbml0eTtcblxuICAgIHRoaXMub3B0aW9ucy5tYXhIaXN0b3J5U2l6ZSA9IHNpemU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IG1heCBzaXplIGZvciB0aGlzIHF1ZXVlXG4gICAqIEBwYXJhbSBzaXplIFRoZSBzaXplIHRvIHNldFxuICAgKi9cbiAgcHVibGljIHNldE1heFNpemUoc2l6ZTogbnVtYmVyKSB7XG4gICAgaWYgKCFUeXBlVXRpbC5pc051bWJlcihzaXplKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmdUeXBlRXJyb3IoJ3NpemUnLCAnbnVtYmVyJywgdHlwZW9mIHNpemUpO1xuICAgIH1cblxuICAgIGlmIChzaXplIDwgMSkgc2l6ZSA9IEluZmluaXR5O1xuXG4gICAgdGhpcy5vcHRpb25zLm1heFNpemUgPSBzaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIHRoaXMgcXVldWVcbiAgICovXG4gIHB1YmxpYyBjbGVhcigpIHtcbiAgICB0aGlzLnRyYWNrcy5jbGVhcigpO1xuICAgIHRoaXMuaGlzdG9yeS5jbGVhcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoaXMgcXVldWUgaGFzIG5vIHRyYWNrcyBsZWZ0IGluIGl0XG4gICAqL1xuICBwdWJsaWMgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy50cmFja3Muc2l6ZSA8IDE7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhpcyBxdWV1ZSBpcyBmdWxsXG4gICAqL1xuICBwdWJsaWMgaXNGdWxsKCkge1xuICAgIHJldHVybiB0aGlzLnRyYWNrcy5zaXplID49IHRoaXMubWF4U2l6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgcXVldWUgY2FwYWNpdHlcbiAgICovXG4gIHB1YmxpYyBnZXRDYXBhY2l0eSgpIHtcbiAgICBpZiAodGhpcy5pc0Z1bGwoKSkgcmV0dXJuIDA7XG4gICAgY29uc3QgY2FwID0gdGhpcy5tYXhTaXplIC0gdGhpcy5zaXplO1xuICAgIHJldHVybiBjYXA7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhpcyBxdWV1ZSBjdXJyZW50bHkgaG9sZHMgYWN0aXZlIGF1ZGlvIHJlc291cmNlXG4gICAqL1xuICBwdWJsaWMgaXNQbGF5aW5nKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmRpc3BhdGNoZXI/LmF1ZGlvUmVzb3VyY2UgIT0gbnVsbCAmJlxuICAgICAgIXRoaXMuZGlzcGF0Y2hlci5hdWRpb1Jlc291cmNlLmVuZGVkKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCB0cmFjayB0byB0aGUgcXVldWUuIFRoaXMgd2lsbCBlbWl0IGBhdWRpb1RyYWNrc0FkZGAgd2hlbiBtdWx0aXBsZSB0cmFja3MgYXJlIGFkZGVkLCBvdGhlcndpc2UgYGF1ZGlvVHJhY2tBZGRgLlxuICAgKiBAcGFyYW0gdHJhY2sgVHJhY2sgb3IgcGxheWxpc3Qgb3IgYXJyYXkgb2YgdHJhY2tzIHRvIGFkZFxuICAgKi9cbiAgcHVibGljIGFkZFRyYWNrKHRyYWNrOiBUcmFjayB8IFRyYWNrW10gfCBQbGF5bGlzdCkge1xuICAgIGNvbnN0IHRvQWRkID0gdHJhY2sgaW5zdGFuY2VvZiBQbGF5bGlzdCA/IHRyYWNrLnRyYWNrcyA6IHRyYWNrO1xuICAgIGNvbnN0IGlzTXVsdGkgPSBBcnJheS5pc0FycmF5KHRvQWRkKTtcblxuICAgIFZBTElEQVRFX1FVRVVFX0NBUCh0aGlzLCB0b0FkZCk7XG5cbiAgICB0aGlzLnRyYWNrcy5hZGQodG9BZGQpO1xuXG4gICAgaWYgKGlzTXVsdGkpIHtcbiAgICAgIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuQXVkaW9UcmFja3NBZGQsIHRoaXMsIHRvQWRkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lbWl0KEd1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrQWRkLCB0aGlzLCB0b0FkZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhIHRyYWNrIGZyb20gcXVldWVcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayB0byByZW1vdmVcbiAgICovXG4gIHB1YmxpYyByZW1vdmVUcmFjayh0cmFjazogVHJhY2tSZXNvbHZhYmxlKSB7XG4gICAgcmV0dXJuIHRoaXMubm9kZS5yZW1vdmUodHJhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFByZXBlbmRzIGEgdHJhY2sgb3IgdHJhY2sgcmVzb2x2YWJsZSB0byB0aGUgcXVldWVcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayByZXNvbHZhYmxlIHRvIGluc2VydFxuICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIGluc2VydCB0aGUgdHJhY2sgYXQgKGRlZmF1bHRzIHRvIDApLiBJZiA+IDAsIHRoZSBpbnNlcnRlZCB0cmFjayB3aWxsIGJlIHBsYWNlZCBiZWZvcmUgdGhlIHRyYWNrIGF0IHRoZSBnaXZlbiBpbmRleC5cbiAgICovXG4gIHB1YmxpYyBwcmVwZW5kKHRyYWNrOiBUcmFjayB8IFF1ZXVlPFRyYWNrPiB8IEFycmF5PFRyYWNrPiwgaW5kZXggPSAwKTogdm9pZCB7XG4gICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+IHRoaXMudHJhY2tzLnNpemUpIHtcbiAgICAgIHRocm93IG5ldyBPdXRPZlJhbmdlRXJyb3IoXG4gICAgICAgICdpbmRleCcsXG4gICAgICAgIGAke2luZGV4fWAsXG4gICAgICAgICcwJyxcbiAgICAgICAgYCR7dGhpcy50cmFja3Muc2l6ZX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGNvdW50ID0gQXJyYXkuaXNBcnJheSh0cmFjaykgP1xuICAgIHRyYWNrLmxlbmd0aCA6XG4gICAgdHJhY2sgaW5zdGFuY2VvZiBRdWV1ZSA/XG4gICAgdHJhY2suc2l6ZSA6XG4gICAgMTtcblxuICAgIFZBTElEQVRFX1FVRVVFX0NBUCh0aGlzLCBjb3VudCk7XG5cbiAgICBjb25zdCBpbnNlcnRpb25JbmRleCA9IGluZGV4ID09PSAwID8gMCA6IGluZGV4IC0gMTtcblxuICAgIGlmICh0cmFjayBpbnN0YW5jZW9mIFRyYWNrKSB7XG4gICAgICB0aGlzLm5vZGUuaW5zZXJ0KHRyYWNrLCBpbnNlcnRpb25JbmRleCk7XG4gICAgICB0aGlzLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LkF1ZGlvVHJhY2tBZGQsIHRoaXMsIHRyYWNrKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFja3MgPSB0cmFjayBpbnN0YW5jZW9mIFF1ZXVlID8gdHJhY2suc3RvcmUgOiB0cmFjaztcblxuICAgIHRoaXMudHJhY2tzLnN0b3JlLnNwbGljZShpbnNlcnRpb25JbmRleCwgMCwgLi4udHJhY2tzKTtcblxuICAgIGlmICghdGhpcy5vcHRpb25zLm5vRW1pdEluc2VydCkge1xuICAgICAgdGhpcy5lbWl0KEd1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrc0FkZCwgdGhpcywgdHJhY2tzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kcyBhIHRyYWNrIG9yIHRyYWNrIHJlc29sdmFibGUgdG8gdGhlIHF1ZXVlXG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2sgcmVzb2x2YWJsZSB0byBpbnNlcnRcbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCB0byBpbnNlcnQgdGhlIHRyYWNrIGF0IChkZWZhdWx0cyB0byAwKS4gSWYgPiAwLCB0aGUgaW5zZXJ0ZWQgdHJhY2sgd2lsbCBiZSBwbGFjZWQgYWZ0ZXIgdGhlIHRyYWNrIGF0IHRoZSBnaXZlbiBpbmRleC5cbiAgICovXG4gIHB1YmxpYyBhcHBlbmQodHJhY2s6IFRyYWNrIHwgUXVldWU8VHJhY2s+IHwgQXJyYXk8VHJhY2s+LCBpbmRleCA9IDApOiB2b2lkIHtcbiAgICBpZiAoaW5kZXggPCAwIHx8IGluZGV4ID4gdGhpcy50cmFja3Muc2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IE91dE9mUmFuZ2VFcnJvcihcbiAgICAgICAgJ2luZGV4JyxcbiAgICAgICAgYCR7aW5kZXh9YCxcbiAgICAgICAgJzAnLFxuICAgICAgICBgJHt0aGlzLnRyYWNrcy5zaXplfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgY291bnQgPSBBcnJheS5pc0FycmF5KHRyYWNrKSA/XG4gICAgdHJhY2subGVuZ3RoIDpcbiAgICB0cmFjayBpbnN0YW5jZW9mIFF1ZXVlID9cbiAgICB0cmFjay5zaXplIDpcbiAgICAxO1xuXG4gICAgVkFMSURBVEVfUVVFVUVfQ0FQKHRoaXMsIGNvdW50KTtcblxuICAgIGlmICh0cmFjayBpbnN0YW5jZW9mIFRyYWNrKSB7XG4gICAgICB0aGlzLm5vZGUuaW5zZXJ0KHRyYWNrLCBpbmRleCk7XG4gICAgICB0aGlzLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LkF1ZGlvVHJhY2tBZGQsIHRoaXMsIHRyYWNrKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0cmFja3MgPSB0cmFjayBpbnN0YW5jZW9mIFF1ZXVlID8gdHJhY2suc3RvcmUgOiB0cmFjaztcblxuICAgIHRoaXMudHJhY2tzLnN0b3JlLnNwbGljZShpbmRleCwgMCwgLi4udHJhY2tzKTtcblxuICAgIGlmICghdGhpcy5vcHRpb25zLm5vRW1pdEluc2VydCkge1xuICAgICAgdGhpcy5lbWl0KEd1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrc0FkZCwgdGhpcywgdHJhY2tzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5zZXJ0cyB0aGUgdHJhY2sgdG8gdGhlIGdpdmVuIGluZGV4XG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2sgdG8gaW5zZXJ0XG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggdG8gaW5zZXJ0IHRoZSB0cmFjayBhdCAoZGVmYXVsdHMgdG8gMClcbiAgICovXG4gIHB1YmxpYyBpbnNlcnRUcmFjayh0cmFjazogVHJhY2ssIGluZGV4ID0gMCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLm5vZGUuaW5zZXJ0KHRyYWNrLCBpbmRleCk7XG4gIH1cblxuICAvKipcbiAgICogTW92ZXMgYSB0cmFjayBpbiB0aGUgcXVldWVcbiAgICogQHBhcmFtIGZyb20gVGhlIHRyYWNrIHRvIG1vdmVcbiAgICogQHBhcmFtIHRvIFRoZSBwb3NpdGlvbiB0byBtb3ZlIHRvXG4gICAqL1xuICBwdWJsaWMgbW92ZVRyYWNrKHRyYWNrOiBUcmFja1Jlc29sdmFibGUsIGluZGV4ID0gMCk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLm5vZGUubW92ZSh0cmFjaywgaW5kZXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvcHkgYSB0cmFjayBpbiB0aGUgcXVldWVcbiAgICogQHBhcmFtIGZyb20gVGhlIHRyYWNrIHRvIGNsb25lXG4gICAqIEBwYXJhbSB0byBUaGUgcG9zaXRpb24gdG8gY2xvbmUgYXRcbiAgICovXG4gIHB1YmxpYyBjb3B5VHJhY2sodHJhY2s6IFRyYWNrUmVzb2x2YWJsZSwgaW5kZXggPSAwKTogdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMubm9kZS5jb3B5KHRyYWNrLCBpbmRleCk7XG4gIH1cblxuICAvKipcbiAgICogU3dhcCB0d28gdHJhY2tzIGluIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gc3JjIFRoZSBmaXJzdCB0cmFjayB0byBzd2FwXG4gICAqIEBwYXJhbSBkZXN0IFRoZSBzZWNvbmQgdHJhY2sgdG8gc3dhcFxuICAgKi9cbiAgcHVibGljIHN3YXBUcmFja3Moc3JjOiBUcmFja1Jlc29sdmFibGUsIGRlc3Q6IFRyYWNrUmVzb2x2YWJsZSk6IHZvaWQge1xuICAgIHJldHVybiB0aGlzLm5vZGUuc3dhcChzcmMsIGRlc3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBzdHJlYW0gZGlzcGF0Y2hlciBmcm9tIHRoZSBnaXZlbiBjb25uZWN0aW9uXG4gICAqIEBwYXJhbSBjb25uZWN0aW9uIFRoZSBjb25uZWN0aW9uIHRvIHVzZVxuICAgKi9cbiAgcHVibGljIGNyZWF0ZURpc3BhdGNoZXIoXG4gIGNvbm5lY3Rpb246IFZvaWNlQ29ubmVjdGlvbixcbiAgb3B0aW9uczogUGljazxWb2ljZUNvbm5lY3RDb25maWcsICdhdWRpb1BsYXllcicgfCAndGltZW91dCc+ID0ge30pXG4gIHtcbiAgICBpZiAoY29ubmVjdGlvbi5zdGF0ZS5zdGF0dXMgPT09IFZvaWNlQ29ubmVjdGlvblN0YXR1cy5EZXN0cm95ZWQpIHtcbiAgICAgIHRocm93IG5ldyBWb2ljZUNvbm5lY3Rpb25EZXN0cm95ZWRFcnJvcigpO1xuICAgIH1cblxuICAgIGNvbnN0IGNoYW5uZWwgPSB0aGlzLnBsYXllci5jbGllbnQuY2hhbm5lbHMuY2FjaGUuZ2V0KFxuICAgICAgY29ubmVjdGlvbi5qb2luQ29uZmlnLmNoYW5uZWxJZCFcbiAgICApO1xuICAgIGlmICghY2hhbm5lbCkgdGhyb3cgbmV3IE5vVm9pY2VDaGFubmVsRXJyb3IoKTtcbiAgICBpZiAoIWNoYW5uZWwuaXNWb2ljZUJhc2VkKCkpXG4gICAgdGhyb3cgbmV3IEludmFsaWRBcmdUeXBlRXJyb3IoXG4gICAgICAnY2hhbm5lbCcsXG4gICAgICBgVm9pY2VCYXNlZENoYW5uZWwgKHR5cGUgJHtDaGFubmVsVHlwZS5HdWlsZFZvaWNlfS8ke0NoYW5uZWxUeXBlLkd1aWxkU3RhZ2VWb2ljZX0pYCxcbiAgICAgIFN0cmluZyhjaGFubmVsPy50eXBlKVxuICAgICk7XG5cbiAgICBpZiAodGhpcy5kaXNwYXRjaGVyKSB7XG4gICAgICB0aGlzLiNyZW1vdmVMaXN0ZW5lcnModGhpcy5kaXNwYXRjaGVyKTtcbiAgICAgIHRoaXMuZGlzcGF0Y2hlci5kZXN0cm95KCk7XG4gICAgICB0aGlzLmRpc3BhdGNoZXIgPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZGlzcGF0Y2hlciA9IG5ldyBTdHJlYW1EaXNwYXRjaGVyKFxuICAgICAgY29ubmVjdGlvbixcbiAgICAgIGNoYW5uZWwsXG4gICAgICB0aGlzLFxuICAgICAgb3B0aW9ucy50aW1lb3V0ID8/IHRoaXMub3B0aW9ucy5jb25uZWN0aW9uVGltZW91dCxcbiAgICAgIG9wdGlvbnMuYXVkaW9QbGF5ZXJcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3QgdG8gYSB2b2ljZSBjaGFubmVsXG4gICAqIEBwYXJhbSBjaGFubmVsUmVzb2x2YWJsZSBUaGUgdm9pY2UgY2hhbm5lbCB0byBjb25uZWN0IHRvXG4gICAqIEBwYXJhbSBvcHRpb25zIEpvaW4gY29uZmlnXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgY29ubmVjdChcbiAgY2hhbm5lbFJlc29sdmFibGU6IEd1aWxkVm9pY2VDaGFubmVsUmVzb2x2YWJsZSxcbiAgb3B0aW9uczogVm9pY2VDb25uZWN0Q29uZmlnID0ge30pXG4gIHtcbiAgICBjb25zdCBjaGFubmVsID0gdGhpcy5wbGF5ZXIuY2xpZW50LmNoYW5uZWxzLnJlc29sdmUoY2hhbm5lbFJlc29sdmFibGUpO1xuICAgIGlmICghY2hhbm5lbCB8fCAhY2hhbm5lbC5pc1ZvaWNlQmFzZWQoKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmdUeXBlRXJyb3IoXG4gICAgICAgICdjaGFubmVsJyxcbiAgICAgICAgYFZvaWNlQmFzZWRDaGFubmVsICh0eXBlICR7Q2hhbm5lbFR5cGUuR3VpbGRWb2ljZX0vJHtDaGFubmVsVHlwZS5HdWlsZFN0YWdlVm9pY2V9KWAsXG4gICAgICAgIFN0cmluZyhjaGFubmVsPy50eXBlKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLmRlYnVnKFxuICAgICAgYENvbm5lY3RpbmcgdG8gJHtcbiAgICAgIGNoYW5uZWwudHlwZSA9PT0gQ2hhbm5lbFR5cGUuR3VpbGRTdGFnZVZvaWNlID8gJ3N0YWdlJyA6ICd2b2ljZSd9IGNoYW5uZWwgJHtcbiAgICAgIGNoYW5uZWwubmFtZX0gKElEOiAke2NoYW5uZWwuaWR9KWBcbiAgICApO1xuXG4gICAgaWYgKHRoaXMuZGlzcGF0Y2hlciAmJiBjaGFubmVsLmlkICE9PSB0aGlzLmRpc3BhdGNoZXIuY2hhbm5lbC5pZCkge1xuICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpIHRoaXMuZGVidWcoJ0Rlc3Ryb3lpbmcgb2xkIGNvbm5lY3Rpb24nKTtcbiAgICAgIHRoaXMuI3JlbW92ZUxpc3RlbmVycyh0aGlzLmRpc3BhdGNoZXIpO1xuICAgICAgdGhpcy5kaXNwYXRjaGVyLmRlc3Ryb3koKTtcbiAgICAgIHRoaXMuZGlzcGF0Y2hlciA9IG51bGw7XG4gICAgfVxuXG4gICAgdGhpcy5kaXNwYXRjaGVyID0gYXdhaXQgdGhpcy5wbGF5ZXIudm9pY2VVdGlscy5jb25uZWN0KGNoYW5uZWwsIHtcbiAgICAgIGRlYWY6IG9wdGlvbnMuZGVhZiA/PyB0aGlzLm9wdGlvbnMuc2VsZkRlYWYgPz8gdHJ1ZSxcbiAgICAgIG1heFRpbWU6IG9wdGlvbnM/LnRpbWVvdXQgPz8gdGhpcy5vcHRpb25zLmNvbm5lY3Rpb25UaW1lb3V0ID8/IDEyMF8wMDAsXG4gICAgICBxdWV1ZTogdGhpcyxcbiAgICAgIGF1ZGlvUGxheWVyOiBvcHRpb25zPy5hdWRpb1BsYXllcixcbiAgICAgIGdyb3VwOiBvcHRpb25zLmdyb3VwID8/IHRoaXMucGxheWVyLmNsaWVudC51c2VyPy5pZCxcbiAgICAgIGRhdmVFbmNyeXB0aW9uOiBvcHRpb25zLmRhdmVFbmNyeXB0aW9uLFxuICAgICAgZGVjcnlwdGlvbkZhaWx1cmVUb2xlcmFuY2U6IG9wdGlvbnMuZGVjcnlwdGlvbkZhaWx1cmVUb2xlcmFuY2VcbiAgICB9KTtcblxuICAgIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuQ29ubmVjdGlvbiwgdGhpcyk7XG5cbiAgICBpZiAodGhpcy5jaGFubmVsIS50eXBlID09PSBDaGFubmVsVHlwZS5HdWlsZFN0YWdlVm9pY2UpIHtcbiAgICAgIGF3YWl0IHRoaXMuY2hhbm5lbCEuZ3VpbGQubWVtYmVycy5tZSEudm9pY2Uuc2V0U3VwcHJlc3NlZChmYWxzZSkuY2F0Y2goXG4gICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5jaGFubmVsIS5ndWlsZC5tZW1iZXJzLm1lIS52b2ljZS5zZXRSZXF1ZXN0VG9TcGVhayhcbiAgICAgICAgICAgIHRydWVcbiAgICAgICAgICApLmNhdGNoKFV0aWwubm9vcCk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy4jYXR0YWNoTGlzdGVuZXJzKHRoaXMuZGlzcGF0Y2hlcik7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgc2h1ZmZsZSBtb2RlIGZvciB0aGlzIHF1ZXVlXG4gICAqIEBwYXJhbSBkeW5hbWljIFdoZXRoZXIgdG8gc2h1ZmZsZSB0aGUgcXVldWUgZHluYW1pY2FsbHkuIERlZmF1bHRzIHRvIGB0cnVlYC5cbiAgICogRHluYW1pYyBzaHVmZmxpbmcgd2lsbCBzaHVmZmxlIHRoZSBxdWV1ZSB3aGVuIHRoZSBjdXJyZW50IHRyYWNrIGVuZHMsIHdpdGhvdXQgbXV0YXRpbmcgdGhlIHF1ZXVlLlxuICAgKiBJZiBzZXQgdG8gYGZhbHNlYCwgdGhlIHF1ZXVlIHdpbGwgYmUgc2h1ZmZsZWQgaW1tZWRpYXRlbHkgaW4tcGxhY2UsIHdoaWNoIGNhbm5vdCBiZSB1bmRvbmUuXG4gICAqL1xuICBwdWJsaWMgZW5hYmxlU2h1ZmZsZShkeW5hbWljID0gdHJ1ZSkge1xuICAgIGlmICghZHluYW1pYykge1xuICAgICAgdGhpcy50cmFja3Muc2h1ZmZsZSgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdGhpcy4jc2h1ZmZsZSA9IHRydWU7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRGlzYWJsZSBzaHVmZmxlIG1vZGUgZm9yIHRoaXMgcXVldWUuXG4gICAqL1xuICBwdWJsaWMgZGlzYWJsZVNodWZmbGUoKSB7XG4gICAgdGhpcy4jc2h1ZmZsZSA9IGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZSBzaHVmZmxlIG1vZGUgZm9yIHRoaXMgcXVldWUuXG4gICAqIEBwYXJhbSBkeW5hbWljIFdoZXRoZXIgdG8gc2h1ZmZsZSB0aGUgcXVldWUgZHluYW1pY2FsbHkuIERlZmF1bHRzIHRvIGB0cnVlYC5cbiAgICogQHJldHVybnMgV2hldGhlciBzaHVmZmxlIGlzIGVuYWJsZWQgb3IgZGlzYWJsZWQuXG4gICAqL1xuICBwdWJsaWMgdG9nZ2xlU2h1ZmZsZShkeW5hbWljID0gdHJ1ZSkge1xuICAgIGlmIChkeW5hbWljKSB7XG4gICAgICB0aGlzLiNzaHVmZmxlID0gIXRoaXMuI3NodWZmbGU7XG4gICAgICByZXR1cm4gdGhpcy4jc2h1ZmZsZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy50cmFja3Muc2h1ZmZsZSgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgc2h1ZmZsZSBtb2RlIGlzIGVuYWJsZWQgZm9yIHRoaXMgcXVldWUuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlzU2h1ZmZsaW5nKCkge1xuICAgIHJldHVybiB0aGlzLiNzaHVmZmxlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB2b2ljZSBjb25uZWN0aW9uIGxhdGVuY3kgb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBwaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb24/LnBpbmcudWRwID8/IC0xO1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSB0aGlzIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZGVsZXRlKCkge1xuICAgIGlmICh0aGlzLnBsYXllci5ub2Rlcy5kZWxldGUodGhpcy5pZCkpIHtcbiAgICAgIHRoaXMuI2RlbGV0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5wbGF5ZXIuZXZlbnRzLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LlF1ZXVlRGVsZXRlLCB0aGlzKTtcbiAgICAgIHRoaXMubm9kZS50YXNrc1F1ZXVlLmNhbmNlbEFsbCgpO1xuICAgICAgdGhpcy50YXNrc1F1ZXVlLmNhbmNlbEFsbCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXZpdmVzIHRoaXMgcXVldWVcbiAgICogQHJldHVybnNcbiAgICovXG4gIHB1YmxpYyByZXZpdmUoKSB7XG4gICAgaWYgKCF0aGlzLmRlbGV0ZWQgfHwgdGhpcy5wbGF5ZXIubm9kZXMuaGFzKHRoaXMuaWQpKSByZXR1cm47XG4gICAgdGhpcy4jZGVsZXRlZCA9IGZhbHNlO1xuICAgIHRoaXMuc2V0VHJhbnNpdGlvbmluZyhmYWxzZSk7XG4gICAgdGhpcy5wbGF5ZXIubm9kZXMuY2FjaGUuc2V0KHRoaXMuaWQsIHRoaXMpO1xuICAgIHRoaXMucGxheWVyLmV2ZW50cy5lbWl0KEd1aWxkUXVldWVFdmVudC5RdWV1ZUNyZWF0ZSwgdGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHNlbGYgZGVhZlxuICAgKiBAcGFyYW0gbW9kZSBPbi9PZmYgc3RhdGVcbiAgICogQHBhcmFtIHJlYXNvbiBSZWFzb25cbiAgICovXG4gIHB1YmxpYyBzZXRTZWxmRGVhZihtb2RlPzogYm9vbGVhbiwgcmVhc29uPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuZ3VpbGQubWVtYmVycy5tZSEudm9pY2Uuc2V0RGVhZihtb2RlLCByZWFzb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBzZWxmIG11dGVcbiAgICogQHBhcmFtIG1vZGUgT24vT2ZmIHN0YXRlXG4gICAqIEBwYXJhbSByZWFzb24gUmVhc29uXG4gICAqL1xuICBwdWJsaWMgc2V0U2VsZk11dGUobW9kZT86IGJvb2xlYW4sIHJlYXNvbj86IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmd1aWxkLm1lbWJlcnMubWUhLnZvaWNlLnNldE11dGUobW9kZSwgcmVhc29uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQbGF5IGEgdHJhY2sgaW4gdGhpcyBxdWV1ZVxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRvIGJlIHBsYXllZFxuICAgKiBAcGFyYW0gb3B0aW9ucyBQbGF5ZXIgbm9kZSBpbml0aWFsaXphdGlvbiBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcGxheShcbiAgdHJhY2s6IFRyYWNrTGlrZSxcbiAgb3B0aW9ucz86IFBsYXllck5vZGVJbml0aWFsaXplck9wdGlvbnM8TWV0YT4pXG4gIHtcbiAgICBpZiAoIXRoaXMuY2hhbm5lbCkgdGhyb3cgbmV3IE5vVm9pY2VDb25uZWN0aW9uRXJyb3IoKTtcblxuICAgIHJldHVybiB0aGlzLnBsYXllci5wbGF5KHRoaXMuY2hhbm5lbCwgdHJhY2ssIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXQgYW4gZXZlbnQgb24gdGhpcyBxdWV1ZVxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIGV2ZW50IHRvIGVtaXRcbiAgICogQHBhcmFtIGFyZ3MgVGhlIGFyZ3MgZm9yIHRoZSBldmVudFxuICAgKi9cbiAgcHVibGljIGVtaXQ8SyBleHRlbmRzIGtleW9mIEd1aWxkUXVldWVFdmVudHM8TWV0YT4+KFxuICBldmVudDogSyxcbiAgLi4uYXJnczogUGFyYW1ldGVyczxHdWlsZFF1ZXVlRXZlbnRzPE1ldGE+W0tdPilcbiAgOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5kZWxldGVkKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRoaXMucGxheWVyLmV2ZW50cy5lbWl0KGV2ZW50LCAuLi5hcmdzKTtcbiAgfVxuXG4gICNhdHRhY2hMaXN0ZW5lcnMoZGlzcGF0Y2hlcjogU3RyZWFtRGlzcGF0Y2hlcikge1xuICAgIGRpc3BhdGNoZXIub24oJ2Vycm9yJywgKGUpID0+IHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuRXJyb3IsIHRoaXMsIGUpKTtcbiAgICBkaXNwYXRjaGVyLm9uKFxuICAgICAgJ2RlYnVnJyxcbiAgICAgIChtKSA9PiB0aGlzLmhhc0RlYnVnZ2VyICYmIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuRGVidWcsIHRoaXMsIG0pXG4gICAgKTtcbiAgICBkaXNwYXRjaGVyLm9uKCdmaW5pc2gnLCAocikgPT4gdGhpcy4jcGVyZm9ybUZpbmlzaChyKSk7XG4gICAgZGlzcGF0Y2hlci5vbignc3RhcnQnLCAocikgPT4gdGhpcy4jcGVyZm9ybVN0YXJ0KHIpKTtcbiAgICBkaXNwYXRjaGVyLm9uKCdkZXN0cm95ZWQnLCAoKSA9PiB7XG4gICAgICB0aGlzLiNyZW1vdmVMaXN0ZW5lcnMoZGlzcGF0Y2hlcik7XG4gICAgICB0aGlzLmRpc3BhdGNoZXIgPSBudWxsO1xuICAgIH0pO1xuICAgIGRpc3BhdGNoZXIub24oJ2RzcCcsIChmKSA9PiB7XG4gICAgICBpZiAoIU9iamVjdC5pcyh0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuZmlsdGVycywgZikpIHtcbiAgICAgICAgdGhpcy5lbWl0KFxuICAgICAgICAgIEd1aWxkUXVldWVFdmVudC5EU1BVcGRhdGUsXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuZmlsdGVycyxcbiAgICAgICAgICBmXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuZmlsdGVycyA9IGY7XG4gICAgfSk7XG4gICAgZGlzcGF0Y2hlci5vbignYmlxdWFkJywgKGYpID0+IHtcbiAgICAgIGlmICh0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuYmlxdWFkICE9PSBmKSB7XG4gICAgICAgIHRoaXMuZW1pdChcbiAgICAgICAgICBHdWlsZFF1ZXVlRXZlbnQuQmlxdWFkRmlsdGVyc1VwZGF0ZSxcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5iaXF1YWQsXG4gICAgICAgICAgZlxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLmJpcXVhZCA9IGY7XG4gICAgfSk7XG4gICAgZGlzcGF0Y2hlci5vbignZXFCYW5kcycsIChmKSA9PiB7XG4gICAgICBpZiAoIU9iamVjdC5pcyhmLCB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuZXF1YWxpemVyKSkge1xuICAgICAgICB0aGlzLmVtaXQoXG4gICAgICAgICAgR3VpbGRRdWV1ZUV2ZW50LkVxdWFsaXplclVwZGF0ZSxcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5lcXVhbGl6ZXIsXG4gICAgICAgICAgZlxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLmVxdWFsaXplciA9IGY7XG4gICAgfSk7XG4gICAgZGlzcGF0Y2hlci5vbigndm9sdW1lJywgKGYpID0+IHtcbiAgICAgIGlmICh0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUudm9sdW1lICE9PSBmKVxuICAgICAgdGhpcy5lbWl0KFxuICAgICAgICBHdWlsZFF1ZXVlRXZlbnQuVm9sdW1lQ2hhbmdlLFxuICAgICAgICB0aGlzLFxuICAgICAgICB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUudm9sdW1lLFxuICAgICAgICBmXG4gICAgICApO1xuICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLnZvbHVtZSA9IGY7XG4gICAgfSk7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgIGNvbnN0IGFyZU9iamVjdHNEaWZmZXJlbnQgPSAoYTogYW55LCBiOiBhbnkpID0+IHtcbiAgICAgIGlmICghYSAmJiAhYikgcmV0dXJuIGZhbHNlO1xuICAgICAgaWYgKCFhIHx8ICFiKSByZXR1cm4gdHJ1ZTtcbiAgICAgIGlmIChPYmplY3Qua2V5cyhhKS5sZW5ndGggIT09IE9iamVjdC5rZXlzKGIpLmxlbmd0aCkgcmV0dXJuIHRydWU7XG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMoYSkuc29tZSgoaykgPT4gYVtrXSAhPT0gYltrXSk7XG4gICAgfTtcblxuICAgIGRpc3BhdGNoZXIub24oJ3NhbXBsZVJhdGUnLCAoZikgPT4ge1xuICAgICAgaWYgKHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5zYW1wbGVSYXRlICE9PSBmLnNhbXBsZVJhdGUpIHtcbiAgICAgICAgdGhpcy5lbWl0KFxuICAgICAgICAgIEd1aWxkUXVldWVFdmVudC5TYW1wbGVSYXRlVXBkYXRlLFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLnNhbXBsZVJhdGUsXG4gICAgICAgICAgZi5zYW1wbGVSYXRlXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLnNhbXBsZVJhdGUgPSBmLnNhbXBsZVJhdGU7XG5cbiAgICAgICAgdGhpcy5maWx0ZXJzLnNlZWtlcj8uc2V0U2FtcGxlUmF0ZShmLnNhbXBsZVJhdGUpO1xuICAgICAgICB0aGlzLmZpbHRlcnMuc2Vla2VyPy5zZXRUb3RhbER1cmF0aW9uKHRoaXMubm9kZS5lc3RpbWF0ZWREdXJhdGlvbik7XG4gICAgICB9XG5cbiAgICAgIGlmIChmLmN1cnJlbnRGaWx0ZXIgIT09IHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5zYW1wbGVSYXRlRmlsdGVyKSB7XG4gICAgICAgIHRoaXMuZW1pdChcbiAgICAgICAgICBHdWlsZFF1ZXVlRXZlbnQuU2FtcGxlUmF0ZUZpbHRlclVwZGF0ZSxcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5zYW1wbGVSYXRlRmlsdGVyID8/IG51bGwsXG4gICAgICAgICAgZi5jdXJyZW50RmlsdGVyXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5zYW1wbGVSYXRlRmlsdGVyID0gZi5jdXJyZW50RmlsdGVyO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGRpc3BhdGNoZXIub24oJ3JldmVyYicsIChmKSA9PiB7XG4gICAgICBpZiAoYXJlT2JqZWN0c0RpZmZlcmVudChmLCB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUucmV2ZXJiKSkge1xuICAgICAgICB0aGlzLmVtaXQoXG4gICAgICAgICAgR3VpbGRRdWV1ZUV2ZW50LlJldmVyYlVwZGF0ZSxcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5yZXZlcmIgPz8gbnVsbCxcbiAgICAgICAgICBmXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5yZXZlcmIgPSBmO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGRpc3BhdGNoZXIub24oJ3NlZWtlcicsIChmKSA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcikge1xuICAgICAgICB0aGlzLmRlYnVnKFxuICAgICAgICAgIGBTZWVrZXIgPj4gU2Vla2VkIHRvICR7Zi5zZWVrVGFyZ2V0fW1zIGZvciBUcmFjayAke3RoaXMuY3VycmVudFRyYWNrPy50aXRsZX1gXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChmLnNlZWtUYXJnZXQgIT0gbnVsbCkgdGhpcy5ub2RlLnNldFByb2dyZXNzKGYuc2Vla1RhcmdldCk7XG5cbiAgICAgIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuUGxheWVyU2VlaywgdGhpcywgZik7XG4gICAgfSk7XG5cbiAgICBkaXNwYXRjaGVyLm9uKCdjb21wcmVzc29yJywgKGYpID0+IHtcbiAgICAgIGlmIChhcmVPYmplY3RzRGlmZmVyZW50KGYsIHRoaXMuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5jb21wcmVzc29yKSkge1xuICAgICAgICB0aGlzLmVtaXQoXG4gICAgICAgICAgR3VpbGRRdWV1ZUV2ZW50LkNvbXByZXNzb3JVcGRhdGUsXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICB0aGlzLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuY29tcHJlc3NvciA/PyBudWxsLFxuICAgICAgICAgIGZcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLmNvbXByZXNzb3IgPSBmO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldCBoYXNEZWJ1Z2dlcigpIHtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXIuZXZlbnRzLmhhc0RlYnVnZ2VyO1xuICB9XG5cbiAgI3JlbW92ZUxpc3RlbmVyczxUIGV4dGVuZHMge3JlbW92ZUFsbExpc3RlbmVyczogKCkgPT4gdW5rbm93bjt9Pih0YXJnZXQ6IFQpIHtcbiAgICB0YXJnZXQucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gIH1cblxuICAjcGVyZm9ybVN0YXJ0KHJlc291cmNlPzogQXVkaW9SZXNvdXJjZTxUcmFjaz4pIHtcbiAgICBjb25zdCB0cmFjayA9IHJlc291cmNlPy5tZXRhZGF0YSB8fCB0aGlzLmN1cnJlbnRUcmFjaztcbiAgICBjb25zdCByZWFzb24gPSB0aGlzLmlzVHJhbnNpdGlvbmluZygpID8gJ2ZpbHRlcnMnIDogJ25vcm1hbCc7XG5cbiAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLmRlYnVnKFxuICAgICAgYFBsYXllciB0cmlnZ2VyZWQgZm9yIFRyYWNrICR7SlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICB0aXRsZTogdHJhY2s/LnRpdGxlLFxuICAgICAgICByZWFzb25cbiAgICAgIH0pfWBcbiAgICApO1xuXG4gICAgdGhpcy5lbWl0KEd1aWxkUXVldWVFdmVudC5QbGF5ZXJUcmlnZ2VyLCB0aGlzLCB0cmFjayEsIHJlYXNvbik7XG4gICAgaWYgKHRyYWNrICYmICF0aGlzLmlzVHJhbnNpdGlvbmluZygpKVxuICAgIHRoaXMuZW1pdChHdWlsZFF1ZXVlRXZlbnQuUGxheWVyU3RhcnQsIHRoaXMsIHRyYWNrKTtcbiAgICB0aGlzLnNldFRyYW5zaXRpb25pbmcoZmFsc2UpO1xuICB9XG5cbiAgI2dldE5leHRUcmFjaygpIHtcbiAgICBpZiAoIXRoaXMuaXNTaHVmZmxpbmcpIHtcbiAgICAgIHJldHVybiB0aGlzLnRyYWNrcy5kaXNwYXRjaCgpO1xuICAgIH1cblxuICAgIGNvbnN0IHN0b3JlID0gdGhpcy50cmFja3Muc3RvcmU7XG5cbiAgICBpZiAoIXN0b3JlLmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgY29uc3QgdHJhY2sgPSBVdGlsLnJhbmRvbUNob2ljZShzdG9yZSk7XG5cbiAgICB0aGlzLnRyYWNrcy5yZW1vdmVPbmUoKHQpID0+IHtcbiAgICAgIHJldHVybiB0LmlkID09PSB0cmFjay5pZDtcbiAgICB9KTtcblxuICAgIHJldHVybiB0cmFjaztcbiAgfVxuXG4gICNwZXJmb3JtRmluaXNoKHJlc291cmNlPzogQXVkaW9SZXNvdXJjZTxUcmFjaz4pIHtcbiAgICBjb25zdCB0cmFjayA9IHJlc291cmNlPy5tZXRhZGF0YSB8fCB0aGlzLmN1cnJlbnRUcmFjaztcblxuICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgIHRoaXMuZGVidWcoXG4gICAgICBgVHJhY2sgJHtKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHRpdGxlOiB0cmFjaz8udGl0bGUsXG4gICAgICAgIGlzVHJhbnNpdGlvbk1vZGU6IHRoaXMuaXNUcmFuc2l0aW9uaW5nKClcbiAgICAgIH0pfSB3YXMgbWFya2VkIGFzIGZpbmlzaGVkYFxuICAgICk7XG5cbiAgICBpZiAoIXRoaXMuaXNUcmFuc2l0aW9uaW5nKCkpIHtcbiAgICAgIHRoaXMuc3luY2VkTHlyaWNzUHJvdmlkZXIudW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMuc3luY2VkTHlyaWNzUHJvdmlkZXIubHlyaWNzLmNsZWFyKCk7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMuZGVidWcoXG4gICAgICAgICdBZGRpbmcgdHJhY2sgdG8gaGlzdG9yeSBhbmQgZW1pdHRpbmcgZmluaXNoIGV2ZW50IHNpbmNlIHRyYW5zaXRpb24gbW9kZSBpcyBkaXNhYmxlZC4uLidcbiAgICAgICk7XG4gICAgICBpZiAodHJhY2spIHtcbiAgICAgICAgdGhpcy5oaXN0b3J5LnB1c2godHJhY2spO1xuICAgICAgICB0aGlzLm5vZGUucmVzZXRQcm9ncmVzcygpO1xuICAgICAgICB0aGlzLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LlBsYXllckZpbmlzaCwgdGhpcywgdHJhY2spO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuI2RlbGV0ZWQpIHJldHVybiB0aGlzLiNlbWl0RW5kKCk7XG4gICAgICBpZiAodGhpcy50cmFja3Muc2l6ZSA8IDEgJiYgdGhpcy5yZXBlYXRNb2RlID09PSBRdWV1ZVJlcGVhdE1vZGUuT0ZGKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgICB0aGlzLmRlYnVnKFxuICAgICAgICAgICdObyBtb3JlIHRyYWNrcyBsZWZ0IGluIHRoZSBxdWV1ZSB0byBwbGF5IGFuZCByZXBlYXQgbW9kZSBpcyBvZmYsIGluaXRpYXRpbmcgI2VtaXRFbmQoKSdcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy4jZW1pdEVuZCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMucmVwZWF0TW9kZSA9PT0gUXVldWVSZXBlYXRNb2RlLlRSQUNLKSB7XG4gICAgICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgICAgICAgdGhpcy5kZWJ1ZyhcbiAgICAgICAgICAgICdSZXBlYXQgbW9kZSBpcyBzZXQgdG8gdHJhY2ssIHJlcGVhdGluZyBsYXN0IHRyYWNrIGZyb20gdGhlIGhpc3RvcnkuLi4nXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLl9fY3VycmVudCA9IHRoaXMuaGlzdG9yeS50cmFja3MuZGlzcGF0Y2goKSB8fCB0cmFjaztcbiAgICAgICAgICByZXR1cm4gdGhpcy5ub2RlLnBsYXkodGhpcy5fX2N1cnJlbnQhLCB7IHF1ZXVlOiBmYWxzZSB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5yZXBlYXRNb2RlID09PSBRdWV1ZVJlcGVhdE1vZGUuUVVFVUUpIHtcbiAgICAgICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICAgICAgICB0aGlzLmRlYnVnKFxuICAgICAgICAgICAgJ1JlcGVhdCBtb2RlIGlzIHNldCB0byBxdWV1ZSwgbW92aW5nIGxhc3QgdHJhY2sgZnJvbSB0aGUgaGlzdG9yeSB0byBjdXJyZW50IHF1ZXVlLi4uJ1xuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgbmV4dCA9IHRoaXMuaGlzdG9yeS50cmFja3MuZGlzcGF0Y2goKSB8fCB0cmFjaztcbiAgICAgICAgICBpZiAobmV4dCkgdGhpcy50cmFja3MuYWRkKG5leHQpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy50cmFja3Muc2l6ZSAmJiB0cmFjaykge1xuICAgICAgICAgIGlmICh0aGlzLnJlcGVhdE1vZGUgPT09IFF1ZXVlUmVwZWF0TW9kZS5BVVRPUExBWSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgICAgICAgICB0aGlzLmRlYnVnKFxuICAgICAgICAgICAgICAnUmVwZWF0IG1vZGUgaXMgc2V0IHRvIGF1dG9wbGF5LCBpbml0aWF0aW5nIGF1dG9wbGF5IGhhbmRsZXIuLi4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy4jaGFuZGxlQXV0b3BsYXkodHJhY2spO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICAgICAgICB0aGlzLmRlYnVnKCdJbml0aWFsaXppbmcgbmV4dCB0cmFjayBvZiB0aGUgcXVldWUuLi4nKTtcbiAgICAgICAgICB0aGlzLl9fY3VycmVudCA9IHRoaXMuI2dldE5leHRUcmFjaygpITtcbiAgICAgICAgICB0aGlzLm5vZGUucGxheSh0aGlzLl9fY3VycmVudCwge1xuICAgICAgICAgICAgcXVldWU6IGZhbHNlXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAjZW1pdEVuZCgpIHtcbiAgICB0aGlzLl9fY3VycmVudCA9IG51bGw7XG4gICAgdGhpcy5lbWl0KEd1aWxkUXVldWVFdmVudC5FbXB0eVF1ZXVlLCB0aGlzKTtcbiAgICBpZiAodGhpcy5vcHRpb25zLmxlYXZlT25FbmQpIHtcbiAgICAgIGNvbnN0IHRtOiBOb2RlSlMuVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5pc1BsYXlpbmcoKSkgcmV0dXJuIGNsZWFyVGltZW91dCh0bSk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hlcj8uZGlzY29ubmVjdCgpO1xuICAgICAgfSwgdGhpcy5vcHRpb25zLmxlYXZlT25FbmRDb29sZG93bikudW5yZWYoKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyAjaGFuZGxlQXV0b3BsYXkodHJhY2s6IFRyYWNrKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5kZWJ1ZyhcbiAgICAgICAgYEF1dG9wbGF5ID4+IEZpbmRpbmcgcmVsYXRlZCB0cmFja3MgZm9yIFRyYWNrICR7dHJhY2sudGl0bGV9ICgke1xuICAgICAgICB0cmFjay51cmx9KSBbZXh0OiR7XG4gICAgICAgIHRyYWNrLmV4dHJhY3Rvcj8uaWRlbnRpZmllciB8fCAnTi9BJ31dYFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHRyYWNrcyA9XG4gICAgICAoYXdhaXQgdHJhY2suZXh0cmFjdG9yPy5nZXRSZWxhdGVkVHJhY2tzKHRyYWNrLCB0aGlzLmhpc3RvcnkpKT8uXG4gICAgICB0cmFja3MgfHxcbiAgICAgIChcbiAgICAgIGF3YWl0IHRoaXMucGxheWVyLmV4dHJhY3RvcnMucnVuKGFzeW5jIChleHQpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgICAgIHRoaXMuZGVidWcoYEF1dG9wbGF5ID4+IFF1ZXJ5aW5nIGV4dHJhY3RvciAke2V4dC5pZGVudGlmaWVyfWApO1xuICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBleHQuZ2V0UmVsYXRlZFRyYWNrcyh0cmFjaywgdGhpcy5oaXN0b3J5KTtcbiAgICAgICAgaWYgKCFyZXMudHJhY2tzLmxlbmd0aCkge1xuICAgICAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgICAgIHRoaXMuZGVidWcoXG4gICAgICAgICAgICBgQXV0b3BsYXkgPj4gRXh0cmFjdG9yICR7ZXh0LmlkZW50aWZpZXJ9IGZhaWxlZCB0byBwcm92aWRlIHJlc3VsdHMuYFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgICAgIHRoaXMuZGVidWcoXG4gICAgICAgICAgYEF1dG9wbGF5ID4+IEV4dHJhY3RvciAke2V4dC5pZGVudGlmaWVyfSBzdWNjZXNzZnVsbHkgcmV0dXJuZWQgcmVzdWx0cy5gXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIHJlcy50cmFja3M7XG4gICAgICB9KSk/LlxuICAgICAgcmVzdWx0IHx8XG4gICAgICBbXTtcblxuICAgICAgbGV0IHJlc29sdmVyOiAodHJhY2s6IFRyYWNrIHwgbnVsbCkgPT4gdm9pZCA9IFV0aWwubm9vcDtcbiAgICAgIGNvbnN0IGRvbmVQcm9taXNlID0gbmV3IFByb21pc2U8VHJhY2sgfCBudWxsPihcbiAgICAgICAgKHJlc29sdmUpID0+IHJlc29sdmVyID0gcmVzb2x2ZVxuICAgICAgKTtcblxuICAgICAgY29uc3Qgc3VjY2VzcyA9IHRoaXMuZW1pdChcbiAgICAgICAgR3VpbGRRdWV1ZUV2ZW50LldpbGxBdXRvUGxheSxcbiAgICAgICAgdGhpcyxcbiAgICAgICAgdHJhY2tzLFxuICAgICAgICByZXNvbHZlciFcbiAgICAgICk7XG5cbiAgICAgIC8vIHByZXZlbnQgZGFuZ2xpbmcgcHJvbWlzZVxuICAgICAgaWYgKCFzdWNjZXNzKSB7XG4gICAgICAgIHJlc29sdmVyKFxuICAgICAgICAgIHRyYWNrcy5sZW5ndGggP1xuICAgICAgICAgICgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB1bmlxdWUgPSB0cmFja3MuZmlsdGVyKFxuICAgICAgICAgICAgICAodHIpID0+ICF0aGlzLmhpc3RvcnkudHJhY2tzLmZpbmQoKHQpID0+IHQudXJsID09PSB0ci51cmwpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHVuaXF1ZT8uWzBdID8/IFV0aWwucmFuZG9tQ2hvaWNlKHRyYWNrcy5zbGljZSgwLCA1KSk7XG4gICAgICAgICAgfSkoKSA6XG4gICAgICAgICAgbnVsbFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBuZXh0VHJhY2sgPSBhd2FpdCBkb25lUHJvbWlzZTtcblxuICAgICAgaWYgKCFuZXh0VHJhY2spIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgICAgIHRoaXMuZGVidWcoJ0F1dG9wbGF5ID4+IE5vIHRyYWNrIHdhcyBmb3VuZCwgaW5pdGlhdGluZyAjZW1pdEVuZCgpJyk7XG4gICAgICAgIHRocm93ICdObyB0cmFjayB3YXMgZm91bmQnO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCB0aGlzLm5vZGUucGxheShuZXh0VHJhY2ssIHtcbiAgICAgICAgcXVldWU6IGZhbHNlLFxuICAgICAgICBzZWVrOiAwLFxuICAgICAgICB0cmFuc2l0aW9uTW9kZTogZmFsc2VcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHRoaXMuI2VtaXRFbmQoKTtcbiAgICB9XG4gIH1cbn0iLCAiaW1wb3J0IHtcbiAgQXVkaW9QbGF5ZXIsXG4gIEF1ZGlvUGxheWVyRXJyb3IsXG4gIEF1ZGlvUGxheWVyU3RhdHVzLFxuICBBdWRpb1Jlc291cmNlLFxuICBjcmVhdGVBdWRpb1BsYXllcixcbiAgY3JlYXRlQXVkaW9SZXNvdXJjZSxcbiAgZW50ZXJzU3RhdGUsXG4gIFN0cmVhbVR5cGUsXG4gIFZvaWNlQ29ubmVjdGlvbixcbiAgVm9pY2VDb25uZWN0aW9uU3RhdHVzLFxuICBWb2ljZUNvbm5lY3Rpb25EaXNjb25uZWN0UmVhc29uIH0gZnJvbVxuJ2Rpc2NvcmQtdm9pcCc7XG5pbXBvcnQgeyBTdGFnZUNoYW5uZWwsIFZvaWNlQ2hhbm5lbCB9IGZyb20gJ2Rpc2NvcmQuanMnO1xuaW1wb3J0IHR5cGUgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBFdmVudEVtaXR0ZXIgfSBmcm9tICdAZGlzY29yZC1wbGF5ZXIvdXRpbHMnO1xuaW1wb3J0IHsgVHJhY2sgfSBmcm9tICcuLi9mYWJyaWMvVHJhY2snO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uL3V0aWxzL1V0aWwnO1xuaW1wb3J0IHtcbiAgRXF1YWxpemVyQmFuZCxcbiAgQmlxdWFkRmlsdGVycyxcbiAgUENNRmlsdGVycyxcbiAgRmlsdGVyc0NoYWluLFxuICBDb21wcmVzc29yUGFyYW1ldGVycyxcbiAgUmV2ZXJiUGFyYW1ldGVycyxcbiAgU2Vla2VyUGFyYW1ldGVycyxcbiAgUmVzYW1wbGVQYXJhbWV0ZXJzLFxuICBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQsXG4gIFNlZWtFdmVudCB9IGZyb21cbidAZGlzY29yZC1wbGF5ZXIvZXF1YWxpemVyJztcbmltcG9ydCB7IEd1aWxkUXVldWUsIEd1aWxkUXVldWVFdmVudCwgUG9zdFByb2Nlc3NlZFJlc3VsdCB9IGZyb20gJy4uL3F1ZXVlJztcbmltcG9ydCB7IE5vQXVkaW9SZXNvdXJjZUVycm9yIH0gZnJvbSAnLi4vZXJyb3JzJztcbmltcG9ydCB7IEludGVyY2VwdGVkU3RyZWFtIH0gZnJvbSAnLi9JbnRlcmNlcHRlZFN0cmVhbSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlU3RyZWFtT3BzIHtcbiAgdHlwZT86IFN0cmVhbVR5cGU7XG4gIGRhdGE6IFRyYWNrO1xuICBkaXNhYmxlVm9sdW1lPzogYm9vbGVhbjtcbiAgZGlzYWJsZUVxdWFsaXplcj86IGJvb2xlYW47XG4gIGRpc2FibGVCaXF1YWQ/OiBib29sZWFuO1xuICBkaXNhYmxlQ29tcHJlc3Nvcj86IGJvb2xlYW47XG4gIGRpc2FibGVSZXNhbXBsZXI/OiBib29sZWFuO1xuICBkaXNhYmxlUmV2ZXJiPzogYm9vbGVhbjtcbiAgZGlzYWJsZVNlZWtlcj86IGJvb2xlYW47XG4gIGVxPzogRXF1YWxpemVyQmFuZFtdO1xuICBiaXF1YWRGaWx0ZXI/OiBCaXF1YWRGaWx0ZXJzO1xuICBkaXNhYmxlRmlsdGVycz86IGJvb2xlYW47XG4gIGRlZmF1bHRGaWx0ZXJzPzogUENNRmlsdGVyc1tdO1xuICB2b2x1bWU/OiBudW1iZXI7XG4gIHNhbXBsZVJhdGU/OiBudW1iZXI7XG4gIHNhbXBsZVJhdGVGaWx0ZXJzPzogQ29tbW9uUmVzYW1wbGVyRmlsdGVyUHJlc2V0O1xuICBza2lwRkZtcGVnPzogYm9vbGVhbjtcbiAgY29tcHJlc3Nvcj86IHtcbiAgICB0aHJlc2hvbGQ6IG51bWJlcjtcbiAgICByYXRpbzogbnVtYmVyO1xuICAgIGF0dGFjazogbnVtYmVyO1xuICAgIHJlbGVhc2U6IG51bWJlcjtcbiAgICBtYWtldXBHYWluOiBudW1iZXI7XG4gICAga25lZVdpZHRoOiBudW1iZXI7XG4gIH07XG4gIHJldmVyYj86IHtcbiAgICByb29tU2l6ZTogbnVtYmVyO1xuICAgIGRhbXBpbmc6IG51bWJlcjtcbiAgICB3ZXRMZXZlbDogbnVtYmVyO1xuICAgIGRyeUxldmVsOiBudW1iZXI7XG4gIH07XG4gIHNlZWtlcj86IHtcbiAgICBzZWVrVGFyZ2V0OiBudW1iZXIgfCBudWxsO1xuICAgIHRvdGFsRHVyYXRpb246IG51bWJlcjtcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWb2ljZUV2ZW50cyB7XG4gIC8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbiAgZXJyb3I6IChlcnJvcjogQXVkaW9QbGF5ZXJFcnJvcikgPT4gYW55O1xuICBkZWJ1ZzogKG1lc3NhZ2U6IHN0cmluZykgPT4gYW55O1xuICBzdGFydDogKHJlc291cmNlOiBBdWRpb1Jlc291cmNlPFRyYWNrPikgPT4gYW55O1xuICBmaW5pc2g6IChyZXNvdXJjZTogQXVkaW9SZXNvdXJjZTxUcmFjaz4pID0+IGFueTtcbiAgZHNwOiAoZmlsdGVyczogUENNRmlsdGVyc1tdKSA9PiBhbnk7XG4gIGVxQmFuZHM6IChmaWx0ZXJzOiBFcXVhbGl6ZXJCYW5kW10pID0+IGFueTtcbiAgc2FtcGxlUmF0ZTogKGZpbHRlcnM6IFJlc2FtcGxlUGFyYW1ldGVycykgPT4gYW55O1xuICBiaXF1YWQ6IChmaWx0ZXJzOiBCaXF1YWRGaWx0ZXJzKSA9PiBhbnk7XG4gIGNvbXByZXNzb3I6IChmaWx0ZXJzOiBDb21wcmVzc29yUGFyYW1ldGVycykgPT4gYW55O1xuICByZXZlcmI6IChmaWx0ZXJzOiBSZXZlcmJQYXJhbWV0ZXJzKSA9PiBhbnk7XG4gIHNlZWtlcjogKGZpbHRlcnM6IFNlZWtlclBhcmFtZXRlcnMpID0+IGFueTtcbiAgdm9sdW1lOiAodm9sdW1lOiBudW1iZXIpID0+IGFueTtcbiAgZGVzdHJveWVkOiAoKSA9PiBhbnk7XG4gIC8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xufVxuXG5jbGFzcyBTdHJlYW1EaXNwYXRjaGVyIGV4dGVuZHMgRXZlbnRFbWl0dGVyPFZvaWNlRXZlbnRzPiB7XG4gIHB1YmxpYyB2b2ljZUNvbm5lY3Rpb246IFZvaWNlQ29ubmVjdGlvbjtcbiAgcHVibGljIGF1ZGlvUGxheWVyOiBBdWRpb1BsYXllcjtcbiAgcHVibGljIGNoYW5uZWw6IFZvaWNlQ2hhbm5lbCB8IFN0YWdlQ2hhbm5lbDtcbiAgcHVibGljIGF1ZGlvUmVzb3VyY2U/OiBBdWRpb1Jlc291cmNlPFRyYWNrPiB8IG51bGw7XG4gIHB1YmxpYyBkc3AgPSBuZXcgRmlsdGVyc0NoYWluKCk7XG5cbiAgI2ludGVyY2VwdG9yOiBJbnRlcmNlcHRlZFN0cmVhbSB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIG5ldyBjb25uZWN0aW9uIG9iamVjdFxuICAgKiBAcGFyYW0ge1ZvaWNlQ29ubmVjdGlvbn0gY29ubmVjdGlvbiBUaGUgY29ubmVjdGlvblxuICAgKiBAcGFyYW0ge1ZvaWNlQ2hhbm5lbHxTdGFnZUNoYW5uZWx9IGNoYW5uZWwgVGhlIGNvbm5lY3RlZCBjaGFubmVsXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgY29ubmVjdGlvbjogVm9pY2VDb25uZWN0aW9uLFxuICBjaGFubmVsOiBWb2ljZUNoYW5uZWwgfCBTdGFnZUNoYW5uZWwsXG4gIHB1YmxpYyBxdWV1ZTogR3VpbGRRdWV1ZSxcbiAgcHVibGljIHJlYWRvbmx5IGNvbm5lY3Rpb25UaW1lb3V0OiBudW1iZXIgPSAyMDAwMCxcbiAgYXVkaW9QbGF5ZXI/OiBBdWRpb1BsYXllcilcbiAge1xuICAgIHN1cGVyKCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdm9pY2UgY29ubmVjdGlvblxuICAgICAqIEB0eXBlIHtWb2ljZUNvbm5lY3Rpb259XG4gICAgICovXG4gICAgdGhpcy52b2ljZUNvbm5lY3Rpb24gPSBjb25uZWN0aW9uO1xuXG4gICAgLyoqXG4gICAgICogVGhlIGF1ZGlvIHBsYXllclxuICAgICAqIEB0eXBlIHtBdWRpb1BsYXllcn1cbiAgICAgKi9cbiAgICB0aGlzLmF1ZGlvUGxheWVyID1cbiAgICBhdWRpb1BsYXllciB8fFxuICAgIGNyZWF0ZUF1ZGlvUGxheWVyKHtcbiAgICAgIGRlYnVnOiB0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgdm9pY2UgY2hhbm5lbFxuICAgICAqIEB0eXBlIHtWb2ljZUNoYW5uZWx8U3RhZ2VDaGFubmVsfVxuICAgICAqL1xuICAgIHRoaXMuY2hhbm5lbCA9IGNoYW5uZWw7XG5cbiAgICB0aGlzLnZvaWNlQ29ubmVjdGlvbi5vbignZGVidWcnLCAobSkgPT4gdm9pZCB0aGlzLmVtaXQoJ2RlYnVnJywgbSkpO1xuICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLm9uKFxuICAgICAgJ2Vycm9yJyxcbiAgICAgIChlcnJvcikgPT4gdm9pZCB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IgYXMgQXVkaW9QbGF5ZXJFcnJvcilcbiAgICApO1xuICAgIHRoaXMuYXVkaW9QbGF5ZXIub24oJ2RlYnVnJywgKG0pID0+IHZvaWQgdGhpcy5lbWl0KCdkZWJ1ZycsIG0pKTtcbiAgICB0aGlzLmF1ZGlvUGxheWVyLm9uKCdlcnJvcicsIChlcnJvcikgPT4gdm9pZCB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyb3IpKTtcblxuICAgIHRoaXMuZHNwLm9uVXBkYXRlID0gKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLmRzcCkgcmV0dXJuO1xuXG4gICAgICBpZiAodGhpcy5kc3AuZmlsdGVycz8uZmlsdGVycykge1xuICAgICAgICB0aGlzLmVtaXQoJ2RzcCcsIHRoaXMuZHNwLmZpbHRlcnM/LmZpbHRlcnMpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5kc3AuYmlxdWFkPy5maWx0ZXJzKSB7XG4gICAgICAgIHRoaXMuZW1pdCgnYmlxdWFkJywgdGhpcy5kc3AuYmlxdWFkPy5maWx0ZXJzKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZHNwLmVxdWFsaXplcikge1xuICAgICAgICB0aGlzLmVtaXQoJ2VxQmFuZHMnLCB0aGlzLmRzcC5lcXVhbGl6ZXIuZ2V0RVEoKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmRzcC52b2x1bWUpIHtcbiAgICAgICAgdGhpcy5lbWl0KCd2b2x1bWUnLCB0aGlzLmRzcC52b2x1bWUudm9sdW1lKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZHNwLnJlc2FtcGxlcikge1xuICAgICAgICB0aGlzLmVtaXQoJ3NhbXBsZVJhdGUnLCB0aGlzLmRzcC5yZXNhbXBsZXIuZ2V0UGFyYW1ldGVycygpKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmRzcC5jb21wcmVzc29yKSB7XG4gICAgICAgIHRoaXMuZW1pdCgnY29tcHJlc3NvcicsIHRoaXMuZHNwLmNvbXByZXNzb3IuZ2V0UGFyYW1ldGVycygpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuZHNwLnJldmVyYikge1xuICAgICAgICB0aGlzLmVtaXQoJ3JldmVyYicsIHRoaXMuZHNwLnJldmVyYi5nZXRQYXJhbWV0ZXJzKCkpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5kc3Auc2Vla2VyKSB7XG4gICAgICAgIHRoaXMuZW1pdCgnc2Vla2VyJywgdGhpcy5kc3Auc2Vla2VyLmdldFBhcmFtZXRlcnMoKSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuZHNwLm9uRXJyb3IgPSAoZSkgPT4gdGhpcy5lbWl0KCdlcnJvcicsIGUgYXMgQXVkaW9QbGF5ZXJFcnJvcik7XG5cbiAgICB0aGlzLnZvaWNlQ29ubmVjdGlvbi5cbiAgICBvbihWb2ljZUNvbm5lY3Rpb25TdGF0dXMuRGlzY29ubmVjdGVkLCBhc3luYyAob2xkU3RhdGUsIG5ld1N0YXRlKSA9PiB7XG4gICAgICBpZiAobmV3U3RhdGUucmVhc29uID09PSBWb2ljZUNvbm5lY3Rpb25EaXNjb25uZWN0UmVhc29uLk1hbnVhbCkge1xuICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICBuZXdTdGF0ZS5yZWFzb24gPT09IFZvaWNlQ29ubmVjdGlvbkRpc2Nvbm5lY3RSZWFzb24uV2ViU29ja2V0Q2xvc2UgJiZcbiAgICAgIG5ld1N0YXRlLmNsb3NlQ29kZSA9PT0gNDAxNClcbiAgICAgIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlbnRlcnNTdGF0ZShcbiAgICAgICAgICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLFxuICAgICAgICAgICAgVm9pY2VDb25uZWN0aW9uU3RhdHVzLkNvbm5lY3RpbmcsXG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb25UaW1lb3V0XG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLnN0YXRlLnN0YXR1cyAhPT1cbiAgICAgICAgICAgIFZvaWNlQ29ubmVjdGlvblN0YXR1cy5EZXN0cm95ZWQpXG5cbiAgICAgICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgdGhpcy5lbWl0KCdlcnJvcicsIGVyciBhcyBBdWRpb1BsYXllckVycm9yKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodGhpcy52b2ljZUNvbm5lY3Rpb24ucmVqb2luQXR0ZW1wdHMgPCA1KSB7XG4gICAgICAgIGF3YWl0IFV0aWwud2FpdCgodGhpcy52b2ljZUNvbm5lY3Rpb24ucmVqb2luQXR0ZW1wdHMgKyAxKSAqIDUwMDApO1xuICAgICAgICB0aGlzLnZvaWNlQ29ubmVjdGlvbi5yZWpvaW4oKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLnN0YXRlLnN0YXR1cyAhPT1cbiAgICAgICAgICBWb2ljZUNvbm5lY3Rpb25TdGF0dXMuRGVzdHJveWVkKVxuXG4gICAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHRoaXMuZW1pdCgnZXJyb3InLCBlcnIgYXMgQXVkaW9QbGF5ZXJFcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KS5cbiAgICBvbihWb2ljZUNvbm5lY3Rpb25TdGF0dXMuRGVzdHJveWVkLCAoKSA9PiB7XG4gICAgICB0aGlzLmVuZCgpO1xuICAgICAgdGhpcy5xdWV1ZS5lbWl0KEd1aWxkUXVldWVFdmVudC5Db25uZWN0aW9uRGVzdHJveWVkLCB0aGlzLnF1ZXVlKTtcbiAgICB9KTtcblxuICAgIHRoaXMuYXVkaW9QbGF5ZXIub24oJ3N0YXRlQ2hhbmdlJywgKG9sZFN0YXRlLCBuZXdTdGF0ZSkgPT4ge1xuICAgICAgaWYgKFxuICAgICAgb2xkU3RhdGUuc3RhdHVzICE9PSBBdWRpb1BsYXllclN0YXR1cy5QYXVzZWQgJiZcbiAgICAgIG5ld1N0YXRlLnN0YXR1cyA9PT0gQXVkaW9QbGF5ZXJTdGF0dXMuUGF1c2VkKVxuICAgICAge1xuICAgICAgICB0aGlzLnF1ZXVlLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LlBsYXllclBhdXNlLCB0aGlzLnF1ZXVlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgb2xkU3RhdGUuc3RhdHVzID09PSBBdWRpb1BsYXllclN0YXR1cy5QYXVzZWQgJiZcbiAgICAgIG5ld1N0YXRlLnN0YXR1cyAhPT0gQXVkaW9QbGF5ZXJTdGF0dXMuUGF1c2VkKVxuICAgICAge1xuICAgICAgICB0aGlzLnF1ZXVlLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LlBsYXllclJlc3VtZSwgdGhpcy5xdWV1ZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChuZXdTdGF0ZS5zdGF0dXMgPT09IEF1ZGlvUGxheWVyU3RhdHVzLlBsYXlpbmcpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICBvbGRTdGF0ZS5zdGF0dXMgPT09IEF1ZGlvUGxheWVyU3RhdHVzLklkbGUgfHxcbiAgICAgICAgb2xkU3RhdGUuc3RhdHVzID09PSBBdWRpb1BsYXllclN0YXR1cy5CdWZmZXJpbmcpXG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5lbWl0KCdzdGFydCcsIHRoaXMuYXVkaW9SZXNvdXJjZSEpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgbmV3U3RhdGUuc3RhdHVzID09PSBBdWRpb1BsYXllclN0YXR1cy5JZGxlICYmXG4gICAgICBvbGRTdGF0ZS5zdGF0dXMgIT09IEF1ZGlvUGxheWVyU3RhdHVzLklkbGUpXG4gICAgICB7XG4gICAgICAgIHRoaXMuZW1pdCgnZmluaXNoJywgdGhpcy5hdWRpb1Jlc291cmNlISk7XG4gICAgICAgIHRoaXMuZHNwLmRlc3Ryb3koKTtcbiAgICAgICAgdGhpcy5hdWRpb1Jlc291cmNlID0gbnVsbDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLnN1YnNjcmliZSh0aGlzLmF1ZGlvUGxheWVyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgcGxheWVyIGhhcyBiZWVuIHBhdXNlZCBtYW51YWxseVxuICAgKi9cbiAgZ2V0IHBhdXNlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5hdWRpb1BsYXllci5zdGF0ZS5zdGF0dXMgPT09IEF1ZGlvUGxheWVyU3RhdHVzLlBhdXNlZDtcbiAgfVxuXG4gIHNldCBwYXVzZWQodmFsOiBib29sZWFuKSB7XG4gICAgdmFsID8gdGhpcy5wYXVzZSh0cnVlKSA6IHRoaXMucmVzdW1lKCk7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciBvciBub3QgdGhlIHBsYXllciBpcyBjdXJyZW50bHkgcGF1c2VkIGF1dG9tYXRpY2FsbHkgb3IgbWFudWFsbHkuXG4gICAqL1xuICBpc1BhdXNlZCgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5wYXVzZWQgfHxcbiAgICAgIHRoaXMuYXVkaW9QbGF5ZXIuc3RhdGUuc3RhdHVzID09PSBBdWRpb1BsYXllclN0YXR1cy5BdXRvUGF1c2VkKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRoZSBwbGF5ZXIgaXMgY3VycmVudGx5IGJ1ZmZlcmluZ1xuICAgKi9cbiAgaXNCdWZmZXJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXVkaW9QbGF5ZXIuc3RhdGUuc3RhdHVzID09PSBBdWRpb1BsYXllclN0YXR1cy5CdWZmZXJpbmc7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciBvciBub3QgdGhlIHBsYXllciBpcyBjdXJyZW50bHkgcGxheWluZ1xuICAgKi9cbiAgaXNQbGF5aW5nKCkge1xuICAgIHJldHVybiB0aGlzLmF1ZGlvUGxheWVyLnN0YXRlLnN0YXR1cyA9PT0gQXVkaW9QbGF5ZXJTdGF0dXMuUGxheWluZztcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgcGxheWVyIGlzIGN1cnJlbnRseSBpZGxlXG4gICAqL1xuICBpc0lkbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXVkaW9QbGF5ZXIuc3RhdGUuc3RhdHVzID09PSBBdWRpb1BsYXllclN0YXR1cy5JZGxlO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRoZSB2b2ljZSBjb25uZWN0aW9uIGhhcyBiZWVuIGRlc3Ryb3llZFxuICAgKi9cbiAgaXNEZXN0cm95ZWQoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLnN0YXRlLnN0YXR1cyA9PT0gVm9pY2VDb25uZWN0aW9uU3RhdHVzLkRlc3Ryb3llZCk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0aGUgdm9pY2UgY29ubmVjdGlvbiBoYXMgYmVlbiBkZXN0cm95ZWRcbiAgICovXG4gIGlzRGlzY29ubmVjdGVkKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnZvaWNlQ29ubmVjdGlvbi5zdGF0ZS5zdGF0dXMgPT09IFZvaWNlQ29ubmVjdGlvblN0YXR1cy5EaXNjb25uZWN0ZWQpO1xuXG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciBvciBub3QgdGhlIHZvaWNlIGNvbm5lY3Rpb24gaXMgcmVhZHkgdG8gcGxheVxuICAgKi9cbiAgaXNSZWFkeSgpIHtcbiAgICByZXR1cm4gdGhpcy52b2ljZUNvbm5lY3Rpb24uc3RhdGUuc3RhdHVzID09PSBWb2ljZUNvbm5lY3Rpb25TdGF0dXMuUmVhZHk7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciBvciBub3QgdGhlIHZvaWNlIGNvbm5lY3Rpb24gaXMgc2lnbmFsbGluZ1xuICAgKi9cbiAgaXNTaWduYWxsaW5nKCkge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLnZvaWNlQ29ubmVjdGlvbi5zdGF0ZS5zdGF0dXMgPT09IFZvaWNlQ29ubmVjdGlvblN0YXR1cy5TaWduYWxsaW5nKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHRoZSB2b2ljZSBjb25uZWN0aW9uIGlzIGNvbm5lY3RpbmdcbiAgICovXG4gIGlzQ29ubmVjdGluZygpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy52b2ljZUNvbm5lY3Rpb24uc3RhdGUuc3RhdHVzID09PSBWb2ljZUNvbm5lY3Rpb25TdGF0dXMuQ29ubmVjdGluZyk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIHN0cmVhbVxuICAgKiBAcGFyYW0ge1JlYWRhYmxlfSBzcmMgVGhlIHN0cmVhbSBzb3VyY2VcbiAgICogQHBhcmFtIHtvYmplY3R9IFtvcHNdIE9wdGlvbnNcbiAgICogQHJldHVybnMge0F1ZGlvUmVzb3VyY2V9XG4gICAqL1xuICBhc3luYyBjcmVhdGVTdHJlYW0oc3JjOiBSZWFkYWJsZSwgb3BzOiBDcmVhdGVTdHJlYW1PcHMpIHtcbiAgICBpZiAoIW9wcz8uZGlzYWJsZUZpbHRlcnMgJiYgdGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLnF1ZXVlLmRlYnVnKCdJbml0aWF0aW5nIERTUCBmaWx0ZXJzIHBpcGVsaW5lLi4uJyk7XG4gICAgY29uc3Qgc3RyZWFtID0gIW9wcz8uZGlzYWJsZUZpbHRlcnMgP1xuICAgIHRoaXMuZHNwLmNyZWF0ZShzcmMsIHtcbiAgICAgIGRzcDoge1xuICAgICAgICBmaWx0ZXJzOiBvcHM/LmRlZmF1bHRGaWx0ZXJzLFxuICAgICAgICBkaXNhYmxlZDogb3BzPy5kaXNhYmxlRmlsdGVyc1xuICAgICAgfSxcbiAgICAgIGJpcXVhZDogb3BzPy5iaXF1YWRGaWx0ZXIgP1xuICAgICAge1xuICAgICAgICBmaWx0ZXI6IG9wcy5iaXF1YWRGaWx0ZXIsXG4gICAgICAgIGRpc2FibGVkOiBvcHM/LmRpc2FibGVCaXF1YWRcbiAgICAgIH0gOlxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgcmVzYW1wbGVyOiBvcHM/LnNhbXBsZVJhdGUgP1xuICAgICAge1xuICAgICAgICBpbnB1dFNhbXBsZVJhdGU6IDQ4MDAwLFxuICAgICAgICB0YXJnZXRTYW1wbGVSYXRlOiBvcHM/LnNhbXBsZVJhdGUsXG4gICAgICAgIGRpc2FibGVkOiBvcHM/LmRpc2FibGVSZXNhbXBsZXJcbiAgICAgIH0gOlxuICAgICAgdW5kZWZpbmVkLFxuICAgICAgZXF1YWxpemVyOiB7XG4gICAgICAgIGJhbmRNdWx0aXBsaWVyOiBvcHM/LmVxLFxuICAgICAgICBkaXNhYmxlZDogb3BzPy5kaXNhYmxlRXF1YWxpemVyXG4gICAgICB9LFxuICAgICAgdm9sdW1lOiB7XG4gICAgICAgIHZvbHVtZTogb3BzPy52b2x1bWUsXG4gICAgICAgIGRpc2FibGVkOiBvcHM/LmRpc2FibGVWb2x1bWVcbiAgICAgIH0sXG4gICAgICBjb21wcmVzc29yOiBvcHM/LmNvbXByZXNzb3IgP1xuICAgICAge1xuICAgICAgICB0aHJlc2hvbGQ6IG9wcz8uY29tcHJlc3Nvci50aHJlc2hvbGQsXG4gICAgICAgIHJhdGlvOiBvcHM/LmNvbXByZXNzb3IucmF0aW8sXG4gICAgICAgIGF0dGFjazogb3BzPy5jb21wcmVzc29yLmF0dGFjayxcbiAgICAgICAgcmVsZWFzZTogb3BzPy5jb21wcmVzc29yLnJlbGVhc2UsXG4gICAgICAgIG1ha2V1cEdhaW46IG9wcz8uY29tcHJlc3Nvci5tYWtldXBHYWluLFxuICAgICAgICBkaXNhYmxlZDogb3BzPy5kaXNhYmxlQ29tcHJlc3NvcixcbiAgICAgICAga25lZVdpZHRoOiBvcHM/LmNvbXByZXNzb3Iua25lZVdpZHRoXG4gICAgICB9IDpcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHJldmVyYjogb3BzPy5yZXZlcmIgP1xuICAgICAge1xuICAgICAgICByb29tU2l6ZTogb3BzPy5yZXZlcmIucm9vbVNpemUsXG4gICAgICAgIGRhbXBpbmc6IG9wcz8ucmV2ZXJiLmRhbXBpbmcsXG4gICAgICAgIHdldExldmVsOiBvcHM/LnJldmVyYi53ZXRMZXZlbCxcbiAgICAgICAgZHJ5TGV2ZWw6IG9wcz8ucmV2ZXJiLmRyeUxldmVsLFxuICAgICAgICBkaXNhYmxlZDogb3BzPy5kaXNhYmxlUmV2ZXJiXG4gICAgICB9IDpcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHNlZWtlcjogb3BzPy5zZWVrZXIgP1xuICAgICAge1xuICAgICAgICBkaXNhYmxlZDogb3BzPy5kaXNhYmxlU2Vla2VyLFxuICAgICAgICBzZWVrVGFyZ2V0OiBvcHM/LnNlZWtlci5zZWVrVGFyZ2V0LFxuICAgICAgICBzYW1wbGVSYXRlOiA0ODAwMCxcbiAgICAgICAgY2hhbm5lbHM6IDIsXG4gICAgICAgIHRvdGFsRHVyYXRpb246IG9wcz8uc2Vla2VyLnRvdGFsRHVyYXRpb25cbiAgICAgIH0gOlxuICAgICAgdW5kZWZpbmVkXG4gICAgfSkgOlxuICAgIHNyYztcblxuICAgIGlmICh0aGlzLmRzcC5zZWVrZXIpIHtcbiAgICAgIC8vIHVzZWQgdG8gaGFuZGxlIGJhY2t3YXJkIHNlZWtpbmdcbiAgICAgIHRoaXMuZHNwLnNlZWtlci5vbignc2VlaycsIChkYXRhOiBTZWVrRXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy5xdWV1ZS5ub2RlLnJlcXVlc3RTZWVrKGRhdGEpLmNhdGNoKCgpID0+IHt9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKSB7XG4gICAgICB0aGlzLnF1ZXVlLmRlYnVnKCdFeGVjdXRpbmcgb25BZnRlckNyZWF0ZVN0cmVhbSBob29rLi4uJyk7XG4gICAgfVxuXG4gICAgY29uc3QgcG9zdFN0cmVhbSA9IGF3YWl0IHRoaXMucXVldWUuXG4gICAgb25BZnRlckNyZWF0ZVN0cmVhbT8uKHN0cmVhbSwgdGhpcy5xdWV1ZSwgb3BzPy5kYXRhKS5cbiAgICBjYXRjaChcbiAgICAgICgpID0+XG4gICAgICAoe1xuICAgICAgICBzdHJlYW06IHN0cmVhbSxcbiAgICAgICAgdHlwZTogb3BzPy50eXBlID8/IFN0cmVhbVR5cGUuQXJiaXRyYXJ5XG4gICAgICB9KSBhcyBQb3N0UHJvY2Vzc2VkUmVzdWx0XG4gICAgKTtcblxuICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKSB0aGlzLnF1ZXVlLmRlYnVnKCdQcmVwYXJpbmcgQXVkaW9SZXNvdXJjZS4uLicpO1xuXG4gICAgY29uc3QgZm9ybWF0ID0gcG9zdFN0cmVhbT8udHlwZSA/PyBvcHM/LnR5cGUgPz8gU3RyZWFtVHlwZS5BcmJpdHJhcnk7XG5cbiAgICBsZXQgX3N0cmVhbTogUmVhZGFibGU7XG5cbiAgICBpZiAodGhpcy5xdWV1ZS5jYW5JbnRlcmNlcHQoKSkge1xuICAgICAgdGhpcy4jaW50ZXJjZXB0b3IgPSBuZXcgSW50ZXJjZXB0ZWRTdHJlYW0oKTtcblxuICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgKHBvc3RTdHJlYW0/LnN0cmVhbSA/PyBzdHJlYW0pLnBpcGUodGhpcy4jaW50ZXJjZXB0b3IpO1xuXG4gICAgICBfc3RyZWFtID0gdGhpcy4jaW50ZXJjZXB0b3I7XG5cbiAgICAgIGF3YWl0IHRoaXMucXVldWUucGxheWVyLmhhbmRsZUludGVyY2VwdGluZ1N0cmVhbShcbiAgICAgICAgdGhpcy5xdWV1ZSxcbiAgICAgICAgb3BzPy5kYXRhLFxuICAgICAgICBmb3JtYXQsXG4gICAgICAgIHRoaXMuI2ludGVyY2VwdG9yXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBfc3RyZWFtID0gcG9zdFN0cmVhbT8uc3RyZWFtID8/IHN0cmVhbTtcbiAgICB9XG5cbiAgICB0aGlzLmF1ZGlvUmVzb3VyY2UgPSBjcmVhdGVBdWRpb1Jlc291cmNlKF9zdHJlYW0sIHtcbiAgICAgIGlucHV0VHlwZTogZm9ybWF0LFxuICAgICAgbWV0YWRhdGE6IG9wcz8uZGF0YSBhcyBUcmFjayxcbiAgICAgIC8vIHZvbHVtZSBjb250cm9scyBoYXBwZW4gZnJvbSBBdWRpb0ZpbHRlciBEU1AgdXRpbGl0eVxuICAgICAgaW5saW5lVm9sdW1lOiBmYWxzZVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuYXVkaW9SZXNvdXJjZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgcmVzYW1wbGVyKCkge1xuICAgIHJldHVybiB0aGlzLmRzcD8ucmVzYW1wbGVyO1xuICB9XG5cbiAgcHVibGljIGdldCBmaWx0ZXJzKCkge1xuICAgIHJldHVybiB0aGlzLmRzcD8uZmlsdGVycztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYmlxdWFkKCkge1xuICAgIHJldHVybiB0aGlzLmRzcD8uYmlxdWFkIHx8IG51bGw7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGVxdWFsaXplcigpIHtcbiAgICByZXR1cm4gdGhpcy5kc3A/LmVxdWFsaXplciB8fCBudWxsO1xuICB9XG5cbiAgcHVibGljIGdldCBjb21wcmVzc29yKCkge1xuICAgIHJldHVybiB0aGlzLmRzcD8uY29tcHJlc3NvciB8fCBudWxsO1xuICB9XG5cbiAgcHVibGljIGdldCByZXZlcmIoKSB7XG4gICAgcmV0dXJuIHRoaXMuZHNwPy5yZXZlcmIgfHwgbnVsbDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc2Vla2VyKCkge1xuICAgIHJldHVybiB0aGlzLmRzcD8uc2Vla2VyIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHBsYXllciBzdGF0dXNcbiAgICogQHR5cGUge0F1ZGlvUGxheWVyU3RhdHVzfVxuICAgKi9cbiAgZ2V0IHN0YXR1cygpIHtcbiAgICByZXR1cm4gdGhpcy5hdWRpb1BsYXllci5zdGF0ZS5zdGF0dXM7XG4gIH1cblxuICAvKipcbiAgICogRGlzY29ubmVjdHMgZnJvbSB2b2ljZVxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGRpc2Nvbm5lY3QoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0aGlzLmF1ZGlvUGxheWVyKSB0aGlzLmF1ZGlvUGxheWVyLnN0b3AodHJ1ZSk7XG4gICAgICBpZiAodGhpcy52b2ljZUNvbm5lY3Rpb24uc3RhdGUuc3RhdHVzICE9PSBWb2ljZUNvbm5lY3Rpb25TdGF0dXMuRGVzdHJveWVkKVxuICAgICAgdGhpcy52b2ljZUNvbm5lY3Rpb24uZGVzdHJveSgpO1xuICAgIH0gY2F0Y2gge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1lbXB0eVxuICB9XG5cbiAgLyoqXG4gICAqIERlc3Ryb3lzIHRoaXMgZGlzcGF0Y2hlclxuICAgKi9cbiAgcHVibGljIGRlc3Ryb3koKSB7XG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHRoaXMuYXVkaW9QbGF5ZXIucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHRoaXMudm9pY2VDb25uZWN0aW9uLnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMuZHNwLmRlc3Ryb3koKTtcbiAgICB0aGlzLmF1ZGlvUmVzb3VyY2UgPSBudWxsO1xuICAgIHRoaXMuZW1pdCgnZGVzdHJveWVkJyk7XG4gIH1cblxuICAvKipcbiAgICogU3RvcHMgdGhlIHBsYXllclxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGVuZCgpIHtcbiAgICB0cnkge1xuICAgICAgdGhpcy5hdWRpb1BsYXllci5zdG9wKCk7XG4gICAgICB0aGlzLmRzcC5kZXN0cm95KCk7XG4gICAgfSBjYXRjaCB7XG5cbiAgICAgIC8vXG4gICAgfX1cblxuICAvKipcbiAgICogUGF1c2VzIHRoZSBzdHJlYW0gcGxheWJhY2tcbiAgICogQHBhcmFtIHtib29sZWFufSBbaW50ZXJwb2xhdGVTaWxlbmNlPWZhbHNlXSBJZiB0cnVlLCB0aGUgcGxheWVyIHdpbGwgcGxheSA1IHBhY2tldHMgb2Ygc2lsZW5jZSBhZnRlciBwYXVzaW5nIHRvIHByZXZlbnQgYXVkaW8gZ2xpdGNoZXMuXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgcGF1c2UoaW50ZXJwb2xhdGVTaWxlbmNlPzogYm9vbGVhbikge1xuICAgIGNvbnN0IHN1Y2Nlc3MgPSB0aGlzLmF1ZGlvUGxheWVyLnBhdXNlKGludGVycG9sYXRlU2lsZW5jZSk7XG4gICAgcmV0dXJuIHN1Y2Nlc3M7XG4gIH1cblxuICAvKipcbiAgICogUmVzdW1lcyB0aGUgc3RyZWFtIHBsYXliYWNrXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgcmVzdW1lKCkge1xuICAgIGNvbnN0IHN1Y2Nlc3MgPSB0aGlzLmF1ZGlvUGxheWVyLnVucGF1c2UoKTtcbiAgICByZXR1cm4gc3VjY2VzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBQbGF5IHN0cmVhbVxuICAgKiBAcGFyYW0ge0F1ZGlvUmVzb3VyY2U8VHJhY2s+fSBbcmVzb3VyY2U9dGhpcy5hdWRpb1Jlc291cmNlXSBUaGUgYXVkaW8gcmVzb3VyY2UgdG8gcGxheVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHVzPWZhbHNlXSBXaGV0aGVyIG9yIG5vdCB0byB1c2Ugb3B1c1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTdHJlYW1EaXNwYXRjaGVyPn1cbiAgICovXG4gIGFzeW5jIHBsYXlTdHJlYW0ocmVzb3VyY2U6IEF1ZGlvUmVzb3VyY2U8VHJhY2s+ID0gdGhpcy5hdWRpb1Jlc291cmNlISkge1xuICAgIGlmICghcmVzb3VyY2UpIHtcbiAgICAgIHRocm93IG5ldyBOb0F1ZGlvUmVzb3VyY2VFcnJvcigpO1xuICAgIH1cbiAgICBpZiAocmVzb3VyY2UuZW5kZWQpIHtcbiAgICAgIHJldHVybiB2b2lkIHRoaXMuZW1pdCgnZmluaXNoJywgcmVzb3VyY2UpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuYXVkaW9SZXNvdXJjZSkgdGhpcy5hdWRpb1Jlc291cmNlID0gcmVzb3VyY2U7XG4gICAgaWYgKHRoaXMudm9pY2VDb25uZWN0aW9uLnN0YXRlLnN0YXR1cyAhPT0gVm9pY2VDb25uZWN0aW9uU3RhdHVzLlJlYWR5KSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBlbnRlcnNTdGF0ZShcbiAgICAgICAgICB0aGlzLnZvaWNlQ29ubmVjdGlvbixcbiAgICAgICAgICBWb2ljZUNvbm5lY3Rpb25TdGF0dXMuUmVhZHksXG4gICAgICAgICAgdGhpcy5jb25uZWN0aW9uVGltZW91dFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHJldHVybiB2b2lkIHRoaXMuZW1pdCgnZXJyb3InLCBlcnIgYXMgQXVkaW9QbGF5ZXJFcnJvcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuYXVkaW9QbGF5ZXIucGxheShyZXNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5lbWl0KCdlcnJvcicsIGUgYXMgQXVkaW9QbGF5ZXJFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBwbGF5YmFjayB2b2x1bWVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSB2b2x1bWUgYW1vdW50XG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgc2V0Vm9sdW1lKHZhbHVlOiBudW1iZXIpIHtcbiAgICBpZiAoIXRoaXMuZHNwLnZvbHVtZSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0aGlzLmRzcC52b2x1bWUuc2V0Vm9sdW1lKHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCB2b2x1bWVcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCB2b2x1bWUoKSB7XG4gICAgaWYgKCF0aGlzLmRzcC52b2x1bWUpIHJldHVybiAxMDA7XG4gICAgcmV0dXJuIHRoaXMuZHNwLnZvbHVtZS52b2x1bWU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHBsYXliYWNrIHRpbWVcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCBzdHJlYW1UaW1lKCkge1xuICAgIGlmICghdGhpcy5hdWRpb1Jlc291cmNlKSByZXR1cm4gMDtcbiAgICByZXR1cm4gdGhpcy5hdWRpb1Jlc291cmNlLnBsYXliYWNrRHVyYXRpb247XG4gIH1cbn1cblxuZXhwb3J0IHsgU3RyZWFtRGlzcGF0Y2hlciB9OyIsICJpbXBvcnQgeyBUcmFuc2Zvcm0sIHR5cGUgVHJhbnNmb3JtQ2FsbGJhY2ssIHR5cGUgV3JpdGFibGUgfSBmcm9tICdub2RlOnN0cmVhbSc7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHN0cmVhbSB0aGF0IGNhbiBiZSBpbnRlcmNlcHRlZCBhbmQgY29uc3VtZWQgd2l0aG91dCBhZmZlY3RpbmcgdGhlIG9yaWdpbmFsIGNvbnN1bWVyLlxuICogQGV4YW1wbGUgY29uc3Qgc3RyZWFtID0gbmV3IEludGVyY2VwdGVkU3RyZWFtKCk7XG4gKlxuICogLy8gcmVhbCBjb25zdW1lclxuICogc3RyZWFtLnBpcGUoZnMuY3JlYXRlV3JpdGVTdHJlYW0oJ2ZpbGUudHh0JykpO1xuICpcbiAqIC8vIG1hbiBpbiB0aGUgbWlkZGxlIGNvbnN1bWVyXG4gKiBjb25zdCBtYW5JblRoZU1pZGRsZSA9IG5ldyBXcml0YWJsZSh7XG4gKiAgd3JpdGUoY2h1bmssIGVuY29kaW5nLCBjYWxsYmFjaykge1xuICogICBjb25zb2xlLmxvZyhjaHVuay50b1N0cmluZygpKTtcbiAqICAgY2FsbGJhY2soKTtcbiAqICB9XG4gKiB9KTtcbiAqXG4gKiAvLyBzdHJlYW0uaW50ZXJjZXB0b3JzIGlzIGEgU2V0IG9mIFdyaXRhYmxlIHN0cmVhbXNcbiAqIHN0cmVhbS5pbnRlcmNlcHRvcnMuYWRkKG1hbkluVGhlTWlkZGxlKTtcbiAqL1xuZXhwb3J0IGNsYXNzIEludGVyY2VwdGVkU3RyZWFtIGV4dGVuZHMgVHJhbnNmb3JtIHtcbiAgcHVibGljIHJlYWRvbmx5IGludGVyY2VwdG9ycyA9IG5ldyBTZXQ8V3JpdGFibGU+KCk7XG4gICNpbnRlcmNlcHRpbmcgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBTdGFydCBpbnRlcmNlcHRpbmcgdGhlIHN0cmVhbS4gVGhpcyBpcyB0aGUgZGVmYXVsdCBzdGF0ZSBvZiBJbnRlcmNlcHRlZFN0cmVhbS5cbiAgICovXG4gIHB1YmxpYyBzdGFydEludGVyY2VwdGluZygpOiB2b2lkIHtcbiAgICB0aGlzLiNpbnRlcmNlcHRpbmcgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0b3AgaW50ZXJjZXB0aW5nIHRoZSBzdHJlYW0uIFRoaXMgd2lsbCBwcmV2ZW50IHRoZSBzdHJlYW0gZnJvbSBiZWluZyBjb25zdW1lZCBieSB0aGUgaW50ZXJjZXB0b3JzLlxuICAgKiBUaGlzIGNhbiBiZSB1c2VmdWwgd2hlbiB5b3Ugd2FudCB0byB0ZW1wb3JhcmlseSBzdG9wIHRoZSBpbnRlcmNlcHRpb24uIFRoZSBzdG9wcGVkIHN0YXRlIGNhbiBiZSByZXN1bWVkIGJ5IGNhbGxpbmcgc3RhcnRJbnRlcmNlcHRpbmcgYWdhaW4uXG4gICAqL1xuICBwdWJsaWMgc3RvcEludGVyY2VwdGluZygpOiB2b2lkIHtcbiAgICB0aGlzLiNpbnRlcmNlcHRpbmcgPSBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBzdHJlYW0gaXMgYmVpbmcgaW50ZXJjZXB0ZWRcbiAgICovXG4gIHB1YmxpYyBpc0ludGVyY2VwdGluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy4jaW50ZXJjZXB0aW5nO1xuICB9XG5cbiAgcHVibGljIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IFRyYW5zZm9ybUNhbGxiYWNrKVxuICA6IHZvaWQge1xuICAgIHRoaXMucHVzaChjaHVuaywgZW5jb2RpbmcpO1xuXG4gICAgaWYgKHRoaXMuI2ludGVyY2VwdGluZyAmJiB0aGlzLmludGVyY2VwdG9ycy5zaXplID4gMCkge1xuICAgICAgZm9yIChjb25zdCBjb25zdW1lciBvZiB0aGlzLmludGVyY2VwdG9ycykge1xuICAgICAgICBjb25zdW1lci53cml0ZShjaHVuaywgZW5jb2RpbmcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBfZmluYWwoY2FsbGJhY2s6IFRyYW5zZm9ybUNhbGxiYWNrKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBjb25zdW1lciBvZiB0aGlzLmludGVyY2VwdG9ycykge1xuICAgICAgY29uc3VtZXIuZW5kKCk7XG4gICAgfVxuXG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIHB1YmxpYyBfZGVzdHJveShlcnJvcjogRXJyb3IsIGNhbGxiYWNrOiBUcmFuc2Zvcm1DYWxsYmFjayk6IHZvaWQge1xuICAgIGNvbnN0IGlnbm9yZUVycm9yID0gU3RyaW5nKGVycm9yKS5pbmNsdWRlcygnRVJSX1NUUkVBTV9QUkVNQVRVUkVfQ0xPU0UnKTtcbiAgICBjb25zdCBlcnIgPSBpZ25vcmVFcnJvciA/IHVuZGVmaW5lZCA6IGVycm9yO1xuXG4gICAgZm9yIChjb25zdCBjb25zdW1lciBvZiB0aGlzLmludGVyY2VwdG9ycykge1xuICAgICAgY29uc3VtZXIuZGVzdHJveShlcnIpO1xuICAgIH1cblxuICAgIHRoaXMuaW50ZXJjZXB0b3JzLmNsZWFyKCk7XG5cbiAgICBjYWxsYmFjayhlcnIpO1xuICB9XG59IiwgImltcG9ydCB7IFF1ZXVlIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL3V0aWxzJztcbmltcG9ydCB7IE5vUmVzdWx0RXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgVHJhY2sgfSBmcm9tICcuLi9mYWJyaWMvVHJhY2snO1xuaW1wb3J0IHsgR3VpbGRRdWV1ZSwgVHJhY2tTa2lwUmVhc29uIH0gZnJvbSAnLi9HdWlsZFF1ZXVlJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmV4cG9ydCBjbGFzcyBHdWlsZFF1ZXVlSGlzdG9yeTxNZXRhID0gYW55PiB7XG4gIHB1YmxpYyB0cmFja3MgPSBuZXcgUXVldWU8VHJhY2s+KCdMSUZPJyk7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4pIHt9XG5cbiAgLyoqXG4gICAqIEN1cnJlbnQgdHJhY2sgaW4gdGhlIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZ2V0IGN1cnJlbnRUcmFjaygpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5hdWRpb1Jlc291cmNlPy5tZXRhZGF0YSB8fFxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgICh0aGlzLnF1ZXVlIGFzIGFueSkuX19jdXJyZW50IGFzIFRyYWNrIHwgbnVsbCk7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBOZXh0IHRyYWNrIGluIHRoZSBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdldCBuZXh0VHJhY2soKSB7XG4gICAgcmV0dXJuIHRoaXMucXVldWUudHJhY2tzLmF0KDApIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUHJldmlvdXMgdHJhY2sgaW4gdGhlIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZ2V0IHByZXZpb3VzVHJhY2soKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhY2tzLmF0KDApIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogSWYgaGlzdG9yeSBpcyBkaXNhYmxlZFxuICAgKi9cbiAgcHVibGljIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5vcHRpb25zLmRpc2FibGVIaXN0b3J5O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHNpemUgb2YgdGhlIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgZ2V0IHNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMudHJhY2tzLnNpemU7XG4gIH1cblxuICBwdWJsaWMgZ2V0U2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zaXplO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIGhpc3RvcnkgaXMgZW1wdHlcbiAgICovXG4gIHB1YmxpYyBpc0VtcHR5KCkge1xuICAgIHJldHVybiB0aGlzLnRyYWNrcy5zaXplIDwgMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgdHJhY2sgdG8gdHJhY2sgaGlzdG9yeVxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRvIGFkZFxuICAgKi9cbiAgcHVibGljIHB1c2godHJhY2s6IFRyYWNrIHwgVHJhY2tbXSkge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSByZXR1cm4gZmFsc2U7XG4gICAgdGhpcy50cmFja3MuYWRkKHRyYWNrKTtcblxuICAgIHRoaXMucmVzaXplKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBoaXN0b3J5XG4gICAqL1xuICBwdWJsaWMgY2xlYXIoKSB7XG4gICAgdGhpcy50cmFja3MuY2xlYXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQbGF5IHRoZSBuZXh0IHRyYWNrIGluIHRoZSBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGFzeW5jIG5leHQoKSB7XG4gICAgY29uc3QgdHJhY2sgPSB0aGlzLm5leHRUcmFjaztcbiAgICBpZiAoIXRyYWNrKSB7XG4gICAgICB0aHJvdyBuZXcgTm9SZXN1bHRFcnJvcignTm8gbmV4dCB0cmFjayBpbiB0aGUgcXVldWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnF1ZXVlLm5vZGUuc2tpcCh7XG4gICAgICByZWFzb246IFRyYWNrU2tpcFJlYXNvbi5IaXN0b3J5TmV4dCxcbiAgICAgIGRlc2NyaXB0aW9uOiAnU2tpcHBlZCBieSBHdWlsZFF1ZXVlSGlzdG9yeS5uZXh0KCknXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGxheSB0aGUgcHJldmlvdXMgdHJhY2sgaW4gdGhlIHF1ZXVlXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcHJldmlvdXMocHJlc2VydmVDdXJyZW50ID0gdHJ1ZSkge1xuICAgIGNvbnN0IHRyYWNrID0gdGhpcy50cmFja3MuZGlzcGF0Y2goKTtcbiAgICBpZiAoIXRyYWNrKSB7XG4gICAgICB0aHJvdyBuZXcgTm9SZXN1bHRFcnJvcignTm8gcHJldmlvdXMgdHJhY2sgaW4gdGhlIHF1ZXVlJyk7XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudFRyYWNrO1xuXG4gICAgYXdhaXQgdGhpcy5xdWV1ZS5ub2RlLnBsYXkodHJhY2ssIHsgcXVldWU6IGZhbHNlIH0pO1xuICAgIGlmIChjdXJyZW50ICYmIHByZXNlcnZlQ3VycmVudCkgdGhpcy5xdWV1ZS5ub2RlLmluc2VydChjdXJyZW50LCAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGlhcyB0byBbR3VpbGRRdWV1ZUhpc3RvcnldLnByZXZpb3VzKClcbiAgICovXG4gIHB1YmxpYyBiYWNrKHByZXNlcnZlQ3VycmVudCA9IHRydWUpIHtcbiAgICByZXR1cm4gdGhpcy5wcmV2aW91cyhwcmVzZXJ2ZUN1cnJlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2l6ZSBoaXN0b3J5IHN0b3JlXG4gICAqL1xuICBwdWJsaWMgcmVzaXplKCkge1xuICAgIGlmICghTnVtYmVyLmlzRmluaXRlKHRoaXMucXVldWUubWF4SGlzdG9yeVNpemUpKSByZXR1cm47XG4gICAgaWYgKHRoaXMudHJhY2tzLnN0b3JlLmxlbmd0aCA8IHRoaXMucXVldWUubWF4SGlzdG9yeVNpemUpIHJldHVybjtcbiAgICB0aGlzLnRyYWNrcy5zdG9yZS5zcGxpY2UodGhpcy5xdWV1ZS5tYXhIaXN0b3J5U2l6ZSk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgQXVkaW9SZXNvdXJjZSwgU3RyZWFtVHlwZSB9IGZyb20gJ2Rpc2NvcmQtdm9pcCc7XG5pbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBRdWVyeVJlc29sdmVyLCBTZWFyY2hRdWVyeVR5cGUgfSBmcm9tICcuLi91dGlscy9RdWVyeVJlc29sdmVyJztcbmltcG9ydCB7IFV0aWwsIFZBTElEQVRFX1FVRVVFX0NBUCB9IGZyb20gJy4uL3V0aWxzL1V0aWwnO1xuaW1wb3J0IHsgVHJhY2ssIFRyYWNrUmVzb2x2YWJsZSB9IGZyb20gJy4uL2ZhYnJpYy9UcmFjayc7XG5pbXBvcnQgeyBHdWlsZFF1ZXVlLCBHdWlsZFF1ZXVlRXZlbnQsIFRyYWNrU2tpcFJlYXNvbiB9IGZyb20gJy4vR3VpbGRRdWV1ZSc7XG5pbXBvcnQgeyBzZXRUaW1lb3V0IGFzIHdhaXRGb3IgfSBmcm9tICd0aW1lcnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgQXN5bmNRdWV1ZSB9IGZyb20gJy4uL3V0aWxzL0FzeW5jUXVldWUnO1xuaW1wb3J0IHtcbiAgSW52YWxpZEFyZ1R5cGVFcnJvcixcbiAgTm9SZXN1bHRFcnJvcixcbiAgTm9Wb2ljZUNvbm5lY3Rpb25FcnJvcixcbiAgT3V0T2ZSYW5nZUVycm9yIH0gZnJvbVxuJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBUeXBlVXRpbCB9IGZyb20gJy4uL3V0aWxzL1R5cGVVdGlsJztcbmltcG9ydCB7IENyZWF0ZVN0cmVhbU9wcyB9IGZyb20gJy4uL3N0cmVhbS9TdHJlYW1EaXNwYXRjaGVyJztcbmltcG9ydCB7IEV4dHJhY3RvclN0cmVhbWFibGUgfSBmcm9tICcuLi9leHRyYWN0b3JzL0Jhc2VFeHRyYWN0b3InO1xuaW1wb3J0IHsgT2dnRGVtdXhlciwgT3B1c0RlY29kZXIsIFdlYm1EZW11eGVyIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL29wdXMnO1xuaW1wb3J0IHsgU2Vla0V2ZW50IH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL2VxdWFsaXplcic7XG5cbmV4cG9ydCBjb25zdCBGRk1QRUdfU1JBVEVfUkVHRVggPSAvYXNldHJhdGU9XFxkK1xcKihcXGQoXFwuXFxkKT8pLztcblxuZXhwb3J0IGludGVyZmFjZSBQbGF5ZXJQcm9ncmVzc2Jhck9wdGlvbnMge1xuICAvKipcbiAgICogSWYgaXQgc2hvdWxkIHJlbmRlciB0aW1lIGNvZGVzXG4gICAqL1xuICB0aW1lY29kZXM/OiBib29sZWFuO1xuICAvKipcbiAgICogSWYgaXQgc2hvdWxkIGNyZWF0ZSBwcm9ncmVzcyBiYXIgZm9yIHRoZSB3aG9sZSBxdWV1ZVxuICAgKi9cbiAgbGVuZ3RoPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIGJhciBsZW5ndGhcbiAgICovXG4gIGxlZnRDaGFyPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGVsYXBzZWQgdGltZSB0cmFja1xuICAgKi9cbiAgcmlnaHRDaGFyPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHJlbWFpbmluZyB0aW1lIHRyYWNrXG4gICAqL1xuICBzZXBhcmF0b3I/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgc2VwYXJhdGlvbiBiZXR3ZWVuIHRpbWVzdGFtcCBhbmQgbGluZVxuICAgKi9cbiAgaW5kaWNhdG9yPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGluZGljYXRvclxuICAgKi9cbiAgcXVldWU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlUGxheU9wdGlvbnMge1xuICBxdWV1ZT86IGJvb2xlYW47XG4gIHNlZWs/OiBudW1iZXI7XG4gIHRyYW5zaXRpb25Nb2RlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTa2lwT3B0aW9ucyB7XG4gIHJlYXNvbjogVHJhY2tTa2lwUmVhc29uO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBsYXllclRpbWVzdGFtcCB7XG4gIGN1cnJlbnQ6IHtcbiAgICBsYWJlbDogc3RyaW5nO1xuICAgIHZhbHVlOiBudW1iZXI7XG4gIH07XG4gIHRvdGFsOiB7XG4gICAgbGFiZWw6IHN0cmluZztcbiAgICB2YWx1ZTogbnVtYmVyO1xuICB9O1xuICBwcm9ncmVzczogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0cmVhbUNvbmZpZyB7XG4gIGRpc3BhdGNoZXJDb25maWc6IENyZWF0ZVN0cmVhbU9wcztcbiAgcGxheWVyQ29uZmlnOiBSZXNvdXJjZVBsYXlPcHRpb25zO1xufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGNsYXNzIEd1aWxkUXVldWVQbGF5ZXJOb2RlPE1ldGEgPSBhbnk+IHtcbiAgI3Byb2dyZXNzID0gMDtcbiAgI2hhc0ZGbXBlZ09wdGltaXphdGlvbiA9IGZhbHNlO1xuICBwdWJsaWMgdGFza3NRdWV1ZSA9IG5ldyBBc3luY1F1ZXVlKCk7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4pIHtcbiAgICB0aGlzLiNoYXNGRm1wZWdPcHRpbWl6YXRpb24gPSAvbGlib3B1czogKHllc3x0cnVlKS8udGVzdChcbiAgICAgIHRoaXMucXVldWUucGxheWVyLnNjYW5EZXBzKClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIHRoZSBwbGF5ZXIgaXMgY3VycmVudGx5IGluIGlkbGUgbW9kZVxuICAgKi9cbiAgcHVibGljIGlzSWRsZSgpIHtcbiAgICByZXR1cm4gISF0aGlzLnF1ZXVlLmRpc3BhdGNoZXI/LmlzSWRsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIElmIHRoZSBwbGF5ZXIgaXMgY3VycmVudGx5IGJ1ZmZlcmluZyB0aGUgdHJhY2tcbiAgICovXG4gIHB1YmxpYyBpc0J1ZmZlcmluZygpIHtcbiAgICByZXR1cm4gISF0aGlzLnF1ZXVlLmRpc3BhdGNoZXI/LmlzQnVmZmVyaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhlIHBsYXllciBpcyBjdXJyZW50bHkgcGxheWluZyBhIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgaXNQbGF5aW5nKCkge1xuICAgIHJldHVybiAhIXRoaXMucXVldWUuZGlzcGF0Y2hlcj8uaXNQbGF5aW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhlIHBsYXllciBpcyBjdXJyZW50bHkgcGF1c2VkXG4gICAqL1xuICBwdWJsaWMgaXNQYXVzZWQoKSB7XG4gICAgcmV0dXJuICEhdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5pc1BhdXNlZCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHByb2dyZXNzIGhpc3RvcnlcbiAgICovXG4gIHB1YmxpYyByZXNldFByb2dyZXNzKCkge1xuICAgIHRoaXMuI3Byb2dyZXNzID0gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgcGxheWVyIHByb2dyZXNzXG4gICAqL1xuICBwdWJsaWMgc2V0UHJvZ3Jlc3MocHJvZ3Jlc3M6IG51bWJlcikge1xuICAgIHRoaXMuI3Byb2dyZXNzID0gcHJvZ3Jlc3M7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHN0cmVhbSB0aW1lIGZvciBjdXJyZW50IHNlc3Npb25cbiAgICovXG4gIHB1YmxpYyBnZXQgc3RyZWFtVGltZSgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5zdHJlYW1UaW1lID8/IDA7XG4gIH1cblxuICAvKipcbiAgICogQ3VycmVudCBwbGF5YmFjayBkdXJhdGlvbiB3aXRoIGhpc3RvcnkgaW5jbHVkZWRcbiAgICovXG4gIHB1YmxpYyBnZXQgcGxheWJhY2tUaW1lKCkge1xuICAgIGlmICh0aGlzLnF1ZXVlLmZpbHRlcnMuc2Vla2VyKSB7XG4gICAgICBjb25zdCBwb3MgPSB0aGlzLnF1ZXVlLmZpbHRlcnMuc2Vla2VyLmdldFBvc2l0aW9uKCk7XG4gICAgICBpZiAocG9zID4gMCkgcmV0dXJuIHBvcztcbiAgICB9XG5cbiAgICBjb25zdCBkdXIgPSB0aGlzLiNwcm9ncmVzcyArIHRoaXMuc3RyZWFtVGltZTtcblxuICAgIHJldHVybiBkdXI7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGR1cmF0aW9uIG11bHRpcGxpZXJcbiAgICovXG4gIHB1YmxpYyBnZXREdXJhdGlvbk11bHRpcGxpZXIoKSB7XG4gICAgY29uc3Qgc3JhdGVGaWx0ZXJzID0gdGhpcy5xdWV1ZS5maWx0ZXJzLmZmbXBlZy5cbiAgICB0b0FycmF5KCkuXG4gICAgZmlsdGVyKChmZikgPT4gRkZNUEVHX1NSQVRFX1JFR0VYLnRlc3QoZmYpKTtcbiAgICBjb25zdCBtdWx0aXBsaWVycyA9IHNyYXRlRmlsdGVycy5cbiAgICBtYXAoKG0pID0+IHtcbiAgICAgIHJldHVybiBwYXJzZUZsb2F0KEZGTVBFR19TUkFURV9SRUdFWC5leGVjKG0pPy5bMV0gYXMgc3RyaW5nKTtcbiAgICB9KS5cbiAgICBmaWx0ZXIoKGYpID0+ICFpc05hTihmKSk7XG5cbiAgICByZXR1cm4gIW11bHRpcGxpZXJzLmxlbmd0aCA/XG4gICAgMSA6XG4gICAgbXVsdGlwbGllcnMucmVkdWNlKChhY2N1bXVsYXRvciwgY3VycmVudCkgPT4gY3VycmVudCArIGFjY3VtdWxhdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFc3RpbWF0ZWQgcHJvZ3Jlc3Mgb2YgdGhlIHBsYXllclxuICAgKi9cbiAgcHVibGljIGdldCBlc3RpbWF0ZWRQbGF5YmFja1RpbWUoKSB7XG4gICAgY29uc3QgZHVyID0gdGhpcy5wbGF5YmFja1RpbWU7XG4gICAgY29uc3QgdmFsID0gdGhpcy5nZXREdXJhdGlvbk11bHRpcGxpZXIoKSAqIGR1cjtcblxuICAgIHJldHVybiB2YWw7XG4gIH1cblxuICAvKipcbiAgICogRXN0aW1hdGVkIHRvdGFsIGR1cmF0aW9uIG9mIHRoZSBwbGF5ZXJcbiAgICovXG4gIHB1YmxpYyBnZXQgZXN0aW1hdGVkRHVyYXRpb24oKSB7XG4gICAgY29uc3QgZHVyID0gdGhpcy50b3RhbER1cmF0aW9uO1xuXG4gICAgLy8gZHVyYXRpb24gbXVsdGlwbGllciBjaGVja3MgZmZtcGVnIGZpbHRlcnMgdGhhdCBtYXkgYWZmZWN0IHRoZSBkdXJhdGlvblxuICAgIGNvbnN0IHZhbCA9IE1hdGgucm91bmQoZHVyIC8gdGhpcy5nZXREdXJhdGlvbk11bHRpcGxpZXIoKSk7XG5cbiAgICAvLyB3ZSBhbHNvIG5lZWQgdG8gY2hlY2sgaWYgd2UgaGF2ZSBhIG5hdGl2ZSByZXNhbXBsZXIgZmlsdGVyIGFzIGl0IG1heSBhbHNvIGFmZmVjdCB0aGUgZHVyYXRpb25cbiAgICBpZiAodGhpcy5xdWV1ZS5maWx0ZXJzLnJlc2FtcGxlcikge1xuICAgICAgLy8gZ2V0IHRoZSByZXNhbXBsZXIgcmF0aW8gaWYgd2UgaGF2ZSBvbmVcbiAgICAgIGNvbnN0IHJhdGlvID0gdGhpcy5xdWV1ZS5maWx0ZXJzLnJlc2FtcGxlci5nZXRSYXRpbygpO1xuICAgICAgaWYgKHJhdGlvIDw9IDApIHJldHVybiB2YWw7XG5cbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbCAvIHJhdGlvKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvdGFsIGR1cmF0aW9uIG9mIHRoZSBjdXJyZW50IGF1ZGlvIHRyYWNrXG4gICAqL1xuICBwdWJsaWMgZ2V0IHRvdGFsRHVyYXRpb24oKSB7XG4gICAgY29uc3QgcHJlZmVyc0JyaWRnZWRNZXRhZGF0YSA9IHRoaXMucXVldWUub3B0aW9ucy5wcmVmZXJCcmlkZ2VkTWV0YWRhdGE7XG4gICAgY29uc3QgdHJhY2sgPSB0aGlzLnF1ZXVlLmN1cnJlbnRUcmFjaztcblxuICAgIGlmIChwcmVmZXJzQnJpZGdlZE1ldGFkYXRhKSB7XG4gICAgICBjb25zdCB0cmFja0hhc0xlZ2FjeU1ldGFkYXRhID1cbiAgICAgIHRyYWNrPy5tZXRhZGF0YSAhPSBudWxsICYmXG4gICAgICB0eXBlb2YgdHJhY2subWV0YWRhdGEgPT09ICdvYmplY3QnICYmXG4gICAgICAnYnJpZGdlJyBpbiB0cmFjay5tZXRhZGF0YSAmJlxuICAgICAgdHJhY2subWV0YWRhdGEuYnJpZGdlICE9IG51bGw7XG4gICAgICBjb25zdCB0cmFja0hhc01ldGFkYXRhID0gdHJhY2s/LmJyaWRnZWRUcmFjayAhPSBudWxsO1xuXG4gICAgICBpZiAodHJhY2tIYXNMZWdhY3lNZXRhZGF0YSB8fCB0cmFja0hhc01ldGFkYXRhKSB7XG4gICAgICAgIGNvbnN0IGR1cmF0aW9uID1cbiAgICAgICAgdHJhY2suYnJpZGdlZFRyYWNrPy5kdXJhdGlvbk1TID8/XG4gICAgICAgIChcbiAgICAgICAgdHJhY2sgYXMgVHJhY2s8e1xuICAgICAgICAgIGJyaWRnZToge1xuICAgICAgICAgICAgZHVyYXRpb246IG51bWJlcjtcbiAgICAgICAgICB9O1xuICAgICAgICB9PikuXG4gICAgICAgIG1ldGFkYXRhPy5icmlkZ2UuZHVyYXRpb247XG5cbiAgICAgICAgaWYgKFR5cGVVdGlsLmlzTnVtYmVyKGR1cmF0aW9uKSkgcmV0dXJuIGR1cmF0aW9uO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cmFjaz8uZHVyYXRpb25NUyA/PyAwO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzdHJlYW0gcHJvZ3Jlc3NcbiAgICogQHBhcmFtIGlnbm9yZUZpbHRlcnMgSWdub3JlIGZpbHRlcnNcbiAgICovXG4gIHB1YmxpYyBnZXRUaW1lc3RhbXAoaWdub3JlRmlsdGVycyA9IGZhbHNlKTogUGxheWVyVGltZXN0YW1wIHwgbnVsbCB7XG4gICAgaWYgKCF0aGlzLnF1ZXVlLmN1cnJlbnRUcmFjaykgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBjdXJyZW50ID0gaWdub3JlRmlsdGVycyA/XG4gICAgdGhpcy5wbGF5YmFja1RpbWUgOlxuICAgIHRoaXMuZXN0aW1hdGVkUGxheWJhY2tUaW1lO1xuICAgIGNvbnN0IHRvdGFsID0gaWdub3JlRmlsdGVycyA/IHRoaXMudG90YWxEdXJhdGlvbiA6IHRoaXMuZXN0aW1hdGVkRHVyYXRpb247XG5cbiAgICByZXR1cm4ge1xuICAgICAgY3VycmVudDoge1xuICAgICAgICBsYWJlbDogVXRpbC5idWlsZFRpbWVDb2RlKFV0aWwucGFyc2VNUyhjdXJyZW50KSksXG4gICAgICAgIHZhbHVlOiBjdXJyZW50XG4gICAgICB9LFxuICAgICAgdG90YWw6IHtcbiAgICAgICAgbGFiZWw6IFV0aWwuYnVpbGRUaW1lQ29kZShVdGlsLnBhcnNlTVModG90YWwpKSxcbiAgICAgICAgdmFsdWU6IHRvdGFsXG4gICAgICB9LFxuICAgICAgcHJvZ3Jlc3M6IE1hdGgucm91bmQoY3VycmVudCAvIHRvdGFsICogMTAwKVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHByb2dyZXNzIGJhciBmb3IgY3VycmVudCBwcm9ncmVzc1xuICAgKiBAcGFyYW0gb3B0aW9ucyBQcm9ncmVzcyBiYXIgb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGNyZWF0ZVByb2dyZXNzQmFyKG9wdGlvbnM/OiBQbGF5ZXJQcm9ncmVzc2Jhck9wdGlvbnMpIHtcbiAgICBjb25zdCB0aW1lc3RhbXAgPSB0aGlzLmdldFRpbWVzdGFtcCgpO1xuICAgIGlmICghdGltZXN0YW1wKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCB7XG4gICAgICBpbmRpY2F0b3IgPSAnXFx1ezFGNTE4fScsXG4gICAgICBsZWZ0Q2hhciA9ICdcXHUyNUFDJyxcbiAgICAgIHJpZ2h0Q2hhciA9ICdcXHUyNUFDJyxcbiAgICAgIGxlbmd0aCA9IDE1LFxuICAgICAgdGltZWNvZGVzID0gdHJ1ZSxcbiAgICAgIHNlcGFyYXRvciA9ICdcXHUyNTAzJ1xuICAgIH0gPSBvcHRpb25zIHx8IHt9O1xuICAgIGlmIChpc05hTihsZW5ndGgpIHx8IGxlbmd0aCA8IDAgfHwgIU51bWJlci5pc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICB0aHJvdyBuZXcgT3V0T2ZSYW5nZUVycm9yKFxuICAgICAgICAnW1BsYXllclByb2dyZXNzQmFyT3B0aW9ucy5sZW5ndGhdJyxcbiAgICAgICAgU3RyaW5nKGxlbmd0aCksXG4gICAgICAgICcwJyxcbiAgICAgICAgJ0Zpbml0ZSBOdW1iZXInXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBpbmRleCA9IE1hdGgucm91bmQoXG4gICAgICB0aW1lc3RhbXAuY3VycmVudC52YWx1ZSAvIHRpbWVzdGFtcC50b3RhbC52YWx1ZSAqIGxlbmd0aFxuICAgICk7XG4gICAgaWYgKGluZGV4ID49IDEgJiYgaW5kZXggPD0gbGVuZ3RoKSB7XG4gICAgICBjb25zdCBiYXIgPSBsZWZ0Q2hhci5yZXBlYXQoaW5kZXggLSAxKS5zcGxpdCgnJyk7XG4gICAgICBiYXIucHVzaChpbmRpY2F0b3IpO1xuICAgICAgYmFyLnB1c2gocmlnaHRDaGFyLnJlcGVhdChsZW5ndGggLSBpbmRleCkpO1xuICAgICAgaWYgKHRpbWVjb2Rlcykge1xuICAgICAgICByZXR1cm4gYCR7dGltZXN0YW1wLmN1cnJlbnQubGFiZWx9ICR7c2VwYXJhdG9yfSAke2Jhci5qb2luKFxuICAgICAgICAgICcnXG4gICAgICAgICl9ICR7c2VwYXJhdG9yfSAke3RpbWVzdGFtcC50b3RhbC5sYWJlbH1gO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGAke2Jhci5qb2luKCcnKX1gO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGltZWNvZGVzKSB7XG4gICAgICAgIHJldHVybiBgJHtcbiAgICAgICAgdGltZXN0YW1wLmN1cnJlbnQubGFiZWx9ICR7XG4gICAgICAgIHNlcGFyYXRvcn0gJHtpbmRpY2F0b3J9JHtyaWdodENoYXIucmVwZWF0KFxuICAgICAgICAgIGxlbmd0aCAtIDFcbiAgICAgICAgKX0gJHtzZXBhcmF0b3J9ICR7dGltZXN0YW1wLnRvdGFsLmxhYmVsfWA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gYCR7aW5kaWNhdG9yfSR7cmlnaHRDaGFyLnJlcGVhdChsZW5ndGggLSAxKX1gO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZWVrIHRoZSBwbGF5ZXJcbiAgICogQHBhcmFtIGR1cmF0aW9uIFRoZSBkdXJhdGlvbiB0byBzZWVrIHRvXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2VlayhkdXJhdGlvbjogbnVtYmVyKSB7XG4gICAgaWYgKCF0aGlzLnF1ZXVlLmN1cnJlbnRUcmFjaykgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChkdXJhdGlvbiA9PT0gdGhpcy5lc3RpbWF0ZWRQbGF5YmFja1RpbWUpIHJldHVybiB0cnVlO1xuICAgIGlmIChkdXJhdGlvbiA+IHRoaXMudG90YWxEdXJhdGlvbikge1xuICAgICAgcmV0dXJuIHRoaXMuc2tpcCh7XG4gICAgICAgIHJlYXNvbjogVHJhY2tTa2lwUmVhc29uLlNFRUtfT1ZFUl9USFJFU0hPTEQsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBuZXcgT3V0T2ZSYW5nZUVycm9yKFxuICAgICAgICAgICdbZHVyYXRpb25dJyxcbiAgICAgICAgICBTdHJpbmcoZHVyYXRpb24pLFxuICAgICAgICAgICcwJyxcbiAgICAgICAgICBTdHJpbmcodGhpcy50b3RhbER1cmF0aW9uKVxuICAgICAgICApLm1lc3NhZ2VcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAoZHVyYXRpb24gPCAwKSBkdXJhdGlvbiA9IDA7XG5cbiAgICBjb25zdCBzZWVrZXIgPSB0aGlzLnF1ZXVlLmZpbHRlcnMuc2Vla2VyO1xuXG4gICAgaWYgKHNlZWtlcikge1xuICAgICAgc2Vla2VyLnNlZWsoZHVyYXRpb24pO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucXVldWUuZmlsdGVycy50cmlnZ2VyUmVwbGF5KGR1cmF0aW9uKS50aGVuKCh2KSA9PiB7XG4gICAgICBpZiAodikge1xuICAgICAgICB0aGlzLnF1ZXVlLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LlBsYXllclNlZWssIHRoaXMucXVldWUsIHtcbiAgICAgICAgICBjdXJyZW50UG9zaXRpb246IHRoaXMuZXN0aW1hdGVkUGxheWJhY2tUaW1lLFxuICAgICAgICAgIHNlZWtUYXJnZXQ6IGR1cmF0aW9uLFxuICAgICAgICAgIHRvdGFsRHVyYXRpb246IHRoaXMuZXN0aW1hdGVkRHVyYXRpb25cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB2O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEN1cnJlbnQgdm9sdW1lXG4gICAqL1xuICBwdWJsaWMgZ2V0IHZvbHVtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy52b2x1bWUgPz8gMTAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB2b2x1bWVcbiAgICogQHBhcmFtIHZvbCBWb2x1bWUgYW1vdW50IHRvIHNldFxuICAgKi9cbiAgcHVibGljIHNldFZvbHVtZSh2b2w6IG51bWJlcikge1xuICAgIGlmICghdGhpcy5xdWV1ZS5kaXNwYXRjaGVyKSByZXR1cm4gZmFsc2U7XG4gICAgY29uc3QgcmVzID0gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyLnNldFZvbHVtZSh2b2wpO1xuICAgIGlmIChyZXMpIHRoaXMucXVldWUuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS52b2x1bWUgPSB2b2w7XG4gICAgcmV0dXJuIHJlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgYml0IHJhdGVcbiAgICogQHBhcmFtIHJhdGUgVGhlIGJpdCByYXRlIHRvIHNldFxuICAgKi9cbiAgcHVibGljIHNldEJpdHJhdGUocmF0ZTogbnVtYmVyIHwgJ2F1dG8nKSB7XG4gICAgdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5hdWRpb1Jlc291cmNlPy5lbmNvZGVyPy5zZXRCaXRyYXRlKFxuICAgICAgcmF0ZSA9PT0gJ2F1dG8nID8gdGhpcy5xdWV1ZS5jaGFubmVsPy5iaXRyYXRlID8/IDY0MDAwIDogcmF0ZVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHBhdXNlZCBzdGF0ZVxuICAgKiBAcGFyYW0gc3RhdGUgVGhlIHN0YXRlXG4gICAqL1xuICBwdWJsaWMgc2V0UGF1c2VkKHN0YXRlOiBib29sZWFuKSB7XG4gICAgaWYgKHN0YXRlKSByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5wYXVzZSh0cnVlKSB8fCBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5yZXN1bWUoKSB8fCBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXVzZSB0aGUgcGxheWJhY2tcbiAgICovXG4gIHB1YmxpYyBwYXVzZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zZXRQYXVzZWQodHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzdW1lIHRoZSBwbGF5YmFja1xuICAgKi9cbiAgcHVibGljIHJlc3VtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zZXRQYXVzZWQoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNraXAgY3VycmVudCB0cmFja1xuICAgKi9cbiAgcHVibGljIHNraXAob3B0aW9ucz86IFNraXBPcHRpb25zKSB7XG4gICAgaWYgKCF0aGlzLnF1ZXVlLmRpc3BhdGNoZXIpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCB0cmFjayA9IHRoaXMucXVldWUuY3VycmVudFRyYWNrO1xuICAgIGlmICghdHJhY2spIHJldHVybiBmYWxzZTtcbiAgICB0aGlzLnF1ZXVlLnNldFRyYW5zaXRpb25pbmcoZmFsc2UpO1xuICAgIHRoaXMucXVldWUuZGlzcGF0Y2hlci5lbmQoKTtcbiAgICBjb25zdCB7IHJlYXNvbiwgZGVzY3JpcHRpb24gfSA9IG9wdGlvbnMgfHwge1xuICAgICAgcmVhc29uOiBUcmFja1NraXBSZWFzb24uTWFudWFsLFxuICAgICAgZGVzY3JpcHRpb246ICdUaGUgdHJhY2sgd2FzIHNraXBwZWQgbWFudWFsbHknXG4gICAgfTtcbiAgICB0aGlzLnF1ZXVlLmVtaXQoXG4gICAgICBHdWlsZFF1ZXVlRXZlbnQuUGxheWVyU2tpcCxcbiAgICAgIHRoaXMucXVldWUsXG4gICAgICB0cmFjayxcbiAgICAgIHJlYXNvbixcbiAgICAgIGRlc2NyaXB0aW9uXG4gICAgKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGdpdmVuIHRyYWNrIGZyb20gcXVldWVcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFjayB0byByZW1vdmVcbiAgICogQHBhcmFtIGVtaXRFdmVudCBXaGV0aGVyIG9yIG5vdCB0byBlbWl0IHRoZSBldmVudCBAZGVmYXVsdFZhbHVlIHRydWVcbiAgICovXG4gIHB1YmxpYyByZW1vdmUodHJhY2s6IFRyYWNrUmVzb2x2YWJsZSwgZW1pdEV2ZW50ID0gdHJ1ZSkge1xuICAgIGNvbnN0IGZvdW5kVHJhY2sgPSB0aGlzLnF1ZXVlLnRyYWNrcy5maW5kKCh0LCBpZHgpID0+IHtcbiAgICAgIGlmICh0cmFjayBpbnN0YW5jZW9mIFRyYWNrIHx8IHR5cGVvZiB0cmFjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuICh0eXBlb2YgdHJhY2sgPT09ICdzdHJpbmcnID8gdHJhY2sgOiB0cmFjay5pZCkgPT09IHQuaWQ7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHRyYWNrID09PSAnc3RyaW5nJykgcmV0dXJuIHRyYWNrID09PSB0LmlkO1xuICAgICAgcmV0dXJuIGlkeCA9PT0gdHJhY2s7XG4gICAgfSk7XG4gICAgaWYgKCFmb3VuZFRyYWNrKSByZXR1cm4gbnVsbDtcblxuICAgIHRoaXMucXVldWUudHJhY2tzLnJlbW92ZU9uZSgodCkgPT4gdC5pZCA9PT0gZm91bmRUcmFjay5pZCk7XG5cbiAgICBpZiAoZW1pdEV2ZW50KVxuICAgIHRoaXMucXVldWUuZW1pdChHdWlsZFF1ZXVlRXZlbnQuQXVkaW9UcmFja1JlbW92ZSwgdGhpcy5xdWV1ZSwgZm91bmRUcmFjayk7XG5cbiAgICByZXR1cm4gZm91bmRUcmFjaztcbiAgfVxuXG4gIC8qKlxuICAgKiBKdW1wIHRvIHNwZWNpZmljIHRyYWNrIG9uIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gdHJhY2sgVGhlIHRyYWNrIHRvIGp1bXAgdG8gd2l0aG91dCByZW1vdmluZyBvdGhlciB0cmFja3NcbiAgICovXG4gIHB1YmxpYyBqdW1wKHRyYWNrOiBUcmFja1Jlc29sdmFibGUpIHtcbiAgICBjb25zdCByZW1vdmVkID0gdGhpcy5yZW1vdmUodHJhY2ssIGZhbHNlKTtcbiAgICBpZiAoIXJlbW92ZWQpIHJldHVybiBmYWxzZTtcbiAgICB0aGlzLnF1ZXVlLnRyYWNrcy5zdG9yZS51bnNoaWZ0KHJlbW92ZWQpO1xuICAgIHJldHVybiB0aGlzLnNraXAoe1xuICAgICAgcmVhc29uOiBUcmFja1NraXBSZWFzb24uSnVtcCxcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHRyYWNrIHdhcyBqdW1wZWQgdG8gbWFudWFsbHknXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRyYWNrIHBvc2l0aW9uXG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2tcbiAgICovXG4gIHB1YmxpYyBnZXRUcmFja1Bvc2l0aW9uKHRyYWNrOiBUcmFja1Jlc29sdmFibGUpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlLnRyYWNrcy50b0FycmF5KCkuZmluZEluZGV4KCh0LCBpZHgpID0+IHtcbiAgICAgIGlmICh0cmFjayBpbnN0YW5jZW9mIFRyYWNrIHx8IHR5cGVvZiB0cmFjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuICh0eXBlb2YgdHJhY2sgPT09ICdzdHJpbmcnID8gdHJhY2sgOiB0cmFjay5pZCkgPT09IHQuaWQ7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHRyYWNrID09PSAnc3RyaW5nJykgcmV0dXJuIHRyYWNrID09PSB0LmlkO1xuICAgICAgcmV0dXJuIGlkeCA9PT0gdHJhY2s7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2tpcCB0byB0aGUgZ2l2ZW4gdHJhY2ssIHJlbW92aW5nIG90aGVycyBvbiB0aGUgd2F5XG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2sgdG8gc2tpcCB0b1xuICAgKi9cbiAgcHVibGljIHNraXBUbyh0cmFjazogVHJhY2tSZXNvbHZhYmxlKSB7XG4gICAgY29uc3QgaWR4ID0gdGhpcy5nZXRUcmFja1Bvc2l0aW9uKHRyYWNrKTtcbiAgICBpZiAoaWR4IDwgMCkgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IHJlbW92ZWQgPSB0aGlzLnJlbW92ZShpZHgpO1xuICAgIGlmICghcmVtb3ZlZCkgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IHRvUmVtb3ZlID0gdGhpcy5xdWV1ZS50cmFja3Muc3RvcmUuZmlsdGVyKChfLCBpKSA9PiBpIDw9IGlkeCk7XG4gICAgdGhpcy5xdWV1ZS50cmFja3Muc3RvcmUuc3BsaWNlKDAsIGlkeCwgcmVtb3ZlZCk7XG4gICAgdGhpcy5xdWV1ZS5lbWl0KEd1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrc1JlbW92ZSwgdGhpcy5xdWV1ZSwgdG9SZW1vdmUpO1xuICAgIHJldHVybiB0aGlzLnNraXAoe1xuICAgICAgcmVhc29uOiBUcmFja1NraXBSZWFzb24uU2tpcFRvLFxuICAgICAgZGVzY3JpcHRpb246ICdUaGUgcGxheWVyIHdhcyBza2lwcGVkIHRvIGFub3RoZXIgdHJhY2sgbWFudWFsbHknXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW5zZXJ0IGEgdHJhY2sgb24gdGhlIGdpdmVuIHBvc2l0aW9uIGluIHF1ZXVlXG4gICAqIEBwYXJhbSB0cmFjayBUaGUgdHJhY2sgdG8gaW5zZXJ0XG4gICAqIEBwYXJhbSBpbmRleCBUaGUgcG9zaXRpb24gdG8gaW5zZXJ0IHRvLCBkZWZhdWx0cyB0byAwLlxuICAgKi9cbiAgcHVibGljIGluc2VydCh0cmFjazogVHJhY2ssIGluZGV4ID0gMCkge1xuICAgIGlmICghKHRyYWNrIGluc3RhbmNlb2YgVHJhY2spKVxuICAgIHRocm93IG5ldyBJbnZhbGlkQXJnVHlwZUVycm9yKFxuICAgICAgJ3RyYWNrIHZhbHVlJyxcbiAgICAgICdpbnN0YW5jZSBvZiBUcmFjaycsXG4gICAgICBTdHJpbmcodHJhY2spXG4gICAgKTtcbiAgICBWQUxJREFURV9RVUVVRV9DQVAodGhpcy5xdWV1ZSwgdHJhY2spO1xuICAgIHRoaXMucXVldWUudHJhY2tzLnN0b3JlLnNwbGljZShpbmRleCwgMCwgdHJhY2spO1xuICAgIGlmICghdGhpcy5xdWV1ZS5vcHRpb25zLm5vRW1pdEluc2VydCkge1xuICAgICAgdGhpcy5xdWV1ZS5lbWl0KEd1aWxkUXVldWVFdmVudC5BdWRpb1RyYWNrQWRkLCB0aGlzLnF1ZXVlLCB0cmFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vdmVzIGEgdHJhY2sgaW4gdGhlIHF1ZXVlXG4gICAqIEBwYXJhbSBmcm9tIFRoZSB0cmFjayB0byBtb3ZlXG4gICAqIEBwYXJhbSB0byBUaGUgcG9zaXRpb24gdG8gbW92ZSB0b1xuICAgKi9cbiAgcHVibGljIG1vdmUoZnJvbTogVHJhY2tSZXNvbHZhYmxlLCB0bzogbnVtYmVyKSB7XG4gICAgY29uc3QgcmVtb3ZlZCA9IHRoaXMucmVtb3ZlKGZyb20pO1xuICAgIGlmICghcmVtb3ZlZCkge1xuICAgICAgdGhyb3cgbmV3IE5vUmVzdWx0RXJyb3IoJ2ludmFsaWQgdHJhY2sgdG8gbW92ZScpO1xuICAgIH1cbiAgICB0aGlzLmluc2VydChyZW1vdmVkLCB0byk7XG4gIH1cblxuICAvKipcbiAgICogQ29weSBhIHRyYWNrIGluIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gZnJvbSBUaGUgdHJhY2sgdG8gY2xvbmVcbiAgICogQHBhcmFtIHRvIFRoZSBwb3NpdGlvbiB0byBjbG9uZSBhdFxuICAgKi9cbiAgcHVibGljIGNvcHkoZnJvbTogVHJhY2tSZXNvbHZhYmxlLCB0bzogbnVtYmVyKSB7XG4gICAgY29uc3Qgc3JjID0gdGhpcy5xdWV1ZS50cmFja3MuYXQodGhpcy5nZXRUcmFja1Bvc2l0aW9uKGZyb20pKTtcbiAgICBpZiAoIXNyYykge1xuICAgICAgdGhyb3cgbmV3IE5vUmVzdWx0RXJyb3IoJ2ludmFsaWQgdHJhY2sgdG8gY29weScpO1xuICAgIH1cbiAgICB0aGlzLmluc2VydChzcmMsIHRvKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTd2FwIHR3byB0cmFja3MgaW4gdGhlIHF1ZXVlXG4gICAqIEBwYXJhbSBmaXJzdCBUaGUgZmlyc3QgdHJhY2sgdG8gc3dhcFxuICAgKiBAcGFyYW0gc2Vjb25kIFRoZSBzZWNvbmQgdHJhY2sgdG8gc3dhcFxuICAgKi9cbiAgcHVibGljIHN3YXAoZmlyc3Q6IFRyYWNrUmVzb2x2YWJsZSwgc2Vjb25kOiBUcmFja1Jlc29sdmFibGUpIHtcbiAgICBjb25zdCBzcmMgPSB0aGlzLmdldFRyYWNrUG9zaXRpb24oZmlyc3QpO1xuICAgIGlmIChzcmMgPCAwKSB0aHJvdyBuZXcgTm9SZXN1bHRFcnJvcignaW52YWxpZCBzcmMgdHJhY2sgdG8gc3dhcCcpO1xuXG4gICAgY29uc3QgZGVzdCA9IHRoaXMuZ2V0VHJhY2tQb3NpdGlvbihzZWNvbmQpO1xuICAgIGlmIChkZXN0IDwgMCkgdGhyb3cgbmV3IE5vUmVzdWx0RXJyb3IoJ2ludmFsaWQgZGVzdCB0cmFjayB0byBzd2FwJyk7XG5cbiAgICBjb25zdCBzcmNUID0gdGhpcy5xdWV1ZS50cmFja3Muc3RvcmVbc3JjXTtcbiAgICBjb25zdCBkZXN0VCA9IHRoaXMucXVldWUudHJhY2tzLnN0b3JlW2Rlc3RdO1xuXG4gICAgdGhpcy5xdWV1ZS50cmFja3Muc3RvcmVbc3JjXSA9IGRlc3RUO1xuICAgIHRoaXMucXVldWUudHJhY2tzLnN0b3JlW2Rlc3RdID0gc3JjVDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdG9wIHRoZSBwbGF5YmFja1xuICAgKiBAcGFyYW0gZm9yY2UgV2hldGhlciBvciBub3QgdG8gZm9yY2VmdWxseSBzdG9wIHRoZSBwbGF5YmFja1xuICAgKi9cbiAgcHVibGljIHN0b3AoZm9yY2UgPSBmYWxzZSkge1xuICAgIHRoaXMucXVldWUudHJhY2tzLmNsZWFyKCk7XG4gICAgdGhpcy5xdWV1ZS5oaXN0b3J5LmNsZWFyKCk7XG4gICAgaWYgKCF0aGlzLnF1ZXVlLmRpc3BhdGNoZXIpIHJldHVybiBmYWxzZTtcbiAgICB0aGlzLnF1ZXVlLmRpc3BhdGNoZXIuZW5kKCk7XG4gICAgaWYgKGZvcmNlKSB7XG4gICAgICB0aGlzLnF1ZXVlLmRpc3BhdGNoZXIuZGVzdHJveSgpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0aGlzLnF1ZXVlLm9wdGlvbnMubGVhdmVPblN0b3ApIHtcbiAgICAgIGNvbnN0IHRtOiBOb2RlSlMuVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5pc1BsYXlpbmcoKSB8fCB0aGlzLnF1ZXVlLnRyYWNrcy5zaXplKSByZXR1cm4gY2xlYXJUaW1lb3V0KHRtKTtcbiAgICAgICAgdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5kZXN0cm95KCk7XG4gICAgICB9LCB0aGlzLnF1ZXVlLm9wdGlvbnMubGVhdmVPblN0b3BDb29sZG93bikudW5yZWYoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc291cmNlIHRvIHNlZWtcbiAgICogQHBhcmFtIGRhdGEgVGhlIHNlZWsgcGFyYW1ldGVyc1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlcXVlc3RTZWVrKGRhdGE6IFNlZWtFdmVudCkge1xuICAgIGNvbnN0IHRyYWNrID0gdGhpcy5xdWV1ZS5jdXJyZW50VHJhY2s7XG4gICAgaWYgKCF0cmFjaykgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKHRyYWNrLnNlZWthYmxlKSB7XG4gICAgICByZXR1cm4gdHJhY2suc2VlayhkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5maWx0ZXJzLnRyaWdnZXJSZXBsYXkoZGF0YS5wb3NpdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogUGxheSB0aGUgZ2l2ZW4gdHJhY2tcbiAgICogQHBhcmFtIHJlcyBUaGUgdHJhY2sgdG8gcGxheVxuICAgKiBAcGFyYW0gb3B0aW9ucyBPcHRpb25zIGZvciBwbGF5aW5nIHRoZSB0cmFja1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHBsYXkocmVzPzogVHJhY2sgfCBudWxsLCBvcHRpb25zPzogUmVzb3VyY2VQbGF5T3B0aW9ucykge1xuICAgIGlmICghdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy52b2ljZUNvbm5lY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBOb1ZvaWNlQ29ubmVjdGlvbkVycm9yKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpXG4gICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgIGBSZWNlaXZlZCBwbGF5IHJlcXVlc3QgZnJvbSBndWlsZCAke3RoaXMucXVldWUuZ3VpbGQubmFtZX0gKElEOiAke3RoaXMucXVldWUuZ3VpbGQuaWR9KWBcbiAgICApO1xuXG4gICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oXG4gICAgICB7fSxcbiAgICAgIHtcbiAgICAgICAgcXVldWU6IHRoaXMucXVldWUuY3VycmVudFRyYWNrICE9IG51bGwsXG4gICAgICAgIHRyYW5zaXRpb25Nb2RlOiBmYWxzZSxcbiAgICAgICAgc2VlazogMFxuICAgICAgfSBhcyBSZXNvdXJjZVBsYXlPcHRpb25zLFxuICAgICAgb3B0aW9uc1xuICAgICkhO1xuXG4gICAgaWYgKHJlcyAmJiBvcHRpb25zLnF1ZXVlKSB7XG4gICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgICdSZXF1ZXN0ZWQgb3B0aW9uIHJlcXVpcmVzIHRvIHF1ZXVlIHRoZSB0cmFjaywgYWRkaW5nIHRoZSBnaXZlbiB0cmFjayB0byBxdWV1ZSBpbnN0ZWFkLi4uJ1xuICAgICAgKTtcbiAgICAgIHJldHVybiB0aGlzLnF1ZXVlLmFkZFRyYWNrKHJlcyk7XG4gICAgfVxuXG4gICAgY29uc3QgdHJhY2sgPSByZXMgfHwgdGhpcy5xdWV1ZS50cmFja3MuZGlzcGF0Y2goKTtcbiAgICBpZiAoIXRyYWNrKSB7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBOb1Jlc3VsdEVycm9yKFxuICAgICAgICAnUGxheSByZXF1ZXN0IHJlY2VpdmVkIGJ1dCB0cmFjayB3YXMgbm90IHByb3ZpZGVkJ1xuICAgICAgKTtcbiAgICAgIHRoaXMucXVldWUuZW1pdChHdWlsZFF1ZXVlRXZlbnQuRXJyb3IsIHRoaXMucXVldWUsIGVycm9yKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLnF1ZXVlLmRlYnVnKFxuICAgICAgJ1JlcXVlc3RlZCBvcHRpb24gcmVxdWlyZXMgdG8gcGxheSB0aGUgdHJhY2ssIGluaXRpYWxpemluZy4uLidcbiAgICApO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFzc2lnbmVkUmVzb3VyY2UgPSB0cmFjay5yZXNvdXJjZTtcblxuICAgICAgaWYgKGFzc2lnbmVkUmVzb3VyY2UpIHtcbiAgICAgICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpXG4gICAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgICAgJ1RyYWNrIGhhcyBhbiBhdWRpbyByZXNvdXJjZSBhc3NpZ25lZCwgcGxheWVyIHdpbGwgbm93IHBsYXkgdGhlIHJlc291cmNlIGRpcmVjdGx5Li4uJ1xuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMucXVldWUuc2V0VHJhbnNpdGlvbmluZyghIW9wdGlvbnMudHJhbnNpdGlvbk1vZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLiNwZXJmb3JtUGxheShhc3NpZ25lZFJlc291cmNlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpXG4gICAgICB0aGlzLnF1ZXVlLmRlYnVnKGBJbml0aWF0aW5nIHN0cmVhbSBleHRyYWN0aW9uIHByb2Nlc3MuLi5gKTtcbiAgICAgIGNvbnN0IHNyYyA9IHRyYWNrLnJhdz8uc291cmNlIHx8IHRyYWNrLnNvdXJjZTtcbiAgICAgIGNvbnN0IHF0OiBTZWFyY2hRdWVyeVR5cGUgPVxuICAgICAgdHJhY2sucXVlcnlUeXBlIHx8IChcbiAgICAgIHNyYyA9PT0gJ3Nwb3RpZnknID9cbiAgICAgICdzcG90aWZ5U29uZycgOlxuICAgICAgc3JjID09PSAnYXBwbGVfbXVzaWMnID9cbiAgICAgICdhcHBsZU11c2ljU29uZycgOlxuICAgICAgc3JjKTtcbiAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgICAgYEV4ZWN1dGluZyBvbkJlZm9yZUNyZWF0ZVN0cmVhbSBob29rIChRdWVyeVR5cGU6ICR7cXR9KS4uLmBcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHN0cmVhbVNyYyA9IHtcbiAgICAgICAgZXJyb3I6IG51bGwgYXMgRXJyb3IgfCBudWxsLFxuICAgICAgICBzdHJlYW06IG51bGwgYXMgRXh0cmFjdG9yU3RyZWFtYWJsZSB8IG51bGxcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHRoaXMucXVldWUuXG4gICAgICBvbkJlZm9yZUNyZWF0ZVN0cmVhbT8uKHRyYWNrLCBxdCB8fCAnYXJiaXRyYXJ5JywgdGhpcy5xdWV1ZSkuXG4gICAgICB0aGVuKFxuICAgICAgICAocykgPT4ge1xuICAgICAgICAgIGlmIChzKSB7XG4gICAgICAgICAgICBzdHJlYW1TcmMuc3RyZWFtID0gcztcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIChlOiBFcnJvcikgPT4gc3RyZWFtU3JjLmVycm9yID0gZVxuICAgICAgKTtcblxuICAgICAgLy8gdGhyb3cgaWYgJ29uQmVmb3JlQ3JlYXRlU3RyZWFtJyBwYW5pY3NcbiAgICAgIGlmICghc3RyZWFtU3JjLnN0cmVhbSAmJiBzdHJlYW1TcmMuZXJyb3IpXG4gICAgICByZXR1cm4gdGhpcy4jdGhyb3codHJhY2ssIHN0cmVhbVNyYy5lcnJvcik7XG5cbiAgICAgIC8vIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiAnb25CZWZvcmVDcmVhdGVTdHJlYW0nIGRpZCBub3QgcGFuaWNcbiAgICAgIGlmICghc3RyZWFtU3JjLnN0cmVhbSkge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgICAgICAnRmFpbGVkIHRvIGdldCBzdHJlYW0gZnJvbSBvbkJlZm9yZUNyZWF0ZVN0cmVhbSwgYXR0ZW1wdGluZyB0byBleHRyYWN0IHN0cmVhbSB1c2luZyBleHRyYWN0b3JzLi4uJ1xuICAgICAgICApO1xuICAgICAgICBhd2FpdCB0aGlzLnF1ZXVlLnBsYXllci5leHRyYWN0b3JzLmNvbnRleHQucHJvdmlkZShcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpZDogY3J5cHRvLnJhbmRvbVVVSUQoKSxcbiAgICAgICAgICAgIGF0dGVtcHRlZEV4dHJhY3RvcnM6IG5ldyBTZXQ8c3RyaW5nPigpLFxuICAgICAgICAgICAgYnJpZGdlQXR0ZW1wdGVkRXh0cmFjdG9yczogbmV3IFNldDxzdHJpbmc+KClcbiAgICAgICAgICB9LFxuICAgICAgICAgICgpID0+XG4gICAgICAgICAgdGhpcy4jY3JlYXRlR2VuZXJpY1N0cmVhbSh0cmFjaykuXG4gICAgICAgICAgdGhlbihhc3luYyAocikgPT4ge1xuICAgICAgICAgICAgaWYgKHI/LnJlc3VsdCkge1xuICAgICAgICAgICAgICBzdHJlYW1TcmMuc3RyZWFtID1cbiAgICAgICAgICAgICAgPFJlYWRhYmxlPiAoXG4gICAgICAgICAgICAgIGF3YWl0IHRoaXMucXVldWUub25TdHJlYW1FeHRyYWN0ZWQ/LihcbiAgICAgICAgICAgICAgICByLnJlc3VsdCxcbiAgICAgICAgICAgICAgICB0cmFjayxcbiAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlXG4gICAgICAgICAgICAgICkpID8/XG4gICAgICAgICAgICAgIHIucmVzdWx0O1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyPy5lcnJvcikge1xuICAgICAgICAgICAgICBzdHJlYW1TcmMuZXJyb3IgPSByLmVycm9yO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0cmVhbVNyYy5zdHJlYW0gPSBzdHJlYW1TcmMuZXJyb3IgPSBudWxsO1xuICAgICAgICAgIH0pLlxuICAgICAgICAgIGNhdGNoKChlOiBFcnJvcikgPT4gc3RyZWFtU3JjLmVycm9yID0gZSlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFzdHJlYW1TcmMuc3RyZWFtKSByZXR1cm4gdGhpcy4jdGhyb3codHJhY2ssIHN0cmVhbVNyYy5lcnJvcik7XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zZWVrID09PSAnbnVtYmVyJyAmJiBvcHRpb25zLnNlZWsgPj0gMCkge1xuICAgICAgICB0aGlzLiNwcm9ncmVzcyA9IG9wdGlvbnMuc2VlaztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuI3Byb2dyZXNzID0gMDtcbiAgICAgIH1cblxuICAgICAgY29uc3QgdHJhY2tTdHJlYW1Db25maWc6IFN0cmVhbUNvbmZpZyA9IHtcbiAgICAgICAgZGlzcGF0Y2hlckNvbmZpZzoge1xuICAgICAgICAgIGRpc2FibGVCaXF1YWQ6IHRoaXMucXVldWUub3B0aW9ucy5kaXNhYmxlQmlxdWFkLFxuICAgICAgICAgIGRpc2FibGVFcXVhbGl6ZXI6IHRoaXMucXVldWUub3B0aW9ucy5kaXNhYmxlRXF1YWxpemVyLFxuICAgICAgICAgIGRpc2FibGVWb2x1bWU6IHRoaXMucXVldWUub3B0aW9ucy5kaXNhYmxlVm9sdW1lLFxuICAgICAgICAgIGRpc2FibGVGaWx0ZXJzOiB0aGlzLnF1ZXVlLm9wdGlvbnMuZGlzYWJsZUZpbHRlcmVyLFxuICAgICAgICAgIGRpc2FibGVSZXNhbXBsZXI6IHRoaXMucXVldWUub3B0aW9ucy5kaXNhYmxlUmVzYW1wbGVyLFxuICAgICAgICAgIGRpc2FibGVDb21wcmVzc29yOiB0aGlzLnF1ZXVlLm9wdGlvbnMuZGlzYWJsZUNvbXByZXNzb3IsXG4gICAgICAgICAgZGlzYWJsZVJldmVyYjogdGhpcy5xdWV1ZS5vcHRpb25zLmRpc2FibGVSZXZlcmIsXG4gICAgICAgICAgZGlzYWJsZVNlZWtlcjogdGhpcy5xdWV1ZS5vcHRpb25zLmRpc2FibGVTZWVrZXIsXG4gICAgICAgICAgY29tcHJlc3NvcjpcbiAgICAgICAgICB0aGlzLnF1ZXVlLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUuY29tcHJlc3NvciA/PyB1bmRlZmluZWQsXG4gICAgICAgICAgcmV2ZXJiOiB0aGlzLnF1ZXVlLmZpbHRlcnMuX2xhc3RGaWx0ZXJzQ2FjaGUucmV2ZXJiID8/IHVuZGVmaW5lZCxcbiAgICAgICAgICBzZWVrZXI6IHtcbiAgICAgICAgICAgIHNlZWtUYXJnZXQ6XG4gICAgICAgICAgICBvcHRpb25zLnRyYW5zaXRpb25Nb2RlICYmIG9wdGlvbnMuc2VlayAhPSBudWxsID9cbiAgICAgICAgICAgIG9wdGlvbnMuc2VlayA6XG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgdG90YWxEdXJhdGlvbjogdHJhY2suZHVyYXRpb25NUyA/PyAwXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzYW1wbGVSYXRlOlxuICAgICAgICAgIHRoaXMucXVldWUuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5zYW1wbGVSYXRlID8/IChcbiAgICAgICAgICB0eXBlb2YgdGhpcy5xdWV1ZS5vcHRpb25zLnJlc2FtcGxlciA9PT0gJ251bWJlcicgJiZcbiAgICAgICAgICB0aGlzLnF1ZXVlLm9wdGlvbnMucmVzYW1wbGVyID4gMCA/XG4gICAgICAgICAgdGhpcy5xdWV1ZS5vcHRpb25zLnJlc2FtcGxlciA6XG4gICAgICAgICAgdW5kZWZpbmVkKSxcbiAgICAgICAgICBiaXF1YWRGaWx0ZXI6XG4gICAgICAgICAgdGhpcy5xdWV1ZS5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLmJpcXVhZCB8fCB1bmRlZmluZWQsXG4gICAgICAgICAgZXE6IHRoaXMucXVldWUuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5lcXVhbGl6ZXIsXG4gICAgICAgICAgZGVmYXVsdEZpbHRlcnM6IHRoaXMucXVldWUuZmlsdGVycy5fbGFzdEZpbHRlcnNDYWNoZS5maWx0ZXJzLFxuICAgICAgICAgIHZvbHVtZTogdGhpcy5xdWV1ZS5maWx0ZXJzLl9sYXN0RmlsdGVyc0NhY2hlLnZvbHVtZSxcbiAgICAgICAgICBkYXRhOiB0cmFjayxcbiAgICAgICAgICB0eXBlOiBTdHJlYW1UeXBlLlJhdyxcbiAgICAgICAgICBza2lwRkZtcGVnOiB0aGlzLnF1ZXVlLnBsYXllci5vcHRpb25zLnNraXBGRm1wZWdcbiAgICAgICAgfSxcbiAgICAgICAgcGxheWVyQ29uZmlnOiBvcHRpb25zXG4gICAgICB9O1xuXG4gICAgICBsZXQgcmVzb2x2ZXI6ICgpID0+IHZvaWQgPSBVdGlsLm5vb3A7XG4gICAgICBjb25zdCBkb25lUHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiByZXNvbHZlciA9IHJlc29sdmUpO1xuXG4gICAgICBjb25zdCBzdWNjZXNzID0gdGhpcy5xdWV1ZS5lbWl0KFxuICAgICAgICBHdWlsZFF1ZXVlRXZlbnQuV2lsbFBsYXlUcmFjayxcbiAgICAgICAgdGhpcy5xdWV1ZSxcbiAgICAgICAgdHJhY2ssXG4gICAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLFxuICAgICAgICByZXNvbHZlciFcbiAgICAgICk7XG5cbiAgICAgIC8vIHByZXZlbnQgZGFuZ2xpbmcgcHJvbWlzZVxuICAgICAgaWYgKCFzdWNjZXNzKSByZXNvbHZlcigpO1xuXG4gICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMucXVldWUuZGVidWcoJ1dhaXRpbmcgZm9yIHdpbGxQbGF5VHJhY2sgZXZlbnQgdG8gcmVzb2x2ZS4uLicpO1xuXG4gICAgICBhd2FpdCBkb25lUHJvbWlzZTtcblxuICAgICAgY29uc3QgZGFzcERpc2FibGVkID0gW1xuICAgICAgdHJhY2tTdHJlYW1Db25maWcuZGlzcGF0Y2hlckNvbmZpZy5kaXNhYmxlQmlxdWFkLFxuICAgICAgdHJhY2tTdHJlYW1Db25maWcuZGlzcGF0Y2hlckNvbmZpZy5kaXNhYmxlRXF1YWxpemVyLFxuICAgICAgdHJhY2tTdHJlYW1Db25maWcuZGlzcGF0Y2hlckNvbmZpZy5kaXNhYmxlRmlsdGVycyxcbiAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLmRpc3BhdGNoZXJDb25maWcuZGlzYWJsZVJlc2FtcGxlcixcbiAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLmRpc3BhdGNoZXJDb25maWcuZGlzYWJsZVZvbHVtZSxcbiAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLmRpc3BhdGNoZXJDb25maWcuZGlzYWJsZUNvbXByZXNzb3IsXG4gICAgICB0cmFja1N0cmVhbUNvbmZpZy5kaXNwYXRjaGVyQ29uZmlnLmRpc2FibGVSZXZlcmIsXG4gICAgICB0cmFja1N0cmVhbUNvbmZpZy5kaXNwYXRjaGVyQ29uZmlnLmRpc2FibGVTZWVrZXJdLlxuICAgICAgZXZlcnkoKGUpID0+ICEhZSA9PT0gdHJ1ZSk7XG5cbiAgICAgIGNvbnN0IG5lZWRzRmlsdGVycyA9XG4gICAgICAhIXRyYWNrU3RyZWFtQ29uZmlnLnBsYXllckNvbmZpZy5zZWVrIHx8XG4gICAgICAhIXRoaXMucXVldWUuZmlsdGVycy5mZm1wZWcuYXJncy5sZW5ndGg7XG4gICAgICBjb25zdCBzaG91bGRTa2lwRkZtcGVnID1cbiAgICAgICEhdHJhY2tTdHJlYW1Db25maWcuZGlzcGF0Y2hlckNvbmZpZy5za2lwRkZtcGVnICYmICFuZWVkc0ZpbHRlcnM7XG5cbiAgICAgIGxldCBmaW5hbFN0cmVhbTogUmVhZGFibGU7XG5cbiAgICAgIGNvbnN0IGRlbXV4YWJsZSA9IChmbXQ6IHN0cmluZykgPT5cbiAgICAgIFtcbiAgICAgIFN0cmVhbVR5cGUuT3B1cyxcbiAgICAgIFN0cmVhbVR5cGUuV2VibU9wdXMsXG4gICAgICBTdHJlYW1UeXBlLk9nZ09wdXMsXG4gICAgICBTdHJlYW1UeXBlLlJhdyxcbiAgICAgICdwY20nXS5cbiAgICAgIGluY2x1ZGVzKGZtdCBhcyBTdHJlYW1UeXBlKTtcblxuICAgICAgLy8gc2tpcCBmZm1wZWcgd2hlbiBwb3NzaWJsZVxuICAgICAgaWYgKFxuICAgICAgc2hvdWxkU2tpcEZGbXBlZyAmJlxuICAgICAgIShzdHJlYW1TcmMuc3RyZWFtIGluc3RhbmNlb2YgUmVhZGFibGUpICYmXG4gICAgICB0eXBlb2Ygc3RyZWFtU3JjLnN0cmVhbSAhPT0gJ3N0cmluZycgJiZcbiAgICAgIGRlbXV4YWJsZShzdHJlYW1TcmMuc3RyZWFtLiRmbXQpKVxuICAgICAge1xuICAgICAgICBjb25zdCB7ICRmbXQsIHN0cmVhbSB9ID0gc3RyZWFtU3JjLnN0cmVhbTtcbiAgICAgICAgY29uc3Qgc2hvdWxkUENNID0gIWRhc3BEaXNhYmxlZDtcblxuICAgICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgICAgICBgc2tpcEZGbXBlZyBpcyBzZXQgdG8gdHJ1ZSBhbmQgc3RyZWFtIGlzIGRlbXV4YWJsZSwgY3JlYXRpbmcgc3RyZWFtIHdpdGggdHlwZSAke1xuICAgICAgICAgIHNob3VsZFBDTSA/ICdwY20nIDogJ29wdXMnfWBcblxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGlzUmF3ID0gJGZtdCA9PT0gJ3BjbScgfHwgJGZtdCA9PT0gU3RyZWFtVHlwZS5SYXc7XG5cbiAgICAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgIGNvbnN0IG9wdXNTdHJlYW0gPVxuICAgICAgICBpc1JhdyB8fCAkZm10ID09PSBTdHJlYW1UeXBlLk9wdXMgP1xuICAgICAgICBzdHJlYW0gOlxuICAgICAgICAkZm10ID09PSBTdHJlYW1UeXBlLk9nZ09wdXMgP1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICBzdHJlYW0ucGlwZShuZXcgT2dnRGVtdXhlcigpIGFzIGFueSkgOlxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICBzdHJlYW0ucGlwZShuZXcgV2VibURlbXV4ZXIoKSBhcyBhbnkpO1xuXG4gICAgICAgIGlmIChzaG91bGRQQ00pIHtcbiAgICAgICAgICBpZiAoaXNSYXcpIHtcbiAgICAgICAgICAgIGZpbmFsU3RyZWFtID0gb3B1c1N0cmVhbTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaWYgd2UgaGF2ZSBhbnkgZmlsdGVycyBlbmFibGVkLCB3ZSBuZWVkIHRvIGRlY29kZSB0aGUgb3B1cyBzdHJlYW0gdG8gcGNtXG4gICAgICAgICAgICBmaW5hbFN0cmVhbSA9IG9wdXNTdHJlYW0ucGlwZShcbiAgICAgICAgICAgICAgbmV3IE9wdXNEZWNvZGVyKHtcbiAgICAgICAgICAgICAgICBjaGFubmVsczogMixcbiAgICAgICAgICAgICAgICBmcmFtZVNpemU6IDk2MCxcbiAgICAgICAgICAgICAgICByYXRlOiA0ODAwMFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLmRpc3BhdGNoZXJDb25maWcudHlwZSA9IFN0cmVhbVR5cGUuUmF3O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBmaW5hbFN0cmVhbSA9IG9wdXNTdHJlYW07XG4gICAgICAgICAgdHJhY2tTdHJlYW1Db25maWcuZGlzcGF0Y2hlckNvbmZpZy50eXBlID0gU3RyZWFtVHlwZS5PcHVzO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjb25zdCBvcHVzID0gZGFzcERpc2FibGVkICYmIHRoaXMuI2hhc0ZGbXBlZ09wdGltaXphdGlvbjtcbiAgICAgICAgLy8gaWYgKG9wdXMgJiYgdGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcikgdGhpcy5xdWV1ZS5kZWJ1ZygnRGlzYWJsaW5nIFBDTSBvdXRwdXQgc2luY2UgYWxsIGZpbHRlcnMgYXJlIGRpc2FibGVkIGFuZCBvcHVzIGVuY29kaW5nIGlzIHN1cHBvcnRlZC4uLicpO1xuXG4gICAgICAgIGZpbmFsU3RyZWFtID0gdGhpcy4jY3JlYXRlRkZtcGVnU3RyZWFtKFxuICAgICAgICAgIHN0cmVhbVNyYy5zdHJlYW0gaW5zdGFuY2VvZiBSZWFkYWJsZSB8fFxuICAgICAgICAgIHR5cGVvZiBzdHJlYW1TcmMuc3RyZWFtID09PSAnc3RyaW5nJyA/XG4gICAgICAgICAgc3RyZWFtU3JjLnN0cmVhbSA6XG4gICAgICAgICAgc3RyZWFtU3JjLnN0cmVhbS5zdHJlYW0sXG4gICAgICAgICAgdHJhY2ssXG4gICAgICAgICAgb3B0aW9ucy5zZWVrID8/IDBcbiAgICAgICAgICAvLyBvcHVzXG4gICAgICAgICk7XG4gICAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLmRpc3BhdGNoZXJDb25maWcudHlwZSA9IFN0cmVhbVR5cGUuUmF3O1xuICAgICAgICAvLyBGSVhNRTogT2dnT3B1cyByZXN1bHRzIGluIHN0YXRpYyBub2lzZVxuICAgICAgICAvLyB0cmFja1N0cmVhbUNvbmZpZy5kaXNwYXRjaGVyQ29uZmlnLnR5cGUgPSBvcHVzID8gU3RyZWFtVHlwZS5PZ2dPcHVzIDogU3RyZWFtVHlwZS5SYXc7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnRyYW5zaXRpb25Nb2RlKSB7XG4gICAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgICAgICB0aGlzLnF1ZXVlLmRlYnVnKFxuICAgICAgICAgIGBUcmFuc2l0aW9uIG1vZGUgZGV0ZWN0ZWQsIHBsYXllciB3aWxsIHdhaXQgZm9yIGJ1ZmZlcmluZyB0aW1lb3V0IHRvIGV4cGlyZSAoVGltZW91dDogJHt0aGlzLnF1ZXVlLm9wdGlvbnMuYnVmZmVyaW5nVGltZW91dH1tcylgXG4gICAgICAgICk7XG4gICAgICAgIGF3YWl0IHdhaXRGb3IodGhpcy5xdWV1ZS5vcHRpb25zLmJ1ZmZlcmluZ1RpbWVvdXQpO1xuICAgICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZygnQnVmZmVyaW5nIHRpbWVvdXQgaGFzIGV4cGlyZWQhJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgICAgYFByZXBhcmluZyBmaW5hbCBzdHJlYW0gY29uZmlnOiAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLFxuICAgICAgICAgIG51bGwsXG4gICAgICAgICAgMlxuICAgICAgICApfWBcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRpc3BhdGNoZXIgPSB0aGlzLnF1ZXVlLmRpc3BhdGNoZXI7XG5cbiAgICAgIGlmICghZGlzcGF0Y2hlcikge1xuICAgICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcikge1xuICAgICAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgICAgICAnRGlzcGF0Y2hlciBpcyBub3QgYXZhaWxhYmxlLCB0aGlzIGlzIG1vc3QgbGlrZWx5IGR1ZSB0byB0aGUgcXVldWUgYmVpbmcgZGVsZXRlZCBpbiB0aGUgbWlkZGxlIG9mIG9wZXJhdGlvbi4gQ2FuY2VsbGluZyB0aGUgc3RyZWFtLi4uJ1xuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBmaW5hbFN0cmVhbS5kZXN0cm95KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCByZXNvdXJjZSA9IGF3YWl0IGRpc3BhdGNoZXIuY3JlYXRlU3RyZWFtKFxuICAgICAgICAgIGZpbmFsU3RyZWFtLFxuICAgICAgICAgIHRyYWNrU3RyZWFtQ29uZmlnLmRpc3BhdGNoZXJDb25maWdcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLnF1ZXVlLnNldFRyYW5zaXRpb25pbmcoISFvcHRpb25zLnRyYW5zaXRpb25Nb2RlKTtcblxuICAgICAgICBhd2FpdCB0aGlzLiNwZXJmb3JtUGxheShyZXNvdXJjZSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpXG4gICAgICB0aGlzLnF1ZXVlLmRlYnVnKGBGYWlsZWQgdG8gaW5pdGlhbGl6ZSBhdWRpbyBwbGF5ZXI6ICR7ZX1gKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgI3Rocm93KHRyYWNrOiBUcmFjaywgZXJyb3I/OiBFcnJvciB8IG51bGwpOiB2b2lkIHtcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBjb25zdCBzdHJlYW1EZWZpbml0ZWx5RmFpbGVkTXlEZWFyVF9UUGxlYXNlVHJ1c3RNZUl0c05vdE15RmF1bHQgPVxuICAgIG5ldyBOb1Jlc3VsdEVycm9yKGBDb3VsZCBub3QgZXh0cmFjdCBzdHJlYW0gZm9yIHRoaXMgdHJhY2ske2Vycm9yID8gYFxcblxcbiR7ZXJyb3Iuc3RhY2sgfHwgZXJyb3J9YCA6ICcnfWApO1xuXG5cbiAgICB0aGlzLnF1ZXVlLmVtaXQoXG4gICAgICBHdWlsZFF1ZXVlRXZlbnQuUGxheWVyU2tpcCxcbiAgICAgIHRoaXMucXVldWUsXG4gICAgICB0cmFjayxcbiAgICAgIFRyYWNrU2tpcFJlYXNvbi5Ob1N0cmVhbSxcbiAgICAgIHN0cmVhbURlZmluaXRlbHlGYWlsZWRNeURlYXJUX1RQbGVhc2VUcnVzdE1lSXRzTm90TXlGYXVsdC5tZXNzYWdlXG4gICAgKTtcbiAgICB0aGlzLnF1ZXVlLmVtaXQoXG4gICAgICBHdWlsZFF1ZXVlRXZlbnQuUGxheWVyRXJyb3IsXG4gICAgICB0aGlzLnF1ZXVlLFxuICAgICAgc3RyZWFtRGVmaW5pdGVseUZhaWxlZE15RGVhclRfVFBsZWFzZVRydXN0TWVJdHNOb3RNeUZhdWx0LFxuICAgICAgdHJhY2tcbiAgICApO1xuICAgIGNvbnN0IG5leHRUcmFjayA9IHRoaXMucXVldWUudHJhY2tzLmRpc3BhdGNoKCk7XG4gICAgaWYgKG5leHRUcmFjaykgcmV0dXJuIHZvaWQgdGhpcy5wbGF5KG5leHRUcmFjaywgeyBxdWV1ZTogZmFsc2UgfSk7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBzaG91bGQgYmUgcmVzb2x2ZWRcbiAgICB0aGlzLnF1ZXVlLmRpc3BhdGNoZXI/LmVtaXQoJ2ZpbmlzaCcsIG51bGwpO1xuICB9XG5cbiAgYXN5bmMgI3BlcmZvcm1QbGF5KHJlc291cmNlOiBBdWRpb1Jlc291cmNlPFRyYWNrPikge1xuICAgIGlmICghdGhpcy5xdWV1ZS5kaXNwYXRjaGVyKSB7XG4gICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcikge1xuICAgICAgICB0aGlzLnF1ZXVlLmRlYnVnKFxuICAgICAgICAgICdEaXNwYXRjaGVyIGlzIG5vdCBhdmFpbGFibGUsIHRoaXMgaXMgbW9zdCBsaWtlbHkgZHVlIHRvIHRoZSBxdWV1ZSBiZWluZyBkZWxldGVkIGluIHRoZSBtaWRkbGUgb2Ygb3BlcmF0aW9uLiBDYW5jZWxsaW5nIHRoZSBzdHJlYW0uLi4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZygnSW5pdGlhbGl6aW5nIGF1ZGlvIHBsYXllci4uLicpO1xuICAgICAgYXdhaXQgdGhpcy5xdWV1ZS5kaXNwYXRjaGVyLnBsYXlTdHJlYW0ocmVzb3VyY2UpO1xuICAgICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpIHRoaXMucXVldWUuZGVidWcoJ0Rpc3BhdGNoaW5nIGF1ZGlvLi4uJyk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgI2NyZWF0ZUdlbmVyaWNTdHJlYW0odHJhY2s6IFRyYWNrKSB7XG4gICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpXG4gICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgIGBBdHRlbXB0aW5nIHRvIGV4dHJhY3Qgc3RyZWFtIGZvciBUcmFjayB7IHRpdGxlOiAke3RyYWNrLnRpdGxlfSwgdXJsOiAke3RyYWNrLnVybH0gfSB1c2luZyByZWdpc3RlcmVkIGV4dHJhY3RvcnNgXG4gICAgKTtcblxuICAgIGNvbnN0IGF0dGVtcHRlZEV4dHJhY3RvcnMgPVxuICAgIHRoaXMucXVldWUucGxheWVyLmV4dHJhY3RvcnMuZ2V0Q29udGV4dCgpPy5hdHRlbXB0ZWRFeHRyYWN0b3JzIHx8XG4gICAgbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICBjb25zdCBzdHJlYW1JbmZvID0gYXdhaXQgdGhpcy5xdWV1ZS5wbGF5ZXIuZXh0cmFjdG9ycy5ydW4oXG4gICAgICBhc3luYyAoZXh0cmFjdG9yKSA9PiB7XG4gICAgICAgIGlmIChcbiAgICAgICAgdGhpcy5xdWV1ZS5wbGF5ZXIub3B0aW9ucy5ibG9ja1N0cmVhbUZyb20/LnNvbWUoXG4gICAgICAgICAgKGV4dCkgPT4gZXh0ID09PSBleHRyYWN0b3IuaWRlbnRpZmllclxuICAgICAgICApKVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKGF0dGVtcHRlZEV4dHJhY3RvcnMuaGFzKGV4dHJhY3Rvci5pZGVudGlmaWVyKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBhdHRlbXB0ZWRFeHRyYWN0b3JzLmFkZChleHRyYWN0b3IuaWRlbnRpZmllcik7XG4gICAgICAgIGNvbnN0IGNhblN0cmVhbSA9IGF3YWl0IGV4dHJhY3Rvci52YWxpZGF0ZShcbiAgICAgICAgICB0cmFjay51cmwsXG4gICAgICAgICAgdHJhY2sucXVlcnlUeXBlIHx8IFF1ZXJ5UmVzb2x2ZXIucmVzb2x2ZSh0cmFjay51cmwpLnR5cGVcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFjYW5TdHJlYW0pIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IGV4dHJhY3Rvci5zdHJlYW0odHJhY2spO1xuICAgICAgfSxcbiAgICAgIGZhbHNlXG4gICAgKTtcblxuICAgIGlmICghc3RyZWFtSW5mbyB8fCAhc3RyZWFtSW5mby5yZXN1bHQpIHtcbiAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKSB7XG4gICAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgICAgYEZhaWxlZCB0byBleHRyYWN0IHN0cmVhbSBmb3IgVHJhY2sgeyB0aXRsZTogJHt0cmFjay50aXRsZX0sIHVybDogJHt0cmFjay51cmx9IH0gdXNpbmcgcmVnaXN0ZXJlZCBleHRyYWN0b3JzYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMucXVldWUub3B0aW9ucy5kaXNhYmxlRmFsbGJhY2tTdHJlYW0pIHtcbiAgICAgICAgaWYgKHRoaXMucXVldWUuaGFzRGVidWdnZXIpXG4gICAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgICAgYEdlbmVyaWMgc3RyZWFtIGV4dHJhY3Rpb24gZmFpbGVkIGFuZCBmYWxsYmFjayBzdHJlYW0gZXh0cmFjdGlvbiBpcyBlbmFibGVkYFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gdGhpcy4jY3JlYXRlRmFsbGJhY2tTdHJlYW0odHJhY2spO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3RyZWFtSW5mbyB8fCBudWxsO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICBgU3RyZWFtIGV4dHJhY3Rpb24gd2FzIHN1Y2Nlc3NmdWwgZm9yIFRyYWNrIHsgdGl0bGU6ICR7XG4gICAgICB0cmFjay50aXRsZX0sIHVybDogJHtcbiAgICAgIHRyYWNrLnVybH0gfSAoRXh0cmFjdG9yOiAke1xuICAgICAgc3RyZWFtSW5mby5leHRyYWN0b3I/LmlkZW50aWZpZXIgfHwgJ04vQSd9KWBcblxuICAgICk7XG5cbiAgICByZXR1cm4gc3RyZWFtSW5mbztcbiAgfVxuXG4gIGFzeW5jICNjcmVhdGVGYWxsYmFja1N0cmVhbSh0cmFjazogVHJhY2spIHtcbiAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLnF1ZXVlLmRlYnVnKFxuICAgICAgYEF0dGVtcHRpbmcgdG8gZXh0cmFjdCBzdHJlYW0gZm9yIFRyYWNrIHsgdGl0bGU6ICR7dHJhY2sudGl0bGV9LCB1cmw6ICR7dHJhY2sudXJsfSB9IHVzaW5nIGZhbGxiYWNrIHN0cmVhbWluZyBtZXRob2QuLi5gXG4gICAgKTtcblxuICAgIGNvbnN0IHZlcmlmeUZhbGxiYWNrU3RyZWFtID0gdGhpcy5xdWV1ZS5vcHRpb25zLnZlcmlmeUZhbGxiYWNrU3RyZWFtO1xuXG4gICAgY29uc3QgZmFsbGJhY2tTdHJlYW0gPSBhd2FpdCB0aGlzLnF1ZXVlLnBsYXllci5leHRyYWN0b3JzLnJ1bihcbiAgICAgIGFzeW5jIChleHRyYWN0b3IpID0+IHtcbiAgICAgICAgaWYgKGV4dHJhY3Rvci5pZGVudGlmaWVyID09PSB0cmFjay5leHRyYWN0b3I/LmlkZW50aWZpZXIpIHJldHVybiBmYWxzZTtcbiAgICAgICAgaWYgKFxuICAgICAgICB0aGlzLnF1ZXVlLnBsYXllci5vcHRpb25zLmJsb2NrU3RyZWFtRnJvbT8uc29tZShcbiAgICAgICAgICAoZXh0KSA9PiBleHQgPT09IGV4dHJhY3Rvci5pZGVudGlmaWVyXG4gICAgICAgICkpXG4gICAgICAgIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBxdWVyeSA9IGAke3RyYWNrLnRpdGxlfSAke3RyYWNrLmF1dGhvcn1gO1xuXG4gICAgICAgIGlmICh2ZXJpZnlGYWxsYmFja1N0cmVhbSkge1xuICAgICAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKSB7XG4gICAgICAgICAgICB0aGlzLnF1ZXVlLmRlYnVnKFxuICAgICAgICAgICAgICBgRmFsbGJhY2sgc3RyZWFtIHZlcmlmaWNhdGlvbiBpcyBlbmFibGVkLCB2YWxpZGF0aW5nIHF1ZXJ5IGZvciBUcmFjayB7IHRpdGxlOiAke3RyYWNrLnRpdGxlfSwgdXJsOiAke3RyYWNrLnVybH0gfSB1c2luZyAke2V4dHJhY3Rvci5pZGVudGlmaWVyfS4uLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3Qgc2hvdWxkUHJvY2VlZCA9IGF3YWl0IGV4dHJhY3Rvci52YWxpZGF0ZShcbiAgICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgICAgdHJhY2sucXVlcnlUeXBlIHx8IHRyYWNrLnNvdXJjZVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoIXNob3VsZFByb2NlZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgICAgICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgICAgICAgICAgYEZhaWxlZCB0byB2YWxpZGF0ZSBxdWVyeSBmb3IgVHJhY2sgeyB0aXRsZTogJHt0cmFjay50aXRsZX0sIHVybDogJHt0cmFjay51cmx9IH0gdXNpbmcgJHtleHRyYWN0b3IuaWRlbnRpZmllcn1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgICAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgICAgICAgIGBRdWVyeSBmb3IgVHJhY2sgeyB0aXRsZTogJHt0cmFjay50aXRsZX0sIHVybDogJHt0cmFjay51cmx9IH0gd2FzIHZhbGlkYXRlZCB1c2luZyAke2V4dHJhY3Rvci5pZGVudGlmaWVyfS4gUHJvY2VlZGluZyB3aXRoIGV4dHJhY3Rpb24uLi5gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZhbGxiYWNrVHJhY2tzID0gYXdhaXQgZXh0cmFjdG9yLmhhbmRsZShxdWVyeSwge1xuICAgICAgICAgIHJlcXVlc3RlZEJ5OiB0cmFjay5yZXF1ZXN0ZWRCeVxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBmYWxsYmFja1RyYWNrID0gZmFsbGJhY2tUcmFja3MudHJhY2tzWzBdO1xuXG4gICAgICAgIGlmICghZmFsbGJhY2tUcmFjaykgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IGV4dHJhY3Rvci5zdHJlYW0oZmFsbGJhY2tUcmFjayk7XG5cbiAgICAgICAgaWYgKCFzdHJlYW0pIHJldHVybiBmYWxzZTtcblxuICAgICAgICB0cmFjay5icmlkZ2VkVHJhY2sgPSBmYWxsYmFja1RyYWNrO1xuXG4gICAgICAgIHJldHVybiBzdHJlYW07XG4gICAgICB9LFxuICAgICAgdHJ1ZVxuICAgICk7XG5cbiAgICBpZiAoIWZhbGxiYWNrU3RyZWFtIHx8ICFmYWxsYmFja1N0cmVhbS5yZXN1bHQpIHtcbiAgICAgIGlmICh0aGlzLnF1ZXVlLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5xdWV1ZS5kZWJ1ZyhcbiAgICAgICAgYEZhaWxlZCB0byBleHRyYWN0IHN0cmVhbSBmb3IgVHJhY2sgeyB0aXRsZTogJHt0cmFjay50aXRsZX0sIHVybDogJHt0cmFjay51cmx9IH0gdXNpbmcgZmFsbGJhY2sgc3RyZWFtaW5nIG1ldGhvZGBcbiAgICAgICk7XG4gICAgICByZXR1cm4gZmFsbGJhY2tTdHJlYW0gfHwgbnVsbDtcbiAgICB9XG5cbiAgICB0cmFjay5icmlkZ2VkRXh0cmFjdG9yID0gZmFsbGJhY2tTdHJlYW0uZXh0cmFjdG9yO1xuXG4gICAgcmV0dXJuIGZhbGxiYWNrU3RyZWFtO1xuICB9XG5cbiAgI2NyZWF0ZUZGbXBlZ1N0cmVhbShcbiAgc3RyZWFtOiBSZWFkYWJsZSB8IHN0cmluZyxcbiAgdHJhY2s6IFRyYWNrLFxuICBzZWVrID0gMCxcbiAgb3B1cz86IGJvb2xlYW4pXG4gIHtcbiAgICBjb25zdCBmZm1wZWdTdHJlYW0gPSB0aGlzLnF1ZXVlLmZpbHRlcnMuZmZtcGVnLlxuICAgIGNyZWF0ZVN0cmVhbShzdHJlYW0sIHtcbiAgICAgIGVuY29kZXJBcmdzOiB0aGlzLnF1ZXVlLmZpbHRlcnMuZmZtcGVnLmFyZ3MsXG4gICAgICBzZWVrOiBzZWVrIC8gMTAwMCxcbiAgICAgIGZtdDogb3B1cyA/ICdvcHVzJyA6ICdzMTZsZScsXG4gICAgICByZXF1ZXN0T3B0aW9uczogdHJhY2sucmF3Py5yZXF1ZXN0T3B0aW9uc1xuICAgIH0pLlxuICAgIG9uKCdlcnJvcicsIChlcnIpID0+IHtcbiAgICAgIGNvbnN0IG0gPSBgJHtlcnJ9YC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICBpZiAodGhpcy5xdWV1ZS5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMucXVldWUuZGVidWcoXG4gICAgICAgIGBTdHJlYW0gY2xvc2VkIGR1ZSB0byBhbiBlcnJvciBmcm9tIEZGbXBlZyBzdHJlYW06ICR7XG4gICAgICAgIGVyci5zdGFjayB8fCBlcnIubWVzc2FnZSB8fCBlcnJ9YFxuXG4gICAgICApO1xuXG4gICAgICBpZiAobS5pbmNsdWRlcygncHJlbWF0dXJlIGNsb3NlJykgfHwgbS5pbmNsdWRlcygnZXBpcGUnKSkgcmV0dXJuO1xuXG4gICAgICB0aGlzLnF1ZXVlLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LlBsYXllckVycm9yLCB0aGlzLnF1ZXVlLCBlcnIsIHRyYWNrKTtcbiAgICB9KTtcblxuICAgIHJldHVybiBmZm1wZWdTdHJlYW07XG4gIH1cbn0iLCAiaW1wb3J0IHsgU25vd2ZsYWtlVXRpbCB9IGZyb20gJ2Rpc2NvcmQuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFzeW5jUXVldWVBY3F1aXNpdGlvbk9wdGlvbnMge1xuICAvKipcbiAgICogQWJvcnRTaWduYWwgdG8gY2FuY2VsIHRoaXMgZW50cnlcbiAgICovXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xufVxuXG5leHBvcnQgdHlwZSBBc3luY1F1ZXVlRXhjZXB0aW9uSGFuZGxlciA9IChleGNlcHRpb246IEVycm9yKSA9PiB2b2lkO1xuXG5leHBvcnQgY2xhc3MgQXN5bmNRdWV1ZSB7XG4gIC8qKlxuICAgKiBUaGUgcXVldWVkIGVudHJpZXNcbiAgICovXG4gIHB1YmxpYyBlbnRyaWVzOiBBcnJheTxBc3luY1F1ZXVlRW50cnk+ID0gW107XG5cbiAgcHVibGljIGV4Y2VwdGlvbkhhbmRsZXI/OiBBc3luY1F1ZXVlRXhjZXB0aW9uSGFuZGxlcjtcblxuICAvKipcbiAgICogQ2xlYXIgZW50cmllcyBxdWV1ZVxuICAgKiBAcGFyYW0gY29uc3VtZSBXaGV0aGVyIG9yIG5vdCB0byBjb25zdW1lIGFsbCBlbnRyaWVzIGJlZm9yZSBjbGVhcmluZ1xuICAgKi9cbiAgcHVibGljIGNsZWFyKGNvbnN1bWUgPSBmYWxzZSkge1xuICAgIGlmIChjb25zdW1lKSB7XG4gICAgICB0aGlzLmVudHJpZXMuZm9yRWFjaCgoZW50cnkpID0+IGVudHJ5LmNvbnN1bWUoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5lbnRyaWVzID0gW107XG4gIH1cblxuICAvKipcbiAgICogVGhlIHRvdGFsIG51bWJlciBvZiBlbnRyaWVzIGluIHRoaXMgcXVldWUuIFJldHVybnMgYDBgIGlmIG5vIGVudHJpZXMgYXJlIGF2YWlsYWJsZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgc2l6ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5lbnRyaWVzLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBY3F1aXJlIGFuIGVudHJ5LlxuICAgKlxuICAgKiBAZXhhbXBsZSAvLyBsb2NrIHRoZSBxdWV1ZVxuICAgKiBjb25zdCBlbnRyeSA9IGFzeW5jUXVldWUuYWNxdWlyZSgpO1xuICAgKiAvLyB3YWl0IHVudGlsIHByZXZpb3VzIHRhc2sgaXMgY29tcGxldGVkXG4gICAqIGF3YWl0IGVudHJ5LmdldFRhc2soKTtcbiAgICogLy8gZG8gc29tZXRoaW5nIGV4cGVuc2l2ZVxuICAgKiBhd2FpdCBwZXJmb3JtU29tZXRoaW5nRXhwZW5zaXZlKCk7XG4gICAqIC8vIG1ha2Ugc3VyZSB0byByZWxlYXNlIHRoZSBsb2NrIG9uY2UgZG9uZVxuICAgKiBhc3luY1F1ZXVlLnJlbGVhc2UoKTtcbiAgICpcbiAgICovXG4gIHB1YmxpYyBhY3F1aXJlKG9wdGlvbnM/OiBBc3luY1F1ZXVlQWNxdWlzaXRpb25PcHRpb25zKSB7XG4gICAgY29uc3QgZW50cnkgPSBuZXcgQXN5bmNRdWV1ZUVudHJ5KHRoaXMsIG9wdGlvbnMpO1xuXG4gICAgaWYgKHRoaXMuZXhjZXB0aW9uSGFuZGxlcikgZW50cnkuZ2V0VGFzaygpLmNhdGNoKHRoaXMuZXhjZXB0aW9uSGFuZGxlcik7XG5cbiAgICBpZiAodGhpcy5lbnRyaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5lbnRyaWVzLnB1c2goZW50cnkpO1xuICAgICAgZW50cnkuY29uc3VtZSgpO1xuICAgICAgcmV0dXJuIGVudHJ5O1xuICAgIH1cblxuICAgIHRoaXMuZW50cmllcy5wdXNoKGVudHJ5KTtcbiAgICByZXR1cm4gZW50cnk7XG4gIH1cblxuICAvKipcbiAgICogUmVsZWFzZSB0aGUgY3VycmVudCBhY3F1aXNpdGlvbiBhbmQgbW92ZSB0byBuZXh0IGVudHJ5LlxuICAgKi9cbiAgcHVibGljIHJlbGVhc2UoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmVudHJpZXMubGVuZ3RoKSByZXR1cm47XG5cbiAgICB0aGlzLmVudHJpZXMuc2hpZnQoKTtcbiAgICB0aGlzLmVudHJpZXNbMF0/LmNvbnN1bWUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYW5jZWwgYWxsIGVudHJpZXNcbiAgICovXG4gIHB1YmxpYyBjYW5jZWxBbGwoKSB7XG4gICAgdGhpcy5lbnRyaWVzLmZvckVhY2goKGVudHJ5KSA9PiBlbnRyeS5jYW5jZWwoKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIHRoZSBnaXZlbiBlbnRyeSBmcm9tIHRoZSBxdWV1ZVxuICAgKiBAcGFyYW0gZW50cnkgVGhlIGVudHJ5IHRvIHJlbW92ZVxuICAgKi9cbiAgcHVibGljIHJlbW92ZUVudHJ5KGVudHJ5OiBBc3luY1F1ZXVlRW50cnkpIHtcbiAgICBjb25zdCBlbnRyeUlkeCA9IHRoaXMuZW50cmllcy5pbmRleE9mKGVudHJ5KTtcblxuICAgIGlmIChlbnRyeUlkeCAhPT0gLTEpIHtcbiAgICAgIHRoaXMuZW50cmllcy5zcGxpY2UoZW50cnlJZHgsIDEpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBBc3luY1F1ZXVlRW50cnkge1xuICBwdWJsaWMgcmVhZG9ubHkgaWQgPSBTbm93Zmxha2VVdGlsLmdlbmVyYXRlKCkudG9TdHJpbmcoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9taXNlOiBQcm9taXNlPHZvaWQ+O1xuICBwdWJsaWMgc2lnbmFsOiBBYm9ydFNpZ25hbCB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgb25BYm9ydDogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVzb2x2ZSE6ICgpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVqZWN0ITogKGVycjogRXJyb3IpID0+IHZvaWQ7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICBwdWJsaWMgcXVldWU6IEFzeW5jUXVldWUsXG4gIHB1YmxpYyBvcHRpb25zPzogQXN5bmNRdWV1ZUFjcXVpc2l0aW9uT3B0aW9ucylcbiAge1xuICAgIHRoaXMucHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgICB0aGlzLnJlamVjdCA9IHJlamVjdDtcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnM/LnNpZ25hbCkge1xuICAgICAgdGhpcy5zZXRBYm9ydFNpZ25hbCh0aGlzLm9wdGlvbnMuc2lnbmFsKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgc2V0QWJvcnRTaWduYWwoc2lnbmFsOiBBYm9ydFNpZ25hbCkge1xuICAgIGlmIChzaWduYWwuYWJvcnRlZCkgcmV0dXJuO1xuICAgIHRoaXMuc2lnbmFsID0gc2lnbmFsO1xuICAgIHRoaXMub25BYm9ydCA9ICgpID0+IHtcbiAgICAgIHRoaXMucXVldWUucmVtb3ZlRW50cnkodGhpcyk7XG4gICAgICB0aGlzLmNhbmNlbCgpO1xuICAgIH07XG5cbiAgICB0aGlzLnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIHRoaXMub25BYm9ydCk7XG4gIH1cblxuICBwdWJsaWMgY29uc3VtZSgpIHtcbiAgICB0aGlzLmNsZWFudXAoKTtcbiAgICB0aGlzLnJlc29sdmUoKTtcbiAgfVxuXG4gIHB1YmxpYyByZWxlYXNlKCkge1xuICAgIHRoaXMuY29uc3VtZSgpO1xuICAgIHRoaXMucXVldWUucmVsZWFzZSgpO1xuICB9XG5cbiAgcHVibGljIGNhbmNlbCgpIHtcbiAgICB0aGlzLmNsZWFudXAoKTtcbiAgICB0aGlzLnJlamVjdChuZXcgRXJyb3IoJ0NhbmNlbGxlZCcpKTtcbiAgfVxuXG4gIHB1YmxpYyBjbGVhbnVwKCkge1xuICAgIGlmICh0aGlzLm9uQWJvcnQpIHRoaXMuc2lnbmFsPy5yZW1vdmVFdmVudExpc3RlbmVyKCdhYm9ydCcsIHRoaXMub25BYm9ydCk7XG4gICAgdGhpcy5zaWduYWwgPSBudWxsO1xuICAgIHRoaXMub25BYm9ydCA9IG51bGw7XG4gIH1cblxuICBwdWJsaWMgZ2V0VGFzaygpIHtcbiAgICByZXR1cm4gdGhpcy5wcm9taXNlO1xuICB9XG59IiwgImltcG9ydCB7IFJlYWRhYmxlIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCB7IEF1ZGlvRmlsdGVycywgRmlsdGVyc05hbWUsIFF1ZXVlRmlsdGVycyB9IGZyb20gJy4uL3V0aWxzL0F1ZGlvRmlsdGVycyc7XG5pbXBvcnQgeyBHdWlsZFF1ZXVlLCBHdWlsZFF1ZXVlRXZlbnQgfSBmcm9tICcuL0d1aWxkUXVldWUnO1xuaW1wb3J0IHtcbiAgQmlxdWFkRmlsdGVycyxcbiAgRXF1YWxpemVyLFxuICBFcXVhbGl6ZXJCYW5kLFxuICBQQ01GaWx0ZXJzIH0gZnJvbVxuJ0BkaXNjb3JkLXBsYXllci9lcXVhbGl6ZXInO1xuaW1wb3J0IHsgRkZtcGVnU3RyZWFtT3B0aW9ucywgY3JlYXRlRkZtcGVnU3RyZWFtIH0gZnJvbSAnLi4vdXRpbHMvRkZtcGVnU3RyZWFtJztcbmltcG9ydCB7IEludmFsaWRBcmdUeXBlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHsgU3RyZWFtQ29uZmlnIH0gZnJvbSAnLi9HdWlsZFF1ZXVlUGxheWVyTm9kZSc7XG5cbnR5cGUgRmlsdGVycyA9IGtleW9mIHR5cGVvZiBBdWRpb0ZpbHRlcnMuZmlsdGVycztcblxuY29uc3QgbWFrZUJhbmRzID0gKGFycjogbnVtYmVyW10pID0+IHtcbiAgcmV0dXJuIEFycmF5LmZyb20oXG4gICAge1xuICAgICAgbGVuZ3RoOiBFcXVhbGl6ZXIuQkFORF9DT1VOVFxuICAgIH0sXG4gICAgKF8sIGkpID0+ICh7XG4gICAgICBiYW5kOiBpLFxuICAgICAgZ2FpbjogYXJyW2ldID8gYXJyW2ldIC8gMzAgOiAwXG4gICAgfSlcbiAgKSBhcyBFcXVhbGl6ZXJCYW5kW107XG59O1xuXG50eXBlIEVRUHJlc2V0ID0ge1xuICBGbGF0OiBFcXVhbGl6ZXJCYW5kW107XG4gIENsYXNzaWNhbDogRXF1YWxpemVyQmFuZFtdO1xuICBDbHViOiBFcXVhbGl6ZXJCYW5kW107XG4gIERhbmNlOiBFcXVhbGl6ZXJCYW5kW107XG4gIEZ1bGxCYXNzOiBFcXVhbGl6ZXJCYW5kW107XG4gIEZ1bGxCYXNzVHJlYmxlOiBFcXVhbGl6ZXJCYW5kW107XG4gIEZ1bGxUcmVibGU6IEVxdWFsaXplckJhbmRbXTtcbiAgSGVhZHBob25lczogRXF1YWxpemVyQmFuZFtdO1xuICBMYXJnZUhhbGw6IEVxdWFsaXplckJhbmRbXTtcbiAgTGl2ZTogRXF1YWxpemVyQmFuZFtdO1xuICBQYXJ0eTogRXF1YWxpemVyQmFuZFtdO1xuICBQb3A6IEVxdWFsaXplckJhbmRbXTtcbiAgUmVnZ2FlOiBFcXVhbGl6ZXJCYW5kW107XG4gIFJvY2s6IEVxdWFsaXplckJhbmRbXTtcbiAgU2thOiBFcXVhbGl6ZXJCYW5kW107XG4gIFNvZnQ6IEVxdWFsaXplckJhbmRbXTtcbiAgU29mdFJvY2s6IEVxdWFsaXplckJhbmRbXTtcbiAgVGVjaG5vOiBFcXVhbGl6ZXJCYW5kW107XG59O1xuXG5leHBvcnQgY29uc3QgRXF1YWxpemVyQ29uZmlndXJhdGlvblByZXNldDogUmVhZG9ubHk8RVFQcmVzZXQ+ID0gT2JqZWN0LmZyZWV6ZSh7XG4gIEZsYXQ6IG1ha2VCYW5kcyhbXSksXG4gIENsYXNzaWNhbDogbWFrZUJhbmRzKFtcbiAgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsIC0xLjExMDIyZS0xNSwgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsXG4gIC0xLjExMDIyZS0xNSwgLTcuMiwgLTcuMiwgLTcuMiwgLTkuNl1cbiAgKSxcbiAgQ2x1YjogbWFrZUJhbmRzKFtcbiAgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsIDguMCwgNS42LCA1LjYsIDUuNiwgMy4yLCAtMS4xMTAyMmUtMTUsXG4gIC0xLjExMDIyZS0xNSwgLTEuMTEwMjJlLTE1XVxuICApLFxuICBEYW5jZTogbWFrZUJhbmRzKFtcbiAgOS42LCA3LjIsIDIuNCwgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsIC01LjYsIC03LjIsIC03LjIsIC0xLjExMDIyZS0xNSxcbiAgLTEuMTEwMjJlLTE1XVxuICApLFxuICBGdWxsQmFzczogbWFrZUJhbmRzKFtcbiAgLTguMCwgOS42LCA5LjYsIDUuNiwgMS42LCAtNC4wLCAtOC4wLCAtMTAuNCwgLTExLjIsIC0xMS4yXVxuICApLFxuICBGdWxsQmFzc1RyZWJsZTogbWFrZUJhbmRzKFtcbiAgNy4yLCA1LjYsIC0xLjExMDIyZS0xNSwgLTcuMiwgLTQuOCwgMS42LCA4LjAsIDExLjIsIDEyLjAsIDEyLjBdXG4gICksXG4gIEZ1bGxUcmVibGU6IG1ha2VCYW5kcyhbXG4gIC05LjYsIC05LjYsIC05LjYsIC00LjAsIDIuNCwgMTEuMiwgMTYuMCwgMTYuMCwgMTYuMCwgMTYuOF1cbiAgKSxcbiAgSGVhZHBob25lczogbWFrZUJhbmRzKFtcbiAgNC44LCAxMS4yLCA1LjYsIC0zLjIsIC0yLjQsIDEuNiwgNC44LCA5LjYsIDEyLjgsIDE0LjRdXG4gICksXG4gIExhcmdlSGFsbDogbWFrZUJhbmRzKFtcbiAgMTAuNCwgMTAuNCwgNS42LCA1LjYsIC0xLjExMDIyZS0xNSwgLTQuOCwgLTQuOCwgLTQuOCwgLTEuMTEwMjJlLTE1LFxuICAtMS4xMTAyMmUtMTVdXG4gICksXG4gIExpdmU6IG1ha2VCYW5kcyhbLTQuOCwgLTEuMTEwMjJlLTE1LCA0LjAsIDUuNiwgNS42LCA1LjYsIDQuMCwgMi40LCAyLjQsIDIuNF0pLFxuICBQYXJ0eTogbWFrZUJhbmRzKFtcbiAgNy4yLCA3LjIsIC0xLjExMDIyZS0xNSwgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsIC0xLjExMDIyZS0xNSxcbiAgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsIDcuMiwgNy4yXVxuICApLFxuICBQb3A6IG1ha2VCYW5kcyhbXG4gIC0xLjYsIDQuOCwgNy4yLCA4LjAsIDUuNiwgLTEuMTEwMjJlLTE1LCAtMi40LCAtMi40LCAtMS42LCAtMS42XVxuICApLFxuICBSZWdnYWU6IG1ha2VCYW5kcyhbXG4gIC0xLjExMDIyZS0xNSwgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTUsIC01LjYsIC0xLjExMDIyZS0xNSwgNi40LCA2LjQsXG4gIC0xLjExMDIyZS0xNSwgLTEuMTEwMjJlLTE1LCAtMS4xMTAyMmUtMTVdXG4gICksXG4gIFJvY2s6IG1ha2VCYW5kcyhbOC4wLCA0LjgsIC01LjYsIC04LjAsIC0zLjIsIDQuMCwgOC44LCAxMS4yLCAxMS4yLCAxMS4yXSksXG4gIFNrYTogbWFrZUJhbmRzKFtcbiAgLTIuNCwgLTQuOCwgLTQuMCwgLTEuMTEwMjJlLTE1LCA0LjAsIDUuNiwgOC44LCA5LjYsIDExLjIsIDkuNl1cbiAgKSxcbiAgU29mdDogbWFrZUJhbmRzKFtcbiAgNC44LCAxLjYsIC0xLjExMDIyZS0xNSwgLTIuNCwgLTEuMTEwMjJlLTE1LCA0LjAsIDguMCwgOS42LCAxMS4yLCAxMi4wXVxuICApLFxuICBTb2Z0Um9jazogbWFrZUJhbmRzKFtcbiAgNC4wLCA0LjAsIDIuNCwgLTEuMTEwMjJlLTE1LCAtNC4wLCAtNS42LCAtMy4yLCAtMS4xMTAyMmUtMTUsIDIuNCwgOC44XVxuICApLFxuICBUZWNobm86IG1ha2VCYW5kcyhbXG4gIDguMCwgNS42LCAtMS4xMTAyMmUtMTUsIC01LjYsIC00LjgsIC0xLjExMDIyZS0xNSwgOC4wLCA5LjYsIDkuNiwgOC44XVxuICApXG59KTtcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmV4cG9ydCBjbGFzcyBGRm1wZWdGaWx0ZXJlcjxNZXRhID0gYW55PiB7XG4gICNmZm1wZWdGaWx0ZXJzOiBGaWx0ZXJzW10gPSBbXTtcbiAgI2lucHV0QXJnczogc3RyaW5nW10gPSBbXTtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIGFmOiBHdWlsZFF1ZXVlQXVkaW9GaWx0ZXJzPE1ldGE+KSB7fVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBmZm1wZWcgbWF5IGJlIHNraXBwZWRcbiAgICovXG4gIHB1YmxpYyBnZXQgc2tpcHBhYmxlKCkge1xuICAgIHJldHVybiAhIXRoaXMuYWYucXVldWUucGxheWVyLm9wdGlvbnMuc2tpcEZGbXBlZztcbiAgfVxuXG4gICNzZXRGaWx0ZXJzKGZpbHRlcnM6IEZpbHRlcnNbXSkge1xuICAgIGNvbnN0IHsgcXVldWUgfSA9IHRoaXMuYWY7XG4gICAgLy8gc2tpcCBpZiBmaWx0ZXJzIGFyZSB0aGUgc2FtZVxuICAgIGlmIChcbiAgICBmaWx0ZXJzLmV2ZXJ5KChmKSA9PiB0aGlzLiNmZm1wZWdGaWx0ZXJzLmluY2x1ZGVzKGYpKSAmJlxuICAgIHRoaXMuI2ZmbXBlZ0ZpbHRlcnMuZXZlcnkoKGYpID0+IGZpbHRlcnMuaW5jbHVkZXMoZikpKVxuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgY29uc3QgaWdub3JlRmlsdGVycyA9XG4gICAgdGhpcy5maWx0ZXJzLnNvbWUoKGZmKSA9PiBmZiA9PT0gJ25pZ2h0Y29yZScgfHwgZmYgPT09ICd2YXBvcndhdmUnKSAmJlxuICAgICFmaWx0ZXJzLnNvbWUoKGZmKSA9PiBmZiA9PT0gJ25pZ2h0Y29yZScgfHwgZmYgPT09ICd2YXBvcndhdmUnKTtcbiAgICBjb25zdCBzZWVrVGltZSA9IHF1ZXVlLm5vZGUuZ2V0VGltZXN0YW1wKGlnbm9yZUZpbHRlcnMpPy5jdXJyZW50LnZhbHVlIHx8IDA7XG4gICAgY29uc3QgcHJldiA9IHRoaXMuI2ZmbXBlZ0ZpbHRlcnMuc2xpY2UoKTtcbiAgICB0aGlzLiNmZm1wZWdGaWx0ZXJzID0gWy4uLm5ldyBTZXQoZmlsdGVycyldO1xuXG4gICAgcmV0dXJuIHRoaXMuYWYudHJpZ2dlclJlcGxheShzZWVrVGltZSkudGhlbigodCkgPT4ge1xuICAgICAgcXVldWUuZW1pdChcbiAgICAgICAgR3VpbGRRdWV1ZUV2ZW50LkF1ZGlvRmlsdGVyc1VwZGF0ZSxcbiAgICAgICAgcXVldWUsXG4gICAgICAgIHByZXYsXG4gICAgICAgIHRoaXMuI2ZmbXBlZ0ZpbHRlcnMuc2xpY2UoKVxuICAgICAgKTtcbiAgICAgIHJldHVybiB0O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBpbnB1dCBhcmdzIGZvciBGRm1wZWdcbiAgICovXG4gIHB1YmxpYyBzZXRJbnB1dEFyZ3MoYXJnczogc3RyaW5nW10pIHtcbiAgICBpZiAoIWFyZ3MuZXZlcnkoKGFyZykgPT4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpKVxuICAgIHRocm93IG5ldyBJbnZhbGlkQXJnVHlwZUVycm9yKCdhcmdzJywgJ0FycmF5PHN0cmluZz4nLCAnaW52YWxpZCBpdGVtKHMpJyk7XG4gICAgdGhpcy4jaW5wdXRBcmdzID0gYXJncztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgaW5wdXQgYXJnc1xuICAgKi9cbiAgcHVibGljIGdldCBpbnB1dEFyZ3MoKSB7XG4gICAgcmV0dXJuIHRoaXMuI2lucHV0QXJncztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZW5jb2RlciBhcmdzXG4gICAqL1xuICBwdWJsaWMgZ2V0IGVuY29kZXJBcmdzKCkge1xuICAgIGlmICghdGhpcy5maWx0ZXJzLmxlbmd0aCkgcmV0dXJuIFtdO1xuXG4gICAgcmV0dXJuIFsnLWFmJywgdGhpcy50b1N0cmluZygpXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZmluYWwgZmZtcGVnIGFyZ3NcbiAgICovXG4gIHB1YmxpYyBnZXQgYXJncygpIHtcbiAgICByZXR1cm4gdGhpcy5pbnB1dEFyZ3MuY29uY2F0KHRoaXMuZW5jb2RlckFyZ3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBmZm1wZWcgc3RyZWFtXG4gICAqIEBwYXJhbSBzb3VyY2UgVGhlIHN0cmVhbSBzb3VyY2VcbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIHN0cmVhbSBvcHRpb25zXG4gICAqL1xuICBwdWJsaWMgY3JlYXRlU3RyZWFtKHNvdXJjZTogc3RyaW5nIHwgUmVhZGFibGUsIG9wdGlvbnM6IEZGbXBlZ1N0cmVhbU9wdGlvbnMpIHtcbiAgICBpZiAodGhpcy4jaW5wdXRBcmdzLmxlbmd0aClcbiAgICBvcHRpb25zLmVuY29kZXJBcmdzID0gW1xuICAgIC4uLnRoaXMuI2lucHV0QXJncyxcbiAgICAuLi4ob3B0aW9ucy5lbmNvZGVyQXJncyB8fCBbXSldO1xuXG5cbiAgICBjb25zdCBzdHJlYW0gPSBjcmVhdGVGRm1wZWdTdHJlYW0oc291cmNlLCBvcHRpb25zKTtcblxuICAgIHJldHVybiBzdHJlYW07XG4gIH1cblxuICAvKipcbiAgICogU2V0IGZmbXBlZyBmaWx0ZXJzXG4gICAqIEBwYXJhbSBmaWx0ZXJzIFRoZSBmaWx0ZXJzXG4gICAqL1xuICBwdWJsaWMgc2V0RmlsdGVycyhcbiAgZmlsdGVyczogRmlsdGVyc1tdIHwgUmVjb3JkPEZpbHRlcnMsIGJvb2xlYW4+IHwgc3RyaW5nW10gfCBib29sZWFuKVxuICB7XG4gICAgbGV0IF9maWx0ZXJzOiBGaWx0ZXJzW10gPSBbXTtcbiAgICBpZiAodHlwZW9mIGZpbHRlcnMgPT09ICdib29sZWFuJykge1xuICAgICAgX2ZpbHRlcnMgPSAhZmlsdGVycyA/XG4gICAgICBbXSA6XG4gICAgICBPYmplY3Qua2V5cyhBdWRpb0ZpbHRlcnMuZmlsdGVycykgYXMgRmlsdGVyc1tdO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShmaWx0ZXJzKSkge1xuICAgICAgX2ZpbHRlcnMgPSBmaWx0ZXJzIGFzIEZpbHRlcnNbXTtcbiAgICB9IGVsc2Uge1xuICAgICAgX2ZpbHRlcnMgPSBPYmplY3QuZW50cmllcyhmaWx0ZXJzKS5cbiAgICAgIGZpbHRlcigocmVzKSA9PiByZXNbMV0gPT09IHRydWUpLlxuICAgICAgbWFwKChtKSA9PiBtWzBdKSBhcyBGaWx0ZXJzW107XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuI3NldEZpbHRlcnMoX2ZpbHRlcnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEN1cnJlbnRseSBhY3RpdmUgZmZtcGVnIGZpbHRlcnNcbiAgICovXG4gIHB1YmxpYyBnZXQgZmlsdGVycygpIHtcbiAgICByZXR1cm4gdGhpcy4jZmZtcGVnRmlsdGVycztcbiAgfVxuXG4gIHB1YmxpYyBzZXQgZmlsdGVycyhmaWx0ZXJzOiBGaWx0ZXJzW10pIHtcbiAgICB0aGlzLnNldEZpbHRlcnMoZmlsdGVycyk7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIGdpdmVuIGZmbXBlZyBmaWx0ZXIocylcbiAgICogQHBhcmFtIGZpbHRlcnMgVGhlIGZpbHRlcihzKVxuICAgKi9cbiAgcHVibGljIHRvZ2dsZShmaWx0ZXJzOiBGaWx0ZXJzW10gfCBGaWx0ZXJzKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGZpbHRlcnMpKSBmaWx0ZXJzID0gW2ZpbHRlcnNdO1xuICAgIGNvbnN0IGZyZXNoOiBGaWx0ZXJzW10gPSBbXTtcblxuICAgIGZpbHRlcnMuZm9yRWFjaCgoZikgPT4ge1xuICAgICAgaWYgKHRoaXMuZmlsdGVycy5pbmNsdWRlcyhmKSkgcmV0dXJuO1xuICAgICAgZnJlc2gucHVzaChmKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB0aGlzLiNzZXRGaWx0ZXJzKFxuICAgICAgdGhpcy4jZmZtcGVnRmlsdGVycy5maWx0ZXIoKHIpID0+ICFmaWx0ZXJzLmluY2x1ZGVzKHIpKS5jb25jYXQoZnJlc2gpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgZGVmYXVsdCBmaWx0ZXJzXG4gICAqIEBwYXJhbSBmZiBGaWx0ZXJzIGxpc3RcbiAgICovXG4gIHB1YmxpYyBzZXREZWZhdWx0cyhmZjogRmlsdGVyc1tdKSB7XG4gICAgdGhpcy4jZmZtcGVnRmlsdGVycyA9IGZmO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBsaXN0IG9mIGVuYWJsZWQgZmlsdGVyc1xuICAgKi9cbiAgcHVibGljIGdldEZpbHRlcnNFbmFibGVkKCkge1xuICAgIHJldHVybiB0aGlzLiNmZm1wZWdGaWx0ZXJzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBsaXN0IG9mIGRpc2FibGVkIGZpbHRlcnNcbiAgICovXG4gIHB1YmxpYyBnZXRGaWx0ZXJzRGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIEF1ZGlvRmlsdGVycy5uYW1lcy5maWx0ZXIoKGYpID0+ICF0aGlzLiNmZm1wZWdGaWx0ZXJzLmluY2x1ZGVzKGYpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gZmlsdGVyIGlzIGVuYWJsZWRcbiAgICogQHBhcmFtIGZpbHRlciBUaGUgZmlsdGVyXG4gICAqL1xuICBwdWJsaWMgaXNFbmFibGVkPFQgZXh0ZW5kcyBGaWx0ZXJzPihmaWx0ZXI6IFQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy4jZmZtcGVnRmlsdGVycy5pbmNsdWRlcyhmaWx0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBnaXZlbiBmaWx0ZXIgaXMgZGlzYWJsZWRcbiAgICogQHBhcmFtIGZpbHRlciBUaGUgZmlsdGVyXG4gICAqL1xuICBwdWJsaWMgaXNEaXNhYmxlZDxUIGV4dGVuZHMgRmlsdGVycz4oZmlsdGVyOiBUKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLmlzRW5hYmxlZChmaWx0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBnaXZlbiBmaWx0ZXIgaXMgYSB2YWxpZCBmaWx0ZXJcbiAgICogQHBhcmFtIGZpbHRlciBUaGUgZmlsdGVyIHRvIHRlc3RcbiAgICovXG4gIHB1YmxpYyBpc1ZhbGlkRmlsdGVyKGZpbHRlcjogc3RyaW5nKTogZmlsdGVyIGlzIEZpbHRlcnNOYW1lIHtcbiAgICByZXR1cm4gQXVkaW9GaWx0ZXJzLmhhcyhmaWx0ZXIgYXMgRmlsdGVycyk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBjdXJyZW50IGZpbHRlcnMgdG8gYXJyYXlcbiAgICovXG4gIHB1YmxpYyB0b0FycmF5KCkge1xuICAgIHJldHVybiB0aGlzLmZpbHRlcnMubWFwKChmaWx0ZXIpID0+IEF1ZGlvRmlsdGVycy5nZXQoZmlsdGVyKSk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBjdXJyZW50IGZpbHRlcnMgdG8gSlNPTiBvYmplY3RcbiAgICovXG4gIHB1YmxpYyB0b0pTT04oKSB7XG4gICAgY29uc3Qgb2JqID0ge30gYXMgUmVjb3JkPGtleW9mIFF1ZXVlRmlsdGVycywgc3RyaW5nPjtcblxuICAgIHRoaXMuZmlsdGVycy5mb3JFYWNoKChmaWx0ZXIpID0+IG9ialtmaWx0ZXJdID0gQXVkaW9GaWx0ZXJzLmdldChmaWx0ZXIpKTtcblxuICAgIHJldHVybiBvYmo7XG4gIH1cblxuICAvKipcbiAgICogU3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGN1cnJlbnQgZmlsdGVyc1xuICAgKi9cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBBdWRpb0ZpbHRlcnMuY3JlYXRlKHRoaXMuZmlsdGVycyk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBHdWlsZFF1ZXVlQUZpbHRlcnNDYWNoZSB7XG4gIGVxdWFsaXplcjogRXF1YWxpemVyQmFuZFtdO1xuICBiaXF1YWQ6IEJpcXVhZEZpbHRlcnMgfCBudWxsO1xuICBmaWx0ZXJzOiBQQ01GaWx0ZXJzW107XG4gIHZvbHVtZTogbnVtYmVyO1xuICBzYW1wbGVSYXRlOiBudW1iZXI7XG4gIHNhbXBsZVJhdGVGaWx0ZXI6XG4gIFN0cmVhbUNvbmZpZ1snZGlzcGF0Y2hlckNvbmZpZyddWydzYW1wbGVSYXRlRmlsdGVycyddIHxcbiAgbnVsbDtcbiAgY29tcHJlc3NvcjogU3RyZWFtQ29uZmlnWydkaXNwYXRjaGVyQ29uZmlnJ11bJ2NvbXByZXNzb3InXSB8IG51bGw7XG4gIHJldmVyYjogU3RyZWFtQ29uZmlnWydkaXNwYXRjaGVyQ29uZmlnJ11bJ3JldmVyYiddIHwgbnVsbDtcbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmV4cG9ydCBjbGFzcyBHdWlsZFF1ZXVlQXVkaW9GaWx0ZXJzPE1ldGEgPSBhbnk+IHtcbiAgcHVibGljIGdyYXBoID0gbmV3IEFGaWx0ZXJHcmFwaDxNZXRhPih0aGlzKTtcbiAgcHVibGljIGZmbXBlZyA9IG5ldyBGRm1wZWdGaWx0ZXJlcjxNZXRhPih0aGlzKTtcbiAgcHVibGljIGVxdWFsaXplclByZXNldHMgPSBFcXVhbGl6ZXJDb25maWd1cmF0aW9uUHJlc2V0O1xuICBwdWJsaWMgX2xhc3RGaWx0ZXJzQ2FjaGU6IEd1aWxkUXVldWVBRmlsdGVyc0NhY2hlID0ge1xuICAgIGJpcXVhZDogbnVsbCxcbiAgICBlcXVhbGl6ZXI6IFtdLFxuICAgIGZpbHRlcnM6IFtdLFxuICAgIHZvbHVtZTogMTAwLFxuICAgIHNhbXBsZVJhdGU6IC0xLFxuICAgIGNvbXByZXNzb3I6IG51bGwsXG4gICAgcmV2ZXJiOiBudWxsLFxuICAgIHNhbXBsZVJhdGVGaWx0ZXI6IG51bGxcbiAgfTtcbiAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyBxdWV1ZTogR3VpbGRRdWV1ZTxNZXRhPikge1xuICAgIGlmICh0eXBlb2YgdGhpcy5xdWV1ZS5vcHRpb25zLnZvbHVtZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuX2xhc3RGaWx0ZXJzQ2FjaGUudm9sdW1lID0gdGhpcy5xdWV1ZS5vcHRpb25zLnZvbHVtZTtcbiAgICB9XG4gIH1cblxuICAvLyBUT0RPOiBlbmFibGUgdGhpcyBpbiB0aGUgZnV0dXJlXG4gIC8vIHB1YmxpYyBnZXQgZmZtcGVnKCk6IEZGbXBlZ0ZpbHRlcmVyPE1ldGE+IHwgbnVsbCB7XG4gIC8vICAgICBpZiAodGhpcy5xdWV1ZS5wbGF5ZXIub3B0aW9ucy5za2lwRkZtcGVnKSB7XG4gIC8vICAgICAgICAgaWYgKHRoaXMuI2ZmbXBlZykgdGhpcy4jZmZtcGVnID0gbnVsbDtcbiAgLy8gICAgICAgICByZXR1cm4gbnVsbDtcbiAgLy8gICAgIH1cblxuICAvLyAgICAgaWYgKCF0aGlzLiNmZm1wZWcpIHtcbiAgLy8gICAgICAgICB0aGlzLiNmZm1wZWcgPSBuZXcgRkZtcGVnRmlsdGVyZXI8TWV0YT4odGhpcyk7XG4gIC8vICAgICB9XG5cbiAgLy8gICAgIHJldHVybiB0aGlzLiNmZm1wZWc7XG4gIC8vIH1cblxuICAvKipcbiAgICogVm9sdW1lIHRyYW5zZm9ybWVyXG4gICAqL1xuICBwdWJsaWMgZ2V0IHZvbHVtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5kc3A/LnZvbHVtZSB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIDE1IEJhbmQgRXF1YWxpemVyXG4gICAqL1xuICBwdWJsaWMgZ2V0IGVxdWFsaXplcigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5lcXVhbGl6ZXIgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaWdpdGFsIGJpcXVhZCBmaWx0ZXJzXG4gICAqL1xuICBwdWJsaWMgZ2V0IGJpcXVhZCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5iaXF1YWQgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEU1AgZmlsdGVyc1xuICAgKi9cbiAgcHVibGljIGdldCBmaWx0ZXJzKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlLmRpc3BhdGNoZXI/LmZpbHRlcnMgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdWRpbyByZXNhbXBsZXJcbiAgICovXG4gIHB1YmxpYyBnZXQgcmVzYW1wbGVyKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXVlLmRpc3BhdGNoZXI/LnJlc2FtcGxlciB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbXByZXNzb3IgdHJhbnNmb3JtZXJcbiAgICovXG4gIHB1YmxpYyBnZXQgY29tcHJlc3NvcigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5jb21wcmVzc29yIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV2ZXJiIHRyYW5zZm9ybWVyXG4gICAqL1xuICBwdWJsaWMgZ2V0IHJldmVyYigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5yZXZlcmIgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQQ00gU2Vla2VyIHRyYW5zZm9ybWVyXG4gICAqL1xuICBwdWJsaWMgZ2V0IHNlZWtlcigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWV1ZS5kaXNwYXRjaGVyPy5zZWVrZXIgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYXkgY3VycmVudCB0cmFjayBpbiB0cmFuc2l0aW9uIG1vZGVcbiAgICogQHBhcmFtIHNlZWsgVGhlIGR1cmF0aW9uIHRvIHNlZWsgdG9cbiAgICovXG4gIHB1YmxpYyBhc3luYyB0cmlnZ2VyUmVwbGF5KHNlZWsgPSAwKSB7XG4gICAgaWYgKCF0aGlzLnF1ZXVlLmN1cnJlbnRUcmFjaykgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5xdWV1ZS5ub2RlLnRhc2tzUXVldWUuYWNxdWlyZSgpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBlbnRyeS5nZXRUYXNrKCk7XG4gICAgICBhd2FpdCB0aGlzLnF1ZXVlLm5vZGUucGxheSh0aGlzLnF1ZXVlLmN1cnJlbnRUcmFjaywge1xuICAgICAgICBxdWV1ZTogZmFsc2UsXG4gICAgICAgIHNlZWssXG4gICAgICAgIHRyYW5zaXRpb25Nb2RlOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIHRoaXMucXVldWUubm9kZS50YXNrc1F1ZXVlLnJlbGVhc2UoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgdGhpcy5xdWV1ZS5ub2RlLnRhc2tzUXVldWUucmVsZWFzZSgpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IGNsYXNzIEFGaWx0ZXJHcmFwaDxNZXRhID0gYW55PiB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgYWY6IEd1aWxkUXVldWVBdWRpb0ZpbHRlcnM8TWV0YT4pIHt9XG5cbiAgcHVibGljIGdldCBmZm1wZWcoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWYuZmZtcGVnPy5maWx0ZXJzID8/IFtdO1xuICB9XG5cbiAgcHVibGljIGdldCBlcXVhbGl6ZXIoKSB7XG4gICAgcmV0dXJuICh0aGlzLmFmLmVxdWFsaXplcj8uYmFuZE11bHRpcGxpZXJzIHx8IFtdKS5tYXAoKG0sIGkpID0+ICh7XG4gICAgICBiYW5kOiBpLFxuICAgICAgZ2FpbjogbVxuICAgIH0pKSBhcyBFcXVhbGl6ZXJCYW5kW107XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJpcXVhZCgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5hZi5iaXF1YWQ/LmdldEZpbHRlck5hbWUoKSBhcyBFeGNsdWRlPFxuICAgICAgICBCaXF1YWRGaWx0ZXJzLFxuICAgICAgICBudW1iZXI+IHxcbiAgICAgIG51bGwgfHwgbnVsbCk7XG5cbiAgfVxuXG4gIHB1YmxpYyBnZXQgZmlsdGVycygpIHtcbiAgICByZXR1cm4gdGhpcy5hZi5maWx0ZXJzPy5maWx0ZXJzIHx8IFtdO1xuICB9XG5cbiAgcHVibGljIGdldCB2b2x1bWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWYudm9sdW1lO1xuICB9XG5cbiAgcHVibGljIGdldCByZXNhbXBsZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWYucmVzYW1wbGVyO1xuICB9XG5cbiAgcHVibGljIGR1bXAoKTogRmlsdGVyR3JhcGgge1xuICAgIHJldHVybiB7XG4gICAgICBmZm1wZWc6IHRoaXMuZmZtcGVnLFxuICAgICAgZXF1YWxpemVyOiB0aGlzLmVxdWFsaXplcixcbiAgICAgIGJpcXVhZDogdGhpcy5iaXF1YWQsXG4gICAgICBmaWx0ZXJzOiB0aGlzLmZpbHRlcnMsXG4gICAgICBzYW1wbGVSYXRlOiB0aGlzLnJlc2FtcGxlcj8uc2FtcGxlUmF0ZSB8fCA0ODAwMCxcbiAgICAgIHZvbHVtZTogdGhpcy52b2x1bWU/LnZvbHVtZSA/PyAxMDBcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsdGVyR3JhcGgge1xuICBmZm1wZWc6IEZpbHRlcnNbXTtcbiAgZXF1YWxpemVyOiBFcXVhbGl6ZXJCYW5kW107XG4gIGJpcXVhZDogRXhjbHVkZTxCaXF1YWRGaWx0ZXJzLCBudW1iZXI+IHwgbnVsbDtcbiAgZmlsdGVyczogUENNRmlsdGVyc1tdO1xuICB2b2x1bWU6IG51bWJlcjtcbiAgc2FtcGxlUmF0ZTogbnVtYmVyO1xufSIsICJpbXBvcnQgdHlwZSB7IER1cGxleCwgUmVhZGFibGUgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgRkZtcGVnLCBjcmVhdGVGRm1wZWdBcmdzIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL2ZmbXBlZyc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnaHR0cCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRkZtcGVnU3RyZWFtT3B0aW9ucyB7XG4gIGZtdD86IHN0cmluZztcbiAgZW5jb2RlckFyZ3M/OiBzdHJpbmdbXTtcbiAgc2Vlaz86IG51bWJlcjtcbiAgc2tpcD86IGJvb2xlYW47XG4gIGNvb2tpZXM/OiBzdHJpbmc7XG4gIHJlcXVlc3RPcHRpb25zPzogUmVxdWVzdE9wdGlvbnM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBGRk1QRUdfQVJHU19TVFJJTkcoXG5zdHJlYW06IHN0cmluZyxcbmZtdD86IHN0cmluZyxcbmNvb2tpZXM/OiBzdHJpbmcsXG5yZXF1ZXN0T3B0aW9ucz86IFJlcXVlc3RPcHRpb25zKVxue1xuICAvLyBCdWlsZCBhcnJheSBtYW51YWxseSB0byBoYW5kbGUgSFRUUCBvcHRpb25zIHByb3Blcmx5XG4gIGNvbnN0IGFyZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gQWRkIHJlY29ubmVjdGlvbiBvcHRpb25zXG4gIGFyZ3MucHVzaCgnLXJlY29ubmVjdCcsICcxJyk7XG4gIGFyZ3MucHVzaCgnLXJlY29ubmVjdF9zdHJlYW1lZCcsICcxJyk7XG4gIGFyZ3MucHVzaCgnLXJlY29ubmVjdF9kZWxheV9tYXgnLCAnNScpO1xuXG4gIC8vIEFkZCBIVFRQIGhlYWRlcnMgaWYgcHJvdmlkZWQgLSBGRm1wZWcgSFRUUCBwcm90b2NvbCBmb3JtYXQsIHRoYW5rIGdvZCBpdCBzdGFydGVkIHdvcmtpbmcuLi5cbiAgaWYgKHJlcXVlc3RPcHRpb25zPy5oZWFkZXJzKSB7XG4gICAgY29uc3QgdXNlckFnZW50ID1cbiAgICByZXF1ZXN0T3B0aW9ucy5oZWFkZXJzWyd1c2VyLWFnZW50J10gfHxcbiAgICByZXF1ZXN0T3B0aW9ucy5oZWFkZXJzWydVc2VyLUFnZW50J107XG4gICAgaWYgKHVzZXJBZ2VudCkge1xuICAgICAgYXJncy5wdXNoKCctdXNlcl9hZ2VudCcsIFN0cmluZyh1c2VyQWdlbnQpKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgb3RoZXIgaGVhZGVycyB1c2luZyBGRm1wZWcncyBoZWFkZXJzIG9wdGlvblxuICAgIGNvbnN0IGZvcm1hdHRlZEhlYWRlcnMgPSBmb3JtYXRGRm1wZWdIZWFkZXJzKFxuICAgICAgcmVxdWVzdE9wdGlvbnMuaGVhZGVycyBhcyBOb2RlSlMuRGljdDxzdHJpbmcgfCBzdHJpbmdbXT5cbiAgICApO1xuICAgIGlmIChmb3JtYXR0ZWRIZWFkZXJzKSB7XG4gICAgICBhcmdzLnB1c2goJy1oZWFkZXJzJywgZm9ybWF0dGVkSGVhZGVycyk7XG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIGNvb2tpZXMgaWYgcHJvdmlkZWRcbiAgaWYgKHR5cGVvZiBjb29raWVzID09PSAnc3RyaW5nJykge1xuICAgIGNvbnN0IGNvb2tpZVZhbHVlID0gIWNvb2tpZXMuaW5jbHVkZXMoJyAnKSA/IGNvb2tpZXMgOiBgXCIke2Nvb2tpZXN9XCJgO1xuICAgIGFyZ3MucHVzaCgnLWNvb2tpZXMnLCBjb29raWVWYWx1ZSk7XG4gIH1cblxuICAvLyBBZGQgaW5wdXQgVVJMXG4gIGFyZ3MucHVzaCgnLWknLCBzdHJlYW0pO1xuXG4gIC8vIEFkZCBhdWRpbyBwcm9jZXNzaW5nIG9wdGlvbnNcbiAgYXJncy5wdXNoKCctYW5hbHl6ZWR1cmF0aW9uJywgJzAnKTtcbiAgYXJncy5wdXNoKCctbG9nbGV2ZWwnLCAnMCcpO1xuICBhcmdzLnB1c2goJy1hcicsICc0ODAwMCcpO1xuICBhcmdzLnB1c2goJy1hYycsICcyJyk7XG4gIGFyZ3MucHVzaCgnLWYnLCB0eXBlb2YgZm10ID09PSAnc3RyaW5nJyA/IGZtdCA6ICdzMTZsZScpO1xuXG4gIGlmIChmbXQgPT09ICdvcHVzJykge1xuICAgIGFyZ3MucHVzaCgnLWFjb2RlYycsICdsaWJvcHVzJyk7XG4gIH1cbiAgcmV0dXJuIGFyZ3M7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdEZGbXBlZ0hlYWRlcnMoXG5oZWFkZXJzOiBOb2RlSlMuRGljdDxzdHJpbmcgfCBzdHJpbmdbXT4pXG46IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBoZWFkZXJQYWlyczogc3RyaW5nW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoaGVhZGVycykpIHtcbiAgICBpZiAodmFsdWUgJiYgbmFtZS50b0xvd2VyQ2FzZSgpICE9PSAndXNlci1hZ2VudCcpIHtcbiAgICAgIGNvbnN0IHZhbHVlU3RyID0gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZS5qb2luKCcsICcpIDogU3RyaW5nKHZhbHVlKTtcbiAgICAgIGhlYWRlclBhaXJzLnB1c2goYCR7bmFtZX06ICR7dmFsdWVTdHJ9YCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGhlYWRlclBhaXJzLmxlbmd0aCA+IDAgPyBoZWFkZXJQYWlycy5qb2luKCdcXHJcXG4nKSA6IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBGRk1QRUdfQVJHU19QSVBFRChmbXQ/OiBzdHJpbmcpIHtcbiAgY29uc3QgYXJncyA9IGNyZWF0ZUZGbXBlZ0FyZ3Moe1xuICAgIGFuYWx5emVkdXJhdGlvbjogMCxcbiAgICBsb2dsZXZlbDogMCxcbiAgICBhcjogNDgwMDAsXG4gICAgYWM6IDIsXG4gICAgZjogYCR7dHlwZW9mIGZtdCA9PT0gJ3N0cmluZycgPyBmbXQgOiAnczE2bGUnfWAsXG4gICAgYWNvZGVjOiBmbXQgPT09ICdvcHVzJyA/ICdsaWJvcHVzJyA6IG51bGxcbiAgfSk7XG5cbiAgcmV0dXJuIGFyZ3M7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBGRm1wZWcgc3RyZWFtXG4gKiBAcGFyYW0gc3RyZWFtIFRoZSBzb3VyY2Ugc3RyZWFtXG4gKiBAcGFyYW0gb3B0aW9ucyBGRm1wZWcgc3RyZWFtIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZGbXBlZ1N0cmVhbShcbnN0cmVhbTogUmVhZGFibGUgfCBEdXBsZXggfCBzdHJpbmcsXG5vcHRpb25zPzogRkZtcGVnU3RyZWFtT3B0aW9ucylcbjogUmVhZGFibGUge1xuICBpZiAob3B0aW9ucz8uc2tpcCAmJiB0eXBlb2Ygc3RyZWFtICE9PSAnc3RyaW5nJykgcmV0dXJuIHN0cmVhbTtcbiAgb3B0aW9ucyA/Pz0ge307XG4gIGNvbnN0IGFyZ3MgPVxuICB0eXBlb2Ygc3RyZWFtID09PSAnc3RyaW5nJyA/XG4gIEZGTVBFR19BUkdTX1NUUklORyhcbiAgICBzdHJlYW0sXG4gICAgb3B0aW9ucy5mbXQsXG4gICAgb3B0aW9ucy5jb29raWVzLFxuICAgIG9wdGlvbnMucmVxdWVzdE9wdGlvbnNcbiAgKSA6XG4gIEZGTVBFR19BUkdTX1BJUEVEKG9wdGlvbnMuZm10KTtcblxuICBpZiAoIU51bWJlci5pc05hTihvcHRpb25zLnNlZWspKSBhcmdzLnVuc2hpZnQoJy1zcycsIFN0cmluZyhvcHRpb25zLnNlZWspKTtcbiAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucy5lbmNvZGVyQXJncykpIGFyZ3MucHVzaCguLi5vcHRpb25zLmVuY29kZXJBcmdzKTtcblxuICBjb25zdCB0cmFuc2NvZGVyID0gbmV3IEZGbXBlZyh7IHNoZWxsOiBmYWxzZSwgYXJncyB9KTtcblxuICB0cmFuc2NvZGVyLm9uKCdjbG9zZScsICgpID0+IHRyYW5zY29kZXIuZGVzdHJveSgpKTtcblxuICBpZiAodHlwZW9mIHN0cmVhbSAhPT0gJ3N0cmluZycpIHtcbiAgICBzdHJlYW0ub24oJ2Vycm9yJywgKCkgPT4gdHJhbnNjb2Rlci5kZXN0cm95KCkpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgc3RyZWFtLnBpcGUodHJhbnNjb2RlciBhcyBhbnkpO1xuICB9XG5cbiAgcmV0dXJuIHRyYW5zY29kZXI7XG59IiwgImltcG9ydCB7IEd1aWxkUXVldWUgfSBmcm9tICcuL0d1aWxkUXVldWUnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEd1aWxkUXVldWVTdGF0aXN0aWNzTWV0YWRhdGEge1xuICBsYXRlbmN5OiB7XG4gICAgZXZlbnRMb29wOiBudW1iZXI7XG4gICAgdm9pY2VDb25uZWN0aW9uOiBudW1iZXI7XG4gIH07XG4gIHN0YXR1czoge1xuICAgIGJ1ZmZlcmluZzogYm9vbGVhbjtcbiAgICBwbGF5aW5nOiBib29sZWFuO1xuICAgIHBhdXNlZDogYm9vbGVhbjtcbiAgICBpZGxlOiBib29sZWFuO1xuICB9O1xuICB0cmFja3NDb3VudDogbnVtYmVyO1xuICBoaXN0b3J5U2l6ZTogbnVtYmVyO1xuICBleHRyYWN0b3JzOiBudW1iZXI7XG4gIGxpc3RlbmVyczogbnVtYmVyO1xuICBtZW1vcnlVc2FnZTogTm9kZUpTLk1lbW9yeVVzYWdlO1xuICB2ZXJzaW9uczoge1xuICAgIG5vZGU6IHN0cmluZztcbiAgICBwbGF5ZXI6IHN0cmluZztcbiAgfTtcbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmV4cG9ydCBjbGFzcyBHdWlsZFF1ZXVlU3RhdGlzdGljczxNZXRhID0gYW55PiB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgcXVldWU6IEd1aWxkUXVldWU8TWV0YT4pIHt9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIHN0YXRpc3RpY3Mgb2YgdGhpcyBxdWV1ZVxuICAgKi9cbiAgcHVibGljIGdlbmVyYXRlKCkge1xuICAgIHJldHVybiB7XG4gICAgICBsYXRlbmN5OiB7XG4gICAgICAgIGV2ZW50TG9vcDogdGhpcy5xdWV1ZS5wbGF5ZXIuZXZlbnRMb29wTGFnLFxuICAgICAgICB2b2ljZUNvbm5lY3Rpb246IHRoaXMucXVldWUucGluZ1xuICAgICAgfSxcbiAgICAgIHN0YXR1czoge1xuICAgICAgICBidWZmZXJpbmc6IHRoaXMucXVldWUubm9kZS5pc0J1ZmZlcmluZygpLFxuICAgICAgICBwbGF5aW5nOiB0aGlzLnF1ZXVlLm5vZGUuaXNQbGF5aW5nKCksXG4gICAgICAgIHBhdXNlZDogdGhpcy5xdWV1ZS5ub2RlLmlzUGF1c2VkKCksXG4gICAgICAgIGlkbGU6IHRoaXMucXVldWUubm9kZS5pc0lkbGUoKVxuICAgICAgfSxcbiAgICAgIHRyYWNrc0NvdW50OiB0aGlzLnF1ZXVlLnRyYWNrcy5zaXplLFxuICAgICAgaGlzdG9yeVNpemU6IHRoaXMucXVldWUuaGlzdG9yeS50cmFja3Muc2l6ZSxcbiAgICAgIGV4dHJhY3RvcnM6IHRoaXMucXVldWUucGxheWVyLmV4dHJhY3RvcnMuc2l6ZSxcbiAgICAgIGxpc3RlbmVyczpcbiAgICAgIHRoaXMucXVldWUuZ3VpbGQubWVtYmVycy5tZT8udm9pY2UuY2hhbm5lbD8ubWVtYmVycy5maWx0ZXIoXG4gICAgICAgIChtKSA9PiAhbS51c2VyLmJvdFxuICAgICAgKS5zaXplIHx8IDAsXG4gICAgICBtZW1vcnlVc2FnZTogcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLFxuICAgICAgdmVyc2lvbnM6IHtcbiAgICAgICAgbm9kZTogcHJvY2Vzcy52ZXJzaW9uLFxuICAgICAgICBwbGF5ZXI6IHRoaXMucXVldWUucGxheWVyLnZlcnNpb25cbiAgICAgIH1cbiAgICB9IGFzIEd1aWxkUXVldWVTdGF0aXN0aWNzTWV0YWRhdGE7XG4gIH1cbn0iLCAiaW1wb3J0IHsgTm90RXhpc3RpbmdFcnJvciB9IGZyb20gJy4uL2Vycm9ycyc7XG5pbXBvcnQgeyBMcmNHZXRSZXN1bHQsIExyY1NlYXJjaFJlc3VsdCB9IGZyb20gJy4uL2xyY2xpYi9McmNMaWInO1xuaW1wb3J0IHR5cGUgeyBHdWlsZFF1ZXVlIH0gZnJvbSAnLi9HdWlsZFF1ZXVlJztcblxuZXhwb3J0IHR5cGUgTHlyaWNzRGF0YSA9IE1hcDxudW1iZXIsIHN0cmluZz47XG5leHBvcnQgdHlwZSBVbnN1YnNjcmliZSA9ICgpID0+IHZvaWQ7XG5leHBvcnQgdHlwZSBMeXJpY3NDYWxsYmFjayA9IChseXJpY3M6IHN0cmluZywgdGltZXN0YW1wOiBudW1iZXIpID0+IHVua25vd247XG5leHBvcnQgdHlwZSBMeXJpY3NBdCA9IHt0aW1lc3RhbXA6IG51bWJlcjtsaW5lOiBzdHJpbmc7fTtcblxuY29uc3QgdGltZXN0YW1wUGF0dGVybiA9IC9cXFsoXFxkezJ9KTooXFxkezJ9KVxcLihcXGR7Mn0pXFxdLztcblxuZXhwb3J0IGNsYXNzIFN5bmNlZEx5cmljc1Byb3ZpZGVyIHtcbiAgI2xvb3A6IE5vZGVKUy5UaW1lb3V0IHwgbnVsbCA9IG51bGw7XG4gICNjYWxsYmFjazogTHlyaWNzQ2FsbGJhY2sgfCBudWxsID0gbnVsbDtcbiAgI29uVW5zdWJzY3JpYmU6IFVuc3Vic2NyaWJlIHwgbnVsbCA9IG51bGw7XG5cbiAgcHVibGljIGludGVydmFsID0gMTAwO1xuICBwdWJsaWMgcmVhZG9ubHkgbHlyaWNzOiBMeXJpY3NEYXRhID0gbmV3IE1hcCgpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgcHVibGljIHJlYWRvbmx5IHF1ZXVlOiBHdWlsZFF1ZXVlLFxuICBwdWJsaWMgcmVhZG9ubHkgcmF3PzogTHJjR2V0UmVzdWx0IHwgTHJjU2VhcmNoUmVzdWx0KVxuICB7XG4gICAgaWYgKHJhdz8uc3luY2VkTHlyaWNzKSB0aGlzLmxvYWQocmF3Py5zeW5jZWRMeXJpY3MpO1xuICB9XG5cbiAgcHVibGljIGlzU3Vic2NyaWJlZCgpIHtcbiAgICByZXR1cm4gdGhpcy4jY2FsbGJhY2sgIT09IG51bGw7XG4gIH1cblxuICBwdWJsaWMgbG9hZChseXJpY3M6IHN0cmluZykge1xuICAgIGlmICghbHlyaWNzKSB0aHJvdyBuZXcgTm90RXhpc3RpbmdFcnJvcignc3luY2VkTHlyaWNzJyk7XG5cbiAgICB0aGlzLmx5cmljcy5jbGVhcigpO1xuICAgIHRoaXMudW5zdWJzY3JpYmUoKTtcblxuICAgIGNvbnN0IGxpbmVzID0gbHlyaWNzLnNwbGl0KCdcXG4nKTtcblxuICAgIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgICAgY29uc3QgbWF0Y2ggPSBsaW5lLm1hdGNoKHRpbWVzdGFtcFBhdHRlcm4pO1xuXG4gICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgY29uc3QgWywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzXSA9IG1hdGNoO1xuICAgICAgICBjb25zdCB0aW1lc3RhbXAgPVxuICAgICAgICBwYXJzZUludChtaW51dGVzKSAqIDYwICogMTAwMCArXG4gICAgICAgIHBhcnNlSW50KHNlY29uZHMpICogMTAwMCArXG4gICAgICAgIHBhcnNlSW50KG1pbGxpc2Vjb25kcyk7XG5cbiAgICAgICAgdGhpcy5seXJpY3Muc2V0KHRpbWVzdGFtcCwgbGluZS5yZXBsYWNlKHRpbWVzdGFtcFBhdHRlcm4sICcnKS50cmltKCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBseXJpY3MgYXQgYSBzcGVjaWZpYyB0aW1lIG9yIGF0IHRoZSBjbG9zZXN0IHRpbWUgKFx1MDBCMTIgc2Vjb25kcylcbiAgICogQHBhcmFtIHRpbWUgVGhlIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAqL1xuICBwdWJsaWMgYXQodGltZTogbnVtYmVyKTogTHlyaWNzQXQgfCBudWxsIHtcbiAgICBjb25zdCBsb3dlc3RUaW1lID0gdGhpcy5seXJpY3Mua2V5cygpLm5leHQoKS52YWx1ZTtcbiAgICBpZiAobG93ZXN0VGltZSA9PSBudWxsIHx8IHRpbWUgPCBsb3dlc3RUaW1lKSByZXR1cm4gbnVsbDtcbiAgICBpZiAodGhpcy5seXJpY3MuaGFzKHRpbWUpKVxuICAgIHJldHVybiB7IGxpbmU6IHRoaXMubHlyaWNzLmdldCh0aW1lKSBhcyBzdHJpbmcsIHRpbWVzdGFtcDogdGltZSB9O1xuXG4gICAgY29uc3Qga2V5cyA9IEFycmF5LmZyb20odGhpcy5seXJpY3Mua2V5cygpKTtcblxuICAgIGNvbnN0IGNsb3Nlc3QgPSBrZXlzLnJlZHVjZSgoYSwgYikgPT5cbiAgICBNYXRoLmFicyhiIC0gdGltZSkgPCBNYXRoLmFicyhhIC0gdGltZSkgPyBiIDogYVxuICAgICk7XG5cbiAgICBpZiAoY2xvc2VzdCA+IHRpbWUpIHJldHVybiBudWxsO1xuXG4gICAgaWYgKE1hdGguYWJzKGNsb3Nlc3QgLSB0aW1lKSA+IDIwMDApIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgbGluZSA9IHRoaXMubHlyaWNzLmdldChjbG9zZXN0KTtcblxuICAgIGlmICghbGluZSkgcmV0dXJuIG51bGw7XG5cbiAgICByZXR1cm4geyB0aW1lc3RhbXA6IGNsb3Nlc3QsIGxpbmUgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBmb3IgdGhlIGx5cmljcyBjaGFuZ2UuXG4gICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICovXG4gIHB1YmxpYyBvbkNoYW5nZShjYWxsYmFjazogTHlyaWNzQ2FsbGJhY2spIHtcbiAgICB0aGlzLiNjYWxsYmFjayA9IGNhbGxiYWNrO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIHRvIGRldGVjdCB3aGVuIHRoZSBwcm92aWRlciBpcyB1bnN1YnNjcmliZWQuXG4gICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgY2FsbGJhY2sgZnVuY3Rpb25cbiAgICovXG4gIHB1YmxpYyBvblVuc3Vic2NyaWJlKGNhbGxiYWNrOiBVbnN1YnNjcmliZSkge1xuICAgIHRoaXMuI29uVW5zdWJzY3JpYmUgPSBjYWxsYmFjaztcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnN1YnNjcmliZXMgZnJvbSB0aGUgcXVldWUuXG4gICAqL1xuICBwdWJsaWMgdW5zdWJzY3JpYmUoKSB7XG4gICAgaWYgKHRoaXMuI2xvb3ApIGNsZWFySW50ZXJ2YWwodGhpcy4jbG9vcCk7XG4gICAgaWYgKHRoaXMuI29uVW5zdWJzY3JpYmUpIHRoaXMuI29uVW5zdWJzY3JpYmUoKTtcblxuICAgIHRoaXMuI2NhbGxiYWNrID0gbnVsbDtcbiAgICB0aGlzLiNvblVuc3Vic2NyaWJlID0gbnVsbDtcbiAgICB0aGlzLiNsb29wID0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJzY3JpYmVzIHRvIHRoZSBxdWV1ZSB0byBtb25pdG9yIHRoZSBjdXJyZW50IHRpbWUuXG4gICAqIEByZXR1cm5zIFRoZSB1bnN1YnNjcmliZSBmdW5jdGlvblxuICAgKi9cbiAgcHVibGljIHN1YnNjcmliZSgpOiBVbnN1YnNjcmliZSB7XG4gICAgaWYgKHRoaXMuI2xvb3ApIHJldHVybiAoKSA9PiB0aGlzLnVuc3Vic2NyaWJlKCk7XG5cbiAgICB0aGlzLiNjcmVhdGVMb29wKCk7XG5cbiAgICByZXR1cm4gKCkgPT4gdGhpcy51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhdXNlcyB0aGUgbHlyaWNzIHByb3ZpZGVyLlxuICAgKi9cbiAgcHVibGljIHBhdXNlKCkge1xuICAgIGNvbnN0IGhhc0xvb3AgPSB0aGlzLiNsb29wICE9PSBudWxsO1xuXG4gICAgaWYgKGhhc0xvb3ApIHtcbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy4jbG9vcCEpO1xuICAgICAgdGhpcy4jbG9vcCA9IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhhc0xvb3A7XG4gIH1cblxuICAvKipcbiAgICogUmVzdW1lcyB0aGUgbHlyaWNzIHByb3ZpZGVyLlxuICAgKi9cbiAgcHVibGljIHJlc3VtZSgpIHtcbiAgICBjb25zdCBoYXNMb29wID0gdGhpcy4jbG9vcCAhPT0gbnVsbDtcblxuICAgIGlmICghaGFzTG9vcCkgdGhpcy4jY3JlYXRlTG9vcCgpO1xuXG4gICAgcmV0dXJuICFoYXNMb29wO1xuICB9XG5cbiAgI2NyZWF0ZUxvb3AoKSB7XG4gICAgaWYgKCF0aGlzLiNjYWxsYmFjaykgcmV0dXJuO1xuICAgIGlmICh0aGlzLiNsb29wKSBjbGVhckludGVydmFsKHRoaXMuI2xvb3ApO1xuXG4gICAgbGV0IGxhc3RWYWx1ZTogTHlyaWNzQXQgfCBudWxsID0gbnVsbDtcblxuICAgIHRoaXMuI2xvb3AgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5xdWV1ZS5kZWxldGVkKSByZXR1cm4gdGhpcy51bnN1YnNjcmliZSgpO1xuXG4gICAgICBpZiAoIXRoaXMuI2NhbGxiYWNrIHx8ICF0aGlzLnF1ZXVlLmlzUGxheWluZygpKSByZXR1cm47XG5cbiAgICAgIGNvbnN0IHRpbWUgPSB0aGlzLnF1ZXVlLm5vZGUuZ2V0VGltZXN0YW1wKCk7XG4gICAgICBpZiAoIXRpbWUpIHJldHVybjtcblxuICAgICAgY29uc3QgbHlyaWNzID0gdGhpcy5hdCh0aW1lLmN1cnJlbnQudmFsdWUpO1xuXG4gICAgICBpZiAoIWx5cmljcykgcmV0dXJuO1xuXG4gICAgICBpZiAoXG4gICAgICBsYXN0VmFsdWUgIT09IG51bGwgJiZcbiAgICAgIGx5cmljcy5saW5lID09PSBsYXN0VmFsdWUubGluZSAmJlxuICAgICAgbHlyaWNzLnRpbWVzdGFtcCA9PT0gbGFzdFZhbHVlLnRpbWVzdGFtcClcblxuICAgICAgcmV0dXJuO1xuXG4gICAgICBsYXN0VmFsdWUgPSBseXJpY3M7XG5cbiAgICAgIHRoaXMuI2NhbGxiYWNrKGx5cmljcy5saW5lLCBseXJpY3MudGltZXN0YW1wKTtcbiAgICB9LCB0aGlzLmludGVydmFsKS51bnJlZigpO1xuICB9XG59IiwgImltcG9ydCB7IHNldFRpbWVvdXQgfSBmcm9tICd0aW1lcnMvcHJvbWlzZXMnO1xuaW1wb3J0IHsgQXN5bmNRdWV1ZSB9IGZyb20gJy4vQXN5bmNRdWV1ZSc7XG5cbmV4cG9ydCB0eXBlIFJlcXVlc3RFbnRpdHkgPSAoKSA9PiBQcm9taXNlPFJlc3BvbnNlPjtcblxuZXhwb3J0IGNsYXNzIFNlcXVlbnRpYWxCdWNrZXQge1xuICBwdWJsaWMgbGltaXQgPSAxO1xuICBwdWJsaWMgcmVtYWluaW5nID0gMTtcbiAgcHVibGljIHJlc2V0QWZ0ZXIgPSAwO1xuICBwdWJsaWMgcXVldWUgPSBuZXcgQXN5bmNRdWV1ZSgpO1xuICBwdWJsaWMgTUFYX1JFVFJJRVMgPSA1O1xuXG4gIC8qKlxuICAgKiBDaGVja3MgaWYgdGhlIGJ1Y2tldCBpcyByYXRlIGxpbWl0ZWQuXG4gICAqL1xuICBwdWJsaWMgaXNSYXRlTGltaXRlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5yZW1haW5pbmcgPD0gMCAmJiBEYXRlLm5vdygpIDwgdGhpcy5yZXNldEFmdGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIEVucXVldWVzIGEgcmVxdWVzdC5cbiAgICogQHBhcmFtIHJlcSBUaGUgcmVxdWVzdCBmdW5jdGlvbiB0byBlbnF1ZXVlXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZW5xdWV1ZShyZXE6IFJlcXVlc3RFbnRpdHkpIHtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMucXVldWUuYWNxdWlyZSgpO1xuICAgIGF3YWl0IGVudHJ5LmdldFRhc2soKTtcblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVxdWVzdChyZXEpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBlbnRyeS5yZWxlYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfcmVxdWVzdChyZXE6IFJlcXVlc3RFbnRpdHksIHJldHJpZXMgPSAwKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICAgIHdoaWxlICh0aGlzLmlzUmF0ZUxpbWl0ZWQoKSkge1xuICAgICAgY29uc3QgcmVzZXQgPSB0aGlzLnJlc2V0QWZ0ZXIgLSBEYXRlLm5vdygpO1xuICAgICAgYXdhaXQgc2V0VGltZW91dChyZXNldCk7XG4gICAgfVxuXG4gICAgbGV0IHBhc3MgPSBmYWxzZTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXMgPSBhd2FpdCByZXEoKTtcblxuICAgICAgdGhpcy5fcGF0Y2hIZWFkZXJzKHJlcyk7XG5cbiAgICAgIGlmIChyZXMuc3RhdHVzID09PSA0MjkpIHtcbiAgICAgICAgY29uc3QgcmVzZXQgPSB0aGlzLnJlc2V0QWZ0ZXIgLSBEYXRlLm5vdygpO1xuICAgICAgICBhd2FpdCBzZXRUaW1lb3V0KHJlc2V0KTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlcXVlc3QocmVxKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFyZXMub2spIHtcbiAgICAgICAgbGV0IGVycjogRXJyb3I7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBib2R5OiB7XG4gICAgICAgICAgICBjb2RlOiBudW1iZXI7XG4gICAgICAgICAgICBuYW1lOiBzdHJpbmc7XG4gICAgICAgICAgICBtZXNzYWdlOiBzdHJpbmc7XG4gICAgICAgICAgfSA9IGF3YWl0IHJlcy5qc29uKCk7XG5cbiAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihib2R5Lm1lc3NhZ2UpIGFzIEVycm9yICYge2NvZGU6IG51bWJlcjt9O1xuXG4gICAgICAgICAgZXJyb3IubmFtZSA9IGJvZHkubmFtZTtcbiAgICAgICAgICBlcnJvci5jb2RlID0gYm9keS5jb2RlO1xuXG4gICAgICAgICAgZXJyID0gZXJyb3I7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIGVyciA9IG5ldyBFcnJvcihgSFRUUCBFcnJvcjogJHtyZXMuc3RhdHVzfSAke3Jlcy5zdGF0dXNUZXh0fWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcGFzcyA9IHRydWU7XG5cbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChwYXNzKSB0aHJvdyBlO1xuXG4gICAgICBjb25zdCBiYWRSZXEgPSBlIGluc3RhbmNlb2YgRXJyb3IgJiYgL0Vycm9yOiA0WzAtOV17Mn0vLnRlc3QoZS5tZXNzYWdlKTtcblxuICAgICAgaWYgKCFiYWRSZXEgJiYgcmV0cmllcyA8IHRoaXMuTUFYX1JFVFJJRVMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlcXVlc3QocmVxLCArK3JldHJpZXMpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3BhdGNoSGVhZGVycyhyZXM6IFJlc3BvbnNlKSB7XG4gICAgY29uc3QgbGltaXQgPSBOdW1iZXIocmVzLmhlYWRlcnMuZ2V0KCdYLVJhdGVMaW1pdC1MaW1pdCcpKTtcbiAgICBjb25zdCByZW1haW5pbmcgPSBOdW1iZXIocmVzLmhlYWRlcnMuZ2V0KCdYLVJhdGVMaW1pdC1SZW1haW5pbmcnKSk7XG4gICAgY29uc3QgcmVzZXRBZnRlciA9XG4gICAgTnVtYmVyKHJlcy5oZWFkZXJzLmdldCgnWC1SYXRlTGltaXQtUmVzZXQnKSkgKiAxMDAwICsgRGF0ZS5ub3coKTtcblxuICAgIGlmICghTnVtYmVyLmlzTmFOKGxpbWl0KSkgdGhpcy5saW1pdCA9IGxpbWl0O1xuICAgIGlmICghTnVtYmVyLmlzTmFOKHJlbWFpbmluZykpIHRoaXMucmVtYWluaW5nID0gcmVtYWluaW5nO1xuICAgIGlmICghTnVtYmVyLmlzTmFOKHJlc2V0QWZ0ZXIpKSB0aGlzLnJlc2V0QWZ0ZXIgPSByZXNldEFmdGVyO1xuICB9XG59IiwgImltcG9ydCB7IEludmFsaWRBcmdUeXBlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuaW1wb3J0IHR5cGUgeyBQbGF5ZXIgfSBmcm9tICcuLi9QbGF5ZXInO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uL3V0aWxzL1V0aWwnO1xuaW1wb3J0IHsgU2VxdWVudGlhbEJ1Y2tldCB9IGZyb20gJy4uL3V0aWxzL1NlcXVlbnRpYWxCdWNrZXQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIExyY1NlYXJjaFBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgcXVlcnkgdG8gc2VhcmNoIGZvci4gRWl0aGVyIHRoaXMgb3IgdHJhY2tOYW1lIGlzIHJlcXVpcmVkLlxuICAgKi9cbiAgcT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSB0cmFjayBuYW1lIHRvIHNlYXJjaCBmb3IuIEVpdGhlciB0aGlzIG9yIHF1ZXJ5IGlzIHJlcXVpcmVkLlxuICAgKi9cbiAgdHJhY2tOYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGFydGlzdCBuYW1lXG4gICAqL1xuICBhcnRpc3ROYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGFsYnVtIG5hbWVcbiAgICovXG4gIGFsYnVtTmFtZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMcmNHZXRQYXJhbXMgZXh0ZW5kcyBSZXF1aXJlZDxPbWl0PExyY1NlYXJjaFBhcmFtcywgJ3F1ZXJ5Jz4+IHtcbiAgLyoqXG4gICAqIFRoZSBkdXJhdGlvbiBvZiB0aGUgdHJhY2tcbiAgICovXG4gIGR1cmF0aW9uOiBudW1iZXI7XG59XG5cbmNvbnN0IHRvU25ha2VDYXNlID0gKG9iajogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPT4ge1xuICBjb25zdCBzbmFrZU9iajogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgY29udGludWU7XG4gICAgY29uc3QgbmV3S2V5ID0ga2V5LnJlcGxhY2UoXG4gICAgICAvW0EtWl0vZyxcbiAgICAgIChsZXR0ZXIpID0+IGBfJHtsZXR0ZXIudG9Mb3dlckNhc2UoKX1gXG4gICAgKTtcbiAgICBzbmFrZU9ialtuZXdLZXldID0gdmFsdWU7XG4gIH1cblxuICByZXR1cm4gc25ha2VPYmo7XG59O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuY29uc3QgY3JlYXRlUXVlcnkgPSAocGFyYW1zOiBhbnkpID0+XG5uZXcgVVJMU2VhcmNoUGFyYW1zKHRvU25ha2VDYXNlKHBhcmFtcykpLnRvU3RyaW5nKCk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTHJjU2VhcmNoUmVzdWx0IHtcbiAgLyoqXG4gICAqIFRoZSB0cmFjayBpZFxuICAgKi9cbiAgaWQ6IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB0cmFjayBuYW1lXG4gICAqL1xuICBuYW1lOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgYXJ0aXN0IG5hbWVcbiAgICovXG4gIHRyYWNrTmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGFsYnVtIG5hbWVcbiAgICovXG4gIGFydGlzdE5hbWU6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBhbGJ1bSBuYW1lXG4gICAqL1xuICBhbGJ1bU5hbWU6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBkdXJhdGlvbiBvZiB0aGUgdHJhY2tcbiAgICovXG4gIGR1cmF0aW9uOiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgcmVsZWFzZSBkYXRlIG9mIHRoZSB0cmFja1xuICAgKi9cbiAgaW5zdHJ1bWVudGFsOiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIHJlbGVhc2UgZGF0ZSBvZiB0aGUgdHJhY2tcbiAgICovXG4gIHBsYWluTHlyaWNzOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcmVsZWFzZSBkYXRlIG9mIHRoZSB0cmFja1xuICAgKi9cbiAgc3luY2VkTHlyaWNzPzogc3RyaW5nO1xufVxuXG5leHBvcnQgdHlwZSBMcmNHZXRSZXN1bHQgPSBPbWl0PExyY1NlYXJjaFJlc3VsdCwgJ25hbWUnPjtcblxuZXhwb3J0IGNsYXNzIExyY0xpYiB7XG4gIC8qKlxuICAgKiBUaGUgQVBJIFVSTFxuICAgKi9cbiAgcHVibGljIGFwaSA9ICdodHRwczovL2xyY2xpYi5uZXQvYXBpJztcbiAgLyoqXG4gICAqIFRoZSByZXF1ZXN0IHRpbWVvdXQuIERlZmF1bHQgaXMgMTUgc2Vjb25kcy5cbiAgICovXG4gIHB1YmxpYyB0aW1lb3V0ID0gMTVfMDAwO1xuICAvKipcbiAgICogVGhlIHJlcXVlc3QgYnVja2V0XG4gICAqL1xuICBwdWJsaWMgYnVja2V0ID0gbmV3IFNlcXVlbnRpYWxCdWNrZXQoKTtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBMcmNMaWIgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtQbGF5ZXJ9IHBsYXllciBUaGUgcGxheWVyIGluc3RhbmNlXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHBsYXllcjogUGxheWVyKSB7fVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSByZXF1ZXN0IHRpbWVvdXRcbiAgICogQHBhcmFtIHtudW1iZXJ9IHRpbWVvdXQgVGhlIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzXG4gICAqL1xuICBwdWJsaWMgc2V0UmVxdWVzdFRpbWVvdXQodGltZW91dDogbnVtYmVyKSB7XG4gICAgdGhpcy50aW1lb3V0ID0gdGltZW91dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSByZXRyeSBsaW1pdC4gRGVmYXVsdCBpcyA1LlxuICAgKiBAcGFyYW0ge251bWJlcn0gbGltaXQgVGhlIHJldHJ5IGxpbWl0XG4gICAqL1xuICBwdWJsaWMgc2V0UmV0cnlMaW1pdChsaW1pdDogbnVtYmVyKSB7XG4gICAgdGhpcy5idWNrZXQuTUFYX1JFVFJJRVMgPSBsaW1pdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGx5cmljc1xuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSBnZXQgcGFyYW1zXG4gICAqL1xuICBwdWJsaWMgZ2V0KHBhcmFtczogTHJjR2V0UGFyYW1zKSB7XG4gICAgY29uc3QgcGF0aCA9IGBnZXQ/JHtjcmVhdGVRdWVyeShwYXJhbXMpfWA7XG5cbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PExyY1NlYXJjaFJlc3VsdD4ocGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBseXJpY3MgYnkgSURcbiAgICogQHBhcmFtIGlkIFRoZSBseXJpY3MgSURcbiAgICovXG4gIHB1YmxpYyBnZXRCeUlkKGlkOiBgJHtudW1iZXJ9YCB8IG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8THJjU2VhcmNoUmVzdWx0PihgZ2V0LyR7aWR9YCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBjYWNoZWQgbHlyaWNzXG4gICAqIEBwYXJhbSBwYXJhbXMgVGhlIGdldCBwYXJhbXNcbiAgICovXG4gIHB1YmxpYyBnZXRDYWNoZWQocGFyYW1zOiBMcmNHZXRQYXJhbXMpIHtcbiAgICBjb25zdCBwYXRoID0gYGdldC1jYWNoZWQ/JHtjcmVhdGVRdWVyeShwYXJhbXMpfWA7XG5cbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PExyY1NlYXJjaFJlc3VsdD4ocGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogU2VhcmNoZXMgZm9yIGx5cmljc1xuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSBzZWFyY2ggcGFyYW1zXG4gICAqL1xuICBwdWJsaWMgc2VhcmNoKHBhcmFtczogTHJjU2VhcmNoUGFyYW1zKSB7XG4gICAgaWYgKCFwYXJhbXMucSAmJiAhcGFyYW1zLnRyYWNrTmFtZSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmdUeXBlRXJyb3IoXG4gICAgICAgICdvbmUgb2YgcSBvciB0cmFja05hbWUnLFxuICAgICAgICAnc3RyaW5nJyxcbiAgICAgICAgW1N0cmluZyhwYXJhbXMucSksIFN0cmluZyhwYXJhbXMudHJhY2tOYW1lKV0uam9pbignLCAnKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXRoID0gYHNlYXJjaD8ke2NyZWF0ZVF1ZXJ5KHBhcmFtcyl9YDtcblxuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8THJjU2VhcmNoUmVzdWx0W10+KHBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3RzIHRoZSBBUElcbiAgICogQHBhcmFtIHBhdGggVGhlIHBhdGhcbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIHJlcXVlc3Qgb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGFzeW5jIHJlcXVlc3Q8VD4ocGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVxdWVzdEluaXQpOiBQcm9taXNlPFQ+IHtcbiAgICBjb25zdCBkaXNwYXRjaGVyID0gKCkgPT4ge1xuICAgICAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBVdGlsLmdldFJ1bnRpbWUoKTtcblxuICAgICAgY29uc3QgcnVudGltZVZlcnNpb24gPVxuICAgICAgbmFtZSA9PT0gJ3Vua25vd24nID8gdmVyc2lvbiA6IGAke25hbWV9LyR7dmVyc2lvbn1gO1xuXG4gICAgICBjb25zdCBpbml0OiBSZXF1ZXN0SW5pdCA9IHtcbiAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgcmVkaXJlY3Q6ICdmb2xsb3cnLFxuICAgICAgICBzaWduYWw6IEFib3J0U2lnbmFsLnRpbWVvdXQodGhpcy50aW1lb3V0KSxcbiAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdVc2VyLUFnZW50JzogYERpc2NvcmQtUGxheWVyLyR7dGhpcy5wbGF5ZXIudmVyc2lvbn0gJHtcbiAgICAgICAgICBydW50aW1lVmVyc2lvbiA/PyAnJ31gLlxuICAgICAgICAgIHRyaW1FbmQoKSxcbiAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgIC4uLm9wdGlvbnM/LmhlYWRlcnNcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgdGhpcy5wbGF5ZXIuZGVidWcoYFtMcmNMaWJdIFJlcXVlc3RpbmcgJHtwYXRofWApO1xuXG4gICAgICByZXR1cm4gZmV0Y2goXG4gICAgICAgIGAke3RoaXMuYXBpfSR7cGF0aC5zdGFydHNXaXRoKCcvJykgPyBwYXRoIDogJy8nICsgcGF0aH1gLFxuICAgICAgICBpbml0XG4gICAgICApO1xuICAgIH07XG5cbiAgICBjb25zdCByZXMgPSBhd2FpdCB0aGlzLmJ1Y2tldC5lbnF1ZXVlKGRpc3BhdGNoZXIpO1xuXG4gICAgcmV0dXJuIHJlcy5qc29uKCk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgVm9pY2VDaGFubmVsLCBTdGFnZUNoYW5uZWwsIFNub3dmbGFrZSB9IGZyb20gJ2Rpc2NvcmQuanMnO1xuaW1wb3J0IHtcbiAgRGlzY29yZEdhdGV3YXlBZGFwdGVyQ3JlYXRvcixcbiAgam9pblZvaWNlQ2hhbm5lbCxcbiAgVm9pY2VDb25uZWN0aW9uLFxuICBnZXRWb2ljZUNvbm5lY3Rpb24sXG4gIFZvaWNlQ29ubmVjdGlvblN0YXR1cyxcbiAgQXVkaW9QbGF5ZXIgfSBmcm9tXG4nZGlzY29yZC12b2lwJztcbmltcG9ydCB7IFN0cmVhbURpc3BhdGNoZXIgfSBmcm9tICcuL1N0cmVhbURpc3BhdGNoZXInO1xuaW1wb3J0IHsgQ29sbGVjdGlvbiB9IGZyb20gJ0BkaXNjb3JkLXBsYXllci91dGlscyc7XG5pbXBvcnQgeyBHdWlsZFF1ZXVlIH0gZnJvbSAnLi4vcXVldWUnO1xuaW1wb3J0IHR5cGUgeyBQbGF5ZXIgfSBmcm9tICcuLi9QbGF5ZXInO1xuaW1wb3J0IHsgTm9HdWlsZFF1ZXVlRXJyb3IgfSBmcm9tICcuLi9lcnJvcnMnO1xuXG5jbGFzcyBWb2ljZVV0aWxzIHtcbiAgLyoqXG4gICAqIFZvaWNlIGNvbm5lY3Rpb24gY2FjaGUgdG8gc3RvcmUgdm9pY2UgY29ubmVjdGlvbnMgb2YgdGhlIFBsYXllciBjb21wb25lbnRzLlxuICAgKiBUaGlzIHByb3BlcnR5IGlzIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgZnV0dXJlLlxuICAgKiBJdCBvbmx5IGV4aXN0cyBmb3IgY29tcGF0aWJpbGl0eSByZWFzb25zLlxuICAgKiBAZGVwcmVjYXRlZFxuICAgKi9cbiAgcHVibGljIGNhY2hlOiBDb2xsZWN0aW9uPFNub3dmbGFrZSwgU3RyZWFtRGlzcGF0Y2hlcj4gPSBuZXcgQ29sbGVjdGlvbjxcbiAgICBTbm93Zmxha2UsXG4gICAgU3RyZWFtRGlzcGF0Y2hlcj4oXG4gICk7XG5cbiAgLyoqXG4gICAqIFRoZSB2b2ljZSB1dGlscyBjb25zdHJ1Y3RvclxuICAgKi9cbiAgY29uc3RydWN0b3IocHVibGljIHBsYXllcjogUGxheWVyKSB7fVxuXG4gIC8qKlxuICAgKiBKb2lucyBhIHZvaWNlIGNoYW5uZWwsIGNyZWF0aW5nIGJhc2ljIHN0cmVhbSBkaXNwYXRjaCBtYW5hZ2VyXG4gICAqIEBwYXJhbSB7U3RhZ2VDaGFubmVsfFZvaWNlQ2hhbm5lbH0gY2hhbm5lbCBUaGUgdm9pY2UgY2hhbm5lbFxuICAgKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdIEpvaW4gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTdHJlYW1EaXNwYXRjaGVyPn1cbiAgICovXG4gIHB1YmxpYyBhc3luYyBjb25uZWN0KFxuICBjaGFubmVsOiBWb2ljZUNoYW5uZWwgfCBTdGFnZUNoYW5uZWwsXG4gIG9wdGlvbnM/OiB7XG4gICAgZGVhZj86IGJvb2xlYW47XG4gICAgbWF4VGltZT86IG51bWJlcjtcbiAgICBxdWV1ZTogR3VpbGRRdWV1ZTtcbiAgICBhdWRpb1BsYXllcj86IEF1ZGlvUGxheWVyO1xuICAgIGdyb3VwPzogc3RyaW5nO1xuICAgIGRhdmVFbmNyeXB0aW9uPzogYm9vbGVhbjtcbiAgICBkZWNyeXB0aW9uRmFpbHVyZVRvbGVyYW5jZT86IG51bWJlcjtcbiAgfSlcbiAgOiBQcm9taXNlPFN0cmVhbURpc3BhdGNoZXI+IHtcbiAgICBpZiAoIW9wdGlvbnM/LnF1ZXVlKSB0aHJvdyBuZXcgTm9HdWlsZFF1ZXVlRXJyb3IoKTtcbiAgICBjb25zdCBjb25uID0gYXdhaXQgdGhpcy5qb2luKGNoYW5uZWwsIG9wdGlvbnMpO1xuICAgIGNvbnN0IHN1YiA9IG5ldyBTdHJlYW1EaXNwYXRjaGVyKFxuICAgICAgY29ubixcbiAgICAgIGNoYW5uZWwsXG4gICAgICBvcHRpb25zLnF1ZXVlLFxuICAgICAgb3B0aW9ucy5tYXhUaW1lLFxuICAgICAgb3B0aW9ucy5hdWRpb1BsYXllclxuICAgICk7XG4gICAgcmV0dXJuIHN1YjtcbiAgfVxuXG4gIC8qKlxuICAgKiBKb2lucyBhIHZvaWNlIGNoYW5uZWxcbiAgICogQHBhcmFtIHtTdGFnZUNoYW5uZWx8Vm9pY2VDaGFubmVsfSBbY2hhbm5lbF0gVGhlIHZvaWNlL3N0YWdlIGNoYW5uZWwgdG8gam9pblxuICAgKiBAcGFyYW0ge29iamVjdH0gW29wdGlvbnNdIEpvaW4gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Vm9pY2VDb25uZWN0aW9ufVxuICAgKi9cbiAgcHVibGljIGFzeW5jIGpvaW4oXG4gIGNoYW5uZWw6IFZvaWNlQ2hhbm5lbCB8IFN0YWdlQ2hhbm5lbCxcbiAgb3B0aW9ucz86IHtcbiAgICBkZWFmPzogYm9vbGVhbjtcbiAgICBtYXhUaW1lPzogbnVtYmVyO1xuICAgIGdyb3VwPzogc3RyaW5nO1xuICAgIGRhdmVFbmNyeXB0aW9uPzogYm9vbGVhbjtcbiAgICBkZWNyeXB0aW9uRmFpbHVyZVRvbGVyYW5jZT86IG51bWJlcjtcbiAgfSlcbiAge1xuICAgIGNvbnN0IGV4aXN0aW5nQ29ubmVjdGlvbiA9IHRoaXMuZ2V0Q29ubmVjdGlvbihcbiAgICAgIGNoYW5uZWwuZ3VpbGQuaWQsXG4gICAgICBvcHRpb25zPy5ncm91cFxuICAgICk7XG5cbiAgICBpZiAoXG4gICAgZXhpc3RpbmdDb25uZWN0aW9uPy5qb2luQ29uZmlnLmNoYW5uZWxJZCA9PT0gY2hhbm5lbD8uaWQgJiZcbiAgICBleGlzdGluZ0Nvbm5lY3Rpb24uc3RhdGUuc3RhdHVzICE9PSBWb2ljZUNvbm5lY3Rpb25TdGF0dXMuRGVzdHJveWVkKVxuICAgIHtcbiAgICAgIHJldHVybiBleGlzdGluZ0Nvbm5lY3Rpb247XG4gICAgfVxuXG4gICAgY29uc3QgY29ubiA9IGpvaW5Wb2ljZUNoYW5uZWwoe1xuICAgICAgZ3VpbGRJZDogY2hhbm5lbC5ndWlsZC5pZCxcbiAgICAgIGNoYW5uZWxJZDogY2hhbm5lbC5pZCxcbiAgICAgIGFkYXB0ZXJDcmVhdG9yOiBjaGFubmVsLmd1aWxkLlxuICAgICAgdm9pY2VBZGFwdGVyQ3JlYXRvciBhcyB1bmtub3duIGFzIERpc2NvcmRHYXRld2F5QWRhcHRlckNyZWF0b3IsXG4gICAgICBzZWxmRGVhZjogQm9vbGVhbihvcHRpb25zPy5kZWFmKSxcbiAgICAgIGRlYnVnOiB0aGlzLnBsYXllci5ldmVudHMubGlzdGVuZXJDb3VudCgnZGVidWcnKSA+IDAsXG4gICAgICBncm91cDogb3B0aW9ucz8uZ3JvdXAsXG4gICAgICBkYXZlRW5jcnlwdGlvbjogb3B0aW9ucz8uZGF2ZUVuY3J5cHRpb24gPz8gdHJ1ZSxcbiAgICAgIGRlY3J5cHRpb25GYWlsdXJlVG9sZXJhbmNlOiBvcHRpb25zPy5kZWNyeXB0aW9uRmFpbHVyZVRvbGVyYW5jZSA/PyAyNFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvbm47XG4gIH1cblxuICAvKipcbiAgICogRGlzY29ubmVjdHMgdm9pY2UgY29ubmVjdGlvblxuICAgKiBAcGFyYW0ge1ZvaWNlQ29ubmVjdGlvbn0gY29ubmVjdGlvbiBUaGUgdm9pY2UgY29ubmVjdGlvblxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHB1YmxpYyBkaXNjb25uZWN0KGNvbm5lY3Rpb246IFZvaWNlQ29ubmVjdGlvbiB8IFN0cmVhbURpc3BhdGNoZXIpIHtcbiAgICBpZiAoY29ubmVjdGlvbiBpbnN0YW5jZW9mIFN0cmVhbURpc3BhdGNoZXIpXG4gICAgY29ubmVjdGlvbiA9IGNvbm5lY3Rpb24udm9pY2VDb25uZWN0aW9uO1xuXG4gICAgdHJ5IHtcbiAgICAgIGlmIChjb25uZWN0aW9uLnN0YXRlLnN0YXR1cyAhPT0gVm9pY2VDb25uZWN0aW9uU3RhdHVzLkRlc3Ryb3llZClcbiAgICAgIHJldHVybiBjb25uZWN0aW9uLmRlc3Ryb3koKTtcbiAgICB9IGNhdGNoIHtcblxuICAgICAgLy9cbiAgICB9fVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIERpc2NvcmQgUGxheWVyIHZvaWNlIGNvbm5lY3Rpb25cbiAgICogQHBhcmFtIHtTbm93Zmxha2V9IGd1aWxkIFRoZSBndWlsZCBpZFxuICAgKiBAcmV0dXJucyB7U3RyZWFtRGlzcGF0Y2hlcn1cbiAgICovXG4gIHB1YmxpYyBnZXRDb25uZWN0aW9uKGd1aWxkOiBTbm93Zmxha2UsIGdyb3VwPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGdldFZvaWNlQ29ubmVjdGlvbihndWlsZCwgZ3JvdXApO1xuICB9XG59XG5cbmV4cG9ydCB7IFZvaWNlVXRpbHMgfTsiLCAiaW1wb3J0IHsgUGxheWVyIH0gZnJvbSAnLi4vUGxheWVyJztcbmltcG9ydCB7IFNlYXJjaFJlc3VsdCB9IGZyb20gJy4uL2ZhYnJpYy9TZWFyY2hSZXN1bHQnO1xuaW1wb3J0IHsgVHJhY2sgfSBmcm9tICcuLi9mYWJyaWMvVHJhY2snO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJ2Rpc2NvcmQuanMnO1xuaW1wb3J0IHsgU2VhcmNoUXVlcnlUeXBlIH0gZnJvbSAnLi9RdWVyeVJlc29sdmVyJztcblxuZXhwb3J0IGludGVyZmFjZSBRdWVyeUNhY2hlT3B0aW9ucyB7XG4gIGNoZWNrSW50ZXJ2YWw/OiBudW1iZXI7XG59XG5cbi8vIDVoXG5jb25zdCBERUZBVUxUX0VYUElSWV9USU1FT1VUID0gMThfMDAwXzAwMDtcblxuZXhwb3J0IGludGVyZmFjZSBRdWVyeUNhY2hlUHJvdmlkZXI8VD4ge1xuICBnZXREYXRhKCk6IFByb21pc2U8RGlzY29yZFBsYXllclF1ZXJ5UmVzdWx0Q2FjaGU8VD5bXT47XG4gIGFkZERhdGEoZGF0YTogU2VhcmNoUmVzdWx0KTogUHJvbWlzZTx2b2lkPjtcbiAgcmVzb2x2ZShjb250ZXh0OiBRdWVyeUNhY2hlUmVzb2x2ZXJDb250ZXh0KTogUHJvbWlzZTxTZWFyY2hSZXN1bHQ+O1xufVxuXG5leHBvcnQgY2xhc3MgUXVlcnlDYWNoZSBpbXBsZW1lbnRzIFF1ZXJ5Q2FjaGVQcm92aWRlcjxUcmFjaz4ge1xuICAjZGVmYXVsdENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIERpc2NvcmRQbGF5ZXJRdWVyeVJlc3VsdENhY2hlPFRyYWNrPj4oKTtcbiAgcHVibGljIHRpbWVyOiBOb2RlSlMuVGltZXI7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgcHVibGljIHBsYXllcjogUGxheWVyLFxuICBwdWJsaWMgb3B0aW9uczogUXVlcnlDYWNoZU9wdGlvbnMgPSB7XG4gICAgY2hlY2tJbnRlcnZhbDogREVGQVVMVF9FWFBJUllfVElNRU9VVFxuICB9KVxuICB7XG4gICAgdGhpcy50aW1lciA9IHNldEludGVydmFsKFxuICAgICAgdGhpcy5jbGVhbnVwLmJpbmQodGhpcyksXG4gICAgICB0aGlzLmNoZWNrSW50ZXJ2YWxcbiAgICApLnVucmVmKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGNoZWNrSW50ZXJ2YWwoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5jaGVja0ludGVydmFsID8/IERFRkFVTFRfRVhQSVJZX1RJTUVPVVQ7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY2xlYW51cCgpIHtcbiAgICBmb3IgKGNvbnN0IFtpZCwgdmFsdWVdIG9mIHRoaXMuI2RlZmF1bHRDYWNoZSkge1xuICAgICAgaWYgKHZhbHVlLmhhc0V4cGlyZWQoKSkge1xuICAgICAgICB0aGlzLiNkZWZhdWx0Q2FjaGUuZGVsZXRlKGlkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY2xlYXIoKSB7XG4gICAgdGhpcy4jZGVmYXVsdENhY2hlLmNsZWFyKCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0RGF0YSgpIHtcbiAgICByZXR1cm4gWy4uLnRoaXMuI2RlZmF1bHRDYWNoZS52YWx1ZXMoKV07XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgYWRkRGF0YShkYXRhOiBTZWFyY2hSZXN1bHQpIHtcbiAgICBkYXRhLnRyYWNrcy5mb3JFYWNoKChkKSA9PiB7XG4gICAgICBpZiAodGhpcy4jZGVmYXVsdENhY2hlLmhhcyhkLnVybCkpIHJldHVybjtcbiAgICAgIHRoaXMuI2RlZmF1bHRDYWNoZS5zZXQoZC51cmwsIG5ldyBEaXNjb3JkUGxheWVyUXVlcnlSZXN1bHRDYWNoZShkKSk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcmVzb2x2ZShjb250ZXh0OiBRdWVyeUNhY2hlUmVzb2x2ZXJDb250ZXh0KSB7XG4gICAgY29uc3QgcmVzdWx0ID0gdGhpcy4jZGVmYXVsdENhY2hlLmdldChjb250ZXh0LnF1ZXJ5KTtcbiAgICBpZiAoIXJlc3VsdClcbiAgICByZXR1cm4gbmV3IFNlYXJjaFJlc3VsdCh0aGlzLnBsYXllciwge1xuICAgICAgcXVlcnk6IGNvbnRleHQucXVlcnksXG4gICAgICByZXF1ZXN0ZWRCeTogY29udGV4dC5yZXF1ZXN0ZWRCeSxcbiAgICAgIHF1ZXJ5VHlwZTogY29udGV4dC5xdWVyeVR5cGVcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgU2VhcmNoUmVzdWx0KHRoaXMucGxheWVyLCB7XG4gICAgICBxdWVyeTogY29udGV4dC5xdWVyeSxcbiAgICAgIHRyYWNrczogW3Jlc3VsdC5kYXRhXSxcbiAgICAgIHBsYXlsaXN0OiBudWxsLFxuICAgICAgcXVlcnlUeXBlOiBjb250ZXh0LnF1ZXJ5VHlwZSxcbiAgICAgIHJlcXVlc3RlZEJ5OiBjb250ZXh0LnJlcXVlc3RlZEJ5XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIERpc2NvcmRQbGF5ZXJRdWVyeVJlc3VsdENhY2hlPFQgPSB1bmtub3duPiB7XG4gIHB1YmxpYyBleHBpcmVBZnRlciA9IERFRkFVTFRfRVhQSVJZX1RJTUVPVVQ7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgcHVibGljIGRhdGE6IFQsXG4gIGV4cGlyZUFmdGVyOiBudW1iZXIgPSBERUZBVUxUX0VYUElSWV9USU1FT1VUKVxuICB7XG4gICAgaWYgKHR5cGVvZiBleHBpcmVBZnRlciA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuZXhwaXJlQWZ0ZXIgPSBEYXRlLm5vdygpICsgZXhwaXJlQWZ0ZXI7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGhhc0V4cGlyZWQoKSB7XG4gICAgaWYgKFxuICAgIHR5cGVvZiB0aGlzLmV4cGlyZUFmdGVyICE9PSAnbnVtYmVyJyB8fFxuICAgIGlzTmFOKHRoaXMuZXhwaXJlQWZ0ZXIpIHx8XG4gICAgdGhpcy5leHBpcmVBZnRlciA8IDEpXG5cbiAgICByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIERhdGUubm93KCkgPD0gdGhpcy5leHBpcmVBZnRlcjtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1ZXJ5Q2FjaGVSZXNvbHZlckNvbnRleHQge1xuICBxdWVyeTogc3RyaW5nO1xuICByZXF1ZXN0ZWRCeT86IFVzZXI7XG4gIHF1ZXJ5VHlwZT86IFNlYXJjaFF1ZXJ5VHlwZSB8IGBleHQ6JHtzdHJpbmd9YDtcbn0iLCAiaW1wb3J0IHsgRkZtcGVnIH0gZnJvbSAnQGRpc2NvcmQtcGxheWVyL2ZmbXBlZyc7XG5pbXBvcnQge1xuICBDbGllbnQsXG4gIFNub3dmbGFrZVV0aWwsXG4gIFZvaWNlU3RhdGUsXG4gIEludGVudHNCaXRGaWVsZCxcbiAgVXNlcixcbiAgR3VpbGRWb2ljZUNoYW5uZWxSZXNvbHZhYmxlLFxuICB2ZXJzaW9uIGFzIGRqc1ZlcnNpb24sXG4gIEV2ZW50cyB9IGZyb21cbidkaXNjb3JkLmpzJztcbmltcG9ydCB7XG4gIFBsYXlsaXN0LFxuICBUcmFjayxcbiAgU2VhcmNoUmVzdWx0LFxuICBTZWFyY2hPcHRpb25zLFxuICBQbGF5bGlzdEluaXREYXRhIH0gZnJvbVxuJy4vZmFicmljJztcbmltcG9ydCB7XG4gIEd1aWxkUXVldWVFdmVudHMsXG4gIFZvaWNlQ29ubmVjdENvbmZpZyxcbiAgR3VpbGROb2RlQ3JlYXRlT3B0aW9ucyxcbiAgR3VpbGROb2RlTWFuYWdlcixcbiAgR3VpbGRRdWV1ZSxcbiAgUmVzb3VyY2VQbGF5T3B0aW9ucyxcbiAgR3VpbGRRdWV1ZUV2ZW50IH0gZnJvbVxuJy4vcXVldWUnO1xuaW1wb3J0IHsgVm9pY2VVdGlscyB9IGZyb20gJy4vc3RyZWFtL1ZvaWNlVXRpbHMnO1xuaW1wb3J0IHtcbiAgUXVlcnlSZXNvbHZlcixcbiAgUXVlcnlUeXBlLFxuICBSZXNvbHZlZFF1ZXJ5LFxuICBTZWFyY2hRdWVyeVR5cGUgfSBmcm9tXG4nLi91dGlscy9RdWVyeVJlc29sdmVyJztcbmltcG9ydCB7IFV0aWwgfSBmcm9tICcuL3V0aWxzL1V0aWwnO1xuaW1wb3J0IHtcbiAgQXVkaW9SZXNvdXJjZSxcbiAgdmVyc2lvbiBhcyBkVm9pY2VWZXJzaW9uLFxuICBTdHJlYW1UeXBlIH0gZnJvbVxuJ2Rpc2NvcmQtdm9pcCc7XG5pbXBvcnQgeyBFeHRyYWN0b3JFeGVjdXRpb25Db250ZXh0IH0gZnJvbSAnLi9leHRyYWN0b3JzL0V4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQnO1xuaW1wb3J0IHsgQmFzZUV4dHJhY3RvciB9IGZyb20gJy4vZXh0cmFjdG9ycy9CYXNlRXh0cmFjdG9yJztcbmltcG9ydCB7IFF1ZXJ5Q2FjaGUsIFF1ZXJ5Q2FjaGVQcm92aWRlciB9IGZyb20gJy4vdXRpbHMvUXVlcnlDYWNoZSc7XG5pbXBvcnQgeyBQbGF5ZXJFdmVudHNFbWl0dGVyIH0gZnJvbSAnLi91dGlscy9QbGF5ZXJFdmVudHNFbWl0dGVyJztcbmltcG9ydCB7IEludmFsaWRBcmdUeXBlRXJyb3IsIE5vUmVzdWx0RXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyBkZWZhdWx0Vm9pY2VTdGF0ZUhhbmRsZXIgfSBmcm9tICcuL0RlZmF1bHRWb2ljZVN0YXRlSGFuZGxlcic7XG5pbXBvcnQgeyBDb250ZXh0LCBjcmVhdGVDb250ZXh0IH0gZnJvbSAnLi9ob29rcyc7XG5pbXBvcnQgeyBIb29rc0N0eCwgU1VQRVJfQ09OVEVYVCB9IGZyb20gJy4vaG9va3MvY29tbW9uJztcbmltcG9ydCB7IExyY0xpYiB9IGZyb20gJy4vbHJjbGliL0xyY0xpYic7XG5pbXBvcnQgeyBnZXRDb21wYXROYW1lLCBpc0NsaWVudFByb3h5IH0gZnJvbSAnLi9jb21wYXQvY29tbW9uJztcbmltcG9ydCB7IERlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3IgfSBmcm9tICcuL3V0aWxzL0RlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3InO1xuaW1wb3J0IHsgZ2V0R2xvYmFsUmVnaXN0cnkgfSBmcm9tICcuL3V0aWxzL19faW50ZXJuYWxfXyc7XG5pbXBvcnQgeyB2ZXJzaW9uIGFzIGRwVmVyc2lvbiB9IGZyb20gJy4vdmVyc2lvbic7XG5pbXBvcnQge1xuICBQbGF5ZXJTdHJlYW1JbnRlcmNlcHRvcixcbiAgdHlwZSBQbGF5ZXJTdHJlYW1JbnRlcmNlcHRvck9wdGlvbnMgfSBmcm9tXG4nLi9QbGF5ZXJTdHJlYW1JbnRlcmNlcHRvcic7XG5pbXBvcnQgdHlwZSB7IEludGVyY2VwdGVkU3RyZWFtIH0gZnJvbSAnLi9zdHJlYW0vSW50ZXJjZXB0ZWRTdHJlYW0nO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovXG5leHBvcnQgaW50ZXJmYWNlIFBsYXllckV2ZW50cyB7XG4gIGRlYnVnOiAobWVzc2FnZTogc3RyaW5nKSA9PiBhbnk7XG4gIGVycm9yOiAoZXJyb3I6IEVycm9yKSA9PiBhbnk7XG4gIHZvaWNlU3RhdGVVcGRhdGU6IChcbiAgcXVldWU6IEd1aWxkUXVldWUsXG4gIG9sZFN0YXRlOiBWb2ljZVN0YXRlLFxuICBuZXdTdGF0ZTogVm9pY2VTdGF0ZSlcbiAgPT4gYW55O1xufVxuXG5leHBvcnQgY29uc3QgUGxheWVyRXZlbnQgPSB7XG4gIGRlYnVnOiAnZGVidWcnLFxuICBEZWJ1ZzogJ2RlYnVnJyxcbiAgZXJyb3I6ICdlcnJvcicsXG4gIEVycm9yOiAnZXJyb3InLFxuICB2b2ljZVN0YXRlVXBkYXRlOiAndm9pY2VTdGF0ZVVwZGF0ZScsXG4gIFZvaWNlU3RhdGVVcGRhdGU6ICd2b2ljZVN0YXRlVXBkYXRlJ1xufSBhcyBjb25zdDtcbmV4cG9ydCB0eXBlIFBsYXllckV2ZW50ID0gKHR5cGVvZiBQbGF5ZXJFdmVudClba2V5b2YgdHlwZW9mIFBsYXllckV2ZW50XTtcblxuZXhwb3J0IGludGVyZmFjZSBQbGF5ZXJOb2RlSW5pdGlhbGl6YXRpb25SZXN1bHQ8VCA9IGFueT4ge1xuICB0cmFjazogVHJhY2s7XG4gIGV4dHJhY3RvcjogQmFzZUV4dHJhY3RvciB8IG51bGw7XG4gIHNlYXJjaFJlc3VsdDogU2VhcmNoUmVzdWx0O1xuICBxdWV1ZTogR3VpbGRRdWV1ZTxUPjtcbn1cblxuLyogZXNsaW50LWVuYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovXG5cbmV4cG9ydCB0eXBlIFRyYWNrTGlrZSA9XG5zdHJpbmcgfFxuVHJhY2sgfFxuU2VhcmNoUmVzdWx0IHxcblRyYWNrW10gfFxuUGxheWxpc3QgfFxuQXVkaW9SZXNvdXJjZTtcblxuZXhwb3J0IGludGVyZmFjZSBQbGF5ZXJOb2RlSW5pdGlhbGl6ZXJPcHRpb25zPFQ+IGV4dGVuZHMgU2VhcmNoT3B0aW9ucyB7XG4gIG5vZGVPcHRpb25zPzogR3VpbGROb2RlQ3JlYXRlT3B0aW9uczxUPjtcbiAgY29ubmVjdGlvbk9wdGlvbnM/OiBWb2ljZUNvbm5lY3RDb25maWc7XG4gIGF1ZGlvUGxheWVyT3B0aW9ucz86IFJlc291cmNlUGxheU9wdGlvbnM7XG4gIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICBhZnRlclNlYXJjaD86IChyZXN1bHQ6IFNlYXJjaFJlc3VsdCkgPT4gUHJvbWlzZTxTZWFyY2hSZXN1bHQ+O1xufVxuXG5leHBvcnQgdHlwZSBWb2ljZVN0YXRlSGFuZGxlciA9IChcbnBsYXllcjogUGxheWVyLFxucXVldWU6IEd1aWxkUXVldWUsXG5vbGRWb2ljZVN0YXRlOiBWb2ljZVN0YXRlLFxubmV3Vm9pY2VTdGF0ZTogVm9pY2VTdGF0ZSlcbj0+IEF3YWl0ZWQ8dm9pZD47XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGxheWVySW5pdE9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHZvaWNlIGNvbm5lY3Rpb24gdGltZW91dFxuICAgKi9cbiAgY29ubmVjdGlvblRpbWVvdXQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaW1lIGluIG1zIHRvIHJlLW1vbml0b3IgZXZlbnQgbG9vcCBsYWdcbiAgICovXG4gIGxhZ01vbml0b3I/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBQcmV2ZW50IHZvaWNlIHN0YXRlIGhhbmRsZXIgZnJvbSBiZWluZyBvdmVycmlkZGVuXG4gICAqL1xuICBsb2NrVm9pY2VTdGF0ZUhhbmRsZXI/OiBib29sZWFuO1xuICAvKipcbiAgICogTGlzdCBvZiBleHRyYWN0b3JzIHRvIGRpc2FibGUgcXVlcnlpbmcgbWV0YWRhdGEgZnJvbVxuICAgKi9cbiAgYmxvY2tFeHRyYWN0b3JzPzogc3RyaW5nW107XG4gIC8qKlxuICAgKiBMaXN0IG9mIGV4dHJhY3RvcnMgdG8gZGlzYWJsZSBzdHJlYW1pbmcgZnJvbVxuICAgKi9cbiAgYmxvY2tTdHJlYW1Gcm9tPzogc3RyaW5nW107XG4gIC8qKlxuICAgKiBRdWVyeSBjYWNoZSBwcm92aWRlclxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgcXVlcnlDYWNoZT86IFF1ZXJ5Q2FjaGVQcm92aWRlcjxhbnk+IHwgbnVsbDtcbiAgLyoqXG4gICAqIFNraXAgZmZtcGVnIHByb2Nlc3Mgd2hlbiBwb3NzaWJsZVxuICAgKi9cbiAgc2tpcEZGbXBlZz86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUaGUgcHJvYmUgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuIERlZmF1bHRzIHRvIDUwMDAuXG4gICAqL1xuICBwcm9iZVRpbWVvdXQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBDb25maWd1cmUgZmZtcGVnIHBhdGhcbiAgICovXG4gIGZmbXBlZ1BhdGg/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIG92ZXJyaWRlIHRoZSBmYWxsYmFjayBjb250ZXh0LiBEZWZhdWx0cyB0byBgdHJ1ZWAuXG4gICAqL1xuICBvdmVycmlkZUZhbGxiYWNrQ29udGV4dD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjbGFzcyBQbGF5ZXIgZXh0ZW5kcyBQbGF5ZXJFdmVudHNFbWl0dGVyPFBsYXllckV2ZW50cz4ge1xuICAjbGFzdExhdGVuY3kgPSAtMTtcbiAgI3ZvaWNlU3RhdGVVcGRhdGVMaXN0ZW5lciA9IHRoaXMuaGFuZGxlVm9pY2VTdGF0ZS5iaW5kKHRoaXMpO1xuICAjbGFnTW9uaXRvclRpbWVvdXQ6IE5vZGVKUy5UaW1lb3V0O1xuICAjbGFnTW9uaXRvckludGVydmFsOiBOb2RlSlMuVGltZW91dDtcbiAgI29uVm9pY2VTdGF0ZVVwZGF0ZTogVm9pY2VTdGF0ZUhhbmRsZXIgPSBkZWZhdWx0Vm9pY2VTdGF0ZUhhbmRsZXI7XG4gICNob29rc0N0eDogQ29udGV4dDxIb29rc0N0eD4gfCBudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIFRoZSB2ZXJzaW9uIG9mIGRpc2NvcmQtcGxheWVyXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IHZlcnNpb246IHN0cmluZyA9IGRwVmVyc2lvbjtcbiAgLyoqXG4gICAqIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGlzIHBsYXllciBpbnN0YW5jZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGlkID0gU25vd2ZsYWtlVXRpbC5nZW5lcmF0ZSgpLnRvU3RyaW5nKCk7XG4gIC8qKlxuICAgKiBUaGUgZGlzY29yZC5qcyBjbGllbnRcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjbGllbnQhOiBDbGllbnQ7XG4gIC8qKlxuICAgKiBUaGUgcGxheWVyIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBvcHRpb25zITogUGxheWVySW5pdE9wdGlvbnM7XG4gIC8qKlxuICAgKiBUaGUgcGxheWVyIG5vZGVzIChxdWV1ZSkgbWFuYWdlclxuICAgKi9cbiAgcHVibGljIG5vZGVzID0gbmV3IEd1aWxkTm9kZU1hbmFnZXIodGhpcyk7XG4gIC8qKlxuICAgKiBUaGUgdm9pY2UgYXBpIHV0aWxpdGllc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZvaWNlVXRpbHMgPSBuZXcgVm9pY2VVdGlscyh0aGlzKTtcbiAgLyoqXG4gICAqIFRoZSBleHRyYWN0b3JzIG1hbmFnZXJcbiAgICovXG4gIHB1YmxpYyBleHRyYWN0b3JzID0gbmV3IEV4dHJhY3RvckV4ZWN1dGlvbkNvbnRleHQodGhpcyk7XG4gIC8qKlxuICAgKiBUaGUgcGxheWVyIGV2ZW50cyBjaGFubmVsXG4gICAqL1xuICBwdWJsaWMgZXZlbnRzID0gbmV3IFBsYXllckV2ZW50c0VtaXR0ZXI8R3VpbGRRdWV1ZUV2ZW50cz4oW1xuICBHdWlsZFF1ZXVlRXZlbnQuRXJyb3IsXG4gIEd1aWxkUXVldWVFdmVudC5QbGF5ZXJFcnJvcl1cbiAgKTtcbiAgLyoqXG4gICAqIFRoZSBwbGF5ZXIgdmVyc2lvblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZlcnNpb24gPSBQbGF5ZXIudmVyc2lvbjtcbiAgLyoqXG4gICAqIFRoZSBseXJpY3MgYXBpXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbHlyaWNzID0gbmV3IExyY0xpYih0aGlzKTtcblxuICAjc3RyZWFtSW50ZXJjZXB0b3I6IFBsYXllclN0cmVhbUludGVyY2VwdG9yIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgbmV3IERpc2NvcmQgUGxheWVyXG4gICAqIEBwYXJhbSB7Q2xpZW50fSBjbGllbnQgVGhlIERpc2NvcmQgQ2xpZW50XG4gICAqIEBwYXJhbSB7UGxheWVySW5pdE9wdGlvbnN9IFtvcHRpb25zXSBUaGUgcGxheWVyIGluaXQgb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKGNsaWVudDogQ2xpZW50LCBvcHRpb25zOiBQbGF5ZXJJbml0T3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoW1BsYXllckV2ZW50LkVycm9yXSk7XG5cbiAgICBpZiAob3B0aW9ucy5mZm1wZWdQYXRoKSB7XG4gICAgICBpZiAodHlwZW9mIG9wdGlvbnMuZmZtcGVnUGF0aCAhPT0gJ3N0cmluZycpXG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICBgRXhwZWN0ZWQgdHlwZSBcInN0cmluZ1wiIGZvciBvcHRpb25zLmZmbXBlZ1BhdGguIEdvdCAke3R5cGVvZiBvcHRpb25zLmZmbXBlZ1BhdGh9IGluc3RlYWRgXG4gICAgICApO1xuXG4gICAgICBwcm9jZXNzLmVudi5GRk1QRUdfUEFUSCA9IG9wdGlvbnMuZmZtcGVnUGF0aDtcbiAgICB9XG5cbiAgICBjb25zdCBpc0NvbXBhdE1vZGUgPSBpc0NsaWVudFByb3h5KGNsaWVudCk7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZGlzY29yZCBjbGllbnRcbiAgICAgKiBAdHlwZSB7Q2xpZW50fVxuICAgICAqL1xuICAgIHRoaXMuY2xpZW50ID0gY2xpZW50O1xuXG4gICAgaWYgKCFpc0NvbXBhdE1vZGUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICghKGNsaWVudCBpbnN0YW5jZW9mIENsaWVudCkpIHtcbiAgICAgICAgICBVdGlsLndhcm4oXG4gICAgICAgICAgICBgQ2xpZW50IGlzIG5vdCBhbiBpbnN0YW5jZSBvZiBkaXNjb3JkLmpzQCR7ZGpzVmVyc2lvbn0gY2xpZW50LCBzb21lIHRoaW5ncyBtYXkgbm90IHdvcmsgY29ycmVjdGx5LiBUaGlzIGNhbiBoYXBwZW4gZHVlIHRvIGNvcnJ1cHQgZGVwZW5kZW5jaWVzIG9yIGhhdmluZyBtdWx0aXBsZSBpbnN0YWxsYXRpb25zIG9mIGRpc2NvcmQuanMuYCxcbiAgICAgICAgICAgICdJbnZhbGlkQ2xpZW50SW5zdGFuY2UnXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGliZiA9XG4gICAgICAgIHRoaXMuY2xpZW50Lm9wdGlvbnMuaW50ZW50cyBpbnN0YW5jZW9mIEludGVudHNCaXRGaWVsZCA/XG4gICAgICAgIHRoaXMuY2xpZW50Lm9wdGlvbnMuaW50ZW50cyA6XG4gICAgICAgIG5ldyBJbnRlbnRzQml0RmllbGQodGhpcy5jbGllbnQub3B0aW9ucy5pbnRlbnRzKTtcblxuICAgICAgICBpZiAoIWliZi5oYXMoSW50ZW50c0JpdEZpZWxkLkZsYWdzLkd1aWxkVm9pY2VTdGF0ZXMpKSB7XG4gICAgICAgICAgVXRpbC53YXJuKFxuICAgICAgICAgICAgJ2NsaWVudCBpcyBtaXNzaW5nIFwiR3VpbGRWb2ljZVN0YXRlc1wiIGludGVudCcsXG4gICAgICAgICAgICAnSW52YWxpZEludGVudHNCaXRGaWVsZCdcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIHtcblxuICAgICAgICAvLyBub29wXG4gICAgICB9fVxuXG4gICAgdGhpcy5vcHRpb25zID0ge1xuICAgICAgbG9ja1ZvaWNlU3RhdGVIYW5kbGVyOiBmYWxzZSxcbiAgICAgIGJsb2NrRXh0cmFjdG9yczogW10sXG4gICAgICBibG9ja1N0cmVhbUZyb206IFtdLFxuICAgICAgY29ubmVjdGlvblRpbWVvdXQ6IDIwMDAwLFxuICAgICAgbGFnTW9uaXRvcjogMzAwMDAsXG4gICAgICBxdWVyeUNhY2hlOlxuICAgICAgb3B0aW9ucy5xdWVyeUNhY2hlID09PSBudWxsID9cbiAgICAgIG51bGwgOlxuICAgICAgb3B0aW9ucy5xdWVyeUNhY2hlIHx8IG5ldyBRdWVyeUNhY2hlKHRoaXMpLFxuICAgICAgc2tpcEZGbXBlZzogdHJ1ZSxcbiAgICAgIHByb2JlVGltZW91dDogNTAwMCxcbiAgICAgIG92ZXJyaWRlRmFsbGJhY2tDb250ZXh0OiB0cnVlLFxuICAgICAgLi4ub3B0aW9uc1xuICAgIH0gc2F0aXNmaWVzIFBsYXllckluaXRPcHRpb25zO1xuXG4gICAgaWYgKCFpc0NvbXBhdE1vZGUpIHtcbiAgICAgIC8vIEB0cy1pZ25vcmUgcHJpdmF0ZSBtZXRob2RcbiAgICAgIHRoaXMuY2xpZW50LmluY3JlbWVudE1heExpc3RlbmVycygpO1xuICAgICAgdGhpcy5jbGllbnQub24oRXZlbnRzLlZvaWNlU3RhdGVVcGRhdGUsIHRoaXMuI3ZvaWNlU3RhdGVVcGRhdGVMaXN0ZW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIEB0cy1pZ25vcmUgcHJpdmF0ZSBtZXRob2RcbiAgICAgICAgdGhpcy5jbGllbnQuX19kcF92b2ljZVN0YXRlVXBkYXRlX3Byb3h5KHRoaXMuI3ZvaWNlU3RhdGVVcGRhdGVMaXN0ZW5lcik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIFV0aWwud2FybihcbiAgICAgICAgICAnRmFpbGVkIHRvIGF0dGFjaCB2b2ljZSBzdGF0ZSB1cGRhdGUgcHJveHksIHZvaWNlIHN0YXRlIGhhbmRsZXIgd2lsbCBub3Qgd29yayBwcm9wZXJseScsXG4gICAgICAgICAgJ0NvbXBhdE1vZGVFcnJvcidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoXG4gICAgdHlwZW9mIHRoaXMub3B0aW9ucy5sYWdNb25pdG9yID09PSAnbnVtYmVyJyAmJlxuICAgIHRoaXMub3B0aW9ucy5sYWdNb25pdG9yID4gMClcbiAgICB7XG4gICAgICB0aGlzLiNsYWdNb25pdG9ySW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIHRoaXMuI2xhZ01vbml0b3JUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy4jbGFzdExhdGVuY3kgPSBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0O1xuICAgICAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgICAgIHRoaXMuZGVidWcoXG4gICAgICAgICAgICBgW0xhZyBNb25pdG9yXSBFdmVudCBsb29wIGxhdGVuY3k6ICR7dGhpcy4jbGFzdExhdGVuY3l9bXNgXG4gICAgICAgICAgKTtcbiAgICAgICAgfSwgMCkudW5yZWYoKTtcbiAgICAgIH0sIHRoaXMub3B0aW9ucy5sYWdNb25pdG9yKS51bnJlZigpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMub3ZlcnJpZGVGYWxsYmFja0NvbnRleHQpIHtcbiAgICAgIGdldEdsb2JhbFJlZ2lzdHJ5KCkuc2V0KCdAW3BsYXllcl0nLCB0aGlzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIGhvb2tzIGNvbnRleHQgZm9yIHRoaXMgcGxheWVyIGluc3RhbmNlLlxuICAgKi9cbiAgcHVibGljIGdldCBjb250ZXh0KCkge1xuICAgIGlmICghdGhpcy4jaG9va3NDdHgpIHtcbiAgICAgIHRoaXMuI2hvb2tzQ3R4ID0gY3JlYXRlQ29udGV4dCgpO1xuXG4gICAgICBjb25zdCBvcmlnaW5hbFByb3ZpZGVyID0gdGhpcy4jaG9va3NDdHgucHJvdmlkZS5iaW5kKHRoaXMuI2hvb2tzQ3R4KTtcblxuICAgICAgdGhpcy4jaG9va3NDdHgucHJvdmlkZSA9ICh2YWx1ZSwgcmVjZWl2ZXIpID0+IHtcbiAgICAgICAgcmV0dXJuIFNVUEVSX0NPTlRFWFQucHJvdmlkZSh0aGlzLCAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIG9yaWdpbmFsUHJvdmlkZXIodmFsdWUsICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiByZWNlaXZlcigpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuI2hvb2tzQ3R4O1xuICB9XG5cbiAgLyoqXG4gICAqIE92ZXJyaWRlIGRlZmF1bHQgdm9pY2Ugc3RhdGUgdXBkYXRlIGhhbmRsZXJcbiAgICogQHBhcmFtIGhhbmRsZXIgVGhlIGhhbmRsZXIgY2FsbGJhY2tcbiAgICovXG4gIHB1YmxpYyBvblZvaWNlU3RhdGVVcGRhdGUoaGFuZGxlcjogVm9pY2VTdGF0ZUhhbmRsZXIpIHtcbiAgICB0aGlzLiNvblZvaWNlU3RhdGVVcGRhdGUgPSBoYW5kbGVyO1xuICB9XG5cbiAgcHVibGljIGRlYnVnKG06IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmVtaXQoJ2RlYnVnJywgbSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBuZXcgZGlzY29yZC1wbGF5ZXIgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSBjbGllbnQgVGhlIGNsaWVudCB0aGF0IGluc3RhbnRpYXRlZCBwbGF5ZXJcbiAgICogQHBhcmFtIG9wdGlvbnMgUGxheWVyIGluaXRpYWxpemVyIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY3JlYXRlKGNsaWVudDogQ2xpZW50LCBvcHRpb25zOiBQbGF5ZXJJbml0T3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBQbGF5ZXIoY2xpZW50LCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBxdWVyeSBjYWNoZSBwcm92aWRlciBpbiB1c2VcbiAgICovXG4gIHB1YmxpYyBnZXQgcXVlcnlDYWNoZSgpIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLnF1ZXJ5Q2FjaGUgPz8gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGlhcyB0byBgUGxheWVyLm5vZGVzYC5cbiAgICovXG4gIHB1YmxpYyBnZXQgcXVldWVzKCkge1xuICAgIHJldHVybiB0aGlzLm5vZGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIEV2ZW50IGxvb3AgbGF0ZW5jeSBpbiBtcy4gSWYgeW91ciBib3QgaXMgbGFnZ3kgYW5kIHRoaXMgcmV0dXJucyBhIG51bWJlciBhYm92ZSAyMG1zIGZvciBleGFtcGxlLFxuICAgKiBzb21lIGV4cGVuc2l2ZSB0YXNrIGlzIGJlaW5nIGV4ZWN1dGVkIG9uIHRoZSBjdXJyZW50IHRocmVhZCB3aGljaCBpcyBzbG93aW5nIGRvd24gdGhlIGV2ZW50IGxvb3AuXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBwdWJsaWMgZ2V0IGV2ZW50TG9vcExhZygpIHtcbiAgICByZXR1cm4gdGhpcy4jbGFzdExhdGVuY3k7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIHN0YXRpc3RpY3MgdGhhdCBjb3VsZCBiZSB1c2VmdWwuIFN0YXRpc3RpY3MgZ2VuZXJhdG9yIGlzIHN0aWxsIGV4cGVyaW1lbnRhbC5cbiAgICogQGV4YW1wbGUgYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBzdGF0cyA9IHBsYXllci5nZW5lcmF0ZVN0YXRpc3RpY3MoKTtcbiAgICpcbiAgICogY29uc29sZS5sb2coc3RhdHMpO1xuICAgKlxuICAgKiAvLyBvdXRwdXRzIHNvbWV0aGluZyBsaWtlXG4gICAqIC8vIHtcbiAgICogLy8gICBxdWV1ZXNDb3VudDogbnVtYmVyLFxuICAgKiAvLyAgIHF1ZXJ5Q2FjaGVFbmFibGVkOiBib29sZWFuLFxuICAgKiAvLyAgIHF1ZXVlczogW1xuICAgKiAvLyAgICAgIEd1aWxkUXVldWVTdGF0aXN0aWNzTWV0YWRhdGEsXG4gICAqIC8vICAgICAgR3VpbGRRdWV1ZVN0YXRpc3RpY3NNZXRhZGF0YSxcbiAgICogLy8gICAgICBHdWlsZFF1ZXVlU3RhdGlzdGljc01ldGFkYXRhLFxuICAgKiAvLyAgICAgIC4uLlxuICAgKiAvLyAgIF1cbiAgICogLy8gfVxuICAgKiBgYGBcbiAgICovXG4gIHB1YmxpYyBnZW5lcmF0ZVN0YXRpc3RpY3MoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHF1ZXVlc0NvdW50OiB0aGlzLnF1ZXVlcy5jYWNoZS5zaXplLFxuICAgICAgcXVlcnlDYWNoZUVuYWJsZWQ6IHRoaXMucXVlcnlDYWNoZSAhPSBudWxsLFxuICAgICAgcXVldWVzOiB0aGlzLnF1ZXVlcy5jYWNoZS5tYXAoKG0pID0+IG0uc3RhdHMuZ2VuZXJhdGUoKSlcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHBsYXllciBpcyBpbiBjb21wYXRpYmlsaXR5IG1vZGUuIENvbXBhdGliaWxpdHkgbW9kZSBpcyBlbmFibGVkIHdoZW4gbm9uLWRpc2NvcmQuanMgY2xpZW50IGlzIHVzZWQuXG4gICAqL1xuICBwdWJsaWMgaXNDb21wYXRNb2RlKCkge1xuICAgIHJldHVybiBpc0NsaWVudFByb3h5KHRoaXMuY2xpZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXN0cm95IGV2ZXJ5IHNpbmdsZSBxdWV1ZXMgbWFuYWdlZCBieSB0aGlzIG1hc3RlciBwbGF5ZXIgaW5zdGFuY2VcbiAgICogQGV4YW1wbGUgYGBgdHlwZXNjcmlwdFxuICAgKiAvLyB1c2UgbWUgd2hlbiB5b3Ugd2FudCB0byBpbW1lZGlhdGVseSB0ZXJtaW5hdGUgZXZlcnkgc2luZ2xlIHF1ZXVlcyBpbiBleGlzdGVuY2UgXHVEODNEXHVERDJBXG4gICAqIGF3YWl0IHBsYXllci5kZXN0cm95KCk7XG4gICAqIGBgYFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRlc3Ryb3koKSB7XG4gICAgdGhpcy5ub2Rlcy5jYWNoZS5mb3JFYWNoKChub2RlKSA9PiBub2RlLmRlbGV0ZSgpKTtcblxuICAgIGlmICghdGhpcy5pc0NvbXBhdE1vZGUoKSkge1xuICAgICAgdGhpcy5jbGllbnQub2ZmKEV2ZW50cy5Wb2ljZVN0YXRlVXBkYXRlLCB0aGlzLiN2b2ljZVN0YXRlVXBkYXRlTGlzdGVuZXIpO1xuICAgICAgLy8gQHRzLWlnbm9yZSBwcml2YXRlIG1ldGhvZFxuICAgICAgdGhpcy5jbGllbnQuZGVjcmVtZW50TWF4TGlzdGVuZXJzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLmV2ZW50cy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICBhd2FpdCB0aGlzLmV4dHJhY3RvcnMudW5yZWdpc3RlckFsbCgpO1xuICAgIGlmICh0aGlzLiNsYWdNb25pdG9ySW50ZXJ2YWwpIGNsZWFySW50ZXJ2YWwodGhpcy4jbGFnTW9uaXRvckludGVydmFsKTtcbiAgICBpZiAodGhpcy4jbGFnTW9uaXRvclRpbWVvdXQpIGNsZWFySW50ZXJ2YWwodGhpcy4jbGFnTW9uaXRvclRpbWVvdXQpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaGFuZGxlVm9pY2VTdGF0ZShvbGRTdGF0ZTogVm9pY2VTdGF0ZSwgbmV3U3RhdGU6IFZvaWNlU3RhdGUpIHtcbiAgICBjb25zdCBxdWV1ZSA9IHRoaXMubm9kZXMuZ2V0KG9sZFN0YXRlLmd1aWxkLmlkKTtcbiAgICBpZiAoIXF1ZXVlIHx8ICFxdWV1ZS5jb25uZWN0aW9uIHx8ICFxdWV1ZS5jaGFubmVsKSByZXR1cm47XG5cbiAgICAvLyBkaXNwYXRjaCB2b2ljZSBzdGF0ZSB1cGRhdGVcbiAgICBjb25zdCB3YXNIYW5kbGVkID0gdGhpcy5ldmVudHMuZW1pdChcbiAgICAgIEd1aWxkUXVldWVFdmVudC5Wb2ljZVN0YXRlVXBkYXRlLFxuICAgICAgcXVldWUsXG4gICAgICBvbGRTdGF0ZSxcbiAgICAgIG5ld1N0YXRlXG4gICAgKTtcbiAgICAvLyBpZiB0aGUgZXZlbnQgd2FzIGhhbmRsZWQsIHJldHVybiBhc3N1bWluZyB0aGUgbGlzdGVuZXIgaW1wbGVtZW50ZWQgYWxsIG9mIHRoZSBsb2dpYyBiZWxvd1xuICAgIGlmICh3YXNIYW5kbGVkICYmICF0aGlzLm9wdGlvbnMubG9ja1ZvaWNlU3RhdGVIYW5kbGVyKSByZXR1cm47XG5cbiAgICByZXR1cm4gdGhpcy4jb25Wb2ljZVN0YXRlVXBkYXRlKHRoaXMsIHF1ZXVlLCBvbGRTdGF0ZSwgbmV3U3RhdGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdm9pY2Ugc3RhdGUgdXBkYXRlXG4gICAqIEBwYXJhbSB7Vm9pY2VTdGF0ZX0gb2xkU3RhdGUgVGhlIG9sZCB2b2ljZSBzdGF0ZVxuICAgKiBAcGFyYW0ge1ZvaWNlU3RhdGV9IG5ld1N0YXRlIFRoZSBuZXcgdm9pY2Ugc3RhdGVcbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqIEBleGFtcGxlIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gcGFzc2luZyB2b2ljZSBzdGF0ZSB1cGRhdGUgZGF0YSB0byB0aGlzIG1ldGhvZCB3aWxsIHRyaWdnZXIgdm9pY2Ugc3RhdGUgaGFuZGxlclxuICAgKlxuICAgKiBjbGllbnQub24oJ3ZvaWNlU3RhdGVVcGRhdGUnLCAob2xkU3RhdGUsIG5ld1N0YXRlKSA9PiB7XG4gICAqICAgLy8gdGhpcyBpcyBkZWZpbml0ZWx5IGEgcm9ja2V0IHNjaWVuY2UsIHJpZ2h0IGhlcmVcbiAgICogICBwbGF5ZXIuaGFuZGxlVm9pY2VTdGF0ZShvbGRTdGF0ZSwgbmV3U3RhdGUpO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBwdWJsaWMgaGFuZGxlVm9pY2VTdGF0ZShvbGRTdGF0ZTogVm9pY2VTdGF0ZSwgbmV3U3RhdGU6IFZvaWNlU3RhdGUpOiB2b2lkIHtcbiAgICB0aGlzLl9oYW5kbGVWb2ljZVN0YXRlKG9sZFN0YXRlLCBuZXdTdGF0ZSk7XG4gIH1cblxuICAvKipcbiAgICogTG9jayB2b2ljZSBzdGF0ZSBoYW5kbGVyLiBXaGVuIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCwgZGlzY29yZC1wbGF5ZXIgd2lsbCBrZWVwIHVzaW5nIHRoZSBkZWZhdWx0IHZvaWNlIHN0YXRlIHVwZGF0ZSBoYW5kbGVyLCBldmVuIGlmIGN1c3RvbSBpbXBsZW1lbnRhdGlvbiBleGlzdHMuXG4gICAqL1xuICBwdWJsaWMgbG9ja1ZvaWNlU3RhdGVIYW5kbGVyKCkge1xuICAgIHRoaXMub3B0aW9ucy5sb2NrVm9pY2VTdGF0ZUhhbmRsZXIgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFVubG9jayB2b2ljZSBzdGF0ZSBoYW5kbGVyLiBXaGVuIHRoaXMgbWV0aG9kIGlzIGNhbGxlZCwgZGlzY29yZC1wbGF5ZXIgd2lsbCBzdG9wIHVzaW5nIHRoZSBkZWZhdWx0IHZvaWNlIHN0YXRlIHVwZGF0ZSBoYW5kbGVyIGlmIGN1c3RvbSBpbXBsZW1lbnRhdGlvbiBleGlzdHMuXG4gICAqL1xuICBwdWJsaWMgdW5sb2NrVm9pY2VTdGF0ZUhhbmRsZXIoKSB7XG4gICAgdGhpcy5vcHRpb25zLmxvY2tWb2ljZVN0YXRlSGFuZGxlciA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB2b2ljZSBzdGF0ZSBoYW5kbGVyIGlzIGxvY2tlZC5cbiAgICovXG4gIHB1YmxpYyBpc1ZvaWNlU3RhdGVIYW5kbGVyTG9ja2VkKCkge1xuICAgIHJldHVybiAhIXRoaXMub3B0aW9ucy5sb2NrVm9pY2VTdGF0ZUhhbmRsZXI7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhdGUgYXVkaW8gcGxheWVyXG4gICAqIEBwYXJhbSBjaGFubmVsIFRoZSB2b2ljZSBjaGFubmVsIG9uIHdoaWNoIHRoZSBtdXNpYyBzaG91bGQgYmUgcGxheWVkXG4gICAqIEBwYXJhbSBxdWVyeSBUaGUgdHJhY2sgb3Igc291cmNlIHRvIHBsYXlcbiAgICogQHBhcmFtIG9wdGlvbnMgT3B0aW9ucyBmb3IgcGxheWVyXG4gICAqIEBleGFtcGxlIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gbm8gbmVlZCB0byB3b3JyeSBhYm91dCBxdWV1ZSBtYW5hZ2VtZW50LCBqdXN0IHVzZSB0aGlzIG1ldGhvZCBcdUQ4M0RcdURFMDRcbiAgICogY29uc3QgcXVlcnkgPSAndGhpcyBpcyBteSBzdXBlciBjb29sIHNlYXJjaCBxdWVyeSB0aGF0IEkgd2FudCB0byBwbGF5JztcbiAgICpcbiAgICogdHJ5IHtcbiAgICogICAgY29uc3QgeyB0cmFjayB9ID0gYXdhaXQgcGxheWVyLnBsYXkodm9pY2VDaGFubmVsLCBxdWVyeSk7XG4gICAqICAgY29uc29sZS5sb2coYFx1RDgzQ1x1REY4OSBJIGFtIHBsYXlpbmcgJHt0cmFjay50aXRsZX0gXHVEODNDXHVERjg5YCk7XG4gICAqIH0gY2F0Y2goZSkge1xuICAgKiAgIGNvbnNvbGUubG9nKGBcdUQ4M0RcdURFMkQgRmFpbGVkIHRvIHBsYXkgZXJyb3Igb2ggbm86XFxuXFxuJHtlfWApO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgcHVibGljIGFzeW5jIHBsYXk8VCA9IHVua25vd24+KFxuICBjaGFubmVsOiBHdWlsZFZvaWNlQ2hhbm5lbFJlc29sdmFibGUsXG4gIHF1ZXJ5OiBUcmFja0xpa2UsXG4gIG9wdGlvbnM6IFBsYXllck5vZGVJbml0aWFsaXplck9wdGlvbnM8VD4gPSB7fSlcbiAgOiBQcm9taXNlPFBsYXllck5vZGVJbml0aWFsaXphdGlvblJlc3VsdDxUPj4ge1xuICAgIGNvbnN0IHZjID0gdGhpcy5jbGllbnQuY2hhbm5lbHMucmVzb2x2ZShjaGFubmVsKTtcbiAgICBpZiAoIXZjPy5pc1ZvaWNlQmFzZWQoKSlcbiAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ1R5cGVFcnJvcihcbiAgICAgICdjaGFubmVsJyxcbiAgICAgICdWb2ljZUJhc2VkQ2hhbm5lbCcsXG4gICAgICAhdmMgPyAndW5kZWZpbmVkJyA6IGBjaGFubmVsIHR5cGUgJHt2Yy50eXBlfWBcbiAgICApO1xuXG4gICAgY29uc3Qgb3JpZ2luYWxSZXN1bHQgPVxuICAgIHF1ZXJ5IGluc3RhbmNlb2YgU2VhcmNoUmVzdWx0ID8gcXVlcnkgOiBhd2FpdCB0aGlzLnNlYXJjaChxdWVyeSwgb3B0aW9ucyk7XG4gICAgY29uc3QgcmVzdWx0ID1cbiAgICAoYXdhaXQgb3B0aW9ucy5hZnRlclNlYXJjaD8uKG9yaWdpbmFsUmVzdWx0KSkgfHwgb3JpZ2luYWxSZXN1bHQ7XG4gICAgaWYgKHJlc3VsdC5pc0VtcHR5KCkpIHtcbiAgICAgIHRocm93IG5ldyBOb1Jlc3VsdEVycm9yKFxuICAgICAgICBgTm8gcmVzdWx0cyBmb3VuZCBmb3IgXCIke3F1ZXJ5fVwiIChFeHRyYWN0b3I6ICR7XG4gICAgICAgIHJlc3VsdC5leHRyYWN0b3I/LmlkZW50aWZpZXIgfHwgJ04vQSd9KWBcblxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBxdWV1ZSA9IHRoaXMubm9kZXMuY3JlYXRlKHZjLmd1aWxkLCBvcHRpb25zLm5vZGVPcHRpb25zKTtcblxuICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKSB0aGlzLmRlYnVnKGBbQXN5bmNRdWV1ZV0gQWNxdWlyaW5nIGFuIGVudHJ5Li4uYCk7XG4gICAgY29uc3QgZW50cnkgPSBxdWV1ZS50YXNrc1F1ZXVlLmFjcXVpcmUoeyBzaWduYWw6IG9wdGlvbnMuc2lnbmFsIH0pO1xuICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgIHRoaXMuZGVidWcoYFtBc3luY1F1ZXVlXSBFbnRyeSAke2VudHJ5LmlkfSB3YXMgYWNxdWlyZWQgc3VjY2Vzc2Z1bGx5IWApO1xuXG4gICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgdGhpcy5kZWJ1ZyhgW0FzeW5jUXVldWVdIFdhaXRpbmcgZm9yIHRoZSBxdWV1ZSB0byByZXNvbHZlLi4uYCk7XG4gICAgYXdhaXQgZW50cnkuZ2V0VGFzaygpO1xuICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgIHRoaXMuZGVidWcoYFtBc3luY1F1ZXVlXSBFbnRyeSAke2VudHJ5LmlkfSB3YXMgcmVzb2x2ZWQhYCk7XG5cbiAgICB0cnkge1xuICAgICAgaWYgKCFxdWV1ZS5jaGFubmVsKSBhd2FpdCBxdWV1ZS5jb25uZWN0KHZjLCBvcHRpb25zLmNvbm5lY3Rpb25PcHRpb25zKTtcblxuICAgICAgaWYgKCFyZXN1bHQucGxheWxpc3QpIHtcbiAgICAgICAgcXVldWUuYWRkVHJhY2socmVzdWx0LnRyYWNrc1swXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBxdWV1ZS5hZGRUcmFjayhyZXN1bHQucGxheWxpc3QpO1xuICAgICAgfVxuICAgICAgaWYgKCFxdWV1ZS5pc1BsYXlpbmcoKSlcbiAgICAgIGF3YWl0IHF1ZXVlLm5vZGUucGxheShudWxsLCBvcHRpb25zLmF1ZGlvUGxheWVyT3B0aW9ucyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgdGhpcy5kZWJ1ZyhgW0FzeW5jUXVldWVdIFJlbGVhc2luZyBhbiBlbnRyeSBmcm9tIHRoZSBxdWV1ZS4uLmApO1xuICAgICAgcXVldWUudGFza3NRdWV1ZS5yZWxlYXNlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRyYWNrOiByZXN1bHQudHJhY2tzWzBdLFxuICAgICAgZXh0cmFjdG9yOiByZXN1bHQuZXh0cmFjdG9yLFxuICAgICAgc2VhcmNoUmVzdWx0OiByZXN1bHQsXG4gICAgICBxdWV1ZVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogU2VhcmNoIHRyYWNrc1xuICAgKiBAcGFyYW0ge3N0cmluZyB8IFRyYWNrIHwgVHJhY2tbXSB8IFBsYXlsaXN0IHwgU2VhcmNoUmVzdWx0fSBxdWVyeSBUaGUgc2VhcmNoIHF1ZXJ5XG4gICAqIEBwYXJhbSB7U2VhcmNoT3B0aW9uc30gb3B0aW9ucyBUaGUgc2VhcmNoIG9wdGlvbnNcbiAgICogQHJldHVybnMge1Byb21pc2U8U2VhcmNoUmVzdWx0Pn1cbiAgICogQGV4YW1wbGUgYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBzZWFyY2hRdWVyeSA9ICdwYXNzIHVybCBvciB0ZXh0IG9yIGRpc2NvcmQtcGxheWVyIHRyYWNrIGNvbnN0cnVjdGFibGUgb2JqZWN0cywgd2UgZ290IHlvdSBjb3ZlcmVkIFx1RDgzRFx1REUwRSc7XG4gICAqIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBsYXllci5zZWFyY2goc2VhcmNoUXVlcnkpO1xuICAgKlxuICAgKiBjb25zb2xlLmxvZyhyZXN1bHQpOyAvLyBMb2dzIGBTZWFyY2hSZXN1bHRgIG9iamVjdFxuICAgKiBgYGBcbiAgICovXG4gIHB1YmxpYyBhc3luYyBzZWFyY2goXG4gIHNlYXJjaFF1ZXJ5OiBUcmFja0xpa2UsXG4gIG9wdGlvbnM6IFNlYXJjaE9wdGlvbnMgPSB7fSlcbiAgOiBQcm9taXNlPFNlYXJjaFJlc3VsdD4ge1xuICAgIGlmIChzZWFyY2hRdWVyeSBpbnN0YW5jZW9mIFNlYXJjaFJlc3VsdCkgcmV0dXJuIHNlYXJjaFF1ZXJ5O1xuXG4gICAgaWYgKHNlYXJjaFF1ZXJ5IGluc3RhbmNlb2YgQXVkaW9SZXNvdXJjZSkge1xuICAgICAgc2VhcmNoUXVlcnkgPSB0aGlzLmNyZWF0ZVRyYWNrRnJvbUF1ZGlvUmVzb3VyY2Uoc2VhcmNoUXVlcnkpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLnJlcXVlc3RlZEJ5ICE9IG51bGwpXG4gICAgb3B0aW9ucy5yZXF1ZXN0ZWRCeSA9IHRoaXMuY2xpZW50LnVzZXJzLnJlc29sdmUob3B0aW9ucy5yZXF1ZXN0ZWRCeSkhO1xuXG4gICAgb3B0aW9ucy5ibG9ja0V4dHJhY3RvcnMgPz89IHRoaXMub3B0aW9ucy5ibG9ja0V4dHJhY3RvcnM7XG4gICAgb3B0aW9ucy5mYWxsYmFja1NlYXJjaEVuZ2luZSA/Pz0gUXVlcnlUeXBlLkFVVE9fU0VBUkNIO1xuXG4gICAgaWYgKHNlYXJjaFF1ZXJ5IGluc3RhbmNlb2YgVHJhY2spIHtcbiAgICAgIHJldHVybiBuZXcgU2VhcmNoUmVzdWx0KHRoaXMsIHtcbiAgICAgICAgcGxheWxpc3Q6IHNlYXJjaFF1ZXJ5LnBsYXlsaXN0IHx8IG51bGwsXG4gICAgICAgIHRyYWNrczogW3NlYXJjaFF1ZXJ5XSxcbiAgICAgICAgcXVlcnk6IHNlYXJjaFF1ZXJ5LnRpdGxlLFxuICAgICAgICBleHRyYWN0b3I6IHNlYXJjaFF1ZXJ5LmV4dHJhY3RvcixcbiAgICAgICAgcXVlcnlUeXBlOiBzZWFyY2hRdWVyeS5xdWVyeVR5cGUsXG4gICAgICAgIHJlcXVlc3RlZEJ5OiBvcHRpb25zLnJlcXVlc3RlZEJ5XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoc2VhcmNoUXVlcnkgaW5zdGFuY2VvZiBQbGF5bGlzdCkge1xuICAgICAgcmV0dXJuIG5ldyBTZWFyY2hSZXN1bHQodGhpcywge1xuICAgICAgICBwbGF5bGlzdDogc2VhcmNoUXVlcnksXG4gICAgICAgIHRyYWNrczogc2VhcmNoUXVlcnkudHJhY2tzLFxuICAgICAgICBxdWVyeTogc2VhcmNoUXVlcnkudGl0bGUsXG4gICAgICAgIGV4dHJhY3Rvcjogc2VhcmNoUXVlcnkudHJhY2tzWzBdPy5leHRyYWN0b3IsXG4gICAgICAgIHF1ZXJ5VHlwZTogUXVlcnlUeXBlLkFVVE8sXG4gICAgICAgIHJlcXVlc3RlZEJ5OiBvcHRpb25zLnJlcXVlc3RlZEJ5XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShzZWFyY2hRdWVyeSkpIHtcbiAgICAgIGNvbnN0IHRyYWNrcyA9IHNlYXJjaFF1ZXJ5LmZpbHRlcigodCkgPT4gdCBpbnN0YW5jZW9mIFRyYWNrKTtcbiAgICAgIHJldHVybiBuZXcgU2VhcmNoUmVzdWx0KHRoaXMsIHtcbiAgICAgICAgcGxheWxpc3Q6IG51bGwsXG4gICAgICAgIHRyYWNrcyxcbiAgICAgICAgcXVlcnk6ICdAQCMle3tVc2VyTG9hZGVkQ29udGVudH19JSNAQCcsXG4gICAgICAgIGV4dHJhY3RvcjogbnVsbCxcbiAgICAgICAgcXVlcnlUeXBlOiBRdWVyeVR5cGUuQVVUTyxcbiAgICAgICAgcmVxdWVzdGVkQnk6IG9wdGlvbnMucmVxdWVzdGVkQnlcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKSB0aGlzLmRlYnVnKGBTZWFyY2hpbmcgJHtzZWFyY2hRdWVyeX1gKTtcblxuICAgIGxldCBleHRyYWN0b3I6IEJhc2VFeHRyYWN0b3IgfCBudWxsID0gbnVsbCxcbiAgICAgIHByb3RvY29sOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIG9wdGlvbnMuc2VhcmNoRW5naW5lID8/PSBRdWVyeVR5cGUuQVVUTztcbiAgICBvcHRpb25zLmZhbGxiYWNrU2VhcmNoRW5naW5lID8/PSBRdWVyeVR5cGUuQVVUT19TRUFSQ0g7XG5cbiAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLmRlYnVnKFxuICAgICAgYFNlYXJjaCBlbmdpbmUgc2V0IHRvICR7b3B0aW9ucy5zZWFyY2hFbmdpbmV9LCBmYWxsYmFjayBzZWFyY2ggZW5naW5lIHNldCB0byAke29wdGlvbnMuZmFsbGJhY2tTZWFyY2hFbmdpbmV9YFxuICAgICk7XG5cbiAgICBpZiAoL15cXHcrOi8udGVzdChzZWFyY2hRdWVyeSkpIHtcbiAgICAgIGNvbnN0IFtwcm90b2NvbE5hbWUsIC4uLnF1ZXJ5XSA9IHNlYXJjaFF1ZXJ5LnNwbGl0KCc6Jyk7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMuZGVidWcoYFByb3RvY29sICR7cHJvdG9jb2xOYW1lfSBkZXRlY3RlZCBpbiBxdWVyeWApO1xuXG4gICAgICBjb25zdCBtYXRjaGluZ0V4dHJhY3RvciA9IHRoaXMuZXh0cmFjdG9ycy5zdG9yZS5maW5kKFxuICAgICAgICAoZSkgPT5cbiAgICAgICAgIXRoaXMuZXh0cmFjdG9ycy5pc0Rpc2FibGVkKGUuaWRlbnRpZmllcikgJiZcbiAgICAgICAgZS5wcm90b2NvbHMuaW5jbHVkZXMocHJvdG9jb2xOYW1lKVxuICAgICAgKTtcblxuICAgICAgaWYgKG1hdGNoaW5nRXh0cmFjdG9yKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgICB0aGlzLmRlYnVnKFxuICAgICAgICAgIGBQcm90b2NvbCAke3Byb3RvY29sTmFtZX0gaXMgc3VwcG9ydGVkIGJ5ICR7bWF0Y2hpbmdFeHRyYWN0b3IuaWRlbnRpZmllcn0gZXh0cmFjdG9yIWBcbiAgICAgICAgKTtcbiAgICAgICAgZXh0cmFjdG9yID0gbWF0Y2hpbmdFeHRyYWN0b3I7XG4gICAgICAgIHNlYXJjaFF1ZXJ5ID0gcXVlcnkuam9pbignOicpO1xuICAgICAgICBwcm90b2NvbCA9IHByb3RvY29sTmFtZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgICAgICB0aGlzLmRlYnVnKFxuICAgICAgICAgIGBDb3VsZCBub3QgZmluZCBhbiBleHRyYWN0b3IgdGhhdCBzdXBwb3J0cyAke3Byb3RvY29sTmFtZX0gcHJvdG9jb2wuIEZhbGxpbmcgYmFjayB0byBkZWZhdWx0IGJlaGF2aW9yLi4uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHJlZGlyZWN0ZWQgPSBhd2FpdCBRdWVyeVJlc29sdmVyLnByZVJlc29sdmUoc2VhcmNoUXVlcnkpO1xuICAgIGNvbnN0IHsgdHlwZTogcXVlcnlUeXBlLCBxdWVyeSB9ID1cbiAgICBvcHRpb25zLnNlYXJjaEVuZ2luZSA9PT0gUXVlcnlUeXBlLkFVVE8gP1xuICAgIFF1ZXJ5UmVzb2x2ZXIucmVzb2x2ZShyZWRpcmVjdGVkLCBvcHRpb25zLmZhbGxiYWNrU2VhcmNoRW5naW5lKSA6XG4gICAgeyB0eXBlOiBvcHRpb25zLnNlYXJjaEVuZ2luZSwgcXVlcnk6IHJlZGlyZWN0ZWQgfSBhcyBSZXNvbHZlZFF1ZXJ5O1xuXG4gICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgdGhpcy5kZWJ1ZyhcbiAgICAgIGBRdWVyeSB0eXBlIGlkZW50aWZpZWQgYXMgJHtxdWVyeVR5cGV9JHtcbiAgICAgIGV4dHJhY3RvciAmJiBwcm90b2NvbCA/XG4gICAgICAnIGJ1dCBtaWdodCBub3QgYmUgdXNlZCBkdWUgdG8gdGhlIHByZXNlbmNlIG9mIHByb3RvY29sJyA6XG4gICAgICAnJ31gXG5cbiAgICApO1xuXG4gICAgLy8gZm9yY2UgcGFydGljdWxhciBleHRyYWN0b3JcbiAgICBpZiAob3B0aW9ucy5zZWFyY2hFbmdpbmUuc3RhcnRzV2l0aCgnZXh0OicpKSB7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMuZGVidWcoYEZvcmNpbmcgJHtvcHRpb25zLnNlYXJjaEVuZ2luZS5zdWJzdHJpbmcoNCl9IGV4dHJhY3Rvci4uLmApO1xuICAgICAgZXh0cmFjdG9yID0gdGhpcy5leHRyYWN0b3JzLmdldChvcHRpb25zLnNlYXJjaEVuZ2luZS5zdWJzdHJpbmcoNCkpITtcbiAgICAgIGlmICghZXh0cmFjdG9yKVxuICAgICAgcmV0dXJuIG5ldyBTZWFyY2hSZXN1bHQodGhpcywge1xuICAgICAgICBxdWVyeSxcbiAgICAgICAgcXVlcnlUeXBlLFxuICAgICAgICBleHRyYWN0b3IsXG4gICAgICAgIHJlcXVlc3RlZEJ5OiBvcHRpb25zLnJlcXVlc3RlZEJ5XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBxdWVyeSBhbGwgZXh0cmFjdG9yc1xuICAgIGlmICghZXh0cmFjdG9yKSB7XG4gICAgICAvLyBjYWNoZSB2YWxpZGF0aW9uXG4gICAgICBpZiAoIW9wdGlvbnMuaWdub3JlQ2FjaGUpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpIHRoaXMuZGVidWcoYENoZWNraW5nIGNhY2hlLi4uYCk7XG4gICAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHRoaXMucXVlcnlDYWNoZT8ucmVzb2x2ZSh7XG4gICAgICAgICAgcXVlcnksXG4gICAgICAgICAgcXVlcnlUeXBlLFxuICAgICAgICAgIHJlcXVlc3RlZEJ5OiBvcHRpb25zLnJlcXVlc3RlZEJ5XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBjYWNoZSBoaXRcbiAgICAgICAgaWYgKHJlcz8uaGFzVHJhY2tzKCkpIHtcbiAgICAgICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcikgdGhpcy5kZWJ1ZyhgQ2FjaGUgaGl0IGZvciBxdWVyeSAke3F1ZXJ5fWApO1xuICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcikgdGhpcy5kZWJ1ZyhgQ2FjaGUgbWlzcyBmb3IgcXVlcnkgJHtxdWVyeX1gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpIHRoaXMuZGVidWcoYEV4ZWN1dGluZyBleHRyYWN0b3JzLi4uYCk7XG5cbiAgICAgIC8vIGNhY2hlIG1pc3NcbiAgICAgIGV4dHJhY3RvciA9XG4gICAgICAoXG4gICAgICBhd2FpdCB0aGlzLmV4dHJhY3RvcnMucnVuKGFzeW5jIChleHQpID0+IHtcbiAgICAgICAgaWYgKG9wdGlvbnMuYmxvY2tFeHRyYWN0b3JzPy5pbmNsdWRlcyhleHQuaWRlbnRpZmllcikpIHJldHVybiBmYWxzZTtcbiAgICAgICAgcmV0dXJuIGV4dC52YWxpZGF0ZShxdWVyeSwgcXVlcnlUeXBlIGFzIFNlYXJjaFF1ZXJ5VHlwZSk7XG4gICAgICB9KSk/LlxuICAgICAgZXh0cmFjdG9yIHx8IG51bGw7XG4gICAgfVxuXG4gICAgLy8gbm8gZXh0cmFjdG9ycyBhdmFpbGFibGVcbiAgICBpZiAoIWV4dHJhY3Rvcikge1xuICAgICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpIHRoaXMuZGVidWcoJ0ZhaWxlZCB0byBmaW5kIGFwcHJvcHJpYXRlIGV4dHJhY3RvcicpO1xuICAgICAgcmV0dXJuIG5ldyBTZWFyY2hSZXN1bHQodGhpcywge1xuICAgICAgICBxdWVyeSxcbiAgICAgICAgcXVlcnlUeXBlLFxuICAgICAgICByZXF1ZXN0ZWRCeTogb3B0aW9ucy5yZXF1ZXN0ZWRCeVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaGFzRGVidWdnZXIpXG4gICAgdGhpcy5kZWJ1ZyhcbiAgICAgIGBFeGVjdXRpbmcgbWV0YWRhdGEgcXVlcnkgdXNpbmcgJHtleHRyYWN0b3IuaWRlbnRpZmllcn0gZXh0cmFjdG9yLi4uYFxuICAgICk7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgZXh0cmFjdG9yLlxuICAgIGhhbmRsZShxdWVyeSwge1xuICAgICAgdHlwZTogcXVlcnlUeXBlIGFzIFNlYXJjaFF1ZXJ5VHlwZSxcbiAgICAgIHJlcXVlc3RlZEJ5OiBvcHRpb25zLnJlcXVlc3RlZEJ5IGFzIFVzZXIsXG4gICAgICByZXF1ZXN0T3B0aW9uczogb3B0aW9ucy5yZXF1ZXN0T3B0aW9ucyxcbiAgICAgIHByb3RvY29sXG4gICAgfSkuXG4gICAgY2F0Y2goKCkgPT4gbnVsbCk7XG5cbiAgICBpZiAocmVzKSB7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcikgdGhpcy5kZWJ1ZygnTWV0YWRhdGEgcXVlcnkgd2FzIHN1Y2Nlc3NmdWwhJyk7XG4gICAgICAvLyBTdG9yZSBSZXF1ZXN0T3B0aW9ucyBpbiB0cmFjayByYXcgZGF0YSBmb3IgbGF0ZXIgdXNlIGR1cmluZyBzdHJlYW1pbmdcbiAgICAgIGlmIChvcHRpb25zLnJlcXVlc3RPcHRpb25zICYmIHJlcy50cmFja3MpIHtcbiAgICAgICAgcmVzLnRyYWNrcy5mb3JFYWNoKCh0cmFjaykgPT4ge1xuICAgICAgICAgIGlmICh0cmFjay5yYXcpIHtcbiAgICAgICAgICAgIHRyYWNrLnJhdy5yZXF1ZXN0T3B0aW9ucyA9IG9wdGlvbnMucmVxdWVzdE9wdGlvbnM7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyYWNrLnJhdyA9IHsgcmVxdWVzdE9wdGlvbnM6IG9wdGlvbnMucmVxdWVzdE9wdGlvbnMgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCByZXN1bHQgPSBuZXcgU2VhcmNoUmVzdWx0KHRoaXMsIHtcbiAgICAgICAgcXVlcnksXG4gICAgICAgIHF1ZXJ5VHlwZSxcbiAgICAgICAgcGxheWxpc3Q6IHJlcy5wbGF5bGlzdCxcbiAgICAgICAgdHJhY2tzOiByZXMudHJhY2tzLFxuICAgICAgICBleHRyYWN0b3IsXG4gICAgICAgIHJlcXVlc3RlZEJ5OiBvcHRpb25zLnJlcXVlc3RlZEJ5XG4gICAgICB9KTtcblxuICAgICAgaWYgKCFvcHRpb25zLmlnbm9yZUNhY2hlKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKSB0aGlzLmRlYnVnKGBBZGRpbmcgZGF0YSB0byBjYWNoZS4uLmApO1xuICAgICAgICBhd2FpdCB0aGlzLnF1ZXJ5Q2FjaGU/LmFkZERhdGEocmVzdWx0KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICB0aGlzLmRlYnVnKFxuICAgICAgJ0ZhaWxlZCB0byBmaW5kIHJlc3VsdCB1c2luZyBhcHByb3ByaWF0ZSBleHRyYWN0b3IuIFF1ZXJ5aW5nIGFsbCBleHRyYWN0b3JzLi4uJ1xuICAgICk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5leHRyYWN0b3JzLnJ1bihcbiAgICAgIGFzeW5jIChleHQpID0+XG4gICAgICAhb3B0aW9ucy5ibG9ja0V4dHJhY3RvcnM/LmluY2x1ZGVzKGV4dC5pZGVudGlmaWVyKSAmJiAoXG4gICAgICBhd2FpdCBleHQudmFsaWRhdGUocXVlcnkpKSAmJlxuICAgICAgZXh0LmhhbmRsZShxdWVyeSwge1xuICAgICAgICB0eXBlOiBxdWVyeVR5cGUgYXMgU2VhcmNoUXVlcnlUeXBlLFxuICAgICAgICByZXF1ZXN0ZWRCeTogb3B0aW9ucy5yZXF1ZXN0ZWRCeSBhcyBVc2VyLFxuICAgICAgICByZXF1ZXN0T3B0aW9uczogb3B0aW9ucy5yZXF1ZXN0T3B0aW9ucyxcbiAgICAgICAgcHJvdG9jb2xcbiAgICAgIH0pXG4gICAgKTtcbiAgICBpZiAoIXJlc3VsdD8ucmVzdWx0KSB7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcilcbiAgICAgIHRoaXMuZGVidWcoXG4gICAgICAgIGBGYWlsZWQgdG8gcXVlcnkgbWV0YWRhdGEgcXVlcnkgdXNpbmcgJHtcbiAgICAgICAgcmVzdWx0Py5leHRyYWN0b3IuaWRlbnRpZmllciB8fCAnTi9BJ30gZXh0cmFjdG9yLmBcblxuICAgICAgKTtcbiAgICAgIHJldHVybiBuZXcgU2VhcmNoUmVzdWx0KHRoaXMsIHtcbiAgICAgICAgcXVlcnksXG4gICAgICAgIHF1ZXJ5VHlwZSxcbiAgICAgICAgcmVxdWVzdGVkQnk6IG9wdGlvbnMucmVxdWVzdGVkQnksXG4gICAgICAgIGV4dHJhY3RvcjogcmVzdWx0Py5leHRyYWN0b3JcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc0RlYnVnZ2VyKVxuICAgIHRoaXMuZGVidWcoXG4gICAgICBgTWV0YWRhdGEgcXVlcnkgd2FzIHN1Y2Nlc3NmdWwgdXNpbmcgJHtyZXN1bHQuZXh0cmFjdG9yLmlkZW50aWZpZXJ9IWBcbiAgICApO1xuXG4gICAgLy8gU3RvcmUgUmVxdWVzdE9wdGlvbnMgaW4gdHJhY2sgcmF3IGRhdGEgZm9yIGxhdGVyIHVzZSBkdXJpbmcgc3RyZWFtaW5nXG4gICAgaWYgKG9wdGlvbnMucmVxdWVzdE9wdGlvbnMgJiYgcmVzdWx0LnJlc3VsdC50cmFja3MpIHtcbiAgICAgIHJlc3VsdC5yZXN1bHQudHJhY2tzLmZvckVhY2goKHRyYWNrKSA9PiB7XG4gICAgICAgIGlmICh0cmFjay5yYXcpIHtcbiAgICAgICAgICB0cmFjay5yYXcucmVxdWVzdE9wdGlvbnMgPSBvcHRpb25zLnJlcXVlc3RPcHRpb25zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRyYWNrLnJhdyA9IHsgcmVxdWVzdE9wdGlvbnM6IG9wdGlvbnMucmVxdWVzdE9wdGlvbnMgfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IG5ldyBTZWFyY2hSZXN1bHQodGhpcywge1xuICAgICAgcXVlcnksXG4gICAgICBxdWVyeVR5cGUsXG4gICAgICBwbGF5bGlzdDogcmVzdWx0LnJlc3VsdC5wbGF5bGlzdCxcbiAgICAgIHRyYWNrczogcmVzdWx0LnJlc3VsdC50cmFja3MsXG4gICAgICBleHRyYWN0b3I6IHJlc3VsdC5leHRyYWN0b3IsXG4gICAgICByZXF1ZXN0ZWRCeTogb3B0aW9ucy5yZXF1ZXN0ZWRCeVxuICAgIH0pO1xuXG4gICAgaWYgKCFvcHRpb25zLmlnbm9yZUNhY2hlKSB7XG4gICAgICBpZiAodGhpcy5oYXNEZWJ1Z2dlcikgdGhpcy5kZWJ1ZyhgQWRkaW5nIGRhdGEgdG8gY2FjaGUuLi5gKTtcbiAgICAgIGF3YWl0IHRoaXMucXVlcnlDYWNoZT8uYWRkRGF0YShkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSByZXBvcnQgb2YgdGhlIGRlcGVuZGVuY2llcyB1c2VkIGJ5IHRoZSBgZGlzY29yZC12b2lwYCBtb2R1bGUuIFVzZWZ1bCBmb3IgZGVidWdnaW5nLlxuICAgKiBAZXhhbXBsZSBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnNvbGUubG9nKHBsYXllci5zY2FuRGVwcygpKTtcbiAgICogLy8gLT4gbG9ncyBkZXBlbmRlbmNpZXMgcmVwb3J0XG4gICAqIGBgYFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgcHVibGljIHNjYW5EZXBzKCkge1xuICAgIGNvbnN0IGxpbmUgPSAnLScucmVwZWF0KDUwKTtcbiAgICBjb25zdCBydW50aW1lID1cbiAgICAnQnVuJyBpbiBnbG9iYWxUaGlzID8gJ0J1bicgOiAnRGVubycgaW4gZ2xvYmFsVGhpcyA/ICdEZW5vJyA6ICdOb2RlJztcbiAgICBjb25zdCBkZXBzUmVwb3J0ID0gW1xuICAgICdEaXNjb3JkIFBsYXllcicsXG4gICAgbGluZSxcbiAgICBgLSBkaXNjb3JkLXBsYXllcjogJHtQbGF5ZXIudmVyc2lvbn0ke1xuICAgIHRoaXMuaXNDb21wYXRNb2RlKCkgP1xuICAgIGAgKCR7Z2V0Q29tcGF0TmFtZSh0aGlzLmNsaWVudCl9IGNvbXBhdGliaWxpdHkgbW9kZSlgIDpcbiAgICAnJ31gLFxuXG4gICAgYC0gZGlzY29yZC12b2lwOiAke2RWb2ljZVZlcnNpb259YCxcbiAgICBgLSBkaXNjb3JkLmpzOiAke2Rqc1ZlcnNpb259YCxcbiAgICBgLSBOb2RlIHZlcnNpb246ICR7cHJvY2Vzcy52ZXJzaW9ufSAoRGV0ZWN0ZWQgUnVudGltZTogJHtydW50aW1lfSwgUGxhdGZvcm06ICR7cHJvY2Vzcy5wbGF0Zm9ybX0gWyR7cHJvY2Vzcy5hcmNofV0pYCxcbiAgICAoKCkgPT4ge1xuICAgICAgY29uc3QgaW5mbyA9IEZGbXBlZy5yZXNvbHZlU2FmZSgpO1xuICAgICAgaWYgKCFpbmZvKSByZXR1cm4gJ0ZGbXBlZy9BdmNvbnYgbm90IGZvdW5kJztcblxuICAgICAgcmV0dXJuIFtcbiAgICAgIGAtIGZmbXBlZzogJHtpbmZvLnZlcnNpb259YCxcbiAgICAgIGAtIGNvbW1hbmQ6ICR7aW5mby5jb21tYW5kfWAsXG4gICAgICBgLSBzdGF0aWM6ICR7aW5mby5tb2R1bGV9YCxcbiAgICAgIGAtIGxpYm9wdXM6ICR7aW5mby5yZXN1bHQhLmluY2x1ZGVzKCctLWVuYWJsZS1saWJvcHVzJyl9YF0uXG4gICAgICBqb2luKCdcXG4nKTtcbiAgICB9KSgpLFxuICAgICdcXG4nLFxuICAgICdMb2FkZWQgRXh0cmFjdG9yczonLFxuICAgIGxpbmUsXG4gICAgdGhpcy5leHRyYWN0b3JzLnN0b3JlLlxuICAgIG1hcCgobSkgPT4ge1xuICAgICAgcmV0dXJuIG0uaWRlbnRpZmllcjtcbiAgICB9KS5cbiAgICBqb2luKCdcXG4nKSB8fCAnTi9BJyxcbiAgICAnXFxuXFxuZGlzY29yZC12b2lwJyxcbiAgICBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yLmdlbmVyYXRlU3RyaW5nKCldO1xuXG5cbiAgICByZXR1cm4gZGVwc1JlcG9ydC5qb2luKCdcXG4nKTtcbiAgfVxuXG4gIHB1YmxpYyAqW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgeWllbGQqIHRoaXMubm9kZXMuY2FjaGUudmFsdWVzKCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBgUGxheWxpc3RgIGluc3RhbmNlXG4gICAqIEBwYXJhbSBkYXRhIFRoZSBkYXRhIHRvIGluaXRpYWxpemUgYSBwbGF5bGlzdFxuICAgKi9cbiAgcHVibGljIGNyZWF0ZVBsYXlsaXN0KGRhdGE6IFBsYXlsaXN0SW5pdERhdGEpIHtcbiAgICByZXR1cm4gbmV3IFBsYXlsaXN0KHRoaXMsIGRhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSB0cmFjayBmcm9tIGFuIGF1ZGlvIHJlc291cmNlLlxuICAgKiBAcGFyYW0gcmVzb3VyY2UgVGhlIGF1ZGlvIHJlc291cmNlXG4gICAqL1xuICBwdWJsaWMgY3JlYXRlVHJhY2tGcm9tQXVkaW9SZXNvdXJjZShyZXNvdXJjZTogQXVkaW9SZXNvdXJjZSkge1xuICAgIGNvbnN0IG1ldGFkYXRhID0gKHJlc291cmNlLm1ldGFkYXRhIHx8IHt9KSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBjb25zdCByZWYgPSBTbm93Zmxha2VVdGlsLmdlbmVyYXRlKCkudG9TdHJpbmcoKTtcbiAgICBjb25zdCBtYXliZVRpdGxlID1cbiAgICAndGl0bGUnIGluIG1ldGFkYXRhID8gYCR7bWV0YWRhdGEudGl0bGV9YCA6IGBUcmFjayAke3JlZn1gO1xuICAgIGNvbnN0IG1heWJlQXV0aG9yID1cbiAgICAnYXV0aG9yJyBpbiBtZXRhZGF0YSA/IGAke21ldGFkYXRhLmF1dGhvcn1gIDogJ1Vua25vd24gYXV0aG9yJztcbiAgICBjb25zdCBtYXliZUR1cmF0aW9uID1cbiAgICAnZHVyYXRpb24nIGluIG1ldGFkYXRhID8gYCR7bWV0YWRhdGEuZHVyYXRpb259YCA6ICcwMDowMCc7XG4gICAgY29uc3QgbWF5YmVUaHVtYm5haWwgPVxuICAgICd0aHVtYm5haWwnIGluIG1ldGFkYXRhID8gYCR7bWV0YWRhdGEudGh1bWJuYWlsfWAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgbWF5YmVVUkwgPVxuICAgICd1cmwnIGluIG1ldGFkYXRhID8gYCR7bWV0YWRhdGEudXJsfWAgOiBgZGlzY29yZC1wbGF5ZXI6Ly9ibG9iLyR7cmVmfWA7XG4gICAgY29uc3QgbWF5YmVEZXNjcmlwdGlvbiA9XG4gICAgJ2Rlc2NyaXB0aW9uJyBpbiBtZXRhZGF0YSA/XG4gICAgYCR7bWV0YWRhdGEuZGVzY3JpcHRpb259YCA6XG4gICAgJ05vIGRlc2NyaXB0aW9uIGF2YWlsYWJsZS4nO1xuICAgIGNvbnN0IG1heWJlVmlld3MgPSAndmlld3MnIGluIG1ldGFkYXRhID8gTnVtYmVyKG1ldGFkYXRhLnZpZXdzKSB8fCAwIDogMDtcblxuICAgIGNvbnN0IHRyYWNrID0gbmV3IFRyYWNrKHRoaXMsIHtcbiAgICAgIHRpdGxlOiBtYXliZVRpdGxlLFxuICAgICAgYXV0aG9yOiBtYXliZUF1dGhvcixcbiAgICAgIGR1cmF0aW9uOiBtYXliZUR1cmF0aW9uLFxuICAgICAgdGh1bWJuYWlsOiBtYXliZVRodW1ibmFpbCxcbiAgICAgIHVybDogbWF5YmVVUkwsXG4gICAgICBkZXNjcmlwdGlvbjogbWF5YmVEZXNjcmlwdGlvbixcbiAgICAgIHF1ZXJ5VHlwZTogUXVlcnlUeXBlLkRJU0NPUkRfUExBWUVSX0JMT0IsXG4gICAgICBzb3VyY2U6ICdhcmJpdHJhcnknLFxuICAgICAgbWV0YWRhdGEsXG4gICAgICBsaXZlOiBmYWxzZSxcbiAgICAgIHZpZXdzOiBtYXliZVZpZXdzXG4gICAgfSk7XG5cbiAgICByZXNvdXJjZS5tZXRhZGF0YSA9IHRyYWNrO1xuXG4gICAgdHJhY2suc2V0UmVzb3VyY2UocmVzb3VyY2UgYXMgQXVkaW9SZXNvdXJjZTxUcmFjaz4pO1xuXG4gICAgcmV0dXJuIHRyYWNrO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgaW50ZXJjZXB0aW5nIHN0cmVhbXNcbiAgICogQHBhcmFtIHN0cmVhbSBUaGUgc3RyZWFtIHRvIGludGVyY2VwdFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGhhbmRsZUludGVyY2VwdGluZ1N0cmVhbShcbiAgcXVldWU6IEd1aWxkUXVldWUsXG4gIHRyYWNrOiBUcmFjayxcbiAgZm9ybWF0OiBTdHJlYW1UeXBlLFxuICBzdHJlYW06IEludGVyY2VwdGVkU3RyZWFtKVxuICB7XG4gICAgaWYgKCF0aGlzLiNzdHJlYW1JbnRlcmNlcHRvcikgcmV0dXJuO1xuXG4gICAgcmV0dXJuIHRoaXMuI3N0cmVhbUludGVyY2VwdG9yLmhhbmRsZShxdWV1ZSwgdHJhY2ssIGZvcm1hdCwgc3RyZWFtKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgZ2xvYmFsIHN0cmVhbSBpbnRlcmNlcHRvclxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgc3RyZWFtIGludGVyY2VwdG9yIG9wdGlvbnNcbiAgICovXG4gIHB1YmxpYyBjcmVhdGVTdHJlYW1JbnRlcmNlcHRvcihvcHRpb25zOiBQbGF5ZXJTdHJlYW1JbnRlcmNlcHRvck9wdGlvbnMpIHtcbiAgICBpZiAodGhpcy4jc3RyZWFtSW50ZXJjZXB0b3IpIHtcbiAgICAgIHJldHVybiB0aGlzLiNzdHJlYW1JbnRlcmNlcHRvcjtcbiAgICB9XG5cbiAgICB0aGlzLiNzdHJlYW1JbnRlcmNlcHRvciA9IG5ldyBQbGF5ZXJTdHJlYW1JbnRlcmNlcHRvcih0aGlzLCBvcHRpb25zKTtcblxuICAgIHJldHVybiB0aGlzLiNzdHJlYW1JbnRlcmNlcHRvcjtcbiAgfVxufSIsICJpbXBvcnQgeyBDaGFubmVsVHlwZSwgVm9pY2VTdGF0ZSB9IGZyb20gJ2Rpc2NvcmQuanMnO1xuaW1wb3J0IHsgR3VpbGRRdWV1ZSwgR3VpbGRRdWV1ZUV2ZW50IH0gZnJvbSAnLi9xdWV1ZSc7XG5pbXBvcnQgeyBQbGF5ZXIgfSBmcm9tICcuL1BsYXllcic7XG5pbXBvcnQgeyBVdGlsIH0gZnJvbSAnLi91dGlscy9VdGlsJztcblxuZnVuY3Rpb24gaGFuZGxlRW1wdHlDaGFubmVsKFxucGxheWVyOiBQbGF5ZXIsXG5xdWV1ZTogR3VpbGRRdWV1ZSxcbmd1aWxkSWQ6IHN0cmluZylcbntcbiAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgIGlmICghVXRpbC5pc1ZvaWNlRW1wdHkocXVldWUuY2hhbm5lbCEpIHx8ICFwbGF5ZXIubm9kZXMuaGFzKHF1ZXVlLmd1aWxkLmlkKSlcbiAgICByZXR1cm47XG4gICAgaWYgKHF1ZXVlLm9wdGlvbnMubGVhdmVPbkVtcHR5KSBxdWV1ZS5kZWxldGUoKTtcbiAgICBwbGF5ZXIuZXZlbnRzLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LkVtcHR5Q2hhbm5lbCwgcXVldWUpO1xuICB9LCBxdWV1ZS5vcHRpb25zLmxlYXZlT25FbXB0eUNvb2xkb3duIHx8IDApLnVucmVmKCk7XG4gIHF1ZXVlLnRpbWVvdXRzLnNldChgZW1wdHlfJHtndWlsZElkfWAsIHRpbWVvdXQpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVDaGFubmVsUG9wdWxhdGUoXG5wbGF5ZXI6IFBsYXllcixcbnF1ZXVlOiBHdWlsZFF1ZXVlLFxuZ3VpbGRJZDogc3RyaW5nKVxue1xuICBjb25zdCBlbXB0eVRpbWVvdXQgPSBxdWV1ZS50aW1lb3V0cy5nZXQoYGVtcHR5XyR7Z3VpbGRJZH1gKTtcbiAgaWYgKCFVdGlsLmlzVm9pY2VFbXB0eShxdWV1ZS5jaGFubmVsISkgJiYgZW1wdHlUaW1lb3V0KSB7XG4gICAgY2xlYXJUaW1lb3V0KGVtcHR5VGltZW91dCk7XG4gICAgcXVldWUudGltZW91dHMuZGVsZXRlKGBlbXB0eV8ke2d1aWxkSWR9YCk7XG4gICAgcGxheWVyLmV2ZW50cy5lbWl0KEd1aWxkUXVldWVFdmVudC5DaGFubmVsUG9wdWxhdGUsIHF1ZXVlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVQYXVzZU9uRW1wdHkocXVldWU6IEd1aWxkUXVldWUpIHtcbiAgY29uc3QgaXNFbXB0eSA9IFV0aWwuaXNWb2ljZUVtcHR5KHF1ZXVlLmNoYW5uZWwhKTtcbiAgY29uc3Qgd2FzUGF1c2VkT25FbXB0eSA9IFJlZmxlY3QuZ2V0KHF1ZXVlLCAnX19wYXVzZWRPbkVtcHR5Jyk7XG5cbiAgaWYgKGlzRW1wdHkgJiYgIXdhc1BhdXNlZE9uRW1wdHkpIHtcbiAgICBxdWV1ZS5ub2RlLnNldFBhdXNlZCh0cnVlKTtcbiAgICBSZWZsZWN0LnNldChxdWV1ZSwgJ19fcGF1c2VkT25FbXB0eScsIHRydWUpO1xuICAgIGlmIChxdWV1ZS5oYXNEZWJ1Z2dlcikge1xuICAgICAgcXVldWUuZGVidWcoXG4gICAgICAgICdWb2ljZSBjaGFubmVsIGlzIGVtcHR5IGFuZCBvcHRpb25zI3BhdXNlT25FbXB0eSBpcyB0cnVlLCBwYXVzaW5nLi4uJ1xuICAgICAgKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoIWlzRW1wdHkgJiYgd2FzUGF1c2VkT25FbXB0eSkge1xuICAgIHF1ZXVlLm5vZGUuc2V0UGF1c2VkKGZhbHNlKTtcbiAgICBSZWZsZWN0LnNldChxdWV1ZSwgJ19fcGF1c2VkT25FbXB0eScsIGZhbHNlKTtcbiAgICBpZiAocXVldWUuaGFzRGVidWdnZXIpIHtcbiAgICAgIHF1ZXVlLmRlYnVnKFxuICAgICAgICAnVm9pY2UgY2hhbm5lbCBpcyBub3QgZW1wdHkgYW5kIG9wdGlvbnMjcGF1c2VPbkVtcHR5IGlzIHRydWUsIHJlc3VtaW5nLi4uJ1xuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaGFuZGxlQm90Vm9pY2VTdGF0ZVVwZGF0ZShcbnF1ZXVlOiBHdWlsZFF1ZXVlLFxub2xkU3RhdGU6IFZvaWNlU3RhdGUsXG5uZXdTdGF0ZTogVm9pY2VTdGF0ZSlcbntcbiAgaWYgKFxuICBuZXdTdGF0ZS5zZXJ2ZXJNdXRlICE9IG51bGwgJiZcbiAgb2xkU3RhdGUuc2VydmVyTXV0ZSAhPT0gbmV3U3RhdGUuc2VydmVyTXV0ZSlcbiAge1xuICAgIHF1ZXVlLm5vZGUuc2V0UGF1c2VkKG5ld1N0YXRlLnNlcnZlck11dGUpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChcbiAgbmV3U3RhdGUuY2hhbm5lbD8udHlwZSA9PT0gQ2hhbm5lbFR5cGUuR3VpbGRTdGFnZVZvaWNlICYmXG4gIG5ld1N0YXRlLnN1cHByZXNzICE9IG51bGwgJiZcbiAgb2xkU3RhdGUuc3VwcHJlc3MgIT09IG5ld1N0YXRlLnN1cHByZXNzKVxuICB7XG4gICAgcXVldWUubm9kZS5zZXRQYXVzZWQobmV3U3RhdGUuc3VwcHJlc3MpO1xuICAgIGlmIChuZXdTdGF0ZS5zdXBwcmVzcykge1xuICAgICAgbmV3U3RhdGUuZ3VpbGQubWVtYmVycy5tZT8udm9pY2Uuc2V0UmVxdWVzdFRvU3BlYWsodHJ1ZSkuY2F0Y2goVXRpbC5ub29wKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRWb2ljZVN0YXRlSGFuZGxlcihcbnBsYXllcjogUGxheWVyLFxucXVldWU6IEd1aWxkUXVldWUsXG5vbGRTdGF0ZTogVm9pY2VTdGF0ZSxcbm5ld1N0YXRlOiBWb2ljZVN0YXRlKVxue1xuICBpZiAoIXF1ZXVlPy5jb25uZWN0aW9uIHx8ICFxdWV1ZS5jaGFubmVsKSByZXR1cm47XG5cbiAgY29uc3QgaXNCb3RTdGF0ZSA9IG5ld1N0YXRlLm1lbWJlcj8uaWQgPT09IG5ld1N0YXRlLmd1aWxkLm1lbWJlcnMubWU/LmlkO1xuICBjb25zdCBndWlsZElkID0gb2xkU3RhdGUuZ3VpbGQuaWQ7XG5cbiAgLy8gQm90IGRpc2Nvbm5lY3RlZFxuICBpZiAoaXNCb3RTdGF0ZSAmJiBvbGRTdGF0ZS5jaGFubmVsSWQgJiYgIW5ld1N0YXRlLmNoYW5uZWxJZCkge1xuICAgIHRyeSB7XG4gICAgICBxdWV1ZS5kZWxldGUoKTtcbiAgICB9IGNhdGNoIHtcblxuICAgICAgLyogbm9vcCAqL31cbiAgICByZXR1cm4gdm9pZCBwbGF5ZXIuZXZlbnRzLmVtaXQoR3VpbGRRdWV1ZUV2ZW50LkRpc2Nvbm5lY3QsIHF1ZXVlKTtcbiAgfVxuXG4gIGlmIChxdWV1ZS5vcHRpb25zLnBhdXNlT25FbXB0eSkge1xuICAgIGhhbmRsZVBhdXNlT25FbXB0eShxdWV1ZSk7XG4gIH1cblxuICAvLyBCb3Qgam9pbmVkIGNoYW5uZWwgb3IgY2hhbmdlZCBzdGF0ZVxuICBpZiAoXG4gIGlzQm90U3RhdGUgJiZcbiAgbmV3U3RhdGUuY2hhbm5lbElkICYmIChcbiAgIW9sZFN0YXRlLmNoYW5uZWxJZCB8fCBvbGRTdGF0ZS5jaGFubmVsSWQgIT09IG5ld1N0YXRlLmNoYW5uZWxJZCkpXG4gIHtcbiAgICBpZiAocXVldWUuY29ubmVjdGlvbikgcXVldWUuY2hhbm5lbCA9IG5ld1N0YXRlLmNoYW5uZWwhO1xuICAgIGhhbmRsZUJvdFZvaWNlU3RhdGVVcGRhdGUocXVldWUsIG9sZFN0YXRlLCBuZXdTdGF0ZSk7XG4gIH1cblxuICAvLyBIYW5kbGUgY2hhbm5lbCBlbXB0eS9wb3B1bGF0ZSBldmVudHNcbiAgaWYgKCFuZXdTdGF0ZS5jaGFubmVsSWQgJiYgb2xkU3RhdGUuY2hhbm5lbElkID09PSBxdWV1ZS5jaGFubmVsLmlkKSB7XG4gICAgaWYgKCFVdGlsLmlzVm9pY2VFbXB0eShxdWV1ZS5jaGFubmVsKSkgcmV0dXJuO1xuICAgIGhhbmRsZUVtcHR5Q2hhbm5lbChwbGF5ZXIsIHF1ZXVlLCBndWlsZElkKTtcbiAgfSBlbHNlIGlmIChuZXdTdGF0ZS5jaGFubmVsSWQgPT09IHF1ZXVlLmNoYW5uZWwuaWQpIHtcbiAgICBoYW5kbGVDaGFubmVsUG9wdWxhdGUocGxheWVyLCBxdWV1ZSwgZ3VpbGRJZCk7XG4gIH0gZWxzZSBpZiAob2xkU3RhdGUuY2hhbm5lbElkICE9PSBuZXdTdGF0ZS5jaGFubmVsSWQpIHtcbiAgICBpZiAoXG4gICAgbmV3U3RhdGUuY2hhbm5lbElkICE9PSBxdWV1ZS5jaGFubmVsLmlkICYmXG4gICAgIVV0aWwuaXNWb2ljZUVtcHR5KHF1ZXVlLmNoYW5uZWwpKVxuXG4gICAgcmV0dXJuO1xuICAgIGlmICghcXVldWUudGltZW91dHMuaGFzKGBlbXB0eV8ke2d1aWxkSWR9YCkpIHtcbiAgICAgIGhhbmRsZUVtcHR5Q2hhbm5lbChwbGF5ZXIsIHF1ZXVlLCBndWlsZElkKTtcbiAgICB9XG4gIH1cbn0iLCAiaW1wb3J0IHsgcmVzb2x2ZSwgZGlybmFtZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBGRm1wZWcsIEZGbXBlZ0xpYiB9IGZyb20gJ0BkaXNjb3JkLXBsYXllci9mZm1wZWcnO1xuaW1wb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4uL3ZlcnNpb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhY2thZ2VKU09OIHtcbiAgbmFtZTogc3RyaW5nO1xuICB2ZXJzaW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIE1heWJlTnVsbDxUPiA9IFQgfCBudWxsO1xuXG5leHBvcnQgaW50ZXJmYWNlIERlcGVuZGVuY2llc1JlcG9ydCB7XG4gIGNvcmU6IHtcbiAgICAnZGlzY29yZC1wbGF5ZXInOiBzdHJpbmc7XG4gICAgJ2Rpc2NvcmQtdm9pcCc6IHN0cmluZztcbiAgfTtcbiAgbGlib3B1czoge1xuICAgIG1lZGlhcGxleDogTWF5YmVOdWxsPHN0cmluZz47XG4gICAgJ0BkaXNjb3JkanMvb3B1cyc6IE1heWJlTnVsbDxzdHJpbmc+O1xuICAgICdAZXZhbi9vcHVzJzogTWF5YmVOdWxsPHN0cmluZz47XG4gICAgb3B1c3NjcmlwdDogTWF5YmVOdWxsPHN0cmluZz47XG4gICAgJ25vZGUtb3B1cyc6IE1heWJlTnVsbDxzdHJpbmc+O1xuICB9O1xuICBsaWJzb2RpdW06IHtcbiAgICAnc29kaXVtLW5hdGl2ZSc6IE1heWJlTnVsbDxzdHJpbmc+O1xuICAgIHNvZGl1bTogTWF5YmVOdWxsPHN0cmluZz47XG4gICAgJ2xpYnNvZGl1bS13cmFwcGVycyc6IE1heWJlTnVsbDxzdHJpbmc+O1xuICAgICdzb2RpdW0tamF2YXNjcmlwdCc6IE1heWJlTnVsbDxzdHJpbmc+O1xuICAgICdAc3RhYmxlbGliL3hjaGFjaGEyMHBvbHkxMzA1JzogTWF5YmVOdWxsPHN0cmluZz47XG4gICAgJ0Bub2JsZS9jaXBoZXJzJzogTWF5YmVOdWxsPHN0cmluZz47XG4gIH07XG4gIERBVkU6IHtcbiAgICAnQHNuYXp6YWgvZGF2ZXknOiBNYXliZU51bGw8c3RyaW5nPjtcbiAgfTtcbiAgZmZtcGVnOiBGRm1wZWdSZXBvcnQ7XG59XG5cbmV4cG9ydCB0eXBlIEZGbXBlZ1JlcG9ydCA9IFJlY29yZDxcbiAgRkZtcGVnTGliLFxuICBNYXliZU51bGw8e1xuICAgIHZlcnNpb246IHN0cmluZztcbiAgICBoYXNMaWJvcHVzOiBib29sZWFuO1xuICB9Pj47XG5cblxuLyoqXG4gKiBBIHV0aWxpdHkgdG8gZ2VuZXJhdGUgYSByZXBvcnQgb2YgdGhlIGRlcGVuZGVuY2llcyB1c2VkIGJ5IHRoZSBkaXNjb3JkLXBsYXllciBtb2R1bGUuXG4gKi9cbmV4cG9ydCBjb25zdCBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yID0ge1xuICAvKipcbiAgICogRmluZHMgdGhlIHBhY2thZ2UuanNvbiBmaWxlIG9mIGEgcGFja2FnZS5cbiAgICogQHBhcmFtIGRpciAtIFRoZSBkaXJlY3RvcnkgdG8gc3RhcnQgc2VhcmNoaW5nIGZyb21cbiAgICogQHBhcmFtIHBhY2thZ2VOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBhY2thZ2UgdG8gZmluZFxuICAgKiBAcGFyYW0gZGVwdGggLSBUaGUgbWF4aW11bSBkZXB0aCB0byBzZWFyY2hcbiAgICogQHJldHVybnMgVGhlIHBhY2thZ2UuanNvbiBmaWxlLCBvciBudWxsIGlmIG5vdCBmb3VuZFxuICAgKi9cbiAgZmluZFBhY2thZ2VKU09OKFxuICBkaXI6IHN0cmluZyxcbiAgcGFja2FnZU5hbWU6IHN0cmluZyxcbiAgZGVwdGg6IG51bWJlcilcbiAgOiBQYWNrYWdlSlNPTiB8IG51bGwge1xuICAgIGlmIChkZXB0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCB0YXJnZXQgPSByZXNvbHZlKGRpciwgJ3BhY2thZ2UuanNvbicpO1xuXG4gICAgY29uc3QgbmV4dCA9ICgpID0+XG4gICAgRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci5maW5kUGFja2FnZUpTT04oXG4gICAgICByZXNvbHZlKGRpciwgJy4uJyksXG4gICAgICBwYWNrYWdlTmFtZSxcbiAgICAgIGRlcHRoIC0gMVxuICAgICk7XG5cbiAgICB0cnkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbiAgICAgIGNvbnN0IHBrZ0pTT046IFBhY2thZ2VKU09OID0gcmVxdWlyZSh0YXJnZXQpO1xuXG4gICAgICBpZiAocGtnSlNPTi5uYW1lICE9PSBwYWNrYWdlTmFtZSkge1xuICAgICAgICByZXR1cm4gbmV4dCgpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGtnSlNPTjtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgfVxuICB9LFxuICAvKipcbiAgICogVHJpZXMgdG8gZmluZCB0aGUgdmVyc2lvbiBvZiBhIGRlcGVuZGVuY3kuXG4gICAqIEBwYXJhbSBuYW1lIC0gVGhlIHBhY2thZ2UgdG8gZmluZCB0aGUgdmVyc2lvbiBvZlxuICAgKiBAcGFyYW0gbWF4TG9va3VwRGVwdGggLSBUaGUgbWF4aW11bSBkZXB0aCB0byBzZWFyY2ggZm9yIHRoZSBwYWNrYWdlLmpzb24gZmlsZVxuICAgKiBAcmV0dXJucyBUaGUgdmVyc2lvbiBvZiB0aGUgcGFja2FnZSwgb3IgbnVsbCBpZiBub3QgZm91bmRcbiAgICovXG4gIHZlcnNpb24obmFtZTogc3RyaW5nLCBtYXhMb29rdXBEZXB0aCA9IDMpOiBzdHJpbmcgfCBudWxsIHtcbiAgICB0cnkge1xuICAgICAgaWYgKG5hbWUgPT09ICdkaXNjb3JkLXBsYXllcicpIHtcbiAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBrZyA9IERlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3IuZmluZFBhY2thZ2VKU09OKFxuICAgICAgICBkaXJuYW1lKHJlcXVpcmUucmVzb2x2ZShuYW1lKSksXG4gICAgICAgIG5hbWUsXG4gICAgICAgIG1heExvb2t1cERlcHRoXG4gICAgICApO1xuICAgICAgcmV0dXJuIHBrZz8udmVyc2lvbiA/PyBudWxsO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9LFxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgcmVwb3J0IG9mIHRoZSBkZXBlbmRlbmNpZXMgdXNlZCBieSB0aGUgZGlzY29yZC1wbGF5ZXIgbW9kdWxlLlxuICAgKiBAcmV0dXJucyBUaGUgcmVwb3J0IG9iamVjdFxuICAgKi9cbiAgZ2VuZXJhdGUoKTogRGVwZW5kZW5jaWVzUmVwb3J0IHtcbiAgICBjb25zdCBmZm1wZWdSZXBvcnQgPSB7fSBhcyBGRm1wZWdSZXBvcnQ7XG5cbiAgICBmb3IgKGNvbnN0IGxpYiBvZiBGRm1wZWcuc291cmNlcykge1xuICAgICAgZmZtcGVnUmVwb3J0W2xpYi5uYW1lXSA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgZmZtcGVnID0gRkZtcGVnLnJlc29sdmVTYWZlKCk7XG5cbiAgICBpZiAoZmZtcGVnKSB7XG4gICAgICBmZm1wZWdSZXBvcnRbZmZtcGVnLm5hbWVdID0ge1xuICAgICAgICBoYXNMaWJvcHVzOiBmZm1wZWcuY29tbWFuZC5pbmNsdWRlcygnLS1lbmFibGUtbGlib3B1cycpLFxuICAgICAgICB2ZXJzaW9uOiBmZm1wZWcudmVyc2lvblxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29yZToge1xuICAgICAgICAnZGlzY29yZC1wbGF5ZXInOiBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yLnZlcnNpb24oXG4gICAgICAgICAgJ2Rpc2NvcmQtcGxheWVyJ1xuICAgICAgICApIGFzIHN0cmluZyxcbiAgICAgICAgJ2Rpc2NvcmQtdm9pcCc6IERlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3IudmVyc2lvbihcbiAgICAgICAgICAnZGlzY29yZC12b2lwJ1xuICAgICAgICApIGFzIHN0cmluZ1xuICAgICAgfSxcbiAgICAgIGxpYm9wdXM6IHtcbiAgICAgICAgbWVkaWFwbGV4OiBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yLnZlcnNpb24oJ21lZGlhcGxleCcpLFxuICAgICAgICAnQGRpc2NvcmRqcy9vcHVzJzogRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci52ZXJzaW9uKCdAZGlzY29yZGpzL29wdXMnKSxcbiAgICAgICAgJ0BldmFuL29wdXMnOiBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yLnZlcnNpb24oJ0BldmFuL29wdXMnKSxcbiAgICAgICAgb3B1c3NjcmlwdDogRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci52ZXJzaW9uKCdvcHVzc2NyaXB0JyksXG4gICAgICAgICdub2RlLW9wdXMnOiBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yLnZlcnNpb24oJ25vZGUtb3B1cycpXG4gICAgICB9LFxuICAgICAgbGlic29kaXVtOiB7XG4gICAgICAgICdzb2RpdW0tbmF0aXZlJzogRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci52ZXJzaW9uKCdzb2RpdW0tbmF0aXZlJyksXG4gICAgICAgIHNvZGl1bTogRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci52ZXJzaW9uKCdzb2RpdW0nKSxcbiAgICAgICAgJ2xpYnNvZGl1bS13cmFwcGVycyc6XG4gICAgICAgIERlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3IudmVyc2lvbignbGlic29kaXVtLXdyYXBwZXJzJyksXG4gICAgICAgICdAc3RhYmxlbGliL3hjaGFjaGEyMHBvbHkxMzA1JzogRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci52ZXJzaW9uKFxuICAgICAgICAgICdAc3RhYmxlbGliL3hjaGFjaGEyMHBvbHkxMzA1J1xuICAgICAgICApLFxuICAgICAgICAnc29kaXVtLWphdmFzY3JpcHQnOlxuICAgICAgICBEZXBlbmRlbmN5UmVwb3J0R2VuZXJhdG9yLnZlcnNpb24oJ3NvZGl1bS1qYXZhc2NyaXB0JyksXG4gICAgICAgICdAbm9ibGUvY2lwaGVycyc6IERlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3IudmVyc2lvbignQG5vYmxlL2NpcGhlcnMnKVxuICAgICAgfSxcbiAgICAgIERBVkU6IHtcbiAgICAgICAgJ0BzbmF6emFoL2RhdmV5JzogRGVwZW5kZW5jeVJlcG9ydEdlbmVyYXRvci52ZXJzaW9uKCdAc25henphaC9kYXZleScpXG4gICAgICB9LFxuICAgICAgZmZtcGVnOiBmZm1wZWdSZXBvcnRcbiAgICB9O1xuICB9LFxuICAvKipcbiAgICogR2VuZXJhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkZXBlbmRlbmNpZXMgcmVwb3J0LlxuICAgKiBAcmV0dXJucyBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICBnZW5lcmF0ZVN0cmluZygpOiBzdHJpbmcge1xuICAgIGNvbnN0IHJlcG9ydCA9IERlcGVuZGVuY3lSZXBvcnRHZW5lcmF0b3IuZ2VuZXJhdGUoKTtcbiAgICBjb25zdCBsaW5lID0gJy0nLnJlcGVhdCg1MCk7XG5cbiAgICBjb25zdCBvdXRwdXQ6IHN0cmluZ1tdID0gW107XG5cbiAgICBvdXRwdXQucHVzaCgnRGVwZW5kZW5jaWVzIFJlcG9ydCcpO1xuICAgIG91dHB1dC5wdXNoKGxpbmUpO1xuXG4gICAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHJlcG9ydCkgYXMgKGtleW9mIERlcGVuZGVuY2llc1JlcG9ydClbXTtcblxuICAgIGZvciAoY29uc3QgX2tleSBvZiBrZXlzKSB7XG4gICAgICBjb25zdCBrZXkgPSBfa2V5IGFzIGtleW9mIERlcGVuZGVuY2llc1JlcG9ydDtcblxuICAgICAgb3V0cHV0LnB1c2goa2V5KTtcblxuICAgICAgY29uc3Qgc3ViS2V5cyA9IE9iamVjdC5rZXlzKHJlcG9ydFtrZXldKTtcblxuICAgICAgZm9yIChjb25zdCBfc3ViS2V5IG9mIHN1YktleXMpIHtcbiAgICAgICAgY29uc3Qgc3ViS2V5ID0gX3N1YktleSBhcyBrZXlvZiBEZXBlbmRlbmNpZXNSZXBvcnRbdHlwZW9mIGtleV07XG4gICAgICAgIGNvbnN0IHZhbHVlID0gcmVwb3J0W2tleV1bc3ViS2V5XSA/PyAnTi9BJztcblxuICAgICAgICBvdXRwdXQucHVzaChcbiAgICAgICAgICBgLSAke3N1YktleX06ICR7XG4gICAgICAgICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyA/IEpTT04uc3RyaW5naWZ5KHZhbHVlLCBudWxsLCAyKSA6IHZhbHVlfWBcblxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBvdXRwdXQucHVzaCgnJyk7XG4gICAgfVxuXG4gICAgb3V0cHV0LnB1c2gobGluZSk7XG5cbiAgICByZXR1cm4gb3V0cHV0LmpvaW4oJ1xcbicpO1xuICB9XG59OyIsICJcblxuXG5cblxuXG5leHBvcnQgY29uc3QgdmVyc2lvbiA9IC8qIEBfX01BQ1JPX18gZ2V0VmVyc2lvbiAqL1wiNy4yLjBcIjsiLCAiaW1wb3J0IHsgU3RyZWFtVHlwZSB9IGZyb20gJ2Rpc2NvcmQtdm9pcCc7XG5pbXBvcnQgdHlwZSB7IFRyYWNrIH0gZnJvbSAnLi9mYWJyaWMnO1xuaW1wb3J0IHR5cGUgeyBQbGF5ZXIgfSBmcm9tICcuL1BsYXllcic7XG5pbXBvcnQgdHlwZSB7IEd1aWxkUXVldWUgfSBmcm9tICcuL3F1ZXVlJztcbmltcG9ydCB0eXBlIHsgSW50ZXJjZXB0ZWRTdHJlYW0gfSBmcm9tICcuL3N0cmVhbS9JbnRlcmNlcHRlZFN0cmVhbSc7XG5cbnR5cGUgQXdhaXRhYmxlPFQ+ID0gVCB8IFByb21pc2VMaWtlPFQ+O1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZXhwb3J0IHR5cGUgU2hvdWxkSW50ZXJjZXB0RnVuY3Rpb24gPSA8VCA9IGFueT4oXG5xdWV1ZTogR3VpbGRRdWV1ZTxUPixcbnRyYWNrOiBUcmFjayxcbmZvcm1hdDogU3RyZWFtVHlwZSxcbnN0cmVhbTogSW50ZXJjZXB0ZWRTdHJlYW0pXG49PiBBd2FpdGFibGU8Ym9vbGVhbj47XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG5leHBvcnQgdHlwZSBPbkludGVyY2VwdGVkU3RyZWFtSGFuZGxlciA9IDxUID0gYW55PihcbnF1ZXVlOiBHdWlsZFF1ZXVlPFQ+LFxudHJhY2s6IFRyYWNrLFxuZm9ybWF0OiBTdHJlYW1UeXBlLFxuc3RyZWFtOiBJbnRlcmNlcHRlZFN0cmVhbSlcbj0+IEF3YWl0YWJsZTx2b2lkPjtcblxuZXhwb3J0IGludGVyZmFjZSBQbGF5ZXJTdHJlYW1JbnRlcmNlcHRvck9wdGlvbnMge1xuICAvKipcbiAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBzdHJlYW0gc2hvdWxkIGJlIGludGVyY2VwdGVkLlxuICAgKi9cbiAgc2hvdWxkSW50ZXJjZXB0PzogU2hvdWxkSW50ZXJjZXB0RnVuY3Rpb247XG59XG5cbmV4cG9ydCBjbGFzcyBQbGF5ZXJTdHJlYW1JbnRlcmNlcHRvciB7XG4gICNvblN0cmVhbSA9IG5ldyBTZXQ8T25JbnRlcmNlcHRlZFN0cmVhbUhhbmRsZXI+KCk7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgUGxheWVyU3RyZWFtSW50ZXJjZXB0b3IgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSBwbGF5ZXIgVGhlIHBsYXllciBpbnN0YW5jZVxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgaW50ZXJjZXB0b3Igb3B0aW9uc1xuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICBwdWJsaWMgcmVhZG9ubHkgcGxheWVyOiBQbGF5ZXIsXG4gIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogUGxheWVyU3RyZWFtSW50ZXJjZXB0b3JPcHRpb25zKVxuICB7fVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSBpbnRlcmNlcHRlZCBzdHJlYW0uXG4gICAqIEBwYXJhbSBxdWV1ZSBUaGUgZ3VpbGQgcXVldWVcbiAgICogQHBhcmFtIHRyYWNrIFRoZSB0cmFja1xuICAgKiBAcGFyYW0gc3RyZWFtIFRoZSBpbnRlcmNlcHRlZCBzdHJlYW1cbiAgICogQHJldHVybnMgV2hldGhlciB0aGUgc3RyZWFtIHdhcyBpbnRlcmNlcHRlZFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGhhbmRsZTxUID0gdW5rbm93bj4oXG4gIHF1ZXVlOiBHdWlsZFF1ZXVlPFQ+LFxuICB0cmFjazogVHJhY2ssXG4gIHR5cGU6IFN0cmVhbVR5cGUsXG4gIHN0cmVhbTogSW50ZXJjZXB0ZWRTdHJlYW0pXG4gIDogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgZmlsdGVyID0gdGhpcy5vcHRpb25zLnNob3VsZEludGVyY2VwdDtcblxuICAgIGlmIChmaWx0ZXIpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbHRlcihxdWV1ZSwgdHJhY2ssIHR5cGUsIHN0cmVhbSk7XG4gICAgICBpZiAoIXJlc3VsdCkgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhhc0xpc3RlbmVycyA9IHRoaXMuI29uU3RyZWFtLnNpemU7XG5cbiAgICBpZiAoIWhhc0xpc3RlbmVycykgcmV0dXJuIGZhbHNlO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBbLi4udGhpcy4jb25TdHJlYW1dLm1hcCgoaGFuZGxlcikgPT4gaGFuZGxlcihxdWV1ZSwgdHJhY2ssIHR5cGUsIHN0cmVhbSkpXG4gICAgKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBuZXcgaW50ZXJjZXB0ZWQgc3RyZWFtIGxpc3RlbmVyLlxuICAgKiBAcGFyYW0gaGFuZGxlciBUaGUgaGFuZGxlclxuICAgKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJcbiAgICovXG4gIHB1YmxpYyBvblN0cmVhbShoYW5kbGVyOiBPbkludGVyY2VwdGVkU3RyZWFtSGFuZGxlcik6ICgpID0+IHZvaWQge1xuICAgIHRoaXMuI29uU3RyZWFtLmFkZChoYW5kbGVyKTtcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB0aGlzLiNvblN0cmVhbS5kZWxldGUoaGFuZGxlcik7XG4gICAgfTtcbiAgfVxufSJdLAogICJtYXBwaW5ncyI6ICI7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QztBQUVsRCxXQUFPO0FBQUEsRUFDVDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNQSxNQUFhLHlCQUNiLE9BQ0EsT0FDQSxRQUNBLFFBQ0E7QUFDRSxRQUFJLENBQUMsbUJBQUssb0JBQW9CO0FBRTlCLFdBQU8sbUJBQUssb0JBQW1CLE9BQU8sT0FBTyxPQUFPLFFBQVEsTUFBTTtBQUFBLEVBQ3BFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU1PLHdCQUF3QixTQUF5QztBQUN0RSxRQUFJLG1CQUFLLHFCQUFvQjtBQUMzQixhQUFPLG1CQUFLO0FBQUEsSUFDZDtBQUVBLHVCQUFLLG9CQUFxQixJQUFJLHdCQUF3QixNQUFNLE9BQU87QUFFbkUsV0FBTyxtQkFBSztBQUFBLEVBQ2Q7QUFDRjtBQXh6QkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBNkNBO0FBbkQ0RDtBQUFBO0FBQUE7QUFBQTtBQVU1RCxjQVZXLFNBVVksV0FBa0I7QUFWcEMsSUFBTSxTQUFOOzs7QTdDbElQLElBQUFLLG9CQVdBO0FBQ0EsSUFBQUMsdUJBV0E7IiwKICAibmFtZXMiOiBbIkd1aWxkUXVldWUiLCAiU2VyaWFsaXplZFR5cGUiLCAicXVlcnkiLCAidmVyc2lvbiIsICJEaXNjb3JkUGxheWVyQ2xpZW50U3ltYm9sIiwgIm1vZHVsZSIsICJEaXNjb3JkUGxheWVyQ2xpZW50U3ltYm9sIiwgImltcG9ydF92MTAiLCAiRGlzY29yZFBsYXllckNsaWVudFN5bWJvbCIsICJkZWNsYXJlUHJvcGVydHkiLCAiZ2V0UHJvcGVydHkiLCAibW9kdWxlIiwgIkRpc2NvcmRQbGF5ZXJDbGllbnRTeW1ib2wiLCAiaW1wb3J0X3V0aWxzIiwgImltcG9ydF91dGlscyIsICJyZXN1bHQiLCAiaW1wb3J0X3V0aWxzIiwgImltcG9ydF9kaXNjb3JkIiwgImltcG9ydF91dGlscyIsICJpbXBvcnRfdXRpbHMiLCAiaW1wb3J0X2Rpc2NvcmRfdm9pcCIsICJpbXBvcnRfdXRpbHMiLCAiaW1wb3J0X2Rpc2NvcmRfdm9pcCIsICJpbXBvcnRfcHJvbWlzZXMiLCAiaW1wb3J0X2Rpc2NvcmQiLCAicmVzb2x2ZSIsICJyZXNvbHZlIiwgIndhaXRGb3IiLCAiaW1wb3J0X2VxdWFsaXplciIsICJUcmFja1NraXBSZWFzb24iLCAicmVzb2x2ZSIsICJHdWlsZFF1ZXVlIiwgIkd1aWxkUXVldWUiLCAiaW1wb3J0X3Byb21pc2VzIiwgInZlcnNpb24iLCAiaW1wb3J0X2Rpc2NvcmRfdm9pcCIsICJpbXBvcnRfdXRpbHMiLCAiaW1wb3J0X2ZmbXBlZyIsICJpbXBvcnRfZGlzY29yZCIsICJpbXBvcnRfZGlzY29yZF92b2lwIiwgImltcG9ydF9kaXNjb3JkIiwgImltcG9ydF9mZm1wZWciLCAiZGpzVmVyc2lvbiIsICJxdWVyeSIsICJyZXMiLCAicmVzdWx0IiwgImRWb2ljZVZlcnNpb24iLCAiaW1wb3J0X2VxdWFsaXplciIsICJpbXBvcnRfZGlzY29yZF92b2lwIl0KfQo=