israeli-bank-scrapers
Version:
Provide scrapers for all major Israeli banks and credit card companies
245 lines (244 loc) • 41.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _moment = _interopRequireDefault(require("moment"));
var _constants = require("../constants");
var _elementsInteractions = require("../helpers/elements-interactions");
var _transactions = require("../helpers/transactions");
var _navigation = require("../helpers/navigation");
var _transactions2 = require("../transactions");
var _baseScraperWithBrowser = require("./base-scraper-with-browser");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const BASE_URL = 'https://hb.unionbank.co.il';
const TRANSACTIONS_URL = `${BASE_URL}/eBanking/Accounts/ExtendedActivity.aspx#/`;
const DATE_FORMAT = 'DD/MM/YY';
const NO_TRANSACTION_IN_DATE_RANGE_TEXT = 'לא קיימות תנועות מתאימות על פי הסינון שהוגדר';
const DATE_HEADER = 'תאריך';
const DESCRIPTION_HEADER = 'תיאור';
const REFERENCE_HEADER = 'אסמכתא';
const DEBIT_HEADER = 'חובה';
const CREDIT_HEADER = 'זכות';
const PENDING_TRANSACTIONS_TABLE_ID = 'trTodayActivityNapaTableUpper';
const COMPLETED_TRANSACTIONS_TABLE_ID = 'ctlActivityTable';
const ERROR_MESSAGE_CLASS = 'errInfo';
const ACCOUNTS_DROPDOWN_SELECTOR = 'select#ddlAccounts_m_ddl';
function getPossibleLoginResults() {
const urls = {};
urls[_baseScraperWithBrowser.LoginResults.Success] = [/eBanking\/Accounts/];
urls[_baseScraperWithBrowser.LoginResults.InvalidPassword] = [/InternalSite\/CustomUpdate\/leumi\/LoginPage.ASP/];
return urls;
}
function createLoginFields(credentials) {
return [{
selector: '#uid',
value: credentials.username
}, {
selector: '#password',
value: credentials.password
}];
}
function getAmountData(amountStr) {
const amountStrCopy = amountStr.replace(',', '');
return parseFloat(amountStrCopy);
}
function getTxnAmount(txn) {
const credit = getAmountData(txn.credit);
const debit = getAmountData(txn.debit);
return (Number.isNaN(credit) ? 0 : credit) - (Number.isNaN(debit) ? 0 : debit);
}
function convertTransactions(txns, options) {
return txns.map(txn => {
const convertedDate = (0, _moment.default)(txn.date, DATE_FORMAT).toISOString();
const convertedAmount = getTxnAmount(txn);
const result = {
type: _transactions2.TransactionTypes.Normal,
identifier: txn.reference ? parseInt(txn.reference, 10) : undefined,
date: convertedDate,
processedDate: convertedDate,
originalAmount: convertedAmount,
originalCurrency: _constants.SHEKEL_CURRENCY,
chargedAmount: convertedAmount,
status: txn.status,
description: txn.description,
memo: txn.memo
};
if (options?.includeRawTransaction) {
result.rawTransaction = (0, _transactions.getRawTransaction)(txn);
}
return result;
});
}
function getTransactionDate(tds, txnsTableHeaders) {
return (tds[txnsTableHeaders[DATE_HEADER]] || '').trim();
}
function getTransactionDescription(tds, txnsTableHeaders) {
return (tds[txnsTableHeaders[DESCRIPTION_HEADER]] || '').trim();
}
function getTransactionReference(tds, txnsTableHeaders) {
return (tds[txnsTableHeaders[REFERENCE_HEADER]] || '').trim();
}
function getTransactionDebit(tds, txnsTableHeaders) {
return (tds[txnsTableHeaders[DEBIT_HEADER]] || '').trim();
}
function getTransactionCredit(tds, txnsTableHeaders) {
return (tds[txnsTableHeaders[CREDIT_HEADER]] || '').trim();
}
function extractTransactionDetails(txnRow, txnsTableHeaders, txnStatus) {
const tds = txnRow.innerTds;
return {
status: txnStatus,
date: getTransactionDate(tds, txnsTableHeaders),
description: getTransactionDescription(tds, txnsTableHeaders),
reference: getTransactionReference(tds, txnsTableHeaders),
debit: getTransactionDebit(tds, txnsTableHeaders),
credit: getTransactionCredit(tds, txnsTableHeaders),
memo: ''
};
}
function isExpandedDescRow(txnRow) {
return txnRow.id === 'rowAdded';
}
function editLastTransactionDesc(txnRow, lastTxn) {
lastTxn.description = `${lastTxn.description} ${txnRow.innerTds[0]}`;
return lastTxn;
}
function handleTransactionRow(txns, txnsTableHeaders, txnRow, txnType) {
if (isExpandedDescRow(txnRow)) {
const lastTransaction = txns.pop();
if (lastTransaction) {
txns.push(editLastTransactionDesc(txnRow, lastTransaction));
} else {
throw new Error('internal union-bank error');
}
} else {
txns.push(extractTransactionDetails(txnRow, txnsTableHeaders, txnType));
}
}
async function getTransactionsTableHeaders(page, tableTypeId) {
const headersMap = [];
const headersObjs = await (0, _elementsInteractions.pageEvalAll)(page, `#WorkSpaceBox #${tableTypeId} tr[class='header'] th`, null, ths => {
return ths.map((th, index) => ({
text: th.innerText.trim(),
index
}));
});
for (const headerObj of headersObjs) {
headersMap[headerObj.text] = headerObj.index;
}
return headersMap;
}
async function extractTransactionsFromTable(page, tableTypeId, txnType) {
const txns = [];
const transactionsTableHeaders = await getTransactionsTableHeaders(page, tableTypeId);
const transactionsRows = await (0, _elementsInteractions.pageEvalAll)(page, `#WorkSpaceBox #${tableTypeId} tr[class]:not([class='header'])`, [], trs => {
return trs.map(tr => ({
id: tr.getAttribute('id') || '',
innerTds: Array.from(tr.getElementsByTagName('td')).map(td => td.innerText)
}));
});
for (const txnRow of transactionsRows) {
handleTransactionRow(txns, transactionsTableHeaders, txnRow, txnType);
}
return txns;
}
async function isNoTransactionInDateRangeError(page) {
const hasErrorInfoElement = await (0, _elementsInteractions.elementPresentOnPage)(page, `.${ERROR_MESSAGE_CLASS}`);
if (hasErrorInfoElement) {
const errorText = await page.$eval(`.${ERROR_MESSAGE_CLASS}`, errorElement => {
return errorElement.innerText;
});
return errorText.trim() === NO_TRANSACTION_IN_DATE_RANGE_TEXT;
}
return false;
}
async function chooseAccount(page, accountId) {
const hasDropDownList = await (0, _elementsInteractions.elementPresentOnPage)(page, ACCOUNTS_DROPDOWN_SELECTOR);
if (hasDropDownList) {
await (0, _elementsInteractions.dropdownSelect)(page, ACCOUNTS_DROPDOWN_SELECTOR, accountId);
}
}
async function searchByDates(page, startDate) {
await (0, _elementsInteractions.dropdownSelect)(page, 'select#ddlTransactionPeriod', '004');
await (0, _elementsInteractions.waitUntilElementFound)(page, 'select#ddlTransactionPeriod');
await (0, _elementsInteractions.fillInput)(page, 'input#dtFromDate_textBox', startDate.format(DATE_FORMAT));
await (0, _elementsInteractions.clickButton)(page, 'input#btnDisplayDates');
await (0, _navigation.waitForNavigation)(page);
}
async function getAccountNumber(page) {
const selectedSnifAccount = await page.$eval('#ddlAccounts_m_ddl option[selected="selected"]', option => {
return option.innerText;
});
return selectedSnifAccount.replace('/', '_');
}
async function expandTransactionsTable(page) {
const hasExpandAllButton = await (0, _elementsInteractions.elementPresentOnPage)(page, "a[id*='lnkCtlExpandAll']");
if (hasExpandAllButton) {
await (0, _elementsInteractions.clickButton)(page, "a[id*='lnkCtlExpandAll']");
}
}
async function scrapeTransactionsFromTable(page, options) {
const pendingTxns = await extractTransactionsFromTable(page, PENDING_TRANSACTIONS_TABLE_ID, _transactions2.TransactionStatuses.Pending);
const completedTxns = await extractTransactionsFromTable(page, COMPLETED_TRANSACTIONS_TABLE_ID, _transactions2.TransactionStatuses.Completed);
const txns = [...pendingTxns, ...completedTxns];
return convertTransactions(txns, options);
}
async function getAccountTransactions(page, options) {
await Promise.race([(0, _elementsInteractions.waitUntilElementFound)(page, `#${COMPLETED_TRANSACTIONS_TABLE_ID}`, false), (0, _elementsInteractions.waitUntilElementFound)(page, `.${ERROR_MESSAGE_CLASS}`, false)]);
const noTransactionInRangeError = await isNoTransactionInDateRangeError(page);
if (noTransactionInRangeError) {
return [];
}
await expandTransactionsTable(page);
return scrapeTransactionsFromTable(page, options);
}
async function fetchAccountData(page, startDate, accountId, options) {
await chooseAccount(page, accountId);
await searchByDates(page, startDate);
const accountNumber = await getAccountNumber(page);
const txns = await getAccountTransactions(page, options);
return {
accountNumber,
txns
};
}
async function fetchAccounts(page, startDate, options) {
const accounts = [];
const accountsList = await (0, _elementsInteractions.dropdownElements)(page, ACCOUNTS_DROPDOWN_SELECTOR);
for (const account of accountsList) {
if (account.value !== '-1') {
// Skip "All accounts" option
const accountData = await fetchAccountData(page, startDate, account.value, options);
accounts.push(accountData);
}
}
return accounts;
}
async function waitForPostLogin(page) {
return Promise.race([(0, _elementsInteractions.waitUntilElementFound)(page, '#signoff', true), (0, _elementsInteractions.waitUntilElementFound)(page, '#restore', true)]);
}
class UnionBankScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser {
getLoginOptions(credentials) {
return {
loginUrl: `${BASE_URL}`,
fields: createLoginFields(credentials),
submitButtonSelector: '#enter',
postAction: async () => waitForPostLogin(this.page),
possibleResults: getPossibleLoginResults()
};
}
async fetchData() {
const defaultStartMoment = (0, _moment.default)().subtract(1, 'years').add(1, 'day');
const startDate = this.options.startDate || defaultStartMoment.toDate();
const startMoment = _moment.default.max(defaultStartMoment, (0, _moment.default)(startDate));
await this.navigateTo(TRANSACTIONS_URL);
const accounts = await fetchAccounts(this.page, startMoment, this.options);
return {
success: true,
accounts
};
}
}
var _default = exports.default = UnionBankScraper;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29uc3RhbnRzIiwiX2VsZW1lbnRzSW50ZXJhY3Rpb25zIiwiX3RyYW5zYWN0aW9ucyIsIl9uYXZpZ2F0aW9uIiwiX3RyYW5zYWN0aW9uczIiLCJfYmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsIkJBU0VfVVJMIiwiVFJBTlNBQ1RJT05TX1VSTCIsIkRBVEVfRk9STUFUIiwiTk9fVFJBTlNBQ1RJT05fSU5fREFURV9SQU5HRV9URVhUIiwiREFURV9IRUFERVIiLCJERVNDUklQVElPTl9IRUFERVIiLCJSRUZFUkVOQ0VfSEVBREVSIiwiREVCSVRfSEVBREVSIiwiQ1JFRElUX0hFQURFUiIsIlBFTkRJTkdfVFJBTlNBQ1RJT05TX1RBQkxFX0lEIiwiQ09NUExFVEVEX1RSQU5TQUNUSU9OU19UQUJMRV9JRCIsIkVSUk9SX01FU1NBR0VfQ0xBU1MiLCJBQ0NPVU5UU19EUk9QRE9XTl9TRUxFQ1RPUiIsImdldFBvc3NpYmxlTG9naW5SZXN1bHRzIiwidXJscyIsIkxvZ2luUmVzdWx0cyIsIlN1Y2Nlc3MiLCJJbnZhbGlkUGFzc3dvcmQiLCJjcmVhdGVMb2dpbkZpZWxkcyIsImNyZWRlbnRpYWxzIiwic2VsZWN0b3IiLCJ2YWx1ZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJnZXRBbW91bnREYXRhIiwiYW1vdW50U3RyIiwiYW1vdW50U3RyQ29weSIsInJlcGxhY2UiLCJwYXJzZUZsb2F0IiwiZ2V0VHhuQW1vdW50IiwidHhuIiwiY3JlZGl0IiwiZGViaXQiLCJOdW1iZXIiLCJpc05hTiIsImNvbnZlcnRUcmFuc2FjdGlvbnMiLCJ0eG5zIiwib3B0aW9ucyIsIm1hcCIsImNvbnZlcnRlZERhdGUiLCJtb21lbnQiLCJkYXRlIiwidG9JU09TdHJpbmciLCJjb252ZXJ0ZWRBbW91bnQiLCJyZXN1bHQiLCJ0eXBlIiwiVHJhbnNhY3Rpb25UeXBlcyIsIk5vcm1hbCIsImlkZW50aWZpZXIiLCJyZWZlcmVuY2UiLCJwYXJzZUludCIsInVuZGVmaW5lZCIsInByb2Nlc3NlZERhdGUiLCJvcmlnaW5hbEFtb3VudCIsIm9yaWdpbmFsQ3VycmVuY3kiLCJTSEVLRUxfQ1VSUkVOQ1kiLCJjaGFyZ2VkQW1vdW50Iiwic3RhdHVzIiwiZGVzY3JpcHRpb24iLCJtZW1vIiwiaW5jbHVkZVJhd1RyYW5zYWN0aW9uIiwicmF3VHJhbnNhY3Rpb24iLCJnZXRSYXdUcmFuc2FjdGlvbiIsImdldFRyYW5zYWN0aW9uRGF0ZSIsInRkcyIsInR4bnNUYWJsZUhlYWRlcnMiLCJ0cmltIiwiZ2V0VHJhbnNhY3Rpb25EZXNjcmlwdGlvbiIsImdldFRyYW5zYWN0aW9uUmVmZXJlbmNlIiwiZ2V0VHJhbnNhY3Rpb25EZWJpdCIsImdldFRyYW5zYWN0aW9uQ3JlZGl0IiwiZXh0cmFjdFRyYW5zYWN0aW9uRGV0YWlscyIsInR4blJvdyIsInR4blN0YXR1cyIsImlubmVyVGRzIiwiaXNFeHBhbmRlZERlc2NSb3ciLCJpZCIsImVkaXRMYXN0VHJhbnNhY3Rpb25EZXNjIiwibGFzdFR4biIsImhhbmRsZVRyYW5zYWN0aW9uUm93IiwidHhuVHlwZSIsImxhc3RUcmFuc2FjdGlvbiIsInBvcCIsInB1c2giLCJFcnJvciIsImdldFRyYW5zYWN0aW9uc1RhYmxlSGVhZGVycyIsInBhZ2UiLCJ0YWJsZVR5cGVJZCIsImhlYWRlcnNNYXAiLCJoZWFkZXJzT2JqcyIsInBhZ2VFdmFsQWxsIiwidGhzIiwidGgiLCJpbmRleCIsInRleHQiLCJpbm5lclRleHQiLCJoZWFkZXJPYmoiLCJleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVRhYmxlIiwidHJhbnNhY3Rpb25zVGFibGVIZWFkZXJzIiwidHJhbnNhY3Rpb25zUm93cyIsInRycyIsInRyIiwiZ2V0QXR0cmlidXRlIiwiQXJyYXkiLCJmcm9tIiwiZ2V0RWxlbWVudHNCeVRhZ05hbWUiLCJ0ZCIsImlzTm9UcmFuc2FjdGlvbkluRGF0ZVJhbmdlRXJyb3IiLCJoYXNFcnJvckluZm9FbGVtZW50IiwiZWxlbWVudFByZXNlbnRPblBhZ2UiLCJlcnJvclRleHQiLCIkZXZhbCIsImVycm9yRWxlbWVudCIsImNob29zZUFjY291bnQiLCJhY2NvdW50SWQiLCJoYXNEcm9wRG93bkxpc3QiLCJkcm9wZG93blNlbGVjdCIsInNlYXJjaEJ5RGF0ZXMiLCJzdGFydERhdGUiLCJ3YWl0VW50aWxFbGVtZW50Rm91bmQiLCJmaWxsSW5wdXQiLCJmb3JtYXQiLCJjbGlja0J1dHRvbiIsIndhaXRGb3JOYXZpZ2F0aW9uIiwiZ2V0QWNjb3VudE51bWJlciIsInNlbGVjdGVkU25pZkFjY291bnQiLCJvcHRpb24iLCJleHBhbmRUcmFuc2FjdGlvbnNUYWJsZSIsImhhc0V4cGFuZEFsbEJ1dHRvbiIsInNjcmFwZVRyYW5zYWN0aW9uc0Zyb21UYWJsZSIsInBlbmRpbmdUeG5zIiwiVHJhbnNhY3Rpb25TdGF0dXNlcyIsIlBlbmRpbmciLCJjb21wbGV0ZWRUeG5zIiwiQ29tcGxldGVkIiwiZ2V0QWNjb3VudFRyYW5zYWN0aW9ucyIsIlByb21pc2UiLCJyYWNlIiwibm9UcmFuc2FjdGlvbkluUmFuZ2VFcnJvciIsImZldGNoQWNjb3VudERhdGEiLCJhY2NvdW50TnVtYmVyIiwiZmV0Y2hBY2NvdW50cyIsImFjY291bnRzIiwiYWNjb3VudHNMaXN0IiwiZHJvcGRvd25FbGVtZW50cyIsImFjY291bnQiLCJhY2NvdW50RGF0YSIsIndhaXRGb3JQb3N0TG9naW4iLCJVbmlvbkJhbmtTY3JhcGVyIiwiQmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImdldExvZ2luT3B0aW9ucyIsImxvZ2luVXJsIiwiZmllbGRzIiwic3VibWl0QnV0dG9uU2VsZWN0b3IiLCJwb3N0QWN0aW9uIiwicG9zc2libGVSZXN1bHRzIiwiZmV0Y2hEYXRhIiwiZGVmYXVsdFN0YXJ0TW9tZW50Iiwic3VidHJhY3QiLCJhZGQiLCJ0b0RhdGUiLCJzdGFydE1vbWVudCIsIm1heCIsIm5hdmlnYXRlVG8iLCJzdWNjZXNzIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmFwZXJzL3VuaW9uLWJhbmsudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG1vbWVudCwgeyB0eXBlIE1vbWVudCB9IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgeyB0eXBlIFBhZ2UgfSBmcm9tICdwdXBwZXRlZXInO1xuaW1wb3J0IHsgU0hFS0VMX0NVUlJFTkNZIH0gZnJvbSAnLi4vY29uc3RhbnRzJztcbmltcG9ydCB7XG4gIGNsaWNrQnV0dG9uLFxuICBkcm9wZG93bkVsZW1lbnRzLFxuICBkcm9wZG93blNlbGVjdCxcbiAgZWxlbWVudFByZXNlbnRPblBhZ2UsXG4gIGZpbGxJbnB1dCxcbiAgcGFnZUV2YWxBbGwsXG4gIHdhaXRVbnRpbEVsZW1lbnRGb3VuZCxcbn0gZnJvbSAnLi4vaGVscGVycy9lbGVtZW50cy1pbnRlcmFjdGlvbnMnO1xuaW1wb3J0IHsgZ2V0UmF3VHJhbnNhY3Rpb24gfSBmcm9tICcuLi9oZWxwZXJzL3RyYW5zYWN0aW9ucyc7XG5pbXBvcnQgeyB3YWl0Rm9yTmF2aWdhdGlvbiB9IGZyb20gJy4uL2hlbHBlcnMvbmF2aWdhdGlvbic7XG5pbXBvcnQgeyBUcmFuc2FjdGlvblN0YXR1c2VzLCBUcmFuc2FjdGlvblR5cGVzLCB0eXBlIFRyYW5zYWN0aW9uLCB0eXBlIFRyYW5zYWN0aW9uc0FjY291bnQgfSBmcm9tICcuLi90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgQmFzZVNjcmFwZXJXaXRoQnJvd3NlciwgTG9naW5SZXN1bHRzLCB0eXBlIFBvc3NpYmxlTG9naW5SZXN1bHRzIH0gZnJvbSAnLi9iYXNlLXNjcmFwZXItd2l0aC1icm93c2VyJztcbmltcG9ydCB7IHR5cGUgU2NyYXBlck9wdGlvbnMgfSBmcm9tICcuL2ludGVyZmFjZSc7XG5cbmNvbnN0IEJBU0VfVVJMID0gJ2h0dHBzOi8vaGIudW5pb25iYW5rLmNvLmlsJztcbmNvbnN0IFRSQU5TQUNUSU9OU19VUkwgPSBgJHtCQVNFX1VSTH0vZUJhbmtpbmcvQWNjb3VudHMvRXh0ZW5kZWRBY3Rpdml0eS5hc3B4Iy9gO1xuY29uc3QgREFURV9GT1JNQVQgPSAnREQvTU0vWVknO1xuY29uc3QgTk9fVFJBTlNBQ1RJT05fSU5fREFURV9SQU5HRV9URVhUID0gJ9ec15Ag16fXmdeZ157XldeqINeq16DXldei15XXqiDXnteq15DXmdee15XXqiDXotecINek15kg15TXodeZ16DXldefINep15TXldeS15PXqCc7XG5jb25zdCBEQVRFX0hFQURFUiA9ICfXqteQ16jXmdeaJztcbmNvbnN0IERFU0NSSVBUSU9OX0hFQURFUiA9ICfXqteZ15DXldeoJztcbmNvbnN0IFJFRkVSRU5DRV9IRUFERVIgPSAn15DXodee15vXqteQJztcbmNvbnN0IERFQklUX0hFQURFUiA9ICfXl9eV15HXlCc7XG5jb25zdCBDUkVESVRfSEVBREVSID0gJ9eW15vXldeqJztcbmNvbnN0IFBFTkRJTkdfVFJBTlNBQ1RJT05TX1RBQkxFX0lEID0gJ3RyVG9kYXlBY3Rpdml0eU5hcGFUYWJsZVVwcGVyJztcbmNvbnN0IENPTVBMRVRFRF9UUkFOU0FDVElPTlNfVEFCTEVfSUQgPSAnY3RsQWN0aXZpdHlUYWJsZSc7XG5jb25zdCBFUlJPUl9NRVNTQUdFX0NMQVNTID0gJ2VyckluZm8nO1xuY29uc3QgQUNDT1VOVFNfRFJPUERPV05fU0VMRUNUT1IgPSAnc2VsZWN0I2RkbEFjY291bnRzX21fZGRsJztcblxuZnVuY3Rpb24gZ2V0UG9zc2libGVMb2dpblJlc3VsdHMoKSB7XG4gIGNvbnN0IHVybHM6IFBvc3NpYmxlTG9naW5SZXN1bHRzID0ge307XG4gIHVybHNbTG9naW5SZXN1bHRzLlN1Y2Nlc3NdID0gWy9lQmFua2luZ1xcL0FjY291bnRzL107XG4gIHVybHNbTG9naW5SZXN1bHRzLkludmFsaWRQYXNzd29yZF0gPSBbL0ludGVybmFsU2l0ZVxcL0N1c3RvbVVwZGF0ZVxcL2xldW1pXFwvTG9naW5QYWdlLkFTUC9dO1xuICByZXR1cm4gdXJscztcbn1cblxuZnVuY3Rpb24gY3JlYXRlTG9naW5GaWVsZHMoY3JlZGVudGlhbHM6IFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzKSB7XG4gIHJldHVybiBbXG4gICAgeyBzZWxlY3RvcjogJyN1aWQnLCB2YWx1ZTogY3JlZGVudGlhbHMudXNlcm5hbWUgfSxcbiAgICB7IHNlbGVjdG9yOiAnI3Bhc3N3b3JkJywgdmFsdWU6IGNyZWRlbnRpYWxzLnBhc3N3b3JkIH0sXG4gIF07XG59XG5cbmZ1bmN0aW9uIGdldEFtb3VudERhdGEoYW1vdW50U3RyOiBzdHJpbmcpIHtcbiAgY29uc3QgYW1vdW50U3RyQ29weSA9IGFtb3VudFN0ci5yZXBsYWNlKCcsJywgJycpO1xuICByZXR1cm4gcGFyc2VGbG9hdChhbW91bnRTdHJDb3B5KTtcbn1cblxuaW50ZXJmYWNlIFNjcmFwZWRUcmFuc2FjdGlvbiB7XG4gIGNyZWRpdDogc3RyaW5nO1xuICBkZWJpdDogc3RyaW5nO1xuICBkYXRlOiBzdHJpbmc7XG4gIHJlZmVyZW5jZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgbWVtbzogc3RyaW5nO1xuICBzdGF0dXM6IFRyYW5zYWN0aW9uU3RhdHVzZXM7XG59XG5cbmZ1bmN0aW9uIGdldFR4bkFtb3VudCh0eG46IFNjcmFwZWRUcmFuc2FjdGlvbikge1xuICBjb25zdCBjcmVkaXQgPSBnZXRBbW91bnREYXRhKHR4bi5jcmVkaXQpO1xuICBjb25zdCBkZWJpdCA9IGdldEFtb3VudERhdGEodHhuLmRlYml0KTtcbiAgcmV0dXJuIChOdW1iZXIuaXNOYU4oY3JlZGl0KSA/IDAgOiBjcmVkaXQpIC0gKE51bWJlci5pc05hTihkZWJpdCkgPyAwIDogZGViaXQpO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0VHJhbnNhY3Rpb25zKHR4bnM6IFNjcmFwZWRUcmFuc2FjdGlvbltdLCBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMpOiBUcmFuc2FjdGlvbltdIHtcbiAgcmV0dXJuIHR4bnMubWFwKHR4biA9PiB7XG4gICAgY29uc3QgY29udmVydGVkRGF0ZSA9IG1vbWVudCh0eG4uZGF0ZSwgREFURV9GT1JNQVQpLnRvSVNPU3RyaW5nKCk7XG4gICAgY29uc3QgY29udmVydGVkQW1vdW50ID0gZ2V0VHhuQW1vdW50KHR4bik7XG4gICAgY29uc3QgcmVzdWx0OiBUcmFuc2FjdGlvbiA9IHtcbiAgICAgIHR5cGU6IFRyYW5zYWN0aW9uVHlwZXMuTm9ybWFsLFxuICAgICAgaWRlbnRpZmllcjogdHhuLnJlZmVyZW5jZSA/IHBhcnNlSW50KHR4bi5yZWZlcmVuY2UsIDEwKSA6IHVuZGVmaW5lZCxcbiAgICAgIGRhdGU6IGNvbnZlcnRlZERhdGUsXG4gICAgICBwcm9jZXNzZWREYXRlOiBjb252ZXJ0ZWREYXRlLFxuICAgICAgb3JpZ2luYWxBbW91bnQ6IGNvbnZlcnRlZEFtb3VudCxcbiAgICAgIG9yaWdpbmFsQ3VycmVuY3k6IFNIRUtFTF9DVVJSRU5DWSxcbiAgICAgIGNoYXJnZWRBbW91bnQ6IGNvbnZlcnRlZEFtb3VudCxcbiAgICAgIHN0YXR1czogdHhuLnN0YXR1cyxcbiAgICAgIGRlc2NyaXB0aW9uOiB0eG4uZGVzY3JpcHRpb24sXG4gICAgICBtZW1vOiB0eG4ubWVtbyxcbiAgICB9O1xuXG4gICAgaWYgKG9wdGlvbnM/LmluY2x1ZGVSYXdUcmFuc2FjdGlvbikge1xuICAgICAgcmVzdWx0LnJhd1RyYW5zYWN0aW9uID0gZ2V0UmF3VHJhbnNhY3Rpb24odHhuKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9KTtcbn1cblxudHlwZSBUcmFuc2FjdGlvbnNUciA9IHsgaWQ6IHN0cmluZzsgaW5uZXJUZHM6IFRyYW5zYWN0aW9uc1RyVGRzIH07XG50eXBlIFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzID0gUmVjb3JkPHN0cmluZywgbnVtYmVyPjtcbnR5cGUgVHJhbnNhY3Rpb25zVHJUZHMgPSBzdHJpbmdbXTtcblxuZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25EYXRlKHRkczogVHJhbnNhY3Rpb25zVHJUZHMsIHR4bnNUYWJsZUhlYWRlcnM6IFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzKSB7XG4gIHJldHVybiAodGRzW3R4bnNUYWJsZUhlYWRlcnNbREFURV9IRUFERVJdXSB8fCAnJykudHJpbSgpO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2FjdGlvbkRlc2NyaXB0aW9uKHRkczogVHJhbnNhY3Rpb25zVHJUZHMsIHR4bnNUYWJsZUhlYWRlcnM6IFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzKSB7XG4gIHJldHVybiAodGRzW3R4bnNUYWJsZUhlYWRlcnNbREVTQ1JJUFRJT05fSEVBREVSXV0gfHwgJycpLnRyaW0oKTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25SZWZlcmVuY2UodGRzOiBUcmFuc2FjdGlvbnNUclRkcywgdHhuc1RhYmxlSGVhZGVyczogVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMpIHtcbiAgcmV0dXJuICh0ZHNbdHhuc1RhYmxlSGVhZGVyc1tSRUZFUkVOQ0VfSEVBREVSXV0gfHwgJycpLnRyaW0oKTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25EZWJpdCh0ZHM6IFRyYW5zYWN0aW9uc1RyVGRzLCB0eG5zVGFibGVIZWFkZXJzOiBUcmFuc2FjdGlvblRhYmxlSGVhZGVycykge1xuICByZXR1cm4gKHRkc1t0eG5zVGFibGVIZWFkZXJzW0RFQklUX0hFQURFUl1dIHx8ICcnKS50cmltKCk7XG59XG5cbmZ1bmN0aW9uIGdldFRyYW5zYWN0aW9uQ3JlZGl0KHRkczogVHJhbnNhY3Rpb25zVHJUZHMsIHR4bnNUYWJsZUhlYWRlcnM6IFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzKSB7XG4gIHJldHVybiAodGRzW3R4bnNUYWJsZUhlYWRlcnNbQ1JFRElUX0hFQURFUl1dIHx8ICcnKS50cmltKCk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RUcmFuc2FjdGlvbkRldGFpbHMoXG4gIHR4blJvdzogVHJhbnNhY3Rpb25zVHIsXG4gIHR4bnNUYWJsZUhlYWRlcnM6IFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzLFxuICB0eG5TdGF0dXM6IFRyYW5zYWN0aW9uU3RhdHVzZXMsXG4pOiBTY3JhcGVkVHJhbnNhY3Rpb24ge1xuICBjb25zdCB0ZHMgPSB0eG5Sb3cuaW5uZXJUZHM7XG4gIHJldHVybiB7XG4gICAgc3RhdHVzOiB0eG5TdGF0dXMsXG4gICAgZGF0ZTogZ2V0VHJhbnNhY3Rpb25EYXRlKHRkcywgdHhuc1RhYmxlSGVhZGVycyksXG4gICAgZGVzY3JpcHRpb246IGdldFRyYW5zYWN0aW9uRGVzY3JpcHRpb24odGRzLCB0eG5zVGFibGVIZWFkZXJzKSxcbiAgICByZWZlcmVuY2U6IGdldFRyYW5zYWN0aW9uUmVmZXJlbmNlKHRkcywgdHhuc1RhYmxlSGVhZGVycyksXG4gICAgZGViaXQ6IGdldFRyYW5zYWN0aW9uRGViaXQodGRzLCB0eG5zVGFibGVIZWFkZXJzKSxcbiAgICBjcmVkaXQ6IGdldFRyYW5zYWN0aW9uQ3JlZGl0KHRkcywgdHhuc1RhYmxlSGVhZGVycyksXG4gICAgbWVtbzogJycsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGlzRXhwYW5kZWREZXNjUm93KHR4blJvdzogVHJhbnNhY3Rpb25zVHIpIHtcbiAgcmV0dXJuIHR4blJvdy5pZCA9PT0gJ3Jvd0FkZGVkJztcbn1cblxuZnVuY3Rpb24gZWRpdExhc3RUcmFuc2FjdGlvbkRlc2ModHhuUm93OiBUcmFuc2FjdGlvbnNUciwgbGFzdFR4bjogU2NyYXBlZFRyYW5zYWN0aW9uKTogU2NyYXBlZFRyYW5zYWN0aW9uIHtcbiAgbGFzdFR4bi5kZXNjcmlwdGlvbiA9IGAke2xhc3RUeG4uZGVzY3JpcHRpb259ICR7dHhuUm93LmlubmVyVGRzWzBdfWA7XG4gIHJldHVybiBsYXN0VHhuO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVUcmFuc2FjdGlvblJvdyhcbiAgdHhuczogU2NyYXBlZFRyYW5zYWN0aW9uW10sXG4gIHR4bnNUYWJsZUhlYWRlcnM6IFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzLFxuICB0eG5Sb3c6IFRyYW5zYWN0aW9uc1RyLFxuICB0eG5UeXBlOiBUcmFuc2FjdGlvblN0YXR1c2VzLFxuKSB7XG4gIGlmIChpc0V4cGFuZGVkRGVzY1Jvdyh0eG5Sb3cpKSB7XG4gICAgY29uc3QgbGFzdFRyYW5zYWN0aW9uID0gdHhucy5wb3AoKTtcbiAgICBpZiAobGFzdFRyYW5zYWN0aW9uKSB7XG4gICAgICB0eG5zLnB1c2goZWRpdExhc3RUcmFuc2FjdGlvbkRlc2ModHhuUm93LCBsYXN0VHJhbnNhY3Rpb24pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnRlcm5hbCB1bmlvbi1iYW5rIGVycm9yJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHR4bnMucHVzaChleHRyYWN0VHJhbnNhY3Rpb25EZXRhaWxzKHR4blJvdywgdHhuc1RhYmxlSGVhZGVycywgdHhuVHlwZSkpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFRyYW5zYWN0aW9uc1RhYmxlSGVhZGVycyhwYWdlOiBQYWdlLCB0YWJsZVR5cGVJZDogc3RyaW5nKSB7XG4gIGNvbnN0IGhlYWRlcnNNYXA6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBbXTtcbiAgY29uc3QgaGVhZGVyc09ianMgPSBhd2FpdCBwYWdlRXZhbEFsbChwYWdlLCBgI1dvcmtTcGFjZUJveCAjJHt0YWJsZVR5cGVJZH0gdHJbY2xhc3M9J2hlYWRlciddIHRoYCwgbnVsbCwgdGhzID0+IHtcbiAgICByZXR1cm4gdGhzLm1hcCgodGgsIGluZGV4KSA9PiAoe1xuICAgICAgdGV4dDogKHRoIGFzIEhUTUxFbGVtZW50KS5pbm5lclRleHQudHJpbSgpLFxuICAgICAgaW5kZXgsXG4gICAgfSkpO1xuICB9KTtcblxuICBmb3IgKGNvbnN0IGhlYWRlck9iaiBvZiBoZWFkZXJzT2Jqcykge1xuICAgIGhlYWRlcnNNYXBbaGVhZGVyT2JqLnRleHRdID0gaGVhZGVyT2JqLmluZGV4O1xuICB9XG4gIHJldHVybiBoZWFkZXJzTWFwO1xufVxuXG5hc3luYyBmdW5jdGlvbiBleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVRhYmxlKFxuICBwYWdlOiBQYWdlLFxuICB0YWJsZVR5cGVJZDogc3RyaW5nLFxuICB0eG5UeXBlOiBUcmFuc2FjdGlvblN0YXR1c2VzLFxuKTogUHJvbWlzZTxTY3JhcGVkVHJhbnNhY3Rpb25bXT4ge1xuICBjb25zdCB0eG5zOiBTY3JhcGVkVHJhbnNhY3Rpb25bXSA9IFtdO1xuICBjb25zdCB0cmFuc2FjdGlvbnNUYWJsZUhlYWRlcnMgPSBhd2FpdCBnZXRUcmFuc2FjdGlvbnNUYWJsZUhlYWRlcnMocGFnZSwgdGFibGVUeXBlSWQpO1xuXG4gIGNvbnN0IHRyYW5zYWN0aW9uc1Jvd3MgPSBhd2FpdCBwYWdlRXZhbEFsbDxUcmFuc2FjdGlvbnNUcltdPihcbiAgICBwYWdlLFxuICAgIGAjV29ya1NwYWNlQm94ICMke3RhYmxlVHlwZUlkfSB0cltjbGFzc106bm90KFtjbGFzcz0naGVhZGVyJ10pYCxcbiAgICBbXSxcbiAgICB0cnMgPT4ge1xuICAgICAgcmV0dXJuICh0cnMgYXMgSFRNTEVsZW1lbnRbXSkubWFwKHRyID0+ICh7XG4gICAgICAgIGlkOiB0ci5nZXRBdHRyaWJ1dGUoJ2lkJykgfHwgJycsXG4gICAgICAgIGlubmVyVGRzOiBBcnJheS5mcm9tKHRyLmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0ZCcpKS5tYXAodGQgPT4gKHRkIGFzIEhUTUxFbGVtZW50KS5pbm5lclRleHQpLFxuICAgICAgfSkpO1xuICAgIH0sXG4gICk7XG5cbiAgZm9yIChjb25zdCB0eG5Sb3cgb2YgdHJhbnNhY3Rpb25zUm93cykge1xuICAgIGhhbmRsZVRyYW5zYWN0aW9uUm93KHR4bnMsIHRyYW5zYWN0aW9uc1RhYmxlSGVhZGVycywgdHhuUm93LCB0eG5UeXBlKTtcbiAgfVxuICByZXR1cm4gdHhucztcbn1cblxuYXN5bmMgZnVuY3Rpb24gaXNOb1RyYW5zYWN0aW9uSW5EYXRlUmFuZ2VFcnJvcihwYWdlOiBQYWdlKSB7XG4gIGNvbnN0IGhhc0Vycm9ySW5mb0VsZW1lbnQgPSBhd2FpdCBlbGVtZW50UHJlc2VudE9uUGFnZShwYWdlLCBgLiR7RVJST1JfTUVTU0FHRV9DTEFTU31gKTtcbiAgaWYgKGhhc0Vycm9ySW5mb0VsZW1lbnQpIHtcbiAgICBjb25zdCBlcnJvclRleHQgPSBhd2FpdCBwYWdlLiRldmFsKGAuJHtFUlJPUl9NRVNTQUdFX0NMQVNTfWAsIGVycm9yRWxlbWVudCA9PiB7XG4gICAgICByZXR1cm4gKGVycm9yRWxlbWVudCBhcyBIVE1MRWxlbWVudCkuaW5uZXJUZXh0O1xuICAgIH0pO1xuICAgIHJldHVybiBlcnJvclRleHQudHJpbSgpID09PSBOT19UUkFOU0FDVElPTl9JTl9EQVRFX1JBTkdFX1RFWFQ7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5hc3luYyBmdW5jdGlvbiBjaG9vc2VBY2NvdW50KHBhZ2U6IFBhZ2UsIGFjY291bnRJZDogc3RyaW5nKSB7XG4gIGNvbnN0IGhhc0Ryb3BEb3duTGlzdCA9IGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKHBhZ2UsIEFDQ09VTlRTX0RST1BET1dOX1NFTEVDVE9SKTtcbiAgaWYgKGhhc0Ryb3BEb3duTGlzdCkge1xuICAgIGF3YWl0IGRyb3Bkb3duU2VsZWN0KHBhZ2UsIEFDQ09VTlRTX0RST1BET1dOX1NFTEVDVE9SLCBhY2NvdW50SWQpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNlYXJjaEJ5RGF0ZXMocGFnZTogUGFnZSwgc3RhcnREYXRlOiBNb21lbnQpIHtcbiAgYXdhaXQgZHJvcGRvd25TZWxlY3QocGFnZSwgJ3NlbGVjdCNkZGxUcmFuc2FjdGlvblBlcmlvZCcsICcwMDQnKTtcbiAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsICdzZWxlY3QjZGRsVHJhbnNhY3Rpb25QZXJpb2QnKTtcbiAgYXdhaXQgZmlsbElucHV0KHBhZ2UsICdpbnB1dCNkdEZyb21EYXRlX3RleHRCb3gnLCBzdGFydERhdGUuZm9ybWF0KERBVEVfRk9STUFUKSk7XG4gIGF3YWl0IGNsaWNrQnV0dG9uKHBhZ2UsICdpbnB1dCNidG5EaXNwbGF5RGF0ZXMnKTtcbiAgYXdhaXQgd2FpdEZvck5hdmlnYXRpb24ocGFnZSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEFjY291bnROdW1iZXIocGFnZTogUGFnZSkge1xuICBjb25zdCBzZWxlY3RlZFNuaWZBY2NvdW50ID0gYXdhaXQgcGFnZS4kZXZhbCgnI2RkbEFjY291bnRzX21fZGRsIG9wdGlvbltzZWxlY3RlZD1cInNlbGVjdGVkXCJdJywgb3B0aW9uID0+IHtcbiAgICByZXR1cm4gKG9wdGlvbiBhcyBIVE1MRWxlbWVudCkuaW5uZXJUZXh0O1xuICB9KTtcblxuICByZXR1cm4gc2VsZWN0ZWRTbmlmQWNjb3VudC5yZXBsYWNlKCcvJywgJ18nKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZXhwYW5kVHJhbnNhY3Rpb25zVGFibGUocGFnZTogUGFnZSkge1xuICBjb25zdCBoYXNFeHBhbmRBbGxCdXR0b24gPSBhd2FpdCBlbGVtZW50UHJlc2VudE9uUGFnZShwYWdlLCBcImFbaWQqPSdsbmtDdGxFeHBhbmRBbGwnXVwiKTtcbiAgaWYgKGhhc0V4cGFuZEFsbEJ1dHRvbikge1xuICAgIGF3YWl0IGNsaWNrQnV0dG9uKHBhZ2UsIFwiYVtpZCo9J2xua0N0bEV4cGFuZEFsbCddXCIpO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNjcmFwZVRyYW5zYWN0aW9uc0Zyb21UYWJsZShwYWdlOiBQYWdlLCBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMpOiBQcm9taXNlPFRyYW5zYWN0aW9uW10+IHtcbiAgY29uc3QgcGVuZGluZ1R4bnMgPSBhd2FpdCBleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVRhYmxlKFxuICAgIHBhZ2UsXG4gICAgUEVORElOR19UUkFOU0FDVElPTlNfVEFCTEVfSUQsXG4gICAgVHJhbnNhY3Rpb25TdGF0dXNlcy5QZW5kaW5nLFxuICApO1xuICBjb25zdCBjb21wbGV0ZWRUeG5zID0gYXdhaXQgZXh0cmFjdFRyYW5zYWN0aW9uc0Zyb21UYWJsZShcbiAgICBwYWdlLFxuICAgIENPTVBMRVRFRF9UUkFOU0FDVElPTlNfVEFCTEVfSUQsXG4gICAgVHJhbnNhY3Rpb25TdGF0dXNlcy5Db21wbGV0ZWQsXG4gICk7XG4gIGNvbnN0IHR4bnMgPSBbLi4ucGVuZGluZ1R4bnMsIC4uLmNvbXBsZXRlZFR4bnNdO1xuICByZXR1cm4gY29udmVydFRyYW5zYWN0aW9ucyh0eG5zLCBvcHRpb25zKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0QWNjb3VudFRyYW5zYWN0aW9ucyhwYWdlOiBQYWdlLCBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMpOiBQcm9taXNlPFRyYW5zYWN0aW9uW10+IHtcbiAgYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgYCMke0NPTVBMRVRFRF9UUkFOU0FDVElPTlNfVEFCTEVfSUR9YCwgZmFsc2UpLFxuICAgIHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCBgLiR7RVJST1JfTUVTU0FHRV9DTEFTU31gLCBmYWxzZSksXG4gIF0pO1xuXG4gIGNvbnN0IG5vVHJhbnNhY3Rpb25JblJhbmdlRXJyb3IgPSBhd2FpdCBpc05vVHJhbnNhY3Rpb25JbkRhdGVSYW5nZUVycm9yKHBhZ2UpO1xuICBpZiAobm9UcmFuc2FjdGlvbkluUmFuZ2VFcnJvcikge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGF3YWl0IGV4cGFuZFRyYW5zYWN0aW9uc1RhYmxlKHBhZ2UpO1xuICByZXR1cm4gc2NyYXBlVHJhbnNhY3Rpb25zRnJvbVRhYmxlKHBhZ2UsIG9wdGlvbnMpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaEFjY291bnREYXRhKFxuICBwYWdlOiBQYWdlLFxuICBzdGFydERhdGU6IE1vbWVudCxcbiAgYWNjb3VudElkOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyxcbik6IFByb21pc2U8VHJhbnNhY3Rpb25zQWNjb3VudD4ge1xuICBhd2FpdCBjaG9vc2VBY2NvdW50KHBhZ2UsIGFjY291bnRJZCk7XG4gIGF3YWl0IHNlYXJjaEJ5RGF0ZXMocGFnZSwgc3RhcnREYXRlKTtcbiAgY29uc3QgYWNjb3VudE51bWJlciA9IGF3YWl0IGdldEFjY291bnROdW1iZXIocGFnZSk7XG4gIGNvbnN0IHR4bnMgPSBhd2FpdCBnZXRBY2NvdW50VHJhbnNhY3Rpb25zKHBhZ2UsIG9wdGlvbnMpO1xuICByZXR1cm4ge1xuICAgIGFjY291bnROdW1iZXIsXG4gICAgdHhucyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hBY2NvdW50cyhwYWdlOiBQYWdlLCBzdGFydERhdGU6IE1vbWVudCwgb3B0aW9ucz86IFNjcmFwZXJPcHRpb25zKSB7XG4gIGNvbnN0IGFjY291bnRzOiBUcmFuc2FjdGlvbnNBY2NvdW50W10gPSBbXTtcbiAgY29uc3QgYWNjb3VudHNMaXN0ID0gYXdhaXQgZHJvcGRvd25FbGVtZW50cyhwYWdlLCBBQ0NPVU5UU19EUk9QRE9XTl9TRUxFQ1RPUik7XG4gIGZvciAoY29uc3QgYWNjb3VudCBvZiBhY2NvdW50c0xpc3QpIHtcbiAgICBpZiAoYWNjb3VudC52YWx1ZSAhPT0gJy0xJykge1xuICAgICAgLy8gU2tpcCBcIkFsbCBhY2NvdW50c1wiIG9wdGlvblxuICAgICAgY29uc3QgYWNjb3VudERhdGEgPSBhd2FpdCBmZXRjaEFjY291bnREYXRhKHBhZ2UsIHN0YXJ0RGF0ZSwgYWNjb3VudC52YWx1ZSwgb3B0aW9ucyk7XG4gICAgICBhY2NvdW50cy5wdXNoKGFjY291bnREYXRhKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGFjY291bnRzO1xufVxuXG5hc3luYyBmdW5jdGlvbiB3YWl0Rm9yUG9zdExvZ2luKHBhZ2U6IFBhZ2UpIHtcbiAgcmV0dXJuIFByb21pc2UucmFjZShbd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsICcjc2lnbm9mZicsIHRydWUpLCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgJyNyZXN0b3JlJywgdHJ1ZSldKTtcbn1cblxudHlwZSBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscyA9IHsgdXNlcm5hbWU6IHN0cmluZzsgcGFzc3dvcmQ6IHN0cmluZyB9O1xuXG5jbGFzcyBVbmlvbkJhbmtTY3JhcGVyIGV4dGVuZHMgQmFzZVNjcmFwZXJXaXRoQnJvd3NlcjxTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscz4ge1xuICBnZXRMb2dpbk9wdGlvbnMoY3JlZGVudGlhbHM6IFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxvZ2luVXJsOiBgJHtCQVNFX1VSTH1gLFxuICAgICAgZmllbGRzOiBjcmVhdGVMb2dpbkZpZWxkcyhjcmVkZW50aWFscyksXG4gICAgICBzdWJtaXRCdXR0b25TZWxlY3RvcjogJyNlbnRlcicsXG4gICAgICBwb3N0QWN0aW9uOiBhc3luYyAoKSA9PiB3YWl0Rm9yUG9zdExvZ2luKHRoaXMucGFnZSksXG4gICAgICBwb3NzaWJsZVJlc3VsdHM6IGdldFBvc3NpYmxlTG9naW5SZXN1bHRzKCksXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGZldGNoRGF0YSgpIHtcbiAgICBjb25zdCBkZWZhdWx0U3RhcnRNb21lbnQgPSBtb21lbnQoKS5zdWJ0cmFjdCgxLCAneWVhcnMnKS5hZGQoMSwgJ2RheScpO1xuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IHRoaXMub3B0aW9ucy5zdGFydERhdGUgfHwgZGVmYXVsdFN0YXJ0TW9tZW50LnRvRGF0ZSgpO1xuICAgIGNvbnN0IHN0YXJ0TW9tZW50ID0gbW9tZW50Lm1heChkZWZhdWx0U3RhcnRNb21lbnQsIG1vbWVudChzdGFydERhdGUpKTtcblxuICAgIGF3YWl0IHRoaXMubmF2aWdhdGVUbyhUUkFOU0FDVElPTlNfVVJMKTtcblxuICAgIGNvbnN0IGFjY291bnRzID0gYXdhaXQgZmV0Y2hBY2NvdW50cyh0aGlzLnBhZ2UsIHN0YXJ0TW9tZW50LCB0aGlzLm9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICBhY2NvdW50cyxcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFVuaW9uQmFua1NjcmFwZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFDLFVBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLHFCQUFBLEdBQUFGLE9BQUE7QUFTQSxJQUFBRyxhQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxXQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxjQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSx1QkFBQSxHQUFBTixPQUFBO0FBQThHLFNBQUFELHVCQUFBUSxDQUFBLFdBQUFBLENBQUEsSUFBQUEsQ0FBQSxDQUFBQyxVQUFBLEdBQUFELENBQUEsS0FBQUUsT0FBQSxFQUFBRixDQUFBO0FBRzlHLE1BQU1HLFFBQVEsR0FBRyw0QkFBNEI7QUFDN0MsTUFBTUMsZ0JBQWdCLEdBQUcsR0FBR0QsUUFBUSw0Q0FBNEM7QUFDaEYsTUFBTUUsV0FBVyxHQUFHLFVBQVU7QUFDOUIsTUFBTUMsaUNBQWlDLEdBQUcsOENBQThDO0FBQ3hGLE1BQU1DLFdBQVcsR0FBRyxPQUFPO0FBQzNCLE1BQU1DLGtCQUFrQixHQUFHLE9BQU87QUFDbEMsTUFBTUMsZ0JBQWdCLEdBQUcsUUFBUTtBQUNqQyxNQUFNQyxZQUFZLEdBQUcsTUFBTTtBQUMzQixNQUFNQyxhQUFhLEdBQUcsTUFBTTtBQUM1QixNQUFNQyw2QkFBNkIsR0FBRywrQkFBK0I7QUFDckUsTUFBTUMsK0JBQStCLEdBQUcsa0JBQWtCO0FBQzFELE1BQU1DLG1CQUFtQixHQUFHLFNBQVM7QUFDckMsTUFBTUMsMEJBQTBCLEdBQUcsMEJBQTBCO0FBRTdELFNBQVNDLHVCQUF1QkEsQ0FBQSxFQUFHO0VBQ2pDLE1BQU1DLElBQTBCLEdBQUcsQ0FBQyxDQUFDO0VBQ3JDQSxJQUFJLENBQUNDLG9DQUFZLENBQUNDLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUM7RUFDbkRGLElB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