UNPKG

israeli-bank-scrapers-core

Version:

Provide scrapers for all major Israeli banks and credit card companies

198 lines (195 loc) 32.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _moment = _interopRequireDefault(require("moment")); var _uuid = require("uuid"); var _debug = require("../helpers/debug"); var _fetch = require("../helpers/fetch"); var _navigation = require("../helpers/navigation"); var _waiting = require("../helpers/waiting"); 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)('hapoalim'); const DATE_FORMAT = 'YYYYMMDD'; // eslint-disable-next-line @typescript-eslint/no-namespace function convertTransactions(txns) { return txns.map(txn => { const isOutbound = txn.eventActivityTypeCode === 2; let memo = ''; if (txn.beneficiaryDetailsData) { const { partyHeadline, partyName, messageHeadline, messageDetail } = txn.beneficiaryDetailsData; const memoLines = []; if (partyHeadline) { memoLines.push(partyHeadline); } if (partyName) { memoLines.push(`${partyName}.`); } if (messageHeadline) { memoLines.push(messageHeadline); } if (messageDetail) { memoLines.push(`${messageDetail}.`); } if (memoLines.length) { memo = memoLines.join(' '); } } const result = { type: _transactions.TransactionTypes.Normal, identifier: txn.referenceNumber, date: (0, _moment.default)(txn.eventDate, DATE_FORMAT).toISOString(), processedDate: (0, _moment.default)(txn.valueDate, DATE_FORMAT).toISOString(), originalAmount: isOutbound ? -txn.eventAmount : txn.eventAmount, originalCurrency: 'ILS', chargedAmount: isOutbound ? -txn.eventAmount : txn.eventAmount, description: txn.activityDescription || '', status: txn.serialNumber === 0 ? _transactions.TransactionStatuses.Pending : _transactions.TransactionStatuses.Completed, memo }; return result; }); } async function getRestContext(page) { await (0, _waiting.waitUntil)(() => { return page.evaluate(() => !!window.bnhpApp); }, 'waiting for app data load'); const result = await page.evaluate(() => { return window.bnhpApp.restContext; }); return result.slice(1); } async function fetchPoalimXSRFWithinPage(page, url, pageUuid) { const cookies = await page.cookies(); const XSRFCookie = cookies.find(cookie => cookie.name === 'XSRF-TOKEN'); const headers = {}; if (XSRFCookie != null) { headers['X-XSRF-TOKEN'] = XSRFCookie.value; } headers.pageUuid = pageUuid; headers.uuid = (0, _uuid.v4)(); headers['Content-Type'] = 'application/json;charset=UTF-8'; return (0, _fetch.fetchPostWithinPage)(page, url, [], headers); } async function getExtraScrap(txnsResult, baseUrl, page, accountNumber) { const promises = txnsResult.transactions.map(async transaction => { const { pfmDetails, serialNumber } = transaction; if (serialNumber !== 0) { const url = `${baseUrl}${pfmDetails}&accountId=${accountNumber}&lang=he`; const extraTransactionDetails = (await (0, _fetch.fetchGetWithinPage)(page, url)) || []; if (extraTransactionDetails && extraTransactionDetails.length) { const { transactionNumber } = extraTransactionDetails[0]; if (transactionNumber) { return { ...transaction, referenceNumber: transactionNumber }; } } } return transaction; }); const res = await Promise.all(promises); return { transactions: res }; } async function getAccountTransactions(baseUrl, apiSiteUrl, page, accountNumber, startDate, endDate, additionalTransactionInformation = false) { const txnsUrl = `${apiSiteUrl}/current-account/transactions?accountId=${accountNumber}&numItemsPerPage=1000&retrievalEndDate=${endDate}&retrievalStartDate=${startDate}&sortCode=1`; const txnsResult = await fetchPoalimXSRFWithinPage(page, txnsUrl, '/current-account/transactions'); const finalResult = additionalTransactionInformation && txnsResult?.transactions.length ? await getExtraScrap(txnsResult, baseUrl, page, accountNumber) : txnsResult; return convertTransactions(finalResult?.transactions ?? []); } async function getAccountBalance(apiSiteUrl, page, accountNumber) { const balanceAndCreditLimitUrl = `${apiSiteUrl}/current-account/composite/balanceAndCreditLimit?accountId=${accountNumber}&view=details&lang=he`; const balanceAndCreditLimit = await (0, _fetch.fetchGetWithinPage)(page, balanceAndCreditLimitUrl); return balanceAndCreditLimit?.currentBalance; } async function fetchAccountData(page, baseUrl, options) { const restContext = await getRestContext(page); const apiSiteUrl = `${baseUrl}/${restContext}`; const accountDataUrl = `${baseUrl}/ServerServices/general/accounts`; debug('fetching accounts data'); const accountsInfo = (await (0, _fetch.fetchGetWithinPage)(page, accountDataUrl)) || []; debug('got %d accounts, fetching txns and balance', accountsInfo.length); const defaultStartMoment = (0, _moment.default)().subtract(1, 'years').add(1, 'day'); const startDate = options.startDate || defaultStartMoment.toDate(); const startMoment = _moment.default.max(defaultStartMoment, (0, _moment.default)(startDate)); const { additionalTransactionInformation } = options; const startDateStr = startMoment.format(DATE_FORMAT); const endDateStr = (0, _moment.default)().format(DATE_FORMAT); const accounts = []; for (const account of accountsInfo) { let balance; const accountNumber = `${account.bankNumber}-${account.branchNumber}-${account.accountNumber}`; const isActiveAccount = account.accountClosingReasonCode === 0; if (isActiveAccount) { balance = await getAccountBalance(apiSiteUrl, page, accountNumber); } else { debug('Skipping balance for a closed account, balance will be undefined'); } const txns = await getAccountTransactions(baseUrl, apiSiteUrl, page, accountNumber, startDateStr, endDateStr, additionalTransactionInformation); accounts.push({ accountNumber, balance, txns }); } const accountData = { success: true, accounts }; debug('fetching ended'); return accountData; } function getPossibleLoginResults(baseUrl) { const urls = {}; urls[_baseScraperWithBrowser.LoginResults.Success] = [`${baseUrl}/portalserver/HomePage`, `${baseUrl}/ng-portals-bt/rb/he/homepage`, `${baseUrl}/ng-portals/rb/he/homepage`]; urls[_baseScraperWithBrowser.LoginResults.InvalidPassword] = [`${baseUrl}/AUTHENTICATE/LOGON?flow=AUTHENTICATE&state=LOGON&errorcode=1.6&callme=false`]; urls[_baseScraperWithBrowser.LoginResults.ChangePassword] = [`${baseUrl}/MCP/START?flow=MCP&state=START&expiredDate=null`, /\/ABOUTTOEXPIRE\/START/i]; return urls; } function createLoginFields(credentials) { return [{ selector: '#userCode', value: credentials.userCode }, { selector: '#password', value: credentials.password }]; } class HapoalimScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser { // eslint-disable-next-line class-methods-use-this get baseUrl() { return 'https://login.bankhapoalim.co.il'; } getLoginOptions(credentials) { return { loginUrl: `${this.baseUrl}/cgi-bin/poalwwwc?reqName=getLogonPage`, fields: createLoginFields(credentials), submitButtonSelector: '.login-btn', postAction: async () => (0, _navigation.waitForRedirect)(this.page), possibleResults: getPossibleLoginResults(this.baseUrl) }; } async fetchData() { return fetchAccountData(this.page, this.baseUrl, this.options); } } var _default = exports.default = HapoalimScraper; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfdXVpZCIsIl9kZWJ1ZyIsIl9mZXRjaCIsIl9uYXZpZ2F0aW9uIiwiX3dhaXRpbmciLCJfdHJhbnNhY3Rpb25zIiwiX2Jhc2VTY3JhcGVyV2l0aEJyb3dzZXIiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJkZWJ1ZyIsImdldERlYnVnIiwiREFURV9GT1JNQVQiLCJjb252ZXJ0VHJhbnNhY3Rpb25zIiwidHhucyIsIm1hcCIsInR4biIsImlzT3V0Ym91bmQiLCJldmVudEFjdGl2aXR5VHlwZUNvZGUiLCJtZW1vIiwiYmVuZWZpY2lhcnlEZXRhaWxzRGF0YSIsInBhcnR5SGVhZGxpbmUiLCJwYXJ0eU5hbWUiLCJtZXNzYWdlSGVhZGxpbmUiLCJtZXNzYWdlRGV0YWlsIiwibWVtb0xpbmVzIiwicHVzaCIsImxlbmd0aCIsImpvaW4iLCJyZXN1bHQiLCJ0eXBlIiwiVHJhbnNhY3Rpb25UeXBlcyIsIk5vcm1hbCIsImlkZW50aWZpZXIiLCJyZWZlcmVuY2VOdW1iZXIiLCJkYXRlIiwibW9tZW50IiwiZXZlbnREYXRlIiwidG9JU09TdHJpbmciLCJwcm9jZXNzZWREYXRlIiwidmFsdWVEYXRlIiwib3JpZ2luYWxBbW91bnQiLCJldmVudEFtb3VudCIsIm9yaWdpbmFsQ3VycmVuY3kiLCJjaGFyZ2VkQW1vdW50IiwiZGVzY3JpcHRpb24iLCJhY3Rpdml0eURlc2NyaXB0aW9uIiwic3RhdHVzIiwic2VyaWFsTnVtYmVyIiwiVHJhbnNhY3Rpb25TdGF0dXNlcyIsIlBlbmRpbmciLCJDb21wbGV0ZWQiLCJnZXRSZXN0Q29udGV4dCIsInBhZ2UiLCJ3YWl0VW50aWwiLCJldmFsdWF0ZSIsIndpbmRvdyIsImJuaHBBcHAiLCJyZXN0Q29udGV4dCIsInNsaWNlIiwiZmV0Y2hQb2FsaW1YU1JGV2l0aGluUGFnZSIsInVybCIsInBhZ2VVdWlkIiwiY29va2llcyIsIlhTUkZDb29raWUiLCJmaW5kIiwiY29va2llIiwibmFtZSIsImhlYWRlcnMiLCJ2YWx1ZSIsInV1aWQiLCJ1dWlkNCIsImZldGNoUG9zdFdpdGhpblBhZ2UiLCJnZXRFeHRyYVNjcmFwIiwidHhuc1Jlc3VsdCIsImJhc2VVcmwiLCJhY2NvdW50TnVtYmVyIiwicHJvbWlzZXMiLCJ0cmFuc2FjdGlvbnMiLCJ0cmFuc2FjdGlvbiIsInBmbURldGFpbHMiLCJleHRyYVRyYW5zYWN0aW9uRGV0YWlscyIsImZldGNoR2V0V2l0aGluUGFnZSIsInRyYW5zYWN0aW9uTnVtYmVyIiwicmVzIiwiUHJvbWlzZSIsImFsbCIsImdldEFjY291bnRUcmFuc2FjdGlvbnMiLCJhcGlTaXRlVXJsIiwic3RhcnREYXRlIiwiZW5kRGF0ZSIsImFkZGl0aW9uYWxUcmFuc2FjdGlvbkluZm9ybWF0aW9uIiwidHhuc1VybCIsImZpbmFsUmVzdWx0IiwiZ2V0QWNjb3VudEJhbGFuY2UiLCJiYWxhbmNlQW5kQ3JlZGl0TGltaXRVcmwiLCJiYWxhbmNlQW5kQ3JlZGl0TGltaXQiLCJjdXJyZW50QmFsYW5jZSIsImZldGNoQWNjb3VudERhdGEiLCJvcHRpb25zIiwiYWNjb3VudERhdGFVcmwiLCJhY2NvdW50c0luZm8iLCJkZWZhdWx0U3RhcnRNb21lbnQiLCJzdWJ0cmFjdCIsImFkZCIsInRvRGF0ZSIsInN0YXJ0TW9tZW50IiwibWF4Iiwic3RhcnREYXRlU3RyIiwiZm9ybWF0IiwiZW5kRGF0ZVN0ciIsImFjY291bnRzIiwiYWNjb3VudCIsImJhbGFuY2UiLCJiYW5rTnVtYmVyIiwiYnJhbmNoTnVtYmVyIiwiaXNBY3RpdmVBY2NvdW50IiwiYWNjb3VudENsb3NpbmdSZWFzb25Db2RlIiwiYWNjb3VudERhdGEiLCJzdWNjZXNzIiwiZ2V0UG9zc2libGVMb2dpblJlc3VsdHMiLCJ1cmxzIiwiTG9naW5SZXN1bHRzIiwiU3VjY2VzcyIsIkludmFsaWRQYXNzd29yZCIsIkNoYW5nZVBhc3N3b3JkIiwiY3JlYXRlTG9naW5GaWVsZHMiLCJjcmVkZW50aWFscyIsInNlbGVjdG9yIiwidXNlckNvZGUiLCJwYXNzd29yZCIsIkhhcG9hbGltU2NyYXBlciIsIkJhc2VTY3JhcGVyV2l0aEJyb3dzZXIiLCJnZXRMb2dpbk9wdGlvbnMiLCJsb2dpblVybCIsImZpZWxkcyIsInN1Ym1pdEJ1dHRvblNlbGVjdG9yIiwicG9zdEFjdGlvbiIsIndhaXRGb3JSZWRpcmVjdCIsInBvc3NpYmxlUmVzdWx0cyIsImZldGNoRGF0YSIsIl9kZWZhdWx0IiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zY3JhcGVycy9oYXBvYWxpbS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQgeyB0eXBlIFBhZ2UgfSBmcm9tICdwdXBwZXRlZXItY29yZSc7XG5pbXBvcnQgeyB2NCBhcyB1dWlkNCB9IGZyb20gJ3V1aWQnO1xuaW1wb3J0IHsgZ2V0RGVidWcgfSBmcm9tICcuLi9oZWxwZXJzL2RlYnVnJztcbmltcG9ydCB7IGZldGNoR2V0V2l0aGluUGFnZSwgZmV0Y2hQb3N0V2l0aGluUGFnZSB9IGZyb20gJy4uL2hlbHBlcnMvZmV0Y2gnO1xuaW1wb3J0IHsgd2FpdEZvclJlZGlyZWN0IH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IHdhaXRVbnRpbCB9IGZyb20gJy4uL2hlbHBlcnMvd2FpdGluZyc7XG5pbXBvcnQgeyB0eXBlIFRyYW5zYWN0aW9uLCBUcmFuc2FjdGlvblN0YXR1c2VzLCBUcmFuc2FjdGlvblR5cGVzLCB0eXBlIFRyYW5zYWN0aW9uc0FjY291bnQgfSBmcm9tICcuLi90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgQmFzZVNjcmFwZXJXaXRoQnJvd3NlciwgTG9naW5SZXN1bHRzLCB0eXBlIFBvc3NpYmxlTG9naW5SZXN1bHRzIH0gZnJvbSAnLi9iYXNlLXNjcmFwZXItd2l0aC1icm93c2VyJztcbmltcG9ydCB7IHR5cGUgU2NyYXBlck9wdGlvbnMgfSBmcm9tICcuL2ludGVyZmFjZSc7XG5cbmNvbnN0IGRlYnVnID0gZ2V0RGVidWcoJ2hhcG9hbGltJyk7XG5cbmNvbnN0IERBVEVfRk9STUFUID0gJ1lZWVlNTUREJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1uYW1lc3BhY2VcbmRlY2xhcmUgbmFtZXNwYWNlIHdpbmRvdyB7XG4gIGNvbnN0IGJuaHBBcHA6IGFueTtcbn1cblxuaW50ZXJmYWNlIFNjcmFwZWRUcmFuc2FjdGlvbiB7XG4gIHNlcmlhbE51bWJlcj86IG51bWJlcjtcbiAgYWN0aXZpdHlEZXNjcmlwdGlvbj86IHN0cmluZztcbiAgZXZlbnRBbW91bnQ6IG51bWJlcjtcbiAgdmFsdWVEYXRlPzogc3RyaW5nO1xuICBldmVudERhdGU/OiBzdHJpbmc7XG4gIHJlZmVyZW5jZU51bWJlcj86IG51bWJlcjtcbiAgU2NyYXBlZFRyYW5zYWN0aW9uPzogc3RyaW5nO1xuICBldmVudEFjdGl2aXR5VHlwZUNvZGU6IG51bWJlcjtcbiAgY3VycmVudEJhbGFuY2U6IG51bWJlcjtcbiAgcGZtRGV0YWlsczogc3RyaW5nO1xuICBiZW5lZmljaWFyeURldGFpbHNEYXRhPzoge1xuICAgIHBhcnR5SGVhZGxpbmU/OiBzdHJpbmc7XG4gICAgcGFydHlOYW1lPzogc3RyaW5nO1xuICAgIG1lc3NhZ2VIZWFkbGluZT86IHN0cmluZztcbiAgICBtZXNzYWdlRGV0YWlsPzogc3RyaW5nO1xuICB9O1xufVxuXG5pbnRlcmZhY2UgU2NyYXBlZFBmbVRyYW5zYWN0aW9uIHtcbiAgdHJhbnNhY3Rpb25OdW1iZXI6IG51bWJlcjtcbn1cblxudHlwZSBGZXRjaGVkQWNjb3VudERhdGEgPSB7XG4gIGJhbmtOdW1iZXI6IHN0cmluZztcbiAgYWNjb3VudE51bWJlcjogc3RyaW5nO1xuICBicmFuY2hOdW1iZXI6IHN0cmluZztcbiAgYWNjb3VudENsb3NpbmdSZWFzb25Db2RlOiBudW1iZXI7XG59W107XG5cbnR5cGUgRmV0Y2hlZEFjY291bnRUcmFuc2FjdGlvbnNEYXRhID0ge1xuICB0cmFuc2FjdGlvbnM6IFNjcmFwZWRUcmFuc2FjdGlvbltdO1xufTtcblxudHlwZSBCYWxhbmNlQW5kQ3JlZGl0TGltaXQgPSB7XG4gIGNyZWRpdExpbWl0QW1vdW50OiBudW1iZXI7XG4gIGNyZWRpdExpbWl0RGVzY3JpcHRpb246IHN0cmluZztcbiAgY3JlZGl0TGltaXRVdGlsaXphdGlvbkFtb3VudDogbnVtYmVyO1xuICBjcmVkaXRMaW1pdFV0aWxpemF0aW9uRXhpc3RhbmNlQ29kZTogbnVtYmVyO1xuICBjcmVkaXRMaW1pdFV0aWxpemF0aW9uUGVyY2VudDogbnVtYmVyO1xuICBjdXJyZW50QWNjb3VudExpbWl0c0Ftb3VudDogbnVtYmVyO1xuICBjdXJyZW50QmFsYW5jZTogbnVtYmVyO1xuICB3aXRoZHJhd2FsQmFsYW5jZTogbnVtYmVyO1xufTtcblxuZnVuY3Rpb24gY29udmVydFRyYW5zYWN0aW9ucyh0eG5zOiBTY3JhcGVkVHJhbnNhY3Rpb25bXSk6IFRyYW5zYWN0aW9uW10ge1xuICByZXR1cm4gdHhucy5tYXAodHhuID0+IHtcbiAgICBjb25zdCBpc091dGJvdW5kID0gdHhuLmV2ZW50QWN0aXZpdHlUeXBlQ29kZSA9PT0gMjtcblxuICAgIGxldCBtZW1vID0gJyc7XG4gICAgaWYgKHR4bi5iZW5lZmljaWFyeURldGFpbHNEYXRhKSB7XG4gICAgICBjb25zdCB7IHBhcnR5SGVhZGxpbmUsIHBhcnR5TmFtZSwgbWVzc2FnZUhlYWRsaW5lLCBtZXNzYWdlRGV0YWlsIH0gPSB0eG4uYmVuZWZpY2lhcnlEZXRhaWxzRGF0YTtcbiAgICAgIGNvbnN0IG1lbW9MaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGlmIChwYXJ0eUhlYWRsaW5lKSB7XG4gICAgICAgIG1lbW9MaW5lcy5wdXNoKHBhcnR5SGVhZGxpbmUpO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFydHlOYW1lKSB7XG4gICAgICAgIG1lbW9MaW5lcy5wdXNoKGAke3BhcnR5TmFtZX0uYCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtZXNzYWdlSGVhZGxpbmUpIHtcbiAgICAgICAgbWVtb0xpbmVzLnB1c2gobWVzc2FnZUhlYWRsaW5lKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1lc3NhZ2VEZXRhaWwpIHtcbiAgICAgICAgbWVtb0xpbmVzLnB1c2goYCR7bWVzc2FnZURldGFpbH0uYCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtZW1vTGluZXMubGVuZ3RoKSB7XG4gICAgICAgIG1lbW8gPSBtZW1vTGluZXMuam9pbignICcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdDogVHJhbnNhY3Rpb24gPSB7XG4gICAgICB0eXBlOiBUcmFuc2FjdGlvblR5cGVzLk5vcm1hbCxcbiAgICAgIGlkZW50aWZpZXI6IHR4bi5yZWZlcmVuY2VOdW1iZXIsXG4gICAgICBkYXRlOiBtb21lbnQodHhuLmV2ZW50RGF0ZSwgREFURV9GT1JNQVQpLnRvSVNPU3RyaW5nKCksXG4gICAgICBwcm9jZXNzZWREYXRlOiBtb21lbnQodHhuLnZhbHVlRGF0ZSwgREFURV9GT1JNQVQpLnRvSVNPU3RyaW5nKCksXG4gICAgICBvcmlnaW5hbEFtb3VudDogaXNPdXRib3VuZCA/IC10eG4uZXZlbnRBbW91bnQgOiB0eG4uZXZlbnRBbW91bnQsXG4gICAgICBvcmlnaW5hbEN1cnJlbmN5OiAnSUxTJyxcbiAgICAgIGNoYXJnZWRBbW91bnQ6IGlzT3V0Ym91bmQgPyAtdHhuLmV2ZW50QW1vdW50IDogdHhuLmV2ZW50QW1vdW50LFxuICAgICAgZGVzY3JpcHRpb246IHR4bi5hY3Rpdml0eURlc2NyaXB0aW9uIHx8ICcnLFxuICAgICAgc3RhdHVzOiB0eG4uc2VyaWFsTnVtYmVyID09PSAwID8gVHJhbnNhY3Rpb25TdGF0dXNlcy5QZW5kaW5nIDogVHJhbnNhY3Rpb25TdGF0dXNlcy5Db21wbGV0ZWQsXG4gICAgICBtZW1vLFxuICAgIH07XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0UmVzdENvbnRleHQocGFnZTogUGFnZSkge1xuICBhd2FpdCB3YWl0VW50aWwoKCkgPT4ge1xuICAgIHJldHVybiBwYWdlLmV2YWx1YXRlKCgpID0+ICEhd2luZG93LmJuaHBBcHApO1xuICB9LCAnd2FpdGluZyBmb3IgYXBwIGRhdGEgbG9hZCcpO1xuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4ge1xuICAgIHJldHVybiB3aW5kb3cuYm5ocEFwcC5yZXN0Q29udGV4dDtcbiAgfSk7XG5cbiAgcmV0dXJuIHJlc3VsdC5zbGljZSgxKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hQb2FsaW1YU1JGV2l0aGluUGFnZShcbiAgcGFnZTogUGFnZSxcbiAgdXJsOiBzdHJpbmcsXG4gIHBhZ2VVdWlkOiBzdHJpbmcsXG4pOiBQcm9taXNlPEZldGNoZWRBY2NvdW50VHJhbnNhY3Rpb25zRGF0YSB8IG51bGw+IHtcbiAgY29uc3QgY29va2llcyA9IGF3YWl0IHBhZ2UuY29va2llcygpO1xuICBjb25zdCBYU1JGQ29va2llID0gY29va2llcy5maW5kKGNvb2tpZSA9PiBjb29raWUubmFtZSA9PT0gJ1hTUkYtVE9LRU4nKTtcbiAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICBpZiAoWFNSRkNvb2tpZSAhPSBudWxsKSB7XG4gICAgaGVhZGVyc1snWC1YU1JGLVRPS0VOJ10gPSBYU1JGQ29va2llLnZhbHVlO1xuICB9XG4gIGhlYWRlcnMucGFnZVV1aWQgPSBwYWdlVXVpZDtcbiAgaGVhZGVycy51dWlkID0gdXVpZDQoKTtcbiAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gPSAnYXBwbGljYXRpb24vanNvbjtjaGFyc2V0PVVURi04JztcbiAgcmV0dXJuIGZldGNoUG9zdFdpdGhpblBhZ2U8RmV0Y2hlZEFjY291bnRUcmFuc2FjdGlvbnNEYXRhPihwYWdlLCB1cmwsIFtdLCBoZWFkZXJzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0RXh0cmFTY3JhcChcbiAgdHhuc1Jlc3VsdDogRmV0Y2hlZEFjY291bnRUcmFuc2FjdGlvbnNEYXRhLFxuICBiYXNlVXJsOiBzdHJpbmcsXG4gIHBhZ2U6IFBhZ2UsXG4gIGFjY291bnROdW1iZXI6IHN0cmluZyxcbik6IFByb21pc2U8RmV0Y2hlZEFjY291bnRUcmFuc2FjdGlvbnNEYXRhPiB7XG4gIGNvbnN0IHByb21pc2VzID0gdHhuc1Jlc3VsdC50cmFuc2FjdGlvbnMubWFwKGFzeW5jICh0cmFuc2FjdGlvbjogU2NyYXBlZFRyYW5zYWN0aW9uKTogUHJvbWlzZTxTY3JhcGVkVHJhbnNhY3Rpb24+ID0+IHtcbiAgICBjb25zdCB7IHBmbURldGFpbHMsIHNlcmlhbE51bWJlciB9ID0gdHJhbnNhY3Rpb247XG4gICAgaWYgKHNlcmlhbE51bWJlciAhPT0gMCkge1xuICAgICAgY29uc3QgdXJsID0gYCR7YmFzZVVybH0ke3BmbURldGFpbHN9JmFjY291bnRJZD0ke2FjY291bnROdW1iZXJ9Jmxhbmc9aGVgO1xuICAgICAgY29uc3QgZXh0cmFUcmFuc2FjdGlvbkRldGFpbHMgPSAoYXdhaXQgZmV0Y2hHZXRXaXRoaW5QYWdlPFNjcmFwZWRQZm1UcmFuc2FjdGlvbltdPihwYWdlLCB1cmwpKSB8fCBbXTtcbiAgICAgIGlmIChleHRyYVRyYW5zYWN0aW9uRGV0YWlscyAmJiBleHRyYVRyYW5zYWN0aW9uRGV0YWlscy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgeyB0cmFuc2FjdGlvbk51bWJlciB9ID0gZXh0cmFUcmFuc2FjdGlvbkRldGFpbHNbMF07XG4gICAgICAgIGlmICh0cmFuc2FjdGlvbk51bWJlcikge1xuICAgICAgICAgIHJldHVybiB7IC4uLnRyYW5zYWN0aW9uLCByZWZlcmVuY2VOdW1iZXI6IHRyYW5zYWN0aW9uTnVtYmVyIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uO1xuICB9KTtcbiAgY29uc3QgcmVzID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICByZXR1cm4geyB0cmFuc2FjdGlvbnM6IHJlcyB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRBY2NvdW50VHJhbnNhY3Rpb25zKFxuICBiYXNlVXJsOiBzdHJpbmcsXG4gIGFwaVNpdGVVcmw6IHN0cmluZyxcbiAgcGFnZTogUGFnZSxcbiAgYWNjb3VudE51bWJlcjogc3RyaW5nLFxuICBzdGFydERhdGU6IHN0cmluZyxcbiAgZW5kRGF0ZTogc3RyaW5nLFxuICBhZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbiA9IGZhbHNlLFxuKSB7XG4gIGNvbnN0IHR4bnNVcmwgPSBgJHthcGlTaXRlVXJsfS9jdXJyZW50LWFjY291bnQvdHJhbnNhY3Rpb25zP2FjY291bnRJZD0ke2FjY291bnROdW1iZXJ9Jm51bUl0ZW1zUGVyUGFnZT0xMDAwJnJldHJpZXZhbEVuZERhdGU9JHtlbmREYXRlfSZyZXRyaWV2YWxTdGFydERhdGU9JHtzdGFydERhdGV9JnNvcnRDb2RlPTFgO1xuICBjb25zdCB0eG5zUmVzdWx0ID0gYXdhaXQgZmV0Y2hQb2FsaW1YU1JGV2l0aGluUGFnZShwYWdlLCB0eG5zVXJsLCAnL2N1cnJlbnQtYWNjb3VudC90cmFuc2FjdGlvbnMnKTtcblxuICBjb25zdCBmaW5hbFJlc3VsdCA9XG4gICAgYWRkaXRpb25hbFRyYW5zYWN0aW9uSW5mb3JtYXRpb24gJiYgdHhuc1Jlc3VsdD8udHJhbnNhY3Rpb25zLmxlbmd0aFxuICAgICAgPyBhd2FpdCBnZXRFeHRyYVNjcmFwKHR4bnNSZXN1bHQsIGJhc2VVcmwsIHBhZ2UsIGFjY291bnROdW1iZXIpXG4gICAgICA6IHR4bnNSZXN1bHQ7XG5cbiAgcmV0dXJuIGNvbnZlcnRUcmFuc2FjdGlvbnMoZmluYWxSZXN1bHQ/LnRyYW5zYWN0aW9ucyA/PyBbXSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEFjY291bnRCYWxhbmNlKGFwaVNpdGVVcmw6IHN0cmluZywgcGFnZTogUGFnZSwgYWNjb3VudE51bWJlcjogc3RyaW5nKSB7XG4gIGNvbnN0IGJhbGFuY2VBbmRDcmVkaXRMaW1pdFVybCA9IGAke2FwaVNpdGVVcmx9L2N1cnJlbnQtYWNjb3VudC9jb21wb3NpdGUvYmFsYW5jZUFuZENyZWRpdExpbWl0P2FjY291bnRJZD0ke2FjY291bnROdW1iZXJ9JnZpZXc9ZGV0YWlscyZsYW5nPWhlYDtcbiAgY29uc3QgYmFsYW5jZUFuZENyZWRpdExpbWl0ID0gYXdhaXQgZmV0Y2hHZXRXaXRoaW5QYWdlPEJhbGFuY2VBbmRDcmVkaXRMaW1pdD4ocGFnZSwgYmFsYW5jZUFuZENyZWRpdExpbWl0VXJsKTtcblxuICByZXR1cm4gYmFsYW5jZUFuZENyZWRpdExpbWl0Py5jdXJyZW50QmFsYW5jZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hBY2NvdW50RGF0YShwYWdlOiBQYWdlLCBiYXNlVXJsOiBzdHJpbmcsIG9wdGlvbnM6IFNjcmFwZXJPcHRpb25zKSB7XG4gIGNvbnN0IHJlc3RDb250ZXh0ID0gYXdhaXQgZ2V0UmVzdENvbnRleHQocGFnZSk7XG4gIGNvbnN0IGFwaVNpdGVVcmwgPSBgJHtiYXNlVXJsfS8ke3Jlc3RDb250ZXh0fWA7XG4gIGNvbnN0IGFjY291bnREYXRhVXJsID0gYCR7YmFzZVVybH0vU2VydmVyU2VydmljZXMvZ2VuZXJhbC9hY2NvdW50c2A7XG5cbiAgZGVidWcoJ2ZldGNoaW5nIGFjY291bnRzIGRhdGEnKTtcbiAgY29uc3QgYWNjb3VudHNJbmZvID0gKGF3YWl0IGZldGNoR2V0V2l0aGluUGFnZTxGZXRjaGVkQWNjb3VudERhdGE+KHBhZ2UsIGFjY291bnREYXRhVXJsKSkgfHwgW107XG4gIGRlYnVnKCdnb3QgJWQgYWNjb3VudHMsIGZldGNoaW5nIHR4bnMgYW5kIGJhbGFuY2UnLCBhY2NvdW50c0luZm8ubGVuZ3RoKTtcblxuICBjb25zdCBkZWZhdWx0U3RhcnRNb21lbnQgPSBtb21lbnQoKS5zdWJ0cmFjdCgxLCAneWVhcnMnKS5hZGQoMSwgJ2RheScpO1xuICBjb25zdCBzdGFydERhdGUgPSBvcHRpb25zLnN0YXJ0RGF0ZSB8fCBkZWZhdWx0U3RhcnRNb21lbnQudG9EYXRlKCk7XG4gIGNvbnN0IHN0YXJ0TW9tZW50ID0gbW9tZW50Lm1heChkZWZhdWx0U3RhcnRNb21lbnQsIG1vbWVudChzdGFydERhdGUpKTtcbiAgY29uc3QgeyBhZGRpdGlvbmFsVHJhbnNhY3Rpb25JbmZvcm1hdGlvbiB9ID0gb3B0aW9ucztcblxuICBjb25zdCBzdGFydERhdGVTdHIgPSBzdGFydE1vbWVudC5mb3JtYXQoREFURV9GT1JNQVQpO1xuICBjb25zdCBlbmREYXRlU3RyID0gbW9tZW50KCkuZm9ybWF0KERBVEVfRk9STUFUKTtcblxuICBjb25zdCBhY2NvdW50czogVHJhbnNhY3Rpb25zQWNjb3VudFtdID0gW107XG5cbiAgZm9yIChjb25zdCBhY2NvdW50IG9mIGFjY291bnRzSW5mbykge1xuICAgIGxldCBiYWxhbmNlOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWNjb3VudE51bWJlciA9IGAke2FjY291bnQuYmFua051bWJlcn0tJHthY2NvdW50LmJyYW5jaE51bWJlcn0tJHthY2NvdW50LmFjY291bnROdW1iZXJ9YDtcblxuICAgIGNvbnN0IGlzQWN0aXZlQWNjb3VudCA9IGFjY291bnQuYWNjb3VudENsb3NpbmdSZWFzb25Db2RlID09PSAwO1xuICAgIGlmIChpc0FjdGl2ZUFjY291bnQpIHtcbiAgICAgIGJhbGFuY2UgPSBhd2FpdCBnZXRBY2NvdW50QmFsYW5jZShhcGlTaXRlVXJsLCBwYWdlLCBhY2NvdW50TnVtYmVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoJ1NraXBwaW5nIGJhbGFuY2UgZm9yIGEgY2xvc2VkIGFjY291bnQsIGJhbGFuY2Ugd2lsbCBiZSB1bmRlZmluZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCB0eG5zID0gYXdhaXQgZ2V0QWNjb3VudFRyYW5zYWN0aW9ucyhcbiAgICAgIGJhc2VVcmwsXG4gICAgICBhcGlTaXRlVXJsLFxuICAgICAgcGFnZSxcbiAgICAgIGFjY291bnROdW1iZXIsXG4gICAgICBzdGFydERhdGVTdHIsXG4gICAgICBlbmREYXRlU3RyLFxuICAgICAgYWRkaXRpb25hbFRyYW5zYWN0aW9uSW5mb3JtYXRpb24sXG4gICAgKTtcblxuICAgIGFjY291bnRzLnB1c2goe1xuICAgICAgYWNjb3VudE51bWJlcixcbiAgICAgIGJhbGFuY2UsXG4gICAgICB0eG5zLFxuICAgIH0pO1xuICB9XG5cbiAgY29uc3QgYWNjb3VudERhdGEgPSB7XG4gICAgc3VjY2VzczogdHJ1ZSxcbiAgICBhY2NvdW50cyxcbiAgfTtcbiAgZGVidWcoJ2ZldGNoaW5nIGVuZGVkJyk7XG4gIHJldHVybiBhY2NvdW50RGF0YTtcbn1cblxuZnVuY3Rpb24gZ2V0UG9zc2libGVMb2dpblJlc3VsdHMoYmFzZVVybDogc3RyaW5nKSB7XG4gIGNvbnN0IHVybHM6IFBvc3NpYmxlTG9naW5SZXN1bHRzID0ge307XG4gIHVybHNbTG9naW5SZXN1bHRzLlN1Y2Nlc3NdID0gW1xuICAgIGAke2Jhc2VVcmx9L3BvcnRhbHNlcnZlci9Ib21lUGFnZWAsXG4gICAgYCR7YmFzZVVybH0vbmctcG9ydGFscy1idC9yYi9oZS9ob21lcGFnZWAsXG4gICAgYCR7YmFzZVVybH0vbmctcG9ydGFscy9yYi9oZS9ob21lcGFnZWAsXG4gIF07XG4gIHVybHNbTG9naW5SZXN1bHRzLkludmFsaWRQYXNzd29yZF0gPSBbXG4gICAgYCR7YmFzZVVybH0vQVVUSEVOVElDQVRFL0xPR09OP2Zsb3c9QVVUSEVOVElDQVRFJnN0YXRlPUxPR09OJmVycm9yY29kZT0xLjYmY2FsbG1lPWZhbHNlYCxcbiAgXTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuQ2hhbmdlUGFzc3dvcmRdID0gW1xuICAgIGAke2Jhc2VVcmx9L01DUC9TVEFSVD9mbG93PU1DUCZzdGF0ZT1TVEFSVCZleHBpcmVkRGF0ZT1udWxsYCxcbiAgICAvXFwvQUJPVVRUT0VYUElSRVxcL1NUQVJUL2ksXG4gIF07XG4gIHJldHVybiB1cmxzO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVMb2dpbkZpZWxkcyhjcmVkZW50aWFsczogU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMpIHtcbiAgcmV0dXJuIFtcbiAgICB7IHNlbGVjdG9yOiAnI3VzZXJDb2RlJywgdmFsdWU6IGNyZWRlbnRpYWxzLnVzZXJDb2RlIH0sXG4gICAgeyBzZWxlY3RvcjogJyNwYXNzd29yZCcsIHZhbHVlOiBjcmVkZW50aWFscy5wYXNzd29yZCB9LFxuICBdO1xufVxuXG50eXBlIFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzID0geyB1c2VyQ29kZTogc3RyaW5nOyBwYXNzd29yZDogc3RyaW5nIH07XG5cbmNsYXNzIEhhcG9hbGltU2NyYXBlciBleHRlbmRzIEJhc2VTY3JhcGVyV2l0aEJyb3dzZXI8U2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHM+IHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgZ2V0IGJhc2VVcmwoKSB7XG4gICAgcmV0dXJuICdodHRwczovL2xvZ2luLmJhbmtoYXBvYWxpbS5jby5pbCc7XG4gIH1cblxuICBnZXRMb2dpbk9wdGlvbnMoY3JlZGVudGlhbHM6IFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxvZ2luVXJsOiBgJHt0aGlzLmJhc2VVcmx9L2NnaS1iaW4vcG9hbHd3d2M/cmVxTmFtZT1nZXRMb2dvblBhZ2VgLFxuICAgICAgZmllbGRzOiBjcmVhdGVMb2dpbkZpZWxkcyhjcmVkZW50aWFscyksXG4gICAgICBzdWJtaXRCdXR0b25TZWxlY3RvcjogJy5sb2dpbi1idG4nLFxuICAgICAgcG9zdEFjdGlvbjogYXN5bmMgKCkgPT4gd2FpdEZvclJlZGlyZWN0KHRoaXMucGFnZSksXG4gICAgICBwb3NzaWJsZVJlc3VsdHM6IGdldFBvc3NpYmxlTG9naW5SZXN1bHRzKHRoaXMuYmFzZVVybCksXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGZldGNoRGF0YSgpIHtcbiAgICByZXR1cm4gZmV0Y2hBY2NvdW50RGF0YSh0aGlzLnBhZ2UsIHRoaXMuYmFzZVVybCwgdGhpcy5vcHRpb25zKTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBIYXBvYWxpbVNjcmFwZXI7XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFDLEtBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLE1BQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLE1BQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLFdBQUEsR0FBQUosT0FBQTtBQUNBLElBQUFLLFFBQUEsR0FBQUwsT0FBQTtBQUNBLElBQUFNLGFBQUEsR0FBQU4sT0FBQTtBQUNBLElBQUFPLHVCQUFBLEdBQUFQLE9BQUE7QUFBOEcsU0FBQUQsdUJBQUFTLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFHOUcsTUFBTUcsS0FBSyxHQUFHLElBQUFDLGVBQVEsRUFBQyxVQUFVLENBQUM7QUFFbEMsTUFBTUMsV0FBVyxHQUFHLFVBQVU7O0FBRTlCOztBQWtEQSxTQUFTQyxtQkFBbUJBLENBQUNDLElBQTBCLEVBQWlCO0VBQ3RFLE9BQU9BLElBQUksQ0FBQ0MsR0FBRyxDQUFDQyxHQUFHLElBQUk7SUFDckIsTUFBTUMsVUFBVSxHQUFHRCxHQUFHLENBQUNFLHFCQUFxQixLQUFLLENBQUM7SUFFbEQsSUFBSUMsSUFBSSxHQUFHLEVBQUU7SUFDYixJQUFJSCxHQUFHLENBQUNJLHNCQUFzQixFQUFFO01BQzlCLE1BQU07UUFBRUMsYUFBYTtRQUFFQyxTQUFTO1FBQUVDLGVBQWU7UUFBRUM7TUFBYyxDQUFDLEdBQUdSLEdBQUcsQ0FBQ0ksc0JBQXNCO01BQy9GLE1BQU1LLFNBQW1CLEdBQUcsRUFBRTtNQUM5QixJQUFJSixhQUFhLEVBQUU7UUFDakJJLFNBQVMsQ0FB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