israeli-bank-scrapers-core
Version:
Provide scrapers for all major Israeli banks and credit card companies
339 lines • 61.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _moment = _interopRequireDefault(require("moment"));
var _constants = require("../constants");
var _definitions = require("../definitions");
var _browser = require("../helpers/browser");
var _dates = _interopRequireDefault(require("../helpers/dates"));
var _debug = require("../helpers/debug");
var _fetch = require("../helpers/fetch");
var _arrays = require("../helpers/arrays");
var _transactions = require("../helpers/transactions");
var _waiting = require("../helpers/waiting");
var _transactions2 = require("../transactions");
var _baseScraperWithBrowser = require("./base-scraper-with-browser");
var _errors = require("./errors");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const RATE_LIMIT = {
SLEEP_BETWEEN: 2500,
// Sweet spot: 2.5s base delay (randomized up to 3s)
TRANSACTIONS_BATCH_SIZE: 10
};
const COUNTRY_CODE = '212';
const ID_TYPE = '1';
const INSTALLMENTS_KEYWORD = 'תשלום';
const DATE_FORMAT = 'DD/MM/YYYY';
const debug = (0, _debug.getDebug)('base-isracard-amex');
function getAccountsUrl(servicesUrl, monthMoment) {
const billingDate = monthMoment.format('YYYY-MM-DD');
const url = new URL(servicesUrl);
url.searchParams.set('reqName', 'DashboardMonth');
url.searchParams.set('actionCode', '0');
url.searchParams.set('billingDate', billingDate);
url.searchParams.set('format', 'Json');
return url.toString();
}
async function fetchAccounts(page, servicesUrl, monthMoment) {
const startTime = performance.now();
const dataUrl = getAccountsUrl(servicesUrl, monthMoment);
debug(`fetching accounts for ${monthMoment.format('YYYY-MM')} from ${dataUrl}`);
await (0, _waiting.randomDelay)(RATE_LIMIT.SLEEP_BETWEEN, RATE_LIMIT.SLEEP_BETWEEN + 500);
const dataResult = await (0, _fetch.fetchGetWithinPage)(page, dataUrl);
debug(`Fetch for ${monthMoment.format('YYYY-MM')} completed in ${performance.now() - startTime}ms`);
if (dataResult && dataResult.Header?.Status === '1' && dataResult.DashboardMonthBean) {
const {
cardsCharges
} = dataResult.DashboardMonthBean;
if (cardsCharges) {
return cardsCharges.map(cardCharge => {
return {
index: parseInt(cardCharge.cardIndex, 10),
accountNumber: cardCharge.cardNumber,
processedDate: (0, _moment.default)(cardCharge.billingDate, DATE_FORMAT).toISOString()
};
});
}
}
return [];
}
function getTransactionsUrl(servicesUrl, monthMoment) {
const month = monthMoment.month() + 1;
const year = monthMoment.year();
const monthStr = month < 10 ? `0${month}` : month.toString();
const url = new URL(servicesUrl);
url.searchParams.set('reqName', 'CardsTransactionsList');
url.searchParams.set('month', monthStr);
url.searchParams.set('year', `${year}`);
url.searchParams.set('requiredDate', 'N');
return url.toString();
}
function convertCurrency(currencyStr) {
if (currencyStr === _constants.SHEKEL_CURRENCY_KEYWORD || currencyStr === _constants.ALT_SHEKEL_CURRENCY) {
return _constants.SHEKEL_CURRENCY;
}
return currencyStr;
}
function getInstallmentsInfo(txn) {
if (!txn.moreInfo || !txn.moreInfo.includes(INSTALLMENTS_KEYWORD)) {
return undefined;
}
const matches = txn.moreInfo.match(/\d+/g);
if (!matches || matches.length < 2) {
return undefined;
}
return {
number: parseInt(matches[0], 10),
total: parseInt(matches[1], 10)
};
}
function getTransactionType(txn) {
return getInstallmentsInfo(txn) ? _transactions2.TransactionTypes.Installments : _transactions2.TransactionTypes.Normal;
}
function convertTransactions(txns, processedDate, options) {
const filteredTxns = txns.filter(txn => txn.dealSumType !== '1' && txn.voucherNumberRatz !== '000000000' && txn.voucherNumberRatzOutbound !== '000000000');
return filteredTxns.map(txn => {
const isOutbound = txn.dealSumOutbound;
const txnDateStr = isOutbound ? txn.fullPurchaseDateOutbound : txn.fullPurchaseDate;
const txnMoment = (0, _moment.default)(txnDateStr, DATE_FORMAT);
const currentProcessedDate = txn.fullPaymentDate ? (0, _moment.default)(txn.fullPaymentDate, DATE_FORMAT).toISOString() : processedDate;
const result = {
type: getTransactionType(txn),
identifier: parseInt(isOutbound ? txn.voucherNumberRatzOutbound : txn.voucherNumberRatz, 10),
date: txnMoment.toISOString(),
processedDate: currentProcessedDate,
originalAmount: isOutbound ? -txn.dealSumOutbound : -txn.dealSum,
originalCurrency: convertCurrency(txn.currentPaymentCurrency ?? txn.currencyId),
chargedAmount: isOutbound ? -txn.paymentSumOutbound : -txn.paymentSum,
chargedCurrency: convertCurrency(txn.currencyId),
description: isOutbound ? txn.fullSupplierNameOutbound : txn.fullSupplierNameHeb,
memo: txn.moreInfo || '',
installments: getInstallmentsInfo(txn) || undefined,
status: _transactions2.TransactionStatuses.Completed
};
if (options?.includeRawTransaction) {
result.rawTransaction = (0, _transactions.getRawTransaction)(txn);
}
return result;
});
}
async function fetchTransactions(page, options, companyServiceOptions, startMoment, monthMoment) {
const startTime = performance.now();
const accounts = await fetchAccounts(page, companyServiceOptions.servicesUrl, monthMoment);
const dataUrl = getTransactionsUrl(companyServiceOptions.servicesUrl, monthMoment);
debug(`fetching transactions for ${monthMoment.format('YYYY-MM')} from ${dataUrl}`);
await (0, _waiting.randomDelay)(RATE_LIMIT.SLEEP_BETWEEN, RATE_LIMIT.SLEEP_BETWEEN + 500);
const dataResult = await (0, _fetch.fetchGetWithinPage)(page, dataUrl);
debug(`Fetch for ${monthMoment.format('YYYY-MM')} completed in ${performance.now() - startTime}ms`);
if (dataResult && dataResult.Header?.Status === '1' && dataResult.CardsTransactionsListBean) {
const accountTxns = {};
accounts.forEach(account => {
const txnGroups = dataResult.CardsTransactionsListBean?.[`Index${account.index}`]?.CurrentCardTransactions;
if (txnGroups) {
let allTxns = [];
txnGroups.forEach(txnGroup => {
if (txnGroup.txnIsrael) {
const txns = convertTransactions(txnGroup.txnIsrael, account.processedDate, options);
allTxns.push(...txns);
}
if (txnGroup.txnAbroad) {
const txns = convertTransactions(txnGroup.txnAbroad, account.processedDate, options);
allTxns.push(...txns);
}
});
if (!options.combineInstallments) {
allTxns = (0, _transactions.fixInstallments)(allTxns);
}
if (options.outputData?.enableTransactionsFilterByDate ?? true) {
allTxns = (0, _transactions.filterOldTransactions)(allTxns, startMoment, options.combineInstallments || false);
}
accountTxns[account.accountNumber] = {
accountNumber: account.accountNumber,
index: account.index,
txns: allTxns
};
}
});
return accountTxns;
}
return {};
}
async function getExtraScrapTransaction(page, options, month, accountIndex, transaction) {
const url = new URL(options.servicesUrl);
url.searchParams.set('reqName', 'PirteyIska_204');
url.searchParams.set('CardIndex', accountIndex.toString());
url.searchParams.set('shovarRatz', transaction.identifier.toString());
url.searchParams.set('moedChiuv', month.format('MMYYYY'));
debug(`fetching extra scrap for transaction ${transaction.identifier} for month ${month.format('YYYY-MM')}`);
const data = await (0, _fetch.fetchGetWithinPage)(page, url.toString());
if (!data) {
return transaction;
}
const rawCategory = data.PirteyIska_204Bean?.sector ?? '';
return {
...transaction,
category: rawCategory.trim(),
rawTransaction: (0, _transactions.getRawTransaction)(data, transaction)
};
}
async function getExtraScrapAccount(page, options, accountMap, month) {
const accounts = [];
for (const account of Object.values(accountMap)) {
debug(`get extra scrap for ${account.accountNumber} with ${account.txns.length} transactions`, month.format('YYYY-MM'));
const txns = [];
for (const txnsChunk of (0, _arrays.chunk)(account.txns, RATE_LIMIT.TRANSACTIONS_BATCH_SIZE)) {
debug(`processing chunk of ${txnsChunk.length} transactions for account ${account.accountNumber}`);
const updatedTxns = await Promise.all(txnsChunk.map(t => getExtraScrapTransaction(page, options, month, account.index, t)));
await (0, _waiting.sleep)(RATE_LIMIT.SLEEP_BETWEEN);
txns.push(...updatedTxns);
}
accounts.push({
...account,
txns
});
}
return accounts.reduce((m, x) => ({
...m,
[x.accountNumber]: x
}), {});
}
async function getAdditionalTransactionInformation(scraperOptions, accountsWithIndex, page, options, allMonths) {
if (!scraperOptions.additionalTransactionInformation || scraperOptions.optInFeatures?.includes('isracard-amex:skipAdditionalTransactionInformation')) {
return accountsWithIndex;
}
return (0, _waiting.runSerial)(accountsWithIndex.map((a, i) => () => getExtraScrapAccount(page, options, a, allMonths[i])));
}
async function fetchAllTransactions(page, options, companyServiceOptions, startMoment) {
const fetchStartTime = performance.now();
const futureMonthsToScrape = options.futureMonthsToScrape ?? 1;
const allMonths = (0, _dates.default)(startMoment, futureMonthsToScrape);
debug(`Fetching transactions for ${allMonths.length} months`);
const results = await (0, _waiting.runSerial)(allMonths.map(monthMoment => () => {
return fetchTransactions(page, options, companyServiceOptions, startMoment, monthMoment);
}));
const finalResult = await getAdditionalTransactionInformation(options, results, page, companyServiceOptions, allMonths);
const combinedTxns = {};
finalResult.forEach(result => {
Object.keys(result).forEach(accountNumber => {
let txnsForAccount = combinedTxns[accountNumber];
if (!txnsForAccount) {
txnsForAccount = [];
combinedTxns[accountNumber] = txnsForAccount;
}
const toBeAddedTxns = result[accountNumber].txns;
combinedTxns[accountNumber].push(...toBeAddedTxns);
});
});
const accounts = Object.keys(combinedTxns).map(accountNumber => {
return {
accountNumber,
txns: combinedTxns[accountNumber]
};
});
debug(`fetchAllTransactions completed in ${performance.now() - fetchStartTime}ms`);
return {
success: true,
accounts
};
}
class IsracardAmexBaseScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser {
constructor(options, baseUrl, companyCode) {
super(options);
this.baseUrl = baseUrl;
this.companyCode = companyCode;
this.servicesUrl = `${baseUrl}/services/ProxyRequestHandler.ashx`;
}
async login(credentials) {
const loginStartTime = performance.now();
await this.page.setRequestInterception(true);
this.page.on('request', request => {
if (request.url().includes('detector-dom.min.js')) {
debug('force abort for request do download detector-dom.min.js resource');
void request.abort(undefined, _browser.interceptionPriorities.abort);
} else {
void request.continue(undefined, _browser.interceptionPriorities.continue);
}
});
await (0, _browser.maskHeadlessUserAgent)(this.page);
await this.navigateTo(`${this.baseUrl}/personalarea/Login`);
this.emitProgress(_definitions.ScraperProgressTypes.LoggingIn);
const validateUrl = `${this.servicesUrl}?reqName=ValidateIdData`;
const validateRequest = {
id: credentials.id,
cardSuffix: credentials.card6Digits,
countryCode: COUNTRY_CODE,
idType: ID_TYPE,
checkLevel: '1',
companyCode: this.companyCode
};
debug('logging in with validate request');
const validateResult = await (0, _fetch.fetchPostWithinPage)(this.page, validateUrl, validateRequest);
if (!validateResult || !validateResult.Header || validateResult.Header.Status !== '1' || !validateResult.ValidateIdDataBean) {
throw new Error('unknown error during login');
}
const validateReturnCode = validateResult.ValidateIdDataBean.returnCode;
debug(`user validate with return code '${validateReturnCode}'`);
if (validateReturnCode === '1') {
const {
userName
} = validateResult.ValidateIdDataBean;
const loginUrl = `${this.servicesUrl}?reqName=performLogonI`;
const request = {
KodMishtamesh: userName,
MisparZihuy: credentials.id,
Sisma: credentials.password,
cardSuffix: credentials.card6Digits,
countryCode: COUNTRY_CODE,
idType: ID_TYPE
};
debug('user login started');
const loginResult = await (0, _fetch.fetchPostWithinPage)(this.page, loginUrl, request);
debug(`user login with status '${loginResult?.status}'`, loginResult);
if (loginResult && loginResult.status === '1') {
this.emitProgress(_definitions.ScraperProgressTypes.LoginSuccess);
debug(`Login completed in ${performance.now() - loginStartTime}ms`);
return {
success: true
};
}
if (loginResult && loginResult.status === '3') {
this.emitProgress(_definitions.ScraperProgressTypes.ChangePassword);
return {
success: false,
errorType: _errors.ScraperErrorTypes.ChangePassword
};
}
this.emitProgress(_definitions.ScraperProgressTypes.LoginFailed);
return {
success: false,
errorType: _errors.ScraperErrorTypes.InvalidPassword
};
}
if (validateReturnCode === '4') {
this.emitProgress(_definitions.ScraperProgressTypes.ChangePassword);
return {
success: false,
errorType: _errors.ScraperErrorTypes.ChangePassword
};
}
this.emitProgress(_definitions.ScraperProgressTypes.LoginFailed);
return {
success: false,
errorType: _errors.ScraperErrorTypes.InvalidPassword
};
}
async fetchData() {
const defaultStartMoment = (0, _moment.default)().subtract(1, 'years');
const startDate = this.options.startDate || defaultStartMoment.toDate();
const startMoment = _moment.default.max(defaultStartMoment, (0, _moment.default)(startDate));
return fetchAllTransactions(this.page, this.options, {
servicesUrl: this.servicesUrl,
companyCode: this.companyCode
}, startMoment);
}
}
var _default = exports.default = IsracardAmexBaseScraper;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29uc3RhbnRzIiwiX2RlZmluaXRpb25zIiwiX2Jyb3dzZXIiLCJfZGF0ZXMiLCJfZGVidWciLCJfZmV0Y2giLCJfYXJyYXlzIiwiX3RyYW5zYWN0aW9ucyIsIl93YWl0aW5nIiwiX3RyYW5zYWN0aW9uczIiLCJfYmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsIl9lcnJvcnMiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJSQVRFX0xJTUlUIiwiU0xFRVBfQkVUV0VFTiIsIlRSQU5TQUNUSU9OU19CQVRDSF9TSVpFIiwiQ09VTlRSWV9DT0RFIiwiSURfVFlQRSIsIklOU1RBTExNRU5UU19LRVlXT1JEIiwiREFURV9GT1JNQVQiLCJkZWJ1ZyIsImdldERlYnVnIiwiZ2V0QWNjb3VudHNVcmwiLCJzZXJ2aWNlc1VybCIsIm1vbnRoTW9tZW50IiwiYmlsbGluZ0RhdGUiLCJmb3JtYXQiLCJ1cmwiLCJVUkwiLCJzZWFyY2hQYXJhbXMiLCJzZXQiLCJ0b1N0cmluZyIsImZldGNoQWNjb3VudHMiLCJwYWdlIiwic3RhcnRUaW1lIiwicGVyZm9ybWFuY2UiLCJub3ciLCJkYXRhVXJsIiwicmFuZG9tRGVsYXkiLCJkYXRhUmVzdWx0IiwiZmV0Y2hHZXRXaXRoaW5QYWdlIiwiSGVhZGVyIiwiU3RhdHVzIiwiRGFzaGJvYXJkTW9udGhCZWFuIiwiY2FyZHNDaGFyZ2VzIiwibWFwIiwiY2FyZENoYXJnZSIsImluZGV4IiwicGFyc2VJbnQiLCJjYXJkSW5kZXgiLCJhY2NvdW50TnVtYmVyIiwiY2FyZE51bWJlciIsInByb2Nlc3NlZERhdGUiLCJtb21lbnQiLCJ0b0lTT1N0cmluZyIsImdldFRyYW5zYWN0aW9uc1VybCIsIm1vbnRoIiwieWVhciIsIm1vbnRoU3RyIiwiY29udmVydEN1cnJlbmN5IiwiY3VycmVuY3lTdHIiLCJTSEVLRUxfQ1VSUkVOQ1lfS0VZV09SRCIsIkFMVF9TSEVLRUxfQ1VSUkVOQ1kiLCJTSEVLRUxfQ1VSUkVOQ1kiLCJnZXRJbnN0YWxsbWVudHNJbmZvIiwidHhuIiwibW9yZUluZm8iLCJpbmNsdWRlcyIsInVuZGVmaW5lZCIsIm1hdGNoZXMiLCJtYXRjaCIsImxlbmd0aCIsIm51bWJlciIsInRvdGFsIiwiZ2V0VHJhbnNhY3Rpb25UeXBlIiwiVHJhbnNhY3Rpb25UeXBlcyIsIkluc3RhbGxtZW50cyIsIk5vcm1hbCIsImNvbnZlcnRUcmFuc2FjdGlvbnMiLCJ0eG5zIiwib3B0aW9ucyIsImZpbHRlcmVkVHhucyIsImZpbHRlciIsImRlYWxTdW1UeXBlIiwidm91Y2hlck51bWJlclJhdHoiLCJ2b3VjaGVyTnVtYmVyUmF0ek91dGJvdW5kIiwiaXNPdXRib3VuZCIsImRlYWxTdW1PdXRib3VuZCIsInR4bkRhdGVTdHIiLCJmdWxsUHVyY2hhc2VEYXRlT3V0Ym91bmQiLCJmdWxsUHVyY2hhc2VEYXRlIiwidHhuTW9tZW50IiwiY3VycmVudFByb2Nlc3NlZERhdGUiLCJmdWxsUGF5bWVudERhdGUiLCJyZXN1bHQiLCJ0eXBlIiwiaWRlbnRpZmllciIsImRhdGUiLCJvcmlnaW5hbEFtb3VudCIsImRlYWxTdW0iLCJvcmlnaW5hbEN1cnJlbmN5IiwiY3VycmVudFBheW1lbnRDdXJyZW5jeSIsImN1cnJlbmN5SWQiLCJjaGFyZ2VkQW1vdW50IiwicGF5bWVudFN1bU91dGJvdW5kIiwicGF5bWVudFN1bSIsImNoYXJnZWRDdXJyZW5jeSIsImRlc2NyaXB0aW9uIiwiZnVsbFN1cHBsaWVyTmFtZU91dGJvdW5kIiwiZnVsbFN1cHBsaWVyTmFtZUhlYiIsIm1lbW8iLCJpbnN0YWxsbWVudHMiLCJzdGF0dXMiLCJUcmFuc2FjdGlvblN0YXR1c2VzIiwiQ29tcGxldGVkIiwiaW5jbHVkZVJhd1RyYW5zYWN0aW9uIiwicmF3VHJhbnNhY3Rpb24iLCJnZXRSYXdUcmFuc2FjdGlvbiIsImZldGNoVHJhbnNhY3Rpb25zIiwiY29tcGFueVNlcnZpY2VPcHRpb25zIiwic3RhcnRNb21lbnQiLCJhY2NvdW50cyIsIkNhcmRzVHJhbnNhY3Rpb25zTGlzdEJlYW4iLCJhY2NvdW50VHhucyIsImZvckVhY2giLCJhY2NvdW50IiwidHhuR3JvdXBzIiwiQ3VycmVudENhcmRUcmFuc2FjdGlvbnMiLCJhbGxUeG5zIiwidHhuR3JvdXAiLCJ0eG5Jc3JhZWwiLCJwdXNoIiwidHhuQWJyb2FkIiwiY29tYmluZUluc3RhbGxtZW50cyIsImZpeEluc3RhbGxtZW50cyIsIm91dHB1dERhdGEiLCJlbmFibGVUcmFuc2FjdGlvbnNGaWx0ZXJCeURhdGUiLCJmaWx0ZXJPbGRUcmFuc2FjdGlvbnMiLCJnZXRFeHRyYVNjcmFwVHJhbnNhY3Rpb24iLCJhY2NvdW50SW5kZXgiLCJ0cmFuc2FjdGlvbiIsImRhdGEiLCJyYXdDYXRlZ29yeSIsIlBpcnRleUlza2FfMjA0QmVhbiIsInNlY3RvciIsImNhdGVnb3J5IiwidHJpbSIsImdldEV4dHJhU2NyYXBBY2NvdW50IiwiYWNjb3VudE1hcCIsIk9iamVjdCIsInZhbHVlcyIsInR4bnNDaHVuayIsImNodW5rIiwidXBkYXRlZFR4bnMiLCJQcm9taXNlIiwiYWxsIiwidCIsInNsZWVwIiwicmVkdWNlIiwibSIsIngiLCJnZXRBZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbiIsInNjcmFwZXJPcHRpb25zIiwiYWNjb3VudHNXaXRoSW5kZXgiLCJhbGxNb250aHMiLCJhZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbiIsIm9wdEluRmVhdHVyZXMiLCJydW5TZXJpYWwiLCJhIiwiaSIsImZldGNoQWxsVHJhbnNhY3Rpb25zIiwiZmV0Y2hTdGFydFRpbWUiLCJmdXR1cmVNb250aHNUb1NjcmFwZSIsImdldEFsbE1vbnRoTW9tZW50cyIsInJlc3VsdHMiLCJmaW5hbFJlc3VsdCIsImNvbWJpbmVkVHhucyIsImtleXMiLCJ0eG5zRm9yQWNjb3VudCIsInRvQmVBZGRlZFR4bnMiLCJzdWNjZXNzIiwiSXNyYWNhcmRBbWV4QmFzZVNjcmFwZXIiLCJCYXNlU2NyYXBlcldpdGhCcm93c2VyIiwiY29uc3RydWN0b3IiLCJiYXNlVXJsIiwiY29tcGFueUNvZGUiLCJsb2dpbiIsImNyZWRlbnRpYWxzIiwibG9naW5TdGFydFRpbWUiLCJzZXRSZXF1ZXN0SW50ZXJjZXB0aW9uIiwib24iLCJyZXF1ZXN0IiwiYWJvcnQiLCJpbnRlcmNlcHRpb25Qcmlvcml0aWVzIiwiY29udGludWUiLCJtYXNrSGVhZGxlc3NVc2VyQWdlbnQiLCJuYXZpZ2F0ZVRvIiwiZW1pdFByb2dyZXNzIiwiU2NyYXBlclByb2dyZXNzVHlwZXMiLCJMb2dnaW5nSW4iLCJ2YWxpZGF0ZVVybCIsInZhbGlkYXRlUmVxdWVzdCIsImlkIiwiY2FyZFN1ZmZpeCIsImNhcmQ2RGlnaXRzIiwiY291bnRyeUNvZGUiLCJpZFR5cGUiLCJjaGVja0xldmVsIiwidmFsaWRhdGVSZXN1bHQiLCJmZXRjaFBvc3RXaXRoaW5QYWdlIiwiVmFsaWRhdGVJZERhdGFCZWFuIiwiRXJyb3IiLCJ2YWxpZGF0ZVJldHVybkNvZGUiLCJyZXR1cm5Db2RlIiwidXNlck5hbWUiLCJsb2dpblVybCIsIktvZE1pc2h0YW1lc2giLCJNaXNwYXJaaWh1eSIsIlNpc21hIiwicGFzc3dvcmQiLCJsb2dpblJlc3VsdCIsIkxvZ2luU3VjY2VzcyIsIkNoYW5nZVBhc3N3b3JkIiwiZXJyb3JUeXBlIiwiU2NyYXBlckVycm9yVHlwZXMiLCJMb2dpbkZhaWxlZCIsIkludmFsaWRQYXNzd29yZCIsImZldGNoRGF0YSIsImRlZmF1bHRTdGFydE1vbWVudCIsInN1YnRyYWN0Iiwic3RhcnREYXRlIiwidG9EYXRlIiwibWF4IiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmFwZXJzL2Jhc2UtaXNyYWNhcmQtYW1leC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbW9tZW50LCB7IHR5cGUgTW9tZW50IH0gZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IHR5cGUgUGFnZSB9IGZyb20gJ3B1cHBldGVlci1jb3JlJztcbmltcG9ydCB7IEFMVF9TSEVLRUxfQ1VSUkVOQ1ksIFNIRUtFTF9DVVJSRU5DWSwgU0hFS0VMX0NVUlJFTkNZX0tFWVdPUkQgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgU2NyYXBlclByb2dyZXNzVHlwZXMgfSBmcm9tICcuLi9kZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBpbnRlcmNlcHRpb25Qcmlvcml0aWVzLCBtYXNrSGVhZGxlc3NVc2VyQWdlbnQgfSBmcm9tICcuLi9oZWxwZXJzL2Jyb3dzZXInO1xuaW1wb3J0IGdldEFsbE1vbnRoTW9tZW50cyBmcm9tICcuLi9oZWxwZXJzL2RhdGVzJztcbmltcG9ydCB7IGdldERlYnVnIH0gZnJvbSAnLi4vaGVscGVycy9kZWJ1Zyc7XG5pbXBvcnQgeyBmZXRjaEdldFdpdGhpblBhZ2UsIGZldGNoUG9zdFdpdGhpblBhZ2UgfSBmcm9tICcuLi9oZWxwZXJzL2ZldGNoJztcbmltcG9ydCB7IGNodW5rIH0gZnJvbSAnLi4vaGVscGVycy9hcnJheXMnO1xuaW1wb3J0IHsgZmlsdGVyT2xkVHJhbnNhY3Rpb25zLCBmaXhJbnN0YWxsbWVudHMsIGdldFJhd1RyYW5zYWN0aW9uIH0gZnJvbSAnLi4vaGVscGVycy90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgcmFuZG9tRGVsYXksIHJ1blNlcmlhbCwgc2xlZXAgfSBmcm9tICcuLi9oZWxwZXJzL3dhaXRpbmcnO1xuaW1wb3J0IHtcbiAgVHJhbnNhY3Rpb25TdGF0dXNlcyxcbiAgVHJhbnNhY3Rpb25UeXBlcyxcbiAgdHlwZSBUcmFuc2FjdGlvbixcbiAgdHlwZSBUcmFuc2FjdGlvbkluc3RhbGxtZW50cyxcbiAgdHlwZSBUcmFuc2FjdGlvbnNBY2NvdW50LFxufSBmcm9tICcuLi90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgQmFzZVNjcmFwZXJXaXRoQnJvd3NlciB9IGZyb20gJy4vYmFzZS1zY3JhcGVyLXdpdGgtYnJvd3Nlcic7XG5pbXBvcnQgeyBTY3JhcGVyRXJyb3JUeXBlcyB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IHR5cGUgU2NyYXBlck9wdGlvbnMsIHR5cGUgU2NyYXBlclNjcmFwaW5nUmVzdWx0IH0gZnJvbSAnLi9pbnRlcmZhY2UnO1xuXG5jb25zdCBSQVRFX0xJTUlUID0ge1xuICBTTEVFUF9CRVRXRUVOOiAyNTAwLCAvLyBTd2VldCBzcG90OiAyLjVzIGJhc2UgZGVsYXkgKHJhbmRvbWl6ZWQgdXAgdG8gM3MpXG4gIFRSQU5TQUNUSU9OU19CQVRDSF9TSVpFOiAxMCxcbn0gYXMgY29uc3Q7XG5cbmNvbnN0IENPVU5UUllfQ09ERSA9ICcyMTInO1xuY29uc3QgSURfVFlQRSA9ICcxJztcbmNvbnN0IElOU1RBTExNRU5UU19LRVlXT1JEID0gJ9eq16nXnNeV150nO1xuXG5jb25zdCBEQVRFX0ZPUk1BVCA9ICdERC9NTS9ZWVlZJztcblxuY29uc3QgZGVidWcgPSBnZXREZWJ1ZygnYmFzZS1pc3JhY2FyZC1hbWV4Jyk7XG5cbnR5cGUgQ29tcGFueVNlcnZpY2VPcHRpb25zID0ge1xuICBzZXJ2aWNlc1VybDogc3RyaW5nO1xuICBjb21wYW55Q29kZTogc3RyaW5nO1xufTtcblxudHlwZSBTY3JhcGVkQWNjb3VudHNXaXRoSW5kZXggPSBSZWNvcmQ8c3RyaW5nLCBUcmFuc2FjdGlvbnNBY2NvdW50ICYgeyBpbmRleDogbnVtYmVyIH0+O1xuXG5pbnRlcmZhY2UgU2NyYXBlZFRyYW5zYWN0aW9uIHtcbiAgZGVhbFN1bVR5cGU6IHN0cmluZztcbiAgdm91Y2hlck51bWJlclJhdHpPdXRib3VuZDogc3RyaW5nO1xuICB2b3VjaGVyTnVtYmVyUmF0ejogc3RyaW5nO1xuICBtb3JlSW5mbz86IHN0cmluZztcbiAgZGVhbFN1bU91dGJvdW5kOiBib29sZWFuO1xuICBjdXJyZW5jeUlkOiBzdHJpbmc7XG4gIGN1cnJlbnRQYXltZW50Q3VycmVuY3k6IHN0cmluZztcbiAgZGVhbFN1bTogbnVtYmVyO1xuICBmdWxsUGF5bWVudERhdGU/OiBzdHJpbmc7XG4gIGZ1bGxQdXJjaGFzZURhdGU/OiBzdHJpbmc7XG4gIGZ1bGxQdXJjaGFzZURhdGVPdXRib3VuZD86IHN0cmluZztcbiAgZnVsbFN1cHBsaWVyTmFtZUhlYjogc3RyaW5nO1xuICBmdWxsU3VwcGxpZXJOYW1lT3V0Ym91bmQ6IHN0cmluZztcbiAgcGF5bWVudFN1bTogbnVtYmVyO1xuICBwYXltZW50U3VtT3V0Ym91bmQ6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFNjcmFwZWRBY2NvdW50IHtcbiAgaW5kZXg6IG51bWJlcjtcbiAgYWNjb3VudE51bWJlcjogc3RyaW5nO1xuICBwcm9jZXNzZWREYXRlOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBTY3JhcGVkTG9naW5WYWxpZGF0aW9uIHtcbiAgSGVhZGVyOiB7XG4gICAgU3RhdHVzOiBzdHJpbmc7XG4gIH07XG4gIFZhbGlkYXRlSWREYXRhQmVhbj86IHtcbiAgICB1c2VyTmFtZT86IHN0cmluZztcbiAgICByZXR1cm5Db2RlOiBzdHJpbmc7XG4gIH07XG59XG5cbmludGVyZmFjZSBTY3JhcGVkQWNjb3VudHNXaXRoaW5QYWdlUmVzcG9uc2Uge1xuICBIZWFkZXI6IHtcbiAgICBTdGF0dXM6IHN0cmluZztcbiAgfTtcbiAgRGFzaGJvYXJkTW9udGhCZWFuPzoge1xuICAgIGNhcmRzQ2hhcmdlczoge1xuICAgICAgY2FyZEluZGV4OiBzdHJpbmc7XG4gICAgICBjYXJkTnVtYmVyOiBzdHJpbmc7XG4gICAgICBiaWxsaW5nRGF0ZTogc3RyaW5nO1xuICAgIH1bXTtcbiAgfTtcbn1cblxuaW50ZXJmYWNlIFNjcmFwZWRDdXJyZW50Q2FyZFRyYW5zYWN0aW9ucyB7XG4gIHR4bklzcmFlbD86IFNjcmFwZWRUcmFuc2FjdGlvbltdO1xuICB0eG5BYnJvYWQ/OiBTY3JhcGVkVHJhbnNhY3Rpb25bXTtcbn1cblxuaW50ZXJmYWNlIFNjcmFwZWRUcmFuc2FjdGlvbkRhdGEge1xuICBIZWFkZXI/OiB7XG4gICAgU3RhdHVzOiBzdHJpbmc7XG4gIH07XG4gIFBpcnRleUlza2FfMjA0QmVhbj86IHtcbiAgICBzZWN0b3I6IHN0cmluZztcbiAgfTtcblxuICBDYXJkc1RyYW5zYWN0aW9uc0xpc3RCZWFuPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICB7XG4gICAgICBDdXJyZW50Q2FyZFRyYW5zYWN0aW9uczogU2NyYXBlZEN1cnJlbnRDYXJkVHJhbnNhY3Rpb25zW107XG4gICAgfVxuICA+O1xufVxuXG5mdW5jdGlvbiBnZXRBY2NvdW50c1VybChzZXJ2aWNlc1VybDogc3RyaW5nLCBtb250aE1vbWVudDogTW9tZW50KSB7XG4gIGNvbnN0IGJpbGxpbmdEYXRlID0gbW9udGhNb21lbnQuZm9ybWF0KCdZWVlZLU1NLUREJyk7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwoc2VydmljZXNVcmwpO1xuICB1cmwuc2VhcmNoUGFyYW1zLnNldCgncmVxTmFtZScsICdEYXNoYm9hcmRNb250aCcpO1xuICB1cmwuc2VhcmNoUGFyYW1zLnNldCgnYWN0aW9uQ29kZScsICcwJyk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdiaWxsaW5nRGF0ZScsIGJpbGxpbmdEYXRlKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoJ2Zvcm1hdCcsICdKc29uJyk7XG4gIHJldHVybiB1cmwudG9TdHJpbmcoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hBY2NvdW50cyhwYWdlOiBQYWdlLCBzZXJ2aWNlc1VybDogc3RyaW5nLCBtb250aE1vbWVudDogTW9tZW50KTogUHJvbWlzZTxTY3JhcGVkQWNjb3VudFtdPiB7XG4gIGNvbnN0IHN0YXJ0VGltZSA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICBjb25zdCBkYXRhVXJsID0gZ2V0QWNjb3VudHNVcmwoc2VydmljZXNVcmwsIG1vbnRoTW9tZW50KTtcblxuICBkZWJ1ZyhgZmV0Y2hpbmcgYWNjb3VudHMgZm9yICR7bW9udGhNb21lbnQuZm9ybWF0KCdZWVlZLU1NJyl9IGZyb20gJHtkYXRhVXJsfWApO1xuICBhd2FpdCByYW5kb21EZWxheShSQVRFX0xJTUlULlNMRUVQX0JFVFdFRU4sIFJBVEVfTElNSVQuU0xFRVBfQkVUV0VFTiArIDUwMCk7XG4gIGNvbnN0IGRhdGFSZXN1bHQgPSBhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8U2NyYXBlZEFjY291bnRzV2l0aGluUGFnZVJlc3BvbnNlPihwYWdlLCBkYXRhVXJsKTtcbiAgZGVidWcoYEZldGNoIGZvciAke21vbnRoTW9tZW50LmZvcm1hdCgnWVlZWS1NTScpfSBjb21wbGV0ZWQgaW4gJHtwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0VGltZX1tc2ApO1xuXG4gIGlmIChkYXRhUmVzdWx0ICYmIGRhdGFSZXN1bHQuSGVhZGVyPy5TdGF0dXMgPT09ICcxJyAmJiBkYXRhUmVzdWx0LkRhc2hib2FyZE1vbnRoQmVhbikge1xuICAgIGNvbnN0IHsgY2FyZHNDaGFyZ2VzIH0gPSBkYXRhUmVzdWx0LkRhc2hib2FyZE1vbnRoQmVhbjtcbiAgICBpZiAoY2FyZHNDaGFyZ2VzKSB7XG4gICAgICByZXR1cm4gY2FyZHNDaGFyZ2VzLm1hcChjYXJkQ2hhcmdlID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpbmRleDogcGFyc2VJbnQoY2FyZENoYXJnZS5jYXJkSW5kZXgsIDEwKSxcbiAgICAgICAgICBhY2NvdW50TnVtYmVyOiBjYXJkQ2hhcmdlLmNhcmROdW1iZXIsXG4gICAgICAgICAgcHJvY2Vzc2VkRGF0ZTogbW9tZW50KGNhcmRDaGFyZ2UuYmlsbGluZ0RhdGUsIERBVEVfRk9STUFUKS50b0lTT1N0cmluZygpLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBbXTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25zVXJsKHNlcnZpY2VzVXJsOiBzdHJpbmcsIG1vbnRoTW9tZW50OiBNb21lbnQpIHtcbiAgY29uc3QgbW9udGggPSBtb250aE1vbWVudC5tb250aCgpICsgMTtcbiAgY29uc3QgeWVhciA9IG1vbnRoTW9tZW50LnllYXIoKTtcbiAgY29uc3QgbW9udGhTdHIgPSBtb250aCA8IDEwID8gYDAke21vbnRofWAgOiBtb250aC50b1N0cmluZygpO1xuICBjb25zdCB1cmwgPSBuZXcgVVJMKHNlcnZpY2VzVXJsKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoJ3JlcU5hbWUnLCAnQ2FyZHNUcmFuc2FjdGlvbnNMaXN0Jyk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdtb250aCcsIG1vbnRoU3RyKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoJ3llYXInLCBgJHt5ZWFyfWApO1xuICB1cmwuc2VhcmNoUGFyYW1zLnNldCgncmVxdWlyZWREYXRlJywgJ04nKTtcbiAgcmV0dXJuIHVybC50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0Q3VycmVuY3koY3VycmVuY3lTdHI6IHN0cmluZykge1xuICBpZiAoY3VycmVuY3lTdHIgPT09IFNIRUtFTF9DVVJSRU5DWV9LRVlXT1JEIHx8IGN1cnJlbmN5U3RyID09PSBBTFRfU0hFS0VMX0NVUlJFTkNZKSB7XG4gICAgcmV0dXJuIFNIRUtFTF9DVVJSRU5DWTtcbiAgfVxuICByZXR1cm4gY3VycmVuY3lTdHI7XG59XG5cbmZ1bmN0aW9uIGdldEluc3RhbGxtZW50c0luZm8odHhuOiBTY3JhcGVkVHJhbnNhY3Rpb24pOiBUcmFuc2FjdGlvbkluc3RhbGxtZW50cyB8IHVuZGVmaW5lZCB7XG4gIGlmICghdHhuLm1vcmVJbmZvIHx8ICF0eG4ubW9yZUluZm8uaW5jbHVkZXMoSU5TVEFMTE1FTlRTX0tFWVdPUkQpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCBtYXRjaGVzID0gdHhuLm1vcmVJbmZvLm1hdGNoKC9cXGQrL2cpO1xuICBpZiAoIW1hdGNoZXMgfHwgbWF0Y2hlcy5sZW5ndGggPCAyKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbnVtYmVyOiBwYXJzZUludChtYXRjaGVzWzBdLCAxMCksXG4gICAgdG90YWw6IHBhcnNlSW50KG1hdGNoZXNbMV0sIDEwKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25UeXBlKHR4bjogU2NyYXBlZFRyYW5zYWN0aW9uKSB7XG4gIHJldHVybiBnZXRJbnN0YWxsbWVudHNJbmZvKHR4bikgPyBUcmFuc2FjdGlvblR5cGVzLkluc3RhbGxtZW50cyA6IFRyYW5zYWN0aW9uVHlwZXMuTm9ybWFsO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0VHJhbnNhY3Rpb25zKFxuICB0eG5zOiBTY3JhcGVkVHJhbnNhY3Rpb25bXSxcbiAgcHJvY2Vzc2VkRGF0ZTogc3RyaW5nLFxuICBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMsXG4pOiBUcmFuc2FjdGlvbltdIHtcbiAgY29uc3QgZmlsdGVyZWRUeG5zID0gdHhucy5maWx0ZXIoXG4gICAgdHhuID0+XG4gICAgICB0eG4uZGVhbFN1bVR5cGUgIT09ICcxJyAmJiB0eG4udm91Y2hlck51bWJlclJhdHogIT09ICcwMDAwMDAwMDAnICYmIHR4bi52b3VjaGVyTnVtYmVyUmF0ek91dGJvdW5kICE9PSAnMDAwMDAwMDAwJyxcbiAgKTtcblxuICByZXR1cm4gZmlsdGVyZWRUeG5zLm1hcCh0eG4gPT4ge1xuICAgIGNvbnN0IGlzT3V0Ym91bmQgPSB0eG4uZGVhbFN1bU91dGJvdW5kO1xuICAgIGNvbnN0IHR4bkRhdGVTdHIgPSBpc091dGJvdW5kID8gdHhuLmZ1bGxQdXJjaGFzZURhdGVPdXRib3VuZCA6IHR4bi5mdWxsUHVyY2hhc2VEYXRlO1xuICAgIGNvbnN0IHR4bk1vbWVudCA9IG1vbWVudCh0eG5EYXRlU3RyLCBEQVRFX0ZPUk1BVCk7XG5cbiAgICBjb25zdCBjdXJyZW50UHJvY2Vzc2VkRGF0ZSA9IHR4bi5mdWxsUGF5bWVudERhdGVcbiAgICAgID8gbW9tZW50KHR4bi5mdWxsUGF5bWVudERhdGUsIERBVEVfRk9STUFUKS50b0lTT1N0cmluZygpXG4gICAgICA6IHByb2Nlc3NlZERhdGU7XG4gICAgY29uc3QgcmVzdWx0OiBUcmFuc2FjdGlvbiA9IHtcbiAgICAgIHR5cGU6IGdldFRyYW5zYWN0aW9uVHlwZSh0eG4pLFxuICAgICAgaWRlbnRpZmllcjogcGFyc2VJbnQoaXNPdXRib3VuZCA/IHR4bi52b3VjaGVyTnVtYmVyUmF0ek91dGJvdW5kIDogdHhuLnZvdWNoZXJOdW1iZXJSYXR6LCAxMCksXG4gICAgICBkYXRlOiB0eG5Nb21lbnQudG9JU09TdHJpbmcoKSxcbiAgICAgIHByb2Nlc3NlZERhdGU6IGN1cnJlbnRQcm9jZXNzZWREYXRlLFxuICAgICAgb3JpZ2luYWxBbW91bnQ6IGlzT3V0Ym91bmQgPyAtdHhuLmRlYWxTdW1PdXRib3VuZCA6IC10eG4uZGVhbFN1bSxcbiAgICAgIG9yaWdpbmFsQ3VycmVuY3k6IGNvbnZlcnRDdXJyZW5jeSh0eG4uY3VycmVudFBheW1lbnRDdXJyZW5jeSA/PyB0eG4uY3VycmVuY3lJZCksXG4gICAgICBjaGFyZ2VkQW1vdW50OiBpc091dGJvdW5kID8gLXR4bi5wYXltZW50U3VtT3V0Ym91bmQgOiAtdHhuLnBheW1lbnRTdW0sXG4gICAgICBjaGFyZ2VkQ3VycmVuY3k6IGNvbnZlcnRDdXJyZW5jeSh0eG4uY3VycmVuY3lJZCksXG4gICAgICBkZXNjcmlwdGlvbjogaXNPdXRib3VuZCA/IHR4bi5mdWxsU3VwcGxpZXJOYW1lT3V0Ym91bmQgOiB0eG4uZnVsbFN1cHBsaWVyTmFtZUhlYixcbiAgICAgIG1lbW86IHR4bi5tb3JlSW5mbyB8fCAnJyxcbiAgICAgIGluc3RhbGxtZW50czogZ2V0SW5zdGFsbG1lbnRzSW5mbyh0eG4pIHx8IHVuZGVmaW5lZCxcbiAgICAgIHN0YXR1czogVHJhbnNhY3Rpb25TdGF0dXNlcy5Db21wbGV0ZWQsXG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zPy5pbmNsdWRlUmF3VHJhbnNhY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5yYXdUcmFuc2FjdGlvbiA9IGdldFJhd1RyYW5zYWN0aW9uKHR4bik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoVHJhbnNhY3Rpb25zKFxuICBwYWdlOiBQYWdlLFxuICBvcHRpb25zOiBTY3JhcGVyT3B0aW9ucyxcbiAgY29tcGFueVNlcnZpY2VPcHRpb25zOiBDb21wYW55U2VydmljZU9wdGlvbnMsXG4gIHN0YXJ0TW9tZW50OiBNb21lbnQsXG4gIG1vbnRoTW9tZW50OiBNb21lbnQsXG4pOiBQcm9taXNlPFNjcmFwZWRBY2NvdW50c1dpdGhJbmRleD4ge1xuICBjb25zdCBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgY29uc3QgYWNjb3VudHMgPSBhd2FpdCBmZXRjaEFjY291bnRzKHBhZ2UsIGNvbXBhbnlTZXJ2aWNlT3B0aW9ucy5zZXJ2aWNlc1VybCwgbW9udGhNb21lbnQpO1xuICBjb25zdCBkYXRhVXJsID0gZ2V0VHJhbnNhY3Rpb25zVXJsKGNvbXBhbnlTZXJ2aWNlT3B0aW9ucy5zZXJ2aWNlc1VybCwgbW9udGhNb21lbnQpO1xuXG4gIGRlYnVnKGBmZXRjaGluZyB0cmFuc2FjdGlvbnMgZm9yICR7bW9udGhNb21lbnQuZm9ybWF0KCdZWVlZLU1NJyl9IGZyb20gJHtkYXRhVXJsfWApO1xuICBhd2FpdCByYW5kb21EZWxheShSQVRFX0xJTUlULlNMRUVQX0JFVFdFRU4sIFJBVEVfTElNSVQuU0xFRVBfQkVUV0VFTiArIDUwMCk7XG4gIGNvbnN0IGRhdGFSZXN1bHQgPSBhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8U2NyYXBlZFRyYW5zYWN0aW9uRGF0YT4ocGFnZSwgZGF0YVVybCk7XG4gIGRlYnVnKGBGZXRjaCBmb3IgJHttb250aE1vbWVudC5mb3JtYXQoJ1lZWVktTU0nKX0gY29tcGxldGVkIGluICR7cGVyZm9ybWFuY2Uubm93KCkgLSBzdGFydFRpbWV9bXNgKTtcblxuICBpZiAoZGF0YVJlc3VsdCAmJiBkYXRhUmVzdWx0LkhlYWRlcj8uU3RhdHVzID09PSAnMScgJiYgZGF0YVJlc3VsdC5DYXJkc1RyYW5zYWN0aW9uc0xpc3RCZWFuKSB7XG4gICAgY29uc3QgYWNjb3VudFR4bnM6IFNjcmFwZWRBY2NvdW50c1dpdGhJbmRleCA9IHt9O1xuICAgIGFjY291bnRzLmZvckVhY2goYWNjb3VudCA9PiB7XG4gICAgICBjb25zdCB0eG5Hcm91cHM6IFNjcmFwZWRDdXJyZW50Q2FyZFRyYW5zYWN0aW9uc1tdIHwgdW5kZWZpbmVkID1cbiAgICAgICAgZGF0YVJlc3VsdC5DYXJkc1RyYW5zYWN0aW9uc0xpc3RCZWFuPy5bYEluZGV4JHthY2NvdW50LmluZGV4fWBdPy5DdXJyZW50Q2FyZFRyYW5zYWN0aW9ucztcbiAgICAgIGlmICh0eG5Hcm91cHMpIHtcbiAgICAgICAgbGV0IGFsbFR4bnM6IFRyYW5zYWN0aW9uW10gPSBbXTtcbiAgICAgICAgdHhuR3JvdXBzLmZvckVhY2godHhuR3JvdXAgPT4ge1xuICAgICAgICAgIGlmICh0eG5Hcm91cC50eG5Jc3JhZWwpIHtcbiAgICAgICAgICAgIGNvbnN0IHR4bnMgPSBjb252ZXJ0VHJhbnNhY3Rpb25zKHR4bkdyb3VwLnR4bklzcmFlbCwgYWNjb3VudC5wcm9jZXNzZWREYXRlLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGFsbFR4bnMucHVzaCguLi50eG5zKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR4bkdyb3VwLnR4bkFicm9hZCkge1xuICAgICAgICAgICAgY29uc3QgdHhucyA9IGNvbnZlcnRUcmFuc2FjdGlvbnModHhuR3JvdXAudHhuQWJyb2FkLCBhY2NvdW50LnByb2Nlc3NlZERhdGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgYWxsVHhucy5wdXNoKC4uLnR4bnMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKCFvcHRpb25zLmNvbWJpbmVJbnN0YWxsbWVudHMpIHtcbiAgICAgICAgICBhbGxUeG5zID0gZml4SW5zdGFsbG1lbnRzKGFsbFR4bnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLm91dHB1dERhdGE/LmVuYWJsZVRyYW5zYWN0aW9uc0ZpbHRlckJ5RGF0ZSA/PyB0cnVlKSB7XG4gICAgICAgICAgYWxsVHhucyA9IGZpbHRlck9sZFRyYW5zYWN0aW9ucyhhbGxUeG5zLCBzdGFydE1vbWVudCwgb3B0aW9ucy5jb21iaW5lSW5zdGFsbG1lbnRzIHx8IGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBhY2NvdW50VHhuc1thY2NvdW50LmFjY291bnROdW1iZXJdID0ge1xuICAgICAgICAgIGFjY291bnROdW1iZXI6IGFjY291bnQuYWNjb3VudE51bWJlcixcbiAgICAgICAgICBpbmRleDogYWNjb3VudC5pbmRleCxcbiAgICAgICAgICB0eG5zOiBhbGxUeG5zLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBhY2NvdW50VHhucztcbiAgfVxuXG4gIHJldHVybiB7fTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0RXh0cmFTY3JhcFRyYW5zYWN0aW9uKFxuICBwYWdlOiBQYWdlLFxuICBvcHRpb25zOiBDb21wYW55U2VydmljZU9wdGlvbnMsXG4gIG1vbnRoOiBNb21lbnQsXG4gIGFjY291bnRJbmRleDogbnVtYmVyLFxuICB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sXG4pOiBQcm9taXNlPFRyYW5zYWN0aW9uPiB7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwob3B0aW9ucy5zZXJ2aWNlc1VybCk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdyZXFOYW1lJywgJ1BpcnRleUlza2FfMjA0Jyk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdDYXJkSW5kZXgnLCBhY2NvdW50SW5kZXgudG9TdHJpbmcoKSk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdzaG92YXJSYXR6JywgdHJhbnNhY3Rpb24uaWRlbnRpZmllciEudG9TdHJpbmcoKSk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdtb2VkQ2hpdXYnLCBtb250aC5mb3JtYXQoJ01NWVlZWScpKTtcblxuICBkZWJ1ZyhgZmV0Y2hpbmcgZXh0cmEgc2NyYXAgZm9yIHRyYW5zYWN0aW9uICR7dHJhbnNhY3Rpb24uaWRlbnRpZmllcn0gZm9yIG1vbnRoICR7bW9udGguZm9ybWF0KCdZWVlZLU1NJyl9YCk7XG4gIGNvbnN0IGRhdGEgPSBhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8U2NyYXBlZFRyYW5zYWN0aW9uRGF0YT4ocGFnZSwgdXJsLnRvU3RyaW5nKCkpO1xuICBpZiAoIWRhdGEpIHtcbiAgICByZXR1cm4gdHJhbnNhY3Rpb247XG4gIH1cblxuICBjb25zdCByYXdDYXRlZ29yeSA9IGRhdGEuUGlydGV5SXNrYV8yMDRCZWFuPy5zZWN0b3IgPz8gJyc7XG4gIHJldHVybiB7XG4gICAgLi4udHJhbnNhY3Rpb24sXG4gICAgY2F0ZWdvcnk6IHJhd0NhdGVnb3J5LnRyaW0oKSxcbiAgICByYXdUcmFuc2FjdGlvbjogZ2V0UmF3VHJhbnNhY3Rpb24oZGF0YSwgdHJhbnNhY3Rpb24pLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRFeHRyYVNjcmFwQWNjb3VudChcbiAgcGFnZTogUGFnZSxcbiAgb3B0aW9uczogQ29tcGFueVNlcnZpY2VPcHRpb25zLFxuICBhY2NvdW50TWFwOiBTY3JhcGVkQWNjb3VudHNXaXRoSW5kZXgsXG4gIG1vbnRoOiBtb21lbnQuTW9tZW50LFxuKTogUHJvbWlzZTxTY3JhcGVkQWNjb3VudHNXaXRoSW5kZXg+IHtcbiAgY29uc3QgYWNjb3VudHM6IFNjcmFwZWRBY2NvdW50c1dpdGhJbmRleFtzdHJpbmddW10gPSBbXTtcbiAgZm9yIChjb25zdCBhY2NvdW50IG9mIE9iamVjdC52YWx1ZXMoYWNjb3VudE1hcCkpIHtcbiAgICBkZWJ1ZyhcbiAgICAgIGBnZXQgZXh0cmEgc2NyYXAgZm9yICR7YWNjb3VudC5hY2NvdW50TnVtYmVyfSB3aXRoICR7YWNjb3VudC50eG5zLmxlbmd0aH0gdHJhbnNhY3Rpb25zYCxcbiAgICAgIG1vbnRoLmZvcm1hdCgnWVlZWS1NTScpLFxuICAgICk7XG4gICAgY29uc3QgdHhuczogVHJhbnNhY3Rpb25bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgdHhuc0NodW5rIG9mIGNodW5rKGFjY291bnQudHhucywgUkFURV9MSU1JVC5UUkFOU0FDVElPTlNfQkFUQ0hfU0laRSkpIHtcbiAgICAgIGRlYnVnKGBwcm9jZXNzaW5nIGNodW5rIG9mICR7dHhuc0NodW5rLmxlbmd0aH0gdHJhbnNhY3Rpb25zIGZvciBhY2NvdW50ICR7YWNjb3VudC5hY2NvdW50TnVtYmVyfWApO1xuICAgICAgY29uc3QgdXBkYXRlZFR4bnMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgdHhuc0NodW5rLm1hcCh0ID0+IGdldEV4dHJhU2NyYXBUcmFuc2FjdGlvbihwYWdlLCBvcHRpb25zLCBtb250aCwgYWNjb3VudC5pbmRleCwgdCkpLFxuICAgICAgKTtcbiAgICAgIGF3YWl0IHNsZWVwKFJBVEVfTElNSVQuU0xFRVBfQkVUV0VFTik7XG4gICAgICB0eG5zLnB1c2goLi4udXBkYXRlZFR4bnMpO1xuICAgIH1cbiAgICBhY2NvdW50cy5wdXNoKHsgLi4uYWNjb3VudCwgdHhucyB9KTtcbiAgfVxuXG4gIHJldHVybiBhY2NvdW50cy5yZWR1Y2UoKG0sIHgpID0+ICh7IC4uLm0sIFt4LmFjY291bnROdW1iZXJdOiB4IH0pLCB7fSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEFkZGl0aW9uYWxUcmFuc2FjdGlvbkluZm9ybWF0aW9uKFxuICBzY3JhcGVyT3B0aW9uczogU2NyYXBlck9wdGlvbnMsXG4gIGFjY291bnRzV2l0aEluZGV4OiBTY3JhcGVkQWNjb3VudHNXaXRoSW5kZXhbXSxcbiAgcGFnZTogUGFnZSxcbiAgb3B0aW9uczogQ29tcGFueVNlcnZpY2VPcHRpb25zLFxuICBhbGxNb250aHM6IG1vbWVudC5Nb21lbnRbXSxcbik6IFByb21pc2U8U2NyYXBlZEFjY291bnRzV2l0aEluZGV4W10+IHtcbiAgaWYgKFxuICAgICFzY3JhcGVyT3B0aW9ucy5hZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbiB8fFxuICAgIHNjcmFwZXJPcHRpb25zLm9wdEluRmVhdHVyZXM/LmluY2x1ZGVzKCdpc3JhY2FyZC1hbWV4OnNraXBBZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbicpXG4gICkge1xuICAgIHJldHVybiBhY2NvdW50c1dpdGhJbmRleDtcbiAgfVxuICByZXR1cm4gcnVuU2VyaWFsKGFjY291bnRzV2l0aEluZGV4Lm1hcCgoYSwgaSkgPT4gKCkgPT4gZ2V0RXh0cmFTY3JhcEFjY291bnQocGFnZSwgb3B0aW9ucywgYSwgYWxsTW9udGhzW2ldKSkpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaEFsbFRyYW5zYWN0aW9ucyhcbiAgcGFnZTogUGFnZSxcbiAgb3B0aW9uczogU2NyYXBlck9wdGlvbnMsXG4gIGNvbXBhbnlTZXJ2aWNlT3B0aW9uczogQ29tcGFueVNlcnZpY2VPcHRpb25zLFxuICBzdGFydE1vbWVudDogTW9tZW50LFxuKSB7XG4gIGNvbnN0IGZldGNoU3RhcnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gIGNvbnN0IGZ1dHVyZU1vbnRoc1RvU2NyYXBlID0gb3B0aW9ucy5mdXR1cmVNb250aHNUb1NjcmFwZSA/PyAxO1xuICBjb25zdCBhbGxNb250aHMgPSBnZXRBbGxNb250aE1vbWVudHMoc3RhcnRNb21lbnQsIGZ1dHVyZU1vbnRoc1RvU2NyYXBlKTtcbiAgZGVidWcoYEZldGNoaW5nIHRyYW5zYWN0aW9ucyBmb3IgJHthbGxNb250aHMubGVuZ3RofSBtb250aHNgKTtcblxuICBjb25zdCByZXN1bHRzOiBTY3JhcGVkQWNjb3VudHNXaXRoSW5kZXhbXSA9IGF3YWl0IHJ1blNlcmlhbChcbiAgICBhbGxNb250aHMubWFwKG1vbnRoTW9tZW50ID0+ICgpID0+IHtcbiAgICAgIHJldHVybiBmZXRjaFRyYW5zYWN0aW9ucyhwYWdlLCBvcHRpb25zLCBjb21wYW55U2VydmljZU9wdGlvbnMsIHN0YXJ0TW9tZW50LCBtb250aE1vbWVudCk7XG4gICAgfSksXG4gICk7XG5cbiAgY29uc3QgZmluYWxSZXN1bHQgPSBhd2FpdCBnZXRBZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbihcbiAgICBvcHRpb25zLFxuICAgIHJlc3VsdHMsXG4gICAgcGFnZSxcbiAgICBjb21wYW55U2VydmljZU9wdGlvbnMsXG4gICAgYWxsTW9udGhzLFxuICApO1xuICBjb25zdCBjb21iaW5lZFR4bnM6IFJlY29yZDxzdHJpbmcsIFRyYW5zYWN0aW9uW10+ID0ge307XG5cbiAgZmluYWxSZXN1bHQuZm9yRWFjaChyZXN1bHQgPT4ge1xuICAgIE9iamVjdC5rZXlzKHJlc3VsdCkuZm9yRWFjaChhY2NvdW50TnVtYmVyID0+IHtcbiAgICAgIGxldCB0eG5zRm9yQWNjb3VudCA9IGNvbWJpbmVkVHhuc1thY2NvdW50TnVtYmVyXTtcbiAgICAgIGlmICghdHhuc0ZvckFjY291bnQpIHtcbiAgICAgICAgdHhuc0ZvckFjY291bnQgPSBbXTtcbiAgICAgICAgY29tYmluZWRUeG5zW2FjY291bnROdW1iZXJdID0gdHhuc0ZvckFjY291bnQ7XG4gICAgICB9XG4gICAgICBjb25zdCB0b0JlQWRkZWRUeG5zID0gcmVzdWx0W2FjY291bnROdW1iZXJdLnR4bnM7XG4gICAgICBjb21iaW5lZFR4bnNbYWNjb3VudE51bWJlcl0ucHVzaCguLi50b0JlQWRkZWRUeG5zKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgY29uc3QgYWNjb3VudHMgPSBPYmplY3Qua2V5cyhjb21iaW5lZFR4bnMpLm1hcChhY2NvdW50TnVtYmVyID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgYWNjb3VudE51bWJlcixcbiAgICAgIHR4bnM6IGNvbWJpbmVkVHhuc1thY2NvdW50TnVtYmVyXSxcbiAgICB9O1xuICB9KTtcblxuICBkZWJ1ZyhgZmV0Y2hBbGxUcmFuc2FjdGlvbnMgY29tcGxldGVkIGluICR7cGVyZm9ybWFuY2Uubm93KCkgLSBmZXRjaFN0YXJ0VGltZX1tc2ApO1xuXG4gIHJldHVybiB7XG4gICAgc3VjY2VzczogdHJ1ZSxcbiAgICBhY2NvdW50cyxcbiAgfTtcbn1cblxudHlwZSBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscyA9IHsgaWQ6IHN0cmluZzsgcGFzc3dvcmQ6IHN0cmluZzsgY2FyZDZEaWdpdHM6IHN0cmluZyB9O1xuY2xhc3MgSXNyYWNhcmRBbWV4QmFzZVNjcmFwZXIgZXh0ZW5kcyBCYXNlU2NyYXBlcldpdGhCcm93c2VyPFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzPiB7XG4gIHByaXZhdGUgYmFzZVVybDogc3RyaW5nO1xuXG4gIHByaXZhdGUgY29tcGFueUNvZGU6IHN0cmluZztcblxuICBwcml2YXRlIHNlcnZpY2VzVXJsOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogU2NyYXBlck9wdGlvbnMsIGJhc2VVcmw6IHN0cmluZywgY29tcGFueUNvZGU6IHN0cmluZykge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgdGhpcy5iYXNlVXJsID0gYmFzZVVybDtcbiAgICB0aGlzLmNvbXBhbnlDb2RlID0gY29tcGFueUNvZGU7XG4gICAgdGhpcy5zZXJ2aWNlc1VybCA9IGAke2Jhc2VVcmx9L3NlcnZpY2VzL1Byb3h5UmVxdWVzdEhhbmRsZXIuYXNoeGA7XG4gIH1cblxuICBhc3luYyBsb2dpbihjcmVkZW50aWFsczogU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMpOiBQcm9taXNlPFNjcmFwZXJTY3JhcGluZ1Jlc3VsdD4ge1xuICAgIGNvbnN0IGxvZ2luU3RhcnRUaW1lID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgYXdhaXQgdGhpcy5wYWdlLnNldFJlcXVlc3RJbnRlcmNlcHRpb24odHJ1ZSk7XG4gICAgdGhpcy5wYWdlLm9uKCdyZXF1ZXN0JywgcmVxdWVzdCA9PiB7XG4gICAgICBpZiAocmVxdWVzdC51cmwoKS5pbmNsdWRlcygnZGV0ZWN0b3ItZG9tLm1pbi5qcycpKSB7XG4gICAgICAgIGRlYnVnKCdmb3JjZSBhYm9ydCBmb3IgcmVxdWVzdCBkbyBkb3dubG9hZCBkZXRlY3Rvci1kb20ubWluLmpzIHJlc291cmNlJyk7XG4gICAgICAgIHZvaWQgcmVxdWVzdC5hYm9ydCh1bmRlZmluZWQsIGludGVyY2VwdGlvblByaW9yaXRpZXMuYWJvcnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdm9pZCByZXF1ZXN0LmNvbnRpbnVlKHVuZGVmaW5lZCwgaW50ZXJjZXB0aW9uUHJpb3JpdGllcy5jb250aW51ZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBhd2FpdCBtYXNrSGVhZGxlc3NVc2VyQWdlbnQodGhpcy5wYWdlKTtcblxuICAgIGF3YWl0IHRoaXMubmF2aWdhdGVUbyhgJHt0aGlzLmJhc2VVcmx9L3BlcnNvbmFsYXJlYS9Mb2dpbmApO1xuXG4gICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuTG9nZ2luZ0luKTtcblxuICAgIGNvbnN0IHZhbGlkYXRlVXJsID0gYCR7dGhpcy5zZXJ2aWNlc1VybH0/cmVxTmFtZT1WYWxpZGF0ZUlkRGF0YWA7XG4gICAgY29uc3QgdmFsaWRhdGVSZXF1ZXN0ID0ge1xuICAgICAgaWQ6IGNyZWRlbnRpYWxzLmlkLFxuICAgICAgY2FyZFN1ZmZpeDogY3JlZGVudGlhbHMuY2FyZDZEaWdpdHMsXG4gICAgICBjb3VudHJ5Q29kZTogQ09VTlRSWV9DT0RFLFxuICAgICAgaWRUeXBlOiBJRF9UWVBFLFxuICAgICAgY2hlY2tMZXZlbDogJzEnLFxuICAgICAgY29tcGFueUNvZGU6IHRoaXMuY29tcGFueUNvZGUsXG4gICAgfTtcbiAgICBkZWJ1ZygnbG9nZ2luZyBpbiB3aXRoIHZhbGlkYXRlIHJlcXVlc3QnKTtcbiAgICBjb25zdCB2YWxpZGF0ZVJlc3VsdCA9IGF3YWl0IGZldGNoUG9zdFdpdGhpblBhZ2U8U2NyYXBlZExvZ2luVmFsaWRhdGlvbj4odGhpcy5wYWdlLCB2YWxpZGF0ZVVybCwgdmFsaWRhdGVSZXF1ZXN0KTtcbiAgICBpZiAoXG4gICAgICAhdmFsaWRhdGVSZXN1bHQgfHxcbiAgICAgICF2YWxpZGF0ZVJlc3VsdC5IZWFkZXIgfHxcbiAgICAgIHZhbGlkYXRlUmVzdWx0LkhlYWRlci5TdGF0dXMgIT09ICcxJyB8fFxuICAgICAgIXZhbGlkYXRlUmVzdWx0LlZhbGlkYXRlSWREYXRhQmVhblxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bmtub3duIGVycm9yIGR1cmluZyBsb2dpbicpO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbGlkYXRlUmV0dXJuQ29kZSA9IHZhbGlkYXRlUmVzdWx0LlZhbGlkYXRlSWREYXRhQmVhbi5yZXR1cm5Db2RlO1xuICAgIGRlYnVnKGB1c2VyIHZhbGlkYXRlIHdpdGggcmV0dXJuIGNvZGUgJyR7dmFsaWRhdGVSZXR1cm5Db2RlfSdgKTtcbiAgICBpZiAodmFsaWRhdGVSZXR1cm5Db2RlID09PSAnMScpIHtcbiAgICAgIGNvbnN0IHsgdXNlck5hbWUgfSA9IHZhbGlkYXRlUmVzdWx0LlZhbGlkYXRlSWREYXRhQmVhbjtcblxuICAgICAgY29uc3QgbG9naW5VcmwgPSBgJHt0aGlzLnNlcnZpY2VzVXJsfT9yZXFOYW1lPXBlcmZvcm1Mb2dvbklgO1xuICAgICAgY29uc3QgcmVxdWVzdCA9IHtcbiAgICAgICAgS29kTWlzaHRhbWVzaDogdXNlck5hbWUsXG4gICAgICAgIE1pc3BhclppaHV5OiBjcmVkZW50aWFscy5pZCxcbiAgICAgICAgU2lzbWE6IGNyZWRlbnRpYWxzLnBhc3N3b3JkLFxuICAgICAgICBjYXJkU3VmZml4OiBjcmVkZW50aWFscy5jYXJkNkRpZ2l0cyxcbiAgICAgICAgY291bnRyeUNvZGU6IENPVU5UUllfQ09ERSxcbiAgICAgICAgaWRUeXBlOiBJRF9UWVBFLFxuICAgICAgfTtcbiAgICAgIGRlYnVnKCd1c2VyIGxvZ2luIHN0YXJ0ZWQnKTtcbiAgICAgIGNvbnN0IGxvZ2luUmVzdWx0ID0gYXdhaXQgZmV0Y2hQb3N0V2l0aGluUGFnZTx7IHN0YXR1czogc3RyaW5nIH0+KHRoaXMucGFnZSwgbG9naW5VcmwsIHJlcXVlc3QpO1xuICAgICAgZGVidWcoYHVzZXIgbG9naW4gd2l0aCBzdGF0dXMgJyR7bG9naW5SZXN1bHQ/LnN0YXR1c30nYCwgbG9naW5SZXN1bHQpO1xuXG4gICAgICBpZiAobG9naW5SZXN1bHQgJiYgbG9naW5SZXN1bHQuc3RhdHVzID09PSAnMScpIHtcbiAgICAgICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuTG9naW5TdWNjZXNzKTtcbiAgICAgICAgZGVidWcoYExvZ2luIGNvbXBsZXRlZCBpbiAke3BlcmZvcm1hbmNlLm5vdygpIC0gbG9naW5TdGFydFRpbWV9bXNgKTtcbiAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSB9O1xuICAgICAgfVxuXG4gICAgICBpZiAobG9naW5SZXN1bHQgJiYgbG9naW5SZXN1bHQuc3RhdHVzID09PSAnMycpIHtcbiAgICAgICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuQ2hhbmdlUGFzc3dvcmQpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIGVycm9yVHlwZTogU2NyYXBlckVycm9yVHlwZXMuQ2hhbmdlUGFzc3dvcmQsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZW1pdFByb2dyZXNzKFNjcmFwZXJQcm9ncmVzc1R5cGVzLkxvZ2luRmFpbGVkKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICBlcnJvclR5cGU6IFNjcmFwZXJFcnJvclR5cGVzLkludmFsaWRQYXNzd29yZCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHZhbGlkYXRlUmV0dXJuQ29kZSA9PT0gJzQnKSB7XG4gICAgICB0aGlzLmVtaXRQcm9ncmVzcyhTY3JhcGVyUHJvZ3Jlc3NUeXBlcy5DaGFuZ2VQYXNzd29yZCk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgZXJyb3JUeXBlOiBTY3JhcGVyRXJyb3JUeXBlcy5DaGFuZ2VQYXNzd29yZCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuTG9naW5GYWlsZWQpO1xuICAgIHJldHVybiB7XG4gICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgIGVycm9yVHlwZTogU2NyYXBlckVycm9yVHlwZXMuSW52YWxpZFBhc3N3b3JkLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBmZXRjaERhdGEoKSB7XG4gICAgY29uc3QgZGVmYXVsdFN0YXJ0TW9tZW50ID0gbW9tZW50KCkuc3VidHJhY3QoMSwgJ3llYXJzJyk7XG4gICAgY29uc3Qgc3RhcnREYXRlID0gdGhpcy5vcHRpb25zLnN0YXJ0RGF0ZSB8fCBkZWZhdWx0U3RhcnRNb21lbnQudG9EYXRlKCk7XG4gICAgY29uc3Qgc3RhcnRNb21lbnQgPSBtb21lbnQubWF4KGRlZmF1bHRTdGFydE1vbWVudCwgbW9tZW50KHN0YXJ0RGF0ZSkpO1xuXG4gICAgcmV0dXJuIGZldGNoQWxsVHJhbnNhY3Rpb25zKFxuICAgICAgdGhpcy5wYWdlLFxuICAgICAgdGhpcy5vcHRpb25zLFxuICAgICAge1xuICAgICAgICBzZXJ2aWNlc1VybDogdGhpcy5zZXJ2aWNlc1VybCxcbiAgICAgICAgY29tcGFueUNvZGU6IHRoaXMuY29tcGFueUNvZGUsXG4gICAgICB9LFxuICAgICAgc3RhcnRNb21lbnQsXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBJc3JhY2FyZEFtZXhCYXNlU2NyYXBlcjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsSUFBQUEsT0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsVUFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsWUFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsUUFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksTUFBQSxHQUFBTCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUss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