UNPKG

israeli-bank-scrapers-core

Version:

Provide scrapers for all major Israeli banks and credit card companies

250 lines (243 loc) 43.8 kB
"use strict"; 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 _navigation = require("../helpers/navigation"); var _transactions = require("../helpers/transactions"); var _transactions2 = require("../transactions"); var _baseScraperWithBrowser = require("./base-scraper-with-browser"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const LOGIN_URL = 'https://login.yahav.co.il/login/'; const BASE_URL = 'https://digital.yahav.co.il/BaNCSDigitalUI/app/index.html#/'; const INVALID_DETAILS_SELECTOR = '.ui-dialog-buttons'; const CHANGE_PASSWORD_OLD_PASS = 'input#ef_req_parameter_old_credential'; const BASE_WELCOME_URL = `${BASE_URL}main/home`; const PORTFOLIO_FORM = 'form[name="formPortfolioSelect"]'; const ACCOUNT_ID_SELECTOR_SINGLE = 'span.portfolio-value'; const ACCOUNT_ID_SELECTOR_MULTI = `${PORTFOLIO_FORM} .selected-item-top`; const PORTFOLIO_OPTION_SELECTOR = `${PORTFOLIO_FORM} .drop-down-item-list li.drop-down-item`; const ACCOUNT_DETAILS_SELECTOR = '.account-details'; const DATE_FORMAT = 'DD/MM/YYYY'; const USER_ELEM = '#username'; const PASSWD_ELEM = '#password'; const NATIONALID_ELEM = '#pinno'; const SUBMIT_LOGIN_SELECTOR = '.btn'; function getPossibleLoginResults(page) { // checkout file `base-scraper-with-browser.ts` for available result types const urls = {}; urls[_baseScraperWithBrowser.LoginResults.Success] = [`${BASE_WELCOME_URL}`]; urls[_baseScraperWithBrowser.LoginResults.InvalidPassword] = [async () => { return (0, _elementsInteractions.elementPresentOnPage)(page, `${INVALID_DETAILS_SELECTOR}`); }]; urls[_baseScraperWithBrowser.LoginResults.ChangePassword] = [async () => { return (0, _elementsInteractions.elementPresentOnPage)(page, `${CHANGE_PASSWORD_OLD_PASS}`); }]; return urls; } 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 handleTransactionRow(txns, txnRow) { const div = txnRow.innerDivs; // Remove anything except digits. const regex = /\D+/gm; const tx = { date: div[1], reference: div[2].replace(regex, ''), memo: '', description: div[3], debit: div[4], credit: div[5], status: _transactions2.TransactionStatuses.Completed }; txns.push(tx); } async function getAccountTransactions(page, options) { // Wait for transactions. await (0, _elementsInteractions.waitUntilElementFound)(page, '.under-line-txn-table-header', true); const txns = []; const transactionsDivs = await (0, _elementsInteractions.pageEvalAll)(page, '.list-item-holder .entire-content-ctr', [], divs => { return divs.map(div => ({ id: div.getAttribute('id') || '', innerDivs: Array.from(div.getElementsByTagName('div')).map(el => el.innerText) })); }); for (const txnRow of transactionsDivs) { handleTransactionRow(txns, txnRow); } return convertTransactions(txns, options); } // All datepicker selectors are scoped to the "from date" control to avoid ambiguity with the "to date" picker. const FROM_PICKER = 'date-picker-access[btn-label="from"]'; async function searchByDates(page, startDate) { await (0, _elementsInteractions.waitUntilElementFound)(page, `${FROM_PICKER} a.datepicker-button`, true); await (0, _elementsInteractions.clickButton)(page, `${FROM_PICKER} a.datepicker-button`); await (0, _elementsInteractions.waitUntilElementFound)(page, `${FROM_PICKER} .datepicker-calendar`, true); // Read the input value (set by ng-value/textToDateFilter, always DD/MM/YYYY) to determine which // month the calendar opened on — avoids parsing the header text which renders in the account's locale. const inputValue = await page.$eval(`${FROM_PICKER} .date-picker-input`, el => el.value); const displayedMoment = (0, _moment.default)(inputValue, 'DD/MM/YYYY'); const monthsToGoBack = (displayedMoment.year() - startDate.year()) * 12 + (displayedMoment.month() - startDate.month()); for (let i = 0; i < monthsToGoBack; i += 1) { const prevMonthSelector = `${FROM_PICKER} .datepicker-month-prev.enabled`; await (0, _elementsInteractions.waitUntilElementFound)(page, prevMonthSelector, true); await (0, _elementsInteractions.clickButton)(page, prevMonthSelector); } // :not(.other-month) avoids adjacent-month cells sharing the same day number. const daySelector = `${FROM_PICKER} .datepicker-calendar td.day.selectable:not(.other-month)[data-value="${startDate.date()}"]`; await (0, _elementsInteractions.waitUntilElementFound)(page, daySelector, true); await (0, _elementsInteractions.clickButton)(page, daySelector); } async function fetchAccountData(page, startDate, accountID, options) { await (0, _elementsInteractions.waitUntilElementDisappear)(page, '.loading-bar-spinner'); await searchByDates(page, startDate); await (0, _elementsInteractions.waitUntilElementDisappear)(page, '.loading-bar-spinner'); const txns = await getAccountTransactions(page, options); return { accountNumber: accountID, txns }; } // Multi-portfolio iteration contributed by @mamlukishay (https://github.com/gczobel/israeli-bank-scrapers/pull/1) // Multi-portfolio accounts render <inline-drop-down> inside form[name="formPortfolioSelect"] // (Angular ng-if="portfolioList.length > 1") with the current portfolio at .selected-item-top // and the unselected ones as <li>s; single-portfolio accounts render only the single selector. // Returned selected-first so fetchAccounts can skip re-selecting on the first iteration. async function getPortfolioIDs(page) { await Promise.any([page.waitForSelector(ACCOUNT_ID_SELECTOR_MULTI, { timeout: 10000 }), page.waitForSelector(ACCOUNT_ID_SELECTOR_SINGLE, { timeout: 10000 })]).catch(() => null); return page.evaluate((multiSelector, optionSelector, singleSelector) => { const selected = document.querySelector(multiSelector)?.textContent?.trim(); if (selected) { const others = Array.from(document.querySelectorAll(optionSelector)).map(li => li.textContent?.trim() ?? ''); return [selected, ...others].filter(Boolean); } const single = document.querySelector(singleSelector)?.textContent?.trim(); return single ? [single] : []; }, ACCOUNT_ID_SELECTOR_MULTI, PORTFOLIO_OPTION_SELECTOR, ACCOUNT_ID_SELECTOR_SINGLE); } // Angular's listItemAction navigates the page back to /main/home with the new portfolio // selected — callers must re-enter the statements flow after this returns. async function selectPortfolio(page, targetID) { const clicked = await page.$$eval(PORTFOLIO_OPTION_SELECTOR, (lis, id) => { const target = lis.find(li => li.textContent?.trim() === id); if (!target) return false; target.click(); return true; }, targetID); if (!clicked) throw new Error(`Portfolio option not found for ID: ${targetID}`); await (0, _elementsInteractions.waitUntilElementDisappear)(page, '.loading-bar-spinner'); } async function fetchAccounts(page, startDate, options) { // Snapshot up front: the dropdown only lists unselected portfolios, so after the first // switch we would lose any not yet scraped. const portfolioIDs = await getPortfolioIDs(page); if (portfolioIDs.length === 0) { throw new Error('No portfolios found on /main/home — Yahav DOM likely changed'); } const accounts = []; for (let i = 0; i < portfolioIDs.length; i += 1) { const portfolioID = portfolioIDs[i]; if (i > 0) { await selectPortfolio(page, portfolioID); } await (0, _elementsInteractions.waitUntilElementFound)(page, ACCOUNT_DETAILS_SELECTOR, true); await (0, _elementsInteractions.clickButton)(page, ACCOUNT_DETAILS_SELECTOR); await (0, _elementsInteractions.waitUntilElementFound)(page, '.statement-options .selected-item-top', true); accounts.push(await fetchAccountData(page, startDate, portfolioID, options)); } return accounts; } async function waitReadinessForAll(page) { await (0, _elementsInteractions.waitUntilElementFound)(page, `${USER_ELEM}`, true); await (0, _elementsInteractions.waitUntilElementFound)(page, `${PASSWD_ELEM}`, true); await (0, _elementsInteractions.waitUntilElementFound)(page, `${NATIONALID_ELEM}`, true); await (0, _elementsInteractions.waitUntilElementFound)(page, `${SUBMIT_LOGIN_SELECTOR}`, true); } async function redirectOrDialog(page) { // Click on bank messages if any. await (0, _navigation.waitForNavigation)(page); await (0, _elementsInteractions.waitUntilElementDisappear)(page, '.loading-bar-spinner'); const hasMessage = await (0, _elementsInteractions.elementPresentOnPage)(page, '.messaging-links-container'); if (hasMessage) { await (0, _elementsInteractions.clickButton)(page, '.link-1'); } const promise1 = page.waitForSelector(ACCOUNT_DETAILS_SELECTOR, { timeout: 30000 }); const promise2 = page.waitForSelector(CHANGE_PASSWORD_OLD_PASS, { timeout: 30000 }); const promises = [promise1, promise2]; await Promise.race(promises); await (0, _elementsInteractions.waitUntilElementDisappear)(page, '.loading-bar-spinner'); } class YahavScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser { getLoginOptions(credentials) { return { loginUrl: `${LOGIN_URL}`, fields: [{ selector: `${USER_ELEM}`, value: credentials.username }, { selector: `${PASSWD_ELEM}`, value: credentials.password }, { selector: `${NATIONALID_ELEM}`, value: credentials.nationalID }], submitButtonSelector: `${SUBMIT_LOGIN_SELECTOR}`, checkReadiness: async () => waitReadinessForAll(this.page), postAction: async () => redirectOrDialog(this.page), possibleResults: getPossibleLoginResults(this.page) }; } async fetchData() { await (0, _elementsInteractions.waitUntilElementFound)(this.page, ACCOUNT_DETAILS_SELECTOR, true); const defaultStartMoment = (0, _moment.default)().subtract(3, 'months').add(1, 'day'); const startDate = this.options.startDate || defaultStartMoment.toDate(); const startMoment = _moment.default.min(_moment.default.max(defaultStartMoment, (0, _moment.default)(startDate)), (0, _moment.default)()); const accounts = await fetchAccounts(this.page, startMoment, this.options); return { success: true, accounts }; } } var _default = exports.default = YahavScraper; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29uc3RhbnRzIiwiX2VsZW1lbnRzSW50ZXJhY3Rpb25zIiwiX25hdmlnYXRpb24iLCJfdHJhbnNhY3Rpb25zIiwiX3RyYW5zYWN0aW9uczIiLCJfYmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsIkxPR0lOX1VSTCIsIkJBU0VfVVJMIiwiSU5WQUxJRF9ERVRBSUxTX1NFTEVDVE9SIiwiQ0hBTkdFX1BBU1NXT1JEX09MRF9QQVNTIiwiQkFTRV9XRUxDT01FX1VSTCIsIlBPUlRGT0xJT19GT1JNIiwiQUNDT1VOVF9JRF9TRUxFQ1RPUl9TSU5HTEUiLCJBQ0NPVU5UX0lEX1NFTEVDVE9SX01VTFRJIiwiUE9SVEZPTElPX09QVElPTl9TRUxFQ1RPUiIsIkFDQ09VTlRfREVUQUlMU19TRUxFQ1RPUiIsIkRBVEVfRk9STUFUIiwiVVNFUl9FTEVNIiwiUEFTU1dEX0VMRU0iLCJOQVRJT05BTElEX0VMRU0iLCJTVUJNSVRfTE9HSU5fU0VMRUNUT1IiLCJnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cyIsInBhZ2UiLCJ1cmxzIiwiTG9naW5SZXN1bHRzIiwiU3VjY2VzcyIsIkludmFsaWRQYXNzd29yZCIsImVsZW1lbnRQcmVzZW50T25QYWdlIiwiQ2hhbmdlUGFzc3dvcmQiLCJnZXRBbW91bnREYXRhIiwiYW1vdW50U3RyIiwiYW1vdW50U3RyQ29weSIsInJlcGxhY2UiLCJwYXJzZUZsb2F0IiwiZ2V0VHhuQW1vdW50IiwidHhuIiwiY3JlZGl0IiwiZGViaXQiLCJOdW1iZXIiLCJpc05hTiIsImNvbnZlcnRUcmFuc2FjdGlvbnMiLCJ0eG5zIiwib3B0aW9ucyIsIm1hcCIsImNvbnZlcnRlZERhdGUiLCJtb21lbnQiLCJkYXRlIiwidG9JU09TdHJpbmciLCJjb252ZXJ0ZWRBbW91bnQiLCJyZXN1bHQiLCJ0eXBlIiwiVHJhbnNhY3Rpb25UeXBlcyIsIk5vcm1hbCIsImlkZW50aWZpZXIiLCJyZWZlcmVuY2UiLCJwYXJzZUludCIsInVuZGVmaW5lZCIsInByb2Nlc3NlZERhdGUiLCJvcmlnaW5hbEFtb3VudCIsIm9yaWdpbmFsQ3VycmVuY3kiLCJTSEVLRUxfQ1VSUkVOQ1kiLCJjaGFyZ2VkQW1vdW50Iiwic3RhdHVzIiwiZGVzY3JpcHRpb24iLCJtZW1vIiwiaW5jbHVkZVJhd1RyYW5zYWN0aW9uIiwicmF3VHJhbnNhY3Rpb24iLCJnZXRSYXdUcmFuc2FjdGlvbiIsImhhbmRsZVRyYW5zYWN0aW9uUm93IiwidHhuUm93IiwiZGl2IiwiaW5uZXJEaXZzIiwicmVnZXgiLCJ0eCIsIlRyYW5zYWN0aW9uU3RhdHVzZXMiLCJDb21wbGV0ZWQiLCJwdXNoIiwiZ2V0QWNjb3VudFRyYW5zYWN0aW9ucyIsIndhaXRVbnRpbEVsZW1lbnRGb3VuZCIsInRyYW5zYWN0aW9uc0RpdnMiLCJwYWdlRXZhbEFsbCIsImRpdnMiLCJpZCIsImdldEF0dHJpYnV0ZSIsIkFycmF5IiwiZnJvbSIsImdldEVsZW1lbnRzQnlUYWdOYW1lIiwiZWwiLCJpbm5lclRleHQiLCJGUk9NX1BJQ0tFUiIsInNlYXJjaEJ5RGF0ZXMiLCJzdGFydERhdGUiLCJjbGlja0J1dHRvbiIsImlucHV0VmFsdWUiLCIkZXZhbCIsInZhbHVlIiwiZGlzcGxheWVkTW9tZW50IiwibW9udGhzVG9Hb0JhY2siLCJ5ZWFyIiwibW9udGgiLCJpIiwicHJldk1vbnRoU2VsZWN0b3IiLCJkYXlTZWxlY3RvciIsImZldGNoQWNjb3VudERhdGEiLCJhY2NvdW50SUQiLCJ3YWl0VW50aWxFbGVtZW50RGlzYXBwZWFyIiwiYWNjb3VudE51bWJlciIsImdldFBvcnRmb2xpb0lEcyIsIlByb21pc2UiLCJhbnkiLCJ3YWl0Rm9yU2VsZWN0b3IiLCJ0aW1lb3V0IiwiY2F0Y2giLCJldmFsdWF0ZSIsIm11bHRpU2VsZWN0b3IiLCJvcHRpb25TZWxlY3RvciIsInNpbmdsZVNlbGVjdG9yIiwic2VsZWN0ZWQiLCJkb2N1bWVudCIsInF1ZXJ5U2VsZWN0b3IiLCJ0ZXh0Q29udGVudCIsInRyaW0iLCJvdGhlcnMiLCJxdWVyeVNlbGVjdG9yQWxsIiwibGkiLCJmaWx0ZXIiLCJCb29sZWFuIiwic2luZ2xlIiwic2VsZWN0UG9ydGZvbGlvIiwidGFyZ2V0SUQiLCJjbGlja2VkIiwiJCRldmFsIiwibGlzIiwidGFyZ2V0IiwiZmluZCIsImNsaWNrIiwiRXJyb3IiLCJmZXRjaEFjY291bnRzIiwicG9ydGZvbGlvSURzIiwibGVuZ3RoIiwiYWNjb3VudHMiLCJwb3J0Zm9saW9JRCIsIndhaXRSZWFkaW5lc3NGb3JBbGwiLCJyZWRpcmVjdE9yRGlhbG9nIiwid2FpdEZvck5hdmlnYXRpb24iLCJoYXNNZXNzYWdlIiwicHJvbWlzZTEiLCJwcm9taXNlMiIsInByb21pc2VzIiwicmFjZSIsIllhaGF2U2NyYXBlciIsIkJhc2VTY3JhcGVyV2l0aEJyb3dzZXIiLCJnZXRMb2dpbk9wdGlvbnMiLCJjcmVkZW50aWFscyIsImxvZ2luVXJsIiwiZmllbGRzIiwic2VsZWN0b3IiLCJ1c2VybmFtZSIsInBhc3N3b3JkIiwibmF0aW9uYWxJRCIsInN1Ym1pdEJ1dHRvblNlbGVjdG9yIiwiY2hlY2tSZWFkaW5lc3MiLCJwb3N0QWN0aW9uIiwicG9zc2libGVSZXN1bHRzIiwiZmV0Y2hEYXRhIiwiZGVmYXVsdFN0YXJ0TW9tZW50Iiwic3VidHJhY3QiLCJhZGQiLCJ0b0RhdGUiLCJzdGFydE1vbWVudCIsIm1pbiIsIm1heCIsInN1Y2Nlc3MiLCJfZGVmYXVsdCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyYXBlcnMveWFoYXYudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG1vbWVudCwgeyB0eXBlIE1vbWVudCB9IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgeyB0eXBlIFBhZ2UgfSBmcm9tICdwdXBwZXRlZXItY29yZSc7XG5pbXBvcnQgeyBTSEVLRUxfQ1VSUkVOQ1kgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuaW1wb3J0IHtcbiAgY2xpY2tCdXR0b24sXG4gIGVsZW1lbnRQcmVzZW50T25QYWdlLFxuICBwYWdlRXZhbEFsbCxcbiAgd2FpdFVudGlsRWxlbWVudERpc2FwcGVhcixcbiAgd2FpdFVudGlsRWxlbWVudEZvdW5kLFxufSBmcm9tICcuLi9oZWxwZXJzL2VsZW1lbnRzLWludGVyYWN0aW9ucyc7XG5pbXBvcnQgeyB3YWl0Rm9yTmF2aWdhdGlvbiB9IGZyb20gJy4uL2hlbHBlcnMvbmF2aWdhdGlvbic7XG5pbXBvcnQgeyBnZXRSYXdUcmFuc2FjdGlvbiB9IGZyb20gJy4uL2hlbHBlcnMvdHJhbnNhY3Rpb25zJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uU3RhdHVzZXMsIFRyYW5zYWN0aW9uVHlwZXMsIHR5cGUgVHJhbnNhY3Rpb24sIHR5cGUgVHJhbnNhY3Rpb25zQWNjb3VudCB9IGZyb20gJy4uL3RyYW5zYWN0aW9ucyc7XG5pbXBvcnQgeyBCYXNlU2NyYXBlcldpdGhCcm93c2VyLCBMb2dpblJlc3VsdHMsIHR5cGUgUG9zc2libGVMb2dpblJlc3VsdHMgfSBmcm9tICcuL2Jhc2Utc2NyYXBlci13aXRoLWJyb3dzZXInO1xuaW1wb3J0IHsgdHlwZSBTY3JhcGVyT3B0aW9ucyB9IGZyb20gJy4vaW50ZXJmYWNlJztcblxuY29uc3QgTE9HSU5fVVJMID0gJ2h0dHBzOi8vbG9naW4ueWFoYXYuY28uaWwvbG9naW4vJztcbmNvbnN0IEJBU0VfVVJMID0gJ2h0dHBzOi8vZGlnaXRhbC55YWhhdi5jby5pbC9CYU5DU0RpZ2l0YWxVSS9hcHAvaW5kZXguaHRtbCMvJztcbmNvbnN0IElOVkFMSURfREVUQUlMU19TRUxFQ1RPUiA9ICcudWktZGlhbG9nLWJ1dHRvbnMnO1xuY29uc3QgQ0hBTkdFX1BBU1NXT1JEX09MRF9QQVNTID0gJ2lucHV0I2VmX3JlcV9wYXJhbWV0ZXJfb2xkX2NyZWRlbnRpYWwnO1xuY29uc3QgQkFTRV9XRUxDT01FX1VSTCA9IGAke0JBU0VfVVJMfW1haW4vaG9tZWA7XG5cbmNvbnN0IFBPUlRGT0xJT19GT1JNID0gJ2Zvcm1bbmFtZT1cImZvcm1Qb3J0Zm9saW9TZWxlY3RcIl0nO1xuY29uc3QgQUNDT1VOVF9JRF9TRUxFQ1RPUl9TSU5HTEUgPSAnc3Bhbi5wb3J0Zm9saW8tdmFsdWUnO1xuY29uc3QgQUNDT1VOVF9JRF9TRUxFQ1RPUl9NVUxUSSA9IGAke1BPUlRGT0xJT19GT1JNfSAuc2VsZWN0ZWQtaXRlbS10b3BgO1xuY29uc3QgUE9SVEZPTElPX09QVElPTl9TRUxFQ1RPUiA9IGAke1BPUlRGT0xJT19GT1JNfSAuZHJvcC1kb3duLWl0ZW0tbGlzdCBsaS5kcm9wLWRvd24taXRlbWA7XG5jb25zdCBBQ0NPVU5UX0RFVEFJTFNfU0VMRUNUT1IgPSAnLmFjY291bnQtZGV0YWlscyc7XG5jb25zdCBEQVRFX0ZPUk1BVCA9ICdERC9NTS9ZWVlZJztcblxuY29uc3QgVVNFUl9FTEVNID0gJyN1c2VybmFtZSc7XG5jb25zdCBQQVNTV0RfRUxFTSA9ICcjcGFzc3dvcmQnO1xuY29uc3QgTkFUSU9OQUxJRF9FTEVNID0gJyNwaW5ubyc7XG5jb25zdCBTVUJNSVRfTE9HSU5fU0VMRUNUT1IgPSAnLmJ0bic7XG5cbmludGVyZmFjZSBTY3JhcGVkVHJhbnNhY3Rpb24ge1xuICBjcmVkaXQ6IHN0cmluZztcbiAgZGViaXQ6IHN0cmluZztcbiAgZGF0ZTogc3RyaW5nO1xuICByZWZlcmVuY2U/OiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIG1lbW86IHN0cmluZztcbiAgc3RhdHVzOiBUcmFuc2FjdGlvblN0YXR1c2VzO1xufVxuXG5mdW5jdGlvbiBnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cyhwYWdlOiBQYWdlKTogUG9zc2libGVMb2dpblJlc3VsdHMge1xuICAvLyBjaGVja291dCBmaWxlIGBiYXNlLXNjcmFwZXItd2l0aC1icm93c2VyLnRzYCBmb3IgYXZhaWxhYmxlIHJlc3VsdCB0eXBlc1xuICBjb25zdCB1cmxzOiBQb3NzaWJsZUxvZ2luUmVzdWx0cyA9IHt9O1xuICB1cmxzW0xvZ2luUmVzdWx0cy5TdWNjZXNzXSA9IFtgJHtCQVNFX1dFTENPTUVfVVJMfWBdO1xuICB1cmxzW0xvZ2luUmVzdWx0cy5JbnZhbGlkUGFzc3dvcmRdID0gW1xuICAgIGFzeW5jICgpID0+IHtcbiAgICAgIHJldHVybiBlbGVtZW50UHJlc2VudE9uUGFnZShwYWdlLCBgJHtJTlZBTElEX0RFVEFJTFNfU0VMRUNUT1J9YCk7XG4gICAgfSxcbiAgXTtcblxuICB1cmxzW0xvZ2luUmVzdWx0cy5DaGFuZ2VQYXNzd29yZF0gPSBbXG4gICAgYXN5bmMgKCkgPT4ge1xuICAgICAgcmV0dXJuIGVsZW1lbnRQcmVzZW50T25QYWdlKHBhZ2UsIGAke0NIQU5HRV9QQVNTV09SRF9PTERfUEFTU31gKTtcbiAgICB9LFxuICBdO1xuXG4gIHJldHVybiB1cmxzO1xufVxuXG5mdW5jdGlvbiBnZXRBbW91bnREYXRhKGFtb3VudFN0cjogc3RyaW5nKSB7XG4gIGNvbnN0IGFtb3VudFN0ckNvcHkgPSBhbW91bnRTdHIucmVwbGFjZSgnLCcsICcnKTtcbiAgcmV0dXJuIHBhcnNlRmxvYXQoYW1vdW50U3RyQ29weSk7XG59XG5cbmZ1bmN0aW9uIGdldFR4bkFtb3VudCh0eG46IFNjcmFwZWRUcmFuc2FjdGlvbikge1xuICBjb25zdCBjcmVkaXQgPSBnZXRBbW91bnREYXRhKHR4bi5jcmVkaXQpO1xuICBjb25zdCBkZWJpdCA9IGdldEFtb3VudERhdGEodHhuLmRlYml0KTtcbiAgcmV0dXJuIChOdW1iZXIuaXNOYU4oY3JlZGl0KSA/IDAgOiBjcmVkaXQpIC0gKE51bWJlci5pc05hTihkZWJpdCkgPyAwIDogZGViaXQpO1xufVxuXG50eXBlIFRyYW5zYWN0aW9uc1RyID0geyBpZDogc3RyaW5nOyBpbm5lckRpdnM6IHN0cmluZ1tdIH07XG5cbmZ1bmN0aW9uIGNvbnZlcnRUcmFuc2FjdGlvbnModHhuczogU2NyYXBlZFRyYW5zYWN0aW9uW10sIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyk6IFRyYW5zYWN0aW9uW10ge1xuICByZXR1cm4gdHhucy5tYXAodHhuID0+IHtcbiAgICBjb25zdCBjb252ZXJ0ZWREYXRlID0gbW9tZW50KHR4bi5kYXRlLCBEQVRFX0ZPUk1BVCkudG9JU09TdHJpbmcoKTtcbiAgICBjb25zdCBjb252ZXJ0ZWRBbW91bnQgPSBnZXRUeG5BbW91bnQodHhuKTtcbiAgICBjb25zdCByZXN1bHQ6IFRyYW5zYWN0aW9uID0ge1xuICAgICAgdHlwZTogVHJhbnNhY3Rpb25UeXBlcy5Ob3JtYWwsXG4gICAgICBpZGVudGlmaWVyOiB0eG4ucmVmZXJlbmNlID8gcGFyc2VJbnQodHhuLnJlZmVyZW5jZSwgMTApIDogdW5kZWZpbmVkLFxuICAgICAgZGF0ZTogY29udmVydGVkRGF0ZSxcbiAgICAgIHByb2Nlc3NlZERhdGU6IGNvbnZlcnRlZERhdGUsXG4gICAgICBvcmlnaW5hbEFtb3VudDogY29udmVydGVkQW1vdW50LFxuICAgICAgb3JpZ2luYWxDdXJyZW5jeTogU0hFS0VMX0NVUlJFTkNZLFxuICAgICAgY2hhcmdlZEFtb3VudDogY29udmVydGVkQW1vdW50LFxuICAgICAgc3RhdHVzOiB0eG4uc3RhdHVzLFxuICAgICAgZGVzY3JpcHRpb246IHR4bi5kZXNjcmlwdGlvbixcbiAgICAgIG1lbW86IHR4bi5tZW1vLFxuICAgIH07XG5cbiAgICBpZiAob3B0aW9ucz8uaW5jbHVkZVJhd1RyYW5zYWN0aW9uKSB7XG4gICAgICByZXN1bHQucmF3VHJhbnNhY3Rpb24gPSBnZXRSYXdUcmFuc2FjdGlvbih0eG4pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVUcmFuc2FjdGlvblJvdyh0eG5zOiBTY3JhcGVkVHJhbnNhY3Rpb25bXSwgdHhuUm93OiBUcmFuc2FjdGlvbnNUcikge1xuICBjb25zdCBkaXYgPSB0eG5Sb3cuaW5uZXJEaXZzO1xuXG4gIC8vIFJlbW92ZSBhbnl0aGluZyBleGNlcHQgZGlnaXRzLlxuICBjb25zdCByZWdleCA9IC9cXEQrL2dtO1xuXG4gIGNvbnN0IHR4OiBTY3JhcGVkVHJhbnNhY3Rpb24gPSB7XG4gICAgZGF0ZTogZGl2WzFdLFxuICAgIHJlZmVyZW5jZTogZGl2WzJdLnJlcGxhY2UocmVnZXgsICcnKSxcbiAgICBtZW1vOiAnJyxcbiAgICBkZXNjcmlwdGlvbjogZGl2WzNdLFxuICAgIGRlYml0OiBkaXZbNF0sXG4gICAgY3JlZGl0OiBkaXZbNV0sXG4gICAgc3RhdHVzOiBUcmFuc2FjdGlvblN0YXR1c2VzLkNvbXBsZXRlZCxcbiAgfTtcblxuICB0eG5zLnB1c2godHgpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRBY2NvdW50VHJhbnNhY3Rpb25zKHBhZ2U6IFBhZ2UsIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyk6IFByb21pc2U8VHJhbnNhY3Rpb25bXT4ge1xuICAvLyBXYWl0IGZvciB0cmFuc2FjdGlvbnMuXG4gIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCAnLnVuZGVyLWxpbmUtdHhuLXRhYmxlLWhlYWRlcicsIHRydWUpO1xuXG4gIGNvbnN0IHR4bnM6IFNjcmFwZWRUcmFuc2FjdGlvbltdID0gW107XG4gIGNvbnN0IHRyYW5zYWN0aW9uc0RpdnMgPSBhd2FpdCBwYWdlRXZhbEFsbDxUcmFuc2FjdGlvbnNUcltdPihcbiAgICBwYWdlLFxuICAgICcubGlzdC1pdGVtLWhvbGRlciAuZW50aXJlLWNvbnRlbnQtY3RyJyxcbiAgICBbXSxcbiAgICBkaXZzID0+IHtcbiAgICAgIHJldHVybiAoZGl2cyBhcyBIVE1MRWxlbWVudFtdKS5tYXAoZGl2ID0+ICh7XG4gICAgICAgIGlkOiBkaXYuZ2V0QXR0cmlidXRlKCdpZCcpIHx8ICcnLFxuICAgICAgICBpbm5lckRpdnM6IEFycmF5LmZyb20oZGl2LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdkaXYnKSkubWFwKGVsID0+IChlbCBhcyBIVE1MRWxlbWVudCkuaW5uZXJUZXh0KSxcbiAgICAgIH0pKTtcbiAgICB9LFxuICApO1xuXG4gIGZvciAoY29uc3QgdHhuUm93IG9mIHRyYW5zYWN0aW9uc0RpdnMpIHtcbiAgICBoYW5kbGVUcmFuc2FjdGlvblJvdyh0eG5zLCB0eG5Sb3cpO1xuICB9XG5cbiAgcmV0dXJuIGNvbnZlcnRUcmFuc2FjdGlvbnModHhucywgb3B0aW9ucyk7XG59XG5cbi8vIEFsbCBkYXRlcGlja2VyIHNlbGVjdG9ycyBhcmUgc2NvcGVkIHRvIHRoZSBcImZyb20gZGF0ZVwiIGNvbnRyb2wgdG8gYXZvaWQgYW1iaWd1aXR5IHdpdGggdGhlIFwidG8gZGF0ZVwiIHBpY2tlci5cbmNvbnN0IEZST01fUElDS0VSID0gJ2RhdGUtcGlja2VyLWFjY2Vzc1tidG4tbGFiZWw9XCJmcm9tXCJdJztcblxuYXN5bmMgZnVuY3Rpb24gc2VhcmNoQnlEYXRlcyhwYWdlOiBQYWdlLCBzdGFydERhdGU6IE1vbWVudCkge1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgYCR7RlJPTV9QSUNLRVJ9IGEuZGF0ZXBpY2tlci1idXR0b25gLCB0cnVlKTtcbiAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgYCR7RlJPTV9QSUNLRVJ9IGEuZGF0ZXBpY2tlci1idXR0b25gKTtcbiAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsIGAke0ZST01fUElDS0VSfSAuZGF0ZXBpY2tlci1jYWxlbmRhcmAsIHRydWUpO1xuXG4gIC8vIFJlYWQgdGhlIGlucHV0IHZhbHVlIChzZXQgYnkgbmctdmFsdWUvdGV4dFRvRGF0ZUZpbHRlciwgYWx3YXlzIEREL01NL1lZWVkpIHRvIGRldGVybWluZSB3aGljaFxuICAvLyBtb250aCB0aGUgY2FsZW5kYXIgb3BlbmVkIG9uIOKAlCBhdm9pZHMgcGFyc2luZyB0aGUgaGVhZGVyIHRleHQgd2hpY2ggcmVuZGVycyBpbiB0aGUgYWNjb3VudCdzIGxvY2FsZS5cbiAgY29uc3QgaW5wdXRWYWx1ZSA9IGF3YWl0IHBhZ2UuJGV2YWwoYCR7RlJPTV9QSUNLRVJ9IC5kYXRlLXBpY2tlci1pbnB1dGAsIGVsID0+IChlbCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSk7XG4gIGNvbnN0IGRpc3BsYXllZE1vbWVudCA9IG1vbWVudChpbnB1dFZhbHVlLCAnREQvTU0vWVlZWScpO1xuICBjb25zdCBtb250aHNUb0dvQmFjayA9XG4gICAgKGRpc3BsYXllZE1vbWVudC55ZWFyKCkgLSBzdGFydERhdGUueWVhcigpKSAqIDEyICsgKGRpc3BsYXllZE1vbWVudC5tb250aCgpIC0gc3RhcnREYXRlLm1vbnRoKCkpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG1vbnRoc1RvR29CYWNrOyBpICs9IDEpIHtcbiAgICBjb25zdCBwcmV2TW9udGhTZWxlY3RvciA9IGAke0ZST01fUElDS0VSfSAuZGF0ZXBpY2tlci1tb250aC1wcmV2LmVuYWJsZWRgO1xuICAgIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCBwcmV2TW9udGhTZWxlY3RvciwgdHJ1ZSk7XG4gICAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgcHJldk1vbnRoU2VsZWN0b3IpO1xuICB9XG5cbiAgLy8gOm5vdCgub3RoZXItbW9udGgpIGF2b2lkcyBhZGphY2VudC1tb250aCBjZWxscyBzaGFyaW5nIHRoZSBzYW1lIGRheSBudW1iZXIuXG4gIGNvbnN0IGRheVNlbGVjdG9yID0gYCR7RlJPTV9QSUNLRVJ9IC5kYXRlcGlja2VyLWNhbGVuZGFyIHRkLmRheS5zZWxlY3RhYmxlOm5vdCgub3RoZXItbW9udGgpW2RhdGEtdmFsdWU9XCIke3N0YXJ0RGF0ZS5kYXRlKCl9XCJdYDtcbiAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsIGRheVNlbGVjdG9yLCB0cnVlKTtcbiAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgZGF5U2VsZWN0b3IpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaEFjY291bnREYXRhKFxuICBwYWdlOiBQYWdlLFxuICBzdGFydERhdGU6IE1vbWVudCxcbiAgYWNjb3VudElEOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyxcbik6IFByb21pc2U8VHJhbnNhY3Rpb25zQWNjb3VudD4ge1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50RGlzYXBwZWFyKHBhZ2UsICcubG9hZGluZy1iYXItc3Bpbm5lcicpO1xuICBhd2FpdCBzZWFyY2hCeURhdGVzKHBhZ2UsIHN0YXJ0RGF0ZSk7XG4gIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnREaXNhcHBlYXIocGFnZSwgJy5sb2FkaW5nLWJhci1zcGlubmVyJyk7XG4gIGNvbnN0IHR4bnMgPSBhd2FpdCBnZXRBY2NvdW50VHJhbnNhY3Rpb25zKHBhZ2UsIG9wdGlvbnMpO1xuXG4gIHJldHVybiB7XG4gICAgYWNjb3VudE51bWJlcjogYWNjb3VudElELFxuICAgIHR4bnMsXG4gIH07XG59XG5cbi8vIE11bHRpLXBvcnRmb2xpbyBpdGVyYXRpb24gY29udHJpYnV0ZWQgYnkgQG1hbWx1a2lzaGF5IChodHRwczovL2dpdGh1Yi5jb20vZ2N6b2JlbC9pc3JhZWxpLWJhbmstc2NyYXBlcnMvcHVsbC8xKVxuLy8gTXVsdGktcG9ydGZvbGlvIGFjY291bnRzIHJlbmRlciA8aW5saW5lLWRyb3AtZG93bj4gaW5zaWRlIGZvcm1bbmFtZT1cImZvcm1Qb3J0Zm9saW9TZWxlY3RcIl1cbi8vIChBbmd1bGFyIG5nLWlmPVwicG9ydGZvbGlvTGlzdC5sZW5ndGggPiAxXCIpIHdpdGggdGhlIGN1cnJlbnQgcG9ydGZvbGlvIGF0IC5zZWxlY3RlZC1pdGVtLXRvcFxuLy8gYW5kIHRoZSB1bnNlbGVjdGVkIG9uZXMgYXMgPGxpPnM7IHNpbmdsZS1wb3J0Zm9saW8gYWNjb3VudHMgcmVuZGVyIG9ubHkgdGhlIHNpbmdsZSBzZWxlY3Rvci5cbi8vIFJldHVybmVkIHNlbGVjdGVkLWZpcnN0IHNvIGZldGNoQWNjb3VudHMgY2FuIHNraXAgcmUtc2VsZWN0aW5nIG9uIHRoZSBmaXJzdCBpdGVyYXRpb24uXG5hc3luYyBmdW5jdGlvbiBnZXRQb3J0Zm9saW9JRHMocGFnZTogUGFnZSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgYXdhaXQgUHJvbWlzZS5hbnkoW1xuICAgIHBhZ2Uud2FpdEZvclNlbGVjdG9yKEFDQ09VTlRfSURfU0VMRUNUT1JfTVVMVEksIHsgdGltZW91dDogMTAwMDAgfSksXG4gICAgcGFnZS53YWl0Rm9yU2VsZWN0b3IoQUNDT1VOVF9JRF9TRUxFQ1RPUl9TSU5HTEUsIHsgdGltZW91dDogMTAwMDAgfSksXG4gIF0pLmNhdGNoKCgpID0+IG51bGwpO1xuXG4gIHJldHVybiBwYWdlLmV2YWx1YXRlKFxuICAgIChtdWx0aVNlbGVjdG9yLCBvcHRpb25TZWxlY3Rvciwgc2luZ2xlU2VsZWN0b3IpID0+IHtcbiAgICAgIGNvbnN0IHNlbGVjdGVkID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihtdWx0aVNlbGVjdG9yKT8udGV4dENvbnRlbnQ/LnRyaW0oKTtcbiAgICAgIGlmIChzZWxlY3RlZCkge1xuICAgICAgICBjb25zdCBvdGhlcnMgPSBBcnJheS5mcm9tKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwob3B0aW9uU2VsZWN0b3IpKS5tYXAobGkgPT4gbGkudGV4dENvbnRlbnQ/LnRyaW0oKSA/PyAnJyk7XG4gICAgICAgIHJldHVybiBbc2VsZWN0ZWQsIC4uLm90aGVyc10uZmlsdGVyKEJvb2xlYW4pO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2luZ2xlID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzaW5nbGVTZWxlY3Rvcik/LnRleHRDb250ZW50Py50cmltKCk7XG4gICAgICByZXR1cm4gc2luZ2xlID8gW3NpbmdsZV0gOiBbXTtcbiAgICB9LFxuICAgIEFDQ09VTlRfSURfU0VMRUNUT1JfTVVMVEksXG4gICAgUE9SVEZPTElPX09QVElPTl9TRUxFQ1RPUixcbiAgICBBQ0NPVU5UX0lEX1NFTEVDVE9SX1NJTkdMRSxcbiAgKTtcbn1cblxuLy8gQW5ndWxhcidzIGxpc3RJdGVtQWN0aW9uIG5hdmlnYXRlcyB0aGUgcGFnZSBiYWNrIHRvIC9tYWluL2hvbWUgd2l0aCB0aGUgbmV3IHBvcnRmb2xpb1xuLy8gc2VsZWN0ZWQg4oCUIGNhbGxlcnMgbXVzdCByZS1lbnRlciB0aGUgc3RhdGVtZW50cyBmbG93IGFmdGVyIHRoaXMgcmV0dXJucy5cbmFzeW5jIGZ1bmN0aW9uIHNlbGVjdFBvcnRmb2xpbyhwYWdlOiBQYWdlLCB0YXJnZXRJRDogc3RyaW5nKSB7XG4gIGNvbnN0IGNsaWNrZWQgPSBhd2FpdCBwYWdlLiQkZXZhbChcbiAgICBQT1JURk9MSU9fT1BUSU9OX1NFTEVDVE9SLFxuICAgIChsaXMsIGlkKSA9PiB7XG4gICAgICBjb25zdCB0YXJnZXQgPSAobGlzIGFzIEhUTUxFbGVtZW50W10pLmZpbmQobGkgPT4gbGkudGV4dENvbnRlbnQ/LnRyaW0oKSA9PT0gaWQpO1xuICAgICAgaWYgKCF0YXJnZXQpIHJldHVybiBmYWxzZTtcbiAgICAgIHRhcmdldC5jbGljaygpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSxcbiAgICB0YXJnZXRJRCxcbiAgKTtcbiAgaWYgKCFjbGlja2VkKSB0aHJvdyBuZXcgRXJyb3IoYFBvcnRmb2xpbyBvcHRpb24gbm90IGZvdW5kIGZvciBJRDogJHt0YXJnZXRJRH1gKTtcbiAgYXdhaXQgd2FpdFVudGlsRWxlbWVudERpc2FwcGVhcihwYWdlLCAnLmxvYWRpbmctYmFyLXNwaW5uZXInKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hBY2NvdW50cyhwYWdlOiBQYWdlLCBzdGFydERhdGU6IE1vbWVudCwgb3B0aW9ucz86IFNjcmFwZXJPcHRpb25zKTogUHJvbWlzZTxUcmFuc2FjdGlvbnNBY2NvdW50W10+IHtcbiAgLy8gU25hcHNob3QgdXAgZnJvbnQ6IHRoZSBkcm9wZG93biBvbmx5IGxpc3RzIHVuc2VsZWN0ZWQgcG9ydGZvbGlvcywgc28gYWZ0ZXIgdGhlIGZpcnN0XG4gIC8vIHN3aXRjaCB3ZSB3b3VsZCBsb3NlIGFueSBub3QgeWV0IHNjcmFwZWQuXG4gIGNvbnN0IHBvcnRmb2xpb0lEcyA9IGF3YWl0IGdldFBvcnRmb2xpb0lEcyhwYWdlKTtcbiAgaWYgKHBvcnRmb2xpb0lEcy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHBvcnRmb2xpb3MgZm91bmQgb24gL21haW4vaG9tZSDigJQgWWFoYXYgRE9NIGxpa2VseSBjaGFuZ2VkJyk7XG4gIH1cbiAgY29uc3QgYWNjb3VudHM6IFRyYW5zYWN0aW9uc0FjY291bnRbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHBvcnRmb2xpb0lEcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgIGNvbnN0IHBvcnRmb2xpb0lEID0gcG9ydGZvbGlvSURzW2ldO1xuICAgIGlmIChpID4gMCkge1xuICAgICAgYXdhaXQgc2VsZWN0UG9ydGZvbGlvKHBhZ2UsIHBvcnRmb2xpb0lEKTtcbiAgICB9XG4gICAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsIEFDQ09VTlRfREVUQUlMU19TRUxFQ1RPUiwgdHJ1ZSk7XG4gICAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgQUNDT1VOVF9ERVRBSUxTX1NFTEVDVE9SKTtcbiAgICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgJy5zdGF0ZW1lbnQtb3B0aW9ucyAuc2VsZWN0ZWQtaXRlbS10b3AnLCB0cnVlKTtcbiAgICBhY2NvdW50cy5wdXNoKGF3YWl0IGZldGNoQWNjb3VudERhdGEocGFnZSwgc3RhcnREYXRlLCBwb3J0Zm9saW9JRCwgb3B0aW9ucykpO1xuICB9XG5cbiAgcmV0dXJuIGFjY291bnRzO1xufVxuXG5hc3luYyBmdW5jdGlvbiB3YWl0UmVhZGluZXNzRm9yQWxsKHBhZ2U6IFBhZ2UpIHtcbiAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsIGAke1VTRVJfRUxFTX1gLCB0cnVlKTtcbiAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsIGAke1BBU1NXRF9FTEVNfWAsIHRydWUpO1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgYCR7TkFUSU9OQUxJRF9FTEVNfWAsIHRydWUpO1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgYCR7U1VCTUlUX0xPR0lOX1NFTEVDVE9SfWAsIHRydWUpO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZWRpcmVjdE9yRGlhbG9nKHBhZ2U6IFBhZ2UpIHtcbiAgLy8gQ2xpY2sgb24gYmFuayBtZXNzYWdlcyBpZiBhbnkuXG4gIGF3YWl0IHdhaXRGb3JOYXZpZ2F0aW9uKHBhZ2UpO1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50RGlzYXBwZWFyKHBhZ2UsICcubG9hZGluZy1iYXItc3Bpbm5lcicpO1xuICBjb25zdCBoYXNNZXNzYWdlID0gYXdhaXQgZWxlbWVudFByZXNlbnRPblBhZ2UocGFnZSwgJy5tZXNzYWdpbmctbGlua3MtY29udGFpbmVyJyk7XG4gIGlmIChoYXNNZXNzYWdlKSB7XG4gICAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgJy5saW5rLTEnKTtcbiAgfVxuXG4gIGNvbnN0IHByb21pc2UxID0gcGFnZS53YWl0Rm9yU2VsZWN0b3IoQUNDT1VOVF9ERVRBSUxTX1NFTEVDVE9SLCB7IHRpbWVvdXQ6IDMwMDAwIH0pO1xuICBjb25zdCBwcm9taXNlMiA9IHBhZ2Uud2FpdEZvclNlbGVjdG9yKENIQU5HRV9QQVNTV09SRF9PTERfUEFTUywgeyB0aW1lb3V0OiAzMDAwMCB9KTtcbiAgY29uc3QgcHJvbWlzZXMgPSBbcHJvbWlzZTEsIHByb21pc2UyXTtcblxuICBhd2FpdCBQcm9taXNlLnJhY2UocHJvbWlzZXMpO1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50RGlzYXBwZWFyKHBhZ2UsICcubG9hZGluZy1iYXItc3Bpbm5lcicpO1xufVxuXG50eXBlIFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzID0geyB1c2VybmFtZTogc3RyaW5nOyBwYXNzd29yZDogc3RyaW5nOyBuYXRpb25hbElEOiBzdHJpbmcgfTtcblxuY2xhc3MgWWFoYXZTY3JhcGVyIGV4dGVuZHMgQmFzZVNjcmFwZXJXaXRoQnJvd3NlcjxTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscz4ge1xuICBnZXRMb2dpbk9wdGlvbnMoY3JlZGVudGlhbHM6IFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxvZ2luVXJsOiBgJHtMT0dJTl9VUkx9YCxcbiAgICAgIGZpZWxkczogW1xuICAgICAgICB7IHNlbGVjdG9yOiBgJHtVU0VSX0VMRU19YCwgdmFsdWU6IGNyZWRlbnRpYWxzLnVzZXJuYW1lIH0sXG4gICAgICAgIHsgc2VsZWN0b3I6IGAke1BBU1NXRF9FTEVNfWAsIHZhbHVlOiBjcmVkZW50aWFscy5wYXNzd29yZCB9LFxuICAgICAgICB7IHNlbGVjdG9yOiBgJHtOQVRJT05BTElEX0VMRU19YCwgdmFsdWU6IGNyZWRlbnRpYWxzLm5hdGlvbmFsSUQgfSxcbiAgICAgIF0sXG4gICAgICBzdWJtaXRCdXR0b25TZWxlY3RvcjogYCR7U1VCTUlUX0xPR0lOX1NFTEVDVE9SfWAsXG4gICAgICBjaGVja1JlYWRpbmVzczogYXN5bmMgKCkgPT4gd2FpdFJlYWRpbmVzc0ZvckFsbCh0aGlzLnBhZ2UpLFxuICAgICAgcG9zdEFjdGlvbjogYXN5bmMgKCkgPT4gcmVkaXJlY3RPckRpYWxvZyh0aGlzLnBhZ2UpLFxuICAgICAgcG9zc2libGVSZXN1bHRzOiBnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cyh0aGlzLnBhZ2UpLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBmZXRjaERhdGEoKSB7XG4gICAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHRoaXMucGFnZSwgQUNDT1VOVF9ERVRBSUxTX1NFTEVDVE9SLCB0cnVlKTtcblxuICAgIGNvbnN0IGRlZmF1bHRTdGFydE1vbWVudCA9IG1vbWVudCgpLnN1YnRyYWN0KDMsICdtb250aHMnKS5hZGQoMSwgJ2RheScpO1xuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IHRoaXMub3B0aW9ucy5zdGFydERhdGUgfHwgZGVmYXVsdFN0YXJ0TW9tZW50LnRvRGF0ZSgpO1xuICAgIGNvbnN0IHN0YXJ0TW9tZW50ID0gbW9tZW50Lm1pbihtb21lbnQubWF4KGRlZmF1bHRTdGFydE1vbWVudCwgbW9tZW50KHN0YXJ0RGF0ZSkpLCBtb21lbnQoKSk7XG5cbiAgICBjb25zdCBhY2NvdW50cyA9IGF3YWl0IGZldGNoQWNjb3VudHModGhpcy5wYWdlLCBzdGFydE1vbWVudCwgdGhpcy5vcHRpb25zKTtcblxuICAgIHJldHVybiB7XG4gICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgYWNjb3VudHMsXG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBZYWhhdlNjcmFwZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFDLFVBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLHFCQUFBLEdBQUFGLE9BQUE7QUFPQSxJQUFBRyxXQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxhQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxjQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSx1QkFBQSxHQUFBTixPQUFBO0FBQThHLFNBQUFELHVCQUFBUSxDQUFBLFdBQUFBLENBQUEsSUFBQUEsQ0FBQSxDQUFBQyxVQUFBLEdBQUFELENBQUEsS0FBQUUsT0FBQSxFQUFBRixDQUFBO0FBRzlHLE1BQU1HLFNBQVMsR0FBRyxrQ0FBa0M7QUFDcEQsTUFBTUMsUUFBUSxHQUFHLDZEQUE2RDtBQUM5RSxNQUFNQyx3QkFBd0IsR0FBRyxvQkFBb0I7QUFDckQsTUFBTUMsd0JBQXdCLEdBQUcsdUNBQXVDO0FBQ3hFLE1BQU1DLGdCQUFnQixHQUFHLEdBQUdILFFBQVEsV0FBVztBQUUvQyxNQUFNSSxjQUFjLEdBQUcsa0NBQWtDO0FBQ3pELE1BQU1DLDBCQUEwQixHQUFHLHNCQUFzQjtBQUN6RCxNQUFNQyx5QkFBeUIsR0FBRyxHQUFHRixjQUFjLHFCQUFxQjtBQUN4RSxNQUFNRyx5QkFBeUIsR0FBRyxHQUFHSCxjQUFjLHlDQUF5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