UNPKG

israeli-bank-scrapers

Version:

Provide scrapers for all major Israeli banks and credit card companies

200 lines (195 loc) 35.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _moment = _interopRequireDefault(require("moment")); var _constants = require("../constants"); var _debug = require("../helpers/debug"); var _elementsInteractions = require("../helpers/elements-interactions"); var _navigation = require("../helpers/navigation"); var _transactions = require("../transactions"); var _baseScraperWithBrowser = require("./base-scraper-with-browser"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const debug = (0, _debug.getDebug)('leumi'); const BASE_URL = 'https://hb2.bankleumi.co.il'; const LOGIN_URL = 'https://www.leumi.co.il/'; const TRANSACTIONS_URL = `${BASE_URL}/eBanking/SO/SPA.aspx#/ts/BusinessAccountTrx?WidgetPar=1`; const FILTERED_TRANSACTIONS_URL = `${BASE_URL}/ChannelWCF/Broker.svc/ProcessRequest?moduleName=UC_SO_27_GetBusinessAccountTrx`; const DATE_FORMAT = 'DD.MM.YY'; const ACCOUNT_BLOCKED_MSG = 'המנוי חסום'; const INVALID_PASSWORD_MSG = 'אחד או יותר מפרטי ההזדהות שמסרת שגויים. ניתן לנסות שוב'; function getPossibleLoginResults() { const urls = { [_baseScraperWithBrowser.LoginResults.Success]: [/ebanking\/SO\/SPA.aspx/i], [_baseScraperWithBrowser.LoginResults.InvalidPassword]: [async options => { if (!options || !options.page) { throw new Error('missing page options argument'); } const errorMessage = await (0, _elementsInteractions.pageEvalAll)(options.page, 'svg#Capa_1', '', element => { return element[0]?.parentElement?.children[1]?.innerText; }); return errorMessage?.startsWith(INVALID_PASSWORD_MSG); }], [_baseScraperWithBrowser.LoginResults.AccountBlocked]: [ // NOTICE - might not be relevant starting the Leumi re-design during 2022 Sep async options => { if (!options || !options.page) { throw new Error('missing page options argument'); } const errorMessage = await (0, _elementsInteractions.pageEvalAll)(options.page, '.errHeader', '', label => { return label[0]?.innerText; }); return errorMessage?.startsWith(ACCOUNT_BLOCKED_MSG); }], [_baseScraperWithBrowser.LoginResults.ChangePassword]: ['https://hb2.bankleumi.co.il/authenticate'] // NOTICE - might not be relevant starting the Leumi re-design during 2022 Sep }; return urls; } function createLoginFields(credentials) { return [{ selector: 'input[placeholder="שם משתמש"]', value: credentials.username }, { selector: 'input[placeholder="סיסמה"]', value: credentials.password }]; } function extractTransactionsFromPage(transactions, status) { if (transactions === null || transactions.length === 0) { return []; } const result = transactions.map(rawTransaction => { const date = (0, _moment.default)(rawTransaction.DateUTC).milliseconds(0).toISOString(); const newTransaction = { status, type: _transactions.TransactionTypes.Normal, date, processedDate: date, description: rawTransaction.Description || '', identifier: rawTransaction.ReferenceNumberLong, memo: rawTransaction.AdditionalData || '', originalCurrency: _constants.SHEKEL_CURRENCY, chargedAmount: rawTransaction.Amount, originalAmount: rawTransaction.Amount }; return newTransaction; }); return result; } function hangProcess(timeout) { return new Promise(resolve => { setTimeout(() => { resolve(); }, timeout); }); } async function clickByXPath(page, xpath) { await page.waitForSelector(xpath, { timeout: 30000, visible: true }); const elm = await page.$$(xpath); await elm[0].click(); } function removeSpecialCharacters(str) { return str.replace(/[^0-9/-]/g, ''); } async function fetchTransactionsForAccount(page, startDate, accountId) { // DEVELOPER NOTICE the account number received from the server is being altered at // runtime for some accounts after 1-2 seconds so we need to hang the process for a short while. await hangProcess(4000); await (0, _elementsInteractions.waitUntilElementFound)(page, 'button[title="חיפוש מתקדם"]', true); await (0, _elementsInteractions.clickButton)(page, 'button[title="חיפוש מתקדם"]'); await (0, _elementsInteractions.waitUntilElementFound)(page, 'bll-radio-button', true); await (0, _elementsInteractions.clickButton)(page, 'bll-radio-button:not([checked])'); await (0, _elementsInteractions.waitUntilElementFound)(page, 'input[formcontrolname="txtInputFrom"]', true); await (0, _elementsInteractions.fillInput)(page, 'input[formcontrolname="txtInputFrom"]', startDate.format(DATE_FORMAT)); // we must blur the from control otherwise the search will use the previous value await page.focus("button[aria-label='סנן']"); await (0, _elementsInteractions.clickButton)(page, "button[aria-label='סנן']"); const finalResponse = await page.waitForResponse(response => { return response.url() === FILTERED_TRANSACTIONS_URL && response.request().method() === 'POST'; }); const responseJson = await finalResponse.json(); const accountNumber = accountId.replace('/', '_').replace(/[^\d-_]/g, ''); const response = JSON.parse(responseJson.jsonResp); const pendingTransactions = response.TodayTransactionsItems; const transactions = response.HistoryTransactionsItems; const balance = response.BalanceDisplay ? parseFloat(response.BalanceDisplay) : undefined; const pendingTxns = extractTransactionsFromPage(pendingTransactions, _transactions.TransactionStatuses.Pending); const completedTxns = extractTransactionsFromPage(transactions, _transactions.TransactionStatuses.Completed); const txns = [...pendingTxns, ...completedTxns]; return { accountNumber, balance, txns }; } async function fetchTransactions(page, startDate) { const accounts = []; // DEVELOPER NOTICE the account number received from the server is being altered at // runtime for some accounts after 1-2 seconds so we need to hang the process for a short while. await hangProcess(4000); const accountsIds = await page.evaluate(() => Array.from(document.querySelectorAll('app-masked-number-combo span.display-number-li'), e => e.textContent)); // due to a bug, the altered value might include undesired signs like & that should be removed if (!accountsIds.length) { throw new Error('Failed to extract or parse the account number'); } for (const accountId of accountsIds) { if (accountsIds.length > 1) { // get list of accounts and check accountId await clickByXPath(page, 'xpath///*[contains(@class, "number") and contains(@class, "combo-inner")]'); await clickByXPath(page, `xpath///span[contains(text(), '${accountId}')]`); } accounts.push(await fetchTransactionsForAccount(page, startDate, removeSpecialCharacters(accountId))); } return accounts; } async function navigateToLogin(page) { const loginButtonSelector = '.enter-account a[originaltitle="כניסה לחשבונך"]'; debug('wait for homepage to click on login button'); await (0, _elementsInteractions.waitUntilElementFound)(page, loginButtonSelector); debug('navigate to login page'); const loginUrl = await (0, _elementsInteractions.pageEval)(page, loginButtonSelector, null, element => { return element.href; }); debug(`navigating to page (${loginUrl})`); await page.goto(loginUrl); debug('waiting for page to be loaded (networkidle2)'); await (0, _navigation.waitForNavigation)(page, { waitUntil: 'networkidle2' }); debug('waiting for components of login to enter credentials'); await Promise.all([(0, _elementsInteractions.waitUntilElementFound)(page, 'input[placeholder="שם משתמש"]', true), (0, _elementsInteractions.waitUntilElementFound)(page, 'input[placeholder="סיסמה"]', true), (0, _elementsInteractions.waitUntilElementFound)(page, 'button[type="submit"]', true)]); } async function waitForPostLogin(page) { await Promise.race([(0, _elementsInteractions.waitUntilElementFound)(page, 'a[title="דלג לחשבון"]', true, 60000), (0, _elementsInteractions.waitUntilElementFound)(page, 'div.main-content', false, 60000), page.waitForSelector(`xpath//div[contains(string(),"${INVALID_PASSWORD_MSG}")]`), (0, _elementsInteractions.waitUntilElementFound)(page, 'form[action="/changepassword"]', true, 60000) // not sure if they kept this one ]); } class LeumiScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser { getLoginOptions(credentials) { return { loginUrl: LOGIN_URL, fields: createLoginFields(credentials), submitButtonSelector: "button[type='submit']", checkReadiness: async () => navigateToLogin(this.page), postAction: async () => waitForPostLogin(this.page), possibleResults: getPossibleLoginResults() }; } async fetchData() { const minimumStartMoment = (0, _moment.default)().subtract(3, 'years').add(1, 'day'); const defaultStartMoment = (0, _moment.default)().subtract(1, 'years').add(1, 'day'); const startDate = this.options.startDate || defaultStartMoment.toDate(); const startMoment = _moment.default.max(minimumStartMoment, (0, _moment.default)(startDate)); await this.navigateTo(TRANSACTIONS_URL); const accounts = await fetchTransactions(this.page, startMoment); return { success: true, accounts }; } } var _default = exports.default = LeumiScraper; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29uc3RhbnRzIiwiX2RlYnVnIiwiX2VsZW1lbnRzSW50ZXJhY3Rpb25zIiwiX25hdmlnYXRpb24iLCJfdHJhbnNhY3Rpb25zIiwiX2Jhc2VTY3JhcGVyV2l0aEJyb3dzZXIiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJkZWJ1ZyIsImdldERlYnVnIiwiQkFTRV9VUkwiLCJMT0dJTl9VUkwiLCJUUkFOU0FDVElPTlNfVVJMIiwiRklMVEVSRURfVFJBTlNBQ1RJT05TX1VSTCIsIkRBVEVfRk9STUFUIiwiQUNDT1VOVF9CTE9DS0VEX01TRyIsIklOVkFMSURfUEFTU1dPUkRfTVNHIiwiZ2V0UG9zc2libGVMb2dpblJlc3VsdHMiLCJ1cmxzIiwiTG9naW5SZXN1bHRzIiwiU3VjY2VzcyIsIkludmFsaWRQYXNzd29yZCIsIm9wdGlvbnMiLCJwYWdlIiwiRXJyb3IiLCJlcnJvck1lc3NhZ2UiLCJwYWdlRXZhbEFsbCIsImVsZW1lbnQiLCJwYXJlbnRFbGVtZW50IiwiY2hpbGRyZW4iLCJpbm5lclRleHQiLCJzdGFydHNXaXRoIiwiQWNjb3VudEJsb2NrZWQiLCJsYWJlbCIsIkNoYW5nZVBhc3N3b3JkIiwiY3JlYXRlTG9naW5GaWVsZHMiLCJjcmVkZW50aWFscyIsInNlbGVjdG9yIiwidmFsdWUiLCJ1c2VybmFtZSIsInBhc3N3b3JkIiwiZXh0cmFjdFRyYW5zYWN0aW9uc0Zyb21QYWdlIiwidHJhbnNhY3Rpb25zIiwic3RhdHVzIiwibGVuZ3RoIiwicmVzdWx0IiwibWFwIiwicmF3VHJhbnNhY3Rpb24iLCJkYXRlIiwibW9tZW50IiwiRGF0ZVVUQyIsIm1pbGxpc2Vjb25kcyIsInRvSVNPU3RyaW5nIiwibmV3VHJhbnNhY3Rpb24iLCJ0eXBlIiwiVHJhbnNhY3Rpb25UeXBlcyIsIk5vcm1hbCIsInByb2Nlc3NlZERhdGUiLCJkZXNjcmlwdGlvbiIsIkRlc2NyaXB0aW9uIiwiaWRlbnRpZmllciIsIlJlZmVyZW5jZU51bWJlckxvbmciLCJtZW1vIiwiQWRkaXRpb25hbERhdGEiLCJvcmlnaW5hbEN1cnJlbmN5IiwiU0hFS0VMX0NVUlJFTkNZIiwiY2hhcmdlZEFtb3VudCIsIkFtb3VudCIsIm9yaWdpbmFsQW1vdW50IiwiaGFuZ1Byb2Nlc3MiLCJ0aW1lb3V0IiwiUHJvbWlzZSIsInJlc29sdmUiLCJzZXRUaW1lb3V0IiwiY2xpY2tCeVhQYXRoIiwieHBhdGgiLCJ3YWl0Rm9yU2VsZWN0b3IiLCJ2aXNpYmxlIiwiZWxtIiwiJCQiLCJjbGljayIsInJlbW92ZVNwZWNpYWxDaGFyYWN0ZXJzIiwic3RyIiwicmVwbGFjZSIsImZldGNoVHJhbnNhY3Rpb25zRm9yQWNjb3VudCIsInN0YXJ0RGF0ZSIsImFjY291bnRJZCIsIndhaXRVbnRpbEVsZW1lbnRGb3VuZCIsImNsaWNrQnV0dG9uIiwiZmlsbElucHV0IiwiZm9ybWF0IiwiZm9jdXMiLCJmaW5hbFJlc3BvbnNlIiwid2FpdEZvclJlc3BvbnNlIiwicmVzcG9uc2UiLCJ1cmwiLCJyZXF1ZXN0IiwibWV0aG9kIiwicmVzcG9uc2VKc29uIiwianNvbiIsImFjY291bnROdW1iZXIiLCJKU09OIiwicGFyc2UiLCJqc29uUmVzcCIsInBlbmRpbmdUcmFuc2FjdGlvbnMiLCJUb2RheVRyYW5zYWN0aW9uc0l0ZW1zIiwiSGlzdG9yeVRyYW5zYWN0aW9uc0l0ZW1zIiwiYmFsYW5jZSIsIkJhbGFuY2VEaXNwbGF5IiwicGFyc2VGbG9hdCIsInVuZGVmaW5lZCIsInBlbmRpbmdUeG5zIiwiVHJhbnNhY3Rpb25TdGF0dXNlcyIsIlBlbmRpbmciLCJjb21wbGV0ZWRUeG5zIiwiQ29tcGxldGVkIiwidHhucyIsImZldGNoVHJhbnNhY3Rpb25zIiwiYWNjb3VudHMiLCJhY2NvdW50c0lkcyIsImV2YWx1YXRlIiwiQXJyYXkiLCJmcm9tIiwiZG9jdW1lbnQiLCJxdWVyeVNlbGVjdG9yQWxsIiwidGV4dENvbnRlbnQiLCJwdXNoIiwibmF2aWdhdGVUb0xvZ2luIiwibG9naW5CdXR0b25TZWxlY3RvciIsImxvZ2luVXJsIiwicGFnZUV2YWwiLCJocmVmIiwiZ290byIsIndhaXRGb3JOYXZpZ2F0aW9uIiwid2FpdFVudGlsIiwiYWxsIiwid2FpdEZvclBvc3RMb2dpbiIsInJhY2UiLCJMZXVtaVNjcmFwZXIiLCJCYXNlU2NyYXBlcldpdGhCcm93c2VyIiwiZ2V0TG9naW5PcHRpb25zIiwiZmllbGRzIiwic3VibWl0QnV0dG9uU2VsZWN0b3IiLCJjaGVja1JlYWRpbmVzcyIsInBvc3RBY3Rpb24iLCJwb3NzaWJsZVJlc3VsdHMiLCJmZXRjaERhdGEiLCJtaW5pbXVtU3RhcnRNb21lbnQiLCJzdWJ0cmFjdCIsImFkZCIsImRlZmF1bHRTdGFydE1vbWVudCIsInRvRGF0ZSIsInN0YXJ0TW9tZW50IiwibWF4IiwibmF2aWdhdGVUbyIsInN1Y2Nlc3MiLCJfZGVmYXVsdCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyYXBlcnMvbGV1bWkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG1vbWVudCwgeyB0eXBlIE1vbWVudCB9IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgeyB0eXBlIFBhZ2UgfSBmcm9tICdwdXBwZXRlZXInO1xuaW1wb3J0IHsgU0hFS0VMX0NVUlJFTkNZIH0gZnJvbSAnLi4vY29uc3RhbnRzJztcbmltcG9ydCB7IGdldERlYnVnIH0gZnJvbSAnLi4vaGVscGVycy9kZWJ1Zyc7XG5pbXBvcnQgeyBjbGlja0J1dHRvbiwgZmlsbElucHV0LCBwYWdlRXZhbCwgcGFnZUV2YWxBbGwsIHdhaXRVbnRpbEVsZW1lbnRGb3VuZCB9IGZyb20gJy4uL2hlbHBlcnMvZWxlbWVudHMtaW50ZXJhY3Rpb25zJztcbmltcG9ydCB7IHdhaXRGb3JOYXZpZ2F0aW9uIH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uU3RhdHVzZXMsIFRyYW5zYWN0aW9uVHlwZXMsIHR5cGUgVHJhbnNhY3Rpb24sIHR5cGUgVHJhbnNhY3Rpb25zQWNjb3VudCB9IGZyb20gJy4uL3RyYW5zYWN0aW9ucyc7XG5pbXBvcnQgeyBCYXNlU2NyYXBlcldpdGhCcm93c2VyLCBMb2dpblJlc3VsdHMsIHR5cGUgTG9naW5PcHRpb25zIH0gZnJvbSAnLi9iYXNlLXNjcmFwZXItd2l0aC1icm93c2VyJztcbmltcG9ydCB7IHR5cGUgU2NyYXBlclNjcmFwaW5nUmVzdWx0IH0gZnJvbSAnLi9pbnRlcmZhY2UnO1xuXG5jb25zdCBkZWJ1ZyA9IGdldERlYnVnKCdsZXVtaScpO1xuY29uc3QgQkFTRV9VUkwgPSAnaHR0cHM6Ly9oYjIuYmFua2xldW1pLmNvLmlsJztcbmNvbnN0IExPR0lOX1VSTCA9ICdodHRwczovL3d3dy5sZXVtaS5jby5pbC8nO1xuY29uc3QgVFJBTlNBQ1RJT05TX1VSTCA9IGAke0JBU0VfVVJMfS9lQmFua2luZy9TTy9TUEEuYXNweCMvdHMvQnVzaW5lc3NBY2NvdW50VHJ4P1dpZGdldFBhcj0xYDtcbmNvbnN0IEZJTFRFUkVEX1RSQU5TQUNUSU9OU19VUkwgPSBgJHtCQVNFX1VSTH0vQ2hhbm5lbFdDRi9Ccm9rZXIuc3ZjL1Byb2Nlc3NSZXF1ZXN0P21vZHVsZU5hbWU9VUNfU09fMjdfR2V0QnVzaW5lc3NBY2NvdW50VHJ4YDtcblxuY29uc3QgREFURV9GT1JNQVQgPSAnREQuTU0uWVknO1xuY29uc3QgQUNDT1VOVF9CTE9DS0VEX01TRyA9ICfXlNee16DXldeZINeX16HXldedJztcbmNvbnN0IElOVkFMSURfUEFTU1dPUkRfTVNHID0gJ9eQ15fXkyDXkNeVINeZ15XXqteoINee16TXqNeY15kg15TXlNeW15PXlNeV16og16nXnteh16jXqiDXqdeS15XXmdeZ150uINeg15nXqtefINec16DXodeV16og16nXldeRJztcblxuZnVuY3Rpb24gZ2V0UG9zc2libGVMb2dpblJlc3VsdHMoKSB7XG4gIGNvbnN0IHVybHM6IExvZ2luT3B0aW9uc1sncG9zc2libGVSZXN1bHRzJ10gPSB7XG4gICAgW0xvZ2luUmVzdWx0cy5TdWNjZXNzXTogWy9lYmFua2luZ1xcL1NPXFwvU1BBLmFzcHgvaV0sXG4gICAgW0xvZ2luUmVzdWx0cy5JbnZhbGlkUGFzc3dvcmRdOiBbXG4gICAgICBhc3luYyBvcHRpb25zID0+IHtcbiAgICAgICAgaWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLnBhZ2UpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcGFnZSBvcHRpb25zIGFyZ3VtZW50Jyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYXdhaXQgcGFnZUV2YWxBbGwob3B0aW9ucy5wYWdlLCAnc3ZnI0NhcGFfMScsICcnLCBlbGVtZW50ID0+IHtcbiAgICAgICAgICByZXR1cm4gKGVsZW1lbnRbMF0/LnBhcmVudEVsZW1lbnQ/LmNoaWxkcmVuWzFdIGFzIEhUTUxEaXZFbGVtZW50KT8uaW5uZXJUZXh0O1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gZXJyb3JNZXNzYWdlPy5zdGFydHNXaXRoKElOVkFMSURfUEFTU1dPUkRfTVNHKTtcbiAgICAgIH0sXG4gICAgXSxcbiAgICBbTG9naW5SZXN1bHRzLkFjY291bnRCbG9ja2VkXTogW1xuICAgICAgLy8gTk9USUNFIC0gbWlnaHQgbm90IGJlIHJlbGV2YW50IHN0YXJ0aW5nIHRoZSBMZXVtaSByZS1kZXNpZ24gZHVyaW5nIDIwMjIgU2VwXG4gICAgICBhc3luYyBvcHRpb25zID0+IHtcbiAgICAgICAgaWYgKCFvcHRpb25zIHx8ICFvcHRpb25zLnBhZ2UpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcGFnZSBvcHRpb25zIGFyZ3VtZW50Jyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gYXdhaXQgcGFnZUV2YWxBbGwob3B0aW9ucy5wYWdlLCAnLmVyckhlYWRlcicsICcnLCBsYWJlbCA9PiB7XG4gICAgICAgICAgcmV0dXJuIChsYWJlbFswXSBhcyBIVE1MRWxlbWVudCk/LmlubmVyVGV4dDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGVycm9yTWVzc2FnZT8uc3RhcnRzV2l0aChBQ0NPVU5UX0JMT0NLRURfTVNHKTtcbiAgICAgIH0sXG4gICAgXSxcbiAgICBbTG9naW5SZXN1bHRzLkNoYW5nZVBhc3N3b3JkXTogWydodHRwczovL2hiMi5iYW5rbGV1bWkuY28uaWwvYXV0aGVudGljYXRlJ10sIC8vIE5PVElDRSAtIG1pZ2h0IG5vdCBiZSByZWxldmFudCBzdGFydGluZyB0aGUgTGV1bWkgcmUtZGVzaWduIGR1cmluZyAyMDIyIFNlcFxuICB9O1xuICByZXR1cm4gdXJscztcbn1cblxuZnVuY3Rpb24gY3JlYXRlTG9naW5GaWVsZHMoY3JlZGVudGlhbHM6IFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzKSB7XG4gIHJldHVybiBbXG4gICAgeyBzZWxlY3RvcjogJ2lucHV0W3BsYWNlaG9sZGVyPVwi16nXnSDXntep16rXntepXCJdJywgdmFsdWU6IGNyZWRlbnRpYWxzLnVzZXJuYW1lIH0sXG4gICAgeyBzZWxlY3RvcjogJ2lucHV0W3BsYWNlaG9sZGVyPVwi16HXmdeh157XlFwiXScsIHZhbHVlOiBjcmVkZW50aWFscy5wYXNzd29yZCB9LFxuICBdO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVBhZ2UodHJhbnNhY3Rpb25zOiBhbnlbXSwgc3RhdHVzOiBUcmFuc2FjdGlvblN0YXR1c2VzKTogVHJhbnNhY3Rpb25bXSB7XG4gIGlmICh0cmFuc2FjdGlvbnMgPT09IG51bGwgfHwgdHJhbnNhY3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdDogVHJhbnNhY3Rpb25bXSA9IHRyYW5zYWN0aW9ucy5tYXAocmF3VHJhbnNhY3Rpb24gPT4ge1xuICAgIGNvbnN0IGRhdGUgPSBtb21lbnQocmF3VHJhbnNhY3Rpb24uRGF0ZVVUQykubWlsbGlzZWNvbmRzKDApLnRvSVNPU3RyaW5nKCk7XG4gICAgY29uc3QgbmV3VHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uID0ge1xuICAgICAgc3RhdHVzLFxuICAgICAgdHlwZTogVHJhbnNhY3Rpb25UeXBlcy5Ob3JtYWwsXG4gICAgICBkYXRlLFxuICAgICAgcHJvY2Vzc2VkRGF0ZTogZGF0ZSxcbiAgICAgIGRlc2NyaXB0aW9uOiByYXdUcmFuc2FjdGlvbi5EZXNjcmlwdGlvbiB8fCAnJyxcbiAgICAgIGlkZW50aWZpZXI6IHJhd1RyYW5zYWN0aW9uLlJlZmVyZW5jZU51bWJlckxvbmcsXG4gICAgICBtZW1vOiByYXdUcmFuc2FjdGlvbi5BZGRpdGlvbmFsRGF0YSB8fCAnJyxcbiAgICAgIG9yaWdpbmFsQ3VycmVuY3k6IFNIRUtFTF9DVVJSRU5DWSxcbiAgICAgIGNoYXJnZWRBbW91bnQ6IHJhd1RyYW5zYWN0aW9uLkFtb3VudCxcbiAgICAgIG9yaWdpbmFsQW1vdW50OiByYXdUcmFuc2FjdGlvbi5BbW91bnQsXG4gICAgfTtcblxuICAgIHJldHVybiBuZXdUcmFuc2FjdGlvbjtcbiAgfSk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gaGFuZ1Byb2Nlc3ModGltZW91dDogbnVtYmVyKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPihyZXNvbHZlID0+IHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHJlc29sdmUoKTtcbiAgICB9LCB0aW1lb3V0KTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNsaWNrQnlYUGF0aChwYWdlOiBQYWdlLCB4cGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IHBhZ2Uud2FpdEZvclNlbGVjdG9yKHhwYXRoLCB7IHRpbWVvdXQ6IDMwMDAwLCB2aXNpYmxlOiB0cnVlIH0pO1xuICBjb25zdCBlbG0gPSBhd2FpdCBwYWdlLiQkKHhwYXRoKTtcbiAgYXdhaXQgZWxtWzBdLmNsaWNrKCk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZVNwZWNpYWxDaGFyYWN0ZXJzKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9bXjAtOS8tXS9nLCAnJyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoVHJhbnNhY3Rpb25zRm9yQWNjb3VudChcbiAgcGFnZTogUGFnZSxcbiAgc3RhcnREYXRlOiBNb21lbnQsXG4gIGFjY291bnRJZDogc3RyaW5nLFxuKTogUHJvbWlzZTxUcmFuc2FjdGlvbnNBY2NvdW50PiB7XG4gIC8vIERFVkVMT1BFUiBOT1RJQ0UgdGhlIGFjY291bnQgbnVtYmVyIHJlY2VpdmVkIGZyb20gdGhlIHNlcnZlciBpcyBiZWluZyBhbHRlcmVkIGF0XG4gIC8vIHJ1bnRpbWUgZm9yIHNvbWUgYWNjb3VudHMgYWZ0ZXIgMS0yIHNlY29uZHMgc28gd2UgbmVlZCB0byBoYW5nIHRoZSBwcm9jZXNzIGZvciBhIHNob3J0IHdoaWxlLlxuICBhd2FpdCBoYW5nUHJvY2Vzcyg0MDAwKTtcblxuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgJ2J1dHRvblt0aXRsZT1cIteX15nXpNeV16kg157Xqten15PXnVwiXScsIHRydWUpO1xuICBhd2FpdCBjbGlja0J1dHRvbihwYWdlLCAnYnV0dG9uW3RpdGxlPVwi15fXmdek15XXqSDXnteq16fXk9edXCJdJyk7XG4gIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCAnYmxsLXJhZGlvLWJ1dHRvbicsIHRydWUpO1xuICBhd2FpdCBjbGlja0J1dHRvbihwYWdlLCAnYmxsLXJhZGlvLWJ1dHRvbjpub3QoW2NoZWNrZWRdKScpO1xuXG4gIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCAnaW5wdXRbZm9ybWNvbnRyb2xuYW1lPVwidHh0SW5wdXRGcm9tXCJdJywgdHJ1ZSk7XG5cbiAgYXdhaXQgZmlsbElucHV0KHBhZ2UsICdpbnB1dFtmb3JtY29udHJvbG5hbWU9XCJ0eHRJbnB1dEZyb21cIl0nLCBzdGFydERhdGUuZm9ybWF0KERBVEVfRk9STUFUKSk7XG5cbiAgLy8gd2UgbXVzdCBibHVyIHRoZSBmcm9tIGNvbnRyb2wgb3RoZXJ3aXNlIHRoZSBzZWFyY2ggd2lsbCB1c2UgdGhlIHByZXZpb3VzIHZhbHVlXG4gIGF3YWl0IHBhZ2UuZm9jdXMoXCJidXR0b25bYXJpYS1sYWJlbD0n16HXoNefJ11cIik7XG5cbiAgYXdhaXQgY2xpY2tCdXR0b24ocGFnZSwgXCJidXR0b25bYXJpYS1sYWJlbD0n16HXoNefJ11cIik7XG4gIGNvbnN0IGZpbmFsUmVzcG9uc2UgPSBhd2FpdCBwYWdlLndhaXRGb3JSZXNwb25zZShyZXNwb25zZSA9PiB7XG4gICAgcmV0dXJuIHJlc3BvbnNlLnVybCgpID09PSBGSUxURVJFRF9UUkFOU0FDVElPTlNfVVJMICYmIHJlc3BvbnNlLnJlcXVlc3QoKS5tZXRob2QoKSA9PT0gJ1BPU1QnO1xuICB9KTtcblxuICBjb25zdCByZXNwb25zZUpzb246IGFueSA9IGF3YWl0IGZpbmFsUmVzcG9uc2UuanNvbigpO1xuXG4gIGNvbnN0IGFjY291bnROdW1iZXIgPSBhY2NvdW50SWQucmVwbGFjZSgnLycsICdfJykucmVwbGFjZSgvW15cXGQtX10vZywgJycpO1xuXG4gIGNvbnN0IHJlc3BvbnNlID0gSlNPTi5wYXJzZShyZXNwb25zZUpzb24uanNvblJlc3ApO1xuXG4gIGNvbnN0IHBlbmRpbmdUcmFuc2FjdGlvbnMgPSByZXNwb25zZS5Ub2RheVRyYW5zYWN0aW9uc0l0ZW1zO1xuICBjb25zdCB0cmFuc2FjdGlvbnMgPSByZXNwb25zZS5IaXN0b3J5VHJhbnNhY3Rpb25zSXRlbXM7XG4gIGNvbnN0IGJhbGFuY2UgPSByZXNwb25zZS5CYWxhbmNlRGlzcGxheSA/IHBhcnNlRmxvYXQocmVzcG9uc2UuQmFsYW5jZURpc3BsYXkpIDogdW5kZWZpbmVkO1xuXG4gIGNvbnN0IHBlbmRpbmdUeG5zID0gZXh0cmFjdFRyYW5zYWN0aW9uc0Zyb21QYWdlKHBlbmRpbmdUcmFuc2FjdGlvbnMsIFRyYW5zYWN0aW9uU3RhdHVzZXMuUGVuZGluZyk7XG4gIGNvbnN0IGNvbXBsZXRlZFR4bnMgPSBleHRyYWN0VHJhbnNhY3Rpb25zRnJvbVBhZ2UodHJhbnNhY3Rpb25zLCBUcmFuc2FjdGlvblN0YXR1c2VzLkNvbXBsZXRlZCk7XG4gIGNvbnN0IHR4bnMgPSBbLi4ucGVuZGluZ1R4bnMsIC4uLmNvbXBsZXRlZFR4bnNdO1xuXG4gIHJldHVybiB7XG4gICAgYWNjb3VudE51bWJlcixcbiAgICBiYWxhbmNlLFxuICAgIHR4bnMsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoVHJhbnNhY3Rpb25zKHBhZ2U6IFBhZ2UsIHN0YXJ0RGF0ZTogTW9tZW50KTogUHJvbWlzZTxUcmFuc2FjdGlvbnNBY2NvdW50W10+IHtcbiAgY29uc3QgYWNjb3VudHM6IFRyYW5zYWN0aW9uc0FjY291bnRbXSA9IFtdO1xuXG4gIC8vIERFVkVMT1BFUiBOT1RJQ0UgdGhlIGFjY291bnQgbnVtYmVyIHJlY2VpdmVkIGZyb20gdGhlIHNlcnZlciBpcyBiZWluZyBhbHRlcmVkIGF0XG4gIC8vIHJ1bnRpbWUgZm9yIHNvbWUgYWNjb3VudHMgYWZ0ZXIgMS0yIHNlY29uZHMgc28gd2UgbmVlZCB0byBoYW5nIHRoZSBwcm9jZXNzIGZvciBhIHNob3J0IHdoaWxlLlxuICBhd2FpdCBoYW5nUHJvY2Vzcyg0MDAwKTtcblxuICBjb25zdCBhY2NvdW50c0lkcyA9IChhd2FpdCBwYWdlLmV2YWx1YXRlKCgpID0+XG4gICAgQXJyYXkuZnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdhcHAtbWFza2VkLW51bWJlci1jb21ibyBzcGFuLmRpc3BsYXktbnVtYmVyLWxpJyksIGUgPT4gZS50ZXh0Q29udGVudCksXG4gICkpIGFzIHN0cmluZ1tdO1xuXG4gIC8vIGR1ZSB0byBhIGJ1ZywgdGhlIGFsdGVyZWQgdmFsdWUgbWlnaHQgaW5jbHVkZSB1bmRlc2lyZWQgc2lnbnMgbGlrZSAmIHRoYXQgc2hvdWxkIGJlIHJlbW92ZWRcblxuICBpZiAoIWFjY291bnRzSWRzLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGV4dHJhY3Qgb3IgcGFyc2UgdGhlIGFjY291bnQgbnVtYmVyJyk7XG4gIH1cblxuICBmb3IgKGNvbnN0IGFjY291bnRJZCBvZiBhY2NvdW50c0lkcykge1xuICAgIGlmIChhY2NvdW50c0lkcy5sZW5ndGggPiAxKSB7XG4gICAgICAvLyBnZXQgbGlzdCBvZiBhY2NvdW50cyBhbmQgY2hlY2sgYWNjb3VudElkXG4gICAgICBhd2FpdCBjbGlja0J5WFBhdGgocGFnZSwgJ3hwYXRoLy8vKltjb250YWlucyhAY2xhc3MsIFwibnVtYmVyXCIpIGFuZCBjb250YWlucyhAY2xhc3MsIFwiY29tYm8taW5uZXJcIildJyk7XG4gICAgICBhd2FpdCBjbGlja0J5WFBhdGgocGFnZSwgYHhwYXRoLy8vc3Bhbltjb250YWlucyh0ZXh0KCksICcke2FjY291bnRJZH0nKV1gKTtcbiAgICB9XG5cbiAgICBhY2NvdW50cy5wdXNoKGF3YWl0IGZldGNoVHJhbnNhY3Rpb25zRm9yQWNjb3VudChwYWdlLCBzdGFydERhdGUsIHJlbW92ZVNwZWNpYWxDaGFyYWN0ZXJzKGFjY291bnRJZCkpKTtcbiAgfVxuXG4gIHJldHVybiBhY2NvdW50cztcbn1cblxuYXN5bmMgZnVuY3Rpb24gbmF2aWdhdGVUb0xvZ2luKHBhZ2U6IFBhZ2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgbG9naW5CdXR0b25TZWxlY3RvciA9ICcuZW50ZXItYWNjb3VudCBhW29yaWdpbmFsdGl0bGU9XCLXm9eg15nXodeUINec15fXqdeR15XXoNeaXCJdJztcbiAgZGVidWcoJ3dhaXQgZm9yIGhvbWVwYWdlIHRvIGNsaWNrIG9uIGxvZ2luIGJ1dHRvbicpO1xuICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgbG9naW5CdXR0b25TZWxlY3Rvcik7XG4gIGRlYnVnKCduYXZpZ2F0ZSB0byBsb2dpbiBwYWdlJyk7XG4gIGNvbnN0IGxvZ2luVXJsID0gYXdhaXQgcGFnZUV2YWwocGFnZSwgbG9naW5CdXR0b25TZWxlY3RvciwgbnVsbCwgZWxlbWVudCA9PiB7XG4gICAgcmV0dXJuIChlbGVtZW50IGFzIGFueSkuaHJlZjtcbiAgfSk7XG4gIGRlYnVnKGBuYXZpZ2F0aW5nIHRvIHBhZ2UgKCR7bG9naW5Vcmx9KWApO1xuICBhd2FpdCBwYWdlLmdvdG8obG9naW5VcmwpO1xuICBkZWJ1Zygnd2FpdGluZyBmb3IgcGFnZSB0byBiZSBsb2FkZWQgKG5ldHdvcmtpZGxlMiknKTtcbiAgYXdhaXQgd2FpdEZvck5hdmlnYXRpb24ocGFnZSwgeyB3YWl0VW50aWw6ICduZXR3b3JraWRsZTInIH0pO1xuICBkZWJ1Zygnd2FpdGluZyBmb3IgY29tcG9uZW50cyBvZiBsb2dpbiB0byBlbnRlciBjcmVkZW50aWFscycpO1xuICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsICdpbnB1dFtwbGFjZWhvbGRlcj1cItep150g157Xqdeq157XqVwiXScsIHRydWUpLFxuICAgIHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCAnaW5wdXRbcGxhY2Vob2xkZXI9XCLXodeZ16HXnteUXCJdJywgdHJ1ZSksXG4gICAgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsICdidXR0b25bdHlwZT1cInN1Ym1pdFwiXScsIHRydWUpLFxuICBdKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd2FpdEZvclBvc3RMb2dpbihwYWdlOiBQYWdlKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsICdhW3RpdGxlPVwi15PXnNeSINec15fXqdeR15XXn1wiXScsIHRydWUsIDYwMDAwKSxcbiAgICB3YWl0VW50aWxFbGVtZW50Rm91bmQocGFnZSwgJ2Rpdi5tYWluLWNvbnRlbnQnLCBmYWxzZSwgNjAwMDApLFxuICAgIHBhZ2Uud2FpdEZvclNlbGVjdG9yKGB4cGF0aC8vZGl2W2NvbnRhaW5zKHN0cmluZygpLFwiJHtJTlZBTElEX1BBU1NXT1JEX01TR31cIildYCksXG4gICAgd2FpdFVudGlsRWxlbWVudEZvdW5kKHBhZ2UsICdmb3JtW2FjdGlvbj1cIi9jaGFuZ2VwYXNzd29yZFwiXScsIHRydWUsIDYwMDAwKSwgLy8gbm90IHN1cmUgaWYgdGhleSBrZXB0IHRoaXMgb25lXG4gIF0pO1xufVxuXG50eXBlIFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzID0geyB1c2VybmFtZTogc3RyaW5nOyBwYXNzd29yZDogc3RyaW5nIH07XG5cbmNsYXNzIExldW1pU2NyYXBlciBleHRlbmRzIEJhc2VTY3JhcGVyV2l0aEJyb3dzZXI8U2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHM+IHtcbiAgZ2V0TG9naW5PcHRpb25zKGNyZWRlbnRpYWxzOiBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscykge1xuICAgIHJldHVybiB7XG4gICAgICBsb2dpblVybDogTE9HSU5fVVJMLFxuICAgICAgZmllbGRzOiBjcmVhdGVMb2dpbkZpZWxkcyhjcmVkZW50aWFscyksXG4gICAgICBzdWJtaXRCdXR0b25TZWxlY3RvcjogXCJidXR0b25bdHlwZT0nc3VibWl0J11cIixcbiAgICAgIGNoZWNrUmVhZGluZXNzOiBhc3luYyAoKSA9PiBuYXZpZ2F0ZVRvTG9naW4odGhpcy5wYWdlKSxcbiAgICAgIHBvc3RBY3Rpb246IGFzeW5jICgpID0+IHdhaXRGb3JQb3N0TG9naW4odGhpcy5wYWdlKSxcbiAgICAgIHBvc3NpYmxlUmVzdWx0czogZ2V0UG9zc2libGVMb2dpblJlc3VsdHMoKSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZmV0Y2hEYXRhKCk6IFByb21pc2U8U2NyYXBlclNjcmFwaW5nUmVzdWx0PiB7XG4gICAgY29uc3QgbWluaW11bVN0YXJ0TW9tZW50ID0gbW9tZW50KCkuc3VidHJhY3QoMywgJ3llYXJzJykuYWRkKDEsICdkYXknKTtcbiAgICBjb25zdCBkZWZhdWx0U3RhcnRNb21lbnQgPSBtb21lbnQoKS5zdWJ0cmFjdCgxLCAneWVhcnMnKS5hZGQoMSwgJ2RheScpO1xuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IHRoaXMub3B0aW9ucy5zdGFydERhdGUgfHwgZGVmYXVsdFN0YXJ0TW9tZW50LnRvRGF0ZSgpO1xuICAgIGNvbnN0IHN0YXJ0TW9tZW50ID0gbW9tZW50Lm1heChtaW5pbXVtU3RhcnRNb21lbnQsIG1vbWVudChzdGFydERhdGUpKTtcblxuICAgIGF3YWl0IHRoaXMubmF2aWdhdGVUbyhUUkFOU0FDVElPTlNfVVJMKTtcblxuICAgIGNvbnN0IGFjY291bnRzID0gYXdhaXQgZmV0Y2hUcmFuc2FjdGlvbnModGhpcy5wYWdlLCBzdGFydE1vbWVudCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgIGFjY291bnRzLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTGV1bWlTY3JhcGVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFBQSxPQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBQyxVQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxNQUFBLEdBQUFGLE9BQUE7QUFDQSxJQUFBRyxxQkFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksV0FBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssYUFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sdUJBQUEsR0FBQU4sT0FBQTtBQUFzRyxTQUFBRCx1QkFBQVEsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUd0RyxNQUFNRyxLQUFLLEdBQUcsSUFBQUMsZUFBUSxFQUFDLE9BQU8sQ0FBQztBQUMvQixNQUFNQyxRQUFRLEdBQUcsNkJBQTZCO0FBQzlDLE1BQU1DLFNBQVMsR0FBRywwQkFBMEI7QUFDNUMsTUFBTUMsZ0JBQWdCLEdBQUcsR0FBR0YsUUFBUSwwREFBMEQ7QUFDOUYsTUFBTUcseUJBQXlCLEdBQUcsR0FB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