// ==UserScript==
// Do not modify and re-release this script!
// If you would like to add support for other sites, please tell me and I'll put it in the includes.
// @id youtube-me-again
// @name YouTube Me Again!
// @namespace hateradio)))
// @author hateradio
// @version 8.0.0
// @description ytma! automatically converts YouTube(TM), Vimeo, Vine, Soundcloud, WebM, and MP4 links into real embedded videos.
// @homepageURL https://greasyfork.org/en/scripts/1023-youtube-me-again
// @icon https://www.dropbox.com/s/b85qmq0bsim407s/ytma32.png?dl=1
// @icon64 https://www.dropbox.com/s/5zw3al38yf39wxb/ytma64.png?dl=1
// @screenshot https://www.dropbox.com/s/syy9916b1prygl9/ytmascreen5.png?dl=1
// @include https://vine.co/v/*/embed/simple
// @match https://vine.co/v/*/embed/simple
// @include https://gfycat.com/iframe/*
// @match https://gfycat.com/iframe/*
// @include http*://*.neogaf.com/threads/*
// @include http*://*.resetera.com/threads/*
// @match *://*.neogaf.com/threads/*
// @match *://*.resetera.com/threads/*
// @updated 2020-06-12T08:16:14.343Z
// @grant GM.xmlhttpRequest
// @grant GM_xmlhttpRequest
// @run-at document-end
// ==/UserScript==
/*
## Updates
#### 8
* Update YTMA to ESNext
* Fix: (XenoForo) YouTube embed
#### 7.9.1
* Fix: (XenoForo) Ignore links in more text areas
#### 7.9
* Fix: (XenoForo) Ignore links in text areas
#### 7.8
* Fix iFrame selectors
* Adds a monitoring interface to check for updated pages
#### 7.7
* New: YTMA will now try to find new links on AJAX-loaded posts on ResetEra
* Reverts Gfycat iFrame support; removes video tag for wider support
* Removes an outdated Chrome blacklist
#### 7.6
* Fix: overrides resetera support of embeded videos
#### 7.5
* New: Support for ResetEra
* Fix: Parses hours from YouTube URLs
#### 7.2.2
* Updates YouTube iFrame to hide related video feature when pausing
#### 7.2.1
* New: Extension info
* Updates JSHint options
* Removes outdated @include links
#### 7.2
* New: CSS rule to make videos fit within smaller windows
* New: GitHub repository and update links
* New: Streamable favicon
* Fix: Vimeo favicon
#### 7.1
* HTTPS links for Vimeo and Gfycat
* Fix: Safari bug
#### 7
* New: NeoGAF HTTPS Support
* New: Streamable.com added
* New: Soundcloud playlist support
* Improved time parser
* Upon scrolling, cached descriptions are shown
* Code reorganization makes adding new media sites easier
### 6
* New: Imgur GIFV (WEBM/MP4) support
* New: Button to remove cache (descriptions/thumbnail links/etc)
* New: SoundCloud playlist support
* Default video quality is now 720p/HD
* Soundcloud now uses HTML5 player
* Players that open on scroll will no longer trigger the opening of players higher on the page
* Adds HTML5, Gfycat, Imgur icons on links
* Improved Soundcloud and GfyCat URL matchers
* Restructured code base to simplify creation of media controls
* Restructured CSS
* Patched back Gfycat iFrame setting for Safari (it is incompatible with new settings)
* Updates YouTube data API
* Removes:
* Object tag for YouTube for Flash (Deprecated)
* "Batch" loading of descriptions (Only manual and scroll methods are supported)
// #Updates
Whitelist these sites on NoScript/NotScript/etc.
------------------------------------------------
* neogaf.com
* youtube.com
* youtube-nocookie.com
* googlevideo.com (HTML5 player sends videos from this domain)
* googleapis.com (YT video descriptions)
* vimeo.com
* vimeocdn.com
* soundcloud.com
* sndcdn.com
* vineco.com
* vine.com
* vine.co
* gfycat.com
* github.io
Whitelist these on Ghostery
---------------------------
* SoundCloud (Widgets, Audio / Music Player)
*/
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _modules_Helpers__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/Helpers */ "./src/modules/Helpers.js");
/* harmony import */ var _modules___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/_ */ "./src/modules/_.js");
/* harmony import */ var _modules_strg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/strg */ "./src/modules/strg.js");
/* harmony import */ var _modules_update__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/update */ "./src/modules/update.js");
(() => {
/** Y T M A CLASS
* @private
* Base YTMA class, filled through constructor() or reactivate() though sub-classes
* Y's only concerned about the anchor and the data props
*
* @param {object} props Properties
* @param {String|Number} props.id Unique ID
* @param {String} props.site Website name eg: youtube, vimeo
* @param {HTMLAnchorElement} props.anchor Anchor element
*/
class Y {
constructor({ id, site, anchor }) {
const uid = Y.escapeId(`${id}_${Y.num += 1}`);
this.state = {
id,
uid: Y.escapeId(uid), // unique id
sid: Y.escapeId(id), // shared id
site,
uri: anchor.href
};
if (anchor && !anchor.dataset.ytmscroll) { anchor.dataset.ytmscroll = true; }
this.anchor = anchor;
}
/**
* Recreates a YTMA object from a trigger element
* @param {HTMLElement} element the element's dataset for the resurection!
*/
reactivate({ dataset }) {
const id = dataset.ytmid;
const anchor = document.querySelector(`a[data-ytmuid="${dataset.ytmuid}"]`);
this.state = {
id,
uid: dataset.ytmuid,
sid: dataset.ytmsid,
site: dataset.ytmsite,
uri: anchor.href
};
this.anchor = anchor;
return this;
}
disableOpenOnScroll() {
this.anchor.dataset.ytmscroll = false;
}
canScroll() {
return this.anchor.dataset.ytmscroll === 'true';
}
isBelow(link) {
return Scroll.compare(this.anchor, link) < 1;
}
canShowUnder(link) {
this.canScroll() && this.isBelow(link);
}
updateAnchor() {
if (this.anchor.getElementsByTagName('img').length === 0) {
this.anchor.classList.add('ytm_link', `ytm_link_${this.state.site}`);
}
this.anchor.dataset.ytmid = this.state.id;
this.anchor.dataset.ytmuid = this.state.uid;
this.anchor.dataset.ytmsid = this.state.sid;
this.anchor.title = 'Visit the video page.';
}
}
/** C O N T A I N E R CLASS
* The container, as the name implies, contains all the interactive elements
* Thumbnail, Player, Controls, etc.
*/
class Container extends Y {
createInterface() {
const { state } = this;
this.site = Y.DB.sites[state.site];
const { ajax, slim } = this.site;
this.updateAnchor();
this.body = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('div', {
id: `w${state.uid}`,
className: `ytm_spacer ytm_block ytm_site_${state.site}`,
innerHTML: this.createThumbnailTemplate()
});
this.thumbnail = this.body.firstElementChild;
if (ajax) { this.createAjaxLink(); }
if (slim) { this.body.classList.add('ytm_site_slim'); }
this.anchor.insertAdjacentElement('afterend', this.body);
try {
Container.decorators[state.site].gui(this);
} catch (e) {
// meh
}
}
updateAnchor() {
const { scroll, https } = this;
if (scroll) { this.anchor.classList.add('ytm_scroll'); }
if (https) { this.anchor.href = this.anchor.href.replace('http:', 'https:'); }
super.updateAnchor();
}
createThumbnailTemplate() {
const { title, thumb = '' } = this.site;
const { id, uid, sid, site } = this.state;
const bg = thumb ? `background-image: ${thumb.replace('%key', id)}` : '';
const template = `
<span class="ytm_trigger ytm_block ytm_normalize ytm_sans"
title="${title}"
data-ytmid="${id}"
data-ytmsite="${id}"
style="${bg}">
<span class="ytm_init ytm_label ytm_sans ytm_box">${title}</span>
<var class="ytm_label ytm_box"
data-ytmid="${id}"
data-ytmuid="${uid}"
data-ytmsid="${sid}"
data-ytmsite="${site}">\u25B6</var>
</span>
</span>`;
return template;
}
createAjaxLink() {
const { sid, id, site, uri } = this.state;
const template = `
<span class="ytm_bd ytm_normalize ytm_manual _${sid}">
<a href="#" class="ytm_title" title="Load this video's description."
data-ytmid="${id}"
data-ytmsite="${site}"
data-ytmuri="${uri}"
data-ytmdescription="true"
>Load Description</a>
</span>`;
this.body.insertAdjacentHTML('beforeend', template);
}
createProjector() {
this.projector = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('div', {
className: 'ytm_projector ytm_none ytm_block ytm_normalize ytm_sans',
innerHTML: Container.templates.menu
});
this.thumbnail.insertAdjacentElement('afterend', this.projector);
}
showPlayer() {
this.thumbnail.classList.add('ytm_none');
this.projector.classList.remove('ytm_none');
}
hidePlayer() {
this.thumbnail.classList.remove('ytm_none');
this.projector.classList.add('ytm_none');
}
}
Container.templates = {
menu: `
<ul class="ytm_options ytm_sans">
<li>
<ul class="ytm_ratios">
<li data-type="ratio" data-value="1" title="SD">4:3</li>
<li data-type="ratio" data-value="2" title="Landscape">16:9</li>
<li data-type="ratio" data-value="3" title="Portrait">9:16</li>
</ul>
</li>
<li>
<ul class="ytm_sizes">
<li data-type="size" data-value="0" title="Hide the video.">\u00D8</li>
<li data-type="size" data-value="240" title="240p">S</li>
<li data-type="size" data-value="360" title="360p">M</li>
<li data-type="size" data-value="480" title="480p">L</li>
<li data-type="size" data-value="720" title="720p">X</li>
</ul>
</li>
<li>
<ul class="ytm_options">
${_modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].on ? '<li data-type="settings" data-value="" title="YTMA Settings">!</li>' : ''}
<li data-type="close" data-value="" title="Close the video.">\u00D7</li>
</ul>
</li>
</ul>`
};
Container.decorators = { // modify interface according to site
youtube: {
gui: function (control) {
control.anchor.href = this.anchor.href.replace('youtu.be/', 'youtube.com/watch?v=');
},
thumbEvent: function (e) {
let time = +this.dataset.time || 1;
if (this.classList.contains('ytm_trigger') && e.type === 'mouseenter' && time < 50) {
this.dataset.thumb = ((this.dataset.thumb || 0) + 1) % 3;
this.style.backgroundImage = `url(https://i3.ytimg.com/vi/${this.dataset.ytmid}/${(+this.dataset.thumb) + 1}.jpg)`;
window.clearTimeout(this.dataset.timeout);
console.log('mouseenter -- clear before setting new ', this.dataset);
this.dataset.timeout = window.setTimeout(Container.decorators.youtube.thumbEvent.bind(this, e), 800);
console.log('mouseenter -- new timeout', this.dataset);
this.dataset.time = time += 1;
} else {
window.clearTimeout(this.dataset.timeout);
this.dataset.time = 0;
console.log('mouseleave -- ', this.dataset);
}
}
}
};
Container.events = {
setup: () => {
Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["on"])(document.body, 'click', 'var[data-ytmuid]', Container.events.fromTarget);
Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["on"])(document.body, 'click', 'a[data-ytmdescription]', Container.events.manualLoad);
Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["on"])(document.body, 'dblclick', 'q[data-full]', Container.events.titleToggle);
Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["on"])(document.body, 'mouseenter mouseleave', 'div.ytm_site_youtube span.ytm_trigger', Container.decorators.youtube.thumbEvent);
},
fromTarget: ({ target }) => { // trigger the ui
console.info('ytma//click+trig(id)', target.dataset.ytmuid);
Control.createFromTrigger(target).showPlayer();
},
manualLoad: e => {
e.preventDefault();
const { target } = e;
console.info('ytma//click+desc(id)', target.dataset.ytmid);
if ((target.dataset.tries || 0) <= 4) {
Y.ajax.loadFromDataset(target.dataset);
}
},
titleToggle: e => {
const target = e.target;
target.classList.toggle('ytm_descr_open');
target.textContent = target.textContent.length < 140 ? target.dataset.full : `${target.dataset.full.substr(0, 130)} . . .`;
target.removeAttribute('style');
}
};
Y.num = 0;
Y.addToSet = ytma => Y.set[ytma.state.uid] = ytma;
Y.create = link => Y.grabIdAndSite(link, (data, err) => {
if (err) {
console.warn(link.href, err);
return {};
}
const control = new Control({ ...data, anchor: link });
Y.addToSet(control);
control.createInterface();
return control;
});
Y.grabIdAndSite = (link, cb) => {
let uri = link.href || link.src;
let id;
let match;
try {
const site = Y.reg.siteByTest[Y.reg.siteExpressions.test(uri) ? RegExp.lastMatch : ''];
// console.log(site);
if (site === 'html5') { // || site === 'html5-audio'
id = uri.slice(-15);
} else if (site === 'soundcloud') {
if (!Y.reg.extra.soundcloud.playlist.test(uri)) {
link.href = uri = Y.reg.fix.soundcloud(uri);
}
match = Y.DB.sites.soundcloud.matcher.exec(uri);
id = Y.escapeId(match[1]);
if (match && Y.reg.extra.soundcloud.tracks.test(uri)) {
id = id.slice(-50);
}
} else {
id = uri.match(Y.DB.sites[site].matcher)[1];
}
console.info('ytma//id+site', id, site, match);
if (id && Y.DB.sites[site]) {
return cb({ id, site }, null);
}
throw TypeError(`Invalid ID/Site: ${id} @ ${site}`);
} catch (e) {
return cb(null, e);
}
};
Y.escapeId = id => `${id}`.replace(/(?:\W)/g, '_');
Y.set = {};
Y.collect = id => {
const a = Object.values(Y.set).filter(ytma => ytma && ytma.data.id === id);
return a;
};
Y.route = {
host: document.location.host.replace('www.', ''),
control: {
$: {
checkStorage: function () {
if (_modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].full() === true) {
console.log('YTMA ERROR: Storage is full!');
try {
localStorage.removeItem(Y.external.version);
_modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].on = _modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].test();
} catch (e) {
console.error(e);
}
}
},
runOnce: function (loop) {
if (!document.body.dataset.ytmaenabled) {
document.body.dataset.ytmaenabled = true;
this.checkStorage();
if (!Y.DB.extension) { _modules_update__WEBPACK_IMPORTED_MODULE_3__["default"].check(); }
Y.css();
Y.user.init();
Y.DB.postInit();
if (loop) {
document.body.dataset.YTMA_LOOP = window.setInterval(loop, 5000);
loop();
}
Container.events.setup();
}
}
},
go: function (host) {
console.info('ytma//host', host);
if (/(?:googlevideo|youtube-nocookie\.com|youtube\.com\.?)/i.test(host)) {
this.sites.youtube();
} else if (this.sites[host]) {
this.sites[host]();
} else {
this.sites.$generic();
}
},
sites: {
$generic: function () {
function loop() {
if (Y.selector.processor() > 0) {
Y.user.fn.loadPreferences();
}
console.info('ytma//again++');
}
Y.route.control.$.runOnce(loop);
},
'resetera.com': function () {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css('.ytm_options li ul li { height: 24px !important }');
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css('.bbCodeQuote .quoteContainer .quote { max-height: initial } .bbCodeQuote .quoteContainer .quoteExpand.quoteCut { display: none }');
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css('.bbCodeQuote .ytm_block iframe, .bbCodeQuote .ytm_block [data-s9e-mediaembed], .bbCodeQuote .ytm_block .fb_iframe_widget, .bbCodeQuote .ytm_block object, .bbCodeQuote .ytm_block embed { max-height: initial; max-width: initial }');
this.$generic();
},
'gfycat.com': function () {
const v = document.querySelector('video');
v.controls = true;
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css('body,html {overflow:hidden;height:100%;width:100%} video {display:table;height:100%;margin:0 auto;}');
document.body.appendChild(v);
},
'vine.co': function () {
// console.log('vine.co');
window.addEventListener('resize', () => {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s('[style]', e => {
e.removeAttribute('style');
});
});
},
youtube: function () { // lets force some quality parity
}
}
},
load: function () {
this.control.go(this.host);
}
};
Y.main = () => {
Y.reg.siteExpressions = Y.reg.getAllSiteRegExps();
// console.log(YTMA.reg.siteExpressions);
Y.route.load();
};
Y.reg = {
siteExpressions: null,
time: /(?:t=(?:(\d+)h)?(?:(\d+)m)?(\d+))/,
ios: /(?:\b(?:ipod|iphone|ipad))\b/i,
extra: {
soundcloud: {
playlist: /(?:soundcloud\.com\/.+\/sets\/)/,
tracks: /(?:soundcloud\.com\/.+\/tracks\/)/
}
},
siteByTest: {
youtu: 'youtube',
vimeo: 'vimeo',
vine: 'vine',
gfycat: 'gfycat',
imgur: 'imgur',
'.webm': 'html5',
'.mp4': 'html5',
// '.mp3': 'html5-audio',
'.gifv': 'html5',
soundcloud: 'soundcloud',
'streamable.com': 'streamable'
},
getAllSiteRegExps: function () {
const regs = Object.values(Y.DB.sites)
.filter(({ reg }) => reg)
.map(({ reg }) => reg);
return new RegExp(`\\b${regs.join('|')}`);
},
fix: {
soundcloud: function (uri) {
const match = Y.DB.sites.soundcloud.matcher.exec(uri);
if (match) {
const id = match[1].split('/', 2).join('/');
uri = Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["removeSearch"])(`https://soundcloud.com/${id}`, true);
}
return uri;
}
}
};
Y.selector = { // to build the selector
parentBlacklist: ['.smallfont', '.colhead_dark', '.spoiler', 'pre', '.messageUserInfo', '.fr-box'],
getAllSiteSelectors: function () {
const sels = Object.values(Y.DB.sites)
.filter(({ selector }) => selector)
.map(({ selector }) => selector);
return sels.join();
},
ignore: function () {
const ignore = [];
const all = Y.selector.getAllSiteSelectors().split(',');
const blacklist = this.parentBlacklist;
for (let i = 0; i < blacklist.length; i++) {
for (let j = 0; j < all.length; j++) {
ignore.push(`${blacklist[i]} ${all[j]}`);
}
}
// console.log(ignore.join(','));
return ignore.join(',');
},
iframes: function () { // for resetera, convert iframes back to anchors
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s('.message-body iframe', f => {
if (/vi\/(.+?)\/hqdefault/.test(f.style.backgroundImage)) {
const src = `https://youtu.be/${RegExp.$1}`;
const span = f.closest('[data-s9e-mediaembed]');
span.insertAdjacentHTML('beforebegin', `<a href="${src}">youtube</a>`);
span.parentElement.removeChild(span);
}
});
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s('[data-s9e-mediaembed-iframe]', s => {
const dat = JSON.parse(s.dataset.s9eMediaembedIframe);
s.parentElement.parentElement.innerHTML = `<a href="${dat[dat.length - 1]}">youtube</a>`;
});
},
links: function () {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(Y.selector.ignore(), ({ dataset }) => dataset.ytmaignore = true);
const links = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].qsa(Y.selector.getAllSiteSelectors()).filter(({ dataset }) => {
const r = !dataset.ytmaprocessed && !dataset.ytmaignore;
dataset.ytmaprocessed = true;
return r;
});
return links;
},
processor: function () {
this.iframes();
const links = this.links();
if (links.length > 0) {
links.forEach(Y.create);
}
return links.length;
}
};
/**
* User Preferences
* size: Small (240p), Medium (360p), Large (480p), XL (720p)
* ratio: 1 4:3, 2 16:9
* quality: 240, 360, 480, 720, 1080
* focus: 0/1; Will attempt to set the window's focus near the video
* autoShow: 0/1; Will automatically display HTML5 videos, which currently lack descriptions and thumbnails
* desc: (Descriptions) 0 None; 1 Yes on scroll; 2 Yes all at once
* yt_nocookie: 0/1; Will disable/enable youtube-nocookie.com
* yt_annotation: 0/1; youtube annotations
*/
Y.user = {
KEY: 'ytmasetts',
$form: null,
init: function () {
this.load();
if (_modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].on) {
this.fn.makeForm();
this.mark();
}
},
valid: {
focus: [0, 1],
desc: [0, 1, 2],
ratio: [1, 2],
size: [240, 360, 480, 720],
quality: [240, 360, 480, 720, 1080],
autoShow: [0, 1],
yt_nocookie: [0, 1],
yt_annotation: [0, 1] // hide | show
},
mapping: { // map values to some other values used by an external API, for example
yt_annotation: [3, 1] // 3 = hide | 1 = show
},
validate: function (property, n) {
n = +n;
return Y.user.valid[property].includes(n) ? n : Y.user.defaults[property];
},
get defaults() {
return {
focus: 0,
desc: 1,
ratio: 2,
size: 360,
quality: 720,
autoShow: 1,
yt_nocookie: 0,
yt_annotation: 1
};
},
load: function () {
const s = _modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].grab(Y.user.KEY, {});
Y.user.preferences = Object.keys(this.defaults).reduce((valid, k) => {
valid[k] = Y.user.validate(k, s[k]);
return valid;
}, {});
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(Y.user.mapping, (key, val) => {
if (!val.hasOwnProperty('indexOf')) {
Y.user.preferences[key] = val[Y.user.valid[key].indexOf(Y.user.preferences[key])];
}
});
console.info('ytma//user+loaded(prefs)', Y.user.preferences);
},
mark: function () {
const a = {};
a.ytma__focus = !!Y.user.preferences.focus;
a.ytma__autoShow = !!Y.user.preferences.autoShow;
a.ytma__yt_nocookie = !!Y.user.preferences.yt_nocookie;
a.ytma__yt_annotation = !!Y.user.preferences.yt_annotation;
a[`ytma__ratio${Y.user.preferences.ratio}`] = true;
a[`ytma__size${Y.user.preferences.size}`] = true;
a[`ytma__desc${Y.user.preferences.desc}`] = true;
a[`ytma__quality${Y.user.preferences.quality}`] = !!Y.user.preferences.quality;
// console.log('marking', a);
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(a, (id, val) => {
try {
const el = document.getElementById(id);
el.checked = val;
el.value = val;
} catch (e) {
// console.log(id, e);
}
});
},
events: {
save: function () {
// console.log(YTMA.user.$form.querySelectorAll('[data-key]'));
// [data-key]:checked
const settings = Array.from(Y.user.$form.querySelectorAll('[data-key]')).reduce((obj, e) => {
let key = e.dataset.key;
if (e.type === 'checkbox') {
obj[key] = +e.checked;
} else if (e.type === 'radio') {
if (e.checked) {
if (e.dataset.num) {
obj[key] = +e.dataset.num;
}
}
} else {
obj[key] = +e.value;
}
return obj;
}, {});
if (_modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].save(Y.user.KEY, settings)) {
Y.user.load();
} else {
Y.user.error.classList.remove('ytm_none');
}
},
reset: function () {
Y.user.preferences = Y.user.defaults;
Y.user.mark();
_modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].wipe(Y.user.KEY);
Y.user.error.classList.add('ytm_none');
},
clear: function () {
try {
localStorage.removeItem(Y.external.version);
Y.user.events.reset();
console.info('ytma//cache+remove', 'removed all YTMA cache');
} catch (e) {
console.error(e);
}
},
formToggle: function (e) {
if (Y.user.$form && (!e || (e && e.target && !(/(?:INPUT|LABEL)/i).test(e.target.nodeName)))) {
Y.user.$form.classList.toggle('ytm_none');
}
},
formToggleKeyboard: function (e) {
// press CTRL+SHIFT+Y (META+SHIFT+Y) to display settings form
if ((e.ctrlKey || e.metaKey) && e.shiftKey && String.fromCharCode(e.which).toLowerCase() === 'y') {
e.preventDefault();
Y.user.events.formToggle();
}
}
},
fn: {
$scroller: null,
$once: false,
loadPreferences: function () {
Y.user.fn.onScrollLoadDescriptions(Y.user.preferences.desc === 1);
this.loadPreferencesOnce();
},
loadPreferencesOnce: function () {
if (this.$once) { return; }
this.$once = true;
if (Y.user.preferences.autoShow === 1) {
Y.user.fn.onScrollViewMedia();
}
},
showMedia: function () {
// console.info('ytma//user+fn-showMedia');
return new Scroll('a.ytm_scroll:not([data-ytmscroll="false"])', link => {
if (Scroll.visibleAll(link, 50)) {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(`var[data-ytmsid="${link.dataset.ytmsid}"]:not([data-ytmscroll="false"])`, trigger => {
const ui = Control.createFromTrigger(trigger);
ui.showOnScroll(link);
});
}
});
},
toggleMedia: function () {
return new Scroll('div.ytm_panel_switcher', div => {
const v = div.querySelector('video');
const paused = v && (v.paused || v.ended);
const ui = Y.set[div.dataset.ytmuid].getControl();
if (paused && !Scroll.visibleAll(div, 0)) {
return ui.play.switchStandby();
}
if (ui.play.isStandby() && Scroll.visibleAll(div, 200)) {
return ui.play.switchOn();
}
// todo ascertain embedded player properties
// f = div.querySelector('iframe, object');
// if (f && !YTMA.Scroll.visibleAll(div, 200)) {
// y.hidePlayer();
// }
});
},
onScrollViewMedia: function () {
this.showMedia();
this.toggleMedia();
},
onScrollLoadDescriptions: function (ajax) {
if (Y.user.fn.$scroller) { Y.user.fn.$scroller.stop(); }
Y.user.fn.$scroller = new Scroll('span.ytm_manual > a.ytm_title:not(.ytm_error)', a => {
if (Scroll.visibleAll(a, 200)) {
if (ajax) {
Y.ajax.loadFromDataset(a.dataset);
} else {
Y.ajax.loadFromCacheDataset(a.dataset);
}
// console.log('doc', document.querySelectorAll(YTMA.user.fn.$scroller.selector).length, a.dataset.id);
}
if (document.querySelectorAll(Y.user.fn.$scroller.selector).length === 0) {
Y.user.fn.$scroller.stop();
}
});
},
makeForm: function () {
const template = `
<div id="ytm_settings" class="ytm_sans ytm_block ytm_normalize">
<form action="" title="Double click to close">
<div id="ytm_settingst">ytma! Site Settings</div><div class="ytm_field_container">
<fieldset><legend title="Load descriptions from the content sever.">Load Descriptions</legend><p><span><input id="ytma__desc0" type="radio" data-num="0" name="ytma__desc" data-key="desc"><label for="ytma__desc0" title="Load descriptions on demand">Manually</label></span><span><input id="ytma__desc1" type="radio" data-num="1" name="ytma__desc" data-key="desc"><label for="ytma__desc1" title="Load descriptions as they become visible on the screen.">Automatically, on scrolling</label></span></p></fieldset>
<fieldset><legend>HTML5 Players</legend><p><input name="ytma__autoShow" data-key="autoShow" id="ytma__autoShow" type="checkbox"><label for="ytma__autoShow">Automatically show WebM, MP4 and Soundcloud players</label></p></fieldset>
<fieldset><legend>Player Size</legend><p><span><input type="radio" name="ytma__size" data-key="size" data-num="240" id="ytma__size240" /><label for="ytma__size240">S <small>240p</small></label></span><span><input name="ytma__size" data-key="size" type="radio" id="ytma__size360" data-num="360" /><label for="ytma__size360">M <small>360p</small></label></span><span><input type="radio" name="ytma__size" data-key="size" data-num="480" id="ytma__size480" /><label for="ytma__size480">L <small>480p</small></label></span><span><input type="radio" name="ytma__size" data-key="size" data-num="720" id="ytma__size720" /><label for="ytma__size720">X <small>720p</small></label></span></p></fieldset>
<fieldset><legend>Quality</legend><p><span><input name="ytma__quality" data-key="quality" data-num="240" id="ytma__quality240" type="radio"><label for="ytma__quality240">240p</label></span><span><input name="ytma__quality" data-key="quality" id="ytma__quality360" data-num="360" type="radio"><label for="ytma__quality360">360p</label></span><span><input name="ytma__quality" data-key="quality" data-num="480" id="ytma__quality480" type="radio"><label for="ytma__quality480">480p</label></span><span><input name="ytma__quality" data-key="quality" data-num="720" id="ytma__quality720" type="radio"><label for="ytma__quality720">720p</label></span><span><input name="ytma__quality" data-key="quality" data-num="1080" id="ytma__quality1080" type="radio"><label for="ytma__quality1080">1080p</label></span></p></fieldset>
<fieldset><legend>Aspect Ratio</legend><p><span><input name="ytma__ratio" data-key="ratio" type="radio" id="ytma__ratio2" data-num="2" /><label for="ytma__ratio2">16:9</label></span><span><input type="radio" name="ytma__ratio" data-key="ratio" data-num="1" id="ytma__ratio1" /><label for="ytma__ratio1">4:3</label></span></p></fieldset>
<fieldset><legend>YouTube</legend>
<p><input name="ytma__yt_annotation" data-key="yt_annotation" type="checkbox" id="ytma__yt_annotation" /><label for="ytma__yt_annotation">Enable video annotations</label></p>
<p><input name="ytma__yt_nocookie" data-key="yt_nocookie" type="checkbox" id="ytma__yt_nocookie" /><label for="ytma__yt_nocookie">Use https://youtube-nocookie.com to load videos</label></p>
</fieldset>
<fieldset><legend>Window Focus</legend><p><input name="ytma__focus" data-key="focus" type="checkbox" id="ytma__focus" value="focus" /><label for="ytma__focus">After clicking the thumbnail, set the video at the top of the window.</label></p></fieldset>
</div>
<p><small id="ytm_settings_error" class="ytm_error ytm_none ytm_title">Error! Your settings could not be saved.</small></p>
<p id="ytm_opts">
<button type="button" id="ytmaclose">Close</button> <button type="button" id="ytmareset">Reset</button> <button type="button" id="ytmaclear" title="Remove all video descriptions that have been cached">Reset & Remove Cache</button>
</p>
</form>
</div>`;
Y.user.$form = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('div', { className: 'ytm_fix_center ytm_none ytm_box', innerHTML: template }, document.body);
Y.user.error = document.getElementById('ytm_settings_error');
Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["on"])(Y.user.$form, 'keyup click', 'input, label', Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["debounce"])(Y.user.events.save, 500));
Y.user.$form.addEventListener('submit', e => e.preventDefault(), false);
document.getElementById('ytmareset').addEventListener('click', Y.user.events.reset, false);
document.getElementById('ytmaclear').addEventListener('click', Y.user.events.clear, false);
// close
Y.user.$form.addEventListener('dblclick', Y.user.events.formToggle, false);
document.getElementById('ytmaclose').addEventListener('click', Y.user.events.formToggle, false);
document.body.addEventListener('keydown', Y.user.events.formToggleKeyboard, false);
}
}
};
Y.css = () => {
const playerCss = Player.css.generator();
const loadingIcon = 'data:image/gif;base64,R0lGODlhDgAKAJEAAP///+BKV////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAADgAKAAACHFSOeQYI71p6MtAJz41162yBH+do5Ih1kKG0QgEAIfkEBQoAAgAsAAABAA0ACAAAAhSUYGEoerkgdIzKGlu2ET/9ceJmFAAh+QQFCgACACwAAAEADQAIAAACFJRhcbmiglx78SXKYK6za+NxHyYVACH5BAUKAAIALAAAAQANAAgAAAIWVCSAl+hqEGRTLhtbdvTqnlUf9nhTAQAh+QQFCgACACwAAAEADQAIAAACFZRiYCh6uaCRzNXYsKVT+5eBW3gJBQAh+QQJCgACACwAAAAADgAKAAACGpSPaWGwfZhwQtIK8VTUvuxpm9Yp4XlmpiIUADs=';
// console.log(playerCss);
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css(playerCss);
// images
// todo update(site, size, padding)
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css(`
.ytm_loading{background:url(${loadingIcon}) 0 3px no-repeat;}
.ytm_link{position:relative !important;background:url(${Y.DB.sites.youtube.favicon}) 0 center no-repeat !important;margin-left:4px;padding-left:20px!important;}
.ytm_link.ytm_link_vimeo{background-image:url(${Y.DB.sites.vimeo.favicon}) !important;background-size:12px 12px !important;padding-left:18px!important}
.ytm_link.ytm_link_vine{background-image:url(${Y.DB.sites.vine.favicon}) !important;background-size:10px 10px!important;padding-left:16px!important}
.ytm_link.ytm_link_soundcloud{background-image:url(${Y.DB.sites.soundcloud.favicon})!important;padding-left:17px!important}
.ytm_link.ytm_link_html5{background-image:url(${Y.DB.sites.html5.favicon}) !important;padding-left:16px!important}
.ytm_link.ytm_link_gfycat{background-image:url(${Y.DB.sites.gfycat.favicon}) !important;background-size:12px 12px !important;padding-left:16px!important;}
.ytm_link.ytm_link_imgur{background-image:url(${Y.DB.sites.imgur.favicon}) !important;background-size:12px 12px !important;padding-left:16px!important}
.ytm_link.ytm_link_streamable{background-image:url(${Y.DB.sites.streamable.favicon}) !important; background-size: 12px 12px !important;padding-left: 14px !important;}
`);
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].css('.ytm_none,.ytm_link br{display:none!important}.ytm_box{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ytm_block{display:block;position:relative;clear:both;text-align:left;border:0;margin:0;padding:0;overflow:hidden}.ytm_normalize{font-weight:400!important;font-style:normal!important;line-height:1.2!important}.ytm_sans{font-family:Arial,Helvetica,sans-serif!important}.ytm_spacer{overflow:auto;margin:0 0 6px;padding:4px}.ytm_spacer.ytm_site_slim{display:inline}.ytm_clear:after{content:"";display:table;clear:both}.ytm_center{text-align:center}.ytm_link b,.ytm_link strong{font-weight:400!important}.ytm_link u{text-decoration:none!important}.ytm_link i,.ytm_link em{font-style:normal!important}.ytm_trigger{width:118px;height:66px;background-color:#262626!important;cursor:pointer;background-position:-1px -12px;float:left;box-shadow:2px 2px rgba(0,0,0,.3);background-size:auto 90px!important;color:#fff;text-shadow:#333 0 0 2px;font-size:13px}.ytm_trigger:hover{box-shadow:2px 2px #60656b80;opacity:.95}.ytm_trigger var{z-index:2;height:100%;width:100%;position:absolute;left:0;top:0;text-align:right}.ytm_label{display:block;padding:3px 6px;line-height:1.2;font-style:normal}.ytm_init{height:22px;background:rgba(11,11,11,.62);padding:4px 25px 6px 6px}.ytm_site_vine .ytm_trigger{background-color:#90ee90!important;background-size:120px auto!important}.ytm_site_slim .ytm_trigger{background:#e34c26!important;height:auto;box-shadow:0 0 2px #ffdb9d inset,2px 2px rgba(0,0,0,.3);margin:0 3px 0 0;width:auto;transition:all .3s ease-in-out 0s}.ytm_site_slim .ytm_trigger:hover{opacity:.8}.ytm_site_slim .ytm_label{text-shadow:0 0 1px #f06529}.ytm_site_slim .ytm_init{background:transparent}.ytm_bd{float:left;max-width:450px;margin:2px 10px;font-size:12px}.ytm_title{font-weight:700}.ytm_error{color:#cc2f24;font-style:italic}.ytm_loading{font-style:italic;padding:1px 1.5em}.ytm_descr{word-wrap:break-word;max-height:48px;overflow:auto;padding-right:20px}.ytm_descr[data-full]{cursor:pointer}.ytm_descr_open{resize:both;white-space:pre-line;background:linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 50%,rgba(0,0,0,0) 80%,rgba(0,0,0,0.1) 100%)}.ytm_descr_open[style]{max-height:none}.ytm_projector{margin-bottom:4px}ul.ytm_options{overflow:hidden;margin:0!important;padding:3px 0 1px;list-style-position:outside!important}.ytm_options li{display:inline;margin:0!important;padding:0!important}.ytm_options li>ul{display:inline-block;margin:0;padding:0 1px 0 0}.ytm_options li ul li{-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;user-select:none;list-style-type:none;cursor:pointer;float:left;color:#858585;border:1px solid #1d1d1d;border-bottom:1px solid #181818;border-top:1px solid #292929;box-shadow:0 0 1px #555;height:14px;font-size:12px!important;line-height:12px!important;background:#222;background:linear-gradient(#2d2c2c,#222);margin:0!important;padding:5px 9px 3px!important}.ytm_options li ul li:first-child{border-radius:2px 0 0 2px}.ytm_options li ul li:last-child{border-left:0!important;border-radius:0 2px 2px 0;margin:0 2px 0 0!important}.ytm_options li ul li:first-child:last-child,.ytm_li_setting{border-radius:2px}.ytm_options li ul li:hover{color:#ccc;text-shadow:1px 1px 0 #333;background:#181818}.ytm_options li ul li[id]{color:#ddd;text-shadow:0 0 2px #444}.ytm_panel_size{background:#000;max-width:100%;}.ytm_panel_switcher[data-standby="true"]{background:#111}.ytm_panel_switcher[data-standby="true"]:after{cursor:cell;color:#0e0e0e;content:"ytma!";display:block;font-size:85px;font-style:italic;font-weight:700;left:50%;position:absolute;text-shadow:2px 1px #181818,-1px -1px #0a0a0a;top:50%;transform:translate(-50%,-50%)}.ytm_site_soundcloud .ytm_panel_size.ytm_soundcloud-playlist{height:334px!important}.ytm_fix_center{background:rgba(51,51,51,.41);height:100%;left:0;position:fixed;top:0;width:100%;z-index:99998}#ytm_settings{z-index:99999;max-width:500px;max-height:85%;overflow:auto;background:#fbfbfb;border:1px solid #bbb;color:#444;box-shadow:0 0 5px rgba(0,0,0,.2),0 0 3px rgba(239,239,239,.1) inset;margin:4% auto;padding:4px 8px 0}#ytm_settings p{margin:5px 0;padding:0}#ytm_settings fieldset{vertical-align:top;border-radius:3px;border:1px solid #ccc;margin:0 0 5px;padding:3px}#ytm_settings legend{padding:3px}#ytm_settings fieldset span{display:inline-block;min-width:5em}#ytm_settings input{vertical-align:baseline!important;margin:3px 5px!important}#ytm_settingst{font-size:110%;border-bottom:1px solid #d00;margin:3px 0 9px;padding:0 3px 3px}#ytm_settings label{cursor:pointer}#ytm_settings small{font-size:90%}#ytm_opts button{cursor:pointer;margin:10px 5px 8px 2px;padding:3px;border:1px solid #adadad;border-radius:2px;background:#eee;font-size:90%}#ytm_opts button:hover{background:#ddd}');
};
Y.ajax = {
load: function (site, id, uri) {
console.info('ytma//ajax+load(id)', site, id, uri);
uri = Y.DB.sites[site].ajax.replace('%key', id).replace('%uri', uri);
if (Y.DB.sites[site].ajaxExtension) { return this.gmxhr(uri, site, id); }
console.info('ytma//ajax+load(uri)', Y.DB.sites[site].ajax.replace('%key', id).replace('%uri', uri));
if (Y.DB.sites[site].ajax) {
// console.log('preping uri');
return this.xhr(uri, site, id);
}
return null;
},
loadFromDataset: function (dataset) {
if (!this.loadFromCacheDataset(dataset)) {
return this.load(dataset.ytmsite, dataset.ytmid, dataset.ytmuri);
}
},
loadFromCacheDataset: function ({ ytmsite, ytmid }) {
const cache = Y.external.dataFromStorage(ytmsite, ytmid);
console.info('ytma//ajax+cache(id)', ytmsite, ytmid);
console.info('ytma//ajax+cache(data)', cache);
if (cache) { Y.external.populate(cache); }
return cache;
},
gmxhr: function (uri, site, id) {
try {
// console.log('gmxhr starting!');
GM.xmlhttpRequest({
method: 'GET',
url: uri,
onload: function ({ responseText }) {
// console.log(response);
Y.external.parse(responseText, site, id);
},
onerror: function () {
console.log('GM Cannot XHR');
Y.ajax.failure.call({ id });
}
});
Y.ajax.preProcess(id);
} catch (e) {
if (Y.DB.extension) {
console.info('ytma//gmxhr-cors');
this.xhr(uri, site, id);
} else {
console.log('No applicable CORS request available.');
this.failure.call({ id });
}
}
},
xhr: function (uri, site, id) {
const x = new XMLHttpRequest();
console.info('ytma//xhr', uri, id, site);
Y.ajax.preProcess(id);
x.onreadystatechange = function () {
if (this.readyState === this.DONE) {
// console.log(this.readyState, this.status);
if (this.status === 200) {
Y.external.parse(this.responseText, site, id);
} else if (this.status === 403) {
Y.external.populate({ site, id, title: 'Error 403', desc: '' });
Y.external.save({ site, id, title: 'Error 403', desc: '' });
} else { // if (this.status >= 400 || this.status === 0) {
Y.ajax.failure.call({ id });
}
}
};
try {
// console.info('ytma//xhr+sending');
x.open('get', uri, true);
x.send();
} catch (e) {
console.error('ytma//xhr+failed(cannot send xhr)', uri);
Y.ajax.failure.call({ id });
console.error(e);
}
},
failure: function () {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(`.ytm_bd._${Y.escapeId(this.id)}`, el => {
const a = el.querySelector('a');
a.dataset.tries = a.dataset.tries ? parseFloat(a.dataset.tries) + 1 : 1;
if (a.dataset.tries >= 5) {
a.textContent = 'Max attempts reached';
} else {
a.textContent = `Error, unable to load data.${a.dataset.tries > 1 ? '' : ' [Retry]'}`;
}
a.className = 'ytm_error ytm_title';
});
},
preProcess: function (id) {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(`.ytm_manual._${Y.escapeId(id)} a`, el => {
el.classList.add('ytm_loading');
el.textContent = 'Loading';
el.title = 'Retry loading data.';
});
}
};
/** E X T E R N A L Apparatus
* Data from external sites
*/
Y.external = {
version: 'ytma.4.1.dat',
parse: function (response, site, id) {
if (this.parsers[site]) {
response = Y.DB.sites[site].rawResponse ? response : JSON.parse(response);
this.populate(this.helper.cutDescription(this.parsers[site](response, id)));
}
},
parsers: {
soundcloud: function ({ title, description, thumbnail_url }, id) {
return {
site: 'soundcloud',
id, //unescape(j.html).match(/tracks\/(\d+)/)[1],
title,
desc: description,
th: Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["removeSearch"])(thumbnail_url)
};
},
vimeo: function (j) {
j = j[0];
return {
site: 'vimeo',
id: j.id,
title: `${j.title} ${Y.external.time.fromSeconds(j.duration)}`,
desc: j.description.replace(/<br.?.?>/g, ''),
th: decodeURI(j.thumbnail_medium)
};
},
youtube: function (j, id) {
if (j.pageInfo.totalResults < 1 || j.items.length === 0) {
return { id, error: true };
}
j = j.items[0];
const o = {
site: 'youtube',
id,
title: `${j.snippet.title} ${Y.external.time.fromIso8601(j.contentDetails.duration)}`,
desc: j.snippet.description
// aspectRatio: j.contentDetails.aspectRatio
};
return o;
},
vine: function ({ title, thumbnail_url }, id) {
return {
site: 'vine',
id,
title,
th: Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["removeSearch"])(thumbnail_url)
};
},
gfycat: function (html, id) {
if (html) {
return {
site: 'gfycat',
id: id,
title: id
};
}
},
streamable: function ({ title }, id) {
return {
site: 'streamable',
id,
title: title || 'Untitled'
};
}
},
set: function (data) {
if (!this.db[data.site]) {
this.db[data.site] = {};
}
this.db[data.site][data.id] = data;
return this.save();
},
unset: function ({ site, id }) {
// console.log('unset', data.id);
if (site) {
delete this.db[site][id];
return this.save();
}
},
limitDB: function (max, db) {
// limits an object's items by half of the max
// removes the older items at the start of the object
const keys = Object.keys(db);
const half = Math.floor(max / 2);
let start;
let ndb;
let i;
if (keys.length > max) {
ndb = {};
start = keys.length - half;
for (i = start; i < keys.length; i++) {
ndb[keys[i]] = db[keys[i]];
}
}
return ndb || db;
},
save: function () {
this.db = this.limitDB(1000, this.db);
return _modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].save(this.version, this.db);
},
helper: {
cutDescription: function (data) {
if (data.desc && data.desc.length > 140) {
data.full = data.desc;
data.desc = `${data.desc.substr(0, 130)} . . .`;
}
return data;
},
thumbnail: function ({ id, th }) {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(`[data-ytmid="${id}"].ytm_trigger`, el => el.setAttribute('style', `background: url(${th})`));
}
},
time: {
keepMinutesAndSeconds: function (v, i) {
return i > 1 || v > 0;
},
leadingZero: function (v, i) {
return i > 0 ? (`00${v}`).slice(-2) : v;
},
fromArray: function (a) {
// [days, hours, mins, secs]
let b;
let p = '';
try {
// Remove empty values, but keep lower indexes (m:s); a[i] > 0 || i > 1
// Add leading 0's, ignoring the first index
// a.slice(0, 1).concat(a.slice(1))
b = a.filter(this.keepMinutesAndSeconds).map(this.leadingZero);
p = `(${b.join(':')})`;
} catch (e) {
console.error('Could not parse this time.');
}
console.info('ytma//time+array', { a, b, p });
return p;
},
fromIso8601: function (iso8601) {
// eg PT3M, T29S
let a;
const parseDigits = reg => {
if (reg.test(iso8601)) {
return RegExp.lastParen;
}
return 0;
};
// P#DT#H#M#S || PT#H#M#S
a = [/(\d+)D/, /(\d+)H/, /(\d+)M/, /(\d+)S/].map(parseDigits);
return this.fromArray(a);
},
fromSeconds: function (seconds) {
const a = [
Math.floor(seconds / 86400) % 24,
Math.floor(seconds / 3600) % 60,
Math.floor(seconds / 60) % 60,
seconds % 60
];
return this.fromArray(a);
}
},
validate: function (data) {
if (!data || !data.id || data.error) {
return Y.ajax.failure.call(data);
}
// todo? empty titles and descriptions should be okay
// if (data.id && !data.title && !data.desc) {
// this.unset(data.id);
// return YTMA.ajax.failure.call(data);
// }
return true;
},
populate: function (data, ignoreValidation) {
if (!ignoreValidation && !this.validate(data)) { return; }
this.set(data);
const { id, th, full, desc, title } = data;
if (th) { this.helper.thumbnail(data); }
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(`.ytm_bd._${Y.escapeId(id)}`, el => {
el.innerHTML = `<span class="ytm_title">${title}</span>`;
if (desc) {
const q = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('q', { className: 'ytm_descr ytm_block', textContent: desc }, el);
if (full.length > desc.length) {
q.dataset.full = full;
q.title = 'Double click to toggle the description.';
}
}
});
},
dataFromStorage: function (site, id) {
if (this.db && this.db[site]) {
return this.db[site][id];
}
}
};
Y.external.db = _modules_strg__WEBPACK_IMPORTED_MODULE_2__["default"].grab(Y.external.version, {});
/** Database */
Y.DB = {
postInit: function () {
if (Y.user.preferences.yt_nocookie) {
Y.DB.sites.youtube.home = 'https://www.youtube-nocookie.com/';
Y.DB.sites.youtube.embed = 'https://www.youtube-nocookie.com/embed/%key';
}
},
extension: window.chrome && window.chrome.extension,
sites: { // supported sites - to add more also make a parser (if api is available) and add an item to sources (if necessary)
youtube: {
title: 'ytma!',
home: 'https://www.youtube.com/',
embed: 'https://www.youtube.com/embed/%key',
ajax: `https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%key${window.atob('JmtleT1BSXphU3lEVG5INkxzRERyVElYaFZTZWRQQjlyRHo1czBSczQzZnM=')}`,
thumb: 'url(https://i3.ytimg.com/vi/%key/1.jpg)',
selector: 'a[href*="youtube."], a[href*="youtu.be/"]',
favicon: 'https://www.youtube.com/favicon.ico',
key: 'id',
reg: '(youtu)',
matcher: /(?:(?:(?:v=|#p\/u\/\d*?\/)|(?:v=|#p\/c\/[a-zA-Z0-9]+\/\d*?\/)|(?:embed\/)|(?:v\/)|(?:\.be\/))([A-Za-z0-9-_]{11}))/i,
https: true
},
vimeo: {
title: 'vimeo too!',
home: 'https://vimeo.com/',
embed: 'https://player.vimeo.com/video/%key?badge=0',
ajax: 'https://vimeo.com/api/v2/video/%key.json',
selector: 'a[href*="vimeo.com/"]',
favicon: 'https://f.vimeocdn.com/images_v6/favicon.ico',
key: 'id',
reg: '(vimeo)',
matcher: /(?:vimeo\.com\/(\d+))/i,
https: true
},
vine: {
title: 'vine me!',
home: 'https://vine.co/',
embed: 'https://vine.co/v/%key/embed/simple?audio=1',
ajaxExtension: true,
ajax: 'https://vine.co/oembed.json?url=https%3A%2F%2Fvine.co%2Fv%2F%key',
selector: 'a[href*="vine.co/"]',
favicon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABcklEQVQ4jX2SvyvFYRTGP+9NdzAYbpIkysA/ICnKoEwvA4vlUkoyGQzvoOiK4R0YbDLhDhbi9maWIjEqcScWkyRhMNzXcM/3On39OMt5nvOe85wfvSbGyH9mgs8Cq8AUkAMegU1gJVpXqfu3umpbwITiLUBB8HJGuryb4KMJ/izVvUMVnwNjwJPwGYCMkLL4zlT3XoUL0boD4FBNUhO4Fd9ogm9SRVmFn8Una79qgWuV2K3wvcLJdG3iL7TaiUocAI4Fn0vnHDBrgt+L1g2q3NoEl8CH4KHkMVr3CSwI7QeOTPA9WsAk/8AEvw+MSrwrWleuJQVfABZJWbTOZBTfVXg6lbgEHKjQTcL1BFngAWimeuH2aN2LvHUDV1JcjNbl0zdI9l0T2pDsboKvB7Yl/ga4X2+gku+AVqAC9AFzwLik5KN1xT8FRGQEOBL6yfdn2onWTZKyTDoQrSsB60KT4lNSh/1TQETmgQ1ZowQMy41+2BeLRXeRaKuHSAAAAABJRU5ErkJggg==',
key: 'id',
reg: '(vine)',
matcher: /(?:vine\.co\/v\/([A-Za-z0-9-_]{11}))/i
},
soundcloud: {
title: 'sound off!',
home: 'https://soundcloud.com/',
embed: 'https://w.soundcloud.com/player/?show_comments=false&url=%key',
ajax: 'https://soundcloud.com/oembed?format=json&url=%uri',
favicon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXZJREFUeNp0UjFOw0AQnD3bCYaEoIgiUIQKikiAKKGgSAkFL0BQ0FEgUfECShpewB+QEE+gokDiBxGRiCCEBBzHd8ucLYGQ4Kw7+9azc7OzJ6oKnFYUxgD+W/DHYNA54GIooifTitYqg1okaPFff6BcTLF5fECYb5IJNJ3kMfUP2dxHPycwcQ0SliARocSGsA46YkKWQW0GS6BDAGlu5Myu84AgSmHKM/DY0NegwwR2+AJrSjBre5BaA1H7GFKpI729QHp9jqiaeTBn5mB7fWirjWB9B9JYBrwEMnop5d0zfD53YO9vYMY8SQcpZGkTZvsIstiivDfoaxfIxt8exYeXCLYOSOwlJZQ6twSpL0DfX4EoZtkCqc7/Njalbxnfdt+oSwhurkBnCWI/1FlgqgKNZ3JnZDSA3FFSpYdQAoF56tKNDmhOYTzJ3OSHXZkflJhYEyawcnH02HpmxZ+DrRJlgmacvrsHRmHln2tRnIiAy5WTLwEGAK4QoBQmtGHkAAAAAElFTkSuQmCC',
selector: 'a[href*="soundcloud.com/"]',
key: 'uri',
reg: '(soundcloud)',
matcher: /(?:\/\/(?:\bwww|m\.\b)?soundcloud\.com\/(.+?\/.+))/i,
https: true,
scroll: true
},
gfycat: {
title: 'gfycat meow!',
home: 'https://gfycat.com/',
embed: 'https://gfycat.com/iframe/%key',
ajaxExtension: true,
rawResponse: true,
ajax: 'https://gfycat.com/%key',
thumb: 'url(https://thumbs.gfycat.com/%key-poster.jpg)',
selector: 'a[href*="gfycat.com/"]',
favicon: 'https://gfycat.com/favicon.ico',
key: 'id',
reg: '(gfycat)',
matcher: /(?:gfycat\.com\/(?:(\b(?:[A-Z][a-z]*){3,}\b)))/i,
https: true,
scroll: true
},
streamable: {
title: 'streamable!',
home: 'https://streamable.com/',
embed: 'https://streamable.com/e/%key',
ajax: 'https://api.streamable.com/oembed.json?url=%uri',
thumb: 'url(https://cdn.streamable.com/image/%key.jpg)',
selector: 'a[href*="streamable.com/"]',
favicon: 'https://streamable.com/favicon.ico',
key: 'id',
reg: '(streamable\\.com)',
matcher: /(?:streamable\.com\/([A-Za-z0-9-_]+))/i,
https: true
},
imgur: {
title: 'imgur it!',
home: 'https://i.imgur.com/',
embed: 'https://i.imgur.com/%key',
thumb: 'url(https://i.imgur.com/%keyh.jpg)',
selector: 'a[href*=".gifv"]',
favicon: 'https://imgur.com/favicon.ico',
reg: '(\\.gifv$)|(imgur)',
matcher: /(?:imgur\.com\/(\w+)\.(?:gifv|mp4|webm))/i,
https: true,
scroll: true,
videoTag: true
},
html5: {
home: true,
title: 'html5 go!',
selector: 'a[href*=".webm"], a[href*=".mp4"]',
favicon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdlJREFUeNpcks9rE0EUx7+b3TRktxvbhUhrNm6SrUWtxxbxJ9iLl0JFKWg8WLD05EWhIuRieogXwYPX4tGb/gPSq/oP6KH+uG2MFaRJJXaTbp7fWbsl+uDDzLx533lv3ozmeyUM2VlSJxeISULygTwhr5Og1JDgOXlPrpLRMAxTIpLlfJa8Ipv/i56Re4lT07SYKIqQSh2eO0/eqYnujI35HF8O19jr9XBneRmt1je0d3ag63qy5ZIAvNObE+WKTJXKktENoVPsrCntdlsWFxbiNXNJyS3KdMUXxv8w6LzY7XZhmiYer9fBYOTzR5HL5XCzWsWxYhFnTs/gxcYGgiCAZVmOyhR5BVcm8nlZvbsi29+3ZdgGg4Gs1+viua4UJiZVpkiJeqo0VaIqxbGPSKfTORRduXQ59peLx5PyItWaj9yDQtmt21XYto1GoxGvbywtxaNhGHE3ab+V6L6aKYczPo7ZuTk8WnuIWq2G64vX4JU8zJw8BXXv5D21gx+xydrn7VEb/f0+tj5twa/4+Pz1C6Y4Oo6DZrOJdDrdYuxkIlKP+ZbZzoV7e8iyk8kD/9rdRXpkBJlMpsmDC/98I97pPF//AQUBl/2/jRvsm5b1kxmeJgJlfwQYAKZQxgzeI6/EAAAAAElFTkSuQmCC',
reg: '(\\.webm$)|(\\.mp4$)',
slim: true,
scroll: true,
videoTag: true
},
'html5-audio': {
home: true,
title: 'hey, listen!',
selector: 'a[href*=".mp3"]',
reg: '(\\.mp3$)',
slim: true,
scroll: true
}
}
};
class Control extends Container {
/** U I CLASS
* Class for the player controls
* This is the control bar once the user clicks on the thumbnail
* Contains its own instance of a Player
* Acts like a decorator on the YTMA and Container intances by adding events
* @param {Y} ytma A YTMA instance
*/
constructor(props) {
super(props);
this.open = false;
this.selected = { size: null, ratio: null };
}
getControl() {
if (!this.projector) {
this.createProjector();
}
return this;
}
createProjector() {
super.createProjector();
this.projector.addEventListener('click', Control.events.videoBar.bind(this), false);
this.play = new Player(this);
this.markSelected(`li[data-type="size"][data-value="${this.play.attrs.size}"]`, 'size');
this.markSelected(`li[data-type="ratio"][data-value="${this.play.attrs.ratio}"]`, 'ratio');
}
resetViewSize() {
this.play.dimmensions();
this.setControlBarSize(this.play.attrs.size);
}
showOnScroll(link) {
if (!this.open && this.canShowUnder(link)) {
this.showPlayer();
}
}
showPlayer() {
this.open = true;
super.showPlayer();
this.attachPlayerPanel();
this.play.switchOn();
if (Y.user.preferences.focus) {
document.location.hash = `#${this.body.id}`;
}
}
hidePlayer() {
this.open = false;
this.play.switchOff();
super.hidePlayer();
}
attachPlayerPanel() {
if (!this.play.panel.parentNode) {
// console.log('attaching display panel');
this.projector.appendChild(this.play.panel);
}
}
hideAllPlayers() {
const group = Y.collect(this.state.id);
console.info('ytma//hide+all(id)', this.state.id, group.length);
group.forEach(g => {
g.disableOpenOnScroll();
g.getControl().hidePlayer();
});
}
setControlBarSize(size) {
this.markSelected(`li[data-type="size"][data-value="${size}"]`, 'size');
}
markSelected(el, type) {
if (typeof el === 'string') {
el = this.projector.querySelector(el);
}
el.id = type + this.state.uid;
try {
this.selected[type].removeAttribute('id');
} catch (e) { }
this.selected[type] = el;
}
}
Control.ratios = {
SD: 1,
HD: 2,
PORTRAIT: 3
};
Control.sizes = {
HIDDEN: 0,
S: 240,
M: 360,
L: 480,
X: 720
};
/** Trigger is the VAR element
* @param {HTMLElement} t VAR element
*/
Control.createFromTrigger = t => {
// console.info('ytma//trigger');
if (t && t.dataset.ytmuid && !Y.set[t.dataset.ytmuid]) {
console.info('ytma//trigger+new');
Y.addToSet(new Control().reactivate(t));
}
console.info('ytma//trigger+control');
return Y.set[t.dataset.ytmuid].getControl();
};
Control.events = {
$fire: {
settings: function () {
Y.user.events.formToggle();
},
close: function () {
if (this.site.scroll) {
// console.log('events.close-1');
this.hideAllPlayers();
} else {
// console.log('events.close-2');
this.disableOpenOnScroll();
this.hidePlayer();
}
},
ratio: function (li) {
const ratio = parseInt(li.dataset.value, 10);
this.play.dimmensions({ ratio });
this.markSelected(li, 'ratio');
},
size: function (li) {
const size = parseInt(li.dataset.value, 10);
this.play.dimmensions({ size });
this.markSelected(li, 'size');
}
},
videoBar: function ({ target }) {
if (target.tagName.toLowerCase() === 'li' && target.dataset && target.dataset.type) {
const t = target.dataset.type;
if (Control.events.$fire[t]) {
Control.events.$fire[t].call(this, target);
}
}
}
};
/** P L A Y E R CLASS
* @param {Control} parent Instance
*/
class Player {
constructor(parent) {
this.parent = parent;
this.mode = 'off';
this.attrs = {
sources: null,
quality: this.quality,
size: null,
ratio: null,
start: this.time(),
type: null
};
this.attrs.sources = this.sources;
// todo improve type/media
this.attrs.type = this.findType();
this.media = Player.makeMedia[this.attrs.type](this);
this.channel = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('div', { className: 'ytm_panel_channel ytm_block' }, this.media, true);
this.switcher = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('div', { className: `ytm_panel_switcher ytm_panel_size ytm_block ytm_${this.attrs.type}`, _ytmuid: this.parent.state.uid, _standby: true });
this.panel = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('div', { className: 'ytm_panel ytm_block' }, this.switcher, true);
if (parent.state.site === 'soundcloud' && Y.reg.extra.soundcloud.playlist.test(parent.anchor.href)) {
this.media.classList.add('ytm_soundcloud-playlist');
this.switcher.classList.add('ytm_soundcloud-playlist');
}
this.dimmensions(Y.user.preferences);
}
get sources() {
try {
return (Player.sources[this.parent.state.site] || Player.sources.iframe)(this.parent.state, this.attrs);
} catch (e) {
console.error(e);
}
}
get quality() {
return Player.qualities[Y.user.preferences.quality] || Player.qualities[360];
}
get className() {
return `ytm_panel ytm_block ytm_panel-${Player.dimms.ratios[this.attrs.ratio]} ytm_panel-${Player.dimms.sizes[this.attrs.size]}`;
}
dimmensions({ ratio, size }) {
this.attrs.ratio = Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["isNumber"])(ratio) ? ratio : this.attrs.ratio;
this.attrs.size = Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["isNumber"])(size) ? size : this.attrs.size;
this.panel.className = this.className;
}
time() {
try {
// debugger;
const m = this.parent.state.uri.match(Y.reg.time).slice(1, 4);
return ((+m[0] || 0) * 60 * 60) + ((+m[1] || 0) * 60) + (+m[2] || 0);
} catch (e) { return 0; }
}
findType() {
if (this.parent.state.site === 'html5-audio') { return 'audio'; }
if (this.parent.site.videoTag) { return 'video'; }
return 'iframe';
}
switchOff() {
// console.log('removed media');
if (this.media.pause) {
// console.log('pausing');
this.media.pause();
}
try {
this.switcher.removeChild(this.channel);
} catch (e) {
// console.error(e);
}
this.mode = 'off';
}
switchOn() {
if (this.attrs.size === 0) {
this.attrs.size = Y.user.preferences.size;
this.parent.resetViewSize();
}
// console.log('switch to media');
this.switcher.appendChild(this.channel);
this.switcher.dataset.standby = false;
this.mode = 'on';
}
switchStandby() {
// console.log('switch to standby');
this.switchOff();
this.switcher.dataset.standby = true;
this.mode = 'standby';
}
isStandby() {
return this.mode === 'standby';
}
}
Player.sources = {
iframe: function (data) {
const key = Y.DB.sites[data.site].key;
return [
{ type: 'text/html', src: Y.DB.sites[data.site].embed.replace('%key', data[key]) }
];
},
'html5-audio': function ({ uri }) {
return [
{ type: 'audio/mp3', src: uri }
];
},
html5: function ({ uri }) {
// attaching the type as either mp4 or webm
if (/(?:webm)/.test(uri)) {
return [
{ type: 'video/webm', src: uri }
];
}
return [
{ type: 'video/mp4', src: uri },
{ type: 'video/webm', src: uri },
{ type: 'video/ogg; codecs="theora, vorbis"', src: uri }
];
},
imgur: function ({ id }) {
const src = Y.DB.sites.imgur.embed.replace('%key', id);
return [
{ type: 'video/webm', src: `${src}.webm` },
{ type: 'video/mp4', src: `${src}.mp4` }
];
},
youtube: function ({ id }, { quality, start }) {
const params = `?html5=1&version=3&modestbranding=1&rel=0&showinfo=1&vq=${quality}&iv_load_policy=${Y.user.preferences.yt_annotation}&start=${start}&rel=0`;
return [
{ type: 'text/html', src: Y.DB.sites.youtube.embed.replace('%key', id) + params }
];
}
};
Player.dimms = {
ratios: {
1: 'sd',
2: 'hd',
3: 'pr'
},
sizes: {
0: 'h',
240: 's',
360: 'm',
480: 'l',
720: 'xl'
},
aspects: {
1: 4 / 3,
2: 16 / 9,
3: 16 / 9
}
};
Player.qualities = {
240: 'small',
360: 'medium',
480: 'large',
720: 'hd720',
1080: 'hd1080',
1081: 'highres'
};
Player.css = {
item: function (key, value) {
if (Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["isNumber"])(value)) {
value += 'px';
}
return `\t${key}: ${value};\n`;
},
iter: function (css, cssEntries) {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(cssEntries, (key, value) => {
css.push(Player.css.item(key, value));
});
css.push('}');
},
generator: function () {
const css = [];
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(this.sizes, (size, sizes) => {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(sizes, (dimm, keys) => {
css.push(`\n.ytm_panel-${size}.ytm_panel-${dimm} .ytm_panel_size {\n`);
Player.css.iter(css, keys);
});
});
// add site overrides
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(this.sites, (site, data) => {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(data, (setting, keys) => {
if (setting === 'all') {
css.push(`\n.ytm_site_${site} .ytm_panel_size {\n`);
} else {
css.push(`\n.ytm_site_${site} .ytm_panel-${setting} .ytm_panel_size {\n`);
}
Player.css.iter(css, keys);
});
});
return css.join('');
},
sizes: (() => {
const merge = {};
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(Player.dimms.sizes, (num, size) => {
if (num >= 0) {
merge[size] = {};
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].o(Player.dimms.ratios, (k, ratio) => {
if (ratio === 'pr') {
const w = Math.floor(num * 0.95); // smaller than the normal sizes
merge[size][ratio] = {
width: w,
height: Math.floor(w * Player.dimms.aspects[k])
};
} else {
merge[size][ratio] = {
width: Math.floor(num * Player.dimms.aspects[k]),
height: num
};
}
});
}
});
return merge;
})(),
sites: { // custom sizes per site
soundcloud: {
all: {
height: '118px !important'
}
},
vine: {
s: {
width: 240,
height: 240
},
m: {
width: 360,
height: 360
},
l: {
width: 480,
height: 480
},
xl: {
width: 720,
height: 720
}
}
}
};
Player.makeMedia = {
$css: function (type) {
return `ytm_panel_media ytm_panel_size ytm_block ytm_${type}`;
},
video: function ({ attrs }) {
const video = _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('video', {
controls: true,
autoplay: false,
loop: true,
className: this.$css('video'),
$allowscriptaccess: true,
preload: 'metadata'
});
const links = [];
attrs.sources.forEach(({ src, type }) => {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('source', { src, $type: type }, video);
links.push(`<a href="${src}">${src}</a>`);
});
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('p', { innerHTML: `Could not load source(s): ${links.join('<br />')}` }, video);
return video;
},
iframe: function ({ attrs }) {
return _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('iframe', {
$allowfullscreen: true,
$referrerpolicy: 'no-referrer',
// $sandbox: 'allow-same-origin allow-scripts allow-popups',
$type: attrs.sources[0].type,
src: attrs.sources[0].src,
className: this.$css('iframe')
});
},
audio: function ({ attrs }) {
return _modules___WEBPACK_IMPORTED_MODULE_1__["default"].e('audio', {
src: attrs.sources[0].src,
$type: attrs.sources[0].type
});
}
};
/** S C R O L L CLASS
* Window-Scroll Event Helper
*/
class Scroll {
constructor(selector, cb, delay = 500) {
this.selector = selector;
this.cb = cb;
this.monitor = this.monitor.bind(this);
// console.log('YTMA.Scroll Monitor: ', selector);
this.bound = Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["debounce"])(this.monitor, delay);
this.bound();
window.addEventListener('scroll', this.bound, false);
}
stop() {
// console.log('clear scroll: ', this.selector);
window.removeEventListener('scroll', this.bound);
}
monitor() {
_modules___WEBPACK_IMPORTED_MODULE_1__["default"].s(this.selector, this.cb);
}
}
Scroll.visible = el => {
const bound = el.getBoundingClientRect();
return (bound.top >= 0 && bound.top <= document.documentElement.clientHeight);
};
Scroll.visibleAll = (el, offset) => {
const bound = el.getBoundingClientRect();
const height = document.documentElement.clientHeight;
offset = Object(_modules_Helpers__WEBPACK_IMPORTED_MODULE_0__["isNumber"])(offset) ? +offset : 0;
return ((bound.bottom + offset >= 0)
&& (bound.top <= height + offset || bound.bottom <= height - offset));
};
/** Returns 1, 0, -1 when el1 is above, exactly the same, or below el2 */
Scroll.compare = (el1, el2) => {
const a = el1.getBoundingClientRect().y;
const b = el2.getBoundingClientRect().y;
if (a < b) { return 1; }
if (a === b) { return 0; }
return -1;
};
Y.main();
})();
/***/ }),
/***/ "./src/modules/Helpers.js":
/*!********************************!*\
!*** ./src/modules/Helpers.js ***!
\********************************/
/*! exports provided: isNumber, removeSearch, on, debounce */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNumber", function() { return isNumber; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeSearch", function() { return removeSearch; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "on", function() { return on; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debounce", function() { return debounce; });
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest) {
Element.prototype.closest = function (s) {
var el = this;
if (!document.documentElement.contains(el)) return null;
do {
if (el.matches(s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
};
}
const isNumber = n => !isNaN(parseFloat(n)) && isFinite(n);
const removeSearch = (uri, keepHash) => {
// removes search query from a uri
const s = uri.indexOf('?');
const h = uri.indexOf('#');
let hash = '';
if (s > -1) {
if (keepHash && h > -1) {
hash = uri.substr(h);
}
uri = uri.substr(0, s) + hash;
}
return uri;
};
/**
* @param {HTMLElement} element HTML element
* @param {string} events Space- or coma-separated string of one or more types, eg "click dblclick"
* @param {string} selector CSS selector for the elements to trigger the event on
* @param {Function} listener A callback
* @param {Boolean} cancel Cancel
*/
const on = (element, events, selector, listener, cancel = true) => {
events = events.split(/(?:\s+|,)/).filter(f => f);
if (events.length === 0) return;
const fn = event => {
const found = event.target.closest(selector);
if (found) listener.call(found, event);
};
events.forEach(type => element.addEventListener(type, fn, cancel));
};
const debounce = (fn, delay = 250) => {
let timeout;
return function (...args) {
const timed = () => {
timeout = null;
fn.apply(this, args);
};
window.clearTimeout(timeout);
timeout = window.setTimeout(timed, delay);
};
};
/***/ }),
/***/ "./src/modules/_.js":
/*!**************************!*\
!*** ./src/modules/_.js ***!
\**************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// H E L P E R Handle
const _ = {
s: (selector, cb) => {
const elements = _.qsa(selector);
elements.some((element, index) => cb(element, index, elements) === false);
},
o: function (object, cb) {
Object.keys(object).some(key => cb(key, object[key], object) === false);
},
e: function (t, o, e, p) {
const c = document.createElement(t);
_.o(o, (k, v) => {
const b = k.charAt(0);
if (b === '_')
c.dataset[k.substring(1)] = v;
else if (b === '$')
c.setAttribute(k.substring(1), v);
else
c[k] = v;
});
if (e && p) {
c.appendChild(e);
} else if (e) {
e.appendChild(c);
}
return c;
},
qsa: selector => Array.from(document.querySelectorAll(selector)),
css: function (text) {
if (!this.style) {
this.style = document.createElement('style');
this.style.type = 'text/css';
document.body.appendChild(this.style);
}
this.style.appendChild(document.createTextNode(`${text}\n`));
},
js: t => {
const j = document.createElement('script');
j.type = 'text/javascript';
j[/^https?:\/\//i.test(t) ? 'src' : 'textContent'] = t;
document.head.appendChild(j);
}
};
/* harmony default export */ __webpack_exports__["default"] = (_);
/***/ }),
/***/ "./src/modules/strg.js":
/*!*****************************!*\
!*** ./src/modules/strg.js ***!
\*****************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
// S T O R A G E HANDLE
const strg = {
MAX: 5012,
on: false,
test: () => {
try {
const l = localStorage;
const c = Math.random().toString(16).substr(2, 8);
l.setItem(c, c);
return l.getItem(c) === c ? !l.removeItem(c) : false;
} catch (e) { return false; }
},
read: (key) => {
try {
return JSON.parse(localStorage.getItem(key));
} catch (e) {
return console.error(`${e.lineNumber}:${e.message}`);
}
},
save: (key, val) => strg.on ? !localStorage.setItem(key, JSON.stringify(val)) : false,
wipe: key => strg.on ? !localStorage.removeItem(key) : false,
zero: o => { for (let k in o) { if (o.hasOwnProperty(k)) { return false; } } return true; }, // check if the object is empty
grab: (key, def) => { const s = strg.read(key); return strg.zero(s) ? def : s; },
size: () => {
let length = 0;
let key;
try {
for (key in window.localStorage) {
if (window.localStorage.hasOwnProperty(key)) {
length += window.localStorage[key].length;
}
}
} catch (e) {
// no more space
}
return 3 + ((length * 16) / (8 * 1024));
},
full: () => {
try {
const date = +(new Date());
localStorage.setItem(date, date);
localStorage.removeItem(date);
return false;
} catch (e) {
if (e.name === 'QuotaExceededError' ||
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
return true;
}
}
},
init: () => { strg.on = strg.test(); }
};
strg.init();
/* harmony default export */ __webpack_exports__["default"] = (strg);
/***/ }),
/***/ "./src/modules/update.js":
/*!*******************************!*\
!*** ./src/modules/update.js ***!
\*******************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _strg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./strg */ "./src/modules/strg.js");
/* harmony import */ var ___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./_ */ "./src/modules/_.js");
// U P D A T E HANDLE
const update = {
name: 'ytma!',
version: 8000,
key: 'ujs_YTMA_UPDT_HR',
callback: 'ytmaupdater',
page: 'https://greasyfork.org/scripts/1023-youtube-me-again',
json: 'https://hateradio.github.io/ytma/update.json',
interval: 7,
day: (new Date()).getTime(),
show: false,
time: () => new Date(update.day + (1000 * 60 * 60 * 24 * update.interval)).getTime(),
notification: ({ version, page }) => {
if (update.version < version) {
_strg__WEBPACK_IMPORTED_MODULE_0__["default"].save(update.key, { date: update.time(), version, page });
update.link();
}
},
link: () => {
if (update.show) { return; }
update.show = true;
const { page } = _strg__WEBPACK_IMPORTED_MODULE_0__["default"].read(update.key);
const link = `
<a href="${page || update.page}" id=updatev3 title=Update target=_blank>
An update for ${update.name} is available.
</a>`;
___WEBPACK_IMPORTED_MODULE_1__["default"].css(update.css);
document.body.insertAdjacentHTML('beforeend', link);
___WEBPACK_IMPORTED_MODULE_1__["default"].on(document.body, 'click', '#updatev3', e => e.target.style.display = 'none');
},
check: (opt) => {
if (!_strg__WEBPACK_IMPORTED_MODULE_0__["default"].on) { return; }
if (window.chrome && window.chrome.extension) { return; }
const stored = _strg__WEBPACK_IMPORTED_MODULE_0__["default"].read(update.key);
let page;
if (opt || !stored || stored.date < update.day) {
page = (stored && stored.page) || update.page;
_strg__WEBPACK_IMPORTED_MODULE_0__["default"].save(update.key, { date: update.time(), version: update.version, page });
fetch(update.json).then(res => res.json()).then(update.notification);
} else if (update.version < stored.version) {
update.link();
}
},
css: '#updater3,#updater3:visited{box-shadow:1px 1px 6px #7776;border-bottom:3px solid #e39c2d;cursor:pointer;color:#555;font-family:sans-serif;font-size:12px;font-weight:700;text-align:justify;position:fixed;z-index:999999;right:10px;top:10px;background:#ebebeb url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgLTM0IDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNlNWViZjUiIGQ9Ik0yNzAuNzgxIDcuNUgyNDEuMjJMOC42NiA0MTAuMzA1bDE0Ljc4MSAyNS42MDFINDg4LjU2bDE0Ljc4LTI1LjYwMXptMCAwIi8+PHBhdGggZmlsbD0iI2Y4ZTg2OCIgZD0iTTQ4LjcwNyA0MDAuOTM0TDI1My4xMjkgNDYuODY3aDUuNzQybDIwNC40MjIgMzU0LjA2N2MtMS4yNzcgMi4yMS0xLjU5NCAyLjc2NS0yLjg3MSA0Ljk3Nkg1MS41NzhjLTEuMjc3LTIuMjEtMS41OTQtMi43NjUtMi44NzEtNC45NzZ6bTAgMCIvPjxwYXRoIGZpbGw9IiNlMzljMmQiIGQ9Ik0yNzUuOTk2IDc2LjUyN2wtMTcuMTI1LTI5LjY2aC01Ljc0Mkw0OC43MDcgNDAwLjkzNGMxLjI3NyAyLjIxIDEuNTk0IDIuNzY1IDIuODcxIDQuOTc2aDM5Ljk5NmMtMS4yNzctMi4yMS0xLjU5Ny0yLjc2NS0yLjg3LTQuOTc2em0wIDAiLz48cGF0aCBmaWxsPSIjY2FkOGVhIiBkPSJNMjc1Ljk5NiAxNi41MzVMMjcwLjc4MSA3LjVIMjQxLjIyTDguNjYgNDEwLjMwNWM2LjU2NyAxMS4zNzkgOC4yMTEgMTQuMjIyIDE0Ljc4MSAyNS42MDFoMzkuOTk2Yy02LjU3LTExLjM3OS04LjIxNC0xNC4yMjItMTQuNzgtMjUuNjAxem0wIDAiLz48cGF0aCBmaWxsPSIjNzI4NjllIiBkPSJNMjcwLjg1NSAzMDIuNDU3aC0yOS43MWMtMy4wMDQtMy4wMDQtNC42OTItNC42ODctNy42OTYtNy42OTFWMTYzLjg2M2g0NS4xMDJ2MTMwLjkwM2MtMy4wMDggMy4wMDQtNC42OTIgNC42ODctNy42OTYgNy42OTF6bTAgMCIvPjxwYXRoIGZpbGw9IiM1MzYyNzUiIGQ9Ik0yNTMuNDUgMTYzLjg2M2gtMjB2MTMwLjkwM2MzLjAwMyAzLjAwNCA0LjY5IDQuNjg3IDcuNjk1IDcuNjkxaDE5Ljk5NmwtNy42OTItNy42OTF6bTAgMCIvPjxwYXRoIGZpbGw9IiM3Mjg2OWUiIGQ9Ik0yMzMuNDUgMzMwLjgxM2g0NS4xdjQ1LjEwMWgtNDUuMXptMCAwIi8+PHBhdGggZmlsbD0iIzUzNjI3NSIgZD0iTTIzMy40NSAzMzAuODEzaDIwdjQ1LjEwMWgtMjB6bTAgMCIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0yNzUuOTk2IDE0MS4zNjdIMjYxdi0xNWgxNC45OTZ6bS0yNC45OTYgMGgtMTV2LTE1aDE1em0wIDAiLz48cGF0aCBkPSJNNDAwLjQzIDIxNy4wNTlsLTEyLjk4OSA3LjVMNDk0LjY4IDQxMC4zMDVsLTEwLjQ1IDE4LjEwMUgyNy43N2wtMTAuNDU0LTE4LjEwMUwyNDUuNTQ2IDE1aDIwLjkwN2wxMDcuMjM4IDE4NS43NDYgMTIuOTg5LTcuNUwyNzUuMTEzIDBoLTM4LjIyMkwwIDQxMC4zMDVsMTkuMTEgMzMuMTAxaDQ3My43NzdMNTEyIDQxMC4zMDV6bTAgMCIvPjxwYXRoIGQ9Ik0xMjUuMTU2IDQxMy40MDZINDY0Ljc1bDcuMjAzLTEyLjQ3Mi0yMDguNzUtMzYxLjU2N2gtMTQuNDA2TDQwLjA0NyA0MDAuOTM0bDcuMiAxMi40NzJoNTcuOTEzVjM5OC40MUg1OC44MjRMMjU2IDU2Ljg5bDE5Ny4xNzYgMzQxLjUyaC0zMjguMDJ6bTAgMCIvPjxwYXRoIGQ9Ik0yODYuMDQ3IDIyOS41NTl2LTczLjE5NmgtNjAuMDk4djE0MS41MDhsMTIuMDkgMTIuMDg2aDM1LjkyMmwxMi4wODYtMTIuMDg2VjI0OS41NkgyNzEuMDV2NDIuMDk3bC0zLjMwMSAzLjMwNWgtMjMuNWwtMy4zLTMuMzA1VjE3MS4zNjNoMzAuMXY1OC4xOTZ6bTAgME0yMjUuOTUgMzgzLjQxaDYwLjA5N3YtNjAuMDk4aC02MC4wOTh6bTE1LTQ1LjA5OGgzMC4xdjMwLjEwMmgtMzAuMXptMCAwIi8+PC9zdmc+) no-repeat 10px center;background-size:40px;padding:0 20px 0 60px;height:55px;line-height:55px}#updater3:hover,#updater3:visited:hover{color:#b33a3a !important;border-color:#ce4b30;text-decoration: none;}' // Icon made by Freepik from www.flaticon.com
};
update.check();
/* harmony default export */ __webpack_exports__["default"] = (update);
/***/ })
/******/ });
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vLy4vc3JjL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NyYy9tb2R1bGVzL0hlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vc3JjL21vZHVsZXMvXy5qcyIsIndlYnBhY2s6Ly8vLi9zcmMvbW9kdWxlcy9zdHJnLmpzIiwid2VicGFjazovLy8uL3NyYy9tb2R1bGVzL3VwZGF0ZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxrREFBMEMsZ0NBQWdDO0FBQzFFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0VBQXdELGtCQUFrQjtBQUMxRTtBQUNBLHlEQUFpRCxjQUFjO0FBQy9EOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBeUMsaUNBQWlDO0FBQzFFLHdIQUFnSCxtQkFBbUIsRUFBRTtBQUNySTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOzs7QUFHQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FDbEZBO0FBQUE7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QUNGO0FBQ0EsT0FBTyw2Q0FBSSxNQUFNLFFBQVE7QUFDekIsaURBQWlELFFBQVE7QUFDekQsaUJBQWlCLDZDQUFJO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQSxHQUFHLDZDQUFJLG1CQUFtQixxREFBcUQ7QUFDL0U7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7QUFDRixtQ0FBbUMsNkJBQTZCLGdDQUFnQyxlQUFlLFdBQVcsdUJBQXVCLGVBQWUsZ0JBQWdCLG1CQUFtQixlQUFlLGVBQWUsV0FBVyxTQUFTLDBDQUEwQyxteEVBQW14RSxxQkFBcUIsc0JBQXNCLFlBQVksaUJBQWlCLHdDQUF3Qyx5QkFBeUIscUJBQXFCLHVCQUF1QjtBQUN2dUY7QUFDQTs7QUFFZSxxRUFBTSxFIiwiZmlsZSI6Inl0bWEudXNlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIiBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbiBcdHZhciBpbnN0YWxsZWRNb2R1bGVzID0ge307XG5cbiBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4gXHRmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cbiBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4gXHRcdGlmKGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdKSB7XG4gXHRcdFx0cmV0dXJuIGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdLmV4cG9ydHM7XG4gXHRcdH1cbiBcdFx0Ly8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSlcbiBcdFx0dmFyIG1vZHVsZSA9IGluc3RhbGxlZE1vZHVsZXNbbW9kdWxlSWRdID0ge1xuIFx0XHRcdGk6IG1vZHVsZUlkLFxuIFx0XHRcdGw6IGZhbHNlLFxuIFx0XHRcdGV4cG9ydHM6IHt9XG4gXHRcdH07XG5cbiBcdFx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG4gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG4gXHRcdC8vIEZsYWcgdGhlIG1vZHVsZSBhcyBsb2FkZWRcbiBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuXG4gXHRcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG4gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbiBcdH1cblxuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZXMgb2JqZWN0IChfX3dlYnBhY2tfbW9kdWxlc19fKVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5tID0gbW9kdWxlcztcblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGUgY2FjaGVcbiBcdF9fd2VicGFja19yZXF1aXJlX18uYyA9IGluc3RhbGxlZE1vZHVsZXM7XG5cbiBcdC8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIGhhcm1vbnkgZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5kID0gZnVuY3Rpb24oZXhwb3J0cywgbmFtZSwgZ2V0dGVyKSB7XG4gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgbmFtZSwgeyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGdldHRlciB9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcbiBcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcbiBcdFx0fVxuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gY3JlYXRlIGEgZmFrZSBuYW1lc3BhY2Ugb2JqZWN0XG4gXHQvLyBtb2RlICYgMTogdmFsdWUgaXMgYSBtb2R1bGUgaWQsIHJlcXVpcmUgaXRcbiBcdC8vIG1vZGUgJiAyOiBtZXJnZSBhbGwgcHJvcGVydGllcyBvZiB2YWx1ZSBpbnRvIHRoZSBuc1xuIFx0Ly8gbW9kZSAmIDQ6IHJldHVybiB2YWx1ZSB3aGVuIGFscmVhZHkgbnMgb2JqZWN0XG4gXHQvLyBtb2RlICYgOHwxOiBiZWhhdmUgbGlrZSByZXF1aXJlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnQgPSBmdW5jdGlvbih2YWx1ZSwgbW9kZSkge1xuIFx0XHRpZihtb2RlICYgMSkgdmFsdWUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKHZhbHVlKTtcbiBcdFx0aWYobW9kZSAmIDgpIHJldHVybiB2YWx1ZTtcbiBcdFx0aWYoKG1vZGUgJiA0KSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICYmIHZhbHVlLl9fZXNNb2R1bGUpIHJldHVybiB2YWx1ZTtcbiBcdFx0dmFyIG5zID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcbiBcdFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yKG5zKTtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG5zLCAnZGVmYXVsdCcsIHsgZW51bWVyYWJsZTogdHJ1ZSwgdmFsdWU6IHZhbHVlIH0pO1xuIFx0XHRpZihtb2RlICYgMiAmJiB0eXBlb2YgdmFsdWUgIT0gJ3N0cmluZycpIGZvcih2YXIga2V5IGluIHZhbHVlKSBfX3dlYnBhY2tfcmVxdWlyZV9fLmQobnMsIGtleSwgZnVuY3Rpb24oa2V5KSB7IHJldHVybiB2YWx1ZVtrZXldOyB9LmJpbmQobnVsbCwga2V5KSk7XG4gXHRcdHJldHVybiBucztcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSBcIi4vc3JjL2luZGV4LmpzXCIpO1xuIiwiaW1wb3J0IHsgaXNOdW1iZXIsIHJlbW92ZVNlYXJjaCwgb24sIGRlYm91bmNlIH0gZnJvbSAnLi9tb2R1bGVzL0hlbHBlcnMnO1xuaW1wb3J0IF8gZnJvbSAnLi9tb2R1bGVzL18nO1xuaW1wb3J0IHN0cmcgZnJvbSAnLi9tb2R1bGVzL3N0cmcnO1xuaW1wb3J0IHVwZGF0ZSBmcm9tICcuL21vZHVsZXMvdXBkYXRlJztcblxuKCgpID0+IHtcblxuXHQvKiogWSBUIE0gQSBDTEFTU1xuXHQgKiBAcHJpdmF0ZVxuXHQgKiBCYXNlIFlUTUEgY2xhc3MsIGZpbGxlZCB0aHJvdWdoIGNvbnN0cnVjdG9yKCkgb3IgcmVhY3RpdmF0ZSgpIHRob3VnaCBzdWItY2xhc3Nlc1xuXHQgKiBZJ3Mgb25seSBjb25jZXJuZWQgYWJvdXQgdGhlIGFuY2hvciBhbmQgdGhlIGRhdGEgcHJvcHNcblx0ICpcblx0ICogQHBhcmFtIHtvYmplY3R9IHByb3BzIFByb3BlcnRpZXNcblx0ICogQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBwcm9wcy5pZCBVbmlxdWUgSURcblx0ICogQHBhcmFtIHtTdHJpbmd9IHByb3BzLnNpdGUgV2Vic2l0ZSBuYW1lIGVnOiB5b3V0dWJlLCB2aW1lb1xuXHQgKiBAcGFyYW0ge0hUTUxBbmNob3JFbGVtZW50fSBwcm9wcy5hbmNob3IgQW5jaG9yIGVsZW1lbnRcblx0ICovXG5cdGNsYXNzIFkge1xuXG5cdFx0Y29uc3RydWN0b3IoeyBpZCwgc2l0ZSwgYW5jaG9yIH0pIHtcblx0XHRcdGNvbnN0IHVpZCA9IFkuZXNjYXBlSWQoYCR7aWR9XyR7WS5udW0gKz0gMX1gKTtcblxuXHRcdFx0dGhpcy5zdGF0ZSA9IHtcblx0XHRcdFx0aWQsXG5cdFx0XHRcdHVpZDogWS5lc2NhcGVJZCh1aWQpLCAvLyB1bmlxdWUgaWRcblx0XHRcdFx0c2lkOiBZLmVzY2FwZUlkKGlkKSwgLy8gc2hhcmVkIGlkXG5cdFx0XHRcdHNpdGUsXG5cdFx0XHRcdHVyaTogYW5jaG9yLmhyZWZcblx0XHRcdH07XG5cblx0XHRcdGlmIChhbmNob3IgJiYgIWFuY2hvci5kYXRhc2V0Lnl0bXNjcm9sbCkgeyBhbmNob3IuZGF0YXNldC55dG1zY3JvbGwgPSB0cnVlOyB9XG5cblx0XHRcdHRoaXMuYW5jaG9yID0gYW5jaG9yO1xuXHRcdH1cblxuXHRcdC8qKlxuXHRcdCAqIFJlY3JlYXRlcyBhIFlUTUEgb2JqZWN0IGZyb20gYSB0cmlnZ2VyIGVsZW1lbnRcblx0XHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50IHRoZSBlbGVtZW50J3MgZGF0YXNldCBmb3IgdGhlIHJlc3VyZWN0aW9uIVxuXHRcdCAqL1xuXHRcdHJlYWN0aXZhdGUoeyBkYXRhc2V0IH0pIHtcblx0XHRcdGNvbnN0IGlkID0gZGF0YXNldC55dG1pZDtcblx0XHRcdGNvbnN0IGFuY2hvciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYGFbZGF0YS15dG11aWQ9XCIke2RhdGFzZXQueXRtdWlkfVwiXWApO1xuXG5cdFx0XHR0aGlzLnN0YXRlID0ge1xuXHRcdFx0XHRpZCxcblx0XHRcdFx0dWlkOiBkYXRhc2V0Lnl0bXVpZCxcblx0XHRcdFx0c2lkOiBkYXRhc2V0Lnl0bXNpZCxcblx0XHRcdFx0c2l0ZTogZGF0YXNldC55dG1zaXRlLFxuXHRcdFx0XHR1cmk6IGFuY2hvci5ocmVmXG5cdFx0XHR9O1xuXG5cdFx0XHR0aGlzLmFuY2hvciA9IGFuY2hvcjtcblxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0ZGlzYWJsZU9wZW5PblNjcm9sbCgpIHtcblx0XHRcdHRoaXMuYW5jaG9yLmRhdGFzZXQueXRtc2Nyb2xsID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Y2FuU2Nyb2xsKCkge1xuXHRcdFx0cmV0dXJuIHRoaXMuYW5jaG9yLmRhdGFzZXQueXRtc2Nyb2xsID09PSAndHJ1ZSc7XG5cdFx0fVxuXG5cdFx0aXNCZWxvdyhsaW5rKSB7XG5cdFx0XHRyZXR1cm4gU2Nyb2xsLmNvbXBhcmUodGhpcy5hbmNob3IsIGxpbmspIDwgMTtcblx0XHR9XG5cblx0XHRjYW5TaG93VW5kZXIobGluaykge1xuXHRcdFx0dGhpcy5jYW5TY3JvbGwoKSAmJiB0aGlzLmlzQmVsb3cobGluayk7XG5cdFx0fVxuXG5cdFx0dXBkYXRlQW5jaG9yKCkge1xuXHRcdFx0aWYgKHRoaXMuYW5jaG9yLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbWcnKS5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0dGhpcy5hbmNob3IuY2xhc3NMaXN0LmFkZCgneXRtX2xpbmsnLCBgeXRtX2xpbmtfJHt0aGlzLnN0YXRlLnNpdGV9YCk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLmFuY2hvci5kYXRhc2V0Lnl0bWlkID0gdGhpcy5zdGF0ZS5pZDtcblx0XHRcdHRoaXMuYW5jaG9yLmRhdGFzZXQueXRtdWlkID0gdGhpcy5zdGF0ZS51aWQ7XG5cdFx0XHR0aGlzLmFuY2hvci5kYXRhc2V0Lnl0bXNpZCA9IHRoaXMuc3RhdGUuc2lkO1xuXHRcdFx0dGhpcy5hbmNob3IudGl0bGUgPSAnVmlzaXQgdGhlIHZpZGVvIHBhZ2UuJztcblx0XHR9XG5cblx0fVxuXG5cdC8qKiBDIE8gTiBUIEEgSSBOIEUgUiBDTEFTU1xuXHQgKiBUaGUgY29udGFpbmVyLCBhcyB0aGUgbmFtZSBpbXBsaWVzLCBjb250YWlucyBhbGwgdGhlIGludGVyYWN0aXZlIGVsZW1lbnRzXG5cdCAqIFRodW1ibmFpbCwgUGxheWVyLCBDb250cm9scywgZXRjLlxuXHQgKi9cblx0Y2xhc3MgQ29udGFpbmVyIGV4dGVuZHMgWSB7XG5cblx0XHRjcmVhdGVJbnRlcmZhY2UoKSB7XG5cdFx0XHRjb25zdCB7IHN0YXRlIH0gPSB0aGlzO1xuXHRcdFx0dGhpcy5zaXRlID0gWS5EQi5zaXRlc1tzdGF0ZS5zaXRlXTtcblx0XHRcdGNvbnN0IHsgYWpheCwgc2xpbSB9ID0gdGhpcy5zaXRlO1xuXG5cdFx0XHR0aGlzLnVwZGF0ZUFuY2hvcigpO1xuXG5cdFx0XHR0aGlzLmJvZHkgPSBfLmUoJ2RpdicsIHtcblx0XHRcdFx0aWQ6IGB3JHtzdGF0ZS51aWR9YCxcblx0XHRcdFx0Y2xhc3NOYW1lOiBgeXRtX3NwYWNlciB5dG1fYmxvY2sgeXRtX3NpdGVfJHtzdGF0ZS5zaXRlfWAsXG5cdFx0XHRcdGlubmVySFRNTDogdGhpcy5jcmVhdGVUaHVtYm5haWxUZW1wbGF0ZSgpXG5cdFx0XHR9KTtcblxuXHRcdFx0dGhpcy50aHVtYm5haWwgPSB0aGlzLmJvZHkuZmlyc3RFbGVtZW50Q2hpbGQ7XG5cblx0XHRcdGlmIChhamF4KSB7IHRoaXMuY3JlYXRlQWpheExpbmsoKTsgfVxuXHRcdFx0aWYgKHNsaW0pIHsgdGhpcy5ib2R5LmNsYXNzTGlzdC5hZGQoJ3l0bV9zaXRlX3NsaW0nKTsgfVxuXG5cdFx0XHR0aGlzLmFuY2hvci5pbnNlcnRBZGphY2VudEVsZW1lbnQoJ2FmdGVyZW5kJywgdGhpcy5ib2R5KTtcblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Q29udGFpbmVyLmRlY29yYXRvcnNbc3RhdGUuc2l0ZV0uZ3VpKHRoaXMpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHQvLyBtZWhcblx0XHRcdH1cblx0XHR9XG5cblx0XHR1cGRhdGVBbmNob3IoKSB7XG5cdFx0XHRjb25zdCB7IHNjcm9sbCwgaHR0cHMgfSA9IHRoaXM7XG5cdFx0XHRpZiAoc2Nyb2xsKSB7IHRoaXMuYW5jaG9yLmNsYXNzTGlzdC5hZGQoJ3l0bV9zY3JvbGwnKTsgfVxuXHRcdFx0aWYgKGh0dHBzKSB7IHRoaXMuYW5jaG9yLmhyZWYgPSB0aGlzLmFuY2hvci5ocmVmLnJlcGxhY2UoJ2h0dHA6JywgJ2h0dHBzOicpOyB9XG5cblx0XHRcdHN1cGVyLnVwZGF0ZUFuY2hvcigpO1xuXHRcdH1cblxuXHRcdGNyZWF0ZVRodW1ibmFpbFRlbXBsYXRlKCkge1xuXHRcdFx0Y29uc3QgeyB0aXRsZSwgdGh1bWIgPSAnJyB9ID0gdGhpcy5zaXRlO1xuXHRcdFx0Y29uc3QgeyBpZCwgdWlkLCBzaWQsIHNpdGUgfSA9IHRoaXMuc3RhdGU7XG5cblx0XHRcdGNvbnN0IGJnID0gdGh1bWIgPyBgYmFja2dyb3VuZC1pbWFnZTogJHt0aHVtYi5yZXBsYWNlKCcla2V5JywgaWQpfWAgOiAnJztcblxuXHRcdFx0Y29uc3QgdGVtcGxhdGUgPSBgXG5cdFx0XHRcdDxzcGFuIGNsYXNzPVwieXRtX3RyaWdnZXIgeXRtX2Jsb2NrIHl0bV9ub3JtYWxpemUgeXRtX3NhbnNcIlxuXHRcdFx0XHRcdHRpdGxlPVwiJHt0aXRsZX1cIlxuXHRcdFx0XHRcdGRhdGEteXRtaWQ9XCIke2lkfVwiXG5cdFx0XHRcdFx0ZGF0YS15dG1zaXRlPVwiJHtpZH1cIlxuXHRcdFx0XHRcdHN0eWxlPVwiJHtiZ31cIj5cblx0XHRcdFx0XHQ8c3BhbiBjbGFzcz1cInl0bV9pbml0IHl0bV9sYWJlbCB5dG1fc2FucyB5dG1fYm94XCI+JHt0aXRsZX08L3NwYW4+XG5cdFx0XHRcdFx0XHQ8dmFyIGNsYXNzPVwieXRtX2xhYmVsIHl0bV9ib3hcIlxuXHRcdFx0XHRcdFx0XHRkYXRhLXl0bWlkPVwiJHtpZH1cIlxuXHRcdFx0XHRcdFx0XHRkYXRhLXl0bXVpZD1cIiR7dWlkfVwiXG5cdFx0XHRcdFx0XHRcdGRhdGEteXRtc2lkPVwiJHtzaWR9XCJcblx0XHRcdFx0XHRcdFx0ZGF0YS15dG1zaXRlPVwiJHtzaXRlfVwiPlxcdTI1QjY8L3Zhcj5cblx0XHRcdFx0XHQ8L3NwYW4+XG5cdFx0XHRcdDwvc3Bhbj5gO1xuXHRcdFx0cmV0dXJuIHRlbXBsYXRlO1xuXHRcdH1cblxuXHRcdGNyZWF0ZUFqYXhMaW5rKCkge1xuXHRcdFx0Y29uc3QgeyBzaWQsIGlkLCBzaXRlLCB1cmkgfSA9IHRoaXMuc3RhdGU7XG5cdFx0XHRjb25zdCB0ZW1wbGF0ZSA9IGBcblx0XHRcdFx0PHNwYW4gY2xhc3M9XCJ5dG1fYmQgeXRtX25vcm1hbGl6ZSB5dG1fbWFudWFsIF8ke3NpZH1cIj5cblx0XHRcdFx0XHQ8YSBocmVmPVwiI1wiIGNsYXNzPVwieXRtX3RpdGxlXCIgdGl0bGU9XCJMb2FkIHRoaXMgdmlkZW8ncyBkZXNjcmlwdGlvbi5cIlxuXHRcdFx0XHRcdFx0ZGF0YS15dG1pZD1cIiR7aWR9XCJcblx0XHRcdFx0XHRcdGRhdGEteXRtc2l0ZT1cIiR7c2l0ZX1cIlxuXHRcdFx0XHRcdFx0ZGF0YS15dG11cmk9XCIke3VyaX1cIlxuXHRcdFx0XHRcdFx0ZGF0YS15dG1kZXNjcmlwdGlvbj1cInRydWVcIlxuXHRcdFx0XHRcdD5Mb2FkIERlc2NyaXB0aW9uPC9hPlxuXHRcdFx0XHQ8L3NwYW4+YDtcblx0XHRcdHRoaXMuYm9keS5pbnNlcnRBZGphY2VudEhUTUwoJ2JlZm9yZWVuZCcsIHRlbXBsYXRlKTtcblx0XHR9XG5cblx0XHRjcmVhdGVQcm9qZWN0b3IoKSB7XG5cdFx0XHR0aGlzLnByb2plY3RvciA9IF8uZSgnZGl2Jywge1xuXHRcdFx0XHRjbGFzc05hbWU6ICd5dG1fcHJvamVjdG9yIHl0bV9ub25lIHl0bV9ibG9jayB5dG1fbm9ybWFsaXplIHl0bV9zYW5zJyxcblx0XHRcdFx0aW5uZXJIVE1MOiBDb250YWluZXIudGVtcGxhdGVzLm1lbnVcblx0XHRcdH0pO1xuXHRcdFx0dGhpcy50aHVtYm5haWwuaW5zZXJ0QWRqYWNlbnRFbGVtZW50KCdhZnRlcmVuZCcsIHRoaXMucHJvamVjdG9yKTtcblx0XHR9XG5cblx0XHRzaG93UGxheWVyKCkge1xuXHRcdFx0dGhpcy50aHVtYm5haWwuY2xhc3NMaXN0LmFkZCgneXRtX25vbmUnKTtcblx0XHRcdHRoaXMucHJvamVjdG9yLmNsYXNzTGlzdC5yZW1vdmUoJ3l0bV9ub25lJyk7XG5cdFx0fVxuXG5cdFx0aGlkZVBsYXllcigpIHtcblx0XHRcdHRoaXMudGh1bWJuYWlsLmNsYXNzTGlzdC5yZW1vdmUoJ3l0bV9ub25lJyk7XG5cdFx0XHR0aGlzLnByb2plY3Rvci5jbGFzc0xpc3QuYWRkKCd5dG1fbm9uZScpO1xuXHRcdH1cblxuXHR9XG5cblx0Q29udGFpbmVyLnRlbXBsYXRlcyA9IHtcblx0XHRtZW51OiBgXG5cdFx0XHQ8dWwgY2xhc3M9XCJ5dG1fb3B0aW9ucyB5dG1fc2Fuc1wiPlxuXHRcdFx0XHQ8bGk+XG5cdFx0XHRcdFx0PHVsIGNsYXNzPVwieXRtX3JhdGlvc1wiPlxuXHRcdFx0XHRcdFx0PGxpIGRhdGEtdHlwZT1cInJhdGlvXCIgZGF0YS12YWx1ZT1cIjFcIiB0aXRsZT1cIlNEXCI+NDozPC9saT5cblx0XHRcdFx0XHRcdDxsaSBkYXRhLXR5cGU9XCJyYXRpb1wiIGRhdGEtdmFsdWU9XCIyXCIgdGl0bGU9XCJMYW5kc2NhcGVcIj4xNjo5PC9saT5cblx0XHRcdFx0XHRcdDxsaSBkYXRhLXR5cGU9XCJyYXRpb1wiIGRhdGEtdmFsdWU9XCIzXCIgdGl0bGU9XCJQb3J0cmFpdFwiPjk6MTY8L2xpPlxuXHRcdFx0XHRcdDwvdWw+XG5cdFx0XHRcdDwvbGk+XG5cdFx0XHRcdDxsaT5cblx0XHRcdFx0XHQ8dWwgY2xhc3M9XCJ5dG1fc2l6ZXNcIj5cblx0XHRcdFx0XHRcdDxsaSBkYXRhLXR5cGU9XCJzaXplXCIgZGF0YS12YWx1ZT1cIjBcIiB0aXRsZT1cIkhpZGUgdGhlIHZpZGVvLlwiPlxcdTAwRDg8L2xpPlxuXHRcdFx0XHRcdFx0PGxpIGRhdGEtdHlwZT1cInNpemVcIiBkYXRhLXZhbHVlPVwiMjQwXCIgdGl0bGU9XCIyNDBwXCI+UzwvbGk+XG5cdFx0XHRcdFx0XHQ8bGkgZGF0YS10eXBlPVwic2l6ZVwiIGRhdGEtdmFsdWU9XCIzNjBcIiB0aXRsZT1cIjM2MHBcIj5NPC9saT5cblx0XHRcdFx0XHRcdDxsaSBkYXRhLXR5cGU9XCJzaXplXCIgZGF0YS12YWx1ZT1cIjQ4MFwiIHRpdGxlPVwiNDgwcFwiPkw8L2xpPlxuXHRcdFx0XHRcdFx0PGxpIGRhdGEtdHlwZT1cInNpemVcIiBkYXRhLXZhbHVlPVwiNzIwXCIgdGl0bGU9XCI3MjBwXCI+WDwvbGk+XG5cdFx0XHRcdFx0PC91bD5cblx0XHRcdFx0PC9saT5cblx0XHRcdFx0PGxpPlxuXHRcdFx0XHRcdDx1bCBjbGFzcz1cInl0bV9vcHRpb25zXCI+XG5cdFx0XHRcdFx0XHQke3N0cmcub24gPyAnPGxpIGRhdGEtdHlwZT1cInNldHRpbmdzXCIgZGF0YS12YWx1ZT1cIlwiIHRpdGxlPVwiWVRNQSBTZXR0aW5nc1wiPiE8L2xpPicgOiAnJ31cblx0XHRcdFx0XHRcdDxsaSBkYXRhLXR5cGU9XCJjbG9zZVwiIGRhdGEtdmFsdWU9XCJcIiB0aXRsZT1cIkNsb3NlIHRoZSB2aWRlby5cIj5cXHUwMEQ3PC9saT5cblx0XHRcdFx0XHQ8L3VsPlxuXHRcdFx0XHQ8L2xpPlxuXHRcdFx0PC91bD5gXG5cdH07XG5cblx0Q29udGFpbmVyLmRlY29yYXRvcnMgPSB7IC8vIG1vZGlmeSBpbnRlcmZhY2UgYWNjb3JkaW5nIHRvIHNpdGVcblx0XHR5b3V0dWJlOiB7XG5cdFx0XHRndWk6IGZ1bmN0aW9uIChjb250cm9sKSB7XG5cdFx0XHRcdGNvbnRyb2wuYW5jaG9yLmhyZWYgPSB0aGlzLmFuY2hvci5ocmVmLnJlcGxhY2UoJ3lvdXR1LmJlLycsICd5b3V0dWJlLmNvbS93YXRjaD92PScpO1xuXHRcdFx0fSxcblx0XHRcdHRodW1iRXZlbnQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdGxldCB0aW1lID0gK3RoaXMuZGF0YXNldC50aW1lIHx8IDE7XG5cdFx0XHRcdGlmICh0aGlzLmNsYXNzTGlzdC5jb250YWlucygneXRtX3RyaWdnZXInKSAmJiBlLnR5cGUgPT09ICdtb3VzZWVudGVyJyAmJiB0aW1lIDwgNTApIHtcblx0XHRcdFx0XHR0aGlzLmRhdGFzZXQudGh1bWIgPSAoKHRoaXMuZGF0YXNldC50aHVtYiB8fCAwKSArIDEpICUgMztcblx0XHRcdFx0XHR0aGlzLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9IGB1cmwoaHR0cHM6Ly9pMy55dGltZy5jb20vdmkvJHt0aGlzLmRhdGFzZXQueXRtaWR9LyR7KCt0aGlzLmRhdGFzZXQudGh1bWIpICsgMX0uanBnKWA7XG5cdFx0XHRcdFx0d2luZG93LmNsZWFyVGltZW91dCh0aGlzLmRhdGFzZXQudGltZW91dCk7XG5cdFx0XHRcdFx0Y29uc29sZS5sb2coJ21vdXNlZW50ZXIgLS0gY2xlYXIgYmVmb3JlIHNldHRpbmcgbmV3ICcsIHRoaXMuZGF0YXNldCk7XG5cdFx0XHRcdFx0dGhpcy5kYXRhc2V0LnRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dChDb250YWluZXIuZGVjb3JhdG9ycy55b3V0dWJlLnRodW1iRXZlbnQuYmluZCh0aGlzLCBlKSwgODAwKTtcblx0XHRcdFx0XHRjb25zb2xlLmxvZygnbW91c2VlbnRlciAtLSBuZXcgdGltZW91dCcsIHRoaXMuZGF0YXNldCk7XG5cdFx0XHRcdFx0dGhpcy5kYXRhc2V0LnRpbWUgPSB0aW1lICs9IDE7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0d2luZG93LmNsZWFyVGltZW91dCh0aGlzLmRhdGFzZXQudGltZW91dCk7XG5cdFx0XHRcdFx0dGhpcy5kYXRhc2V0LnRpbWUgPSAwO1xuXHRcdFx0XHRcdGNvbnNvbGUubG9nKCdtb3VzZWxlYXZlIC0tICcsIHRoaXMuZGF0YXNldCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0Q29udGFpbmVyLmV2ZW50cyA9IHtcblx0XHRzZXR1cDogKCkgPT4ge1xuXHRcdFx0b24oZG9jdW1lbnQuYm9keSwgJ2NsaWNrJywgJ3ZhcltkYXRhLXl0bXVpZF0nLCBDb250YWluZXIuZXZlbnRzLmZyb21UYXJnZXQpO1xuXHRcdFx0b24oZG9jdW1lbnQuYm9keSwgJ2NsaWNrJywgJ2FbZGF0YS15dG1kZXNjcmlwdGlvbl0nLCBDb250YWluZXIuZXZlbnRzLm1hbnVhbExvYWQpO1xuXHRcdFx0b24oZG9jdW1lbnQuYm9keSwgJ2RibGNsaWNrJywgJ3FbZGF0YS1mdWxsXScsIENvbnRhaW5lci5ldmVudHMudGl0bGVUb2dnbGUpO1xuXG5cdFx0XHRvbihkb2N1bWVudC5ib2R5LCAnbW91c2VlbnRlciBtb3VzZWxlYXZlJywgJ2Rpdi55dG1fc2l0ZV95b3V0dWJlIHNwYW4ueXRtX3RyaWdnZXInLCBDb250YWluZXIuZGVjb3JhdG9ycy55b3V0dWJlLnRodW1iRXZlbnQpO1xuXHRcdH0sXG5cdFx0ZnJvbVRhcmdldDogKHsgdGFyZ2V0IH0pID0+IHsgLy8gdHJpZ2dlciB0aGUgdWlcblx0XHRcdGNvbnNvbGUuaW5mbygneXRtYS8vY2xpY2srdHJpZyhpZCknLCB0YXJnZXQuZGF0YXNldC55dG11aWQpO1xuXHRcdFx0Q29udHJvbC5jcmVhdGVGcm9tVHJpZ2dlcih0YXJnZXQpLnNob3dQbGF5ZXIoKTtcblx0XHR9LFxuXHRcdG1hbnVhbExvYWQ6IGUgPT4ge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0Y29uc3QgeyB0YXJnZXQgfSA9IGU7XG5cdFx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL2NsaWNrK2Rlc2MoaWQpJywgdGFyZ2V0LmRhdGFzZXQueXRtaWQpO1xuXHRcdFx0aWYgKCh0YXJnZXQuZGF0YXNldC50cmllcyB8fCAwKSA8PSA0KSB7XG5cdFx0XHRcdFkuYWpheC5sb2FkRnJvbURhdGFzZXQodGFyZ2V0LmRhdGFzZXQpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0dGl0bGVUb2dnbGU6IGUgPT4ge1xuXHRcdFx0Y29uc3QgdGFyZ2V0ID0gZS50YXJnZXQ7XG5cdFx0XHR0YXJnZXQuY2xhc3NMaXN0LnRvZ2dsZSgneXRtX2Rlc2NyX29wZW4nKTtcblx0XHRcdHRhcmdldC50ZXh0Q29udGVudCA9IHRhcmdldC50ZXh0Q29udGVudC5sZW5ndGggPCAxNDAgPyB0YXJnZXQuZGF0YXNldC5mdWxsIDogYCR7dGFyZ2V0LmRhdGFzZXQuZnVsbC5zdWJzdHIoMCwgMTMwKX0gLiAuIC5gO1xuXHRcdFx0dGFyZ2V0LnJlbW92ZUF0dHJpYnV0ZSgnc3R5bGUnKTtcblx0XHR9XG5cdH07XG5cblx0WS5udW0gPSAwO1xuXG5cdFkuYWRkVG9TZXQgPSB5dG1hID0+IFkuc2V0W3l0bWEuc3RhdGUudWlkXSA9IHl0bWE7XG5cblx0WS5jcmVhdGUgPSBsaW5rID0+IFkuZ3JhYklkQW5kU2l0ZShsaW5rLCAoZGF0YSwgZXJyKSA9PiB7XG5cdFx0aWYgKGVycikge1xuXHRcdFx0Y29uc29sZS53YXJuKGxpbmsuaHJlZiwgZXJyKTtcblx0XHRcdHJldHVybiB7fTtcblx0XHR9XG5cblx0XHRjb25zdCBjb250cm9sID0gbmV3IENvbnRyb2woeyAuLi5kYXRhLCBhbmNob3I6IGxpbmsgfSk7XG5cdFx0WS5hZGRUb1NldChjb250cm9sKTtcblx0XHRjb250cm9sLmNyZWF0ZUludGVyZmFjZSgpO1xuXG5cdFx0cmV0dXJuIGNvbnRyb2w7XG5cdH0pO1xuXG5cdFkuZ3JhYklkQW5kU2l0ZSA9IChsaW5rLCBjYikgPT4ge1xuXHRcdGxldCB1cmkgPSBsaW5rLmhyZWYgfHwgbGluay5zcmM7XG5cdFx0bGV0IGlkO1xuXHRcdGxldCBtYXRjaDtcblx0XHR0cnkge1xuXHRcdFx0Y29uc3Qgc2l0ZSA9IFkucmVnLnNpdGVCeVRlc3RbWS5yZWcuc2l0ZUV4cHJlc3Npb25zLnRlc3QodXJpKSA/IFJlZ0V4cC5sYXN0TWF0Y2ggOiAnJ107XG5cdFx0XHQvLyBjb25zb2xlLmxvZyhzaXRlKTtcblxuXHRcdFx0aWYgKHNpdGUgPT09ICdodG1sNScpIHsgLy8gfHwgc2l0ZSA9PT0gJ2h0bWw1LWF1ZGlvJ1xuXHRcdFx0XHRpZCA9IHVyaS5zbGljZSgtMTUpO1xuXHRcdFx0fSBlbHNlIGlmIChzaXRlID09PSAnc291bmRjbG91ZCcpIHtcblx0XHRcdFx0aWYgKCFZLnJlZy5leHRyYS5zb3VuZGNsb3VkLnBsYXlsaXN0LnRlc3QodXJpKSkge1xuXHRcdFx0XHRcdGxpbmsuaHJlZiA9IHVyaSA9IFkucmVnLmZpeC5zb3VuZGNsb3VkKHVyaSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRtYXRjaCA9IFkuREIuc2l0ZXMuc291bmRjbG91ZC5tYXRjaGVyLmV4ZWModXJpKTtcblx0XHRcdFx0aWQgPSBZLmVzY2FwZUlkKG1hdGNoWzFdKTtcblxuXHRcdFx0XHRpZiAobWF0Y2ggJiYgWS5yZWcuZXh0cmEuc291bmRjbG91ZC50cmFja3MudGVzdCh1cmkpKSB7XG5cdFx0XHRcdFx0aWQgPSBpZC5zbGljZSgtNTApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZCA9IHVyaS5tYXRjaChZLkRCLnNpdGVzW3NpdGVdLm1hdGNoZXIpWzFdO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL2lkK3NpdGUnLCBpZCwgc2l0ZSwgbWF0Y2gpO1xuXHRcdFx0aWYgKGlkICYmIFkuREIuc2l0ZXNbc2l0ZV0pIHtcblx0XHRcdFx0cmV0dXJuIGNiKHsgaWQsIHNpdGUgfSwgbnVsbCk7XG5cdFx0XHR9XG5cdFx0XHR0aHJvdyBUeXBlRXJyb3IoYEludmFsaWQgSUQvU2l0ZTogJHtpZH0gQCAke3NpdGV9YCk7XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0cmV0dXJuIGNiKG51bGwsIGUpO1xuXHRcdH1cblx0fTtcblxuXHRZLmVzY2FwZUlkID0gaWQgPT4gYCR7aWR9YC5yZXBsYWNlKC8oPzpcXFcpL2csICdfJyk7XG5cblx0WS5zZXQgPSB7fTtcblxuXHRZLmNvbGxlY3QgPSBpZCA9PiB7XG5cdFx0Y29uc3QgYSA9IE9iamVjdC52YWx1ZXMoWS5zZXQpLmZpbHRlcih5dG1hID0+IHl0bWEgJiYgeXRtYS5kYXRhLmlkID09PSBpZCk7XG5cdFx0cmV0dXJuIGE7XG5cdH07XG5cblx0WS5yb3V0ZSA9IHtcblx0XHRob3N0OiBkb2N1bWVudC5sb2NhdGlvbi5ob3N0LnJlcGxhY2UoJ3d3dy4nLCAnJyksXG5cdFx0Y29udHJvbDoge1xuXHRcdFx0JDoge1xuXHRcdFx0XHRjaGVja1N0b3JhZ2U6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRpZiAoc3RyZy5mdWxsKCkgPT09IHRydWUpIHtcblx0XHRcdFx0XHRcdGNvbnNvbGUubG9nKCdZVE1BIEVSUk9SOiBTdG9yYWdlIGlzIGZ1bGwhJyk7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShZLmV4dGVybmFsLnZlcnNpb24pO1xuXHRcdFx0XHRcdFx0XHRzdHJnLm9uID0gc3RyZy50ZXN0KCk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnNvbGUuZXJyb3IoZSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRydW5PbmNlOiBmdW5jdGlvbiAobG9vcCkge1xuXHRcdFx0XHRcdGlmICghZG9jdW1lbnQuYm9keS5kYXRhc2V0Lnl0bWFlbmFibGVkKSB7XG5cdFx0XHRcdFx0XHRkb2N1bWVudC5ib2R5LmRhdGFzZXQueXRtYWVuYWJsZWQgPSB0cnVlO1xuXG5cdFx0XHRcdFx0XHR0aGlzLmNoZWNrU3RvcmFnZSgpO1xuXG5cdFx0XHRcdFx0XHRpZiAoIVkuREIuZXh0ZW5zaW9uKSB7IHVwZGF0ZS5jaGVjaygpOyB9XG5cblx0XHRcdFx0XHRcdFkuY3NzKCk7XG5cdFx0XHRcdFx0XHRZLnVzZXIuaW5pdCgpO1xuXHRcdFx0XHRcdFx0WS5EQi5wb3N0SW5pdCgpO1xuXG5cdFx0XHRcdFx0XHRpZiAobG9vcCkge1xuXHRcdFx0XHRcdFx0XHRkb2N1bWVudC5ib2R5LmRhdGFzZXQuWVRNQV9MT09QID0gd2luZG93LnNldEludGVydmFsKGxvb3AsIDUwMDApO1xuXHRcdFx0XHRcdFx0XHRsb29wKCk7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdENvbnRhaW5lci5ldmVudHMuc2V0dXAoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRnbzogZnVuY3Rpb24gKGhvc3QpIHtcblx0XHRcdFx0Y29uc29sZS5pbmZvKCd5dG1hLy9ob3N0JywgaG9zdCk7XG5cdFx0XHRcdGlmICgvKD86Z29vZ2xldmlkZW98eW91dHViZS1ub2Nvb2tpZVxcLmNvbXx5b3V0dWJlXFwuY29tXFwuPykvaS50ZXN0KGhvc3QpKSB7XG5cdFx0XHRcdFx0dGhpcy5zaXRlcy55b3V0dWJlKCk7XG5cdFx0XHRcdH0gZWxzZSBpZiAodGhpcy5zaXRlc1tob3N0XSkge1xuXHRcdFx0XHRcdHRoaXMuc2l0ZXNbaG9zdF0oKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLnNpdGVzLiRnZW5lcmljKCk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRzaXRlczoge1xuXHRcdFx0XHQkZ2VuZXJpYzogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdGZ1bmN0aW9uIGxvb3AoKSB7XG5cdFx0XHRcdFx0XHRpZiAoWS5zZWxlY3Rvci5wcm9jZXNzb3IoKSA+IDApIHtcblx0XHRcdFx0XHRcdFx0WS51c2VyLmZuLmxvYWRQcmVmZXJlbmNlcygpO1xuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL2FnYWluKysnKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRZLnJvdXRlLmNvbnRyb2wuJC5ydW5PbmNlKGxvb3ApO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHQncmVzZXRlcmEuY29tJzogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdF8uY3NzKCcueXRtX29wdGlvbnMgbGkgdWwgbGkgeyBoZWlnaHQ6IDI0cHggIWltcG9ydGFudCB9Jyk7XG5cdFx0XHRcdFx0Xy5jc3MoJy5iYkNvZGVRdW90ZSAucXVvdGVDb250YWluZXIgLnF1b3RlIHsgbWF4LWhlaWdodDogaW5pdGlhbCB9IC5iYkNvZGVRdW90ZSAucXVvdGVDb250YWluZXIgLnF1b3RlRXhwYW5kLnF1b3RlQ3V0IHsgZGlzcGxheTogbm9uZSB9Jyk7XG5cdFx0XHRcdFx0Xy5jc3MoJy5iYkNvZGVRdW90ZSAueXRtX2Jsb2NrIGlmcmFtZSwgLmJiQ29kZVF1b3RlIC55dG1fYmxvY2sgW2RhdGEtczllLW1lZGlhZW1iZWRdLCAuYmJDb2RlUXVvdGUgLnl0bV9ibG9jayAuZmJfaWZyYW1lX3dpZGdldCwgLmJiQ29kZVF1b3RlIC55dG1fYmxvY2sgb2JqZWN0LCAuYmJDb2RlUXVvdGUgLnl0bV9ibG9jayBlbWJlZCB7IG1heC1oZWlnaHQ6IGluaXRpYWw7IG1heC13aWR0aDogaW5pdGlhbCB9Jyk7XG5cdFx0XHRcdFx0dGhpcy4kZ2VuZXJpYygpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XHQnZ2Z5Y2F0LmNvbSc6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRjb25zdCB2ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcigndmlkZW8nKTtcblx0XHRcdFx0XHR2LmNvbnRyb2xzID0gdHJ1ZTtcblx0XHRcdFx0XHRfLmNzcygnYm9keSxodG1sIHtvdmVyZmxvdzpoaWRkZW47aGVpZ2h0OjEwMCU7d2lkdGg6MTAwJX0gdmlkZW8ge2Rpc3BsYXk6dGFibGU7aGVpZ2h0OjEwMCU7bWFyZ2luOjAgYXV0bzt9Jyk7XG5cdFx0XHRcdFx0ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh2KTtcblx0XHRcdFx0fSxcblx0XHRcdFx0J3ZpbmUuY28nOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0Ly8gY29uc29sZS5sb2coJ3ZpbmUuY28nKTtcblxuXHRcdFx0XHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdyZXNpemUnLCAoKSA9PiB7XG5cdFx0XHRcdFx0XHRfLnMoJ1tzdHlsZV0nLCBlID0+IHtcblx0XHRcdFx0XHRcdFx0ZS5yZW1vdmVBdHRyaWJ1dGUoJ3N0eWxlJyk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSxcblx0XHRcdFx0eW91dHViZTogZnVuY3Rpb24gKCkgeyAvLyBsZXRzIGZvcmNlIHNvbWUgcXVhbGl0eSBwYXJpdHlcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0bG9hZDogZnVuY3Rpb24gKCkge1xuXHRcdFx0dGhpcy5jb250cm9sLmdvKHRoaXMuaG9zdCk7XG5cdFx0fVxuXHR9O1xuXG5cdFkubWFpbiA9ICgpID0+IHtcblx0XHRZLnJlZy5zaXRlRXhwcmVzc2lvbnMgPSBZLnJlZy5nZXRBbGxTaXRlUmVnRXhwcygpO1xuXHRcdC8vIGNvbnNvbGUubG9nKFlUTUEucmVnLnNpdGVFeHByZXNzaW9ucyk7XG5cdFx0WS5yb3V0ZS5sb2FkKCk7XG5cdH07XG5cblx0WS5yZWcgPSB7XG5cdFx0c2l0ZUV4cHJlc3Npb25zOiBudWxsLFxuXHRcdHRpbWU6IC8oPzp0PSg/OihcXGQrKWgpPyg/OihcXGQrKW0pPyhcXGQrKSkvLFxuXHRcdGlvczogLyg/OlxcYig/Omlwb2R8aXBob25lfGlwYWQpKVxcYi9pLFxuXHRcdGV4dHJhOiB7XG5cdFx0XHRzb3VuZGNsb3VkOiB7XG5cdFx0XHRcdHBsYXlsaXN0OiAvKD86c291bmRjbG91ZFxcLmNvbVxcLy4rXFwvc2V0c1xcLykvLFxuXHRcdFx0XHR0cmFja3M6IC8oPzpzb3VuZGNsb3VkXFwuY29tXFwvLitcXC90cmFja3NcXC8pL1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c2l0ZUJ5VGVzdDoge1xuXHRcdFx0eW91dHU6ICd5b3V0dWJlJyxcblx0XHRcdHZpbWVvOiAndmltZW8nLFxuXHRcdFx0dmluZTogJ3ZpbmUnLFxuXHRcdFx0Z2Z5Y2F0OiAnZ2Z5Y2F0Jyxcblx0XHRcdGltZ3VyOiAnaW1ndXInLFxuXHRcdFx0Jy53ZWJtJzogJ2h0bWw1Jyxcblx0XHRcdCcubXA0JzogJ2h0bWw1Jyxcblx0XHRcdC8vICcubXAzJzogJ2h0bWw1LWF1ZGlvJyxcblx0XHRcdCcuZ2lmdic6ICdodG1sNScsXG5cdFx0XHRzb3VuZGNsb3VkOiAnc291bmRjbG91ZCcsXG5cdFx0XHQnc3RyZWFtYWJsZS5jb20nOiAnc3RyZWFtYWJsZSdcblx0XHR9LFxuXHRcdGdldEFsbFNpdGVSZWdFeHBzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRjb25zdCByZWdzID0gT2JqZWN0LnZhbHVlcyhZLkRCLnNpdGVzKVxuXHRcdFx0XHQuZmlsdGVyKCh7IHJlZyB9KSA9PiByZWcpXG5cdFx0XHRcdC5tYXAoKHsgcmVnIH0pID0+IHJlZyk7XG5cblx0XHRcdHJldHVybiBuZXcgUmVnRXhwKGBcXFxcYiR7cmVncy5qb2luKCd8Jyl9YCk7XG5cdFx0fSxcblx0XHRmaXg6IHtcblx0XHRcdHNvdW5kY2xvdWQ6IGZ1bmN0aW9uICh1cmkpIHtcblx0XHRcdFx0Y29uc3QgbWF0Y2ggPSBZLkRCLnNpdGVzLnNvdW5kY2xvdWQubWF0Y2hlci5leGVjKHVyaSk7XG5cdFx0XHRcdGlmIChtYXRjaCkge1xuXHRcdFx0XHRcdGNvbnN0IGlkID0gbWF0Y2hbMV0uc3BsaXQoJy8nLCAyKS5qb2luKCcvJyk7XG5cdFx0XHRcdFx0dXJpID0gcmVtb3ZlU2VhcmNoKGBodHRwczovL3NvdW5kY2xvdWQuY29tLyR7aWR9YCwgdHJ1ZSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdXJpO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHRZLnNlbGVjdG9yID0geyAvLyB0byBidWlsZCB0aGUgc2VsZWN0b3Jcblx0XHRwYXJlbnRCbGFja2xpc3Q6IFsnLnNtYWxsZm9udCcsICcuY29saGVhZF9kYXJrJywgJy5zcG9pbGVyJywgJ3ByZScsICcubWVzc2FnZVVzZXJJbmZvJywgJy5mci1ib3gnXSxcblx0XHRnZXRBbGxTaXRlU2VsZWN0b3JzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRjb25zdCBzZWxzID0gT2JqZWN0LnZhbHVlcyhZLkRCLnNpdGVzKVxuXHRcdFx0XHQuZmlsdGVyKCh7IHNlbGVjdG9yIH0pID0+IHNlbGVjdG9yKVxuXHRcdFx0XHQubWFwKCh7IHNlbGVjdG9yIH0pID0+IHNlbGVjdG9yKTtcblxuXHRcdFx0cmV0dXJuIHNlbHMuam9pbigpO1xuXHRcdH0sXG5cdFx0aWdub3JlOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRjb25zdCBpZ25vcmUgPSBbXTtcblx0XHRcdGNvbnN0IGFsbCA9IFkuc2VsZWN0b3IuZ2V0QWxsU2l0ZVNlbGVjdG9ycygpLnNwbGl0KCcsJyk7XG5cdFx0XHRjb25zdCBibGFja2xpc3QgPSB0aGlzLnBhcmVudEJsYWNrbGlzdDtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYmxhY2tsaXN0Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgYWxsLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRcdFx0aWdub3JlLnB1c2goYCR7YmxhY2tsaXN0W2ldfSAke2FsbFtqXX1gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly8gY29uc29sZS5sb2coaWdub3JlLmpvaW4oJywnKSk7XG5cdFx0XHRyZXR1cm4gaWdub3JlLmpvaW4oJywnKTtcblx0XHR9LFxuXHRcdGlmcmFtZXM6IGZ1bmN0aW9uICgpIHsgLy8gZm9yIHJlc2V0ZXJhLCBjb252ZXJ0IGlmcmFtZXMgYmFjayB0byBhbmNob3JzXG5cdFx0XHRfLnMoJy5tZXNzYWdlLWJvZHkgaWZyYW1lJywgZiA9PiB7XG5cdFx0XHRcdGlmICgvdmlcXC8oLis/KVxcL2hxZGVmYXVsdC8udGVzdChmLnN0eWxlLmJhY2tncm91bmRJbWFnZSkpIHtcblx0XHRcdFx0XHRjb25zdCBzcmMgPSBgaHR0cHM6Ly95b3V0dS5iZS8ke1JlZ0V4cC4kMX1gO1xuXHRcdFx0XHRcdGNvbnN0IHNwYW4gPSBmLmNsb3Nlc3QoJ1tkYXRhLXM5ZS1tZWRpYWVtYmVkXScpO1xuXHRcdFx0XHRcdHNwYW4uaW5zZXJ0QWRqYWNlbnRIVE1MKCdiZWZvcmViZWdpbicsIGA8YSBocmVmPVwiJHtzcmN9XCI+eW91dHViZTwvYT5gKTtcblx0XHRcdFx0XHRzcGFuLnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoc3Bhbik7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXG5cdFx0XHRfLnMoJ1tkYXRhLXM5ZS1tZWRpYWVtYmVkLWlmcmFtZV0nLCBzID0+IHtcblx0XHRcdFx0Y29uc3QgZGF0ID0gSlNPTi5wYXJzZShzLmRhdGFzZXQuczllTWVkaWFlbWJlZElmcmFtZSk7XG5cdFx0XHRcdHMucGFyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50LmlubmVySFRNTCA9IGA8YSBocmVmPVwiJHtkYXRbZGF0Lmxlbmd0aCAtIDFdfVwiPnlvdXR1YmU8L2E+YDtcblx0XHRcdH0pO1xuXHRcdH0sXG5cdFx0bGlua3M6IGZ1bmN0aW9uICgpIHtcblx0XHRcdF8ucyhZLnNlbGVjdG9yLmlnbm9yZSgpLCAoeyBkYXRhc2V0IH0pID0+IGRhdGFzZXQueXRtYWlnbm9yZSA9IHRydWUpO1xuXG5cdFx0XHRjb25zdCBsaW5rcyA9IF8ucXNhKFkuc2VsZWN0b3IuZ2V0QWxsU2l0ZVNlbGVjdG9ycygpKS5maWx0ZXIoKHsgZGF0YXNldCB9KSA9PiB7XG5cdFx0XHRcdGNvbnN0IHIgPSAhZGF0YXNldC55dG1hcHJvY2Vzc2VkICYmICFkYXRhc2V0Lnl0bWFpZ25vcmU7XG5cdFx0XHRcdGRhdGFzZXQueXRtYXByb2Nlc3NlZCA9IHRydWU7XG5cdFx0XHRcdHJldHVybiByO1xuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiBsaW5rcztcblx0XHR9LFxuXHRcdHByb2Nlc3NvcjogZnVuY3Rpb24gKCkge1xuXHRcdFx0dGhpcy5pZnJhbWVzKCk7XG5cdFx0XHRjb25zdCBsaW5rcyA9IHRoaXMubGlua3MoKTtcblxuXHRcdFx0aWYgKGxpbmtzLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0bGlua3MuZm9yRWFjaChZLmNyZWF0ZSk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBsaW5rcy5sZW5ndGg7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuXHQgKiBVc2VyIFByZWZlcmVuY2VzXG5cdCAqIHNpemU6IFNtYWxsICgyNDBwKSwgTWVkaXVtICgzNjBwKSwgTGFyZ2UgKDQ4MHApLCBYTCAoNzIwcClcblx0ICogcmF0aW86IDEgNDozLCAyIDE2Ojlcblx0ICogcXVhbGl0eTogMjQwLCAzNjAsIDQ4MCwgNzIwLCAxMDgwXG5cdCAqIGZvY3VzOiAwLzE7IFdpbGwgYXR0ZW1wdCB0byBzZXQgdGhlIHdpbmRvdydzIGZvY3VzIG5lYXIgdGhlIHZpZGVvXG5cdCAqIGF1dG9TaG93OiAwLzE7IFdpbGwgYXV0b21hdGljYWxseSBkaXNwbGF5IEhUTUw1IHZpZGVvcywgd2hpY2ggY3VycmVudGx5IGxhY2sgZGVzY3JpcHRpb25zIGFuZCB0aHVtYm5haWxzXG5cdCAqIGRlc2M6IChEZXNjcmlwdGlvbnMpIDAgTm9uZTsgMSBZZXMgb24gc2Nyb2xsOyAyIFllcyBhbGwgYXQgb25jZVxuXHQgKiB5dF9ub2Nvb2tpZTogMC8xOyBXaWxsIGRpc2FibGUvZW5hYmxlIHlvdXR1YmUtbm9jb29raWUuY29tXG5cdCAqIHl0X2Fubm90YXRpb246IDAvMTsgeW91dHViZSBhbm5vdGF0aW9uc1xuXHQgKi9cblx0WS51c2VyID0ge1xuXHRcdEtFWTogJ3l0bWFzZXR0cycsXG5cdFx0JGZvcm06IG51bGwsXG5cdFx0aW5pdDogZnVuY3Rpb24gKCkge1xuXHRcdFx0dGhpcy5sb2FkKCk7XG5cblx0XHRcdGlmIChzdHJnLm9uKSB7XG5cdFx0XHRcdHRoaXMuZm4ubWFrZUZvcm0oKTtcblx0XHRcdFx0dGhpcy5tYXJrKCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHR2YWxpZDoge1xuXHRcdFx0Zm9jdXM6IFswLCAxXSxcblx0XHRcdGRlc2M6IFswLCAxLCAyXSxcblx0XHRcdHJhdGlvOiBbMSwgMl0sXG5cdFx0XHRzaXplOiBbMjQwLCAzNjAsIDQ4MCwgNzIwXSxcblx0XHRcdHF1YWxpdHk6IFsyNDAsIDM2MCwgNDgwLCA3MjAsIDEwODBdLFxuXHRcdFx0YXV0b1Nob3c6IFswLCAxXSxcblx0XHRcdHl0X25vY29va2llOiBbMCwgMV0sXG5cdFx0XHR5dF9hbm5vdGF0aW9uOiBbMCwgMV0gLy8gaGlkZSB8IHNob3dcblx0XHR9LFxuXHRcdG1hcHBpbmc6IHsgLy8gbWFwIHZhbHVlcyB0byBzb21lIG90aGVyIHZhbHVlcyB1c2VkIGJ5IGFuIGV4dGVybmFsIEFQSSwgZm9yIGV4YW1wbGVcblx0XHRcdHl0X2Fubm90YXRpb246IFszLCAxXSAvLyAzID0gaGlkZSB8IDEgPSBzaG93XG5cdFx0fSxcblx0XHR2YWxpZGF0ZTogZnVuY3Rpb24gKHByb3BlcnR5LCBuKSB7XG5cdFx0XHRuID0gK247XG5cdFx0XHRyZXR1cm4gWS51c2VyLnZhbGlkW3Byb3BlcnR5XS5pbmNsdWRlcyhuKSA/IG4gOiBZLnVzZXIuZGVmYXVsdHNbcHJvcGVydHldO1xuXHRcdH0sXG5cdFx0Z2V0IGRlZmF1bHRzKCkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0Zm9jdXM6IDAsXG5cdFx0XHRcdGRlc2M6IDEsXG5cdFx0XHRcdHJhdGlvOiAyLFxuXHRcdFx0XHRzaXplOiAzNjAsXG5cdFx0XHRcdHF1YWxpdHk6IDcyMCxcblx0XHRcdFx0YXV0b1Nob3c6IDEsXG5cdFx0XHRcdHl0X25vY29va2llOiAwLFxuXHRcdFx0XHR5dF9hbm5vdGF0aW9uOiAxXG5cdFx0XHR9O1xuXHRcdH0sXG5cdFx0bG9hZDogZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29uc3QgcyA9IHN0cmcuZ3JhYihZLnVzZXIuS0VZLCB7fSk7XG5cblx0XHRcdFkudXNlci5wcmVmZXJlbmNlcyA9IE9iamVjdC5rZXlzKHRoaXMuZGVmYXVsdHMpLnJlZHVjZSgodmFsaWQsIGspID0+IHtcblx0XHRcdFx0dmFsaWRba10gPSBZLnVzZXIudmFsaWRhdGUoaywgc1trXSk7XG5cdFx0XHRcdHJldHVybiB2YWxpZDtcblx0XHRcdH0sIHt9KTtcblxuXHRcdFx0Xy5vKFkudXNlci5tYXBwaW5nLCAoa2V5LCB2YWwpID0+IHtcblx0XHRcdFx0aWYgKCF2YWwuaGFzT3duUHJvcGVydHkoJ2luZGV4T2YnKSkge1xuXHRcdFx0XHRcdFkudXNlci5wcmVmZXJlbmNlc1trZXldID0gdmFsW1kudXNlci52YWxpZFtrZXldLmluZGV4T2YoWS51c2VyLnByZWZlcmVuY2VzW2tleV0pXTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdGNvbnNvbGUuaW5mbygneXRtYS8vdXNlcitsb2FkZWQocHJlZnMpJywgWS51c2VyLnByZWZlcmVuY2VzKTtcblx0XHR9LFxuXHRcdG1hcms6IGZ1bmN0aW9uICgpIHtcblx0XHRcdGNvbnN0IGEgPSB7fTtcblx0XHRcdGEueXRtYV9fZm9jdXMgPSAhIVkudXNlci5wcmVmZXJlbmNlcy5mb2N1cztcblx0XHRcdGEueXRtYV9fYXV0b1Nob3cgPSAhIVkudXNlci5wcmVmZXJlbmNlcy5hdXRvU2hvdztcblx0XHRcdGEueXRtYV9feXRfbm9jb29raWUgPSAhIVkudXNlci5wcmVmZXJlbmNlcy55dF9ub2Nvb2tpZTtcblx0XHRcdGEueXRtYV9feXRfYW5ub3RhdGlvbiA9ICEhWS51c2VyLnByZWZlcmVuY2VzLnl0X2Fubm90YXRpb247XG5cdFx0XHRhW2B5dG1hX19yYXRpbyR7WS51c2VyLnByZWZlcmVuY2VzLnJhdGlvfWBdID0gdHJ1ZTtcblx0XHRcdGFbYHl0bWFfX3NpemUke1kudXNlci5wcmVmZXJlbmNlcy5zaXplfWBdID0gdHJ1ZTtcblx0XHRcdGFbYHl0bWFfX2Rlc2Mke1kudXNlci5wcmVmZXJlbmNlcy5kZXNjfWBdID0gdHJ1ZTtcblx0XHRcdGFbYHl0bWFfX3F1YWxpdHkke1kudXNlci5wcmVmZXJlbmNlcy5xdWFsaXR5fWBdID0gISFZLnVzZXIucHJlZmVyZW5jZXMucXVhbGl0eTtcblxuXHRcdFx0Ly8gY29uc29sZS5sb2coJ21hcmtpbmcnLCBhKTtcblx0XHRcdF8ubyhhLCAoaWQsIHZhbCkgPT4ge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGNvbnN0IGVsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpO1xuXHRcdFx0XHRcdGVsLmNoZWNrZWQgPSB2YWw7XG5cdFx0XHRcdFx0ZWwudmFsdWUgPSB2YWw7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHQvLyBjb25zb2xlLmxvZyhpZCwgZSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0sXG5cdFx0ZXZlbnRzOiB7XG5cdFx0XHRzYXZlOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdC8vIGNvbnNvbGUubG9nKFlUTUEudXNlci4kZm9ybS5xdWVyeVNlbGVjdG9yQWxsKCdbZGF0YS1rZXldJykpO1xuXHRcdFx0XHQvLyBbZGF0YS1rZXldOmNoZWNrZWRcblx0XHRcdFx0Y29uc3Qgc2V0dGluZ3MgPSBBcnJheS5mcm9tKFkudXNlci4kZm9ybS5xdWVyeVNlbGVjdG9yQWxsKCdbZGF0YS1rZXldJykpLnJlZHVjZSgob2JqLCBlKSA9PiB7XG5cdFx0XHRcdFx0bGV0IGtleSA9IGUuZGF0YXNldC5rZXk7XG5cblx0XHRcdFx0XHRpZiAoZS50eXBlID09PSAnY2hlY2tib3gnKSB7XG5cdFx0XHRcdFx0XHRvYmpba2V5XSA9ICtlLmNoZWNrZWQ7XG5cdFx0XHRcdFx0fSBlbHNlIGlmIChlLnR5cGUgPT09ICdyYWRpbycpIHtcblx0XHRcdFx0XHRcdGlmIChlLmNoZWNrZWQpIHtcblx0XHRcdFx0XHRcdFx0aWYgKGUuZGF0YXNldC5udW0pIHtcblx0XHRcdFx0XHRcdFx0XHRvYmpba2V5XSA9ICtlLmRhdGFzZXQubnVtO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdG9ialtrZXldID0gK2UudmFsdWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIG9iajtcblx0XHRcdFx0fSwge30pO1xuXG5cdFx0XHRcdGlmIChzdHJnLnNhdmUoWS51c2VyLktFWSwgc2V0dGluZ3MpKSB7XG5cdFx0XHRcdFx0WS51c2VyLmxvYWQoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRZLnVzZXIuZXJyb3IuY2xhc3NMaXN0LnJlbW92ZSgneXRtX25vbmUnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHR9LFxuXHRcdFx0cmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0WS51c2VyLnByZWZlcmVuY2VzID0gWS51c2VyLmRlZmF1bHRzO1xuXHRcdFx0XHRZLnVzZXIubWFyaygpO1xuXHRcdFx0XHRzdHJnLndpcGUoWS51c2VyLktFWSk7XG5cdFx0XHRcdFkudXNlci5lcnJvci5jbGFzc0xpc3QuYWRkKCd5dG1fbm9uZScpO1xuXHRcdFx0fSxcblx0XHRcdGNsZWFyOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0bG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oWS5leHRlcm5hbC52ZXJzaW9uKTtcblx0XHRcdFx0XHRZLnVzZXIuZXZlbnRzLnJlc2V0KCk7XG5cdFx0XHRcdFx0Y29uc29sZS5pbmZvKCd5dG1hLy9jYWNoZStyZW1vdmUnLCAncmVtb3ZlZCBhbGwgWVRNQSBjYWNoZScpO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0Y29uc29sZS5lcnJvcihlKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGZvcm1Ub2dnbGU6IGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdGlmIChZLnVzZXIuJGZvcm0gJiYgKCFlIHx8IChlICYmIGUudGFyZ2V0ICYmICEoLyg/OklOUFVUfExBQkVMKS9pKS50ZXN0KGUudGFyZ2V0Lm5vZGVOYW1lKSkpKSB7XG5cdFx0XHRcdFx0WS51c2VyLiRmb3JtLmNsYXNzTGlzdC50b2dnbGUoJ3l0bV9ub25lJyk7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0XHRmb3JtVG9nZ2xlS2V5Ym9hcmQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0XHRcdC8vIHByZXNzIENUUkwrU0hJRlQrWSAoTUVUQStTSElGVCtZKSB0byBkaXNwbGF5IHNldHRpbmdzIGZvcm1cblx0XHRcdFx0aWYgKChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSAmJiBlLnNoaWZ0S2V5ICYmIFN0cmluZy5mcm9tQ2hhckNvZGUoZS53aGljaCkudG9Mb3dlckNhc2UoKSA9PT0gJ3knKSB7XG5cdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdFkudXNlci5ldmVudHMuZm9ybVRvZ2dsZSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRmbjoge1xuXHRcdFx0JHNjcm9sbGVyOiBudWxsLFxuXHRcdFx0JG9uY2U6IGZhbHNlLFxuXHRcdFx0bG9hZFByZWZlcmVuY2VzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFkudXNlci5mbi5vblNjcm9sbExvYWREZXNjcmlwdGlvbnMoWS51c2VyLnByZWZlcmVuY2VzLmRlc2MgPT09IDEpO1xuXG5cdFx0XHRcdHRoaXMubG9hZFByZWZlcmVuY2VzT25jZSgpO1xuXHRcdFx0fSxcblx0XHRcdGxvYWRQcmVmZXJlbmNlc09uY2U6IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0aWYgKHRoaXMuJG9uY2UpIHsgcmV0dXJuOyB9XG5cblx0XHRcdFx0dGhpcy4kb25jZSA9IHRydWU7XG5cblx0XHRcdFx0aWYgKFkudXNlci5wcmVmZXJlbmNlcy5hdXRvU2hvdyA9PT0gMSkge1xuXHRcdFx0XHRcdFkudXNlci5mbi5vblNjcm9sbFZpZXdNZWRpYSgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0c2hvd01lZGlhOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdC8vIGNvbnNvbGUuaW5mbygneXRtYS8vdXNlcitmbi1zaG93TWVkaWEnKTtcblx0XHRcdFx0cmV0dXJuIG5ldyBTY3JvbGwoJ2EueXRtX3Njcm9sbDpub3QoW2RhdGEteXRtc2Nyb2xsPVwiZmFsc2VcIl0pJywgbGluayA9PiB7XG5cdFx0XHRcdFx0aWYgKFNjcm9sbC52aXNpYmxlQWxsKGxpbmssIDUwKSkge1xuXHRcdFx0XHRcdFx0Xy5zKGB2YXJbZGF0YS15dG1zaWQ9XCIke2xpbmsuZGF0YXNldC55dG1zaWR9XCJdOm5vdChbZGF0YS15dG1zY3JvbGw9XCJmYWxzZVwiXSlgLCB0cmlnZ2VyID0+IHtcblx0XHRcdFx0XHRcdFx0Y29uc3QgdWkgPSBDb250cm9sLmNyZWF0ZUZyb21UcmlnZ2VyKHRyaWdnZXIpO1xuXHRcdFx0XHRcdFx0XHR1aS5zaG93T25TY3JvbGwobGluayk7XG5cdFx0XHRcdFx0XHR9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSxcblx0XHRcdHRvZ2dsZU1lZGlhOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJldHVybiBuZXcgU2Nyb2xsKCdkaXYueXRtX3BhbmVsX3N3aXRjaGVyJywgZGl2ID0+IHtcblx0XHRcdFx0XHRjb25zdCB2ID0gZGl2LnF1ZXJ5U2VsZWN0b3IoJ3ZpZGVvJyk7XG5cdFx0XHRcdFx0Y29uc3QgcGF1c2VkID0gdiAmJiAodi5wYXVzZWQgfHwgdi5lbmRlZCk7XG5cdFx0XHRcdFx0Y29uc3QgdWkgPSBZLnNldFtkaXYuZGF0YXNldC55dG11aWRdLmdldENvbnRyb2woKTtcblxuXHRcdFx0XHRcdGlmIChwYXVzZWQgJiYgIVNjcm9sbC52aXNpYmxlQWxsKGRpdiwgMCkpIHtcblx0XHRcdFx0XHRcdHJldHVybiB1aS5wbGF5LnN3aXRjaFN0YW5kYnkoKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAodWkucGxheS5pc1N0YW5kYnkoKSAmJiBTY3JvbGwudmlzaWJsZUFsbChkaXYsIDIwMCkpIHtcblx0XHRcdFx0XHRcdHJldHVybiB1aS5wbGF5LnN3aXRjaE9uKCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gdG9kbyBhc2NlcnRhaW4gZW1iZWRkZWQgcGxheWVyIHByb3BlcnRpZXNcblx0XHRcdFx0XHQvLyBmID0gZGl2LnF1ZXJ5U2VsZWN0b3IoJ2lmcmFtZSwgb2JqZWN0Jyk7XG5cdFx0XHRcdFx0Ly8gaWYgKGYgJiYgIVlUTUEuU2Nyb2xsLnZpc2libGVBbGwoZGl2LCAyMDApKSB7XG5cdFx0XHRcdFx0Ly8gXHR5LmhpZGVQbGF5ZXIoKTtcblx0XHRcdFx0XHQvLyB9XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSxcblx0XHRcdG9uU2Nyb2xsVmlld01lZGlhOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRoaXMuc2hvd01lZGlhKCk7XG5cdFx0XHRcdHRoaXMudG9nZ2xlTWVkaWEoKTtcblx0XHRcdH0sXG5cdFx0XHRvblNjcm9sbExvYWREZXNjcmlwdGlvbnM6IGZ1bmN0aW9uIChhamF4KSB7XG5cdFx0XHRcdGlmIChZLnVzZXIuZm4uJHNjcm9sbGVyKSB7IFkudXNlci5mbi4kc2Nyb2xsZXIuc3RvcCgpOyB9XG5cblx0XHRcdFx0WS51c2VyLmZuLiRzY3JvbGxlciA9IG5ldyBTY3JvbGwoJ3NwYW4ueXRtX21hbnVhbCA+IGEueXRtX3RpdGxlOm5vdCgueXRtX2Vycm9yKScsIGEgPT4ge1xuXHRcdFx0XHRcdGlmIChTY3JvbGwudmlzaWJsZUFsbChhLCAyMDApKSB7XG5cdFx0XHRcdFx0XHRpZiAoYWpheCkge1xuXHRcdFx0XHRcdFx0XHRZLmFqYXgubG9hZEZyb21EYXRhc2V0KGEuZGF0YXNldCk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRZLmFqYXgubG9hZEZyb21DYWNoZURhdGFzZXQoYS5kYXRhc2V0KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vIGNvbnNvbGUubG9nKCdkb2MnLCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKFlUTUEudXNlci5mbi4kc2Nyb2xsZXIuc2VsZWN0b3IpLmxlbmd0aCwgYS5kYXRhc2V0LmlkKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChZLnVzZXIuZm4uJHNjcm9sbGVyLnNlbGVjdG9yKS5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0XHRcdFkudXNlci5mbi4kc2Nyb2xsZXIuc3RvcCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cdFx0XHR9LFxuXHRcdFx0bWFrZUZvcm06IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0Y29uc3QgdGVtcGxhdGUgPSBgXG5cdFx0XHRcdFx0PGRpdiBpZD1cInl0bV9zZXR0aW5nc1wiIGNsYXNzPVwieXRtX3NhbnMgeXRtX2Jsb2NrIHl0bV9ub3JtYWxpemVcIj5cblx0XHRcdFx0XHRcdDxmb3JtIGFjdGlvbj1cIlwiIHRpdGxlPVwiRG91YmxlIGNsaWNrIHRvIGNsb3NlXCI+XG5cdFx0XHRcdFx0XHRcdDxkaXYgaWQ9XCJ5dG1fc2V0dGluZ3N0XCI+eXRtYSEgU2l0ZSBTZXR0aW5nczwvZGl2PjxkaXYgY2xhc3M9XCJ5dG1fZmllbGRfY29udGFpbmVyXCI+XG5cdFx0XHRcdFx0XHRcdFx0PGZpZWxkc2V0PjxsZWdlbmQgdGl0bGU9XCJMb2FkIGRlc2NyaXB0aW9ucyBmcm9tIHRoZSBjb250ZW50IHNldmVyLlwiPkxvYWQgRGVzY3JpcHRpb25zPC9sZWdlbmQ+PHA+PHNwYW4+PGlucHV0IGlkPVwieXRtYV9fZGVzYzBcIiB0eXBlPVwicmFkaW9cIiBkYXRhLW51bT1cIjBcIiBuYW1lPVwieXRtYV9fZGVzY1wiIGRhdGEta2V5PVwiZGVzY1wiPjxsYWJlbCBmb3I9XCJ5dG1hX19kZXNjMFwiIHRpdGxlPVwiTG9hZCBkZXNjcmlwdGlvbnMgb24gZGVtYW5kXCI+TWFudWFsbHk8L2xhYmVsPjwvc3Bhbj48c3Bhbj48aW5wdXQgaWQ9XCJ5dG1hX19kZXNjMVwiIHR5cGU9XCJyYWRpb1wiIGRhdGEtbnVtPVwiMVwiIG5hbWU9XCJ5dG1hX19kZXNjXCIgZGF0YS1rZXk9XCJkZXNjXCI+PGxhYmVsIGZvcj1cInl0bWFfX2Rlc2MxXCIgdGl0bGU9XCJMb2FkIGRlc2NyaXB0aW9ucyBhcyB0aGV5IGJlY29tZSB2aXNpYmxlIG9uIHRoZSBzY3JlZW4uXCI+QXV0b21hdGljYWxseSwgb24gc2Nyb2xsaW5nPC9sYWJlbD48L3NwYW4+PC9wPjwvZmllbGRzZXQ+XG5cdFx0XHRcdFx0XHRcdFx0PGZpZWxkc2V0PjxsZWdlbmQ+SFRNTDUgUGxheWVyczwvbGVnZW5kPjxwPjxpbnB1dCBuYW1lPVwieXRtYV9fYXV0b1Nob3dcIiBkYXRhLWtleT1cImF1dG9TaG93XCIgaWQ9XCJ5dG1hX19hdXRvU2hvd1wiIHR5cGU9XCJjaGVja2JveFwiPjxsYWJlbCBmb3I9XCJ5dG1hX19hdXRvU2hvd1wiPkF1dG9tYXRpY2FsbHkgc2hvdyBXZWJNLCBNUDQgYW5kIFNvdW5kY2xvdWQgcGxheWVyczwvbGFiZWw+PC9wPjwvZmllbGRzZXQ+XG5cdFx0XHRcdFx0XHRcdFx0PGZpZWxkc2V0PjxsZWdlbmQ+UGxheWVyIFNpemU8L2xlZ2VuZD48cD48c3Bhbj48aW5wdXQgdHlwZT1cInJhZGlvXCIgbmFtZT1cInl0bWFfX3NpemVcIiBkYXRhLWtleT1cInNpemVcIiBkYXRhLW51bT1cIjI0MFwiIGlkPVwieXRtYV9fc2l6ZTI0MFwiIC8+PGxhYmVsIGZvcj1cInl0bWFfX3NpemUyNDBcIj5TIDxzbWFsbD4yNDBwPC9zbWFsbD48L2xhYmVsPjwvc3Bhbj48c3Bhbj48aW5wdXQgbmFtZT1cInl0bWFfX3NpemVcIiBkYXRhLWtleT1cInNpemVcIiB0eXBlPVwicmFkaW9cIiBpZD1cInl0bWFfX3NpemUzNjBcIiBkYXRhLW51bT1cIjM2MFwiIC8+PGxhYmVsIGZvcj1cInl0bWFfX3NpemUzNjBcIj5NIDxzbWFsbD4zNjBwPC9zbWFsbD48L2xhYmVsPjwvc3Bhbj48c3Bhbj48aW5wdXQgdHlwZT1cInJhZGlvXCIgbmFtZT1cInl0bWFfX3NpemVcIiBkYXRhLWtleT1cInNpemVcIiBkYXRhLW51bT1cIjQ4MFwiIGlkPVwieXRtYV9fc2l6ZTQ4MFwiIC8+PGxhYmVsIGZvcj1cInl0bWFfX3NpemU0ODBcIj5MIDxzbWFsbD40ODBwPC9zbWFsbD48L2xhYmVsPjwvc3Bhbj48c3Bhbj48aW5wdXQgdHlwZT1cInJhZGlvXCIgbmFtZT1cInl0bWFfX3NpemVcIiBkYXRhLWtleT1cInNpemVcIiBkYXRhLW51bT1cIjcyMFwiIGlkPVwieXRtYV9fc2l6ZTcyMFwiIC8+PGxhYmVsIGZvcj1cInl0bWFfX3NpemU3MjBcIj5YIDxzbWFsbD43MjBwPC9zbWFsbD48L2xhYmVsPjwvc3Bhbj48L3A+PC9maWVsZHNldD5cblx0XHRcdFx0XHRcdFx0XHQ8ZmllbGRzZXQ+PGxlZ2VuZD5RdWFsaXR5PC9sZWdlbmQ+PHA+PHNwYW4+PGlucHV0IG5hbWU9XCJ5dG1hX19xdWFsaXR5XCIgZGF0YS1rZXk9XCJxdWFsaXR5XCIgZGF0YS1udW09XCIyNDBcIiBpZD1cInl0bWFfX3F1YWxpdHkyNDBcIiB0eXBlPVwicmFkaW9cIj48bGFiZWwgZm9yPVwieXRtYV9fcXVhbGl0eTI0MFwiPjI0MHA8L2xhYmVsPjwvc3Bhbj48c3Bhbj48aW5wdXQgbmFtZT1cInl0bWFfX3F1YWxpdHlcIiBkYXRhLWtleT1cInF1YWxpdHlcIiBpZD1cInl0bWFfX3F1YWxpdHkzNjBcIiBkYXRhLW51bT1cIjM2MFwiIHR5cGU9XCJyYWRpb1wiPjxsYWJlbCBmb3I9XCJ5dG1hX19xdWFsaXR5MzYwXCI+MzYwcDwvbGFiZWw+PC9zcGFuPjxzcGFuPjxpbnB1dCBuYW1lPVwieXRtYV9fcXVhbGl0eVwiIGRhdGEta2V5PVwicXVhbGl0eVwiIGRhdGEtbnVtPVwiNDgwXCIgaWQ9XCJ5dG1hX19xdWFsaXR5NDgwXCIgdHlwZT1cInJhZGlvXCI+PGxhYmVsIGZvcj1cInl0bWFfX3F1YWxpdHk0ODBcIj40ODBwPC9sYWJlbD48L3NwYW4+PHNwYW4+PGlucHV0IG5hbWU9XCJ5dG1hX19xdWFsaXR5XCIgZGF0YS1rZXk9XCJxdWFsaXR5XCIgZGF0YS1udW09XCI3MjBcIiBpZD1cInl0bWFfX3F1YWxpdHk3MjBcIiB0eXBlPVwicmFkaW9cIj48bGFiZWwgZm9yPVwieXRtYV9fcXVhbGl0eTcyMFwiPjcyMHA8L2xhYmVsPjwvc3Bhbj48c3Bhbj48aW5wdXQgbmFtZT1cInl0bWFfX3F1YWxpdHlcIiBkYXRhLWtleT1cInF1YWxpdHlcIiBkYXRhLW51bT1cIjEwODBcIiBpZD1cInl0bWFfX3F1YWxpdHkxMDgwXCIgdHlwZT1cInJhZGlvXCI+PGxhYmVsIGZvcj1cInl0bWFfX3F1YWxpdHkxMDgwXCI+MTA4MHA8L2xhYmVsPjwvc3Bhbj48L3A+PC9maWVsZHNldD5cblx0XHRcdFx0XHRcdFx0XHQ8ZmllbGRzZXQ+PGxlZ2VuZD5Bc3BlY3QgUmF0aW88L2xlZ2VuZD48cD48c3Bhbj48aW5wdXQgbmFtZT1cInl0bWFfX3JhdGlvXCIgZGF0YS1rZXk9XCJyYXRpb1wiIHR5cGU9XCJyYWRpb1wiIGlkPVwieXRtYV9fcmF0aW8yXCIgZGF0YS1udW09XCIyXCIgLz48bGFiZWwgZm9yPVwieXRtYV9fcmF0aW8yXCI+MTY6OTwvbGFiZWw+PC9zcGFuPjxzcGFuPjxpbnB1dCB0eXBlPVwicmFkaW9cIiBuYW1lPVwieXRtYV9fcmF0aW9cIiBkYXRhLWtleT1cInJhdGlvXCIgZGF0YS1udW09XCIxXCIgaWQ9XCJ5dG1hX19yYXRpbzFcIiAvPjxsYWJlbCBmb3I9XCJ5dG1hX19yYXRpbzFcIj40OjM8L2xhYmVsPjwvc3Bhbj48L3A+PC9maWVsZHNldD5cblx0XHRcdFx0XHRcdFx0XHQ8ZmllbGRzZXQ+PGxlZ2VuZD5Zb3VUdWJlPC9sZWdlbmQ+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8cD48aW5wdXQgbmFtZT1cInl0bWFfX3l0X2Fubm90YXRpb25cIiBkYXRhLWtleT1cInl0X2Fubm90YXRpb25cIiB0eXBlPVwiY2hlY2tib3hcIiBpZD1cInl0bWFfX3l0X2Fubm90YXRpb25cIiAvPjxsYWJlbCBmb3I9XCJ5dG1hX195dF9hbm5vdGF0aW9uXCI+RW5hYmxlIHZpZGVvIGFubm90YXRpb25zPC9sYWJlbD48L3A+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8cD48aW5wdXQgbmFtZT1cInl0bWFfX3l0X25vY29va2llXCIgZGF0YS1rZXk9XCJ5dF9ub2Nvb2tpZVwiIHR5cGU9XCJjaGVja2JveFwiIGlkPVwieXRtYV9feXRfbm9jb29raWVcIiAvPjxsYWJlbCBmb3I9XCJ5dG1hX195dF9ub2Nvb2tpZVwiPlVzZSBodHRwczovL3lvdXR1YmUtbm9jb29raWUuY29tIHRvIGxvYWQgdmlkZW9zPC9sYWJlbD48L3A+XG5cdFx0XHRcdFx0XHRcdFx0PC9maWVsZHNldD5cblx0XHRcdFx0XHRcdFx0XHQ8ZmllbGRzZXQ+PGxlZ2VuZD5XaW5kb3cgRm9jdXM8L2xlZ2VuZD48cD48aW5wdXQgbmFtZT1cInl0bWFfX2ZvY3VzXCIgZGF0YS1rZXk9XCJmb2N1c1wiIHR5cGU9XCJjaGVja2JveFwiIGlkPVwieXRtYV9fZm9jdXNcIiB2YWx1ZT1cImZvY3VzXCIgLz48bGFiZWwgZm9yPVwieXRtYV9fZm9jdXNcIj5BZnRlciBjbGlja2luZyB0aGUgdGh1bWJuYWlsLCBzZXQgdGhlIHZpZGVvIGF0IHRoZSB0b3Agb2YgdGhlIHdpbmRvdy48L2xhYmVsPjwvcD48L2ZpZWxkc2V0PlxuXHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0PHA+PHNtYWxsIGlkPVwieXRtX3NldHRpbmdzX2Vycm9yXCIgY2xhc3M9XCJ5dG1fZXJyb3IgeXRtX25vbmUgeXRtX3RpdGxlXCI+RXJyb3IhIFlvdXIgc2V0dGluZ3MgY291bGQgbm90IGJlIHNhdmVkLjwvc21hbGw+PC9wPlxuXHRcdFx0XHRcdFx0XHQ8cCBpZD1cInl0bV9vcHRzXCI+XG5cdFx0XHRcdFx0XHRcdFx0PGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgaWQ9XCJ5dG1hY2xvc2VcIj5DbG9zZTwvYnV0dG9uPiA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBpZD1cInl0bWFyZXNldFwiPlJlc2V0PC9idXR0b24+IDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGlkPVwieXRtYWNsZWFyXCIgdGl0bGU9XCJSZW1vdmUgYWxsIHZpZGVvIGRlc2NyaXB0aW9ucyB0aGF0IGhhdmUgYmVlbiBjYWNoZWRcIj5SZXNldCAmIFJlbW92ZSBDYWNoZTwvYnV0dG9uPlxuXHRcdFx0XHRcdFx0XHQ8L3A+XG5cdFx0XHRcdFx0XHQ8L2Zvcm0+XG5cdFx0XHRcdFx0PC9kaXY+YDtcblxuXHRcdFx0XHRZLnVzZXIuJGZvcm0gPSBfLmUoJ2RpdicsIHsgY2xhc3NOYW1lOiAneXRtX2ZpeF9jZW50ZXIgeXRtX25vbmUgeXRtX2JveCcsIGlubmVySFRNTDogdGVtcGxhdGUgfSwgZG9jdW1lbnQuYm9keSk7XG5cdFx0XHRcdFkudXNlci5lcnJvciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd5dG1fc2V0dGluZ3NfZXJyb3InKTtcblxuXHRcdFx0XHRvbihZLnVzZXIuJGZvcm0sICdrZXl1cCBjbGljaycsICdpbnB1dCwgbGFiZWwnLCBkZWJvdW5jZShZLnVzZXIuZXZlbnRzLnNhdmUsIDUwMCkpO1xuXHRcdFx0XHRZLnVzZXIuJGZvcm0uYWRkRXZlbnRMaXN0ZW5lcignc3VibWl0JywgZSA9PiBlLnByZXZlbnREZWZhdWx0KCksIGZhbHNlKTtcblxuXHRcdFx0XHRkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgneXRtYXJlc2V0JykuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBZLnVzZXIuZXZlbnRzLnJlc2V0LCBmYWxzZSk7XG5cdFx0XHRcdGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd5dG1hY2xlYXInKS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIFkudXNlci5ldmVudHMuY2xlYXIsIGZhbHNlKTtcblxuXHRcdFx0XHQvLyBjbG9zZVxuXHRcdFx0XHRZLnVzZXIuJGZvcm0uYWRkRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBZLnVzZXIuZXZlbnRzLmZvcm1Ub2dnbGUsIGZhbHNlKTtcblx0XHRcdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3l0bWFjbG9zZScpLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgWS51c2VyLmV2ZW50cy5mb3JtVG9nZ2xlLCBmYWxzZSk7XG5cdFx0XHRcdGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIFkudXNlci5ldmVudHMuZm9ybVRvZ2dsZUtleWJvYXJkLCBmYWxzZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdFkuY3NzID0gKCkgPT4ge1xuXHRcdGNvbnN0IHBsYXllckNzcyA9IFBsYXllci5jc3MuZ2VuZXJhdG9yKCk7XG5cdFx0Y29uc3QgbG9hZGluZ0ljb24gPSAnZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoRGdBS0FKRUFBUC8vLytCS1YvLy8vd0FBQUNIL0MwNUZWRk5EUVZCRk1pNHdBd0VBQUFBaCtRUUZDZ0FDQUN3QUFBQUFEZ0FLQUFBQ0hGU09lUVlJNzFwNk10QUp6NDExNjJ5QkgrZG81SWgxa0tHMFFnRUFJZmtFQlFvQUFnQXNBQUFCQUEwQUNBQUFBaFNVWUdFb2Vya2dkSXpLR2x1MkVULzljZUptRkFBaCtRUUZDZ0FDQUN3QUFBRUFEUUFJQUFBQ0ZKUmhjYm1pZ2x4NzhTWEtZSzZ6YStOeEh5WVZBQ0g1QkFVS0FBSUFMQUFBQVFBTkFBZ0FBQUlXVkNTQWwraHFFR1JUTGh0YmR2VHFubFVmOW5oVEFRQWgrUVFGQ2dBQ0FDd0FBQUVBRFFBSUFBQUNGWlJpWUNoNnVhQ1J6TlhZc0tWVCs1ZUJXM2dKQlFBaCtRUUpDZ0FDQUN3QUFBQUFEZ0FLQUFBQ0dwU1BhV0d3Zlpod1F0SUs4VlRVdnV4cG05WXA0WGxtcGlJVUFEcz0nO1xuXG5cdFx0Ly8gY29uc29sZS5sb2cocGxheWVyQ3NzKTtcblx0XHRfLmNzcyhwbGF5ZXJDc3MpO1xuXG5cdFx0Ly8gaW1hZ2VzXG5cdFx0Ly8gdG9kbyB1cGRhdGUoc2l0ZSwgc2l6ZSwgcGFkZGluZylcblx0XHRfLmNzcyhgXG5cdFx0XHQueXRtX2xvYWRpbmd7YmFja2dyb3VuZDp1cmwoJHtsb2FkaW5nSWNvbn0pIDAgM3B4IG5vLXJlcGVhdDt9XG5cdFx0XHQueXRtX2xpbmt7cG9zaXRpb246cmVsYXRpdmUgIWltcG9ydGFudDtiYWNrZ3JvdW5kOnVybCgke1kuREIuc2l0ZXMueW91dHViZS5mYXZpY29ufSkgMCBjZW50ZXIgbm8tcmVwZWF0ICFpbXBvcnRhbnQ7bWFyZ2luLWxlZnQ6NHB4O3BhZGRpbmctbGVmdDoyMHB4IWltcG9ydGFudDt9XG5cdFx0XHQueXRtX2xpbmsueXRtX2xpbmtfdmltZW97YmFja2dyb3VuZC1pbWFnZTp1cmwoJHtZLkRCLnNpdGVzLnZpbWVvLmZhdmljb259KSAhaW1wb3J0YW50O2JhY2tncm91bmQtc2l6ZToxMnB4IDEycHggIWltcG9ydGFudDtwYWRkaW5nLWxlZnQ6MThweCFpbXBvcnRhbnR9XG5cdFx0XHQueXRtX2xpbmsueXRtX2xpbmtfdmluZXtiYWNrZ3JvdW5kLWltYWdlOnVybCgke1kuREIuc2l0ZXMudmluZS5mYXZpY29ufSkgIWltcG9ydGFudDtiYWNrZ3JvdW5kLXNpemU6MTBweCAxMHB4IWltcG9ydGFudDtwYWRkaW5nLWxlZnQ6MTZweCFpbXBvcnRhbnR9XG5cdFx0XHQueXRtX2xpbmsueXRtX2xpbmtfc291bmRjbG91ZHtiYWNrZ3JvdW5kLWltYWdlOnVybCgke1kuREIuc2l0ZXMuc291bmRjbG91ZC5mYXZpY29ufSkhaW1wb3J0YW50O3BhZGRpbmctbGVmdDoxN3B4IWltcG9ydGFudH1cblx0XHRcdC55dG1fbGluay55dG1fbGlua19odG1sNXtiYWNrZ3JvdW5kLWltYWdlOnVybCgke1kuREIuc2l0ZXMuaHRtbDUuZmF2aWNvbn0pICFpbXBvcnRhbnQ7cGFkZGluZy1sZWZ0OjE2cHghaW1wb3J0YW50fVxuXHRcdFx0Lnl0bV9saW5rLnl0bV9saW5rX2dmeWNhdHtiYWNrZ3JvdW5kLWltYWdlOnVybCgke1kuREIuc2l0ZXMuZ2Z5Y2F0LmZhdmljb259KSAhaW1wb3J0YW50O2JhY2tncm91bmQtc2l6ZToxMnB4IDEycHggIWltcG9ydGFudDtwYWRkaW5nLWxlZnQ6MTZweCFpbXBvcnRhbnQ7fVxuXHRcdFx0Lnl0bV9saW5rLnl0bV9saW5rX2ltZ3Vye2JhY2tncm91bmQtaW1hZ2U6dXJsKCR7WS5EQi5zaXRlcy5pbWd1ci5mYXZpY29ufSkgIWltcG9ydGFudDtiYWNrZ3JvdW5kLXNpemU6MTJweCAxMnB4ICFpbXBvcnRhbnQ7cGFkZGluZy1sZWZ0OjE2cHghaW1wb3J0YW50fVxuXHRcdFx0Lnl0bV9saW5rLnl0bV9saW5rX3N0cmVhbWFibGV7YmFja2dyb3VuZC1pbWFnZTp1cmwoJHtZLkRCLnNpdGVzLnN0cmVhbWFibGUuZmF2aWNvbn0pICFpbXBvcnRhbnQ7IGJhY2tncm91bmQtc2l6ZTogMTJweCAxMnB4ICFpbXBvcnRhbnQ7cGFkZGluZy1sZWZ0OiAxNHB4ICFpbXBvcnRhbnQ7fVxuXHRcdGApO1xuXG5cdFx0Xy5jc3MoJy55dG1fbm9uZSwueXRtX2xpbmsgYnJ7ZGlzcGxheTpub25lIWltcG9ydGFudH0ueXRtX2JveHstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3h9Lnl0bV9ibG9ja3tkaXNwbGF5OmJsb2NrO3Bvc2l0aW9uOnJlbGF0aXZlO2NsZWFyOmJvdGg7dGV4dC1hbGlnbjpsZWZ0O2JvcmRlcjowO21hcmdpbjowO3BhZGRpbmc6MDtvdmVyZmxvdzpoaWRkZW59Lnl0bV9ub3JtYWxpemV7Zm9udC13ZWlnaHQ6NDAwIWltcG9ydGFudDtmb250LXN0eWxlOm5vcm1hbCFpbXBvcnRhbnQ7bGluZS1oZWlnaHQ6MS4yIWltcG9ydGFudH0ueXRtX3NhbnN7Zm9udC1mYW1pbHk6QXJpYWwsSGVsdmV0aWNhLHNhbnMtc2VyaWYhaW1wb3J0YW50fS55dG1fc3BhY2Vye292ZXJmbG93OmF1dG87bWFyZ2luOjAgMCA2cHg7cGFkZGluZzo0cHh9Lnl0bV9zcGFjZXIueXRtX3NpdGVfc2xpbXtkaXNwbGF5OmlubGluZX0ueXRtX2NsZWFyOmFmdGVye2NvbnRlbnQ6XCJcIjtkaXNwbGF5OnRhYmxlO2NsZWFyOmJvdGh9Lnl0bV9jZW50ZXJ7dGV4dC1hbGlnbjpjZW50ZXJ9Lnl0bV9saW5rIGIsLnl0bV9saW5rIHN0cm9uZ3tmb250LXdlaWdodDo0MDAhaW1wb3J0YW50fS55dG1fbGluayB1e3RleHQtZGVjb3JhdGlvbjpub25lIWltcG9ydGFudH0ueXRtX2xpbmsgaSwueXRtX2xpbmsgZW17Zm9udC1zdHlsZTpub3JtYWwhaW1wb3J0YW50fS55dG1fdHJpZ2dlcnt3aWR0aDoxMThweDtoZWlnaHQ6NjZweDtiYWNrZ3JvdW5kLWNvbG9yOiMyNjI2MjYhaW1wb3J0YW50O2N1cnNvcjpwb2ludGVyO2JhY2tncm91bmQtcG9zaXRpb246LTFweCAtMTJweDtmbG9hdDpsZWZ0O2JveC1zaGFkb3c6MnB4IDJweCByZ2JhKDAsMCwwLC4zKTtiYWNrZ3JvdW5kLXNpemU6YXV0byA5MHB4IWltcG9ydGFudDtjb2xvcjojZmZmO3RleHQtc2hhZG93OiMzMzMgMCAwIDJweDtmb250LXNpemU6MTNweH0ueXRtX3RyaWdnZXI6aG92ZXJ7Ym94LXNoYWRvdzoycHggMnB4ICM2MDY1NmI4MDtvcGFjaXR5Oi45NX0ueXRtX3RyaWdnZXIgdmFye3otaW5kZXg6MjtoZWlnaHQ6MTAwJTt3aWR0aDoxMDAlO3Bvc2l0aW9uOmFic29sdXRlO2xlZnQ6MDt0b3A6MDt0ZXh0LWFsaWduOnJpZ2h0fS55dG1fbGFiZWx7ZGlzcGxheTpibG9jaztwYWRkaW5nOjNweCA2cHg7bGluZS1oZWlnaHQ6MS4yO2ZvbnQtc3R5bGU6bm9ybWFsfS55dG1faW5pdHtoZWlnaHQ6MjJweDtiYWNrZ3JvdW5kOnJnYmEoMTEsMTEsMTEsLjYyKTtwYWRkaW5nOjRweCAyNXB4IDZweCA2cHh9Lnl0bV9zaXRlX3ZpbmUgLnl0bV90cmlnZ2Vye2JhY2tncm91bmQtY29sb3I6IzkwZWU5MCFpbXBvcnRhbnQ7YmFja2dyb3VuZC1zaXplOjEyMHB4IGF1dG8haW1wb3J0YW50fS55dG1fc2l0ZV9zbGltIC55dG1fdHJpZ2dlcntiYWNrZ3JvdW5kOiNlMzRjMjYhaW1wb3J0YW50O2hlaWdodDphdXRvO2JveC1zaGFkb3c6MCAwIDJweCAjZmZkYjlkIGluc2V0LDJweCAycHggcmdiYSgwLDAsMCwuMyk7bWFyZ2luOjAgM3B4IDAgMDt3aWR0aDphdXRvO3RyYW5zaXRpb246YWxsIC4zcyBlYXNlLWluLW91dCAwc30ueXRtX3NpdGVfc2xpbSAueXRtX3RyaWdnZXI6aG92ZXJ7b3BhY2l0eTouOH0ueXRtX3NpdGVfc2xpbSAueXRtX2xhYmVse3RleHQtc2hhZG93OjAgMCAxcHggI2YwNjUyOX0ueXRtX3NpdGVfc2xpbSAueXRtX2luaXR7YmFja2dyb3VuZDp0cmFuc3BhcmVudH0ueXRtX2Jke2Zsb2F0OmxlZnQ7bWF4LXdpZHRoOjQ1MHB4O21hcmdpbjoycHggMTBweDtmb250LXNpemU6MTJweH0ueXRtX3RpdGxle2ZvbnQtd2VpZ2h0OjcwMH0ueXRtX2Vycm9ye2NvbG9yOiNjYzJmMjQ7Zm9udC1zdHlsZTppdGFsaWN9Lnl0bV9sb2FkaW5ne2ZvbnQtc3R5bGU6aXRhbGljO3BhZGRpbmc6MXB4IDEuNWVtfS55dG1fZGVzY3J7d29yZC13cmFwOmJyZWFrLXdvcmQ7bWF4LWhlaWdodDo0OHB4O292ZXJmbG93OmF1dG87cGFkZGluZy1yaWdodDoyMHB4fS55dG1fZGVzY3JbZGF0YS1mdWxsXXtjdXJzb3I6cG9pbnRlcn0ueXRtX2Rlc2NyX29wZW57cmVzaXplOmJvdGg7d2hpdGUtc3BhY2U6cHJlLWxpbmU7YmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQodG8gYm90dG9tLCByZ2JhKDAsMCwwLDApIDAlLHJnYmEoMCwwLDAsMCkgNTAlLHJnYmEoMCwwLDAsMCkgODAlLHJnYmEoMCwwLDAsMC4xKSAxMDAlKX0ueXRtX2Rlc2NyX29wZW5bc3R5bGVde21heC1oZWlnaHQ6bm9uZX0ueXRtX3Byb2plY3RvcnttYXJnaW4tYm90dG9tOjRweH11bC55dG1fb3B0aW9uc3tvdmVyZmxvdzpoaWRkZW47bWFyZ2luOjAhaW1wb3J0YW50O3BhZGRpbmc6M3B4IDAgMXB4O2xpc3Qtc3R5bGUtcG9zaXRpb246b3V0c2lkZSFpbXBvcnRhbnR9Lnl0bV9vcHRpb25zIGxpe2Rpc3BsYXk6aW5saW5lO21hcmdpbjowIWltcG9ydGFudDtwYWRkaW5nOjAhaW1wb3J0YW50fS55dG1fb3B0aW9ucyBsaT51bHtkaXNwbGF5OmlubGluZS1ibG9jazttYXJnaW46MDtwYWRkaW5nOjAgMXB4IDAgMH0ueXRtX29wdGlvbnMgbGkgdWwgbGl7LXdlYmtpdC11c2VyLXNlbGVjdDpub25lOy1tb3otdXNlci1zZWxlY3Q6bm9uZTstby11c2VyLXNlbGVjdDpub25lO3VzZXItc2VsZWN0Om5vbmU7bGlzdC1zdHlsZS10eXBlOm5vbmU7Y3Vyc29yOnBvaW50ZXI7ZmxvYXQ6bGVmdDtjb2xvcjojODU4NTg1O2JvcmRlcjoxcHggc29saWQgIzFkMWQxZDtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMTgxODE4O2JvcmRlci10b3A6MXB4IHNvbGlkICMyOTI5Mjk7Ym94LXNoYWRvdzowIDAgMXB4ICM1NTU7aGVpZ2h0OjE0cHg7Zm9udC1zaXplOjEycHghaW1wb3J0YW50O2xpbmUtaGVpZ2h0OjEycHghaW1wb3J0YW50O2JhY2tncm91bmQ6IzIyMjtiYWNrZ3JvdW5kOmxpbmVhci1ncmFkaWVudCgjMmQyYzJjLCMyMjIpO21hcmdpbjowIWltcG9ydGFudDtwYWRkaW5nOjVweCA5cHggM3B4IWltcG9ydGFudH0ueXRtX29wdGlvbnMgbGkgdWwgbGk6Zmlyc3QtY2hpbGR7Ym9yZGVyLXJhZGl1czoycHggMCAwIDJweH0ueXRtX29wdGlvbnMgbGkgdWwgbGk6bGFzdC1jaGlsZHtib3JkZXItbGVmdDowIWltcG9ydGFudDtib3JkZXItcmFkaXVzOjAgMnB4IDJweCAwO21hcmdpbjowIDJweCAwIDAhaW1wb3J0YW50fS55dG1fb3B0aW9ucyBsaSB1bCBsaTpmaXJzdC1jaGlsZDpsYXN0LWNoaWxkLC55dG1fbGlfc2V0dGluZ3tib3JkZXItcmFkaXVzOjJweH0ueXRtX29wdGlvbnMgbGkgdWwgbGk6aG92ZXJ7Y29sb3I6I2NjYzt0ZXh0LXNoYWRvdzoxcHggMXB4IDAgIzMzMztiYWNrZ3JvdW5kOiMxODE4MTh9Lnl0bV9vcHRpb25zIGxpIHVsIGxpW2lkXXtjb2xvcjojZGRkO3RleHQtc2hhZG93OjAgMCAycHggIzQ0NH0ueXRtX3BhbmVsX3NpemV7YmFja2dyb3VuZDojMDAwO21heC13aWR0aDoxMDAlO30ueXRtX3BhbmVsX3N3aXRjaGVyW2RhdGEtc3RhbmRieT1cInRydWVcIl17YmFja2dyb3VuZDojMTExfS55dG1fcGFuZWxfc3dpdGNoZXJbZGF0YS1zdGFuZGJ5PVwidHJ1ZVwiXTphZnRlcntjdXJzb3I6Y2VsbDtjb2xvcjojMGUwZTBlO2NvbnRlbnQ6XCJ5dG1hIVwiO2Rpc3BsYXk6YmxvY2s7Zm9udC1zaXplOjg1cHg7Zm9udC1zdHlsZTppdGFsaWM7Zm9udC13ZWlnaHQ6NzAwO2xlZnQ6NTAlO3Bvc2l0aW9uOmFic29sdXRlO3RleHQtc2hhZG93OjJweCAxcHggIzE4MTgxOCwtMXB4IC0xcHggIzBhMGEwYTt0b3A6NTAlO3RyYW5zZm9ybTp0cmFuc2xhdGUoLTUwJSwtNTAlKX0ueXRtX3NpdGVfc291bmRjbG91ZCAueXRtX3BhbmVsX3NpemUueXRtX3NvdW5kY2xvdWQtcGxheWxpc3R7aGVpZ2h0OjMzNHB4IWltcG9ydGFudH0ueXRtX2ZpeF9jZW50ZXJ7YmFja2dyb3VuZDpyZ2JhKDUxLDUxLDUxLC40MSk7aGVpZ2h0OjEwMCU7bGVmdDowO3Bvc2l0aW9uOmZpeGVkO3RvcDowO3dpZHRoOjEwMCU7ei1pbmRleDo5OTk5OH0jeXRtX3NldHRpbmdze3otaW5kZXg6OTk5OTk7bWF4LXdpZHRoOjUwMHB4O21heC1oZWlnaHQ6ODUlO292ZXJmbG93OmF1dG87YmFja2dyb3VuZDojZmJmYmZiO2JvcmRlcjoxcHggc29saWQgI2JiYjtjb2xvcjojNDQ0O2JveC1zaGFkb3c6MCAwIDVweCByZ2JhKDAsMCwwLC4yKSwwIDAgM3B4IHJnYmEoMjM5LDIzOSwyMzksLjEpIGluc2V0O21hcmdpbjo0JSBhdXRvO3BhZGRpbmc6NHB4IDhweCAwfSN5dG1fc2V0dGluZ3MgcHttYXJnaW46NXB4IDA7cGFkZGluZzowfSN5dG1fc2V0dGluZ3MgZmllbGRzZXR7dmVydGljYWwtYWxpZ246dG9wO2JvcmRlci1yYWRpdXM6M3B4O2JvcmRlcjoxcHggc29saWQgI2NjYzttYXJnaW46MCAwIDVweDtwYWRkaW5nOjNweH0jeXRtX3NldHRpbmdzIGxlZ2VuZHtwYWRkaW5nOjNweH0jeXRtX3NldHRpbmdzIGZpZWxkc2V0IHNwYW57ZGlzcGxheTppbmxpbmUtYmxvY2s7bWluLXdpZHRoOjVlbX0jeXRtX3NldHRpbmdzIGlucHV0e3ZlcnRpY2FsLWFsaWduOmJhc2VsaW5lIWltcG9ydGFudDttYXJnaW46M3B4IDVweCFpbXBvcnRhbnR9I3l0bV9zZXR0aW5nc3R7Zm9udC1zaXplOjExMCU7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgI2QwMDttYXJnaW46M3B4IDAgOXB4O3BhZGRpbmc6MCAzcHggM3B4fSN5dG1fc2V0dGluZ3MgbGFiZWx7Y3Vyc29yOnBvaW50ZXJ9I3l0bV9zZXR0aW5ncyBzbWFsbHtmb250LXNpemU6OTAlfSN5dG1fb3B0cyBidXR0b257Y3Vyc29yOnBvaW50ZXI7bWFyZ2luOjEwcHggNXB4IDhweCAycHg7cGFkZGluZzozcHg7Ym9yZGVyOjFweCBzb2xpZCAjYWRhZGFkO2JvcmRlci1yYWRpdXM6MnB4O2JhY2tncm91bmQ6I2VlZTtmb250LXNpemU6OTAlfSN5dG1fb3B0cyBidXR0b246aG92ZXJ7YmFja2dyb3VuZDojZGRkfScpO1xuXHR9O1xuXG5cdFkuYWpheCA9IHtcblx0XHRsb2FkOiBmdW5jdGlvbiAoc2l0ZSwgaWQsIHVyaSkge1xuXHRcdFx0Y29uc29sZS5pbmZvKCd5dG1hLy9hamF4K2xvYWQoaWQpJywgc2l0ZSwgaWQsIHVyaSk7XG5cdFx0XHR1cmkgPSBZLkRCLnNpdGVzW3NpdGVdLmFqYXgucmVwbGFjZSgnJWtleScsIGlkKS5yZXBsYWNlKCcldXJpJywgdXJpKTtcblxuXHRcdFx0aWYgKFkuREIuc2l0ZXNbc2l0ZV0uYWpheEV4dGVuc2lvbikgeyByZXR1cm4gdGhpcy5nbXhocih1cmksIHNpdGUsIGlkKTsgfVxuXG5cdFx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL2FqYXgrbG9hZCh1cmkpJywgWS5EQi5zaXRlc1tzaXRlXS5hamF4LnJlcGxhY2UoJyVrZXknLCBpZCkucmVwbGFjZSgnJXVyaScsIHVyaSkpO1xuXHRcdFx0aWYgKFkuREIuc2l0ZXNbc2l0ZV0uYWpheCkge1xuXHRcdFx0XHQvLyBjb25zb2xlLmxvZygncHJlcGluZyB1cmknKTtcblx0XHRcdFx0cmV0dXJuIHRoaXMueGhyKHVyaSwgc2l0ZSwgaWQpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9LFxuXHRcdGxvYWRGcm9tRGF0YXNldDogZnVuY3Rpb24gKGRhdGFzZXQpIHtcblx0XHRcdGlmICghdGhpcy5sb2FkRnJvbUNhY2hlRGF0YXNldChkYXRhc2V0KSkge1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5sb2FkKGRhdGFzZXQueXRtc2l0ZSwgZGF0YXNldC55dG1pZCwgZGF0YXNldC55dG11cmkpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0bG9hZEZyb21DYWNoZURhdGFzZXQ6IGZ1bmN0aW9uICh7IHl0bXNpdGUsIHl0bWlkIH0pIHtcblx0XHRcdGNvbnN0IGNhY2hlID0gWS5leHRlcm5hbC5kYXRhRnJvbVN0b3JhZ2UoeXRtc2l0ZSwgeXRtaWQpO1xuXG5cdFx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL2FqYXgrY2FjaGUoaWQpJywgeXRtc2l0ZSwgeXRtaWQpO1xuXHRcdFx0Y29uc29sZS5pbmZvKCd5dG1hLy9hamF4K2NhY2hlKGRhdGEpJywgY2FjaGUpO1xuXG5cdFx0XHRpZiAoY2FjaGUpIHsgWS5leHRlcm5hbC5wb3B1bGF0ZShjYWNoZSk7IH1cblxuXHRcdFx0cmV0dXJuIGNhY2hlO1xuXHRcdH0sXG5cdFx0Z214aHI6IGZ1bmN0aW9uICh1cmksIHNpdGUsIGlkKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHQvLyBjb25zb2xlLmxvZygnZ214aHIgc3RhcnRpbmchJyk7XG5cdFx0XHRcdEdNLnhtbGh0dHBSZXF1ZXN0KHtcblx0XHRcdFx0XHRtZXRob2Q6ICdHRVQnLFxuXHRcdFx0XHRcdHVybDogdXJpLFxuXHRcdFx0XHRcdG9ubG9hZDogZnVuY3Rpb24gKHsgcmVzcG9uc2VUZXh0IH0pIHtcblx0XHRcdFx0XHRcdC8vIGNvbnNvbGUubG9nKHJlc3BvbnNlKTtcblx0XHRcdFx0XHRcdFkuZXh0ZXJuYWwucGFyc2UocmVzcG9uc2VUZXh0LCBzaXRlLCBpZCk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRvbmVycm9yOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRjb25zb2xlLmxvZygnR00gQ2Fubm90IFhIUicpO1xuXHRcdFx0XHRcdFx0WS5hamF4LmZhaWx1cmUuY2FsbCh7IGlkIH0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0WS5hamF4LnByZVByb2Nlc3MoaWQpO1xuXG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGlmIChZLkRCLmV4dGVuc2lvbikge1xuXHRcdFx0XHRcdGNvbnNvbGUuaW5mbygneXRtYS8vZ214aHItY29ycycpO1xuXHRcdFx0XHRcdHRoaXMueGhyKHVyaSwgc2l0ZSwgaWQpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnNvbGUubG9nKCdObyBhcHBsaWNhYmxlIENPUlMgcmVxdWVzdCBhdmFpbGFibGUuJyk7XG5cdFx0XHRcdFx0dGhpcy5mYWlsdXJlLmNhbGwoeyBpZCB9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0eGhyOiBmdW5jdGlvbiAodXJpLCBzaXRlLCBpZCkge1xuXHRcdFx0Y29uc3QgeCA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuXHRcdFx0Y29uc29sZS5pbmZvKCd5dG1hLy94aHInLCB1cmksIGlkLCBzaXRlKTtcblxuXHRcdFx0WS5hamF4LnByZVByb2Nlc3MoaWQpO1xuXG5cdFx0XHR4Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0aWYgKHRoaXMucmVhZHlTdGF0ZSA9PT0gdGhpcy5ET05FKSB7XG5cdFx0XHRcdFx0Ly8gY29uc29sZS5sb2codGhpcy5yZWFkeVN0YXRlLCB0aGlzLnN0YXR1cyk7XG5cdFx0XHRcdFx0aWYgKHRoaXMuc3RhdHVzID09PSAyMDApIHtcblx0XHRcdFx0XHRcdFkuZXh0ZXJuYWwucGFyc2UodGhpcy5yZXNwb25zZVRleHQsIHNpdGUsIGlkKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKHRoaXMuc3RhdHVzID09PSA0MDMpIHtcblx0XHRcdFx0XHRcdFkuZXh0ZXJuYWwucG9wdWxhdGUoeyBzaXRlLCBpZCwgdGl0bGU6ICdFcnJvciA0MDMnLCBkZXNjOiAnJyB9KTtcblx0XHRcdFx0XHRcdFkuZXh0ZXJuYWwuc2F2ZSh7IHNpdGUsIGlkLCB0aXRsZTogJ0Vycm9yIDQwMycsIGRlc2M6ICcnIH0pO1xuXHRcdFx0XHRcdH0gZWxzZSB7IC8vIGlmICh0aGlzLnN0YXR1cyA+PSA0MDAgfHwgdGhpcy5zdGF0dXMgPT09IDApIHtcblx0XHRcdFx0XHRcdFkuYWpheC5mYWlsdXJlLmNhbGwoeyBpZCB9KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdC8vIGNvbnNvbGUuaW5mbygneXRtYS8veGhyK3NlbmRpbmcnKTtcblx0XHRcdFx0eC5vcGVuKCdnZXQnLCB1cmksIHRydWUpO1xuXHRcdFx0XHR4LnNlbmQoKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcigneXRtYS8veGhyK2ZhaWxlZChjYW5ub3Qgc2VuZCB4aHIpJywgdXJpKTtcblx0XHRcdFx0WS5hamF4LmZhaWx1cmUuY2FsbCh7IGlkIH0pO1xuXHRcdFx0XHRjb25zb2xlLmVycm9yKGUpO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0ZmFpbHVyZTogZnVuY3Rpb24gKCkge1xuXHRcdFx0Xy5zKGAueXRtX2JkLl8ke1kuZXNjYXBlSWQodGhpcy5pZCl9YCwgZWwgPT4ge1xuXHRcdFx0XHRjb25zdCBhID0gZWwucXVlcnlTZWxlY3RvcignYScpO1xuXHRcdFx0XHRhLmRhdGFzZXQudHJpZXMgPSBhLmRhdGFzZXQudHJpZXMgPyBwYXJzZUZsb2F0KGEuZGF0YXNldC50cmllcykgKyAxIDogMTtcblx0XHRcdFx0aWYgKGEuZGF0YXNldC50cmllcyA+PSA1KSB7XG5cdFx0XHRcdFx0YS50ZXh0Q29udGVudCA9ICdNYXggYXR0ZW1wdHMgcmVhY2hlZCc7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0YS50ZXh0Q29udGVudCA9IGBFcnJvciwgdW5hYmxlIHRvIGxvYWQgZGF0YS4ke2EuZGF0YXNldC50cmllcyA+IDEgPyAnJyA6ICcgW1JldHJ5XSd9YDtcblx0XHRcdFx0fVxuXHRcdFx0XHRhLmNsYXNzTmFtZSA9ICd5dG1fZXJyb3IgeXRtX3RpdGxlJztcblx0XHRcdH0pO1xuXHRcdH0sXG5cdFx0cHJlUHJvY2VzczogZnVuY3Rpb24gKGlkKSB7XG5cdFx0XHRfLnMoYC55dG1fbWFudWFsLl8ke1kuZXNjYXBlSWQoaWQpfSBhYCwgZWwgPT4ge1xuXHRcdFx0XHRlbC5jbGFzc0xpc3QuYWRkKCd5dG1fbG9hZGluZycpO1xuXHRcdFx0XHRlbC50ZXh0Q29udGVudCA9ICdMb2FkaW5nJztcblx0XHRcdFx0ZWwudGl0bGUgPSAnUmV0cnkgbG9hZGluZyBkYXRhLic7XG5cdFx0XHR9KTtcblx0XHR9XG5cdH07XG5cblx0LyoqIEUgWCBUIEUgUiBOIEEgTCBBcHBhcmF0dXNcblx0ICogRGF0YSBmcm9tIGV4dGVybmFsIHNpdGVzXG5cdCAqL1xuXHRZLmV4dGVybmFsID0ge1xuXHRcdHZlcnNpb246ICd5dG1hLjQuMS5kYXQnLFxuXHRcdHBhcnNlOiBmdW5jdGlvbiAocmVzcG9uc2UsIHNpdGUsIGlkKSB7XG5cdFx0XHRpZiAodGhpcy5wYXJzZXJzW3NpdGVdKSB7XG5cdFx0XHRcdHJlc3BvbnNlID0gWS5EQi5zaXRlc1tzaXRlXS5yYXdSZXNwb25zZSA/IHJlc3BvbnNlIDogSlNPTi5wYXJzZShyZXNwb25zZSk7XG5cdFx0XHRcdHRoaXMucG9wdWxhdGUodGhpcy5oZWxwZXIuY3V0RGVzY3JpcHRpb24odGhpcy5wYXJzZXJzW3NpdGVdKHJlc3BvbnNlLCBpZCkpKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdHBhcnNlcnM6IHtcblx0XHRcdHNvdW5kY2xvdWQ6IGZ1bmN0aW9uICh7IHRpdGxlLCBkZXNjcmlwdGlvbiwgdGh1bWJuYWlsX3VybCB9LCBpZCkge1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdHNpdGU6ICdzb3VuZGNsb3VkJyxcblx0XHRcdFx0XHRpZCwgLy91bmVzY2FwZShqLmh0bWwpLm1hdGNoKC90cmFja3NcXC8oXFxkKykvKVsxXSxcblx0XHRcdFx0XHR0aXRsZSxcblx0XHRcdFx0XHRkZXNjOiBkZXNjcmlwdGlvbixcblx0XHRcdFx0XHR0aDogcmVtb3ZlU2VhcmNoKHRodW1ibmFpbF91cmwpXG5cdFx0XHRcdH07XG5cdFx0XHR9LFxuXHRcdFx0dmltZW86IGZ1bmN0aW9uIChqKSB7XG5cdFx0XHRcdGogPSBqWzBdO1xuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdHNpdGU6ICd2aW1lbycsXG5cdFx0XHRcdFx0aWQ6IGouaWQsXG5cdFx0XHRcdFx0dGl0bGU6IGAke2oudGl0bGV9ICR7WS5leHRlcm5hbC50aW1lLmZyb21TZWNvbmRzKGouZHVyYXRpb24pfWAsXG5cdFx0XHRcdFx0ZGVzYzogai5kZXNjcmlwdGlvbi5yZXBsYWNlKC88YnIuPy4/Pi9nLCAnJyksXG5cdFx0XHRcdFx0dGg6IGRlY29kZVVSSShqLnRodW1ibmFpbF9tZWRpdW0pXG5cdFx0XHRcdH07XG5cdFx0XHR9LFxuXHRcdFx0eW91dHViZTogZnVuY3Rpb24gKGosIGlkKSB7XG5cdFx0XHRcdGlmIChqLnBhZ2VJbmZvLnRvdGFsUmVzdWx0cyA8IDEgfHwgai5pdGVtcy5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0XHRyZXR1cm4geyBpZCwgZXJyb3I6IHRydWUgfTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGogPSBqLml0ZW1zWzBdO1xuXHRcdFx0XHRjb25zdCBvID0ge1xuXHRcdFx0XHRcdHNpdGU6ICd5b3V0dWJlJyxcblx0XHRcdFx0XHRpZCxcblx0XHRcdFx0XHR0aXRsZTogYCR7ai5zbmlwcGV0LnRpdGxlfSAke1kuZXh0ZXJuYWwudGltZS5mcm9tSXNvODYwMShqLmNvbnRlbnREZXRhaWxzLmR1cmF0aW9uKX1gLFxuXHRcdFx0XHRcdGRlc2M6IGouc25pcHBldC5kZXNjcmlwdGlvblxuXHRcdFx0XHRcdC8vIGFzcGVjdFJhdGlvOiBqLmNvbnRlbnREZXRhaWxzLmFzcGVjdFJhdGlvXG5cdFx0XHRcdH07XG5cblx0XHRcdFx0cmV0dXJuIG87XG5cdFx0XHR9LFxuXHRcdFx0dmluZTogZnVuY3Rpb24gKHsgdGl0bGUsIHRodW1ibmFpbF91cmwgfSwgaWQpIHtcblx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRzaXRlOiAndmluZScsXG5cdFx0XHRcdFx0aWQsXG5cdFx0XHRcdFx0dGl0bGUsXG5cdFx0XHRcdFx0dGg6IHJlbW92ZVNlYXJjaCh0aHVtYm5haWxfdXJsKVxuXHRcdFx0XHR9O1xuXHRcdFx0fSxcblx0XHRcdGdmeWNhdDogZnVuY3Rpb24gKGh0bWwsIGlkKSB7XG5cdFx0XHRcdGlmIChodG1sKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdHNpdGU6ICdnZnljYXQnLFxuXHRcdFx0XHRcdFx0aWQ6IGlkLFxuXHRcdFx0XHRcdFx0dGl0bGU6IGlkXG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdHN0cmVhbWFibGU6IGZ1bmN0aW9uICh7IHRpdGxlIH0sIGlkKSB7XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0c2l0ZTogJ3N0cmVhbWFibGUnLFxuXHRcdFx0XHRcdGlkLFxuXHRcdFx0XHRcdHRpdGxlOiB0aXRsZSB8fCAnVW50aXRsZWQnXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzZXQ6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRpZiAoIXRoaXMuZGJbZGF0YS5zaXRlXSkge1xuXHRcdFx0XHR0aGlzLmRiW2RhdGEuc2l0ZV0gPSB7fTtcblx0XHRcdH1cblx0XHRcdHRoaXMuZGJbZGF0YS5zaXRlXVtkYXRhLmlkXSA9IGRhdGE7XG5cdFx0XHRyZXR1cm4gdGhpcy5zYXZlKCk7XG5cdFx0fSxcblx0XHR1bnNldDogZnVuY3Rpb24gKHsgc2l0ZSwgaWQgfSkge1xuXHRcdFx0Ly8gY29uc29sZS5sb2coJ3Vuc2V0JywgZGF0YS5pZCk7XG5cdFx0XHRpZiAoc2l0ZSkge1xuXHRcdFx0XHRkZWxldGUgdGhpcy5kYltzaXRlXVtpZF07XG5cdFx0XHRcdHJldHVybiB0aGlzLnNhdmUoKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGxpbWl0REI6IGZ1bmN0aW9uIChtYXgsIGRiKSB7XG5cdFx0XHQvLyBsaW1pdHMgYW4gb2JqZWN0J3MgaXRlbXMgYnkgaGFsZiBvZiB0aGUgbWF4XG5cdFx0XHQvLyByZW1vdmVzIHRoZSBvbGRlciBpdGVtcyBhdCB0aGUgc3RhcnQgb2YgdGhlIG9iamVjdFxuXHRcdFx0Y29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGRiKTtcblxuXHRcdFx0Y29uc3QgaGFsZiA9IE1hdGguZmxvb3IobWF4IC8gMik7XG5cdFx0XHRsZXQgc3RhcnQ7XG5cdFx0XHRsZXQgbmRiO1xuXHRcdFx0bGV0IGk7XG5cblx0XHRcdGlmIChrZXlzLmxlbmd0aCA+IG1heCkge1xuXHRcdFx0XHRuZGIgPSB7fTtcblx0XHRcdFx0c3RhcnQgPSBrZXlzLmxlbmd0aCAtIGhhbGY7XG5cblx0XHRcdFx0Zm9yIChpID0gc3RhcnQ7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0bmRiW2tleXNbaV1dID0gZGJba2V5c1tpXV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG5kYiB8fCBkYjtcblx0XHR9LFxuXHRcdHNhdmU6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHRoaXMuZGIgPSB0aGlzLmxpbWl0REIoMTAwMCwgdGhpcy5kYik7XG5cdFx0XHRyZXR1cm4gc3RyZy5zYXZlKHRoaXMudmVyc2lvbiwgdGhpcy5kYik7XG5cdFx0fSxcblx0XHRoZWxwZXI6IHtcblx0XHRcdGN1dERlc2NyaXB0aW9uOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRpZiAoZGF0YS5kZXNjICYmIGRhdGEuZGVzYy5sZW5ndGggPiAxNDApIHtcblx0XHRcdFx0XHRkYXRhLmZ1bGwgPSBkYXRhLmRlc2M7XG5cdFx0XHRcdFx0ZGF0YS5kZXNjID0gYCR7ZGF0YS5kZXNjLnN1YnN0cigwLCAxMzApfSAuIC4gLmA7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHR9LFxuXHRcdFx0dGh1bWJuYWlsOiBmdW5jdGlvbiAoeyBpZCwgdGggfSkge1xuXHRcdFx0XHRfLnMoYFtkYXRhLXl0bWlkPVwiJHtpZH1cIl0ueXRtX3RyaWdnZXJgLCBlbCA9PiBlbC5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgYGJhY2tncm91bmQ6IHVybCgke3RofSlgKSk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHR0aW1lOiB7XG5cdFx0XHRrZWVwTWludXRlc0FuZFNlY29uZHM6IGZ1bmN0aW9uICh2LCBpKSB7XG5cdFx0XHRcdHJldHVybiBpID4gMSB8fCB2ID4gMDtcblx0XHRcdH0sXG5cdFx0XHRsZWFkaW5nWmVybzogZnVuY3Rpb24gKHYsIGkpIHtcblx0XHRcdFx0cmV0dXJuIGkgPiAwID8gKGAwMCR7dn1gKS5zbGljZSgtMikgOiB2O1xuXHRcdFx0fSxcblx0XHRcdGZyb21BcnJheTogZnVuY3Rpb24gKGEpIHtcblx0XHRcdFx0Ly8gW2RheXMsIGhvdXJzLCBtaW5zLCBzZWNzXVxuXHRcdFx0XHRsZXQgYjtcblxuXHRcdFx0XHRsZXQgcCA9ICcnO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Ly8gUmVtb3ZlIGVtcHR5IHZhbHVlcywgYnV0IGtlZXAgbG93ZXIgaW5kZXhlcyAobTpzKTsgYVtpXSA+IDAgfHwgaSA+IDFcblx0XHRcdFx0XHQvLyBBZGQgbGVhZGluZyAwJ3MsIGlnbm9yaW5nIHRoZSBmaXJzdCBpbmRleFxuXHRcdFx0XHRcdC8vIGEuc2xpY2UoMCwgMSkuY29uY2F0KGEuc2xpY2UoMSkpXG5cdFx0XHRcdFx0YiA9IGEuZmlsdGVyKHRoaXMua2VlcE1pbnV0ZXNBbmRTZWNvbmRzKS5tYXAodGhpcy5sZWFkaW5nWmVybyk7XG5cdFx0XHRcdFx0cCA9IGAoJHtiLmpvaW4oJzonKX0pYDtcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdGNvbnNvbGUuZXJyb3IoJ0NvdWxkIG5vdCBwYXJzZSB0aGlzIHRpbWUuJyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL3RpbWUrYXJyYXknLCB7IGEsIGIsIHAgfSk7XG5cdFx0XHRcdHJldHVybiBwO1xuXHRcdFx0fSxcblx0XHRcdGZyb21Jc284NjAxOiBmdW5jdGlvbiAoaXNvODYwMSkge1xuXHRcdFx0XHQvLyBlZyBQVDNNLCBUMjlTXG5cdFx0XHRcdGxldCBhO1xuXG5cdFx0XHRcdGNvbnN0IHBhcnNlRGlnaXRzID0gcmVnID0+IHtcblx0XHRcdFx0XHRpZiAocmVnLnRlc3QoaXNvODYwMSkpIHtcblx0XHRcdFx0XHRcdHJldHVybiBSZWdFeHAubGFzdFBhcmVuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gMDtcblx0XHRcdFx0fTtcblxuXHRcdFx0XHQvLyBQI0RUI0gjTSNTIHx8IFBUI0gjTSNTXG5cdFx0XHRcdGEgPSBbLyhcXGQrKUQvLCAvKFxcZCspSC8sIC8oXFxkKylNLywgLyhcXGQrKVMvXS5tYXAocGFyc2VEaWdpdHMpO1xuXG5cdFx0XHRcdHJldHVybiB0aGlzLmZyb21BcnJheShhKTtcblx0XHRcdH0sXG5cdFx0XHRmcm9tU2Vjb25kczogZnVuY3Rpb24gKHNlY29uZHMpIHtcblx0XHRcdFx0Y29uc3QgYSA9IFtcblx0XHRcdFx0XHRNYXRoLmZsb29yKHNlY29uZHMgLyA4NjQwMCkgJSAyNCxcblx0XHRcdFx0XHRNYXRoLmZsb29yKHNlY29uZHMgLyAzNjAwKSAlIDYwLFxuXHRcdFx0XHRcdE1hdGguZmxvb3Ioc2Vjb25kcyAvIDYwKSAlIDYwLFxuXHRcdFx0XHRcdHNlY29uZHMgJSA2MFxuXHRcdFx0XHRdO1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5mcm9tQXJyYXkoYSk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHR2YWxpZGF0ZTogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdGlmICghZGF0YSB8fCAhZGF0YS5pZCB8fCBkYXRhLmVycm9yKSB7XG5cdFx0XHRcdHJldHVybiBZLmFqYXguZmFpbHVyZS5jYWxsKGRhdGEpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyB0b2RvPyBlbXB0eSB0aXRsZXMgYW5kIGRlc2NyaXB0aW9ucyBzaG91bGQgYmUgb2theVxuXHRcdFx0Ly8gaWYgKGRhdGEuaWQgJiYgIWRhdGEudGl0bGUgJiYgIWRhdGEuZGVzYykge1xuXHRcdFx0Ly8gXHR0aGlzLnVuc2V0KGRhdGEuaWQpO1xuXHRcdFx0Ly8gXHRyZXR1cm4gWVRNQS5hamF4LmZhaWx1cmUuY2FsbChkYXRhKTtcblx0XHRcdC8vIH1cblxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblx0XHRwb3B1bGF0ZTogZnVuY3Rpb24gKGRhdGEsIGlnbm9yZVZhbGlkYXRpb24pIHtcblx0XHRcdGlmICghaWdub3JlVmFsaWRhdGlvbiAmJiAhdGhpcy52YWxpZGF0ZShkYXRhKSkgeyByZXR1cm47IH1cblxuXHRcdFx0dGhpcy5zZXQoZGF0YSk7XG5cdFx0XHRjb25zdCB7IGlkLCB0aCwgZnVsbCwgZGVzYywgdGl0bGUgfSA9IGRhdGE7XG5cblx0XHRcdGlmICh0aCkgeyB0aGlzLmhlbHBlci50aHVtYm5haWwoZGF0YSk7IH1cblxuXHRcdFx0Xy5zKGAueXRtX2JkLl8ke1kuZXNjYXBlSWQoaWQpfWAsIGVsID0+IHtcblx0XHRcdFx0ZWwuaW5uZXJIVE1MID0gYDxzcGFuIGNsYXNzPVwieXRtX3RpdGxlXCI+JHt0aXRsZX08L3NwYW4+YDtcblx0XHRcdFx0aWYgKGRlc2MpIHtcblx0XHRcdFx0XHRjb25zdCBxID0gXy5lKCdxJywgeyBjbGFzc05hbWU6ICd5dG1fZGVzY3IgeXRtX2Jsb2NrJywgdGV4dENvbnRlbnQ6IGRlc2MgfSwgZWwpO1xuXHRcdFx0XHRcdGlmIChmdWxsLmxlbmd0aCA+IGRlc2MubGVuZ3RoKSB7XG5cdFx0XHRcdFx0XHRxLmRhdGFzZXQuZnVsbCA9IGZ1bGw7XG5cdFx0XHRcdFx0XHRxLnRpdGxlID0gJ0RvdWJsZSBjbGljayB0byB0b2dnbGUgdGhlIGRlc2NyaXB0aW9uLic7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9LFxuXHRcdGRhdGFGcm9tU3RvcmFnZTogZnVuY3Rpb24gKHNpdGUsIGlkKSB7XG5cdFx0XHRpZiAodGhpcy5kYiAmJiB0aGlzLmRiW3NpdGVdKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmRiW3NpdGVdW2lkXTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cdFkuZXh0ZXJuYWwuZGIgPSBzdHJnLmdyYWIoWS5leHRlcm5hbC52ZXJzaW9uLCB7fSk7XG5cblx0LyoqIERhdGFiYXNlICovXG5cdFkuREIgPSB7XG5cdFx0cG9zdEluaXQ6IGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmIChZLnVzZXIucHJlZmVyZW5jZXMueXRfbm9jb29raWUpIHtcblx0XHRcdFx0WS5EQi5zaXRlcy55b3V0dWJlLmhvbWUgPSAnaHR0cHM6Ly93d3cueW91dHViZS1ub2Nvb2tpZS5jb20vJztcblx0XHRcdFx0WS5EQi5zaXRlcy55b3V0dWJlLmVtYmVkID0gJ2h0dHBzOi8vd3d3LnlvdXR1YmUtbm9jb29raWUuY29tL2VtYmVkLyVrZXknO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0ZXh0ZW5zaW9uOiB3aW5kb3cuY2hyb21lICYmIHdpbmRvdy5jaHJvbWUuZXh0ZW5zaW9uLFxuXHRcdHNpdGVzOiB7IC8vIHN1cHBvcnRlZCBzaXRlcyAtIHRvIGFkZCBtb3JlIGFsc28gbWFrZSBhIHBhcnNlciAoaWYgYXBpIGlzIGF2YWlsYWJsZSkgYW5kIGFkZCBhbiBpdGVtIHRvIHNvdXJjZXMgKGlmIG5lY2Vzc2FyeSlcblx0XHRcdHlvdXR1YmU6IHtcblx0XHRcdFx0dGl0bGU6ICd5dG1hIScsXG5cdFx0XHRcdGhvbWU6ICdodHRwczovL3d3dy55b3V0dWJlLmNvbS8nLFxuXHRcdFx0XHRlbWJlZDogJ2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2VtYmVkLyVrZXknLFxuXHRcdFx0XHRhamF4OiBgaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20veW91dHViZS92My92aWRlb3M/cGFydD1zbmlwcGV0LGNvbnRlbnREZXRhaWxzJmlkPSVrZXkke3dpbmRvdy5hdG9iKCdKbXRsZVQxQlNYcGhVM2xFVkc1SU5reHpSRVJ5VkVsWWFGWlRaV1JRUWpseVJIbzFjekJTY3pRelpuTT0nKX1gLFxuXHRcdFx0XHR0aHVtYjogJ3VybChodHRwczovL2kzLnl0aW1nLmNvbS92aS8la2V5LzEuanBnKScsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cInlvdXR1YmUuXCJdLCBhW2hyZWYqPVwieW91dHUuYmUvXCJdJyxcblx0XHRcdFx0ZmF2aWNvbjogJ2h0dHBzOi8vd3d3LnlvdXR1YmUuY29tL2Zhdmljb24uaWNvJyxcblx0XHRcdFx0a2V5OiAnaWQnLFxuXHRcdFx0XHRyZWc6ICcoeW91dHUpJyxcblx0XHRcdFx0bWF0Y2hlcjogLyg/Oig/Oig/OnY9fCNwXFwvdVxcL1xcZCo/XFwvKXwoPzp2PXwjcFxcL2NcXC9bYS16QS1aMC05XStcXC9cXGQqP1xcLyl8KD86ZW1iZWRcXC8pfCg/OnZcXC8pfCg/OlxcLmJlXFwvKSkoW0EtWmEtejAtOS1fXXsxMX0pKS9pLFxuXHRcdFx0XHRodHRwczogdHJ1ZVxuXHRcdFx0fSxcblx0XHRcdHZpbWVvOiB7XG5cdFx0XHRcdHRpdGxlOiAndmltZW8gdG9vIScsXG5cdFx0XHRcdGhvbWU6ICdodHRwczovL3ZpbWVvLmNvbS8nLFxuXHRcdFx0XHRlbWJlZDogJ2h0dHBzOi8vcGxheWVyLnZpbWVvLmNvbS92aWRlby8la2V5P2JhZGdlPTAnLFxuXHRcdFx0XHRhamF4OiAnaHR0cHM6Ly92aW1lby5jb20vYXBpL3YyL3ZpZGVvLyVrZXkuanNvbicsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cInZpbWVvLmNvbS9cIl0nLFxuXHRcdFx0XHRmYXZpY29uOiAnaHR0cHM6Ly9mLnZpbWVvY2RuLmNvbS9pbWFnZXNfdjYvZmF2aWNvbi5pY28nLFxuXHRcdFx0XHRrZXk6ICdpZCcsXG5cdFx0XHRcdHJlZzogJyh2aW1lbyknLFxuXHRcdFx0XHRtYXRjaGVyOiAvKD86dmltZW9cXC5jb21cXC8oXFxkKykpL2ksXG5cdFx0XHRcdGh0dHBzOiB0cnVlXG5cdFx0XHR9LFxuXHRcdFx0dmluZToge1xuXHRcdFx0XHR0aXRsZTogJ3ZpbmUgbWUhJyxcblx0XHRcdFx0aG9tZTogJ2h0dHBzOi8vdmluZS5jby8nLFxuXHRcdFx0XHRlbWJlZDogJ2h0dHBzOi8vdmluZS5jby92LyVrZXkvZW1iZWQvc2ltcGxlP2F1ZGlvPTEnLFxuXHRcdFx0XHRhamF4RXh0ZW5zaW9uOiB0cnVlLFxuXHRcdFx0XHRhamF4OiAnaHR0cHM6Ly92aW5lLmNvL29lbWJlZC5qc29uP3VybD1odHRwcyUzQSUyRiUyRnZpbmUuY28lMkZ2JTJGJWtleScsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cInZpbmUuY28vXCJdJyxcblx0XHRcdFx0ZmF2aWNvbjogJ2RhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBUUNBWUFBQUFmOC85aEFBQUJja2xFUVZRNGpYMlN2eXZGWVJUR1ArOU5kekFZYnBJa3lzQS9JQ25Lb0V3dkE0dmxVa295R1F6dm9PaUs0UjBZYkRMaERoYmk5bWFXSWpFcWNTY1dreVJoTU56WGNNLzNPbjM5T010NW52T2U4NXdmdlNiR3lIOW1nczhDcThBVWtBTWVnVTFnSlZwWHFmdTN1bXBid0lUaUxVQkI4SEpHdXJ5YjRLTUovaXpWdlVNVm53Tmp3SlB3R1lDTWtMTDR6bFQzWG9VTDBib0Q0RkJOVWhPNEZkOW9nbTlTUlZtRm44VW5hNzlxZ1d1VjJLM3d2Y0xKZEczaUw3VGFpVW9jQUk0Rm4wdm5IREJyZ3QrTDFnMnEzTm9FbDhDSDRLSGtNVnIzQ1N3STdRZU9UUEE5V3NBay84QUV2dytNU3J3cldsZXVKUVZmQUJaSldiVE9aQlRmVlhnNmxiZ0VIS2pRVGNMMUJGbmdBV2ltZXVIMmFOMkx2SFVEVjFKY2pOYmwwemRJOWwwVDJwRHNib0t2QjdZbC9nYTRYMitna3UrQVZxQUM5QUZ6d0xpazVLTjF4VDhGUkdRRU9CTDZ5ZmRuMm9uV1RaS3lURG9RclNzQjYwS1Q0bE5TaC8xVFFFVG1nUTFab3dRTXk0MSsyQmVMUlhlUmFLdUhTQUFBQUFCSlJVNUVya0pnZ2c9PScsXG5cdFx0XHRcdGtleTogJ2lkJyxcblx0XHRcdFx0cmVnOiAnKHZpbmUpJyxcblx0XHRcdFx0bWF0Y2hlcjogLyg/OnZpbmVcXC5jb1xcL3ZcXC8oW0EtWmEtejAtOS1fXXsxMX0pKS9pXG5cdFx0XHR9LFxuXHRcdFx0c291bmRjbG91ZDoge1xuXHRcdFx0XHR0aXRsZTogJ3NvdW5kIG9mZiEnLFxuXHRcdFx0XHRob21lOiAnaHR0cHM6Ly9zb3VuZGNsb3VkLmNvbS8nLFxuXHRcdFx0XHRlbWJlZDogJ2h0dHBzOi8vdy5zb3VuZGNsb3VkLmNvbS9wbGF5ZXIvP3Nob3dfY29tbWVudHM9ZmFsc2UmdXJsPSVrZXknLFxuXHRcdFx0XHRhamF4OiAnaHR0cHM6Ly9zb3VuZGNsb3VkLmNvbS9vZW1iZWQ/Zm9ybWF0PWpzb24mdXJsPSV1cmknLFxuXHRcdFx0XHRmYXZpY29uOiAnZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBd0FBQUFNQ0FZQUFBQldkVnpuQUFBQUdYUkZXSFJUYjJaMGQyRnlaUUJCWkc5aVpTQkpiV0ZuWlZKbFlXUjVjY2xsUEFBQUFYWkpSRUZVZU5wMFVqRk93MEFRbkQzYkNZYUVvSWdpVUlRS2lraUFLS0dnU0FrRkwwQlEwRkVnVWZFQ1NocGV3QitRRUUrZ29rRGlCeEdSaUNDRUJCekhkOHVjTFlHUTRLdzcrOWF6YzdPeko2b0tuRllVeGdEK1cvREhZTkE1NEdJb29pZlRpdFlxZzFva2FQRmZmNkJjVExGNWZFQ1liNUlKTkoza01mVVAyZHhIUHljd2NRMFNsaUFSb2NTR3NBNDZZa0tXUVcwR1M2QkRBR2x1NU15dTg0QWdTbUhLTS9EWTBOZWd3d1IyK0FKclNqQnJlNUJhQTFIN0dGS3BJNzI5UUhwOWpxaWFlVEJuNW1CN2ZXaXJqV0I5QjlKWUJyd0VNbm9wNWQwemZENTNZTzl2WU1ZOFNRY3BaR2tUWnZzSXN0aWl2RGZvYXhmSXh0OGV4WWVYQ0xZT1NPd2xKWlE2dHdTcEwwRGZYNEVvWnRrQ3FjNy9OamFsYnhuZmR0K29Td2h1cmtCbkNXSS8xRmxncWdLTlozSm5aRFNBM0ZGU3BZZFFBb0Y1NnRLTkRtaE9ZVHpKM09TSFhaa2ZsSmhZRXlhd2NuSDAySHBteForRHJSSmxnbWFjdnJzSFJtSGxuMnRSbklpQXk1V1RMd0VHQUs0UW9CUW10R0hrQUFBQUFFbEZUa1N1UW1DQycsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cInNvdW5kY2xvdWQuY29tL1wiXScsXG5cdFx0XHRcdGtleTogJ3VyaScsXG5cdFx0XHRcdHJlZzogJyhzb3VuZGNsb3VkKScsXG5cdFx0XHRcdG1hdGNoZXI6IC8oPzpcXC9cXC8oPzpcXGJ3d3d8bVxcLlxcYik/c291bmRjbG91ZFxcLmNvbVxcLyguKz9cXC8uKykpL2ksXG5cdFx0XHRcdGh0dHBzOiB0cnVlLFxuXHRcdFx0XHRzY3JvbGw6IHRydWVcblx0XHRcdH0sXG5cdFx0XHRnZnljYXQ6IHtcblx0XHRcdFx0dGl0bGU6ICdnZnljYXQgbWVvdyEnLFxuXHRcdFx0XHRob21lOiAnaHR0cHM6Ly9nZnljYXQuY29tLycsXG5cdFx0XHRcdGVtYmVkOiAnaHR0cHM6Ly9nZnljYXQuY29tL2lmcmFtZS8la2V5Jyxcblx0XHRcdFx0YWpheEV4dGVuc2lvbjogdHJ1ZSxcblx0XHRcdFx0cmF3UmVzcG9uc2U6IHRydWUsXG5cdFx0XHRcdGFqYXg6ICdodHRwczovL2dmeWNhdC5jb20vJWtleScsXG5cdFx0XHRcdHRodW1iOiAndXJsKGh0dHBzOi8vdGh1bWJzLmdmeWNhdC5jb20vJWtleS1wb3N0ZXIuanBnKScsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cImdmeWNhdC5jb20vXCJdJyxcblx0XHRcdFx0ZmF2aWNvbjogJ2h0dHBzOi8vZ2Z5Y2F0LmNvbS9mYXZpY29uLmljbycsXG5cdFx0XHRcdGtleTogJ2lkJyxcblx0XHRcdFx0cmVnOiAnKGdmeWNhdCknLFxuXHRcdFx0XHRtYXRjaGVyOiAvKD86Z2Z5Y2F0XFwuY29tXFwvKD86KFxcYig/OltBLVpdW2Etel0qKXszLH1cXGIpKSkvaSxcblx0XHRcdFx0aHR0cHM6IHRydWUsXG5cdFx0XHRcdHNjcm9sbDogdHJ1ZVxuXHRcdFx0fSxcblx0XHRcdHN0cmVhbWFibGU6IHtcblx0XHRcdFx0dGl0bGU6ICdzdHJlYW1hYmxlIScsXG5cdFx0XHRcdGhvbWU6ICdodHRwczovL3N0cmVhbWFibGUuY29tLycsXG5cdFx0XHRcdGVtYmVkOiAnaHR0cHM6Ly9zdHJlYW1hYmxlLmNvbS9lLyVrZXknLFxuXHRcdFx0XHRhamF4OiAnaHR0cHM6Ly9hcGkuc3RyZWFtYWJsZS5jb20vb2VtYmVkLmpzb24/dXJsPSV1cmknLFxuXHRcdFx0XHR0aHVtYjogJ3VybChodHRwczovL2Nkbi5zdHJlYW1hYmxlLmNvbS9pbWFnZS8la2V5LmpwZyknLFxuXHRcdFx0XHRzZWxlY3RvcjogJ2FbaHJlZio9XCJzdHJlYW1hYmxlLmNvbS9cIl0nLFxuXHRcdFx0XHRmYXZpY29uOiAnaHR0cHM6Ly9zdHJlYW1hYmxlLmNvbS9mYXZpY29uLmljbycsXG5cdFx0XHRcdGtleTogJ2lkJyxcblx0XHRcdFx0cmVnOiAnKHN0cmVhbWFibGVcXFxcLmNvbSknLFxuXHRcdFx0XHRtYXRjaGVyOiAvKD86c3RyZWFtYWJsZVxcLmNvbVxcLyhbQS1aYS16MC05LV9dKykpL2ksXG5cdFx0XHRcdGh0dHBzOiB0cnVlXG5cdFx0XHR9LFxuXHRcdFx0aW1ndXI6IHtcblx0XHRcdFx0dGl0bGU6ICdpbWd1ciBpdCEnLFxuXHRcdFx0XHRob21lOiAnaHR0cHM6Ly9pLmltZ3VyLmNvbS8nLFxuXHRcdFx0XHRlbWJlZDogJ2h0dHBzOi8vaS5pbWd1ci5jb20vJWtleScsXG5cdFx0XHRcdHRodW1iOiAndXJsKGh0dHBzOi8vaS5pbWd1ci5jb20vJWtleWguanBnKScsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cIi5naWZ2XCJdJyxcblx0XHRcdFx0ZmF2aWNvbjogJ2h0dHBzOi8vaW1ndXIuY29tL2Zhdmljb24uaWNvJyxcblx0XHRcdFx0cmVnOiAnKFxcXFwuZ2lmdiQpfChpbWd1ciknLFxuXHRcdFx0XHRtYXRjaGVyOiAvKD86aW1ndXJcXC5jb21cXC8oXFx3KylcXC4oPzpnaWZ2fG1wNHx3ZWJtKSkvaSxcblx0XHRcdFx0aHR0cHM6IHRydWUsXG5cdFx0XHRcdHNjcm9sbDogdHJ1ZSxcblx0XHRcdFx0dmlkZW9UYWc6IHRydWVcblx0XHRcdH0sXG5cdFx0XHRodG1sNToge1xuXHRcdFx0XHRob21lOiB0cnVlLFxuXHRcdFx0XHR0aXRsZTogJ2h0bWw1IGdvIScsXG5cdFx0XHRcdHNlbGVjdG9yOiAnYVtocmVmKj1cIi53ZWJtXCJdLCBhW2hyZWYqPVwiLm1wNFwiXScsXG5cdFx0XHRcdGZhdmljb246ICdkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUEwQUFBQU5DQVlBQUFCeTYrUjhBQUFBR1hSRldIUlRiMlowZDJGeVpRQkJaRzlpWlNCSmJXRm5aVkpsWVdSNWNjbGxQQUFBQWRsSlJFRlVlTnBja3M5ckUwRVV4NytiM1RSa3R4dmJoVWhyTm02U3JVV3R4eGJ4SjlpTGwwSkZLV2c4V0xEMDVFV2hJdVJpZW9nWHdZUFg0dEdiL2dQU3Evb1A2S0grdUcyTUZhUkpKWGFUYnA3Zldic2wrdUREekx4NTMzbHYzb3ptZXlVTTJWbFNKeGVJU1VMeWdUd2hyNU9nMUpEZ09YbFBycExSTUF4VElwTGxmSmE4SXB2L2k1NlJlNGxUMDdTWUtJcVFTaDJlTzAvZXFZbnVqSTM1SEY4TzE5anI5WEJuZVJtdDFqZTBkM2FnNjNxeTVaSUF2Tk9iRStXS1RKWEtrdEVOb1ZQc3JDbnRkbHNXRnhiaU5YTkp5UzNLZE1VWHh2OHc2THpZN1haaG1pWWVyOWZCWU9UelI1SEw1WEN6V3NXeFloRm5Ucy9neGNZR2dpQ0FaVm1PeWhSNUJWY204bmxadmJzaTI5KzNaZGdHZzRHczErdml1YTRVSmlaVnBraUplcW8wVmFJcXhiR1BTS2ZUT1JSZHVYUTU5cGVMeDVQeUl0V2FqOXlEUXRtdDIxWFl0bzFHb3hHdmJ5d3R4YU5oR0hFM2FiK1Y2TDZhS1ljelBvN1p1VGs4V251SVdxMkc2NHZYNEpVOHpKdzhCWFh2NUQyMWd4K3h5ZHJuN1ZFYi9mMCt0ajV0d2EvNCtQejFDNlk0T282RFpyT0pkRHJkWXV4a0lsS1ArWmJaem9WN2U4aXlrOGtELzlyZFJYcGtCSmxNcHNtREMvOThJOTdwUEYvL0FRVUJsLzIvalJ2c201YjFreG1lSmdKbGZ3UVlBS1pReGd6ZUk2L0VBQUFBQUVsRlRrU3VRbUNDJyxcblx0XHRcdFx0cmVnOiAnKFxcXFwud2VibSQpfChcXFxcLm1wNCQpJyxcblx0XHRcdFx0c2xpbTogdHJ1ZSxcblx0XHRcdFx0c2Nyb2xsOiB0cnVlLFxuXHRcdFx0XHR2aWRlb1RhZzogdHJ1ZVxuXHRcdFx0fSxcblx0XHRcdCdodG1sNS1hdWRpbyc6IHtcblx0XHRcdFx0aG9tZTogdHJ1ZSxcblx0XHRcdFx0dGl0bGU6ICdoZXksIGxpc3RlbiEnLFxuXHRcdFx0XHRzZWxlY3RvcjogJ2FbaHJlZio9XCIubXAzXCJdJyxcblx0XHRcdFx0cmVnOiAnKFxcXFwubXAzJCknLFxuXHRcdFx0XHRzbGltOiB0cnVlLFxuXHRcdFx0XHRzY3JvbGw6IHRydWVcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0Y2xhc3MgQ29udHJvbCBleHRlbmRzIENvbnRhaW5lciB7XG5cdFx0LyoqIFUgSSBDTEFTU1xuXHRcdCAqIENsYXNzIGZvciB0aGUgcGxheWVyIGNvbnRyb2xzXG5cdFx0ICogVGhpcyBpcyB0aGUgY29udHJvbCBiYXIgb25jZSB0aGUgdXNlciBjbGlja3Mgb24gdGhlIHRodW1ibmFpbFxuXHRcdCAqIENvbnRhaW5zIGl0cyBvd24gaW5zdGFuY2Ugb2YgYSBQbGF5ZXJcblx0XHQgKiBBY3RzIGxpa2UgYSBkZWNvcmF0b3Igb24gdGhlIFlUTUEgYW5kIENvbnRhaW5lciBpbnRhbmNlcyBieSBhZGRpbmcgZXZlbnRzXG5cdFx0ICogQHBhcmFtIHtZfSB5dG1hIEEgWVRNQSBpbnN0YW5jZVxuXHRcdCAqL1xuXHRcdGNvbnN0cnVjdG9yKHByb3BzKSB7XG5cdFx0XHRzdXBlcihwcm9wcyk7XG5cblx0XHRcdHRoaXMub3BlbiA9IGZhbHNlO1xuXHRcdFx0dGhpcy5zZWxlY3RlZCA9IHsgc2l6ZTogbnVsbCwgcmF0aW86IG51bGwgfTtcblx0XHR9XG5cblx0XHRnZXRDb250cm9sKCkge1xuXHRcdFx0aWYgKCF0aGlzLnByb2plY3Rvcikge1xuXHRcdFx0XHR0aGlzLmNyZWF0ZVByb2plY3RvcigpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Y3JlYXRlUHJvamVjdG9yKCkge1xuXHRcdFx0c3VwZXIuY3JlYXRlUHJvamVjdG9yKCk7XG5cdFx0XHR0aGlzLnByb2plY3Rvci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIENvbnRyb2wuZXZlbnRzLnZpZGVvQmFyLmJpbmQodGhpcyksIGZhbHNlKTtcblx0XHRcdHRoaXMucGxheSA9IG5ldyBQbGF5ZXIodGhpcyk7XG5cblx0XHRcdHRoaXMubWFya1NlbGVjdGVkKGBsaVtkYXRhLXR5cGU9XCJzaXplXCJdW2RhdGEtdmFsdWU9XCIke3RoaXMucGxheS5hdHRycy5zaXplfVwiXWAsICdzaXplJyk7XG5cdFx0XHR0aGlzLm1hcmtTZWxlY3RlZChgbGlbZGF0YS10eXBlPVwicmF0aW9cIl1bZGF0YS12YWx1ZT1cIiR7dGhpcy5wbGF5LmF0dHJzLnJhdGlvfVwiXWAsICdyYXRpbycpO1xuXHRcdH1cblxuXHRcdHJlc2V0Vmlld1NpemUoKSB7XG5cdFx0XHR0aGlzLnBsYXkuZGltbWVuc2lvbnMoKTtcblx0XHRcdHRoaXMuc2V0Q29udHJvbEJhclNpemUodGhpcy5wbGF5LmF0dHJzLnNpemUpO1xuXHRcdH1cblxuXHRcdHNob3dPblNjcm9sbChsaW5rKSB7XG5cdFx0XHRpZiAoIXRoaXMub3BlbiAmJiB0aGlzLmNhblNob3dVbmRlcihsaW5rKSkge1xuXHRcdFx0XHR0aGlzLnNob3dQbGF5ZXIoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRzaG93UGxheWVyKCkge1xuXHRcdFx0dGhpcy5vcGVuID0gdHJ1ZTtcblxuXHRcdFx0c3VwZXIuc2hvd1BsYXllcigpO1xuXHRcdFx0dGhpcy5hdHRhY2hQbGF5ZXJQYW5lbCgpO1xuXHRcdFx0dGhpcy5wbGF5LnN3aXRjaE9uKCk7XG5cblx0XHRcdGlmIChZLnVzZXIucHJlZmVyZW5jZXMuZm9jdXMpIHtcblx0XHRcdFx0ZG9jdW1lbnQubG9jYXRpb24uaGFzaCA9IGAjJHt0aGlzLmJvZHkuaWR9YDtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRoaWRlUGxheWVyKCkge1xuXHRcdFx0dGhpcy5vcGVuID0gZmFsc2U7XG5cblx0XHRcdHRoaXMucGxheS5zd2l0Y2hPZmYoKTtcblx0XHRcdHN1cGVyLmhpZGVQbGF5ZXIoKTtcblx0XHR9XG5cblx0XHRhdHRhY2hQbGF5ZXJQYW5lbCgpIHtcblx0XHRcdGlmICghdGhpcy5wbGF5LnBhbmVsLnBhcmVudE5vZGUpIHtcblx0XHRcdFx0Ly8gY29uc29sZS5sb2coJ2F0dGFjaGluZyBkaXNwbGF5IHBhbmVsJyk7XG5cdFx0XHRcdHRoaXMucHJvamVjdG9yLmFwcGVuZENoaWxkKHRoaXMucGxheS5wYW5lbCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aGlkZUFsbFBsYXllcnMoKSB7XG5cdFx0XHRjb25zdCBncm91cCA9IFkuY29sbGVjdCh0aGlzLnN0YXRlLmlkKTtcblx0XHRcdGNvbnNvbGUuaW5mbygneXRtYS8vaGlkZSthbGwoaWQpJywgdGhpcy5zdGF0ZS5pZCwgZ3JvdXAubGVuZ3RoKTtcblx0XHRcdGdyb3VwLmZvckVhY2goZyA9PiB7XG5cdFx0XHRcdGcuZGlzYWJsZU9wZW5PblNjcm9sbCgpO1xuXHRcdFx0XHRnLmdldENvbnRyb2woKS5oaWRlUGxheWVyKCk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRzZXRDb250cm9sQmFyU2l6ZShzaXplKSB7XG5cdFx0XHR0aGlzLm1hcmtTZWxlY3RlZChgbGlbZGF0YS10eXBlPVwic2l6ZVwiXVtkYXRhLXZhbHVlPVwiJHtzaXplfVwiXWAsICdzaXplJyk7XG5cdFx0fVxuXG5cdFx0bWFya1NlbGVjdGVkKGVsLCB0eXBlKSB7XG5cdFx0XHRpZiAodHlwZW9mIGVsID09PSAnc3RyaW5nJykge1xuXHRcdFx0XHRlbCA9IHRoaXMucHJvamVjdG9yLnF1ZXJ5U2VsZWN0b3IoZWwpO1xuXHRcdFx0fVxuXHRcdFx0ZWwuaWQgPSB0eXBlICsgdGhpcy5zdGF0ZS51aWQ7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHR0aGlzLnNlbGVjdGVkW3R5cGVdLnJlbW92ZUF0dHJpYnV0ZSgnaWQnKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHsgfVxuXHRcdFx0dGhpcy5zZWxlY3RlZFt0eXBlXSA9IGVsO1xuXHRcdH1cblx0fVxuXG5cdENvbnRyb2wucmF0aW9zID0ge1xuXHRcdFNEOiAxLFxuXHRcdEhEOiAyLFxuXHRcdFBPUlRSQUlUOiAzXG5cdH07XG5cblx0Q29udHJvbC5zaXplcyA9IHtcblx0XHRISURERU46IDAsXG5cdFx0UzogMjQwLFxuXHRcdE06IDM2MCxcblx0XHRMOiA0ODAsXG5cdFx0WDogNzIwXG5cdH07XG5cblx0LyoqIFRyaWdnZXIgaXMgdGhlIFZBUiBlbGVtZW50XG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHQgVkFSIGVsZW1lbnRcblx0ICovXG5cdENvbnRyb2wuY3JlYXRlRnJvbVRyaWdnZXIgPSB0ID0+IHtcblx0XHQvLyBjb25zb2xlLmluZm8oJ3l0bWEvL3RyaWdnZXInKTtcblx0XHRpZiAodCAmJiB0LmRhdGFzZXQueXRtdWlkICYmICFZLnNldFt0LmRhdGFzZXQueXRtdWlkXSkge1xuXHRcdFx0Y29uc29sZS5pbmZvKCd5dG1hLy90cmlnZ2VyK25ldycpO1xuXHRcdFx0WS5hZGRUb1NldChuZXcgQ29udHJvbCgpLnJlYWN0aXZhdGUodCkpO1xuXHRcdH1cblx0XHRjb25zb2xlLmluZm8oJ3l0bWEvL3RyaWdnZXIrY29udHJvbCcpO1xuXHRcdHJldHVybiBZLnNldFt0LmRhdGFzZXQueXRtdWlkXS5nZXRDb250cm9sKCk7XG5cdH07XG5cblx0Q29udHJvbC5ldmVudHMgPSB7XG5cdFx0JGZpcmU6IHtcblx0XHRcdHNldHRpbmdzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFkudXNlci5ldmVudHMuZm9ybVRvZ2dsZSgpO1xuXHRcdFx0fSxcblx0XHRcdGNsb3NlOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdGlmICh0aGlzLnNpdGUuc2Nyb2xsKSB7XG5cdFx0XHRcdFx0Ly8gY29uc29sZS5sb2coJ2V2ZW50cy5jbG9zZS0xJyk7XG5cdFx0XHRcdFx0dGhpcy5oaWRlQWxsUGxheWVycygpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIGNvbnNvbGUubG9nKCdldmVudHMuY2xvc2UtMicpO1xuXHRcdFx0XHRcdHRoaXMuZGlzYWJsZU9wZW5PblNjcm9sbCgpO1xuXHRcdFx0XHRcdHRoaXMuaGlkZVBsYXllcigpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0cmF0aW86IGZ1bmN0aW9uIChsaSkge1xuXHRcdFx0XHRjb25zdCByYXRpbyA9IHBhcnNlSW50KGxpLmRhdGFzZXQudmFsdWUsIDEwKTtcblx0XHRcdFx0dGhpcy5wbGF5LmRpbW1lbnNpb25zKHsgcmF0aW8gfSk7XG5cdFx0XHRcdHRoaXMubWFya1NlbGVjdGVkKGxpLCAncmF0aW8nKTtcblx0XHRcdH0sXG5cdFx0XHRzaXplOiBmdW5jdGlvbiAobGkpIHtcblx0XHRcdFx0Y29uc3Qgc2l6ZSA9IHBhcnNlSW50KGxpLmRhdGFzZXQudmFsdWUsIDEwKTtcblx0XHRcdFx0dGhpcy5wbGF5LmRpbW1lbnNpb25zKHsgc2l6ZSB9KTtcblx0XHRcdFx0dGhpcy5tYXJrU2VsZWN0ZWQobGksICdzaXplJyk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHR2aWRlb0JhcjogZnVuY3Rpb24gKHsgdGFyZ2V0IH0pIHtcblx0XHRcdGlmICh0YXJnZXQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnbGknICYmIHRhcmdldC5kYXRhc2V0ICYmIHRhcmdldC5kYXRhc2V0LnR5cGUpIHtcblx0XHRcdFx0Y29uc3QgdCA9IHRhcmdldC5kYXRhc2V0LnR5cGU7XG5cdFx0XHRcdGlmIChDb250cm9sLmV2ZW50cy4kZmlyZVt0XSkge1xuXHRcdFx0XHRcdENvbnRyb2wuZXZlbnRzLiRmaXJlW3RdLmNhbGwodGhpcywgdGFyZ2V0KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHQvKiogUCBMIEEgWSBFIFIgQ0xBU1Ncblx0ICogIEBwYXJhbSB7Q29udHJvbH0gcGFyZW50IEluc3RhbmNlXG5cdCAqL1xuXHRjbGFzcyBQbGF5ZXIge1xuXG5cdFx0Y29uc3RydWN0b3IocGFyZW50KSB7XG5cdFx0XHR0aGlzLnBhcmVudCA9IHBhcmVudDtcblxuXHRcdFx0dGhpcy5tb2RlID0gJ29mZic7XG5cblx0XHRcdHRoaXMuYXR0cnMgPSB7XG5cdFx0XHRcdHNvdXJjZXM6IG51bGwsXG5cdFx0XHRcdHF1YWxpdHk6IHRoaXMucXVhbGl0eSxcblx0XHRcdFx0c2l6ZTogbnVsbCxcblx0XHRcdFx0cmF0aW86IG51bGwsXG5cdFx0XHRcdHN0YXJ0OiB0aGlzLnRpbWUoKSxcblx0XHRcdFx0dHlwZTogbnVsbFxuXHRcdFx0fTtcblxuXHRcdFx0dGhpcy5hdHRycy5zb3VyY2VzID0gdGhpcy5zb3VyY2VzO1xuXG5cdFx0XHQvLyB0b2RvIGltcHJvdmUgdHlwZS9tZWRpYVxuXHRcdFx0dGhpcy5hdHRycy50eXBlID0gdGhpcy5maW5kVHlwZSgpO1xuXHRcdFx0dGhpcy5tZWRpYSA9IFBsYXllci5tYWtlTWVkaWFbdGhpcy5hdHRycy50eXBlXSh0aGlzKTtcblxuXHRcdFx0dGhpcy5jaGFubmVsID0gXy5lKCdkaXYnLCB7IGNsYXNzTmFtZTogJ3l0bV9wYW5lbF9jaGFubmVsIHl0bV9ibG9jaycgfSwgdGhpcy5tZWRpYSwgdHJ1ZSk7XG5cdFx0XHR0aGlzLnN3aXRjaGVyID0gXy5lKCdkaXYnLCB7IGNsYXNzTmFtZTogYHl0bV9wYW5lbF9zd2l0Y2hlciB5dG1fcGFuZWxfc2l6ZSB5dG1fYmxvY2sgeXRtXyR7dGhpcy5hdHRycy50eXBlfWAsIF95dG11aWQ6IHRoaXMucGFyZW50LnN0YXRlLnVpZCwgX3N0YW5kYnk6IHRydWUgfSk7XG5cdFx0XHR0aGlzLnBhbmVsID0gXy5lKCdkaXYnLCB7IGNsYXNzTmFtZTogJ3l0bV9wYW5lbCB5dG1fYmxvY2snIH0sIHRoaXMuc3dpdGNoZXIsIHRydWUpO1xuXG5cdFx0XHRpZiAocGFyZW50LnN0YXRlLnNpdGUgPT09ICdzb3VuZGNsb3VkJyAmJiBZLnJlZy5leHRyYS5zb3VuZGNsb3VkLnBsYXlsaXN0LnRlc3QocGFyZW50LmFuY2hvci5ocmVmKSkge1xuXHRcdFx0XHR0aGlzLm1lZGlhLmNsYXNzTGlzdC5hZGQoJ3l0bV9zb3VuZGNsb3VkLXBsYXlsaXN0Jyk7XG5cdFx0XHRcdHRoaXMuc3dpdGNoZXIuY2xhc3NMaXN0LmFkZCgneXRtX3NvdW5kY2xvdWQtcGxheWxpc3QnKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5kaW1tZW5zaW9ucyhZLnVzZXIucHJlZmVyZW5jZXMpO1xuXHRcdH1cblxuXHRcdGdldCBzb3VyY2VzKCkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0cmV0dXJuIChQbGF5ZXIuc291cmNlc1t0aGlzLnBhcmVudC5zdGF0ZS5zaXRlXSB8fCBQbGF5ZXIuc291cmNlcy5pZnJhbWUpKHRoaXMucGFyZW50LnN0YXRlLCB0aGlzLmF0dHJzKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcihlKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRnZXQgcXVhbGl0eSgpIHtcblx0XHRcdHJldHVybiBQbGF5ZXIucXVhbGl0aWVzW1kudXNlci5wcmVmZXJlbmNlcy5xdWFsaXR5XSB8fCBQbGF5ZXIucXVhbGl0aWVzWzM2MF07XG5cdFx0fVxuXG5cdFx0Z2V0IGNsYXNzTmFtZSgpIHtcblx0XHRcdHJldHVybiBgeXRtX3BhbmVsIHl0bV9ibG9jayB5dG1fcGFuZWwtJHtQbGF5ZXIuZGltbXMucmF0aW9zW3RoaXMuYXR0cnMucmF0aW9dfSB5dG1fcGFuZWwtJHtQbGF5ZXIuZGltbXMuc2l6ZXNbdGhpcy5hdHRycy5zaXplXX1gO1xuXHRcdH1cblxuXHRcdGRpbW1lbnNpb25zKHsgcmF0aW8sIHNpemUgfSkge1xuXHRcdFx0dGhpcy5hdHRycy5yYXRpbyA9IGlzTnVtYmVyKHJhdGlvKSA/IHJhdGlvIDogdGhpcy5hdHRycy5yYXRpbztcblx0XHRcdHRoaXMuYXR0cnMuc2l6ZSA9IGlzTnVtYmVyKHNpemUpID8gc2l6ZSA6IHRoaXMuYXR0cnMuc2l6ZTtcblx0XHRcdHRoaXMucGFuZWwuY2xhc3NOYW1lID0gdGhpcy5jbGFzc05hbWU7XG5cdFx0fVxuXG5cdFx0dGltZSgpIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdC8vIGRlYnVnZ2VyO1xuXHRcdFx0XHRjb25zdCBtID0gdGhpcy5wYXJlbnQuc3RhdGUudXJpLm1hdGNoKFkucmVnLnRpbWUpLnNsaWNlKDEsIDQpO1xuXHRcdFx0XHRyZXR1cm4gKCgrbVswXSB8fCAwKSAqIDYwICogNjApICsgKCgrbVsxXSB8fCAwKSAqIDYwKSArICgrbVsyXSB8fCAwKTtcblx0XHRcdH0gY2F0Y2ggKGUpIHsgcmV0dXJuIDA7IH1cblx0XHR9XG5cblx0XHRmaW5kVHlwZSgpIHtcblx0XHRcdGlmICh0aGlzLnBhcmVudC5zdGF0ZS5zaXRlID09PSAnaHRtbDUtYXVkaW8nKSB7IHJldHVybiAnYXVkaW8nOyB9XG5cdFx0XHRpZiAodGhpcy5wYXJlbnQuc2l0ZS52aWRlb1RhZykgeyByZXR1cm4gJ3ZpZGVvJzsgfVxuXHRcdFx0cmV0dXJuICdpZnJhbWUnO1xuXHRcdH1cblxuXHRcdHN3aXRjaE9mZigpIHtcblx0XHRcdC8vIGNvbnNvbGUubG9nKCdyZW1vdmVkIG1lZGlhJyk7XG5cblx0XHRcdGlmICh0aGlzLm1lZGlhLnBhdXNlKSB7XG5cdFx0XHRcdC8vIGNvbnNvbGUubG9nKCdwYXVzaW5nJyk7XG5cdFx0XHRcdHRoaXMubWVkaWEucGF1c2UoKTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0dGhpcy5zd2l0Y2hlci5yZW1vdmVDaGlsZCh0aGlzLmNoYW5uZWwpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHQvLyBjb25zb2xlLmVycm9yKGUpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5tb2RlID0gJ29mZic7XG5cdFx0fVxuXG5cdFx0c3dpdGNoT24oKSB7XG5cdFx0XHRpZiAodGhpcy5hdHRycy5zaXplID09PSAwKSB7XG5cdFx0XHRcdHRoaXMuYXR0cnMuc2l6ZSA9IFkudXNlci5wcmVmZXJlbmNlcy5zaXplO1xuXHRcdFx0XHR0aGlzLnBhcmVudC5yZXNldFZpZXdTaXplKCk7XG5cdFx0XHR9XG5cdFx0XHQvLyBjb25zb2xlLmxvZygnc3dpdGNoIHRvIG1lZGlhJyk7XG5cdFx0XHR0aGlzLnN3aXRjaGVyLmFwcGVuZENoaWxkKHRoaXMuY2hhbm5lbCk7XG5cdFx0XHR0aGlzLnN3aXRjaGVyLmRhdGFzZXQuc3RhbmRieSA9IGZhbHNlO1xuXHRcdFx0dGhpcy5tb2RlID0gJ29uJztcblx0XHR9XG5cblx0XHRzd2l0Y2hTdGFuZGJ5KCkge1xuXHRcdFx0Ly8gY29uc29sZS5sb2coJ3N3aXRjaCB0byBzdGFuZGJ5Jyk7XG5cdFx0XHR0aGlzLnN3aXRjaE9mZigpO1xuXHRcdFx0dGhpcy5zd2l0Y2hlci5kYXRhc2V0LnN0YW5kYnkgPSB0cnVlO1xuXHRcdFx0dGhpcy5tb2RlID0gJ3N0YW5kYnknO1xuXHRcdH1cblxuXHRcdGlzU3RhbmRieSgpIHtcblx0XHRcdHJldHVybiB0aGlzLm1vZGUgPT09ICdzdGFuZGJ5Jztcblx0XHR9XG5cdH1cblxuXHRQbGF5ZXIuc291cmNlcyA9IHtcblx0XHRpZnJhbWU6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHRjb25zdCBrZXkgPSBZLkRCLnNpdGVzW2RhdGEuc2l0ZV0ua2V5O1xuXG5cdFx0XHRyZXR1cm4gW1xuXHRcdFx0XHR7IHR5cGU6ICd0ZXh0L2h0bWwnLCBzcmM6IFkuREIuc2l0ZXNbZGF0YS5zaXRlXS5lbWJlZC5yZXBsYWNlKCcla2V5JywgZGF0YVtrZXldKSB9XG5cdFx0XHRdO1xuXHRcdH0sXG5cdFx0J2h0bWw1LWF1ZGlvJzogZnVuY3Rpb24gKHsgdXJpIH0pIHtcblx0XHRcdHJldHVybiBbXG5cdFx0XHRcdHsgdHlwZTogJ2F1ZGlvL21wMycsIHNyYzogdXJpIH1cblx0XHRcdF07XG5cdFx0fSxcblx0XHRodG1sNTogZnVuY3Rpb24gKHsgdXJpIH0pIHtcblx0XHRcdC8vIGF0dGFjaGluZyB0aGUgdHlwZSBhcyBlaXRoZXIgbXA0IG9yIHdlYm1cblxuXHRcdFx0aWYgKC8oPzp3ZWJtKS8udGVzdCh1cmkpKSB7XG5cdFx0XHRcdHJldHVybiBbXG5cdFx0XHRcdFx0eyB0eXBlOiAndmlkZW8vd2VibScsIHNyYzogdXJpIH1cblx0XHRcdFx0XTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIFtcblx0XHRcdFx0eyB0eXBlOiAndmlkZW8vbXA0Jywgc3JjOiB1cmkgfSxcblx0XHRcdFx0eyB0eXBlOiAndmlkZW8vd2VibScsIHNyYzogdXJpIH0sXG5cdFx0XHRcdHsgdHlwZTogJ3ZpZGVvL29nZzsgY29kZWNzPVwidGhlb3JhLCB2b3JiaXNcIicsIHNyYzogdXJpIH1cblx0XHRcdF07XG5cdFx0fSxcblx0XHRpbWd1cjogZnVuY3Rpb24gKHsgaWQgfSkge1xuXHRcdFx0Y29uc3Qgc3JjID0gWS5EQi5zaXRlcy5pbWd1ci5lbWJlZC5yZXBsYWNlKCcla2V5JywgaWQpO1xuXG5cdFx0XHRyZXR1cm4gW1xuXHRcdFx0XHR7IHR5cGU6ICd2aWRlby93ZWJtJywgc3JjOiBgJHtzcmN9LndlYm1gIH0sXG5cdFx0XHRcdHsgdHlwZTogJ3ZpZGVvL21wNCcsIHNyYzogYCR7c3JjfS5tcDRgIH1cblx0XHRcdF07XG5cdFx0fSxcblx0XHR5b3V0dWJlOiBmdW5jdGlvbiAoeyBpZCB9LCB7IHF1YWxpdHksIHN0YXJ0IH0pIHtcblx0XHRcdGNvbnN0IHBhcmFtcyA9IGA/aHRtbDU9MSZ2ZXJzaW9uPTMmbW9kZXN0YnJhbmRpbmc9MSZyZWw9MCZzaG93aW5mbz0xJnZxPSR7cXVhbGl0eX0maXZfbG9hZF9wb2xpY3k9JHtZLnVzZXIucHJlZmVyZW5jZXMueXRfYW5ub3RhdGlvbn0mc3RhcnQ9JHtzdGFydH0mcmVsPTBgO1xuXG5cdFx0XHRyZXR1cm4gW1xuXHRcdFx0XHR7IHR5cGU6ICd0ZXh0L2h0bWwnLCBzcmM6IFkuREIuc2l0ZXMueW91dHViZS5lbWJlZC5yZXBsYWNlKCcla2V5JywgaWQpICsgcGFyYW1zIH1cblx0XHRcdF07XG5cdFx0fVxuXHR9O1xuXG5cdFBsYXllci5kaW1tcyA9IHtcblx0XHRyYXRpb3M6IHtcblx0XHRcdDE6ICdzZCcsXG5cdFx0XHQyOiAnaGQnLFxuXHRcdFx0MzogJ3ByJ1xuXHRcdH0sXG5cdFx0c2l6ZXM6IHtcblx0XHRcdDA6ICdoJyxcblx0XHRcdDI0MDogJ3MnLFxuXHRcdFx0MzYwOiAnbScsXG5cdFx0XHQ0ODA6ICdsJyxcblx0XHRcdDcyMDogJ3hsJ1xuXHRcdH0sXG5cdFx0YXNwZWN0czoge1xuXHRcdFx0MTogNCAvIDMsXG5cdFx0XHQyOiAxNiAvIDksXG5cdFx0XHQzOiAxNiAvIDlcblx0XHR9XG5cdH07XG5cblx0UGxheWVyLnF1YWxpdGllcyA9IHtcblx0XHQyNDA6ICdzbWFsbCcsXG5cdFx0MzYwOiAnbWVkaXVtJyxcblx0XHQ0ODA6ICdsYXJnZScsXG5cdFx0NzIwOiAnaGQ3MjAnLFxuXHRcdDEwODA6ICdoZDEwODAnLFxuXHRcdDEwODE6ICdoaWdocmVzJ1xuXHR9O1xuXG5cdFBsYXllci5jc3MgPSB7XG5cdFx0aXRlbTogZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcblx0XHRcdGlmIChpc051bWJlcih2YWx1ZSkpIHtcblx0XHRcdFx0dmFsdWUgKz0gJ3B4Jztcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGBcXHQke2tleX06ICR7dmFsdWV9O1xcbmA7XG5cdFx0fSxcblx0XHRpdGVyOiBmdW5jdGlvbiAoY3NzLCBjc3NFbnRyaWVzKSB7XG5cdFx0XHRfLm8oY3NzRW50cmllcywgKGtleSwgdmFsdWUpID0+IHtcblx0XHRcdFx0Y3NzLnB1c2goUGxheWVyLmNzcy5pdGVtKGtleSwgdmFsdWUpKTtcblx0XHRcdH0pO1xuXHRcdFx0Y3NzLnB1c2goJ30nKTtcblx0XHR9LFxuXHRcdGdlbmVyYXRvcjogZnVuY3Rpb24gKCkge1xuXHRcdFx0Y29uc3QgY3NzID0gW107XG5cblx0XHRcdF8ubyh0aGlzLnNpemVzLCAoc2l6ZSwgc2l6ZXMpID0+IHtcblx0XHRcdFx0Xy5vKHNpemVzLCAoZGltbSwga2V5cykgPT4ge1xuXHRcdFx0XHRcdGNzcy5wdXNoKGBcXG4ueXRtX3BhbmVsLSR7c2l6ZX0ueXRtX3BhbmVsLSR7ZGltbX0gLnl0bV9wYW5lbF9zaXplIHtcXG5gKTtcblx0XHRcdFx0XHRQbGF5ZXIuY3NzLml0ZXIoY3NzLCBrZXlzKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0Ly8gYWRkIHNpdGUgb3ZlcnJpZGVzXG5cdFx0XHRfLm8odGhpcy5zaXRlcywgKHNpdGUsIGRhdGEpID0+IHtcblx0XHRcdFx0Xy5vKGRhdGEsIChzZXR0aW5nLCBrZXlzKSA9PiB7XG5cdFx0XHRcdFx0aWYgKHNldHRpbmcgPT09ICdhbGwnKSB7XG5cdFx0XHRcdFx0XHRjc3MucHVzaChgXFxuLnl0bV9zaXRlXyR7c2l0ZX0gLnl0bV9wYW5lbF9zaXplIHtcXG5gKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Y3NzLnB1c2goYFxcbi55dG1fc2l0ZV8ke3NpdGV9IC55dG1fcGFuZWwtJHtzZXR0aW5nfSAueXRtX3BhbmVsX3NpemUge1xcbmApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRQbGF5ZXIuY3NzLml0ZXIoY3NzLCBrZXlzKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0cmV0dXJuIGNzcy5qb2luKCcnKTtcblx0XHR9LFxuXHRcdHNpemVzOiAoKCkgPT4ge1xuXHRcdFx0Y29uc3QgbWVyZ2UgPSB7fTtcblxuXHRcdFx0Xy5vKFBsYXllci5kaW1tcy5zaXplcywgKG51bSwgc2l6ZSkgPT4ge1xuXHRcdFx0XHRpZiAobnVtID49IDApIHtcblx0XHRcdFx0XHRtZXJnZVtzaXplXSA9IHt9O1xuXG5cdFx0XHRcdFx0Xy5vKFBsYXllci5kaW1tcy5yYXRpb3MsIChrLCByYXRpbykgPT4ge1xuXHRcdFx0XHRcdFx0aWYgKHJhdGlvID09PSAncHInKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IHcgPSBNYXRoLmZsb29yKG51bSAqIDAuOTUpOyAvLyBzbWFsbGVyIHRoYW4gdGhlIG5vcm1hbCBzaXplc1xuXHRcdFx0XHRcdFx0XHRtZXJnZVtzaXplXVtyYXRpb10gPSB7XG5cdFx0XHRcdFx0XHRcdFx0d2lkdGg6IHcsXG5cdFx0XHRcdFx0XHRcdFx0aGVpZ2h0OiBNYXRoLmZsb29yKHcgKiBQbGF5ZXIuZGltbXMuYXNwZWN0c1trXSlcblx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdG1lcmdlW3NpemVdW3JhdGlvXSA9IHtcblx0XHRcdFx0XHRcdFx0XHR3aWR0aDogTWF0aC5mbG9vcihudW0gKiBQbGF5ZXIuZGltbXMuYXNwZWN0c1trXSksXG5cdFx0XHRcdFx0XHRcdFx0aGVpZ2h0OiBudW1cblx0XHRcdFx0XHRcdFx0fTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdHJldHVybiBtZXJnZTtcblx0XHR9KSgpLFxuXHRcdHNpdGVzOiB7IC8vIGN1c3RvbSBzaXplcyBwZXIgc2l0ZVxuXHRcdFx0c291bmRjbG91ZDoge1xuXHRcdFx0XHRhbGw6IHtcblx0XHRcdFx0XHRoZWlnaHQ6ICcxMThweCAhaW1wb3J0YW50J1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0dmluZToge1xuXHRcdFx0XHRzOiB7XG5cdFx0XHRcdFx0d2lkdGg6IDI0MCxcblx0XHRcdFx0XHRoZWlnaHQ6IDI0MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRtOiB7XG5cdFx0XHRcdFx0d2lkdGg6IDM2MCxcblx0XHRcdFx0XHRoZWlnaHQ6IDM2MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRsOiB7XG5cdFx0XHRcdFx0d2lkdGg6IDQ4MCxcblx0XHRcdFx0XHRoZWlnaHQ6IDQ4MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR4bDoge1xuXHRcdFx0XHRcdHdpZHRoOiA3MjAsXG5cdFx0XHRcdFx0aGVpZ2h0OiA3MjBcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHRQbGF5ZXIubWFrZU1lZGlhID0ge1xuXHRcdCRjc3M6IGZ1bmN0aW9uICh0eXBlKSB7XG5cdFx0XHRyZXR1cm4gYHl0bV9wYW5lbF9tZWRpYSB5dG1fcGFuZWxfc2l6ZSB5dG1fYmxvY2sgeXRtXyR7dHlwZX1gO1xuXHRcdH0sXG5cdFx0dmlkZW86IGZ1bmN0aW9uICh7IGF0dHJzIH0pIHtcblx0XHRcdGNvbnN0IHZpZGVvID0gXy5lKCd2aWRlbycsIHtcblx0XHRcdFx0Y29udHJvbHM6IHRydWUsXG5cdFx0XHRcdGF1dG9wbGF5OiBmYWxzZSxcblx0XHRcdFx0bG9vcDogdHJ1ZSxcblx0XHRcdFx0Y2xhc3NOYW1lOiB0aGlzLiRjc3MoJ3ZpZGVvJyksXG5cdFx0XHRcdCRhbGxvd3NjcmlwdGFjY2VzczogdHJ1ZSxcblx0XHRcdFx0cHJlbG9hZDogJ21ldGFkYXRhJ1xuXHRcdFx0fSk7XG5cblx0XHRcdGNvbnN0IGxpbmtzID0gW107XG5cblx0XHRcdGF0dHJzLnNvdXJjZXMuZm9yRWFjaCgoeyBzcmMsIHR5cGUgfSkgPT4ge1xuXHRcdFx0XHRfLmUoJ3NvdXJjZScsIHsgc3JjLCAkdHlwZTogdHlwZSB9LCB2aWRlbyk7XG5cblx0XHRcdFx0bGlua3MucHVzaChgPGEgaHJlZj1cIiR7c3JjfVwiPiR7c3JjfTwvYT5gKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRfLmUoJ3AnLCB7IGlubmVySFRNTDogYENvdWxkIG5vdCBsb2FkIHNvdXJjZShzKTogJHtsaW5rcy5qb2luKCc8YnIgLz4nKX1gIH0sIHZpZGVvKTtcblxuXHRcdFx0cmV0dXJuIHZpZGVvO1xuXHRcdH0sXG5cdFx0aWZyYW1lOiBmdW5jdGlvbiAoeyBhdHRycyB9KSB7XG5cdFx0XHRyZXR1cm4gXy5lKCdpZnJhbWUnLCB7XG5cdFx0XHRcdCRhbGxvd2Z1bGxzY3JlZW46IHRydWUsXG5cdFx0XHRcdCRyZWZlcnJlcnBvbGljeTogJ25vLXJlZmVycmVyJyxcblx0XHRcdFx0Ly8gJHNhbmRib3g6ICdhbGxvdy1zYW1lLW9yaWdpbiBhbGxvdy1zY3JpcHRzIGFsbG93LXBvcHVwcycsXG5cdFx0XHRcdCR0eXBlOiBhdHRycy5zb3VyY2VzWzBdLnR5cGUsXG5cdFx0XHRcdHNyYzogYXR0cnMuc291cmNlc1swXS5zcmMsXG5cdFx0XHRcdGNsYXNzTmFtZTogdGhpcy4kY3NzKCdpZnJhbWUnKVxuXHRcdFx0fSk7XG5cdFx0fSxcblx0XHRhdWRpbzogZnVuY3Rpb24gKHsgYXR0cnMgfSkge1xuXHRcdFx0cmV0dXJuIF8uZSgnYXVkaW8nLCB7XG5cdFx0XHRcdHNyYzogYXR0cnMuc291cmNlc1swXS5zcmMsXG5cdFx0XHRcdCR0eXBlOiBhdHRycy5zb3VyY2VzWzBdLnR5cGVcblx0XHRcdH0pO1xuXHRcdH1cblx0fTtcblxuXHQvKiogUyBDIFIgTyBMIEwgQ0xBU1Ncblx0ICogV2luZG93LVNjcm9sbCBFdmVudCBIZWxwZXJcblx0ICovXG5cdGNsYXNzIFNjcm9sbCB7XG5cdFx0Y29uc3RydWN0b3Ioc2VsZWN0b3IsIGNiLCBkZWxheSA9IDUwMCkge1xuXHRcdFx0dGhpcy5zZWxlY3RvciA9IHNlbGVjdG9yO1xuXHRcdFx0dGhpcy5jYiA9IGNiO1xuXHRcdFx0dGhpcy5tb25pdG9yID0gdGhpcy5tb25pdG9yLmJpbmQodGhpcyk7XG5cblx0XHRcdC8vIGNvbnNvbGUubG9nKCdZVE1BLlNjcm9sbCBNb25pdG9yOiAnLCBzZWxlY3Rvcik7XG5cdFx0XHR0aGlzLmJvdW5kID0gZGVib3VuY2UodGhpcy5tb25pdG9yLCBkZWxheSk7XG5cblx0XHRcdHRoaXMuYm91bmQoKTtcblx0XHRcdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLmJvdW5kLCBmYWxzZSk7XG5cdFx0fVxuXG5cdFx0c3RvcCgpIHtcblx0XHRcdC8vIGNvbnNvbGUubG9nKCdjbGVhciBzY3JvbGw6ICcsIHRoaXMuc2VsZWN0b3IpO1xuXHRcdFx0d2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuYm91bmQpO1xuXHRcdH1cblxuXHRcdG1vbml0b3IoKSB7XG5cdFx0XHRfLnModGhpcy5zZWxlY3RvciwgdGhpcy5jYik7XG5cdFx0fVxuXHR9XG5cblx0U2Nyb2xsLnZpc2libGUgPSBlbCA9PiB7XG5cdFx0Y29uc3QgYm91bmQgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRyZXR1cm4gKGJvdW5kLnRvcCA+PSAwICYmIGJvdW5kLnRvcCA8PSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0KTtcblx0fTtcblxuXHRTY3JvbGwudmlzaWJsZUFsbCA9IChlbCwgb2Zmc2V0KSA9PiB7XG5cdFx0Y29uc3QgYm91bmQgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRjb25zdCBoZWlnaHQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuXHRcdG9mZnNldCA9IGlzTnVtYmVyKG9mZnNldCkgPyArb2Zmc2V0IDogMDtcblx0XHRyZXR1cm4gKChib3VuZC5ib3R0b20gKyBvZmZzZXQgPj0gMClcblx0XHRcdCYmIChib3VuZC50b3AgPD0gaGVpZ2h0ICsgb2Zmc2V0IHx8IGJvdW5kLmJvdHRvbSA8PSBoZWlnaHQgLSBvZmZzZXQpKTtcblx0fTtcblxuXHQvKiogUmV0dXJucyAxLCAwLCAtMSB3aGVuIGVsMSBpcyBhYm92ZSwgZXhhY3RseSB0aGUgc2FtZSwgb3IgYmVsb3cgZWwyICovXG5cdFNjcm9sbC5jb21wYXJlID0gKGVsMSwgZWwyKSA9PiB7XG5cdFx0Y29uc3QgYSA9IGVsMS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS55O1xuXHRcdGNvbnN0IGIgPSBlbDIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkueTtcblxuXHRcdGlmIChhIDwgYikgeyByZXR1cm4gMTsgfVxuXHRcdGlmIChhID09PSBiKSB7IHJldHVybiAwOyB9XG5cdFx0cmV0dXJuIC0xO1xuXHR9O1xuXG5cblx0WS5tYWluKCk7XG59KSgpO1xuIiwiaWYgKCFFbGVtZW50LnByb3RvdHlwZS5tYXRjaGVzKVxuXHRFbGVtZW50LnByb3RvdHlwZS5tYXRjaGVzID0gRWxlbWVudC5wcm90b3R5cGUubXNNYXRjaGVzU2VsZWN0b3IgfHwgRWxlbWVudC5wcm90b3R5cGUud2Via2l0TWF0Y2hlc1NlbGVjdG9yO1xuXG5pZiAoIUVsZW1lbnQucHJvdG90eXBlLmNsb3Nlc3QpIHtcblx0RWxlbWVudC5wcm90b3R5cGUuY2xvc2VzdCA9IGZ1bmN0aW9uIChzKSB7XG5cdFx0dmFyIGVsID0gdGhpcztcblx0XHRpZiAoIWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jb250YWlucyhlbCkpIHJldHVybiBudWxsO1xuXHRcdGRvIHtcblx0XHRcdGlmIChlbC5tYXRjaGVzKHMpKSByZXR1cm4gZWw7XG5cdFx0XHRlbCA9IGVsLnBhcmVudEVsZW1lbnQgfHwgZWwucGFyZW50Tm9kZTtcblx0XHR9IHdoaWxlIChlbCAhPT0gbnVsbCAmJiBlbC5ub2RlVHlwZSA9PT0gMSk7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH07XG59XG5cbmV4cG9ydCBjb25zdCBpc051bWJlciA9IG4gPT4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xuXG5leHBvcnQgY29uc3QgcmVtb3ZlU2VhcmNoID0gKHVyaSwga2VlcEhhc2gpID0+IHtcblx0Ly8gcmVtb3ZlcyBzZWFyY2ggcXVlcnkgZnJvbSBhIHVyaVxuXHRjb25zdCBzID0gdXJpLmluZGV4T2YoJz8nKTtcblx0Y29uc3QgaCA9IHVyaS5pbmRleE9mKCcjJyk7XG5cdGxldCBoYXNoID0gJyc7XG5cdGlmIChzID4gLTEpIHtcblx0XHRpZiAoa2VlcEhhc2ggJiYgaCA+IC0xKSB7XG5cdFx0XHRoYXNoID0gdXJpLnN1YnN0cihoKTtcblx0XHR9XG5cdFx0dXJpID0gdXJpLnN1YnN0cigwLCBzKSArIGhhc2g7XG5cdH1cblx0cmV0dXJuIHVyaTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudCBIVE1MIGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudHMgU3BhY2UtIG9yIGNvbWEtc2VwYXJhdGVkIHN0cmluZyBvZiBvbmUgb3IgbW9yZSB0eXBlcywgZWcgXCJjbGljayBkYmxjbGlja1wiXG4gKiBAcGFyYW0ge3N0cmluZ30gc2VsZWN0b3IgQ1NTIHNlbGVjdG9yIGZvciB0aGUgZWxlbWVudHMgdG8gdHJpZ2dlciB0aGUgZXZlbnQgb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIEEgY2FsbGJhY2tcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gY2FuY2VsIENhbmNlbFxuICovXG5leHBvcnQgY29uc3Qgb24gPSAoZWxlbWVudCwgZXZlbnRzLCBzZWxlY3RvciwgbGlzdGVuZXIsIGNhbmNlbCA9IHRydWUpID0+IHtcblx0ZXZlbnRzID0gZXZlbnRzLnNwbGl0KC8oPzpcXHMrfCwpLykuZmlsdGVyKGYgPT4gZik7XG5cblx0aWYgKGV2ZW50cy5sZW5ndGggPT09IDApIHJldHVybjtcblxuXHRjb25zdCBmbiA9IGV2ZW50ID0+IHtcblx0XHRjb25zdCBmb3VuZCA9IGV2ZW50LnRhcmdldC5jbG9zZXN0KHNlbGVjdG9yKTtcblx0XHRpZiAoZm91bmQpIGxpc3RlbmVyLmNhbGwoZm91bmQsIGV2ZW50KTtcblx0fTtcblxuXHRldmVudHMuZm9yRWFjaCh0eXBlID0+IGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0eXBlLCBmbiwgY2FuY2VsKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZGVib3VuY2UgPSAoZm4sIGRlbGF5ID0gMjUwKSA9PiB7XG5cdGxldCB0aW1lb3V0O1xuXG5cdHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuXHRcdGNvbnN0IHRpbWVkID0gKCkgPT4ge1xuXHRcdFx0dGltZW91dCA9IG51bGw7XG5cdFx0XHRmbi5hcHBseSh0aGlzLCBhcmdzKTtcblx0XHR9O1xuXG5cdFx0d2luZG93LmNsZWFyVGltZW91dCh0aW1lb3V0KTtcblx0XHR0aW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQodGltZWQsIGRlbGF5KTtcblx0fTtcbn07IiwiLy8gSCBFIEwgUCBFIFIgSGFuZGxlXG5jb25zdCBfID0ge1xuXHRzOiAoc2VsZWN0b3IsIGNiKSA9PiB7XG5cdFx0Y29uc3QgZWxlbWVudHMgPSBfLnFzYShzZWxlY3Rvcik7XG5cdFx0ZWxlbWVudHMuc29tZSgoZWxlbWVudCwgaW5kZXgpID0+IGNiKGVsZW1lbnQsIGluZGV4LCBlbGVtZW50cykgPT09IGZhbHNlKTtcblx0fSxcblx0bzogZnVuY3Rpb24gKG9iamVjdCwgY2IpIHtcblx0XHRPYmplY3Qua2V5cyhvYmplY3QpLnNvbWUoa2V5ID0+IGNiKGtleSwgb2JqZWN0W2tleV0sIG9iamVjdCkgPT09IGZhbHNlKTtcblx0fSxcblx0ZTogZnVuY3Rpb24gKHQsIG8sIGUsIHApIHtcblx0XHRjb25zdCBjID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0KTtcblx0XHRfLm8obywgKGssIHYpID0+IHtcblx0XHRcdGNvbnN0IGIgPSBrLmNoYXJBdCgwKTtcblx0XHRcdGlmIChiID09PSAnXycpXG5cdFx0XHRcdGMuZGF0YXNldFtrLnN1YnN0cmluZygxKV0gPSB2O1xuXHRcdFx0ZWxzZSBpZiAoYiA9PT0gJyQnKVxuXHRcdFx0XHRjLnNldEF0dHJpYnV0ZShrLnN1YnN0cmluZygxKSwgdik7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdGNba10gPSB2O1xuXHRcdH0pO1xuXG5cdFx0aWYgKGUgJiYgcCkge1xuXHRcdFx0Yy5hcHBlbmRDaGlsZChlKTtcblx0XHR9IGVsc2UgaWYgKGUpIHtcblx0XHRcdGUuYXBwZW5kQ2hpbGQoYyk7XG5cdFx0fVxuXHRcdHJldHVybiBjO1xuXHR9LFxuXHRxc2E6IHNlbGVjdG9yID0+IEFycmF5LmZyb20oZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikpLFxuXHRjc3M6IGZ1bmN0aW9uICh0ZXh0KSB7XG5cdFx0aWYgKCF0aGlzLnN0eWxlKSB7XG5cdFx0XHR0aGlzLnN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblx0XHRcdHRoaXMuc3R5bGUudHlwZSA9ICd0ZXh0L2Nzcyc7XG5cdFx0XHRkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRoaXMuc3R5bGUpO1xuXHRcdH1cblx0XHR0aGlzLnN0eWxlLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGAke3RleHR9XFxuYCkpO1xuXHR9LFxuXHRqczogdCA9PiB7XG5cdFx0Y29uc3QgaiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuXHRcdGoudHlwZSA9ICd0ZXh0L2phdmFzY3JpcHQnO1xuXHRcdGpbL15odHRwcz86XFwvXFwvL2kudGVzdCh0KSA/ICdzcmMnIDogJ3RleHRDb250ZW50J10gPSB0O1xuXHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoaik7XG5cdH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IF87IiwiLy8gUyBUIE8gUiBBIEcgRSBIQU5ETEVcbmNvbnN0IHN0cmcgPSB7XG5cdE1BWDogNTAxMixcblx0b246IGZhbHNlLFxuXHR0ZXN0OiAoKSA9PiB7XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IGwgPSBsb2NhbFN0b3JhZ2U7XG5cdFx0XHRjb25zdCBjID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygxNikuc3Vic3RyKDIsIDgpO1xuXHRcdFx0bC5zZXRJdGVtKGMsIGMpO1xuXHRcdFx0cmV0dXJuIGwuZ2V0SXRlbShjKSA9PT0gYyA/ICFsLnJlbW92ZUl0ZW0oYykgOiBmYWxzZTtcblx0XHR9IGNhdGNoIChlKSB7IHJldHVybiBmYWxzZTsgfVxuXHR9LFxuXHRyZWFkOiAoa2V5KSA9PiB7XG5cdFx0dHJ5IHtcblx0XHRcdHJldHVybiBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKGtleSkpO1xuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdHJldHVybiBjb25zb2xlLmVycm9yKGAke2UubGluZU51bWJlcn06JHtlLm1lc3NhZ2V9YCk7XG5cdFx0fVxuXHR9LFxuXHRzYXZlOiAoa2V5LCB2YWwpID0+IHN0cmcub24gPyAhbG9jYWxTdG9yYWdlLnNldEl0ZW0oa2V5LCBKU09OLnN0cmluZ2lmeSh2YWwpKSA6IGZhbHNlLFxuXHR3aXBlOiBrZXkgPT4gc3RyZy5vbiA/ICFsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShrZXkpIDogZmFsc2UsXG5cdHplcm86IG8gPT4geyBmb3IgKGxldCBrIGluIG8pIHsgaWYgKG8uaGFzT3duUHJvcGVydHkoaykpIHsgcmV0dXJuIGZhbHNlOyB9IH0gcmV0dXJuIHRydWU7IH0sIC8vIGNoZWNrIGlmIHRoZSBvYmplY3QgaXMgZW1wdHlcblx0Z3JhYjogKGtleSwgZGVmKSA9PiB7IGNvbnN0IHMgPSBzdHJnLnJlYWQoa2V5KTsgcmV0dXJuIHN0cmcuemVybyhzKSA/IGRlZiA6IHM7IH0sXG5cdHNpemU6ICgpID0+IHtcblx0XHRsZXQgbGVuZ3RoID0gMDtcblx0XHRsZXQga2V5O1xuXHRcdHRyeSB7XG5cdFx0XHRmb3IgKGtleSBpbiB3aW5kb3cubG9jYWxTdG9yYWdlKSB7XG5cdFx0XHRcdGlmICh3aW5kb3cubG9jYWxTdG9yYWdlLmhhc093blByb3BlcnR5KGtleSkpIHtcblx0XHRcdFx0XHRsZW5ndGggKz0gd2luZG93LmxvY2FsU3RvcmFnZVtrZXldLmxlbmd0aDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdC8vIG5vIG1vcmUgc3BhY2Vcblx0XHR9XG5cdFx0cmV0dXJuIDMgKyAoKGxlbmd0aCAqIDE2KSAvICg4ICogMTAyNCkpO1xuXHR9LFxuXHRmdWxsOiAoKSA9PiB7XG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IGRhdGUgPSArKG5ldyBEYXRlKCkpO1xuXHRcdFx0bG9jYWxTdG9yYWdlLnNldEl0ZW0oZGF0ZSwgZGF0ZSk7XG5cdFx0XHRsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShkYXRlKTtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRpZiAoZS5uYW1lID09PSAnUXVvdGFFeGNlZWRlZEVycm9yJyB8fFxuXHRcdFx0XHRcdGUubmFtZSA9PT0gJ05TX0VSUk9SX0RPTV9RVU9UQV9SRUFDSEVEJykge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cdGluaXQ6ICgpID0+IHsgc3RyZy5vbiA9IHN0cmcudGVzdCgpOyB9XG59O1xuc3RyZy5pbml0KCk7XG5cbmV4cG9ydCBkZWZhdWx0IHN0cmc7IiwiaW1wb3J0IHN0cmcgZnJvbSAnLi9zdHJnJztcbmltcG9ydCBfIGZyb20gJy4vXyc7XG5cbi8vIFUgUCBEIEEgVCBFIEhBTkRMRVxuY29uc3QgdXBkYXRlID0ge1xuXHRuYW1lOiAneXRtYSEnLFxuXHR2ZXJzaW9uOiA4MDAwLFxuXHRrZXk6ICd1anNfWVRNQV9VUERUX0hSJyxcblx0Y2FsbGJhY2s6ICd5dG1hdXBkYXRlcicsXG5cdHBhZ2U6ICdodHRwczovL2dyZWFzeWZvcmsub3JnL3NjcmlwdHMvMTAyMy15b3V0dWJlLW1lLWFnYWluJyxcblx0anNvbjogJ2h0dHBzOi8vaGF0ZXJhZGlvLmdpdGh1Yi5pby95dG1hL3VwZGF0ZS5qc29uJyxcblx0aW50ZXJ2YWw6IDcsXG5cdGRheTogKG5ldyBEYXRlKCkpLmdldFRpbWUoKSxcblx0c2hvdzogZmFsc2UsXG5cdHRpbWU6ICgpID0+IG5ldyBEYXRlKHVwZGF0ZS5kYXkgKyAoMTAwMCAqIDYwICogNjAgKiAyNCAqIHVwZGF0ZS5pbnRlcnZhbCkpLmdldFRpbWUoKSxcblx0bm90aWZpY2F0aW9uOiAoeyB2ZXJzaW9uLCBwYWdlIH0pID0+IHtcblx0XHRpZiAodXBkYXRlLnZlcnNpb24gPCB2ZXJzaW9uKSB7XG5cdFx0XHRzdHJnLnNhdmUodXBkYXRlLmtleSwgeyBkYXRlOiB1cGRhdGUudGltZSgpLCB2ZXJzaW9uLCBwYWdlIH0pO1xuXHRcdFx0dXBkYXRlLmxpbmsoKTtcblx0XHR9XG5cdH0sXG5cdGxpbms6ICgpID0+IHtcblx0XHRpZiAodXBkYXRlLnNob3cpIHsgcmV0dXJuOyB9XG5cdFx0dXBkYXRlLnNob3cgPSB0cnVlO1xuXG5cdFx0Y29uc3QgeyBwYWdlIH0gPSBzdHJnLnJlYWQodXBkYXRlLmtleSk7XG5cdFx0Y29uc3QgbGluayA9IGBcblx0XHRcdFx0PGEgaHJlZj1cIiR7cGFnZSB8fCB1cGRhdGUucGFnZX1cIiBpZD11cGRhdGV2MyB0aXRsZT1VcGRhdGUgdGFyZ2V0PV9ibGFuaz5cblx0XHRcdFx0XHRBbiB1cGRhdGUgZm9yICR7dXBkYXRlLm5hbWV9IGlzIGF2YWlsYWJsZS5cblx0XHRcdFx0PC9hPmA7XG5cblx0XHRfLmNzcyh1cGRhdGUuY3NzKTtcblx0XHRkb2N1bWVudC5ib2R5Lmluc2VydEFkamFjZW50SFRNTCgnYmVmb3JlZW5kJywgbGluayk7XG5cdFx0Xy5vbihkb2N1bWVudC5ib2R5LCAnY2xpY2snLCAnI3VwZGF0ZXYzJywgZSA9PiBlLnRhcmdldC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnKTtcblx0fSxcblx0Y2hlY2s6IChvcHQpID0+IHtcblx0XHRpZiAoIXN0cmcub24pIHsgcmV0dXJuOyB9XG5cdFx0aWYgKHdpbmRvdy5jaHJvbWUgJiYgd2luZG93LmNocm9tZS5leHRlbnNpb24pIHsgcmV0dXJuOyB9XG5cdFx0Y29uc3Qgc3RvcmVkID0gc3RyZy5yZWFkKHVwZGF0ZS5rZXkpO1xuXHRcdGxldCBwYWdlO1xuXG5cdFx0aWYgKG9wdCB8fCAhc3RvcmVkIHx8IHN0b3JlZC5kYXRlIDwgdXBkYXRlLmRheSkge1xuXHRcdFx0cGFnZSA9IChzdG9yZWQgJiYgc3RvcmVkLnBhZ2UpIHx8IHVwZGF0ZS5wYWdlO1xuXHRcdFx0c3RyZy5zYXZlKHVwZGF0ZS5rZXksIHsgZGF0ZTogdXBkYXRlLnRpbWUoKSwgdmVyc2lvbjogdXBkYXRlLnZlcnNpb24sIHBhZ2UgfSk7XG5cdFx0XHRmZXRjaCh1cGRhdGUuanNvbikudGhlbihyZXMgPT4gcmVzLmpzb24oKSkudGhlbih1cGRhdGUubm90aWZpY2F0aW9uKTtcblx0XHR9IGVsc2UgaWYgKHVwZGF0ZS52ZXJzaW9uIDwgc3RvcmVkLnZlcnNpb24pIHtcblx0XHRcdHVwZGF0ZS5saW5rKCk7XG5cdFx0fVxuXHR9LFxuXHRjc3M6ICcjdXBkYXRlcjMsI3VwZGF0ZXIzOnZpc2l0ZWR7Ym94LXNoYWRvdzoxcHggMXB4IDZweCAjNzc3Njtib3JkZXItYm90dG9tOjNweCBzb2xpZCAjZTM5YzJkO2N1cnNvcjpwb2ludGVyO2NvbG9yOiM1NTU7Zm9udC1mYW1pbHk6c2Fucy1zZXJpZjtmb250LXNpemU6MTJweDtmb250LXdlaWdodDo3MDA7dGV4dC1hbGlnbjpqdXN0aWZ5O3Bvc2l0aW9uOmZpeGVkO3otaW5kZXg6OTk5OTk5O3JpZ2h0OjEwcHg7dG9wOjEwcHg7YmFja2dyb3VuZDojZWJlYmViIHVybChkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSFpwWlhkQ2IzZzlJakFnTFRNMElEVXhNaUExTVRJaVBqeHdZWFJvSUdacGJHdzlJaU5sTldWaVpqVWlJR1E5SWsweU56QXVOemd4SURjdU5VZ3lOREV1TWpKTU9DNDJOaUEwTVRBdU16QTFiREUwTGpjNE1TQXlOUzQyTURGSU5EZzRMalUyYkRFMExqYzRMVEkxTGpZd01YcHRNQ0F3SWk4K1BIQmhkR2dnWm1sc2JEMGlJMlk0WlRnMk9DSWdaRDBpVFRRNExqY3dOeUEwTURBdU9UTTBUREkxTXk0eE1qa2dORFl1T0RZM2FEVXVOelF5YkRJd05DNDBNaklnTXpVMExqQTJOMk10TVM0eU56Y2dNaTR5TVMweExqVTVOQ0F5TGpjMk5TMHlMamczTVNBMExqazNOa2cxTVM0MU56aGpMVEV1TWpjM0xUSXVNakV0TVM0MU9UUXRNaTQzTmpVdE1pNDROekV0TkM0NU56WjZiVEFnTUNJdlBqeHdZWFJvSUdacGJHdzlJaU5sTXpsak1tUWlJR1E5SWsweU56VXVPVGsySURjMkxqVXlOMnd0TVRjdU1USTFMVEk1TGpZMmFDMDFMamMwTWt3ME9DNDNNRGNnTkRBd0xqa3pOR014TGpJM055QXlMakl4SURFdU5UazBJREl1TnpZMUlESXVPRGN4SURRdU9UYzJhRE01TGprNU5tTXRNUzR5TnpjdE1pNHlNUzB4TGpVNU55MHlMamMyTlMweUxqZzNMVFF1T1RjMmVtMHdJREFpTHo0OGNHRjBhQ0JtYVd4c1BTSWpZMkZrT0dWaElpQmtQU0pOTWpjMUxqazVOaUF4Tmk0MU16Vk1NamN3TGpjNE1TQTNMalZJTWpReExqSXlURGd1TmpZZ05ERXdMak13TldNMkxqVTJOeUF4TVM0ek56a2dPQzR5TVRFZ01UUXVNakl5SURFMExqYzRNU0F5TlM0Mk1ERm9Nemt1T1RrMll5MDJMalUzTFRFeExqTTNPUzA0TGpJeE5DMHhOQzR5TWpJdE1UUXVOemd0TWpVdU5qQXhlbTB3SURBaUx6NDhjR0YwYUNCbWFXeHNQU0lqTnpJNE5qbGxJaUJrUFNKTk1qY3dMamcxTlNBek1ESXVORFUzYUMweU9TNDNNV010TXk0d01EUXRNeTR3TURRdE5DNDJPVEl0TkM0Mk9EY3ROeTQyT1RZdE55NDJPVEZXTVRZekxqZzJNMmcwTlM0eE1ESjJNVE13TGprd00yTXRNeTR3TURnZ015NHdNRFF0TkM0Mk9USWdOQzQyT0RjdE55NDJPVFlnTnk0Mk9URjZiVEFnTUNJdlBqeHdZWFJvSUdacGJHdzlJaU0xTXpZeU56VWlJR1E5SWsweU5UTXVORFVnTVRZekxqZzJNMmd0TWpCMk1UTXdMamt3TTJNekxqQXdNeUF6TGpBd05DQTBMalk1SURRdU5qZzNJRGN1TmprMUlEY3VOamt4YURFNUxqazVObXd0Tnk0Mk9USXROeTQyT1RGNmJUQWdNQ0l2UGp4d1lYUm9JR1pwYkd3OUlpTTNNamcyT1dVaUlHUTlJazB5TXpNdU5EVWdNek13TGpneE0yZzBOUzR4ZGpRMUxqRXdNV2d0TkRVdU1YcHRNQ0F3SWk4K1BIQmhkR2dnWm1sc2JEMGlJelV6TmpJM05TSWdaRDBpVFRJek15NDBOU0F6TXpBdU9ERXphREl3ZGpRMUxqRXdNV2d0TWpCNmJUQWdNQ0l2UGp4d1lYUm9JR1pwYkd3OUlpTm1abVlpSUdROUlrMHlOelV1T1RrMklERTBNUzR6TmpkSU1qWXhkaTB4TldneE5DNDVPVFo2YlMweU5DNDVPVFlnTUdndE1UVjJMVEUxYURFMWVtMHdJREFpTHo0OGNHRjBhQ0JrUFNKTk5EQXdMalF6SURJeE55NHdOVGxzTFRFeUxqazRPU0EzTGpWTU5EazBMalk0SURReE1DNHpNRFZzTFRFd0xqUTFJREU0TGpFd01VZ3lOeTQzTjJ3dE1UQXVORFUwTFRFNExqRXdNVXd5TkRVdU5UUTJJREUxYURJd0xqa3dOMnd4TURjdU1qTTRJREU0TlM0M05EWWdNVEl1T1RnNUxUY3VOVXd5TnpVdU1URXpJREJvTFRNNExqSXlNa3d3SURReE1DNHpNRFZzTVRrdU1URWdNek11TVRBeGFEUTNNeTQzTnpkTU5URXlJRFF4TUM0ek1EVjZiVEFnTUNJdlBqeHdZWFJvSUdROUlrMHhNalV1TVRVMklEUXhNeTQwTURaSU5EWTBMamMxYkRjdU1qQXpMVEV5TGpRM01pMHlNRGd1TnpVdE16WXhMalUyTjJndE1UUXVOREEyVERRd0xqQTBOeUEwTURBdU9UTTBiRGN1TWlBeE1pNDBOekpvTlRjdU9URXpWak01T0M0ME1VZzFPQzQ0TWpSTU1qVTJJRFUyTGpnNWJERTVOeTR4TnpZZ016UXhMalV5YUMwek1qZ3VNREo2YlRBZ01DSXZQanh3WVhSb0lHUTlJazB5T0RZdU1EUTNJREl5T1M0MU5UbDJMVGN6TGpFNU5tZ3ROakF1TURrNGRqRTBNUzQxTURoc01USXVNRGtnTVRJdU1EZzJhRE0xTGpreU1td3hNaTR3T0RZdE1USXVNRGcyVmpJME9TNDFOa2d5TnpFdU1EVjJOREl1TURrM2JDMHpMak13TVNBekxqTXdOV2d0TWpNdU5Xd3RNeTR6TFRNdU16QTFWakUzTVM0ek5qTm9NekF1TVhZMU9DNHhPVFo2YlRBZ01FMHlNalV1T1RVZ016Z3pMalF4YURZd0xqQTVOM1l0TmpBdU1EazRhQzAyTUM0d09UaDZiVEUxTFRRMUxqQTVPR2d6TUM0eGRqTXdMakV3TW1ndE16QXVNWHB0TUNBd0lpOCtQQzl6ZG1jKykgbm8tcmVwZWF0IDEwcHggY2VudGVyO2JhY2tncm91bmQtc2l6ZTo0MHB4O3BhZGRpbmc6MCAyMHB4IDAgNjBweDtoZWlnaHQ6NTVweDtsaW5lLWhlaWdodDo1NXB4fSN1cGRhdGVyMzpob3ZlciwjdXBkYXRlcjM6dmlzaXRlZDpob3Zlcntjb2xvcjojYjMzYTNhICFpbXBvcnRhbnQ7Ym9yZGVyLWNvbG9yOiNjZTRiMzA7dGV4dC1kZWNvcmF0aW9uOiBub25lO30nIC8vIEljb24gbWFkZSBieSBGcmVlcGlrIGZyb20gd3d3LmZsYXRpY29uLmNvbSBcbn07XG51cGRhdGUuY2hlY2soKTtcblxuZXhwb3J0IGRlZmF1bHQgdXBkYXRlOyJdLCJzb3VyY2VSb290IjoiIn0=