UNPKG

israeli-bank-scrapers-core

Version:

Provide scrapers for all major Israeli banks and credit card companies

198 lines (195 loc) 33.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _moment = _interopRequireDefault(require("moment")); var _crypto = require("crypto"); 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"); var _transactions2 = require("../helpers/transactions"); 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, options) { 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 }; if (options?.includeRawTransaction) { result.rawTransaction = (0, _transactions2.getRawTransaction)(txn); } 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, _crypto.randomUUID)(); 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, additionalInformation: extraTransactionDetails }; } } } return transaction; }); const res = await Promise.all(promises); return { transactions: res }; } async function getAccountTransactions(baseUrl, apiSiteUrl, page, accountNumber, startDate, endDate, additionalTransactionInformation = false, options) { 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 ?? [], options); } 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)) || []; const openAccountsInfo = accountsInfo.filter(account => account.accountClosingReasonCode === 0); debug('got %d open accounts from %d total accounts, fetching txns and balance', openAccountsInfo.length, 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 openAccountsInfo) { debug('getting information for account %s', account.accountNumber); const accountNumber = `${account.bankNumber}-${account.branchNumber}-${account.accountNumber}`; const balance = await getAccountBalance(apiSiteUrl, page, accountNumber); const txns = await getAccountTransactions(baseUrl, apiSiteUrl, page, accountNumber, startDateStr, endDateStr, additionalTransactionInformation, options); 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 { 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,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY3J5cHRvIiwiX2RlYnVnIiwiX2ZldGNoIiwiX25hdmlnYXRpb24iLCJfd2FpdGluZyIsIl90cmFuc2FjdGlvbnMiLCJfYmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsIl90cmFuc2FjdGlvbnMyIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiZGVidWciLCJnZXREZWJ1ZyIsIkRBVEVfRk9STUFUIiwiY29udmVydFRyYW5zYWN0aW9ucyIsInR4bnMiLCJvcHRpb25zIiwibWFwIiwidHhuIiwiaXNPdXRib3VuZCIsImV2ZW50QWN0aXZpdHlUeXBlQ29kZSIsIm1lbW8iLCJiZW5lZmljaWFyeURldGFpbHNEYXRhIiwicGFydHlIZWFkbGluZSIsInBhcnR5TmFtZSIsIm1lc3NhZ2VIZWFkbGluZSIsIm1lc3NhZ2VEZXRhaWwiLCJtZW1vTGluZXMiLCJwdXNoIiwibGVuZ3RoIiwiam9pbiIsInJlc3VsdCIsInR5cGUiLCJUcmFuc2FjdGlvblR5cGVzIiwiTm9ybWFsIiwiaWRlbnRpZmllciIsInJlZmVyZW5jZU51bWJlciIsImRhdGUiLCJtb21lbnQiLCJldmVudERhdGUiLCJ0b0lTT1N0cmluZyIsInByb2Nlc3NlZERhdGUiLCJ2YWx1ZURhdGUiLCJvcmlnaW5hbEFtb3VudCIsImV2ZW50QW1vdW50Iiwib3JpZ2luYWxDdXJyZW5jeSIsImNoYXJnZWRBbW91bnQiLCJkZXNjcmlwdGlvbiIsImFjdGl2aXR5RGVzY3JpcHRpb24iLCJzdGF0dXMiLCJzZXJpYWxOdW1iZXIiLCJUcmFuc2FjdGlvblN0YXR1c2VzIiwiUGVuZGluZyIsIkNvbXBsZXRlZCIsImluY2x1ZGVSYXdUcmFuc2FjdGlvbiIsInJhd1RyYW5zYWN0aW9uIiwiZ2V0UmF3VHJhbnNhY3Rpb24iLCJnZXRSZXN0Q29udGV4dCIsInBhZ2UiLCJ3YWl0VW50aWwiLCJldmFsdWF0ZSIsIndpbmRvdyIsImJuaHBBcHAiLCJyZXN0Q29udGV4dCIsInNsaWNlIiwiZmV0Y2hQb2FsaW1YU1JGV2l0aGluUGFnZSIsInVybCIsInBhZ2VVdWlkIiwiY29va2llcyIsIlhTUkZDb29raWUiLCJmaW5kIiwiY29va2llIiwibmFtZSIsImhlYWRlcnMiLCJ2YWx1ZSIsInV1aWQiLCJyYW5kb21VVUlEIiwiZmV0Y2hQb3N0V2l0aGluUGFnZSIsImdldEV4dHJhU2NyYXAiLCJ0eG5zUmVzdWx0IiwiYmFzZVVybCIsImFjY291bnROdW1iZXIiLCJwcm9taXNlcyIsInRyYW5zYWN0aW9ucyIsInRyYW5zYWN0aW9uIiwicGZtRGV0YWlscyIsImV4dHJhVHJhbnNhY3Rpb25EZXRhaWxzIiwiZmV0Y2hHZXRXaXRoaW5QYWdlIiwidHJhbnNhY3Rpb25OdW1iZXIiLCJhZGRpdGlvbmFsSW5mb3JtYXRpb24iLCJyZXMiLCJQcm9taXNlIiwiYWxsIiwiZ2V0QWNjb3VudFRyYW5zYWN0aW9ucyIsImFwaVNpdGVVcmwiLCJzdGFydERhdGUiLCJlbmREYXRlIiwiYWRkaXRpb25hbFRyYW5zYWN0aW9uSW5mb3JtYXRpb24iLCJ0eG5zVXJsIiwiZmluYWxSZXN1bHQiLCJnZXRBY2NvdW50QmFsYW5jZSIsImJhbGFuY2VBbmRDcmVkaXRMaW1pdFVybCIsImJhbGFuY2VBbmRDcmVkaXRMaW1pdCIsImN1cnJlbnRCYWxhbmNlIiwiZmV0Y2hBY2NvdW50RGF0YSIsImFjY291bnREYXRhVXJsIiwiYWNjb3VudHNJbmZvIiwib3BlbkFjY291bnRzSW5mbyIsImZpbHRlciIsImFjY291bnQiLCJhY2NvdW50Q2xvc2luZ1JlYXNvbkNvZGUiLCJkZWZhdWx0U3RhcnRNb21lbnQiLCJzdWJ0cmFjdCIsImFkZCIsInRvRGF0ZSIsInN0YXJ0TW9tZW50IiwibWF4Iiwic3RhcnREYXRlU3RyIiwiZm9ybWF0IiwiZW5kRGF0ZVN0ciIsImFjY291bnRzIiwiYmFua051bWJlciIsImJyYW5jaE51bWJlciIsImJhbGFuY2UiLCJhY2NvdW50RGF0YSIsInN1Y2Nlc3MiLCJnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cyIsInVybHMiLCJMb2dpblJlc3VsdHMiLCJTdWNjZXNzIiwiSW52YWxpZFBhc3N3b3JkIiwiQ2hhbmdlUGFzc3dvcmQiLCJjcmVhdGVMb2dpbkZpZWxkcyIsImNyZWRlbnRpYWxzIiwic2VsZWN0b3IiLCJ1c2VyQ29kZSIsInBhc3N3b3JkIiwiSGFwb2FsaW1TY3JhcGVyIiwiQmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImdldExvZ2luT3B0aW9ucyIsImxvZ2luVXJsIiwiZmllbGRzIiwic3VibWl0QnV0dG9uU2VsZWN0b3IiLCJwb3N0QWN0aW9uIiwid2FpdEZvclJlZGlyZWN0IiwicG9zc2libGVSZXN1bHRzIiwiZmV0Y2hEYXRhIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmFwZXJzL2hhcG9hbGltLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IHR5cGUgUGFnZSB9IGZyb20gJ3B1cHBldGVlci1jb3JlJztcbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgZ2V0RGVidWcgfSBmcm9tICcuLi9oZWxwZXJzL2RlYnVnJztcbmltcG9ydCB7IGZldGNoR2V0V2l0aGluUGFnZSwgZmV0Y2hQb3N0V2l0aGluUGFnZSB9IGZyb20gJy4uL2hlbHBlcnMvZmV0Y2gnO1xuaW1wb3J0IHsgd2FpdEZvclJlZGlyZWN0IH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IHdhaXRVbnRpbCB9IGZyb20gJy4uL2hlbHBlcnMvd2FpdGluZyc7XG5pbXBvcnQgeyB0eXBlIFRyYW5zYWN0aW9uLCBUcmFuc2FjdGlvblN0YXR1c2VzLCBUcmFuc2FjdGlvblR5cGVzLCB0eXBlIFRyYW5zYWN0aW9uc0FjY291bnQgfSBmcm9tICcuLi90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgQmFzZVNjcmFwZXJXaXRoQnJvd3NlciwgTG9naW5SZXN1bHRzLCB0eXBlIFBvc3NpYmxlTG9naW5SZXN1bHRzIH0gZnJvbSAnLi9iYXNlLXNjcmFwZXItd2l0aC1icm93c2VyJztcbmltcG9ydCB7IHR5cGUgU2NyYXBlck9wdGlvbnMgfSBmcm9tICcuL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBnZXRSYXdUcmFuc2FjdGlvbiB9IGZyb20gJy4uL2hlbHBlcnMvdHJhbnNhY3Rpb25zJztcblxuY29uc3QgZGVidWcgPSBnZXREZWJ1ZygnaGFwb2FsaW0nKTtcblxuY29uc3QgREFURV9GT1JNQVQgPSAnWVlZWU1NREQnO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5hbWVzcGFjZVxuZGVjbGFyZSBuYW1lc3BhY2Ugd2luZG93IHtcbiAgY29uc3QgYm5ocEFwcDogYW55O1xufVxuXG5pbnRlcmZhY2UgU2NyYXBlZFRyYW5zYWN0aW9uIHtcbiAgc2VyaWFsTnVtYmVyPzogbnVtYmVyO1xuICBhY3Rpdml0eURlc2NyaXB0aW9uPzogc3RyaW5nO1xuICBldmVudEFtb3VudDogbnVtYmVyO1xuICB2YWx1ZURhdGU/OiBzdHJpbmc7XG4gIGV2ZW50RGF0ZT86IHN0cmluZztcbiAgcmVmZXJlbmNlTnVtYmVyPzogbnVtYmVyO1xuICBTY3JhcGVkVHJhbnNhY3Rpb24/OiBzdHJpbmc7XG4gIGV2ZW50QWN0aXZpdHlUeXBlQ29kZTogbnVtYmVyO1xuICBjdXJyZW50QmFsYW5jZTogbnVtYmVyO1xuICBwZm1EZXRhaWxzOiBzdHJpbmc7XG4gIGJlbmVmaWNpYXJ5RGV0YWlsc0RhdGE/OiB7XG4gICAgcGFydHlIZWFkbGluZT86IHN0cmluZztcbiAgICBwYXJ0eU5hbWU/OiBzdHJpbmc7XG4gICAgbWVzc2FnZUhlYWRsaW5lPzogc3RyaW5nO1xuICAgIG1lc3NhZ2VEZXRhaWw/OiBzdHJpbmc7XG4gIH07XG4gIGFkZGl0aW9uYWxJbmZvcm1hdGlvbj86IHVua25vd247XG59XG5cbmludGVyZmFjZSBTY3JhcGVkUGZtVHJhbnNhY3Rpb24ge1xuICB0cmFuc2FjdGlvbk51bWJlcjogbnVtYmVyO1xufVxuXG50eXBlIEZldGNoZWRBY2NvdW50RGF0YSA9IHtcbiAgYmFua051bWJlcjogc3RyaW5nO1xuICBhY2NvdW50TnVtYmVyOiBzdHJpbmc7XG4gIGJyYW5jaE51bWJlcjogc3RyaW5nO1xuICBhY2NvdW50Q2xvc2luZ1JlYXNvbkNvZGU6IG51bWJlcjtcbn1bXTtcblxudHlwZSBGZXRjaGVkQWNjb3VudFRyYW5zYWN0aW9uc0RhdGEgPSB7XG4gIHRyYW5zYWN0aW9uczogU2NyYXBlZFRyYW5zYWN0aW9uW107XG59O1xuXG50eXBlIEJhbGFuY2VBbmRDcmVkaXRMaW1pdCA9IHtcbiAgY3JlZGl0TGltaXRBbW91bnQ6IG51bWJlcjtcbiAgY3JlZGl0TGltaXREZXNjcmlwdGlvbjogc3RyaW5nO1xuICBjcmVkaXRMaW1pdFV0aWxpemF0aW9uQW1vdW50OiBudW1iZXI7XG4gIGNyZWRpdExpbWl0VXRpbGl6YXRpb25FeGlzdGFuY2VDb2RlOiBudW1iZXI7XG4gIGNyZWRpdExpbWl0VXRpbGl6YXRpb25QZXJjZW50OiBudW1iZXI7XG4gIGN1cnJlbnRBY2NvdW50TGltaXRzQW1vdW50OiBudW1iZXI7XG4gIGN1cnJlbnRCYWxhbmNlOiBudW1iZXI7XG4gIHdpdGhkcmF3YWxCYWxhbmNlOiBudW1iZXI7XG59O1xuXG5mdW5jdGlvbiBjb252ZXJ0VHJhbnNhY3Rpb25zKHR4bnM6IFNjcmFwZWRUcmFuc2FjdGlvbltdLCBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMpOiBUcmFuc2FjdGlvbltdIHtcbiAgcmV0dXJuIHR4bnMubWFwKHR4biA9PiB7XG4gICAgY29uc3QgaXNPdXRib3VuZCA9IHR4bi5ldmVudEFjdGl2aXR5VHlwZUNvZGUgPT09IDI7XG5cbiAgICBsZXQgbWVtbyA9ICcnO1xuICAgIGlmICh0eG4uYmVuZWZpY2lhcnlEZXRhaWxzRGF0YSkge1xuICAgICAgY29uc3QgeyBwYXJ0eUhlYWRsaW5lLCBwYXJ0eU5hbWUsIG1lc3NhZ2VIZWFkbGluZSwgbWVzc2FnZURldGFpbCB9ID0gdHhuLmJlbmVmaWNpYXJ5RGV0YWlsc0RhdGE7XG4gICAgICBjb25zdCBtZW1vTGluZXM6IHN0cmluZ1tdID0gW107XG4gICAgICBpZiAocGFydHlIZWFkbGluZSkge1xuICAgICAgICBtZW1vTGluZXMucHVzaChwYXJ0eUhlYWRsaW5lKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcnR5TmFtZSkge1xuICAgICAgICBtZW1vTGluZXMucHVzaChgJHtwYXJ0eU5hbWV9LmApO1xuICAgICAgfVxuXG4gICAgICBpZiAobWVzc2FnZUhlYWRsaW5lKSB7XG4gICAgICAgIG1lbW9MaW5lcy5wdXNoKG1lc3NhZ2VIZWFkbGluZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtZXNzYWdlRGV0YWlsKSB7XG4gICAgICAgIG1lbW9MaW5lcy5wdXNoKGAke21lc3NhZ2VEZXRhaWx9LmApO1xuICAgICAgfVxuXG4gICAgICBpZiAobWVtb0xpbmVzLmxlbmd0aCkge1xuICAgICAgICBtZW1vID0gbWVtb0xpbmVzLmpvaW4oJyAnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQ6IFRyYW5zYWN0aW9uID0ge1xuICAgICAgdHlwZTogVHJhbnNhY3Rpb25UeXBlcy5Ob3JtYWwsXG4gICAgICBpZGVudGlmaWVyOiB0eG4ucmVmZXJlbmNlTnVtYmVyLFxuICAgICAgZGF0ZTogbW9tZW50KHR4bi5ldmVudERhdGUsIERBVEVfRk9STUFUKS50b0lTT1N0cmluZygpLFxuICAgICAgcHJvY2Vzc2VkRGF0ZTogbW9tZW50KHR4bi52YWx1ZURhdGUsIERBVEVfRk9STUFUKS50b0lTT1N0cmluZygpLFxuICAgICAgb3JpZ2luYWxBbW91bnQ6IGlzT3V0Ym91bmQgPyAtdHhuLmV2ZW50QW1vdW50IDogdHhuLmV2ZW50QW1vdW50LFxuICAgICAgb3JpZ2luYWxDdXJyZW5jeTogJ0lMUycsXG4gICAgICBjaGFyZ2VkQW1vdW50OiBpc091dGJvdW5kID8gLXR4bi5ldmVudEFtb3VudCA6IHR4bi5ldmVudEFtb3VudCxcbiAgICAgIGRlc2NyaXB0aW9uOiB0eG4uYWN0aXZpdHlEZXNjcmlwdGlvbiB8fCAnJyxcbiAgICAgIHN0YXR1czogdHhuLnNlcmlhbE51bWJlciA9PT0gMCA/IFRyYW5zYWN0aW9uU3RhdHVzZXMuUGVuZGluZyA6IFRyYW5zYWN0aW9uU3RhdHVzZXMuQ29tcGxldGVkLFxuICAgICAgbWVtbyxcbiAgICB9O1xuXG4gICAgaWYgKG9wdGlvbnM/LmluY2x1ZGVSYXdUcmFuc2FjdGlvbikge1xuICAgICAgcmVzdWx0LnJhd1RyYW5zYWN0aW9uID0gZ2V0UmF3VHJhbnNhY3Rpb24odHhuKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0UmVzdENvbnRleHQocGFnZTogUGFnZSkge1xuICBhd2FpdCB3YWl0VW50aWwoKCkgPT4ge1xuICAgIHJldHVybiBwYWdlLmV2YWx1YXRlKCgpID0+ICEhd2luZG93LmJuaHBBcHApO1xuICB9LCAnd2FpdGluZyBmb3IgYXBwIGRhdGEgbG9hZCcpO1xuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHBhZ2UuZXZhbHVhdGUoKCkgPT4ge1xuICAgIHJldHVybiB3aW5kb3cuYm5ocEFwcC5yZXN0Q29udGV4dDtcbiAgfSk7XG5cbiAgcmV0dXJuIHJlc3VsdC5zbGljZSgxKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZmV0Y2hQb2FsaW1YU1JGV2l0aGluUGFnZShcbiAgcGFnZTogUGFnZSxcbiAgdXJsOiBzdHJpbmcsXG4gIHBhZ2VVdWlkOiBzdHJpbmcsXG4pOiBQcm9taXNlPEZldGNoZWRBY2NvdW50VHJhbnNhY3Rpb25zRGF0YSB8IG51bGw+IHtcbiAgY29uc3QgY29va2llcyA9IGF3YWl0IHBhZ2UuY29va2llcygpO1xuICBjb25zdCBYU1JGQ29va2llID0gY29va2llcy5maW5kKGNvb2tpZSA9PiBjb29raWUubmFtZSA9PT0gJ1hTUkYtVE9LRU4nKTtcbiAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9O1xuICBpZiAoWFNSRkNvb2tpZSAhPSBudWxsKSB7XG4gICAgaGVhZGVyc1snWC1YU1JGLVRPS0VOJ10gPSBYU1JGQ29va2llLnZhbHVlO1xuICB9XG4gIGhlYWRlcnMucGFnZVV1aWQgPSBwYWdlVXVpZDtcbiAgaGVhZGVycy51dWlkID0gcmFuZG9tVVVJRCgpO1xuICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9ICdhcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9VVRGLTgnO1xuICByZXR1cm4gZmV0Y2hQb3N0V2l0aGluUGFnZTxGZXRjaGVkQWNjb3VudFRyYW5zYWN0aW9uc0RhdGE+KHBhZ2UsIHVybCwgW10sIGhlYWRlcnMpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRFeHRyYVNjcmFwKFxuICB0eG5zUmVzdWx0OiBGZXRjaGVkQWNjb3VudFRyYW5zYWN0aW9uc0RhdGEsXG4gIGJhc2VVcmw6IHN0cmluZyxcbiAgcGFnZTogUGFnZSxcbiAgYWNjb3VudE51bWJlcjogc3RyaW5nLFxuKTogUHJvbWlzZTxGZXRjaGVkQWNjb3VudFRyYW5zYWN0aW9uc0RhdGE+IHtcbiAgY29uc3QgcHJvbWlzZXMgPSB0eG5zUmVzdWx0LnRyYW5zYWN0aW9ucy5tYXAoYXN5bmMgKHRyYW5zYWN0aW9uOiBTY3JhcGVkVHJhbnNhY3Rpb24pOiBQcm9taXNlPFNjcmFwZWRUcmFuc2FjdGlvbj4gPT4ge1xuICAgIGNvbnN0IHsgcGZtRGV0YWlscywgc2VyaWFsTnVtYmVyIH0gPSB0cmFuc2FjdGlvbjtcbiAgICBpZiAoc2VyaWFsTnVtYmVyICE9PSAwKSB7XG4gICAgICBjb25zdCB1cmwgPSBgJHtiYXNlVXJsfSR7cGZtRGV0YWlsc30mYWNjb3VudElkPSR7YWNjb3VudE51bWJlcn0mbGFuZz1oZWA7XG4gICAgICBjb25zdCBleHRyYVRyYW5zYWN0aW9uRGV0YWlscyA9IChhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8U2NyYXBlZFBmbVRyYW5zYWN0aW9uW10+KHBhZ2UsIHVybCkpIHx8IFtdO1xuICAgICAgaWYgKGV4dHJhVHJhbnNhY3Rpb25EZXRhaWxzICYmIGV4dHJhVHJhbnNhY3Rpb25EZXRhaWxzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCB7IHRyYW5zYWN0aW9uTnVtYmVyIH0gPSBleHRyYVRyYW5zYWN0aW9uRGV0YWlsc1swXTtcbiAgICAgICAgaWYgKHRyYW5zYWN0aW9uTnVtYmVyKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnRyYW5zYWN0aW9uLFxuICAgICAgICAgICAgcmVmZXJlbmNlTnVtYmVyOiB0cmFuc2FjdGlvbk51bWJlcixcbiAgICAgICAgICAgIGFkZGl0aW9uYWxJbmZvcm1hdGlvbjogZXh0cmFUcmFuc2FjdGlvbkRldGFpbHMsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJhbnNhY3Rpb247XG4gIH0pO1xuICBjb25zdCByZXMgPSBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gIHJldHVybiB7IHRyYW5zYWN0aW9uczogcmVzIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEFjY291bnRUcmFuc2FjdGlvbnMoXG4gIGJhc2VVcmw6IHN0cmluZyxcbiAgYXBpU2l0ZVVybDogc3RyaW5nLFxuICBwYWdlOiBQYWdlLFxuICBhY2NvdW50TnVtYmVyOiBzdHJpbmcsXG4gIHN0YXJ0RGF0ZTogc3RyaW5nLFxuICBlbmREYXRlOiBzdHJpbmcsXG4gIGFkZGl0aW9uYWxUcmFuc2FjdGlvbkluZm9ybWF0aW9uID0gZmFsc2UsXG4gIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucyxcbikge1xuICBjb25zdCB0eG5zVXJsID0gYCR7YXBpU2l0ZVVybH0vY3VycmVudC1hY2NvdW50L3RyYW5zYWN0aW9ucz9hY2NvdW50SWQ9JHthY2NvdW50TnVtYmVyfSZudW1JdGVtc1BlclBhZ2U9MTAwMCZyZXRyaWV2YWxFbmREYXRlPSR7ZW5kRGF0ZX0mcmV0cmlldmFsU3RhcnREYXRlPSR7c3RhcnREYXRlfSZzb3J0Q29kZT0xYDtcbiAgY29uc3QgdHhuc1Jlc3VsdCA9IGF3YWl0IGZldGNoUG9hbGltWFNSRldpdGhpblBhZ2UocGFnZSwgdHhuc1VybCwgJy9jdXJyZW50LWFjY291bnQvdHJhbnNhY3Rpb25zJyk7XG5cbiAgY29uc3QgZmluYWxSZXN1bHQgPVxuICAgIGFkZGl0aW9uYWxUcmFuc2FjdGlvbkluZm9ybWF0aW9uICYmIHR4bnNSZXN1bHQ/LnRyYW5zYWN0aW9ucy5sZW5ndGhcbiAgICAgID8gYXdhaXQgZ2V0RXh0cmFTY3JhcCh0eG5zUmVzdWx0LCBiYXNlVXJsLCBwYWdlLCBhY2NvdW50TnVtYmVyKVxuICAgICAgOiB0eG5zUmVzdWx0O1xuXG4gIHJldHVybiBjb252ZXJ0VHJhbnNhY3Rpb25zKGZpbmFsUmVzdWx0Py50cmFuc2FjdGlvbnMgPz8gW10sIG9wdGlvbnMpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRBY2NvdW50QmFsYW5jZShhcGlTaXRlVXJsOiBzdHJpbmcsIHBhZ2U6IFBhZ2UsIGFjY291bnROdW1iZXI6IHN0cmluZykge1xuICBjb25zdCBiYWxhbmNlQW5kQ3JlZGl0TGltaXRVcmwgPSBgJHthcGlTaXRlVXJsfS9jdXJyZW50LWFjY291bnQvY29tcG9zaXRlL2JhbGFuY2VBbmRDcmVkaXRMaW1pdD9hY2NvdW50SWQ9JHthY2NvdW50TnVtYmVyfSZ2aWV3PWRldGFpbHMmbGFuZz1oZWA7XG4gIGNvbnN0IGJhbGFuY2VBbmRDcmVkaXRMaW1pdCA9IGF3YWl0IGZldGNoR2V0V2l0aGluUGFnZTxCYWxhbmNlQW5kQ3JlZGl0TGltaXQ+KHBhZ2UsIGJhbGFuY2VBbmRDcmVkaXRMaW1pdFVybCk7XG5cbiAgcmV0dXJuIGJhbGFuY2VBbmRDcmVkaXRMaW1pdD8uY3VycmVudEJhbGFuY2U7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZldGNoQWNjb3VudERhdGEocGFnZTogUGFnZSwgYmFzZVVybDogc3RyaW5nLCBvcHRpb25zOiBTY3JhcGVyT3B0aW9ucykge1xuICBjb25zdCByZXN0Q29udGV4dCA9IGF3YWl0IGdldFJlc3RDb250ZXh0KHBhZ2UpO1xuICBjb25zdCBhcGlTaXRlVXJsID0gYCR7YmFzZVVybH0vJHtyZXN0Q29udGV4dH1gO1xuICBjb25zdCBhY2NvdW50RGF0YVVybCA9IGAke2Jhc2VVcmx9L1NlcnZlclNlcnZpY2VzL2dlbmVyYWwvYWNjb3VudHNgO1xuXG4gIGRlYnVnKCdmZXRjaGluZyBhY2NvdW50cyBkYXRhJyk7XG4gIGNvbnN0IGFjY291bnRzSW5mbyA9IChhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8RmV0Y2hlZEFjY291bnREYXRhPihwYWdlLCBhY2NvdW50RGF0YVVybCkpIHx8IFtdO1xuICBjb25zdCBvcGVuQWNjb3VudHNJbmZvID0gYWNjb3VudHNJbmZvLmZpbHRlcihhY2NvdW50ID0+IGFjY291bnQuYWNjb3VudENsb3NpbmdSZWFzb25Db2RlID09PSAwKTtcbiAgZGVidWcoXG4gICAgJ2dvdCAlZCBvcGVuIGFjY291bnRzIGZyb20gJWQgdG90YWwgYWNjb3VudHMsIGZldGNoaW5nIHR4bnMgYW5kIGJhbGFuY2UnLFxuICAgIG9wZW5BY2NvdW50c0luZm8ubGVuZ3RoLFxuICAgIGFjY291bnRzSW5mby5sZW5ndGgsXG4gICk7XG5cbiAgY29uc3QgZGVmYXVsdFN0YXJ0TW9tZW50ID0gbW9tZW50KCkuc3VidHJhY3QoMSwgJ3llYXJzJykuYWRkKDEsICdkYXknKTtcbiAgY29uc3Qgc3RhcnREYXRlID0gb3B0aW9ucy5zdGFydERhdGUgfHwgZGVmYXVsdFN0YXJ0TW9tZW50LnRvRGF0ZSgpO1xuICBjb25zdCBzdGFydE1vbWVudCA9IG1vbWVudC5tYXgoZGVmYXVsdFN0YXJ0TW9tZW50LCBtb21lbnQoc3RhcnREYXRlKSk7XG4gIGNvbnN0IHsgYWRkaXRpb25hbFRyYW5zYWN0aW9uSW5mb3JtYXRpb24gfSA9IG9wdGlvbnM7XG5cbiAgY29uc3Qgc3RhcnREYXRlU3RyID0gc3RhcnRNb21lbnQuZm9ybWF0KERBVEVfRk9STUFUKTtcbiAgY29uc3QgZW5kRGF0ZVN0ciA9IG1vbWVudCgpLmZvcm1hdChEQVRFX0ZPUk1BVCk7XG5cbiAgY29uc3QgYWNjb3VudHM6IFRyYW5zYWN0aW9uc0FjY291bnRbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgYWNjb3VudCBvZiBvcGVuQWNjb3VudHNJbmZvKSB7XG4gICAgZGVidWcoJ2dldHRpbmcgaW5mb3JtYXRpb24gZm9yIGFjY291bnQgJXMnLCBhY2NvdW50LmFjY291bnROdW1iZXIpO1xuICAgIGNvbnN0IGFjY291bnROdW1iZXIgPSBgJHthY2NvdW50LmJhbmtOdW1iZXJ9LSR7YWNjb3VudC5icmFuY2hOdW1iZXJ9LSR7YWNjb3VudC5hY2NvdW50TnVtYmVyfWA7XG5cbiAgICBjb25zdCBiYWxhbmNlID0gYXdhaXQgZ2V0QWNjb3VudEJhbGFuY2UoYXBpU2l0ZVVybCwgcGFnZSwgYWNjb3VudE51bWJlcik7XG4gICAgY29uc3QgdHhucyA9IGF3YWl0IGdldEFjY291bnRUcmFuc2FjdGlvbnMoXG4gICAgICBiYXNlVXJsLFxuICAgICAgYXBpU2l0ZVVybCxcbiAgICAgIHBhZ2UsXG4gICAgICBhY2NvdW50TnVtYmVyLFxuICAgICAgc3RhcnREYXRlU3RyLFxuICAgICAgZW5kRGF0ZVN0cixcbiAgICAgIGFkZGl0aW9uYWxUcmFuc2FjdGlvbkluZm9ybWF0aW9uLFxuICAgICAgb3B0aW9ucyxcbiAgICApO1xuXG4gICAgYWNjb3VudHMucHVzaCh7XG4gICAgICBhY2NvdW50TnVtYmVyLFxuICAgICAgYmFsYW5jZSxcbiAgICAgIHR4bnMsXG4gICAgfSk7XG4gIH1cblxuICBjb25zdCBhY2NvdW50RGF0YSA9IHtcbiAgICBzdWNjZXNzOiB0cnVlLFxuICAgIGFjY291bnRzLFxuICB9O1xuICBkZWJ1ZygnZmV0Y2hpbmcgZW5kZWQnKTtcbiAgcmV0dXJuIGFjY291bnREYXRhO1xufVxuXG5mdW5jdGlvbiBnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cyhiYXNlVXJsOiBzdHJpbmcpIHtcbiAgY29uc3QgdXJsczogUG9zc2libGVMb2dpblJlc3VsdHMgPSB7fTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuU3VjY2Vzc10gPSBbXG4gICAgYCR7YmFzZVVybH0vcG9ydGFsc2VydmVyL0hvbWVQYWdlYCxcbiAgICBgJHtiYXNlVXJsfS9uZy1wb3J0YWxzLWJ0L3JiL2hlL2hvbWVwYWdlYCxcbiAgICBgJHtiYXNlVXJsfS9uZy1wb3J0YWxzL3JiL2hlL2hvbWVwYWdlYCxcbiAgXTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuSW52YWxpZFBhc3N3b3JkXSA9IFtcbiAgICBgJHtiYXNlVXJsfS9BVVRIRU5USUNBVEUvTE9HT04/Zmxvdz1BVVRIRU5USUNBVEUmc3RhdGU9TE9HT04mZXJyb3Jjb2RlPTEuNiZjYWxsbWU9ZmFsc2VgLFxuICBdO1xuICB1cmxzW0xvZ2luUmVzdWx0cy5DaGFuZ2VQYXNzd29yZF0gPSBbXG4gICAgYCR7YmFzZVVybH0vTUNQL1NUQVJUP2Zsb3c9TUNQJnN0YXRlPVNUQVJUJmV4cGlyZWREYXRlPW51bGxgLFxuICAgIC9cXC9BQk9VVFRPRVhQSVJFXFwvU1RBUlQvaSxcbiAgXTtcbiAgcmV0dXJuIHVybHM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxvZ2luRmllbGRzKGNyZWRlbnRpYWxzOiBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscykge1xuICByZXR1cm4gW1xuICAgIHsgc2VsZWN0b3I6ICcjdXNlckNvZGUnLCB2YWx1ZTogY3JlZGVudGlhbHMudXNlckNvZGUgfSxcbiAgICB7IHNlbGVjdG9yOiAnI3Bhc3N3b3JkJywgdmFsdWU6IGNyZWRlbnRpYWxzLnBhc3N3b3JkIH0sXG4gIF07XG59XG5cbnR5cGUgU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMgPSB7IHVzZXJDb2RlOiBzdHJpbmc7IHBhc3N3b3JkOiBzdHJpbmcgfTtcblxuY2xhc3MgSGFwb2FsaW1TY3JhcGVyIGV4dGVuZHMgQmFzZVNjcmFwZXJXaXRoQnJvd3NlcjxTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscz4ge1xuICBnZXQgYmFzZVVybCgpIHtcbiAgICByZXR1cm4gJ2h0dHBzOi8vbG9naW4uYmFua2hhcG9hbGltLmNvLmlsJztcbiAgfVxuXG4gIGdldExvZ2luT3B0aW9ucyhjcmVkZW50aWFsczogU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbG9naW5Vcmw6IGAke3RoaXMuYmFzZVVybH0vY2dpLWJpbi9wb2Fsd3d3Yz9yZXFOYW1lPWdldExvZ29uUGFnZWAsXG4gICAgICBmaWVsZHM6IGNyZWF0ZUxvZ2luRmllbGRzKGNyZWRlbnRpYWxzKSxcbiAgICAgIHN1Ym1pdEJ1dHRvblNlbGVjdG9yOiAnLmxvZ2luLWJ0bicsXG4gICAgICBwb3N0QWN0aW9uOiBhc3luYyAoKSA9PiB3YWl0Rm9yUmVkaXJlY3QodGhpcy5wYWdlKSxcbiAgICAgIHBvc3NpYmxlUmVzdWx0czogZ2V0UG9zc2libGVMb2dpblJlc3VsdHModGhpcy5iYXNlVXJsKSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZmV0Y2hEYXRhKCkge1xuICAgIHJldHVybiBmZXRjaEFjY291bnREYXRhKHRoaXMucGFnZSwgdGhpcy5iYXNlVXJsLCB0aGlzLm9wdGlvbnMpO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEhhcG9hbGltU2NyYXBlcjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsSUFBQUEsT0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBQ0EsSUFBQUUsTUFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsTUFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksV0FBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssUUFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sYUFBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sdUJBQUEsR0FBQVAsT0FBQTtBQUVBLElBQUFRLGNBQUEsR0FBQVIsT0FBQTtBQUE0RCxTQUFBRCx1QkFBQVUs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