UNPKG

israeli-bank-scrapers-core

Version:

Provide scrapers for all major Israeli banks and credit card companies

344 lines 57.3 kB
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
exports.getMemo = getMemo;
var _moment = _interopRequireDefault(require("moment"));
var _constants = require("../constants");
var _dates = _interopRequireDefault(require("../helpers/dates"));
var _debug = require("../helpers/debug");
var _elementsInteractions = require("../helpers/elements-interactions");
var _fetch = require("../helpers/fetch");
var _navigation = require("../helpers/navigation");
var _transactions = require("../helpers/transactions");
var _waiting = require("../helpers/waiting");
var _transactions2 = require("../transactions");
var _baseScraperWithBrowser = require("./base-scraper-with-browser");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const debug = (0, _debug.getDebug)('max');
const BASE_API_ACTIONS_URL = 'https://onlinelcapi.max.co.il';
const BASE_WELCOME_URL = 'https://www.max.co.il';
const HOME_PAGE_DATA_URL = `${BASE_WELCOME_URL}/api/registered/getHomePageData`;
const LOGIN_URL = `${BASE_WELCOME_URL}/login`;
const PASSWORD_EXPIRED_URL = `${BASE_WELCOME_URL}/renew-password`;
const SUCCESS_URL = `${BASE_WELCOME_URL}/homepage/personal`;
var MaxPlanName = /*#__PURE__*/function (MaxPlanName) {
  MaxPlanName["Normal"] = "\u05E8\u05D2\u05D9\u05DC\u05D4";
  MaxPlanName["ImmediateCharge"] = "\u05D7\u05D9\u05D5\u05D1 \u05E2\u05E1\u05E7\u05D5\u05EA \u05DE\u05D9\u05D9\u05D3\u05D9";
  MaxPlanName["InternetShopping"] = "\u05D0\u05D9\u05E0\u05D8\u05E8\u05E0\u05D8/\u05D7\u05D5\"\u05DC";
  MaxPlanName["Installments"] = "\u05EA\u05E9\u05DC\u05D5\u05DE\u05D9\u05DD";
  MaxPlanName["MonthlyCharge"] = "\u05D7\u05D9\u05D5\u05D1 \u05D7\u05D5\u05D3\u05E9\u05D9";
  MaxPlanName["OneMonthPostponed"] = "\u05D3\u05D7\u05D5\u05D9 \u05D7\u05D5\u05D3\u05E9";
  MaxPlanName["MonthlyPostponed"] = "\u05D3\u05D7\u05D5\u05D9 \u05DC\u05D7\u05D9\u05D5\u05D1 \u05D4\u05D7\u05D5\u05D3\u05E9\u05D9";
  MaxPlanName["MonthlyPayment"] = "\u05EA\u05E9\u05DC\u05D5\u05DD \u05D7\u05D5\u05D3\u05E9\u05D9";
  MaxPlanName["FuturePurchaseFinancing"] = "\u05DE\u05D9\u05DE\u05D5\u05DF \u05DC\u05E8\u05DB\u05D9\u05E9\u05D4 \u05E2\u05EA\u05D9\u05D3\u05D9\u05EA";
  MaxPlanName["MonthlyPostponedInstallments"] = "\u05D3\u05D7\u05D5\u05D9 \u05D7\u05D5\u05D3\u05E9 \u05EA\u05E9\u05DC\u05D5\u05DE\u05D9\u05DD";
  MaxPlanName["ThirtyDaysPlus"] = "\u05E2\u05E1\u05E7\u05EA 30 \u05E4\u05DC\u05D5\u05E1";
  MaxPlanName["TwoMonthsPostponed"] = "\u05D3\u05D7\u05D5\u05D9 \u05D7\u05D5\u05D3\u05E9\u05D9\u05D9\u05DD";
  MaxPlanName["TwoMonthsPostponed2"] = "\u05D3\u05D7\u05D5\u05D9 2 \u05D7' \u05EA\u05E9\u05DC\u05D5\u05DE\u05D9\u05DD";
  MaxPlanName["MonthlyChargePlusInterest"] = "\u05D7\u05D5\u05D3\u05E9\u05D9 + \u05E8\u05D9\u05D1\u05D9\u05EA";
  MaxPlanName["Credit"] = "\u05E7\u05E8\u05D3\u05D9\u05D8";
  MaxPlanName["CreditOutsideTheLimit"] = "\u05E7\u05E8\u05D3\u05D9\u05D8-\u05DE\u05D7\u05D5\u05E5 \u05DC\u05DE\u05E1\u05D2\u05E8\u05EA";
  MaxPlanName["AccumulatingBasket"] = "\u05E1\u05DC \u05DE\u05E6\u05D8\u05D1\u05E8";
  MaxPlanName["PostponedTransactionInstallments"] = "\u05E4\u05E8\u05D9\u05E1\u05EA \u05D4\u05E2\u05E1\u05E7\u05D4 \u05D4\u05D3\u05D7\u05D5\u05D9\u05D4";
  MaxPlanName["ReplacementCard"] = "\u05DB\u05E8\u05D8\u05D9\u05E1 \u05D7\u05DC\u05D9\u05E4\u05D9";
  MaxPlanName["EarlyRepayment"] = "\u05E4\u05E8\u05E2\u05D5\u05DF \u05DE\u05D5\u05E7\u05D3\u05DD";
  MaxPlanName["MonthlyCardFee"] = "\u05D3\u05DE\u05D9 \u05DB\u05E8\u05D8\u05D9\u05E1";
  MaxPlanName["CurrencyPocket"] = "\u05D7\u05D9\u05D5\u05D1 \u05D0\u05E8\u05E0\u05E7 \u05DE\u05D8\u05D7";
  MaxPlanName["MonthlyChargeDistribution"] = "\u05D7\u05DC\u05D5\u05E7\u05EA \u05D7\u05D9\u05D5\u05D1 \u05D7\u05D5\u05D3\u05E9\u05D9";
  return MaxPlanName;
}(MaxPlanName || {});
const INVALID_DETAILS_SELECTOR = '#popupWrongDetails';
const LOGIN_ERROR_SELECTOR = '#popupCardHoldersLoginError';
const categories = new Map();
function redirectOrDialog(page) {
  return Promise.race([(0, _navigation.waitForRedirect)(page, 20000, false, [BASE_WELCOME_URL, `${BASE_WELCOME_URL}/`]), (0, _elementsInteractions.waitUntilElementFound)(page, INVALID_DETAILS_SELECTOR, true), (0, _elementsInteractions.waitUntilElementFound)(page, LOGIN_ERROR_SELECTOR, true)]);
}
function getTransactionsUrl(monthMoment) {
  const month = monthMoment.month() + 1;
  const year = monthMoment.year();
  const date = `${year}-${month}-01`;

  /**
   * url explanation:
   * userIndex: -1 for all account owners
   * cardIndex: -1 for all cards under the account
   * all other query params are static, beside the date which changes for request per month
   */
  const url = new URL(`${BASE_API_ACTIONS_URL}/api/registered/transactionDetails/getTransactionsAndGraphs`);
  url.searchParams.set('filterData', `{"userIndex":-1,"cardIndex":-1,"monthView":true,"date":"${date}","dates":{"startDate":"0","endDate":"0"},"bankAccount":{"bankAccountIndex":-1,"cards":null}}`);
  url.searchParams.set('firstCallCardIndex', '-1');
  return url.toString();
}
async function loadHomePageData(page) {
  debug('Loading home page data for card balances');
  const res = await (0, _fetch.fetchGetWithinPage)(page, HOME_PAGE_DATA_URL);
  const cardMap = new Map();
  if (res?.Result?.UserCards?.Cards) {
    for (const card of res.Result.UserCards.Cards) {
      cardMap.set(card.Last4Digits, card);
    }
  }
  return cardMap;
}
function getCardBalance(card) {
  if (card.CreditLimit == null || card.OpenToBuy == null) return undefined;
  const balance = -(card.CreditLimit - card.OpenToBuy);
  return Math.round(balance * 100) / 100;
}
function getCardBalanceDate(card) {
  const shekelEntry = card.CycleSummary?.find(entry => entry.CurrencySymbol.includes('₪'));
  return shekelEntry ? shekelEntry.Date : undefined;
}
async function loadCategories(page) {
  debug('Loading categories');
  const res = await (0, _fetch.fetchGetWithinPage)(page, `${BASE_API_ACTIONS_URL}/api/contents/getCategories`);
  if (res && Array.isArray(res.result)) {
    debug(`${res.result.length} categories loaded`);
    res.result?.forEach(({
      id,
      name
    }) => categories.set(id, name));
  }
}
function getTransactionType(planName, planTypeId) {
  const cleanedUpTxnTypeStr = planName.replace('\t', ' ').trim();
  switch (cleanedUpTxnTypeStr) {
    case MaxPlanName.ImmediateCharge:
    case MaxPlanName.Normal:
    case MaxPlanName.MonthlyCharge:
    case MaxPlanName.OneMonthPostponed:
    case MaxPlanName.MonthlyPostponed:
    case MaxPlanName.FuturePurchaseFinancing:
    case MaxPlanName.MonthlyPayment:
    case MaxPlanName.MonthlyPostponedInstallments:
    case MaxPlanName.ThirtyDaysPlus:
    case MaxPlanName.TwoMonthsPostponed:
    case MaxPlanName.TwoMonthsPostponed2:
    case MaxPlanName.AccumulatingBasket:
    case MaxPlanName.InternetShopping:
    case MaxPlanName.MonthlyChargePlusInterest:
    case MaxPlanName.PostponedTransactionInstallments:
    case MaxPlanName.ReplacementCard:
    case MaxPlanName.EarlyRepayment:
    case MaxPlanName.MonthlyCardFee:
    case MaxPlanName.CurrencyPocket:
    case MaxPlanName.MonthlyChargeDistribution:
      return _transactions2.TransactionTypes.Normal;
    case MaxPlanName.Installments:
    case MaxPlanName.Credit:
    case MaxPlanName.CreditOutsideTheLimit:
      return _transactions2.TransactionTypes.Installments;
    default:
      switch (planTypeId) {
        case 2:
        case 3:
          return _transactions2.TransactionTypes.Installments;
        case 5:
          return _transactions2.TransactionTypes.Normal;
        default:
          throw new Error(`Unknown transaction type ${cleanedUpTxnTypeStr}`);
      }
  }
}
function getInstallmentsInfo(comments) {
  if (!comments) {
    return undefined;
  }
  const matches = comments.match(/\d+/g);
  if (!matches || matches.length < 2) {
    return undefined;
  }
  return {
    number: parseInt(matches[0], 10),
    total: parseInt(matches[1], 10)
  };
}
function getChargedCurrency(currencyId) {
  switch (currencyId) {
    case 376:
      return _constants.SHEKEL_CURRENCY;
    case 840:
      return _constants.DOLLAR_CURRENCY;
    case 978:
      return _constants.EURO_CURRENCY;
    default:
      return undefined;
  }
}
function getMemo({
  comments,
  fundsTransferReceiverOrTransfer,
  fundsTransferComment
}) {
  if (fundsTransferReceiverOrTransfer) {
    const memo = comments ? `${comments} ${fundsTransferReceiverOrTransfer}` : fundsTransferReceiverOrTransfer;
    return fundsTransferComment ? `${memo}: ${fundsTransferComment}` : memo;
  }
  return comments;
}
function mapTransaction(rawTransaction, options) {
  const isPending = rawTransaction.paymentDate === null;
  const processedDate = (0, _moment.default)(isPending ? rawTransaction.purchaseDate : rawTransaction.paymentDate).toISOString();
  const status = isPending ? _transactions2.TransactionStatuses.Pending : _transactions2.TransactionStatuses.Completed;
  const installments = getInstallmentsInfo(rawTransaction.comments);
  const identifier = installments ? `${rawTransaction.dealData?.arn}_${installments.number}` : rawTransaction.dealData?.arn;
  const result = {
    type: getTransactionType(rawTransaction.planName, rawTransaction.planTypeId),
    date: (0, _moment.default)(rawTransaction.purchaseDate).toISOString(),
    processedDate,
    originalAmount: -rawTransaction.originalAmount,
    originalCurrency: rawTransaction.originalCurrency,
    chargedAmount: -rawTransaction.actualPaymentAmount,
    chargedCurrency: getChargedCurrency(rawTransaction.paymentCurrency),
    description: rawTransaction.merchantName.trim(),
    memo: getMemo(rawTransaction),
    category: categories.get(rawTransaction?.categoryId),
    installments,
    identifier,
    status
  };
  if (options?.includeRawTransaction) {
    result.rawTransaction = (0, _transactions.getRawTransaction)(rawTransaction);
  }
  return result;
}
async function fetchTransactionsForMonth(page, monthMoment, options) {
  const url = getTransactionsUrl(monthMoment);
  const data = await (0, _fetch.fetchGetWithinPage)(page, url);
  const transactionsByAccount = {};
  if (!data || !data.result) return transactionsByAccount;
  data.result.transactions
  // Filter out non-transactions without a plan type, e.g. summary rows
  .filter(transaction => !!transaction.planName).forEach(transaction => {
    if (!transactionsByAccount[transaction.shortCardNumber]) {
      transactionsByAccount[transaction.shortCardNumber] = [];
    }
    const mappedTransaction = mapTransaction(transaction, options);
    transactionsByAccount[transaction.shortCardNumber].push(mappedTransaction);
  });
  return transactionsByAccount;
}
function addResult(allResults, result) {
  const clonedResults = {
    ...allResults
  };
  Object.keys(result).forEach(accountNumber => {
    if (!clonedResults[accountNumber]) {
      clonedResults[accountNumber] = [];
    }
    clonedResults[accountNumber].push(...result[accountNumber]);
  });
  return clonedResults;
}
function prepareTransactions(txns, startMoment, combineInstallments, enableTransactionsFilterByDate) {
  let clonedTxns = Array.from(txns);
  if (!combineInstallments) {
    clonedTxns = (0, _transactions.fixInstallments)(clonedTxns);
  }
  clonedTxns = (0, _transactions.sortTransactionsByDate)(clonedTxns);
  clonedTxns = enableTransactionsFilterByDate ? (0, _transactions.filterOldTransactions)(clonedTxns, startMoment, combineInstallments || false) : clonedTxns;
  return clonedTxns;
}
async function fetchTransactions(page, options) {
  const futureMonthsToScrape = options.futureMonthsToScrape ?? 1;
  const defaultStartMoment = (0, _moment.default)().subtract(1, 'years');
  const startMomentLimit = (0, _moment.default)().subtract(4, 'years');
  const startDate = options.startDate || defaultStartMoment.toDate();
  const startMoment = _moment.default.max(startMomentLimit, (0, _moment.default)(startDate));
  const allMonths = (0, _dates.default)(startMoment, futureMonthsToScrape);
  await loadCategories(page);
  const homePageCards = await loadHomePageData(page);
  let allResults = {};
  for (let i = 0; i < allMonths.length; i += 1) {
    const result = await fetchTransactionsForMonth(page, allMonths[i], options);
    allResults = addResult(allResults, result);
  }
  Object.keys(allResults).forEach(accountNumber => {
    let txns = allResults[accountNumber];
    txns = prepareTransactions(txns, startMoment, options.combineInstallments || false, options.outputData?.enableTransactionsFilterByDate ?? true);
    allResults[accountNumber] = txns;
  });
  return {
    allResults,
    homePageCards
  };
}
function getPossibleLoginResults(page) {
  const urls = {};
  urls[_baseScraperWithBrowser.LoginResults.Success] = [SUCCESS_URL];
  urls[_baseScraperWithBrowser.LoginResults.ChangePassword] = [PASSWORD_EXPIRED_URL];
  urls[_baseScraperWithBrowser.LoginResults.InvalidPassword] = [async () => {
    return (0, _elementsInteractions.elementPresentOnPage)(page, INVALID_DETAILS_SELECTOR);
  }];
  urls[_baseScraperWithBrowser.LoginResults.UnknownError] = [async () => {
    return (0, _elementsInteractions.elementPresentOnPage)(page, LOGIN_ERROR_SELECTOR);
  }];
  return urls;
}
function createLoginFields(credentials) {
  return [{
    selector: '#user-name',
    value: credentials.username
  }, {
    selector: '#password',
    value: credentials.password
  }];
}
class MaxScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser {
  getLoginOptions(credentials) {
    return {
      loginUrl: LOGIN_URL,
      fields: createLoginFields(credentials),
      submitButtonSelector: 'app-user-login-form .general-button.send-me-code',
      preAction: async () => {
        if (await (0, _elementsInteractions.elementPresentOnPage)(this.page, '#closePopup')) {
          await (0, _elementsInteractions.clickButton)(this.page, '#closePopup');
        }
        await (0, _elementsInteractions.clickButton)(this.page, '.personal-area > a.go-to-personal-area');
        if (await (0, _elementsInteractions.elementPresentOnPage)(this.page, '.login-link#private')) {
          await (0, _elementsInteractions.clickButton)(this.page, '.login-link#private');
        }
        // Try twice in case it can't find it the first time
        try {
          await (0, _elementsInteractions.waitUntilElementFound)(this.page, '#login-password-link', true, 10000);
        } catch {
          await (0, _waiting.sleep)(1000);
          await (0, _elementsInteractions.waitUntilElementFound)(this.page, '#login-password-link', true, 10000);
        }
        await (0, _elementsInteractions.clickButton)(this.page, '#login-password-link');
        await (0, _elementsInteractions.waitUntilElementFound)(this.page, '#login-password.tab-pane.active app-user-login-form', true);
      },
      checkReadiness: async () => {
        await (0, _elementsInteractions.waitUntilElementFound)(this.page, '.personal-area > a.go-to-personal-area', true);
      },
      postAction: async () => redirectOrDialog(this.page),
      possibleResults: getPossibleLoginResults(this.page),
      waitUntil: 'domcontentloaded'
    };
  }
  async fetchData() {
    const {
      allResults,
      homePageCards
    } = await fetchTransactions(this.page, this.options);
    const accounts = Object.keys(allResults).map(accountNumber => {
      const card = homePageCards.get(accountNumber);
      return {
        accountNumber,
        txns: allResults[accountNumber],
        balance: card ? getCardBalance(card) : undefined,
        balanceDate: card ? getCardBalanceDate(card) : undefined,
        cardFrame: card?.CreditLimit ?? undefined
      };
    });
    return {
      success: true,
      accounts
    };
  }
}
var _default = exports.default = MaxScraper;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfY29uc3RhbnRzIiwiX2RhdGVzIiwiX2RlYnVnIiwiX2VsZW1lbnRzSW50ZXJhY3Rpb25zIiwiX2ZldGNoIiwiX25hdmlnYXRpb24iLCJfdHJhbnNhY3Rpb25zIiwiX3dhaXRpbmciLCJfdHJhbnNhY3Rpb25zMiIsIl9iYXNlU2NyYXBlcldpdGhCcm93c2VyIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiZGVidWciLCJnZXREZWJ1ZyIsIkJBU0VfQVBJX0FDVElPTlNfVVJMIiwiQkFTRV9XRUxDT01FX1VSTCIsIkhPTUVfUEFHRV9EQVRBX1VSTCIsIkxPR0lOX1VSTCIsIlBBU1NXT1JEX0VYUElSRURfVVJMIiwiU1VDQ0VTU19VUkwiLCJNYXhQbGFuTmFtZSIsIklOVkFMSURfREVUQUlMU19TRUxFQ1RPUiIsIkxPR0lOX0VSUk9SX1NFTEVDVE9SIiwiY2F0ZWdvcmllcyIsIk1hcCIsInJlZGlyZWN0T3JEaWFsb2ciLCJwYWdlIiwiUHJvbWlzZSIsInJhY2UiLCJ3YWl0Rm9yUmVkaXJlY3QiLCJ3YWl0VW50aWxFbGVtZW50Rm91bmQiLCJnZXRUcmFuc2FjdGlvbnNVcmwiLCJtb250aE1vbWVudCIsIm1vbnRoIiwieWVhciIsImRhdGUiLCJ1cmwiLCJVUkwiLCJzZWFyY2hQYXJhbXMiLCJzZXQiLCJ0b1N0cmluZyIsImxvYWRIb21lUGFnZURhdGEiLCJyZXMiLCJmZXRjaEdldFdpdGhpblBhZ2UiLCJjYXJkTWFwIiwiUmVzdWx0IiwiVXNlckNhcmRzIiwiQ2FyZHMiLCJjYXJkIiwiTGFzdDREaWdpdHMiLCJnZXRDYXJkQmFsYW5jZSIsIkNyZWRpdExpbWl0IiwiT3BlblRvQnV5IiwidW5kZWZpbmVkIiwiYmFsYW5jZSIsIk1hdGgiLCJyb3VuZCIsImdldENhcmRCYWxhbmNlRGF0ZSIsInNoZWtlbEVudHJ5IiwiQ3ljbGVTdW1tYXJ5IiwiZmluZCIsImVudHJ5IiwiQ3VycmVuY3lTeW1ib2wiLCJpbmNsdWRlcyIsIkRhdGUiLCJsb2FkQ2F0ZWdvcmllcyIsIkFycmF5IiwiaXNBcnJheSIsInJlc3VsdCIsImxlbmd0aCIsImZvckVhY2giLCJpZCIsIm5hbWUiLCJnZXRUcmFuc2FjdGlvblR5cGUiLCJwbGFuTmFtZSIsInBsYW5UeXBlSWQiLCJjbGVhbmVkVXBUeG5UeXBlU3RyIiwicmVwbGFjZSIsInRyaW0iLCJJbW1lZGlhdGVDaGFyZ2UiLCJOb3JtYWwiLCJNb250aGx5Q2hhcmdlIiwiT25lTW9udGhQb3N0cG9uZWQiLCJNb250aGx5UG9zdHBvbmVkIiwiRnV0dXJlUHVyY2hhc2VGaW5hbmNpbmciLCJNb250aGx5UGF5bWVudCIsIk1vbnRobHlQb3N0cG9uZWRJbnN0YWxsbWVudHMiLCJUaGlydHlEYXlzUGx1cyIsIlR3b01vbnRoc1Bvc3Rwb25lZCIsIlR3b01vbnRoc1Bvc3Rwb25lZDIiLCJBY2N1bXVsYXRpbmdCYXNrZXQiLCJJbnRlcm5ldFNob3BwaW5nIiwiTW9udGhseUNoYXJnZVBsdXNJbnRlcmVzdCIsIlBvc3Rwb25lZFRyYW5zYWN0aW9uSW5zdGFsbG1lbnRzIiwiUmVwbGFjZW1lbnRDYXJkIiwiRWFybHlSZXBheW1lbnQiLCJNb250aGx5Q2FyZEZlZSIsIkN1cnJlbmN5UG9ja2V0IiwiTW9udGhseUNoYXJnZURpc3RyaWJ1dGlvbiIsIlRyYW5zYWN0aW9uVHlwZXMiLCJJbnN0YWxsbWVudHMiLCJDcmVkaXQiLCJDcmVkaXRPdXRzaWRlVGhlTGltaXQiLCJFcnJvciIsImdldEluc3RhbGxtZW50c0luZm8iLCJjb21tZW50cyIsIm1hdGNoZXMiLCJtYXRjaCIsIm51bWJlciIsInBhcnNlSW50IiwidG90YWwiLCJnZXRDaGFyZ2VkQ3VycmVuY3kiLCJjdXJyZW5jeUlkIiwiU0hFS0VMX0NVUlJFTkNZIiwiRE9MTEFSX0NVUlJFTkNZIiwiRVVST19DVVJSRU5DWSIsImdldE1lbW8iLCJmdW5kc1RyYW5zZmVyUmVjZWl2ZXJPclRyYW5zZmVyIiwiZnVuZHNUcmFuc2ZlckNvbW1lbnQiLCJtZW1vIiwibWFwVHJhbnNhY3Rpb24iLCJyYXdUcmFuc2FjdGlvbiIsIm9wdGlvbnMiLCJpc1BlbmRpbmciLCJwYXltZW50RGF0ZSIsInByb2Nlc3NlZERhdGUiLCJtb21lbnQiLCJwdXJjaGFzZURhdGUiLCJ0b0lTT1N0cmluZyIsInN0YXR1cyIsIlRyYW5zYWN0aW9uU3RhdHVzZXMiLCJQZW5kaW5nIiwiQ29tcGxldGVkIiwiaW5zdGFsbG1lbnRzIiwiaWRlbnRpZmllciIsImRlYWxEYXRhIiwiYXJuIiwidHlwZSIsIm9yaWdpbmFsQW1vdW50Iiwib3JpZ2luYWxDdXJyZW5jeSIsImNoYXJnZWRBbW91bnQiLCJhY3R1YWxQYXltZW50QW1vdW50IiwiY2hhcmdlZEN1cnJlbmN5IiwicGF5bWVudEN1cnJlbmN5IiwiZGVzY3JpcHRpb24iLCJtZXJjaGFudE5hbWUiLCJjYXRlZ29yeSIsImdldCIsImNhdGVnb3J5SWQiLCJpbmNsdWRlUmF3VHJhbnNhY3Rpb24iLCJnZXRSYXdUcmFuc2FjdGlvbiIsImZldGNoVHJhbnNhY3Rpb25zRm9yTW9udGgiLCJkYXRhIiwidHJhbnNhY3Rpb25zQnlBY2NvdW50IiwidHJhbnNhY3Rpb25zIiwiZmlsdGVyIiwidHJhbnNhY3Rpb24iLCJzaG9ydENhcmROdW1iZXIiLCJtYXBwZWRUcmFuc2FjdGlvbiIsInB1c2giLCJhZGRSZXN1bHQiLCJhbGxSZXN1bHRzIiwiY2xvbmVkUmVzdWx0cyIsIk9iamVjdCIsImtleXMiLCJhY2NvdW50TnVtYmVyIiwicHJlcGFyZVRyYW5zYWN0aW9ucyIsInR4bnMiLCJzdGFydE1vbWVudCIsImNvbWJpbmVJbnN0YWxsbWVudHMiLCJlbmFibGVUcmFuc2FjdGlvbnNGaWx0ZXJCeURhdGUiLCJjbG9uZWRUeG5zIiwiZnJvbSIsImZpeEluc3RhbGxtZW50cyIsInNvcnRUcmFuc2FjdGlvbnNCeURhdGUiLCJmaWx0ZXJPbGRUcmFuc2FjdGlvbnMiLCJmZXRjaFRyYW5zYWN0aW9ucyIsImZ1dHVyZU1vbnRoc1RvU2NyYXBlIiwiZGVmYXVsdFN0YXJ0TW9tZW50Iiwic3VidHJhY3QiLCJzdGFydE1vbWVudExpbWl0Iiwic3RhcnREYXRlIiwidG9EYXRlIiwibWF4IiwiYWxsTW9udGhzIiwiZ2V0QWxsTW9udGhNb21lbnRzIiwiaG9tZVBhZ2VDYXJkcyIsImkiLCJvdXRwdXREYXRhIiwiZ2V0UG9zc2libGVMb2dpblJlc3VsdHMiLCJ1cmxzIiwiTG9naW5SZXN1bHRzIiwiU3VjY2VzcyIsIkNoYW5nZVBhc3N3b3JkIiwiSW52YWxpZFBhc3N3b3JkIiwiZWxlbWVudFByZXNlbnRPblBhZ2UiLCJVbmtub3duRXJyb3IiLCJjcmVhdGVMb2dpbkZpZWxkcyIsImNyZWRlbnRpYWxzIiwic2VsZWN0b3IiLCJ2YWx1ZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJNYXhTY3JhcGVyIiwiQmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImdldExvZ2luT3B0aW9ucyIsImxvZ2luVXJsIiwiZmllbGRzIiwic3VibWl0QnV0dG9uU2VsZWN0b3IiLCJwcmVBY3Rpb24iLCJjbGlja0J1dHRvbiIsInNsZWVwIiwiY2hlY2tSZWFkaW5lc3MiLCJwb3N0QWN0aW9uIiwicG9zc2libGVSZXN1bHRzIiwid2FpdFVudGlsIiwiZmV0Y2hEYXRhIiwiYWNjb3VudHMiLCJtYXAiLCJiYWxhbmNlRGF0ZSIsImNhcmRGcmFtZSIsInN1Y2Nlc3MiLCJfZGVmYXVsdCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc2NyYXBlcnMvbWF4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBtb21lbnQsIHsgdHlwZSBNb21lbnQgfSBmcm9tICdtb21lbnQnO1xuaW1wb3J0IHsgdHlwZSBQYWdlIH0gZnJvbSAncHVwcGV0ZWVyLWNvcmUnO1xuaW1wb3J0IHsgRE9MTEFSX0NVUlJFTkNZLCBFVVJPX0NVUlJFTkNZLCBTSEVLRUxfQ1VSUkVOQ1kgfSBmcm9tICcuLi9jb25zdGFudHMnO1xuaW1wb3J0IGdldEFsbE1vbnRoTW9tZW50cyBmcm9tICcuLi9oZWxwZXJzL2RhdGVzJztcbmltcG9ydCB7IGdldERlYnVnIH0gZnJvbSAnLi4vaGVscGVycy9kZWJ1Zyc7XG5pbXBvcnQgeyBjbGlja0J1dHRvbiwgZWxlbWVudFByZXNlbnRPblBhZ2UsIHdhaXRVbnRpbEVsZW1lbnRGb3VuZCB9IGZyb20gJy4uL2hlbHBlcnMvZWxlbWVudHMtaW50ZXJhY3Rpb25zJztcbmltcG9ydCB7IGZldGNoR2V0V2l0aGluUGFnZSB9IGZyb20gJy4uL2hlbHBlcnMvZmV0Y2gnO1xuaW1wb3J0IHsgd2FpdEZvclJlZGlyZWN0IH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7XG4gIGZpbHRlck9sZFRyYW5zYWN0aW9ucyxcbiAgZml4SW5zdGFsbG1lbnRzLFxuICBzb3J0VHJhbnNhY3Rpb25zQnlEYXRlLFxuICBnZXRSYXdUcmFuc2FjdGlvbixcbn0gZnJvbSAnLi4vaGVscGVycy90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tICcuLi9oZWxwZXJzL3dhaXRpbmcnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25TdGF0dXNlcywgVHJhbnNhY3Rpb25UeXBlcywgdHlwZSBUcmFuc2FjdGlvbiwgdHlwZSBUcmFuc2FjdGlvbnNBY2NvdW50IH0gZnJvbSAnLi4vdHJhbnNhY3Rpb25zJztcbmltcG9ydCB7XG4gIEJhc2VTY3JhcGVyV2l0aEJyb3dzZXIsXG4gIExvZ2luUmVzdWx0cyxcbiAgdHlwZSBMb2dpbk9wdGlvbnMsXG4gIHR5cGUgUG9zc2libGVMb2dpblJlc3VsdHMsXG59IGZyb20gJy4vYmFzZS1zY3JhcGVyLXdpdGgtYnJvd3Nlcic7XG5pbXBvcnQgeyB0eXBlIFNjcmFwZXJPcHRpb25zIH0gZnJvbSAnLi9pbnRlcmZhY2UnO1xuXG5jb25zdCBkZWJ1ZyA9IGdldERlYnVnKCdtYXgnKTtcblxuZXhwb3J0IGludGVyZmFjZSBTY3JhcGVkVHJhbnNhY3Rpb24ge1xuICBzaG9ydENhcmROdW1iZXI6IHN0cmluZztcbiAgcGF5bWVudERhdGU/OiBzdHJpbmc7XG4gIHB1cmNoYXNlRGF0ZTogc3RyaW5nO1xuICBhY3R1YWxQYXltZW50QW1vdW50OiBzdHJpbmc7XG4gIHBheW1lbnRDdXJyZW5jeTogbnVtYmVyIHwgbnVsbDtcbiAgb3JpZ2luYWxDdXJyZW5jeTogc3RyaW5nO1xuICBvcmlnaW5hbEFtb3VudDogbnVtYmVyO1xuICBwbGFuTmFtZTogc3RyaW5nO1xuICBwbGFuVHlwZUlkOiBudW1iZXI7XG4gIGNvbW1lbnRzOiBzdHJpbmc7XG4gIG1lcmNoYW50TmFtZTogc3RyaW5nO1xuICBjYXRlZ29yeUlkOiBudW1iZXI7XG4gIGZ1bmRzVHJhbnNmZXJDb21tZW50Pzogc3RyaW5nO1xuICBmdW5kc1RyYW5zZmVyUmVjZWl2ZXJPclRyYW5zZmVyPzogc3RyaW5nO1xuICBkZWFsRGF0YT86IHtcbiAgICBhcm46IHN0cmluZztcbiAgfTtcbn1cblxuY29uc3QgQkFTRV9BUElfQUNUSU9OU19VUkwgPSAnaHR0cHM6Ly9vbmxpbmVsY2FwaS5tYXguY28uaWwnO1xuY29uc3QgQkFTRV9XRUxDT01FX1VSTCA9ICdodHRwczovL3d3dy5tYXguY28uaWwnO1xuY29uc3QgSE9NRV9QQUdFX0RBVEFfVVJMID0gYCR7QkFTRV9XRUxDT01FX1VSTH0vYXBpL3JlZ2lzdGVyZWQvZ2V0SG9tZVBhZ2VEYXRhYDtcblxuY29uc3QgTE9HSU5fVVJMID0gYCR7QkFTRV9XRUxDT01FX1VSTH0vbG9naW5gO1xuY29uc3QgUEFTU1dPUkRfRVhQSVJFRF9VUkwgPSBgJHtCQVNFX1dFTENPTUVfVVJMfS9yZW5ldy1wYXNzd29yZGA7XG5jb25zdCBTVUNDRVNTX1VSTCA9IGAke0JBU0VfV0VMQ09NRV9VUkx9L2hvbWVwYWdlL3BlcnNvbmFsYDtcblxuZW51bSBNYXhQbGFuTmFtZSB7XG4gIE5vcm1hbCA9ICfXqNeS15nXnNeUJyxcbiAgSW1tZWRpYXRlQ2hhcmdlID0gJ9eX15nXldeRINei16HXp9eV16og157XmdeZ15PXmScsXG4gIEludGVybmV0U2hvcHBpbmcgPSAn15DXmdeg15jXqNeg15gv15fXlVwi15wnLFxuICBJbnN0YWxsbWVudHMgPSAn16rXqdec15XXnteZ150nLFxuICBNb250aGx5Q2hhcmdlID0gJ9eX15nXldeRINeX15XXk9ep15knLFxuICBPbmVNb250aFBvc3Rwb25lZCA9ICfXk9eX15XXmSDXl9eV15PXqScsXG4gIE1vbnRobHlQb3N0cG9uZWQgPSAn15PXl9eV15kg15zXl9eZ15XXkSDXlNeX15XXk9ep15knLFxuICBNb250aGx5UGF5bWVudCA9ICfXqtep15zXldedINeX15XXk9ep15knLFxuICBGdXR1cmVQdXJjaGFzZUZpbmFuY2luZyA9ICfXnteZ157XldefINec16jXm9eZ16nXlCDXoteq15nXk9eZ16onLFxuICBNb250aGx5UG9zdHBvbmVkSW5zdGFsbG1lbnRzID0gJ9eT15fXldeZINeX15XXk9epINeq16nXnNeV157XmdedJyxcbiAgVGhpcnR5RGF5c1BsdXMgPSAn16LXoden16ogMzAg16TXnNeV16EnLFxuICBUd29Nb250aHNQb3N0cG9uZWQgPSAn15PXl9eV15kg15fXldeT16nXmdeZ150nLFxuICBUd29Nb250aHNQb3N0cG9uZWQyID0gXCLXk9eX15XXmSAyINeXJyDXqtep15zXldee15nXnVwiLFxuICBNb250aGx5Q2hhcmdlUGx1c0ludGVyZXN0ID0gJ9eX15XXk9ep15kgKyDXqNeZ15HXmdeqJyxcbiAgQ3JlZGl0ID0gJ9en16jXk9eZ15gnLFxuICBDcmVkaXRPdXRzaWRlVGhlTGltaXQgPSAn16fXqNeT15nXmC3XnteX15XXpSDXnNee16HXkteo16onLFxuICBBY2N1bXVsYXRpbmdCYXNrZXQgPSAn16HXnCDXntem15jXkdeoJyxcbiAgUG9zdHBvbmVkVHJhbnNhY3Rpb25JbnN0YWxsbWVudHMgPSAn16TXqNeZ16HXqiDXlNei16HXp9eUINeU15PXl9eV15nXlCcsXG4gIFJlcGxhY2VtZW50Q2FyZCA9ICfXm9eo15jXmdehINeX15zXmdek15knLFxuICBFYXJseVJlcGF5bWVudCA9ICfXpNeo16LXldefINee15XXp9eT150nLFxuICBNb250aGx5Q2FyZEZlZSA9ICfXk9ee15kg15vXqNeY15nXoScsXG4gIEN1cnJlbmN5UG9ja2V0ID0gJ9eX15nXldeRINeQ16jXoNenINee15jXlycsXG4gIE1vbnRobHlDaGFyZ2VEaXN0cmlidXRpb24gPSAn15fXnNeV16fXqiDXl9eZ15XXkSDXl9eV15PXqdeZJyxcbn1cblxuY29uc3QgSU5WQUxJRF9ERVRBSUxTX1NFTEVDVE9SID0gJyNwb3B1cFdyb25nRGV0YWlscyc7XG5jb25zdCBMT0dJTl9FUlJPUl9TRUxFQ1RPUiA9ICcjcG9wdXBDYXJkSG9sZGVyc0xvZ2luRXJyb3InO1xuXG5pbnRlcmZhY2UgSG9tZVBhZ2VDYXJkIHtcbiAgTGFzdDREaWdpdHM6IHN0cmluZztcbiAgQ3JlZGl0TGltaXQ6IG51bWJlciB8IG51bGw7XG4gIE9wZW5Ub0J1eTogbnVtYmVyIHwgbnVsbDtcbiAgQ3ljbGVTdW1tYXJ5OiBBcnJheTx7XG4gICAgRGF0ZTogc3RyaW5nO1xuICAgIEN1cnJlbmN5U3ltYm9sOiBzdHJpbmc7XG4gIH0+O1xufVxuXG5pbnRlcmZhY2UgSG9tZVBhZ2VEYXRhUmVzdWx0IHtcbiAgUmVzdWx0Pzoge1xuICAgIFVzZXJDYXJkcz86IHtcbiAgICAgIENhcmRzPzogSG9tZVBhZ2VDYXJkW107XG4gICAgfTtcbiAgfTtcbn1cblxuY29uc3QgY2F0ZWdvcmllcyA9IG5ldyBNYXA8bnVtYmVyLCBzdHJpbmc+KCk7XG5cbmZ1bmN0aW9uIHJlZGlyZWN0T3JEaWFsb2cocGFnZTogUGFnZSkge1xuICByZXR1cm4gUHJvbWlzZS5yYWNlKFtcbiAgICB3YWl0Rm9yUmVkaXJlY3QocGFnZSwgMjAwMDAsIGZhbHNlLCBbQkFTRV9XRUxDT01FX1VSTCwgYCR7QkFTRV9XRUxDT01FX1VSTH0vYF0pLFxuICAgIHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCBJTlZBTElEX0RFVEFJTFNfU0VMRUNUT1IsIHRydWUpLFxuICAgIHdhaXRVbnRpbEVsZW1lbnRGb3VuZChwYWdlLCBMT0dJTl9FUlJPUl9TRUxFQ1RPUiwgdHJ1ZSksXG4gIF0pO1xufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2FjdGlvbnNVcmwobW9udGhNb21lbnQ6IE1vbWVudCkge1xuICBjb25zdCBtb250aCA9IG1vbnRoTW9tZW50Lm1vbnRoKCkgKyAxO1xuICBjb25zdCB5ZWFyID0gbW9udGhNb21lbnQueWVhcigpO1xuICBjb25zdCBkYXRlID0gYCR7eWVhcn0tJHttb250aH0tMDFgO1xuXG4gIC8qKlxuICAgKiB1cmwgZXhwbGFuYXRpb246XG4gICAqIHVzZXJJbmRleDogLTEgZm9yIGFsbCBhY2NvdW50IG93bmVyc1xuICAgKiBjYXJkSW5kZXg6IC0xIGZvciBhbGwgY2FyZHMgdW5kZXIgdGhlIGFjY291bnRcbiAgICogYWxsIG90aGVyIHF1ZXJ5IHBhcmFtcyBhcmUgc3RhdGljLCBiZXNpZGUgdGhlIGRhdGUgd2hpY2ggY2hhbmdlcyBmb3IgcmVxdWVzdCBwZXIgbW9udGhcbiAgICovXG4gIGNvbnN0IHVybCA9IG5ldyBVUkwoYCR7QkFTRV9BUElfQUNUSU9OU19VUkx9L2FwaS9yZWdpc3RlcmVkL3RyYW5zYWN0aW9uRGV0YWlscy9nZXRUcmFuc2FjdGlvbnNBbmRHcmFwaHNgKTtcbiAgdXJsLnNlYXJjaFBhcmFtcy5zZXQoXG4gICAgJ2ZpbHRlckRhdGEnLFxuICAgIGB7XCJ1c2VySW5kZXhcIjotMSxcImNhcmRJbmRleFwiOi0xLFwibW9udGhWaWV3XCI6dHJ1ZSxcImRhdGVcIjpcIiR7ZGF0ZX1cIixcImRhdGVzXCI6e1wic3RhcnREYXRlXCI6XCIwXCIsXCJlbmREYXRlXCI6XCIwXCJ9LFwiYmFua0FjY291bnRcIjp7XCJiYW5rQWNjb3VudEluZGV4XCI6LTEsXCJjYXJkc1wiOm51bGx9fWAsXG4gICk7XG4gIHVybC5zZWFyY2hQYXJhbXMuc2V0KCdmaXJzdENhbGxDYXJkSW5kZXgnLCAnLTEnKTtcbiAgcmV0dXJuIHVybC50b1N0cmluZygpO1xufVxuXG5pbnRlcmZhY2UgRmV0Y2hDYXRlZ29yeVJlc3VsdCB7XG4gIHJlc3VsdD86IEFycmF5PHtcbiAgICBpZDogbnVtYmVyO1xuICAgIG5hbWU6IHN0cmluZztcbiAgfT47XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvYWRIb21lUGFnZURhdGEocGFnZTogUGFnZSk6IFByb21pc2U8TWFwPHN0cmluZywgSG9tZVBhZ2VDYXJkPj4ge1xuICBkZWJ1ZygnTG9hZGluZyBob21lIHBhZ2UgZGF0YSBmb3IgY2FyZCBiYWxhbmNlcycpO1xuICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8SG9tZVBhZ2VEYXRhUmVzdWx0PihwYWdlLCBIT01FX1BBR0VfREFUQV9VUkwpO1xuICBjb25zdCBjYXJkTWFwID0gbmV3IE1hcDxzdHJpbmcsIEhvbWVQYWdlQ2FyZD4oKTtcbiAgaWYgKHJlcz8uUmVzdWx0Py5Vc2VyQ2FyZHM/LkNhcmRzKSB7XG4gICAgZm9yIChjb25zdCBjYXJkIG9mIHJlcy5SZXN1bHQuVXNlckNhcmRzLkNhcmRzKSB7XG4gICAgICBjYXJkTWFwLnNldChjYXJkLkxhc3Q0RGlnaXRzLCBjYXJkKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNhcmRNYXA7XG59XG5cbmZ1bmN0aW9uIGdldENhcmRCYWxhbmNlKGNhcmQ6IEhvbWVQYWdlQ2FyZCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gIGlmIChjYXJkLkNyZWRpdExpbWl0ID09IG51bGwgfHwgY2FyZC5PcGVuVG9CdXkgPT0gbnVsbCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgYmFsYW5jZSA9IC0oY2FyZC5DcmVkaXRMaW1pdCAtIGNhcmQuT3BlblRvQnV5KTtcbiAgcmV0dXJuIE1hdGgucm91bmQoYmFsYW5jZSAqIDEwMCkgLyAxMDA7XG59XG5cbmZ1bmN0aW9uIGdldENhcmRCYWxhbmNlRGF0ZShjYXJkOiBIb21lUGFnZUNhcmQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBzaGVrZWxFbnRyeSA9IGNhcmQuQ3ljbGVTdW1tYXJ5Py5maW5kKGVudHJ5ID0+IGVudHJ5LkN1cnJlbmN5U3ltYm9sLmluY2x1ZGVzKCfigqonKSk7XG4gIHJldHVybiBzaGVrZWxFbnRyeSA/IHNoZWtlbEVudHJ5LkRhdGUgOiB1bmRlZmluZWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvYWRDYXRlZ29yaWVzKHBhZ2U6IFBhZ2UpIHtcbiAgZGVidWcoJ0xvYWRpbmcgY2F0ZWdvcmllcycpO1xuICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8RmV0Y2hDYXRlZ29yeVJlc3VsdD4ocGFnZSwgYCR7QkFTRV9BUElfQUNUSU9OU19VUkx9L2FwaS9jb250ZW50cy9nZXRDYXRlZ29yaWVzYCk7XG4gIGlmIChyZXMgJiYgQXJyYXkuaXNBcnJheShyZXMucmVzdWx0KSkge1xuICAgIGRlYnVnKGAke3Jlcy5yZXN1bHQubGVuZ3RofSBjYXRlZ29yaWVzIGxvYWRlZGApO1xuICAgIHJlcy5yZXN1bHQ/LmZvckVhY2goKHsgaWQsIG5hbWUgfSkgPT4gY2F0ZWdvcmllcy5zZXQoaWQsIG5hbWUpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRUcmFuc2FjdGlvblR5cGUocGxhbk5hbWU6IHN0cmluZywgcGxhblR5cGVJZDogbnVtYmVyKSB7XG4gIGNvbnN0IGNsZWFuZWRVcFR4blR5cGVTdHIgPSBwbGFuTmFtZS5yZXBsYWNlKCdcXHQnLCAnICcpLnRyaW0oKSBhcyBNYXhQbGFuTmFtZTtcbiAgc3dpdGNoIChjbGVhbmVkVXBUeG5UeXBlU3RyKSB7XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5JbW1lZGlhdGVDaGFyZ2U6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5Ob3JtYWw6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5Nb250aGx5Q2hhcmdlOlxuICAgIGNhc2UgTWF4UGxhbk5hbWUuT25lTW9udGhQb3N0cG9uZWQ6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5Nb250aGx5UG9zdHBvbmVkOlxuICAgIGNhc2UgTWF4UGxhbk5hbWUuRnV0dXJlUHVyY2hhc2VGaW5hbmNpbmc6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5Nb250aGx5UGF5bWVudDpcbiAgICBjYXNlIE1heFBsYW5OYW1lLk1vbnRobHlQb3N0cG9uZWRJbnN0YWxsbWVudHM6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5UaGlydHlEYXlzUGx1czpcbiAgICBjYXNlIE1heFBsYW5OYW1lLlR3b01vbnRoc1Bvc3Rwb25lZDpcbiAgICBjYXNlIE1heFBsYW5OYW1lLlR3b01vbnRoc1Bvc3Rwb25lZDI6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5BY2N1bXVsYXRpbmdCYXNrZXQ6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5JbnRlcm5ldFNob3BwaW5nOlxuICAgIGNhc2UgTWF4UGxhbk5hbWUuTW9udGhseUNoYXJnZVBsdXNJbnRlcmVzdDpcbiAgICBjYXNlIE1heFBsYW5OYW1lLlBvc3Rwb25lZFRyYW5zYWN0aW9uSW5zdGFsbG1lbnRzOlxuICAgIGNhc2UgTWF4UGxhbk5hbWUuUmVwbGFjZW1lbnRDYXJkOlxuICAgIGNhc2UgTWF4UGxhbk5hbWUuRWFybHlSZXBheW1lbnQ6XG4gICAgY2FzZSBNYXhQbGFuTmFtZS5Nb250aGx5Q2FyZEZlZTpcbiAgICBjYXNlIE1heFBsYW5OYW1lLkN1cnJlbmN5UG9ja2V0OlxuICAgIGNhc2UgTWF4UGxhbk5hbWUuTW9udGhseUNoYXJnZURpc3RyaWJ1dGlvbjpcbiAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGVzLk5vcm1hbDtcbiAgICBjYXNlIE1heFBsYW5OYW1lLkluc3RhbGxtZW50czpcbiAgICBjYXNlIE1heFBsYW5OYW1lLkNyZWRpdDpcbiAgICBjYXNlIE1heFBsYW5OYW1lLkNyZWRpdE91dHNpZGVUaGVMaW1pdDpcbiAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGVzLkluc3RhbGxtZW50cztcbiAgICBkZWZhdWx0OlxuICAgICAgc3dpdGNoIChwbGFuVHlwZUlkKSB7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGVzLkluc3RhbGxtZW50cztcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIHJldHVybiBUcmFuc2FjdGlvblR5cGVzLk5vcm1hbDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gdHJhbnNhY3Rpb24gdHlwZSAke2NsZWFuZWRVcFR4blR5cGVTdHIgYXMgc3RyaW5nfWApO1xuICAgICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldEluc3RhbGxtZW50c0luZm8oY29tbWVudHM6IHN0cmluZykge1xuICBpZiAoIWNvbW1lbnRzKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICBjb25zdCBtYXRjaGVzID0gY29tbWVudHMubWF0Y2goL1xcZCsvZyk7XG4gIGlmICghbWF0Y2hlcyB8fCBtYXRjaGVzLmxlbmd0aCA8IDIpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBudW1iZXI6IHBhcnNlSW50KG1hdGNoZXNbMF0sIDEwKSxcbiAgICB0b3RhbDogcGFyc2VJbnQobWF0Y2hlc1sxXSwgMTApLFxuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRDaGFyZ2VkQ3VycmVuY3koY3VycmVuY3lJZDogbnVtYmVyIHwgbnVsbCkge1xuICBzd2l0Y2ggKGN1cnJlbmN5SWQpIHtcbiAgICBjYXNlIDM3NjpcbiAgICAgIHJldHVybiBTSEVLRUxfQ1VSUkVOQ1k7XG4gICAgY2FzZSA4NDA6XG4gICAgICByZXR1cm4gRE9MTEFSX0NVUlJFTkNZO1xuICAgIGNhc2UgOTc4OlxuICAgICAgcmV0dXJuIEVVUk9fQ1VSUkVOQ1k7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1lbW8oe1xuICBjb21tZW50cyxcbiAgZnVuZHNUcmFuc2ZlclJlY2VpdmVyT3JUcmFuc2ZlcixcbiAgZnVuZHNUcmFuc2ZlckNvbW1lbnQsXG59OiBQaWNrPFNjcmFwZWRUcmFuc2FjdGlvbiwgJ2NvbW1lbnRzJyB8ICdmdW5kc1RyYW5zZmVyUmVjZWl2ZXJPclRyYW5zZmVyJyB8ICdmdW5kc1RyYW5zZmVyQ29tbWVudCc+KSB7XG4gIGlmIChmdW5kc1RyYW5zZmVyUmVjZWl2ZXJPclRyYW5zZmVyKSB7XG4gICAgY29uc3QgbWVtbyA9IGNvbW1lbnRzID8gYCR7Y29tbWVudHN9ICR7ZnVuZHNUcmFuc2ZlclJlY2VpdmVyT3JUcmFuc2Zlcn1gIDogZnVuZHNUcmFuc2ZlclJlY2VpdmVyT3JUcmFuc2ZlcjtcbiAgICByZXR1cm4gZnVuZHNUcmFuc2ZlckNvbW1lbnQgPyBgJHttZW1vfTogJHtmdW5kc1RyYW5zZmVyQ29tbWVudH1gIDogbWVtbztcbiAgfVxuXG4gIHJldHVybiBjb21tZW50cztcbn1cblxuZnVuY3Rpb24gbWFwVHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IFNjcmFwZWRUcmFuc2FjdGlvbiwgb3B0aW9ucz86IFNjcmFwZXJPcHRpb25zKTogVHJhbnNhY3Rpb24ge1xuICBjb25zdCBpc1BlbmRpbmcgPSByYXdUcmFuc2FjdGlvbi5wYXltZW50RGF0ZSA9PT0gbnVsbDtcbiAgY29uc3QgcHJvY2Vzc2VkRGF0ZSA9IG1vbWVudChpc1BlbmRpbmcgPyByYXdUcmFuc2FjdGlvbi5wdXJjaGFzZURhdGUgOiByYXdUcmFuc2FjdGlvbi5wYXltZW50RGF0ZSkudG9JU09TdHJpbmcoKTtcbiAgY29uc3Qgc3RhdHVzID0gaXNQZW5kaW5nID8gVHJhbnNhY3Rpb25TdGF0dXNlcy5QZW5kaW5nIDogVHJhbnNhY3Rpb25TdGF0dXNlcy5Db21wbGV0ZWQ7XG5cbiAgY29uc3QgaW5zdGFsbG1lbnRzID0gZ2V0SW5zdGFsbG1lbnRzSW5mbyhyYXdUcmFuc2FjdGlvbi5jb21tZW50cyk7XG4gIGNvbnN0IGlkZW50aWZpZXIgPSBpbnN0YWxsbWVudHNcbiAgICA/IGAke3Jhd1RyYW5zYWN0aW9uLmRlYWxEYXRhPy5hcm59XyR7aW5zdGFsbG1lbnRzLm51bWJlcn1gXG4gICAgOiByYXdUcmFuc2FjdGlvbi5kZWFsRGF0YT8uYXJuO1xuXG4gIGNvbnN0IHJlc3VsdDogVHJhbnNhY3Rpb24gPSB7XG4gICAgdHlwZTogZ2V0VHJhbnNhY3Rpb25UeXBlKHJhd1RyYW5zYWN0aW9uLnBsYW5OYW1lLCByYXdUcmFuc2FjdGlvbi5wbGFuVHlwZUlkKSxcbiAgICBkYXRlOiBtb21lbnQocmF3VHJhbnNhY3Rpb24ucHVyY2hhc2VEYXRlKS50b0lTT1N0cmluZygpLFxuICAgIHByb2Nlc3NlZERhdGUsXG4gICAgb3JpZ2luYWxBbW91bnQ6IC1yYXdUcmFuc2FjdGlvbi5vcmlnaW5hbEFtb3VudCxcbiAgICBvcmlnaW5hbEN1cnJlbmN5OiByYXdUcmFuc2FjdGlvbi5vcmlnaW5hbEN1cnJlbmN5LFxuICAgIGNoYXJnZWRBbW91bnQ6IC1yYXdUcmFuc2FjdGlvbi5hY3R1YWxQYXltZW50QW1vdW50LFxuICAgIGNoYXJnZWRDdXJyZW5jeTogZ2V0Q2hhcmdlZEN1cnJlbmN5KHJhd1RyYW5zYWN0aW9uLnBheW1lbnRDdXJyZW5jeSksXG4gICAgZGVzY3JpcHRpb246IHJhd1RyYW5zYWN0aW9uLm1lcmNoYW50TmFtZS50cmltKCksXG4gICAgbWVtbzogZ2V0TWVtbyhyYXdUcmFuc2FjdGlvbiksXG4gICAgY2F0ZWdvcnk6IGNhdGVnb3JpZXMuZ2V0KHJhd1RyYW5zYWN0aW9uPy5jYXRlZ29yeUlkKSxcbiAgICBpbnN0YWxsbWVudHMsXG4gICAgaWRlbnRpZmllcixcbiAgICBzdGF0dXMsXG4gIH07XG5cbiAgaWYgKG9wdGlvbnM/LmluY2x1ZGVSYXdUcmFuc2FjdGlvbikge1xuICAgIHJlc3VsdC5yYXdUcmFuc2FjdGlvbiA9IGdldFJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5pbnRlcmZhY2UgU2NyYXBlZFRyYW5zYWN0aW9uc1Jlc3VsdCB7XG4gIHJlc3VsdD86IHtcbiAgICB0cmFuc2FjdGlvbnM6IFNjcmFwZWRUcmFuc2FjdGlvbltdO1xuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaFRyYW5zYWN0aW9uc0Zvck1vbnRoKHBhZ2U6IFBhZ2UsIG1vbnRoTW9tZW50OiBNb21lbnQsIG9wdGlvbnM/OiBTY3JhcGVyT3B0aW9ucykge1xuICBjb25zdCB1cmwgPSBnZXRUcmFuc2FjdGlvbnNVcmwobW9udGhNb21lbnQpO1xuXG4gIGNvbnN0IGRhdGEgPSBhd2FpdCBmZXRjaEdldFdpdGhpblBhZ2U8U2NyYXBlZFRyYW5zYWN0aW9uc1Jlc3VsdD4ocGFnZSwgdXJsKTtcbiAgY29uc3QgdHJhbnNhY3Rpb25zQnlBY2NvdW50OiBSZWNvcmQ8c3RyaW5nLCBUcmFuc2FjdGlvbltdPiA9IHt9O1xuXG4gIGlmICghZGF0YSB8fCAhZGF0YS5yZXN1bHQpIHJldHVybiB0cmFuc2FjdGlvbnNCeUFjY291bnQ7XG5cbiAgZGF0YS5yZXN1bHQudHJhbnNhY3Rpb25zXG4gICAgLy8gRmlsdGVyIG91dCBub24tdHJhbnNhY3Rpb25zIHdpdGhvdXQgYSBwbGFuIHR5cGUsIGUuZy4gc3VtbWFyeSByb3dzXG4gICAgLmZpbHRlcih0cmFuc2FjdGlvbiA9PiAhIXRyYW5zYWN0aW9uLnBsYW5OYW1lKVxuICAgIC5mb3JFYWNoKCh0cmFuc2FjdGlvbjogU2NyYXBlZFRyYW5zYWN0aW9uKSA9PiB7XG4gICAgICBpZiAoIXRyYW5zYWN0aW9uc0J5QWNjb3VudFt0cmFuc2FjdGlvbi5zaG9ydENhcmROdW1iZXJdKSB7XG4gICAgICAgIHRyYW5zYWN0aW9uc0J5QWNjb3VudFt0cmFuc2FjdGlvbi5zaG9ydENhcmROdW1iZXJdID0gW107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1hcHBlZFRyYW5zYWN0aW9uID0gbWFwVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24sIG9wdGlvbnMpO1xuICAgICAgdHJhbnNhY3Rpb25zQnlBY2NvdW50W3RyYW5zYWN0aW9uLnNob3J0Q2FyZE51bWJlcl0ucHVzaChtYXBwZWRUcmFuc2FjdGlvbik7XG4gICAgfSk7XG5cbiAgcmV0dXJuIHRyYW5zYWN0aW9uc0J5QWNjb3VudDtcbn1cblxuZnVuY3Rpb24gYWRkUmVzdWx0KGFsbFJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIFRyYW5zYWN0aW9uW10+LCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIFRyYW5zYWN0aW9uW10+KSB7XG4gIGNvbnN0IGNsb25lZFJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIFRyYW5zYWN0aW9uW10+ID0geyAuLi5hbGxSZXN1bHRzIH07XG4gIE9iamVjdC5rZXlzKHJlc3VsdCkuZm9yRWFjaChhY2NvdW50TnVtYmVyID0+IHtcbiAgICBpZiAoIWNsb25lZFJlc3VsdHNbYWNjb3VudE51bWJlcl0pIHtcbiAgICAgIGNsb25lZFJlc3VsdHNbYWNjb3VudE51bWJlcl0gPSBbXTtcbiAgICB9XG4gICAgY2xvbmVkUmVzdWx0c1thY2NvdW50TnVtYmVyXS5wdXNoKC4uLnJlc3VsdFthY2NvdW50TnVtYmVyXSk7XG4gIH0pO1xuICByZXR1cm4gY2xvbmVkUmVzdWx0cztcbn1cblxuZnVuY3Rpb24gcHJlcGFyZVRyYW5zYWN0aW9ucyhcbiAgdHhuczogVHJhbnNhY3Rpb25bXSxcbiAgc3RhcnRNb21lbnQ6IG1vbWVudC5Nb21lbnQsXG4gIGNvbWJpbmVJbnN0YWxsbWVudHM6IGJvb2xlYW4sXG4gIGVuYWJsZVRyYW5zYWN0aW9uc0ZpbHRlckJ5RGF0ZTogYm9vbGVhbixcbikge1xuICBsZXQgY2xvbmVkVHhucyA9IEFycmF5LmZyb20odHhucyk7XG4gIGlmICghY29tYmluZUluc3RhbGxtZW50cykge1xuICAgIGNsb25lZFR4bnMgPSBmaXhJbnN0YWxsbWVudHMoY2xvbmVkVHhucyk7XG4gIH1cbiAgY2xvbmVkVHhucyA9IHNvcnRUcmFuc2FjdGlvbnNCeURhdGUoY2xvbmVkVHhucyk7XG4gIGNsb25lZFR4bnMgPSBlbmFibGVUcmFuc2FjdGlvbnNGaWx0ZXJCeURhdGVcbiAgICA/IGZpbHRlck9sZFRyYW5zYWN0aW9ucyhjbG9uZWRUeG5zLCBzdGFydE1vbWVudCwgY29tYmluZUluc3RhbGxtZW50cyB8fCBmYWxzZSlcbiAgICA6IGNsb25lZFR4bnM7XG4gIHJldHVybiBjbG9uZWRUeG5zO1xufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaFRyYW5zYWN0aW9ucyhwYWdlOiBQYWdlLCBvcHRpb25zOiBTY3JhcGVyT3B0aW9ucykge1xuICBjb25zdCBmdXR1cmVNb250aHNUb1NjcmFwZSA9IG9wdGlvbnMuZnV0dXJlTW9udGhzVG9TY3JhcGUgPz8gMTtcbiAgY29uc3QgZGVmYXVsdFN0YXJ0TW9tZW50ID0gbW9tZW50KCkuc3VidHJhY3QoMSwgJ3llYXJzJyk7XG4gIGNvbnN0IHN0YXJ0TW9tZW50TGltaXQgPSBtb21lbnQoKS5zdWJ0cmFjdCg0LCAneWVhcnMnKTtcbiAgY29uc3Qgc3RhcnREYXRlID0gb3B0aW9ucy5zdGFydERhdGUgfHwgZGVmYXVsdFN0YXJ0TW9tZW50LnRvRGF0ZSgpO1xuICBjb25zdCBzdGFydE1vbWVudCA9IG1vbWVudC5tYXgoc3RhcnRNb21lbnRMaW1pdCwgbW9tZW50KHN0YXJ0RGF0ZSkpO1xuICBjb25zdCBhbGxNb250aHMgPSBnZXRBbGxNb250aE1vbWVudHMoc3RhcnRNb21lbnQsIGZ1dHVyZU1vbnRoc1RvU2NyYXBlKTtcblxuICBhd2FpdCBsb2FkQ2F0ZWdvcmllcyhwYWdlKTtcbiAgY29uc3QgaG9tZVBhZ2VDYXJkcyA9IGF3YWl0IGxvYWRIb21lUGFnZURhdGEocGFnZSk7XG5cbiAgbGV0IGFsbFJlc3VsdHM6IFJlY29yZDxzdHJpbmcsIFRyYW5zYWN0aW9uW10+ID0ge307XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYWxsTW9udGhzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZmV0Y2hUcmFuc2FjdGlvbnNGb3JNb250aChwYWdlLCBhbGxNb250aHNbaV0sIG9wdGlvbnMpO1xuICAgIGFsbFJlc3VsdHMgPSBhZGRSZXN1bHQoYWxsUmVzdWx0cywgcmVzdWx0KTtcbiAgfVxuXG4gIE9iamVjdC5rZXlzKGFsbFJlc3VsdHMpLmZvckVhY2goYWNjb3VudE51bWJlciA9PiB7XG4gICAgbGV0IHR4bnMgPSBhbGxSZXN1bHRzW2FjY291bnROdW1iZXJdO1xuICAgIHR4bnMgPSBwcmVwYXJlVHJhbnNhY3Rpb25zKFxuICAgICAgdHhucyxcbiAgICAgIHN0YXJ0TW9tZW50LFxuICAgICAgb3B0aW9ucy5jb21iaW5lSW5zdGFsbG1lbnRzIHx8IGZhbHNlLFxuICAgICAgb3B0aW9ucy5vdXRwdXREYXRhPy5lbmFibGVUcmFuc2FjdGlvbnNGaWx0ZXJCeURhdGUgPz8gdHJ1ZSxcbiAgICApO1xuICAgIGFsbFJlc3VsdHNbYWNjb3VudE51bWJlcl0gPSB0eG5zO1xuICB9KTtcblxuICByZXR1cm4geyBhbGxSZXN1bHRzLCBob21lUGFnZUNhcmRzIH07XG59XG5cbmZ1bmN0aW9uIGdldFBvc3NpYmxlTG9naW5SZXN1bHRzKHBhZ2U6IFBhZ2UpOiBQb3NzaWJsZUxvZ2luUmVzdWx0cyB7XG4gIGNvbnN0IHVybHM6IFBvc3NpYmxlTG9naW5SZXN1bHRzID0ge307XG4gIHVybHNbTG9naW5SZXN1bHRzLlN1Y2Nlc3NdID0gW1NVQ0NFU1NfVVJMXTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuQ2hhbmdlUGFzc3dvcmRdID0gW1BBU1NXT1JEX0VYUElSRURfVVJMXTtcbiAgdXJsc1tMb2dpblJlc3VsdHMuSW52YWxpZFBhc3N3b3JkXSA9IFtcbiAgICBhc3luYyAoKSA9PiB7XG4gICAgICByZXR1cm4gZWxlbWVudFByZXNlbnRPblBhZ2UocGFnZSwgSU5WQUxJRF9ERVRBSUxTX1NFTEVDVE9SKTtcbiAgICB9LFxuICBdO1xuICB1cmxzW0xvZ2luUmVzdWx0cy5Vbmtub3duRXJyb3JdID0gW1xuICAgIGFzeW5jICgpID0+IHtcbiAgICAgIHJldHVybiBlbGVtZW50UHJlc2VudE9uUGFnZShwYWdlLCBMT0dJTl9FUlJPUl9TRUxFQ1RPUik7XG4gICAgfSxcbiAgXTtcbiAgcmV0dXJuIHVybHM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxvZ2luRmllbGRzKGNyZWRlbnRpYWxzOiBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscykge1xuICByZXR1cm4gW1xuICAgIHsgc2VsZWN0b3I6ICcjdXNlci1uYW1lJywgdmFsdWU6IGNyZWRlbnRpYWxzLnVzZXJuYW1lIH0sXG4gICAgeyBzZWxlY3RvcjogJyNwYXNzd29yZCcsIHZhbHVlOiBjcmVkZW50aWFscy5wYXNzd29yZCB9LFxuICBdO1xufVxuXG50eXBlIFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzID0geyB1c2VybmFtZTogc3RyaW5nOyBwYXNzd29yZDogc3RyaW5nIH07XG5cbmNsYXNzIE1heFNjcmFwZXIgZXh0ZW5kcyBCYXNlU2NyYXBlcldpdGhCcm93c2VyPFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzPiB7XG4gIGdldExvZ2luT3B0aW9ucyhjcmVkZW50aWFsczogU2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHMpOiBMb2dpbk9wdGlvbnMge1xuICAgIHJldHVybiB7XG4gICAgICBsb2dpblVybDogTE9HSU5fVVJMLFxuICAgICAgZmllbGRzOiBjcmVhdGVMb2dpbkZpZWxkcyhjcmVkZW50aWFscyksXG4gICAgICBzdWJtaXRCdXR0b25TZWxlY3RvcjogJ2FwcC11c2VyLWxvZ2luLWZvcm0gLmdlbmVyYWwtYnV0dG9uLnNlbmQtbWUtY29kZScsXG4gICAgICBwcmVBY3Rpb246IGFzeW5jICgpID0+IHtcbiAgICAgICAgaWYgKGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKHRoaXMucGFnZSwgJyNjbG9zZVBvcHVwJykpIHtcbiAgICAgICAgICBhd2FpdCBjbGlja0J1dHRvbih0aGlzLnBhZ2UsICcjY2xvc2VQb3B1cCcpO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGNsaWNrQnV0dG9uKHRoaXMucGFnZSwgJy5wZXJzb25hbC1hcmVhID4gYS5nby10by1wZXJzb25hbC1hcmVhJyk7XG4gICAgICAgIGlmIChhd2FpdCBlbGVtZW50UHJlc2VudE9uUGFnZSh0aGlzLnBhZ2UsICcubG9naW4tbGluayNwcml2YXRlJykpIHtcbiAgICAgICAgICBhd2FpdCBjbGlja0J1dHRvbih0aGlzLnBhZ2UsICcubG9naW4tbGluayNwcml2YXRlJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVHJ5IHR3aWNlIGluIGNhc2UgaXQgY2FuJ3QgZmluZCBpdCB0aGUgZmlyc3QgdGltZVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZCh0aGlzLnBhZ2UsICcjbG9naW4tcGFzc3dvcmQtbGluaycsIHRydWUsIDEwMDAwKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgYXdhaXQgc2xlZXAoMTAwMCk7XG4gICAgICAgICAgYXdhaXQgd2FpdFVudGlsRWxlbWVudEZvdW5kKHRoaXMucGFnZSwgJyNsb2dpbi1wYXNzd29yZC1saW5rJywgdHJ1ZSwgMTAwMDApO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGNsaWNrQnV0dG9uKHRoaXMucGFnZSwgJyNsb2dpbi1wYXNzd29yZC1saW5rJyk7XG4gICAgICAgIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZCh0aGlzLnBhZ2UsICcjbG9naW4tcGFzc3dvcmQudGFiLXBhbmUuYWN0aXZlIGFwcC11c2VyLWxvZ2luLWZvcm0nLCB0cnVlKTtcbiAgICAgIH0sXG4gICAgICBjaGVja1JlYWRpbmVzczogYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQodGhpcy5wYWdlLCAnLnBlcnNvbmFsLWFyZWEgPiBhLmdvLXRvLXBlcnNvbmFsLWFyZWEnLCB0cnVlKTtcbiAgICAgIH0sXG4gICAgICBwb3N0QWN0aW9uOiBhc3luYyAoKSA9PiByZWRpcmVjdE9yRGlhbG9nKHRoaXMucGFnZSksXG4gICAgICBwb3NzaWJsZVJlc3VsdHM6IGdldFBvc3NpYmxlTG9naW5SZXN1bHRzKHRoaXMucGFnZSksXG4gICAgICB3YWl0VW50aWw6ICdkb21jb250ZW50bG9hZGVkJyxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgZmV0Y2hEYXRhKCkge1xuICAgIGNvbnN0IHsgYWxsUmVzdWx0cywgaG9tZVBhZ2VDYXJkcyB9ID0gYXdhaXQgZmV0Y2hUcmFuc2FjdGlvbnModGhpcy5wYWdlLCB0aGlzLm9wdGlvbnMpO1xuICAgIGNvbnN0IGFjY291bnRzOiBUcmFuc2FjdGlvbnNBY2NvdW50W10gPSBPYmplY3Qua2V5cyhhbGxSZXN1bHRzKS5tYXAoYWNjb3VudE51bWJlciA9PiB7XG4gICAgICBjb25zdCBjYXJkID0gaG9tZVBhZ2VDYXJkcy5nZXQoYWNjb3VudE51bWJlcik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhY2NvdW50TnVtYmVyLFxuICAgICAgICB0eG5zOiBhbGxSZXN1bHRzW2FjY291bnROdW1iZXJdLFxuICAgICAgICBiYWxhbmNlOiBjYXJkID8gZ2V0Q2FyZEJhbGFuY2UoY2FyZCkgOiB1bmRlZmluZWQsXG4gICAgICAgIGJhbGFuY2VEYXRlOiBjYXJkID8gZ2V0Q2FyZEJhbGFuY2VEYXRlKGNhcmQpIDogdW5kZWZpbmVkLFxuICAgICAgICBjYXJkRnJhbWU6IGNhcmQ/LkNyZWRpdExpbWl0ID8/IHVuZGVmaW5lZCxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgIGFjY291bnRzLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWF4U2NyYXBlcjtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUVBLElBQUFDLFVBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLE1BQUEsR0FBQUgsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFHLE1BQUEsR0FBQUgsT0FBQTtBQUNBLElBQUFJLHFCQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxNQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxXQUFBLEdBQUFOLE9BQUE7QUFDQSxJQUFBTyxh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