israeli-bank-scrapers-core
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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29uc3RhbnRzIiwiX2VsZW1lbnRzSW50ZXJhY3Rpb25zIiwiX3RyYW5zYWN0aW9ucyIsIl9uYXZpZ2F0aW9uIiwiX3RyYW5zYWN0aW9uczIiLCJfYmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsIkJBU0VfVVJMIiwiVFJBTlNBQ1RJT05TX1VSTCIsIkRBVEVfRk9STUFUIiwiTk9fVFJBTlNBQ1RJT05fSU5fREFURV9SQU5HRV9URVhUIiwiREFURV9IRUFERVIiLCJERVNDUklQVElPTl9IRUFERVIiLCJSRUZFUkVOQ0VfSEVBREVSIiwiREVCSVRfSEVBREVSIiwiQ1JFRElUX0hFQURFUiIsIlBFTkRJTkdfVFJBTlNBQ1RJT05TX1RBQkxFX0lEIiwiQ09NUExFVEVEX1RSQU5TQUNUSU9OU19UQUJMRV9JRCIsIkVSUk9SX01FU1NBR0VfQ0xBU1MiLCJBQ0NPVU5UU19EUk9QRE9XTl9TRUxFQ1RPUiIsImdldFBvc3NpYmxlTG9naW5SZXN1bHRzIiwidXJscyIsIkxvZ2luUmVzdWx0cyIsIlN1Y2Nlc3MiLCJJbnZhbGlkUGFzc3dvcmQiLCJjcmVhdGVMb2dpbkZpZWxkcyIsImNyZWRlbnRpYWxzIiwic2VsZWN0b3IiLCJ2YWx1ZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJnZXRBbW91bnREYXRhIiwiYW1vdW50U3RyIiwiYW1vdW50U3RyQ29weSIsInJlcGxhY2UiLCJwYXJzZUZsb2F0IiwiZ2V0VHhuQW1vdW50IiwidHhuIiwiY3JlZGl0IiwiZGViaXQiLCJOdW1iZXIiLCJpc05hTiIsImNvbnZlcnRUcmFuc2FjdGlvbnMiLCJ0eG5zIiwib3B0aW9ucyIsIm1hcCIsImNvbnZlcnRlZERhdGUiLCJtb21lbnQiLCJkYXRlIiwidG9JU09TdHJpbmciLCJjb252ZXJ0ZWRBbW91bnQiLCJyZXN1bHQiLCJ0eXBlIiwiVHJhbnNhY3Rpb25UeXBlcyIsIk5vcm1hbCIsImlkZW50aWZpZXIiLCJyZWZlcmVuY2UiLCJwYXJzZUludCIsInVuZGVmaW5lZCIsInByb2Nlc3NlZERhdGUiLCJvcmlnaW5hbEFtb3VudCIsIm9yaWdpbmFsQ3VycmVuY3kiLCJTSEVLRUxfQ1VSUkVOQ1kiLCJjaGFyZ2VkQW1vdW50Iiwic3RhdHVzIiwiZGVzY3JpcHRpb24iLCJtZW1vIiwiaW5jbHVkZVJhd1RyYW5zYWN0aW9uIiwicmF3VHJhbnNhY3Rpb24iLCJnZXRSYXdUcmFuc2FjdGlvbiIsImdldFRyYW5zYWN0aW9uRGF0ZSIsInRkcyIsInR4bnNUYWJsZUhlYWRlcnMiLCJ0cmltIiwiZ2V0VHJhbnNhY3Rpb25EZXNjcmlwdGlvbiIsImdldFRyYW5zYWN0aW9uUmVmZXJlbmNlIiwiZ2V0VHJhbnNhY3Rpb25EZWJpdCIsImdldFRyYW5zYWN0aW9uQ3JlZGl0IiwiZXh0cmFjdFRyYW5zYWN0aW9uRGV0YWlscyIsInR4blJvdyIsInR4blN0YXR1cyIsImlubmVyVGRzIiwiaXNFeHBhbmRlZERlc2NSb3ciLCJpZCIsImVkaXRMYXN0VHJhbnNhY3Rpb25EZXNjIiwibGFzdFR4biIsImhhbmRsZVRyYW5zYWN0aW9uUm93IiwidHhuVHlwZSIsImxhc3RUcmFuc2FjdGlvbiIsInBvcCIsInB1c2giLCJFcnJvciIsImdldFRyYW5zYWN0aW9uc1RhYmxlSGVhZGVycyIsInBhZ2UiLCJ0YWJsZVR5cGVJZCIsImhlYWRlcnNNYXAiLCJoZWFkZXJzT2JqcyIsInBhZ2VFdmFsQWxsIiwidGhzIiwidGgiLCJpbmRleCIsInRleHQiLCJpbm5lclRleHQiLCJoZWFkZXJPYmoiLCJleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVRhYmxlIiwidHJhbnNhY3Rpb25zVGFibGVIZWFkZXJzIiwidHJhbnNhY3Rpb25zUm93cyIsInRycyIsInRyIiwiZ2V0QXR0cmlidXRlIiwiQXJyYXkiLCJmcm9tIiwiZ2V0RWxlbWVudHNCeVRhZ05hbWUiLCJ0ZCIsImlzTm9UcmFuc2FjdGlvbkluRGF0ZVJhbmdlRXJyb3IiLCJoYXNFcnJvckluZm9FbGVtZW50IiwiZWxlbWVudFByZXNlbnRPblBhZ2UiLCJlcnJvclRleHQiLCIkZXZhbCIsImVycm9yRWxlbWVudCIsImNob29zZUFjY291bnQiLCJhY2NvdW50SWQiLCJoYXNEcm9wRG93bkxpc3QiLCJkcm9wZG93blNlbGVjdCIsInNlYXJjaEJ5RGF0ZXMiLCJzdGFydERhdGUiLCJ3YWl0VW50aWxFbGVtZW50Rm91bmQiLCJmaWxsSW5wdXQiLCJmb3JtYXQiLCJjbGlja0J1dHRvbiIsIndhaXRGb3JOYXZpZ2F0aW9uIiwiZ2V0QWNjb3VudE51bWJlciIsInNlbGVjdGVkU25pZkFjY291bnQiLCJvcHRpb24iLCJleHBhbmRUcmFuc2FjdGlvbnNUYWJsZSIsImhhc0V4cGFuZEFsbEJ1dHRvbiIsInNjcmFwZVRyYW5zYWN0aW9uc0Zyb21UYWJsZSIsInBlbmRpbmdUeG5zIiwiVHJhbnNhY3Rpb25TdGF0dXNlcyIsIlBlbmRpbmciLCJjb21wbGV0ZWRUeG5zIiwiQ29tcGxldGVkIiwiZ2V0QWNjb3VudFRyYW5zYWN0aW9ucyIsIlByb21pc2UiLCJyYWNlIiwibm9UcmFuc2FjdGlvbkluUmFuZ2VFcnJvciIsImZldGNoQWNjb3VudERhdGEiLCJhY2NvdW50TnVtYmVyIiwiZmV0Y2hBY2NvdW50cyIsImFjY291bnRzIiwiYWNjb3VudHNMaXN0IiwiZHJvcGRvd25FbGVtZW50cyIsImFjY291bnQiLCJhY2NvdW50RGF0YSIsIndhaXRGb3JQb3N0TG9naW4iLCJVbmlvbkJhbmtTY3JhcGVyIiwiQmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImdldExvZ2luT3B0aW9ucyIsImxvZ2luVXJsIiwiZmllbGRzIiwic3VibWl0QnV0dG9uU2VsZWN0b3IiLCJwb3N0QWN0aW9uIiwicG9zc2libGVSZXN1bHRzIiwiZmV0Y2hEYXRhIiwiZGVmYXVsdFN0YXJ0TW9tZW50Iiwic3VidHJhY3QiLCJhZGQiLCJ0b0RhdGUiLCJzdGFydE1vbWVudCIsIm1heCIsIm5hdmlnYXRlVG8iLCJzdWNjZXNzIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmFwZXJzL3VuaW9uLWJhbmsudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG1vbWVudCwgeyB0eXBlIE1vbWVudCB9IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgeyB0eXBlIFBhZ2UgfSBmcm9tICdwdXBwZXRlZXItY29yZSc7XG5pbXBvcnQgeyBTSEVLRUxfQ1VSUkVOQ1kgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuaW1wb3J0IHtcbiAgY2xpY2tCdXR0b24sXG4gIGRyb3Bkb3duRWxlbWVudHMsXG4gIGRyb3Bkb3duU2VsZWN0LFxuICBlbGVtZW50UHJlc2VudE9uUGFnZSxcbiAgZmlsbElucHV0LFxuICBwYWdlRXZhbEFsbCxcbiAgd2FpdFVudGlsRWxlbWVudEZvdW5kLFxufSBmcm9tICcuLi9oZWxwZXJzL2VsZW1lbnRzLWludGVyYWN0aW9ucyc7XG5pbXBvcnQgeyBnZXRSYXdUcmFuc2FjdGlvbiB9IGZyb20gJy4uL2hlbHBlcnMvdHJhbnNhY3Rpb25zJztcbmltcG9ydCB7IHdhaXRGb3JOYXZpZ2F0aW9uIH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uU3RhdHVzZXMsIFRyYW5zYWN0aW9uVHlwZXMsIHR5cGUgVHJhbnNhY3Rpb24sIHR5cGUgVHJhbnNhY3Rpb25zQWNjb3VudCB9IGZyb20gJy4uL3RyYW5zYWN0aW9ucyc7XG5pbXBvcnQgeyBCYXNlU2NyYXBlcldpdGhCcm93c2VyLCBMb2dpblJlc3VsdHMsIHR5cGUgUG9zc2libGVMb2dpblJlc3VsdHMgfSBmcm9tICcuL2Jhc2Utc2NyYXBlci13aXRoLWJyb3dzZXInO1xuaW1wb3J0IHsgdHlwZSBTY3JhcGVyT3B0aW9ucyB9IGZyb20gJy4vaW50ZXJmYWNlJztcblxuY29uc3QgQkFTRV9VUkwgPSAnaHR0cHM6Ly9oYi51bmlvbmJhbmsuY28uaWwnO1xuY29uc3QgVFJBTlNBQ1RJT05TX1VSTCA9IGAke0JBU0VfVVJMfS9lQmFua2luZy9BY2NvdW50cy9FeHRlbmRlZEFjdGl2aXR5LmFzcHgjL2A7XG5jb25zdCBEQVRFX0ZPUk1BVCA9ICdERC9NTS9ZWSc7XG5jb25zdCBOT19UUkFOU0FDVElPTl9JTl9EQVRFX1JBTkdFX1RFWFQgPSAn15zXkCDXp9eZ15nXnteV16og16rXoNeV16LXldeqINee16rXkNeZ157XldeqINei15wg16TXmSDXlNeh15nXoNeV158g16nXlNeV15LXk9eoJztcbmNvbnN0IERBVEVfSEVBREVSID0gJ9eq15DXqNeZ15onO1xuY29uc3QgREVTQ1JJUFRJT05fSEVBREVSID0gJ9eq15nXkNeV16gnO1xuY29uc3QgUkVGRVJFTkNFX0hFQURFUiA9ICfXkNeh157Xm9eq15AnO1xuY29uc3QgREVCSVRfSEVBREVSID0gJ9eX15XXkdeUJztcbmNvbnN0IENSRURJVF9IRUFERVIgPSAn15bXm9eV16onO1xuY29uc3QgUEVORElOR19UUkFOU0FDVElPTlNfVEFCTEVfSUQgPSAndHJUb2RheUFjdGl2aXR5TmFwYVRhYmxlVXBwZXInO1xuY29uc3QgQ09NUExFVEVEX1RSQU5TQUNUSU9OU19UQUJMRV9JRCA9ICdjdGxBY3Rpdml0eVRhYmxlJztcbmNvbnN0IEVSUk9SX01FU1NBR0VfQ0xBU1MgPSAnZXJySW5mbyc7XG5jb25zdCBBQ0NPVU5UU19EUk9QRE9XTl9TRUxFQ1RPUiA9ICdzZWxlY3QjZGRsQWNjb3VudHNfbV9kZGwnO1xuXG5mdW5jdGlvbiBnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cygpIHtcbiAgY29uc3QgdXJsczogUG9zc2libGVMb2dpblJlc3VsdHMgPSB7fTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuU3VjY2Vzc10gPSBbL2VCYW5raW5nXFwvQWNjb3VudHMvXTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuSW52YWxpZFBhc3N3b3JkXSA9IFsvSW50ZXJuYWxTaXRlXFwvQ3VzdG9tVXBkYXRlXFwvbGV1bWlcXC9Mb2dpblBhZ2UuQVNQL107XG4gIHJldHVybiB1cmxzO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVMb2dpbkZpZWxkcyhjcmVkZW50aWFsczogU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMpIHtcbiAgcmV0dXJuIFtcbiAgICB7IHNlbGVjdG9yOiAnI3VpZCcsIHZhbHVlOiBjcmVkZW50aWFscy51c2VybmFtZSB9LFxuICAgIHsgc2VsZWN0b3I6ICcjcGFzc3dvcmQnLCB2YWx1ZTogY3JlZGVudGlhbHMucGFzc3dvcmQgfSxcbiAgXTtcbn1cblxuZnVuY3Rpb24gZ2V0QW1vdW50RGF0YShhbW91bnRTdHI6IHN0cmluZykge1xuICBjb25zdCBhbW91bnRTdHJDb3B5ID0gYW1vdW50U3RyLnJlcGxhY2UoJywnLCAnJyk7XG4gIHJldHVybiBwYXJzZUZsb2F0KGFtb3VudFN0ckNvcHkpO1xufVxuXG5pbnRlcmZhY2UgU2NyYXBlZFRyYW5zYWN0aW9uIHtcbiAgY3JlZGl0OiBzdHJpbmc7XG4gIGRlYml0OiBzdHJpbmc7XG4gIGRhdGU6IHN0cmluZztcbiAgcmVmZXJlbmNlPzogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBtZW1vOiBzdHJpbmc7XG4gIHN0YXR1czogVHJhbnNhY3Rpb25TdGF0dXNlcztcbn1cblxuZnVuY3Rpb24gZ2V0VHhuQW1vdW50KHR4bjogU2NyYXBlZFRyYW5zYWN0aW9uKSB7XG4gIGNvbnN0IGNyZWRpdCA9IGdldEFtb3VudERhdGEodHhuLmNyZWRpdCk7XG4gIGNvbnN0IGRlYml0ID0gZ2V0QW1vdW50RGF0YSh0eG4uZGViaXQpO1xuICByZXR1cm4gKE51bWJlci5pc05hTihjcmVkaXQpID8gMCA6IGNyZWRpdCkgLSAoTnVtYmVyLmlzTmFOKGRlYml0KSA/IDAgOiBkZWJpdCk7XG59XG5cbmZ1bmN0aW9uIGNvbnZlcnRUcmFuc2FjdGlvbnModHhuczogU2NyYXBlZFRyYW5zYWN0aW9uW10sIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyk6IFRyYW5zYWN0aW9uW10ge1xuICByZXR1cm4gdHhucy5tYXAodHhuID0+IHtcbiAgICBjb25zdCBjb252ZXJ0ZWREYXRlID0gbW9tZW50KHR4bi5kYXRlLCBEQVRFX0ZPUk1BVCkudG9JU09TdHJpbmcoKTtcbiAgICBjb25zdCBjb252ZXJ0ZWRBbW91bnQgPSBnZXRUeG5BbW91bnQodHhuKTtcbiAgICBjb25zdCByZXN1bHQ6IFRyYW5zYWN0aW9uID0ge1xuICAgICAgdHlwZTogVHJhbnNhY3Rpb25UeXBlcy5Ob3JtYWwsXG4gICAgICBpZGVudGlmaWVyOiB0eG4ucmVmZXJlbmNlID8gcGFyc2VJbnQodHhuLnJlZmVyZW5jZSwgMTApIDogdW5kZWZpbmVkLFxuICAgICAgZGF0ZTogY29udmVydGVkRGF0ZSxcbiAgICAgIHByb2Nlc3NlZERhdGU6IGNvbnZlcnRlZERhdGUsXG4gICAgICBvcmlnaW5hbEFtb3VudDogY29udmVydGVkQW1vdW50LFxuICAgICAgb3JpZ2luYWxDdXJyZW5jeTogU0hFS0VMX0NVUlJFTkNZLFxuICAgICAgY2hhcmdlZEFtb3VudDogY29udmVydGVkQW1vdW50LFxuICAgICAgc3RhdHVzOiB0eG4uc3RhdHVzLFxuICAgICAgZGVzY3JpcHRpb246IHR4bi5kZXNjcmlwdGlvbixcbiAgICAgIG1lbW86IHR4bi5tZW1vLFxuICAgIH07XG5cbiAgICBpZiAob3B0aW9ucz8uaW5jbHVkZVJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICByZXN1bHQucmF3VHJhbnNhY3Rpb24gPSBnZXRSYXdUcmFuc2FjdGlvbih0eG4pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0pO1xufVxuXG50eXBlIFRyYW5zYWN0aW9uc1RyID0geyBpZDogc3RyaW5nOyBpbm5lclRkczogVHJhbnNhY3Rpb25zVHJUZHMgfTtcbnR5cGUgVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMgPSBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+O1xudHlwZSBUcmFuc2FjdGlvbnNUclRkcyA9IHN0cmluZ1tdO1xuXG5mdW5jdGlvbiBnZXRUcmFuc2FjdGlvbkRhdGUodGRzOiBUcmFuc2FjdGlvbnNUclRkcywgdHhuc1RhYmxlSGVhZGVyczogVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMpIHtcbiAgcmV0dXJuICh0ZHNbdHhuc1RhYmxlSGVhZGVyc1tEQVRFX0hFQURFUl1dIHx8ICcnKS50cmltKCk7XG59XG5cbmZ1bmN0aW9uIGdldFRyYW5zYWN0aW9uRGVzY3JpcHRpb24odGRzOiBUcmFuc2FjdGlvbnNUclRkcywgdHhuc1RhYmxlSGVhZGVyczogVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMpIHtcbiAgcmV0dXJuICh0ZHNbdHhuc1RhYmxlSGVhZGVyc1tERVNDUklQVElPTl9IRUFERVJdXSB8fCAnJykudHJpbSgpO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2FjdGlvblJlZmVyZW5jZSh0ZHM6IFRyYW5zYWN0aW9uc1RyVGRzLCB0eG5zVGFibGVIZWFkZXJzOiBUcmFuc2FjdGlvblRhYmxlSGVhZGVycykge1xuICByZXR1cm4gKHRkc1t0eG5zVGFibGVIZWFkZXJzW1JFRkVSRU5DRV9IRUFERVJdXSB8fCAnJykudHJpbSgpO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2FjdGlvbkRlYml0KHRkczogVHJhbnNhY3Rpb25zVHJUZHMsIHR4bnNUYWJsZUhlYWRlcnM6IFRyYW5zYWN0aW9uVGFibGVIZWFkZXJzKSB7XG4gIHJldHVybiAodGRzW3R4bnNUYWJsZUhlYWRlcnNbREVCSVRfSEVBREVSXV0gfHwgJycpLnRyaW0oKTtcbn1cblxuZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25DcmVkaXQodGRzOiBUcmFuc2FjdGlvbnNUclRkcywgdHhuc1RhYmxlSGVhZGVyczogVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMpIHtcbiAgcmV0dXJuICh0ZHNbdHhuc1RhYmxlSGVhZGVyc1tDUkVESVRfSEVBREVSXV0gfHwgJycpLnRyaW0oKTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdFRyYW5zYWN0aW9uRGV0YWlscyhcbiAgdHhuUm93OiBUcmFuc2FjdGlvbnNUcixcbiAgdHhuc1RhYmxlSGVhZGVyczogVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMsXG4gIHR4blN0YXR1czogVHJhbnNhY3Rpb25TdGF0dXNlcyxcbik6IFNjcmFwZWRUcmFuc2FjdGlvbiB7XG4gIGNvbnN0IHRkcyA9IHR4blJvdy5pbm5lclRkcztcbiAgcmV0dXJuIHtcbiAgICBzdGF0dXM6IHR4blN0YXR1cyxcbiAgICBkYXRlOiBnZXRUcmFuc2FjdGlvbkRhdGUodGRzLCB0eG5zVGFibGVIZWFkZXJzKSxcbiAgICBkZXNjcmlwdGlvbjogZ2V0VHJhbnNhY3Rpb25EZXNjcmlwdGlvbih0ZHMsIHR4bnNUYWJsZUhlYWRlcnMpLFxuICAgIHJlZmVyZW5jZTogZ2V0VHJhbnNhY3Rpb25SZWZlcmVuY2UodGRzLCB0eG5zVGFibGVIZWFkZXJzKSxcbiAgICBkZWJpdDogZ2V0VHJhbnNhY3Rpb25EZWJpdCh0ZHMsIHR4bnNUYWJsZUhlYWRlcnMpLFxuICAgIGNyZWRpdDogZ2V0VHJhbnNhY3Rpb25DcmVkaXQodGRzLCB0eG5zVGFibGVIZWFkZXJzKSxcbiAgICBtZW1vOiAnJyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gaXNFeHBhbmRlZERlc2NSb3codHhuUm93OiBUcmFuc2FjdGlvbnNUcikge1xuICByZXR1cm4gdHhuUm93LmlkID09PSAncm93QWRkZWQnO1xufVxuXG5mdW5jdGlvbiBlZGl0TGFzdFRyYW5zYWN0aW9uRGVzYyh0eG5Sb3c6IFRyYW5zYWN0aW9uc1RyLCBsYXN0VHhuOiBTY3JhcGVkVHJhbnNhY3Rpb24pOiBTY3JhcGVkVHJhbnNhY3Rpb24ge1xuICBsYXN0VHhuLmRlc2NyaXB0aW9uID0gYCR7bGFzdFR4bi5kZXNjcmlwdGlvbn0gJHt0eG5Sb3cuaW5uZXJUZHNbMF19YDtcbiAgcmV0dXJuIGxhc3RUeG47XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVRyYW5zYWN0aW9uUm93KFxuICB0eG5zOiBTY3JhcGVkVHJhbnNhY3Rpb25bXSxcbiAgdHhuc1RhYmxlSGVhZGVyczogVHJhbnNhY3Rpb25UYWJsZUhlYWRlcnMsXG4gIHR4blJvdzogVHJhbnNhY3Rpb25zVHIsXG4gIHR4blR5cGU6IFRyYW5zYWN0aW9uU3RhdHVzZXMsXG4pIHtcbiAgaWYgKGlzRXhwYW5kZWREZXNjUm93KHR4blJvdykpIHtcbiAgICBjb25zdCBsYXN0VHJhbnNhY3Rpb24gPSB0eG5zLnBvcCgpO1xuICAgIGlmIChsYXN0VHJhbnNhY3Rpb24pIHtcbiAgICAgIHR4bnMucHVzaChlZGl0TGFzdFRyYW5zYWN0aW9uRGVzYyh0eG5Sb3csIGxhc3RUcmFuc2FjdGlvbikpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludGVybmFsIHVuaW9uLWJhbmsgZXJyb3InKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdHhucy5wdXNoKGV4dHJhY3RUcmFuc2FjdGlvbkRldGFpbHModHhuUm93LCB0eG5zVGFibGVIZWFkZXJzLCB0eG5UeXBlKSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0VHJhbnNhY3Rpb25zVGFibGVIZWFkZXJzKHBhZ2U6IFBhZ2UsIHRhYmxlVHlwZUlkOiBzdHJpbmcpIHtcbiAgY29uc3QgaGVhZGVyc01hcDogUmVjb3JkPHN0cmluZywgYW55PiA9IFtdO1xuICBjb25zdCBoZWFkZXJzT2JqcyA9IGF3YWl0IHBhZ2VFdmFsQWxsKHBhZ2UsIGAjV29ya1NwYWNlQm94ICMke3RhYmxlVHlwZUlkfSB0cltjbGFzcz0naGVhZGVyJ10gdGhgLCBudWxsLCB0aHMgPT4ge1xuICAgIHJldHVybiB0aHMubWFwKCh0aCwgaW5kZXgpID0+ICh7XG4gICAgICB0ZXh0OiAodGggYXMgSFRNTEVsZW1lbnQpLmlubmVyVGV4dC50cmltKCksXG4gICAgICBpbmRleCxcbiAgICB9KSk7XG4gIH0pO1xuXG4gIGZvciAoY29uc3QgaGVhZGVyT2JqIG9mIGhlYWRlcnNPYmpzKSB7XG4gICAgaGVhZGVyc01hcFtoZWFkZXJPYmoudGV4dF0gPSBoZWFkZXJPYmouaW5kZXg7XG4gIH1cbiAgcmV0dXJuIGhlYWRlcnNNYXA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGV4dHJhY3RUcmFuc2FjdGlvbnNGcm9tVGFibGUoXG4gIHBhZ2U6IFBhZ2UsXG4gIHRhYmxlVHlwZUlkOiBzdHJpbmcsXG4gIHR4blR5cGU6IFRyYW5zYWN0aW9uU3RhdHVzZXMsXG4pOiBQcm9taXNlPFNjcmFwZWRUcmFuc2FjdGlvbltdPiB7XG4gIGNvbnN0IHR4bnM6IFNjcmFwZWRUcmFuc2FjdGlvbltdID0gW107XG4gIGNvbnN0IHRyYW5zYWN0aW9uc1RhYmxlSGVhZGVycyA9IGF3YWl0IGdldFRyYW5zYWN0aW9uc1RhYmxlSGVhZGVycyhwYWdlLCB0YWJsZVR5cGVJZCk7XG5cbiAgY29uc3QgdHJhbnNhY3Rpb25zUm93cyA9IGF3YWl0IHBhZ2VFdmFsQWxsPFRyYW5zYWN0aW9uc1RyW10+KFxuICAgIHBhZ2UsXG4gICAgYCNXb3JrU3BhY2VCb3ggIyR7dGFibGVUeXBlSWR9IHRyW2NsYXNzXTpub3QoW2NsYXNzPSdoZWFkZXInXSlgLFxuICAgIFtdLFxuICAgIHRycyA9PiB7XG4gICAgICByZXR1cm4gKHRycyBhcyBIVE1MRWxlbWVudFtdKS5tYXAodHIgPT4gKHtcbiAgICAgICAgaWQ6IHRyLmdldEF0dHJpYnV0ZSgnaWQnKSB8fCAnJyxcbiAgICAgICAgaW5uZXJUZHM6IEFycmF5LmZyb20odHIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3RkJykpLm1hcCh0ZCA9PiAodGQgYXMgSFRNTEVsZW1lbnQpLmlubmVyVGV4dCksXG4gICAgICB9KSk7XG4gICAgfSxcbiAgKTtcblxuICBmb3IgKGNvbnN0IHR4blJvdyBvZiB0cmFuc2FjdGlvbnNSb3dzKSB7XG4gICAgaGFuZGxlVHJhbnNhY3Rpb25Sb3codHhucywgdHJhbnNhY3Rpb25zVGFibGVIZWFkZXJzLCB0eG5Sb3csIHR4blR5cGUpO1xuICB9XG4gIHJldHVybiB0eG5zO1xufVxuXG5hc3luYyBmdW5jdGlvbiBpc05vVHJhbnNhY3Rpb25JbkRhdGVSYW5nZUVycm9yKHBhZ2U6IFBhZ2UpIHtcbiAgY29uc3QgaGFzRXJyb3JJbmZvRWxlbWVudCA9IGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKHBhZ2UsIGAuJHtFUlJPUl9NRVNTQUdFX0NMQVNTfWApO1xuICBpZiAoaGFzRXJyb3JJbmZvRWxlbWVudCkge1xuICAgIGNvbnN0IGVycm9yVGV4dCA9IGF3YWl0IHBhZ2UuJGV2YWwoYC4ke0VSUk9SX01FU1NBR0VfQ0xBU1N9YCwgZXJyb3JFbGVtZW50ID0+IHtcbiAgICAgIHJldHVybiAoZXJyb3JFbGVtZW50IGFzIEhUTUxFbGVtZW50KS5pbm5lclRleHQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIGVycm9yVGV4dC50cmltKCkgPT09IE5PX1RSQU5TQUNUSU9OX0lOX0RBVEVfUkFOR0VfVEVYVDtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNob29zZUFjY291bnQocGFnZTogUGFnZSwgYWNjb3VudElkOiBzdHJpbmcpIHtcbiAgY29uc3QgaGFzRHJvcERvd25MaXN0ID0gYXdhaXQgZWxlbWVudFByZXNlbnRPblBhZ2UocGFnZSwgQUNDT1VOVFNfRFJPUERPV05fU0VMRUNUT1IpO1xuICBpZiAoaGFzRHJvcERvd25MaXN0KSB7XG4gICAgYXdhaXQgZHJvcGRvd25TZWxlY3QocGFnZSwgQUNDT1VOVFNfRFJPUERPV05fU0VMRUNUT1IsIGFjY291bnRJZCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gc2VhcmNoQnlEYXRlcyhwYWdlOiBQYWdlLCBzdGFydERhdGU6IE1vbWVudCkge1xuICBhd2FpdCBkcm9wZG93blNlbGVjdChwYWdlLCAnc2VsZWN0I2RkbFRyYW5zYWN0aW9uUGVyaW9kJywgJzAwNCcpO1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgJ3NlbGVjdCNkZGxUcmFuc2FjdGlvblBlcmlvZCcpO1xuICBhd2FpdCBmaWxsSW5wdXQocGFnZSwgJ2lucHV0I2R0RnJvbURhdGVfdGV4dEJveCcsIHN0YXJ0RGF0ZS5mb3JtYXQoREFURV9GT1JNQVQpKTtcbiAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgJ2lucHV0I2J0bkRpc3BsYXlEYXRlcycpO1xuICBhd2FpdCB3YWl0Rm9yTmF2aWdhdGlvbihwYWdlKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0QWNjb3VudE51bWJlcihwYWdlOiBQYWdlKSB7XG4gIGNvbnN0IHNlbGVjdGVkU25pZkFjY291bnQgPSBhd2FpdCBwYWdlLiRldmFsKCcjZGRsQWNjb3VudHNfbV9kZGwgb3B0aW9uW3NlbGVjdGVkPVwic2VsZWN0ZWRcIl0nLCBvcHRpb24gPT4ge1xuICAgIHJldHVybiAob3B0aW9uIGFzIEhUTUxFbGVtZW50KS5pbm5lclRleHQ7XG4gIH0pO1xuXG4gIHJldHVybiBzZWxlY3RlZFNuaWZBY2NvdW50LnJlcGxhY2UoJy8nLCAnXycpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBleHBhbmRUcmFuc2FjdGlvbnNUYWJsZShwYWdlOiBQYWdlKSB7XG4gIGNvbnN0IGhhc0V4cGFuZEFsbEJ1dHRvbiA9IGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKHBhZ2UsIFwiYVtpZCo9J2xua0N0bEV4cGFuZEFsbCddXCIpO1xuICBpZiAoaGFzRXhwYW5kQWxsQnV0dG9uKSB7XG4gICAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgXCJhW2lkKj0nbG5rQ3RsRXhwYW5kQWxsJ11cIik7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gc2NyYXBlVHJhbnNhY3Rpb25zRnJvbVRhYmxlKHBhZ2U6IFBhZ2UsIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyk6IFByb21pc2U8VHJhbnNhY3Rpb25bXT4ge1xuICBjb25zdCBwZW5kaW5nVHhucyA9IGF3YWl0IGV4dHJhY3RUcmFuc2FjdGlvbnNGcm9tVGFibGUoXG4gICAgcGFnZSxcbiAgICBQRU5ESU5HX1RSQU5TQUNUSU9OU19UQUJMRV9JRCxcbiAgICBUcmFuc2FjdGlvblN0YXR1c2VzLlBlbmRpbmcsXG4gICk7XG4gIGNvbnN0IGNvbXBsZXRlZFR4bnMgPSBhd2FpdCBleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVRhYmxlKFxuICAgIHBhZ2UsXG4gICAgQ09NUExFVEVEX1RSQU5TQUNUSU9OU19UQUJMRV9JRCxcbiAgICBUcmFuc2FjdGlvblN0YXR1c2VzLkNvbXBsZXRlZCxcbiAgKTtcbiAgY29uc3QgdHhucyA9IFsuLi5wZW5kaW5nVHhucywgLi4uY29tcGxldGVkVHhuc107XG4gIHJldHVybiBjb252ZXJ0VHJhbnNhY3Rpb25zKHR4bnMsIG9wdGlvbnMpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRBY2NvdW50VHJhbnNhY3Rpb25zKHBhZ2U6IFBhZ2UsIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyk6IFByb21pc2U8VHJhbnNhY3Rpb25bXT4ge1xuICBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgIHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCBgIyR7Q09NUExFVEVEX1RSQU5TQUNUSU9OU19UQUJMRV9JRH1gLCBmYWxzZSksXG4gICAgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsIGAuJHtFUlJPUl9NRVNTQUdFX0NMQVNTfWAsIGZhbHNlKSxcbiAgXSk7XG5cbiAgY29uc3Qgbm9UcmFuc2FjdGlvbkluUmFuZ2VFcnJvciA9IGF3YWl0IGlzTm9UcmFuc2FjdGlvbkluRGF0ZVJhbmdlRXJyb3IocGFnZSk7XG4gIGlmIChub1RyYW5zYWN0aW9uSW5SYW5nZUVycm9yKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgYXdhaXQgZXhwYW5kVHJhbnNhY3Rpb25zVGFibGUocGFnZSk7XG4gIHJldHVybiBzY3JhcGVUcmFuc2FjdGlvbnNGcm9tVGFibGUocGFnZSwgb3B0aW9ucyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoQWNjb3VudERhdGEoXG4gIHBhZ2U6IFBhZ2UsXG4gIHN0YXJ0RGF0ZTogTW9tZW50LFxuICBhY2NvdW50SWQ6IHN0cmluZyxcbiAgb3B0aW9ucz86IFNjcmFwZXJPcHRpb25zLFxuKTogUHJvbWlzZTxUcmFuc2FjdGlvbnNBY2NvdW50PiB7XG4gIGF3YWl0IGNob29zZUFjY291bnQocGFnZSwgYWNjb3VudElkKTtcbiAgYXdhaXQgc2VhcmNoQnlEYXRlcyhwYWdlLCBzdGFydERhdGUpO1xuICBjb25zdCBhY2NvdW50TnVtYmVyID0gYXdhaXQgZ2V0QWNjb3VudE51bWJlcihwYWdlKTtcbiAgY29uc3QgdHhucyA9IGF3YWl0IGdldEFjY291bnRUcmFuc2FjdGlvbnMocGFnZSwgb3B0aW9ucyk7XG4gIHJldHVybiB7XG4gICAgYWNjb3VudE51bWJlcixcbiAgICB0eG5zLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaEFjY291bnRzKHBhZ2U6IFBhZ2UsIHN0YXJ0RGF0ZTogTW9tZW50LCBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMpIHtcbiAgY29uc3QgYWNjb3VudHM6IFRyYW5zYWN0aW9uc0FjY291bnRbXSA9IFtdO1xuICBjb25zdCBhY2NvdW50c0xpc3QgPSBhd2FpdCBkcm9wZG93bkVsZW1lbnRzKHBhZ2UsIEFDQ09VTlRTX0RST1BET1dOX1NFTEVDVE9SKTtcbiAgZm9yIChjb25zdCBhY2NvdW50IG9mIGFjY291bnRzTGlzdCkge1xuICAgIGlmIChhY2NvdW50LnZhbHVlICE9PSAnLTEnKSB7XG4gICAgICAvLyBTa2lwIFwiQWxsIGFjY291bnRzXCIgb3B0aW9uXG4gICAgICBjb25zdCBhY2NvdW50RGF0YSA9IGF3YWl0IGZldGNoQWNjb3VudERhdGEocGFnZSwgc3RhcnREYXRlLCBhY2NvdW50LnZhbHVlLCBvcHRpb25zKTtcbiAgICAgIGFjY291bnRzLnB1c2goYWNjb3VudERhdGEpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYWNjb3VudHM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JQb3N0TG9naW4ocGFnZTogUGFnZSkge1xuICByZXR1cm4gUHJvbWlzZS5yYWNlKFt3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgJyNzaWdub2ZmJywgdHJ1ZSksIHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCAnI3Jlc3RvcmUnLCB0cnVlKV0pO1xufVxuXG50eXBlIFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzID0geyB1c2VybmFtZTogc3RyaW5nOyBwYXNzd29yZDogc3RyaW5nIH07XG5cbmNsYXNzIFVuaW9uQmFua1NjcmFwZXIgZXh0ZW5kcyBCYXNlU2NyYXBlcldpdGhCcm93c2VyPFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzPiB7XG4gIGdldExvZ2luT3B0aW9ucyhjcmVkZW50aWFsczogU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbG9naW5Vcmw6IGAke0JBU0VfVVJMfWAsXG4gICAgICBmaWVsZHM6IGNyZWF0ZUxvZ2luRmllbGRzKGNyZWRlbnRpYWxzKSxcbiAgICAgIHN1Ym1pdEJ1dHRvblNlbGVjdG9yOiAnI2VudGVyJyxcbiAgICAgIHBvc3RBY3Rpb246IGFzeW5jICgpID0+IHdhaXRGb3JQb3N0TG9naW4odGhpcy5wYWdlKSxcbiAgICAgIHBvc3NpYmxlUmVzdWx0czogZ2V0UG9zc2libGVMb2dpblJlc3VsdHMoKSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZmV0Y2hEYXRhKCkge1xuICAgIGNvbnN0IGRlZmF1bHRTdGFydE1vbWVudCA9IG1vbWVudCgpLnN1YnRyYWN0KDEsICd5ZWFycycpLmFkZCgxLCAnZGF5Jyk7XG4gICAgY29uc3Qgc3RhcnREYXRlID0gdGhpcy5vcHRpb25zLnN0YXJ0RGF0ZSB8fCBkZWZhdWx0U3RhcnRNb21lbnQudG9EYXRlKCk7XG4gICAgY29uc3Qgc3RhcnRNb21lbnQgPSBtb21lbnQubWF4KGRlZmF1bHRTdGFydE1vbWVudCwgbW9tZW50KHN0YXJ0RGF0ZSkpO1xuXG4gICAgYXdhaXQgdGhpcy5uYXZpZ2F0ZVRvKFRSQU5TQUNUSU9OU19VUkwpO1xuXG4gICAgY29uc3QgYWNjb3VudHMgPSBhd2FpdCBmZXRjaEFjY291bnRzKHRoaXMucGFnZSwgc3RhcnRNb21lbnQsIHRoaXMub3B0aW9ucyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgIGFjY291bnRzLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgVW5pb25CYW5rU2NyYXBlcjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsSUFBQUEsT0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsVUFBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUscUJBQUEsR0FBQUYsT0FBQTtBQVNBLElBQUFHLGFBQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFdBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLGNBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLHVCQUFBLEdBQUFOLE9BQUE7QUFBOEcsU0FBQUQsdUJBQUFRLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFHOUcsTUFBTUcsUUFBUSxHQUFHLDRCQUE0QjtBQUM3QyxNQUFNQyxnQkFBZ0IsR0FBRyxHQUFHRCxRQUFRLDRDQUE0QztBQUNoRixNQUFNRSxXQUFXLEdBQUcsVUFBVTtBQUM5QixNQUFNQyxpQ0FBaUMsR0FBRyw4Q0FBOEM7QUFDeEYsTUFBTUMsV0FBVyxHQUFHLE9BQU87QUFDM0IsTUFBTUMsa0JBQWtCLEdBQUcsT0FBTztBQUNsQyxNQUFNQyxnQkFBZ0IsR0FBRyxRQUFRO0FBQ2pDLE1BQU1DLFlBQVksR0FBRyxNQUFNO0FBQzNCLE1BQU1DLGFBQWEsR0FBRyxNQUFNO0FBQzVCLE1BQU1DLDZCQUE2QixHQUFHLCtCQUErQjtBQUNyRSxNQUFNQywrQkFBK0IsR0FBRyxrQkFBa0I7QUFDMUQsTUFBTUMsbUJBQW1CLEdBQUcsU0FBUztBQUNyQyxNQUFNQywwQkFBMEIsR0FBRywwQkFBMEI7QUFFN0QsU0FBU0MsdUJBQXVCQSxDQUFBLEVBQUc7RUFDakMsTUFBTUMsSUFBMEIsR0FBRyxDQUFDLENBQUM7RUFDckNBLElBQUksQ0FBQ0Msb0NBQVksQ0FBQ0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQztFQUNu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