UNPKG

israeli-bank-scrapers-core

Version:

Provide scrapers for all major Israeli banks and credit card companies

386 lines 71.8 kB
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _moment = _interopRequireDefault(require("moment"));
var _debug = require("../helpers/debug");
var _elementsInteractions = require("../helpers/elements-interactions");
var _fetch = require("../helpers/fetch");
var _navigation = require("../helpers/navigation");
var _storage = require("../helpers/storage");
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 apiHeaders = {
  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36',
  Origin: 'https://digital-web.cal-online.co.il',
  Referer: 'https://digital-web.cal-online.co.il',
  'Accept-Language': 'he-IL,he;q=0.9,en-US;q=0.8,en;q=0.7',
  'Sec-Fetch-Site': 'same-site',
  'Sec-Fetch-Mode': 'cors',
  'Sec-Fetch-Dest': 'empty'
};
const LOGIN_URL = 'https://www.cal-online.co.il/';
const TRANSACTIONS_REQUEST_ENDPOINT = 'https://api.cal-online.co.il/Transactions/api/transactionsDetails/getCardTransactionsDetails';
const FRAMES_REQUEST_ENDPOINT = 'https://api.cal-online.co.il/Frames/api/Frames/GetFrameStatus';
const PENDING_TRANSACTIONS_REQUEST_ENDPOINT = 'https://api.cal-online.co.il/Transactions/api/approvals/getClearanceRequests';
const SSO_AUTHORIZATION_REQUEST_ENDPOINT = 'https://connect.cal-online.co.il/col-rest/calconnect/authentication/SSO';
const InvalidPasswordMessage = 'שם המשתמש או הסיסמה שהוזנו שגויים';
const ChangePasswordMessage = 'להחליף סיסמה';
const ChangePasswordSubtitle = 'הגיע הזמן לסיסמה חדשה';
const ChangePasswordUrl = '/change-password';
const debug = (0, _debug.getDebug)('visa-cal');
var TrnTypeCode = /*#__PURE__*/function (TrnTypeCode) {
  TrnTypeCode["regular"] = "5";
  TrnTypeCode["credit"] = "6";
  TrnTypeCode["installments"] = "8";
  TrnTypeCode["standingOrder"] = "9";
  return TrnTypeCode;
}(TrnTypeCode || {});
function isAuthModule(result) {
  return Boolean(result?.auth?.calConnectToken && String(result.auth.calConnectToken).trim());
}
function authModuleOrUndefined(result) {
  return isAuthModule(result) ? result : undefined;
}
function isPending(transaction) {
  return transaction.debCrdDate === undefined; // an arbitrary field that only appears in a completed transaction
}
function isCardTransactionDetails(result) {
  return result.result !== undefined;
}
function isCardPendingTransactionDetails(result) {
  return result.result !== undefined;
}
async function getLoginFrame(page) {
  let frame = null;
  debug('wait until login frame found');
  await (0, _waiting.waitUntil)(() => {
    frame = page.frames().find(f => f.url().includes('connect')) || null;
    return Promise.resolve(!!frame);
  }, 'wait for iframe with login form', 10000, 1000);
  if (!frame) {
    debug('failed to find login frame for 10 seconds');
    throw new Error('failed to extract login iframe');
  }
  return frame;
}
async function hasInvalidPasswordError(page) {
  const frame = await getLoginFrame(page);
  const errorFound = await (0, _elementsInteractions.elementPresentOnPage)(frame, 'div.general-error > div');
  const errorMessage = errorFound ? await (0, _elementsInteractions.pageEval)(frame, 'div.general-error > div', '', item => {
    return item.innerText;
  }) : '';
  return errorMessage === InvalidPasswordMessage;
}
async function hasChangePasswordForm(page) {
  // Check if any frame navigated to the change-password route
  const changePasswordFrame = page.frames().find(f => {
    const url = f.url();
    return url.includes('connect.cal-online.co.il') && url.includes(ChangePasswordUrl);
  });
  if (changePasswordFrame) {
    return true;
  }
  try {
    const frame = await getLoginFrame(page);

    // Check for the change-password Angular component
    if (await (0, _elementsInteractions.elementPresentOnPage)(frame, 'change-password')) {
      return true;
    }

    // Check for the change password title element
    if (await (0, _elementsInteractions.elementPresentOnPage)(frame, '.change-password-title')) {
      return true;
    }

    // Check for the change password subtitle text
    if (await (0, _elementsInteractions.elementPresentOnPage)(frame, '.change-password-subtitle')) {
      const subtitleText = await (0, _elementsInteractions.pageEval)(frame, '.change-password-subtitle', '', item => {
        return item.innerText.trim();
      });
      if (subtitleText.includes(ChangePasswordSubtitle)) {
        return true;
      }
    }

    // Legacy: check for the old .err-desc based change password message
    const errorFound = await (0, _elementsInteractions.elementPresentOnPage)(frame, '.err-desc');
    if (errorFound) {
      const errText = await (0, _elementsInteractions.pageEval)(frame, '.err-desc', '', item => {
        return item.innerText.trim();
      });
      return errText.includes(ChangePasswordMessage);
    }
  } catch (e) {
    debug('failed to check change password form in login frame: %s', e.message);
  }
  return false;
}
function getPossibleLoginResults() {
  debug('return possible login results');
  const urls = {
    [_baseScraperWithBrowser.LoginResults.Success]: [/dashboard/i],
    [_baseScraperWithBrowser.LoginResults.InvalidPassword]: [async options => {
      const page = options?.page;
      if (!page) {
        return false;
      }
      return hasInvalidPasswordError(page);
    }],
    // [LoginResults.AccountBlocked]: [], // TODO add when reaching this scenario
    [_baseScraperWithBrowser.LoginResults.ChangePassword]: [async options => {
      const page = options?.page;
      if (!page) {
        return false;
      }
      return hasChangePasswordForm(page);
    }]
  };
  return urls;
}
function createLoginFields(credentials) {
  debug('create login fields for username and password');
  return [{
    selector: '[formcontrolname="userName"]',
    value: credentials.username
  }, {
    selector: '[formcontrolname="password"]',
    value: credentials.password
  }];
}
function convertParsedDataToTransactions(data, pendingData, options) {
  const pendingTransactions = pendingData?.result ? pendingData.result.cardsList.flatMap(card => card.authDetalisList) : [];
  const bankAccounts = data.flatMap(monthData => monthData.result.bankAccounts);
  const regularDebitDays = bankAccounts.flatMap(accounts => accounts.debitDates);
  const immediateDebitDays = bankAccounts.flatMap(accounts => accounts.immidiateDebits.debitDays);
  const completedTransactions = [...regularDebitDays, ...immediateDebitDays].flatMap(debitDate => debitDate.transactions);
  const all = [...pendingTransactions, ...completedTransactions];
  return all.map(transaction => {
    const numOfPayments = isPending(transaction) ? transaction.numberOfPayments : transaction.numOfPayments;
    const installments = numOfPayments ? {
      number: isPending(transaction) ? 1 : transaction.curPaymentNum,
      total: numOfPayments
    } : undefined;
    const date = (0, _moment.default)(transaction.trnPurchaseDate);
    const chargedAmount = (isPending(transaction) ? transaction.trnAmt : transaction.amtBeforeConvAndIndex) * -1;
    const originalAmount = transaction.trnAmt * (transaction.trnTypeCode === TrnTypeCode.credit ? 1 : -1);
    const result = {
      identifier: !isPending(transaction) ? transaction.trnIntId : undefined,
      type: [TrnTypeCode.regular, TrnTypeCode.standingOrder].includes(transaction.trnTypeCode) ? _transactions2.TransactionTypes.Normal : _transactions2.TransactionTypes.Installments,
      status: isPending(transaction) ? _transactions2.TransactionStatuses.Pending : _transactions2.TransactionStatuses.Completed,
      date: installments ? date.add(installments.number - 1, 'month').toISOString() : date.toISOString(),
      processedDate: isPending(transaction) ? date.toISOString() : new Date(transaction.debCrdDate).toISOString(),
      originalAmount,
      originalCurrency: transaction.trnCurrencySymbol,
      chargedAmount,
      chargedCurrency: !isPending(transaction) ? transaction.debCrdCurrencySymbol : undefined,
      description: transaction.merchantName,
      memo: transaction.transTypeCommentDetails.toString(),
      category: transaction.branchCodeDesc
    };
    if (installments) {
      result.installments = installments;
    }
    if (options?.includeRawTransaction) {
      result.rawTransaction = (0, _transactions.getRawTransaction)(transaction);
    }
    return result;
  });
}
class VisaCalScraper extends _baseScraperWithBrowser.BaseScraperWithBrowser {
  authorization = undefined;
  openLoginPopup = async () => {
    debug('open login popup, wait until login button available');
    await (0, _elementsInteractions.waitUntilElementFound)(this.page, '#ccLoginDesktopBtn', true);
    debug('click on the login button');
    await (0, _elementsInteractions.clickButton)(this.page, '#ccLoginDesktopBtn');
    debug('get the frame that holds the login');
    const frame = await getLoginFrame(this.page);
    debug('wait until the password login tab header is available');
    await (0, _elementsInteractions.waitUntilElementFound)(frame, '#regular-login');
    debug('navigate to the password login tab');
    await (0, _elementsInteractions.clickButton)(frame, '#regular-login');
    debug('wait until the password login tab is active');
    await (0, _elementsInteractions.waitUntilElementFound)(frame, 'regular-login');
    return frame;
  };
  async getCards() {
    const initData = await (0, _waiting.waitUntil)(() => (0, _storage.getFromSessionStorage)(this.page, 'init'), 'get init data in session storage', 10000, 1000);
    if (!initData) {
      throw new Error('could not find "init" data in session storage');
    }
    return initData?.result.cards.map(({
      cardUniqueId,
      last4Digits
    }) => ({
      cardUniqueId,
      last4Digits
    }));
  }
  async getAuthorizationHeader() {
    if (!this.authorization) {
      debug('fetching authorization header');
      const authModule = await (0, _waiting.waitUntil)(async () => authModuleOrUndefined(await (0, _storage.getFromSessionStorage)(this.page, 'auth-module')), 'get authorization header with valid token in session storage', 10_000, 50);
      return `CALAuthScheme ${authModule.auth.calConnectToken}`;
    }
    return this.authorization;
  }
  async getXSiteId() {
    /*
      I don't know if the constant below will change in the feature.
      If so, use the next code:
       return this.page.evaluate(() => new Ut().xSiteId);
       To get the classname search for 'xSiteId' in the page source
      class Ut {
        constructor(_e, on, yn) {
            this.store = _e,
            this.config = on,
            this.eventBusService = yn,
            this.xSiteId = "09031987-273E-2311-906C-8AF85B17C8D9",
    */
    return Promise.resolve('09031987-273E-2311-906C-8AF85B17C8D9');
  }
  getLoginOptions(credentials) {
    this.authRequestPromise = this.page.waitForRequest(SSO_AUTHORIZATION_REQUEST_ENDPOINT, {
      timeout: 10_000
    }).catch(e => {
      debug('error while waiting for the token request', e);
      return undefined;
    });
    return {
      loginUrl: `${LOGIN_URL}`,
      fields: createLoginFields(credentials),
      submitButtonSelector: 'button[type="submit"]',
      possibleResults: getPossibleLoginResults(),
      checkReadiness: async () => (0, _elementsInteractions.waitUntilElementFound)(this.page, '#ccLoginDesktopBtn'),
      preAction: this.openLoginPopup,
      postAction: async () => {
        try {
          await (0, _navigation.waitForNavigation)(this.page);
          const currentUrl = await (0, _navigation.getCurrentUrl)(this.page);
          if (currentUrl.endsWith('site-tutorial')) {
            await (0, _elementsInteractions.clickButton)(this.page, 'button.btn-close');
          }
          const request = await this.authRequestPromise;
          this.authorization = String(request?.headers().authorization || '').trim();
        } catch (e) {
          const currentUrl = await (0, _navigation.getCurrentUrl)(this.page);
          if (currentUrl.endsWith('dashboard')) return;
          const requiresChangePassword = await hasChangePasswordForm(this.page);
          if (requiresChangePassword) return;
          throw e;
        }
      },
      userAgent: apiHeaders['User-Agent']
    };
  }
  async fetchCardData(card, startMoment, startDate, futureMonthsToScrape, Authorization, xSiteId) {
    debug('fetch frames (misgarot) for card %s', card.cardUniqueId);
    const frames = await (0, _fetch.fetchPost)(FRAMES_REQUEST_ENDPOINT, {
      cardsForFrameData: [{
        cardUniqueId: card.cardUniqueId
      }]
    }, {
      Authorization,
      'X-Site-Id': xSiteId,
      'Content-Type': 'application/json',
      ...apiHeaders
    });
    debug('frames response for card %s: %O', card.cardUniqueId, frames);

    // Look for card-level frame in both calIssuedCards and bankIssuedCards
    const bankIssuedFrame = frames.result?.bankIssuedCards?.cardLevelFrames?.find(f => f.cardUniqueId === card.cardUniqueId);
    const calIssuedFrame = frames.result?.calIssuedCards?.cardLevelFrames?.find(f => f.cardUniqueId === card.cardUniqueId);
    let frame;
    let cardType;
    let accountGroup;
    if (bankIssuedFrame) {
      frame = bankIssuedFrame;
      cardType = _transactions2.CardType.BankIssued;
      accountGroup = frames.result?.bankIssuedCards;
    } else {
      frame = calIssuedFrame;
      cardType = _transactions2.CardType.CompanyIssued;
      accountGroup = frames.result?.calIssuedCards;
    }
    debug('searching for frame for card %s, found: %O', card.cardUniqueId, frame);
    debug('card type for card %s: %s', card.cardUniqueId, cardType);
    const balanceDate = frame?.nextDebitDate ?? accountGroup?.nextTotalDebitDateForAccount;
    const finalMonthToFetchMoment = (0, _moment.default)().add(futureMonthsToScrape, 'month');
    const months = finalMonthToFetchMoment.diff(startMoment, 'months');
    const allMonthsData = [];
    debug(`fetch pending transactions for card ${card.cardUniqueId}`);
    let pendingData = await (0, _fetch.fetchPost)(PENDING_TRANSACTIONS_REQUEST_ENDPOINT, {
      cardUniqueIDArray: [card.cardUniqueId]
    }, {
      Authorization,
      'X-Site-Id': xSiteId,
      'Content-Type': 'application/json',
      ...apiHeaders
    });
    debug(`fetch completed transactions for card ${card.cardUniqueId}`);
    for (let i = 0; i <= months; i++) {
      const month = finalMonthToFetchMoment.clone().subtract(i, 'months');
      const monthData = await (0, _fetch.fetchPost)(TRANSACTIONS_REQUEST_ENDPOINT, {
        cardUniqueId: card.cardUniqueId,
        month: month.format('M'),
        year: month.format('YYYY')
      }, {
        Authorization,
        'X-Site-Id': xSiteId,
        'Content-Type': 'application/json',
        ...apiHeaders
      });
      if (monthData?.statusCode !== 1) throw new Error(`failed to fetch transactions for card ${card.last4Digits}. Message: ${monthData?.title || ''}`);
      if (!isCardTransactionDetails(monthData)) {
        throw new Error('monthData is not of type CardTransactionDetails');
      }
      allMonthsData.push(monthData);
    }
    if (pendingData?.statusCode !== 1 && pendingData?.statusCode !== 96) {
      debug(`failed to fetch pending transactions for card ${card.last4Digits}. Message: ${pendingData?.title || ''}`);
      pendingData = null;
    } else if (!isCardPendingTransactionDetails(pendingData)) {
      debug('pendingData is not of type CardTransactionDetails');
      pendingData = null;
    }
    const transactions = convertParsedDataToTransactions(allMonthsData, pendingData, this.options);
    debug('filter out old transactions');
    const txns = this.options.outputData?.enableTransactionsFilterByDate ?? true ? (0, _transactions.filterOldTransactions)(transactions, (0, _moment.default)(startDate), this.options.combineInstallments || false) : transactions;

    // Use card-level balance if available, otherwise fall back to account-level balance
    const balanceAmount = frame?.nextTotalDebit ?? accountGroup?.nextTotalDebitForAccount;
    const result = {
      txns,
      balance: balanceAmount != null ? -balanceAmount : undefined,
      balanceDate: balanceDate != null ? balanceDate : undefined,
      accountNumber: card.last4Digits,
      cardType,
      cardFrame: accountGroup?.frameLimitForCardAmount
    };
    return result;
  }
  async fetchData() {
    const defaultStartMoment = (0, _moment.default)().subtract(1, 'years').subtract(6, 'months').add(1, 'day');
    const startDate = this.options.startDate || defaultStartMoment.toDate();
    const startMoment = _moment.default.max(defaultStartMoment, (0, _moment.default)(startDate));
    debug(`fetch transactions starting ${startMoment.format()}`);
    const [cards, xSiteId, Authorization] = await Promise.all([this.getCards(), this.getXSiteId(), this.getAuthorizationHeader()]);
    const futureMonthsToScrape = this.options.futureMonthsToScrape ?? 1;
    const accounts = await Promise.all(cards.map(card => this.fetchCardData(card, startMoment, startDate, futureMonthsToScrape, Authorization, xSiteId)));
    debug('return the scraped accounts');
    debug(JSON.stringify(accounts, null, 2));
    return {
      success: true,
      accounts
    };
  }
}
var _default = exports.default = VisaCalScraper;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbW9tZW50IiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZGVidWciLCJfZWxlbWVudHNJbnRlcmFjdGlvbnMiLCJfZmV0Y2giLCJfbmF2aWdhdGlvbiIsIl9zdG9yYWdlIiwiX3RyYW5zYWN0aW9ucyIsIl93YWl0aW5nIiwiX3RyYW5zYWN0aW9uczIiLCJfYmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImFwaUhlYWRlcnMiLCJPcmlnaW4iLCJSZWZlcmVyIiwiTE9HSU5fVVJMIiwiVFJBTlNBQ1RJT05TX1JFUVVFU1RfRU5EUE9JTlQiLCJGUkFNRVNfUkVRVUVTVF9FTkRQT0lOVCIsIlBFTkRJTkdfVFJBTlNBQ1RJT05TX1JFUVVFU1RfRU5EUE9JTlQiLCJTU09fQVVUSE9SSVpBVElPTl9SRVFVRVNUX0VORFBPSU5UIiwiSW52YWxpZFBhc3N3b3JkTWVzc2FnZSIsIkNoYW5nZVBhc3N3b3JkTWVzc2FnZSIsIkNoYW5nZVBhc3N3b3JkU3VidGl0bGUiLCJDaGFuZ2VQYXNzd29yZFVybCIsImRlYnVnIiwiZ2V0RGVidWciLCJUcm5UeXBlQ29kZSIsImlzQXV0aE1vZHVsZSIsInJlc3VsdCIsIkJvb2xlYW4iLCJhdXRoIiwiY2FsQ29ubmVjdFRva2VuIiwiU3RyaW5nIiwidHJpbSIsImF1dGhNb2R1bGVPclVuZGVmaW5lZCIsInVuZGVmaW5lZCIsImlzUGVuZGluZyIsInRyYW5zYWN0aW9uIiwiZGViQ3JkRGF0ZSIsImlzQ2FyZFRyYW5zYWN0aW9uRGV0YWlscyIsImlzQ2FyZFBlbmRpbmdUcmFuc2FjdGlvbkRldGFpbHMiLCJnZXRMb2dpbkZyYW1lIiwicGFnZSIsImZyYW1lIiwid2FpdFVudGlsIiwiZnJhbWVzIiwiZmluZCIsImYiLCJ1cmwiLCJpbmNsdWRlcyIsIlByb21pc2UiLCJyZXNvbHZlIiwiRXJyb3IiLCJoYXNJbnZhbGlkUGFzc3dvcmRFcnJvciIsImVycm9yRm91bmQiLCJlbGVtZW50UHJlc2VudE9uUGFnZSIsImVycm9yTWVzc2FnZSIsInBhZ2VFdmFsIiwiaXRlbSIsImlubmVyVGV4dCIsImhhc0NoYW5nZVBhc3N3b3JkRm9ybSIsImNoYW5nZVBhc3N3b3JkRnJhbWUiLCJzdWJ0aXRsZVRleHQiLCJlcnJUZXh0IiwibWVzc2FnZSIsImdldFBvc3NpYmxlTG9naW5SZXN1bHRzIiwidXJscyIsIkxvZ2luUmVzdWx0cyIsIlN1Y2Nlc3MiLCJJbnZhbGlkUGFzc3dvcmQiLCJvcHRpb25zIiwiQ2hhbmdlUGFzc3dvcmQiLCJjcmVhdGVMb2dpbkZpZWxkcyIsImNyZWRlbnRpYWxzIiwic2VsZWN0b3IiLCJ2YWx1ZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJjb252ZXJ0UGFyc2VkRGF0YVRvVHJhbnNhY3Rpb25zIiwiZGF0YSIsInBlbmRpbmdEYXRhIiwicGVuZGluZ1RyYW5zYWN0aW9ucyIsImNhcmRzTGlzdCIsImZsYXRNYXAiLCJjYXJkIiwiYXV0aERldGFsaXNMaXN0IiwiYmFua0FjY291bnRzIiwibW9udGhEYXRhIiwicmVndWxhckRlYml0RGF5cyIsImFjY291bnRzIiwiZGViaXREYXRlcyIsImltbWVkaWF0ZURlYml0RGF5cyIsImltbWlkaWF0ZURlYml0cyIsImRlYml0RGF5cyIsImNvbXBsZXRlZFRyYW5zYWN0aW9ucyIsImRlYml0RGF0ZSIsInRyYW5zYWN0aW9ucyIsImFsbCIsIm1hcCIsIm51bU9mUGF5bWVudHMiLCJudW1iZXJPZlBheW1lbnRzIiwiaW5zdGFsbG1lbnRzIiwibnVtYmVyIiwiY3VyUGF5bWVudE51bSIsInRvdGFsIiwiZGF0ZSIsIm1vbWVudCIsInRyblB1cmNoYXNlRGF0ZSIsImNoYXJnZWRBbW91bnQiLCJ0cm5BbXQiLCJhbXRCZWZvcmVDb252QW5kSW5kZXgiLCJvcmlnaW5hbEFtb3VudCIsInRyblR5cGVDb2RlIiwiY3JlZGl0IiwiaWRlbnRpZmllciIsInRybkludElkIiwidHlwZSIsInJlZ3VsYXIiLCJzdGFuZGluZ09yZGVyIiwiVHJhbnNhY3Rpb25UeXBlcyIsIk5vcm1hbCIsIkluc3RhbGxtZW50cyIsInN0YXR1cyIsIlRyYW5zYWN0aW9uU3RhdHVzZXMiLCJQZW5kaW5nIiwiQ29tcGxldGVkIiwiYWRkIiwidG9JU09TdHJpbmciLCJwcm9jZXNzZWREYXRlIiwiRGF0ZSIsIm9yaWdpbmFsQ3VycmVuY3kiLCJ0cm5DdXJyZW5jeVN5bWJvbCIsImNoYXJnZWRDdXJyZW5jeSIsImRlYkNyZEN1cnJlbmN5U3ltYm9sIiwiZGVzY3JpcHRpb24iLCJtZXJjaGFudE5hbWUiLCJtZW1vIiwidHJhbnNUeXBlQ29tbWVudERldGFpbHMiLCJ0b1N0cmluZyIsImNhdGVnb3J5IiwiYnJhbmNoQ29kZURlc2MiLCJpbmNsdWRlUmF3VHJhbnNhY3Rpb24iLCJyYXdUcmFuc2FjdGlvbiIsImdldFJhd1RyYW5zYWN0aW9uIiwiVmlzYUNhbFNjcmFwZXIiLCJCYXNlU2NyYXBlcldpdGhCcm93c2VyIiwiYXV0aG9yaXphdGlvbiIsIm9wZW5Mb2dpblBvcHVwIiwid2FpdFVudGlsRWxlbWVudEZvdW5kIiwiY2xpY2tCdXR0b24iLCJnZXRDYXJkcyIsImluaXREYXRhIiwiZ2V0RnJvbVNlc3Npb25TdG9yYWdlIiwiY2FyZHMiLCJjYXJkVW5pcXVlSWQiLCJsYXN0NERpZ2l0cyIsImdldEF1dGhvcml6YXRpb25IZWFkZXIiLCJhdXRoTW9kdWxlIiwiZ2V0WFNpdGVJZCIsImdldExvZ2luT3B0aW9ucyIsImF1dGhSZXF1ZXN0UHJvbWlzZSIsIndhaXRGb3JSZXF1ZXN0IiwidGltZW91dCIsImNhdGNoIiwibG9naW5VcmwiLCJmaWVsZHMiLCJzdWJtaXRCdXR0b25TZWxlY3RvciIsInBvc3NpYmxlUmVzdWx0cyIsImNoZWNrUmVhZGluZXNzIiwicHJlQWN0aW9uIiwicG9zdEFjdGlvbiIsIndhaXRGb3JOYXZpZ2F0aW9uIiwiY3VycmVudFVybCIsImdldEN1cnJlbnRVcmwiLCJlbmRzV2l0aCIsInJlcXVlc3QiLCJoZWFkZXJzIiwicmVxdWlyZXNDaGFuZ2VQYXNzd29yZCIsInVzZXJBZ2VudCIsImZldGNoQ2FyZERhdGEiLCJzdGFydE1vbWVudCIsInN0YXJ0RGF0ZSIsImZ1dHVyZU1vbnRoc1RvU2NyYXBlIiwiQXV0aG9yaXphdGlvbiIsInhTaXRlSWQiLCJmZXRjaFBvc3QiLCJjYXJkc0ZvckZyYW1lRGF0YSIsImJhbmtJc3N1ZWRGcmFtZSIsImJhbmtJc3N1ZWRDYXJkcyIsImNhcmRMZXZlbEZyYW1lcyIsImNhbElzc3VlZEZyYW1lIiwiY2FsSXNzdWVkQ2FyZHMiLCJjYXJkVHlwZSIsImFjY291bnRHcm91cCIsIkNhcmRUeXBlIiwiQmFua0lzc3VlZCIsIkNvbXBhbnlJc3N1ZWQiLCJiYWxhbmNlRGF0ZSIsIm5leHREZWJpdERhdGUiLCJuZXh0VG90YWxEZWJpdERhdGVGb3JBY2NvdW50IiwiZmluYWxNb250aFRvRmV0Y2hNb21lbnQiLCJtb250aHMiLCJkaWZmIiwiYWxsTW9udGhzRGF0YSIsImNhcmRVbmlxdWVJREFycmF5IiwiaSIsIm1vbnRoIiwiY2xvbmUiLCJzdWJ0cmFjdCIsImZvcm1hdCIsInllYXIiLCJzdGF0dXNDb2RlIiwidGl0bGUiLCJwdXNoIiwidHhucyIsIm91dHB1dERhdGEiLCJlbmFibGVUcmFuc2FjdGlvbnNGaWx0ZXJCeURhdGUiLCJmaWx0ZXJPbGRUcmFuc2FjdGlvbnMiLCJjb21iaW5lSW5zdGFsbG1lbnRzIiwiYmFsYW5jZUFtb3VudCIsIm5leHRUb3RhbERlYml0IiwibmV4dFRvdGFsRGViaXRGb3JBY2NvdW50IiwiYmFsYW5jZSIsImFjY291bnROdW1iZXIiLCJjYXJkRnJhbWUiLCJmcmFtZUxpbWl0Rm9yQ2FyZEFtb3VudCIsImZldGNoRGF0YSIsImRlZmF1bHRTdGFydE1vbWVudCIsInRvRGF0ZSIsIm1heCIsIkpTT04iLCJzdHJpbmdpZnkiLCJzdWNjZXNzIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjcmFwZXJzL3Zpc2EtY2FsLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IHR5cGUgSFRUUFJlcXVlc3QsIHR5cGUgRnJhbWUsIHR5cGUgUGFnZSB9IGZyb20gJ3B1cHBldGVlci1jb3JlJztcbmltcG9ydCB7IGdldERlYnVnIH0gZnJvbSAnLi4vaGVscGVycy9kZWJ1Zyc7XG5pbXBvcnQgeyBjbGlja0J1dHRvbiwgZWxlbWVudFByZXNlbnRPblBhZ2UsIHBhZ2VFdmFsLCB3YWl0VW50aWxFbGVtZW50Rm91bmQgfSBmcm9tICcuLi9oZWxwZXJzL2VsZW1lbnRzLWludGVyYWN0aW9ucyc7XG5pbXBvcnQgeyBmZXRjaFBvc3QgfSBmcm9tICcuLi9oZWxwZXJzL2ZldGNoJztcbmltcG9ydCB7IGdldEN1cnJlbnRVcmwsIHdhaXRGb3JOYXZpZ2F0aW9uIH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IGdldEZyb21TZXNzaW9uU3RvcmFnZSB9IGZyb20gJy4uL2hlbHBlcnMvc3RvcmFnZSc7XG5pbXBvcnQgeyBmaWx0ZXJPbGRUcmFuc2FjdGlvbnMsIGdldFJhd1RyYW5zYWN0aW9uIH0gZnJvbSAnLi4vaGVscGVycy90cmFuc2FjdGlvbnMnO1xuaW1wb3J0IHsgd2FpdFVudGlsIH0gZnJvbSAnLi4vaGVscGVycy93YWl0aW5nJztcbmltcG9ydCB7XG4gIENhcmRUeXBlLFxuICBUcmFuc2FjdGlvblN0YXR1c2VzLFxuICBUcmFuc2FjdGlvblR5cGVzLFxuICB0eXBlIFRyYW5zYWN0aW9uLFxuICB0eXBlIFRyYW5zYWN0aW9uc0FjY291bnQsXG59IGZyb20gJy4uL3RyYW5zYWN0aW9ucyc7XG5pbXBvcnQgeyBCYXNlU2NyYXBlcldpdGhCcm93c2VyLCBMb2dpblJlc3VsdHMsIHR5cGUgTG9naW5PcHRpb25zIH0gZnJvbSAnLi9iYXNlLXNjcmFwZXItd2l0aC1icm93c2VyJztcbmltcG9ydCB7IHR5cGUgU2NyYXBlclNjcmFwaW5nUmVzdWx0LCB0eXBlIFNjcmFwZXJPcHRpb25zIH0gZnJvbSAnLi9pbnRlcmZhY2UnO1xuXG5jb25zdCBhcGlIZWFkZXJzID0ge1xuICAnVXNlci1BZ2VudCc6XG4gICAgJ01vemlsbGEvNS4wIChNYWNpbnRvc2g7IEludGVsIE1hYyBPUyBYIDEwXzE1XzcpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS8xNDIuMC4wLjAgU2FmYXJpLzUzNy4zNicsXG4gIE9yaWdpbjogJ2h0dHBzOi8vZGlnaXRhbC13ZWIuY2FsLW9ubGluZS5jby5pbCcsXG4gIFJlZmVyZXI6ICdodHRwczovL2RpZ2l0YWwtd2ViLmNhbC1vbmxpbmUuY28uaWwnLFxuICAnQWNjZXB0LUxhbmd1YWdlJzogJ2hlLUlMLGhlO3E9MC45LGVuLVVTO3E9MC44LGVuO3E9MC43JyxcbiAgJ1NlYy1GZXRjaC1TaXRlJzogJ3NhbWUtc2l0ZScsXG4gICdTZWMtRmV0Y2gtTW9kZSc6ICdjb3JzJyxcbiAgJ1NlYy1GZXRjaC1EZXN0JzogJ2VtcHR5Jyxcbn07XG5jb25zdCBMT0dJTl9VUkwgPSAnaHR0cHM6Ly93d3cuY2FsLW9ubGluZS5jby5pbC8nO1xuY29uc3QgVFJBTlNBQ1RJT05TX1JFUVVFU1RfRU5EUE9JTlQgPVxuICAnaHR0cHM6Ly9hcGkuY2FsLW9ubGluZS5jby5pbC9UcmFuc2FjdGlvbnMvYXBpL3RyYW5zYWN0aW9uc0RldGFpbHMvZ2V0Q2FyZFRyYW5zYWN0aW9uc0RldGFpbHMnO1xuY29uc3QgRlJBTUVTX1JFUVVFU1RfRU5EUE9JTlQgPSAnaHR0cHM6Ly9hcGkuY2FsLW9ubGluZS5jby5pbC9GcmFtZXMvYXBpL0ZyYW1lcy9HZXRGcmFtZVN0YXR1cyc7XG5jb25zdCBQRU5ESU5HX1RSQU5TQUNUSU9OU19SRVFVRVNUX0VORFBPSU5UID1cbiAgJ2h0dHBzOi8vYXBpLmNhbC1vbmxpbmUuY28uaWwvVHJhbnNhY3Rpb25zL2FwaS9hcHByb3ZhbHMvZ2V0Q2xlYXJhbmNlUmVxdWVzdHMnO1xuY29uc3QgU1NPX0FVVEhPUklaQVRJT05fUkVRVUVTVF9FTkRQT0lOVCA9ICdodHRwczovL2Nvbm5lY3QuY2FsLW9ubGluZS5jby5pbC9jb2wtcmVzdC9jYWxjb25uZWN0L2F1dGhlbnRpY2F0aW9uL1NTTyc7XG5cbmNvbnN0IEludmFsaWRQYXNzd29yZE1lc3NhZ2UgPSAn16nXnSDXlNee16nXqtee16kg15DXlSDXlNeh15nXodee15Qg16nXlNeV15bXoNeVINep15LXldeZ15nXnSc7XG5jb25zdCBDaGFuZ2VQYXNzd29yZE1lc3NhZ2UgPSAn15zXlNeX15zXmdejINeh15nXodee15QnO1xuY29uc3QgQ2hhbmdlUGFzc3dvcmRTdWJ0aXRsZSA9ICfXlNeS15nXoiDXlNeW157XnyDXnNeh15nXodee15Qg15fXk9ep15QnO1xuY29uc3QgQ2hhbmdlUGFzc3dvcmRVcmwgPSAnL2NoYW5nZS1wYXNzd29yZCc7XG5cbmNvbnN0IGRlYnVnID0gZ2V0RGVidWcoJ3Zpc2EtY2FsJyk7XG5cbmVudW0gVHJuVHlwZUNvZGUge1xuICByZWd1bGFyID0gJzUnLFxuICBjcmVkaXQgPSAnNicsXG4gIGluc3RhbGxtZW50cyA9ICc4JyxcbiAgc3RhbmRpbmdPcmRlciA9ICc5Jyxcbn1cblxuaW50ZXJmYWNlIFNjcmFwZWRUcmFuc2FjdGlvbiB7XG4gIGFtdEJlZm9yZUNvbnZBbmRJbmRleDogbnVtYmVyO1xuICBicmFuY2hDb2RlRGVzYzogc3RyaW5nO1xuICBjYXNoQWNjTWFuYWdlck5hbWU6IG51bGw7XG4gIGNhc2hBY2NvdW50TWFuYWdlcjogbnVsbDtcbiAgY2FzaEFjY291bnRUcm5BbXQ6IG51bWJlcjtcbiAgY2hhcmdlRXh0ZXJuYWxUb0NhcmRDb21tZW50OiBzdHJpbmc7XG4gIGNvbW1lbnRzOiBbXTtcbiAgY3VyUGF5bWVudE51bTogbnVtYmVyO1xuICBkZWJDcmRDdXJyZW5jeVN5bWJvbDogQ3VycmVuY3lTeW1ib2w7XG4gIGRlYkNyZERhdGU6IHN0cmluZztcbiAgZGViaXRTcHJlYWRJbmQ6IGJvb2xlYW47XG4gIGRpc2NvdW50QW1vdW50OiB1bmtub3duO1xuICBkaXNjb3VudFJlYXNvbjogdW5rbm93bjtcbiAgaW1tZWRpYXRlQ29tbWVudHM6IFtdO1xuICBpc0ltbWVkaWF0ZUNvbW1lbnRJbmQ6IGJvb2xlYW47XG4gIGlzSW1tZWRpYXRlSEhLSW5kOiBib29sZWFuO1xuICBpc01hcmdhcml0YTogYm9vbGVhbjtcbiAgaXNTcHJlYWRQYXltZW5zdEFicm9hZDogYm9vbGVhbjtcbiAgbGlua2VkQ29tbWVudHM6IFtdO1xuICBtZXJjaGFudEFkZHJlc3M6IHN0cmluZztcbiAgbWVyY2hhbnROYW1lOiBzdHJpbmc7XG4gIG1lcmNoYW50UGhvbmVObzogc3RyaW5nO1xuICBudW1PZlBheW1lbnRzOiBudW1iZXI7XG4gIG9uR29pbmdUcmFuc2FjdGlvbnNDb21tZW50OiBzdHJpbmc7XG4gIHJlZnVuZEluZDogYm9vbGVhbjtcbiAgcm91bmRpbmdBbW91bnQ6IHVua25vd247XG4gIHJvdW5kaW5nUmVhc29uOiB1bmtub3duO1xuICB0b2tlbkluZDogMDtcbiAgdG9rZW5OdW1iZXJQYXJ0NDogJyc7XG4gIHRyYW5zQ2FyZFByZXNlbnRJbmQ6IGJvb2xlYW47XG4gIHRyYW5zVHlwZUNvbW1lbnREZXRhaWxzOiBbXTtcbiAgdHJuQW10OiBudW1iZXI7XG4gIHRybkN1cnJlbmN5U3ltYm9sOiBDdXJyZW5jeVN5bWJvbDtcbiAgdHJuRXhhY1dheTogbnVtYmVyO1xuICB0cm5JbnRJZDogc3RyaW5nO1xuICB0cm5OdW1hcmV0b3I6IG51bWJlcjtcbiAgdHJuUHVyY2hhc2VEYXRlOiBzdHJpbmc7XG4gIHRyblR5cGU6IHN0cmluZztcbiAgdHJuVHlwZUNvZGU6IFRyblR5cGVDb2RlO1xuICB3YWxsZXRQcm92aWRlckNvZGU6IDA7XG4gIHdhbGxldFByb3ZpZGVyRGVzYzogJyc7XG4gIGVhcmx5UGF5bWVudEluZDogYm9vbGVhbjtcbn1cbmludGVyZmFjZSBTY3JhcGVkUGVuZGluZ1RyYW5zYWN0aW9uIHtcbiAgbWVyY2hhbnRJRDogc3RyaW5nO1xuICBtZXJjaGFudE5hbWU6IHN0cmluZztcbiAgdHJuUHVyY2hhc2VEYXRlOiBzdHJpbmc7XG4gIHdhbGxldFRyYW5JbmQ6IG51bWJlcjtcbiAgdHJhbnNhY3Rpb25zT3JpZ2luOiBudW1iZXI7XG4gIHRybkFtdDogbnVtYmVyO1xuICB0cGFBcHByb3ZhbEFtb3VudDogdW5rbm93bjtcbiAgdHJuQ3VycmVuY3lTeW1ib2w6IEN1cnJlbmN5U3ltYm9sO1xuICB0cm5UeXBlQ29kZTogVHJuVHlwZUNvZGU7XG4gIHRyblR5cGU6IHN0cmluZztcbiAgYnJhbmNoQ29kZURlc2M6IHN0cmluZztcbiAgdHJhbnNDYXJkUHJlc2VudEluZDogYm9vbGVhbjtcbiAgajVJbmRpY2F0b3I6IHN0cmluZztcbiAgbnVtYmVyT2ZQYXltZW50czogbnVtYmVyO1xuICBmaXJzdFBheW1lbnRBbW91bnQ6IG51bWJlcjtcbiAgdHJhbnNUeXBlQ29tbWVudERldGFpbHM6IFtdO1xufVxuaW50ZXJmYWNlIEluaXRSZXNwb25zZSB7XG4gIHJlc3VsdDoge1xuICAgIGNhcmRzOiB7XG4gICAgICBjYXJkVW5pcXVlSWQ6IHN0cmluZztcbiAgICAgIGxhc3Q0RGlnaXRzOiBzdHJpbmc7XG4gICAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICAgIH1bXTtcbiAgfTtcbn1cbnR5cGUgQ3VycmVuY3lTeW1ib2wgPSBzdHJpbmc7XG5pbnRlcmZhY2UgQ2FyZFRyYW5zYWN0aW9uRGV0YWlsc0Vycm9yIHtcbiAgdGl0bGU6IHN0cmluZztcbiAgc3RhdHVzQ29kZTogbnVtYmVyO1xufVxuaW50ZXJmYWNlIENhcmRUcmFuc2FjdGlvbkRldGFpbHMgZXh0ZW5kcyBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzRXJyb3Ige1xuICByZXN1bHQ6IHtcbiAgICBiYW5rQWNjb3VudHM6IHtcbiAgICAgIGJhbmtBY2NvdW50TnVtOiBzdHJpbmc7XG4gICAgICBiYW5rTmFtZTogc3RyaW5nO1xuICAgICAgY2hvaWNlRXh0ZXJuYWxUcmFuc2FjdGlvbnM6IGFueTtcbiAgICAgIGN1cnJlbnRCYW5rQWNjb3VudEluZDogYm9vbGVhbjtcbiAgICAgIGRlYml0RGF0ZXM6IHtcbiAgICAgICAgYmFza2V0QW1vdW50Q29tbWVudDogdW5rbm93bjtcbiAgICAgICAgY2hvaWNlSEhLRGViaXQ6IG51bWJlcjtcbiAgICAgICAgZGF0ZTogc3RyaW5nO1xuICAgICAgICBkZWJpdFJlYXNvbjogdW5rbm93bjtcbiAgICAgICAgZml4RGViaXRBbW91bnQ6IG51bWJlcjtcbiAgICAgICAgZnJvbVB1cmNoYXNlRGF0ZTogc3RyaW5nO1xuICAgICAgICBpc0Nob2ljZVJlcGFpbWVudDogYm9vbGVhbjtcbiAgICAgICAgdG9QdXJjaGFzZURhdGU6IHN0cmluZztcbiAgICAgICAgdG90YWxCYXNrZXRBbW91bnQ6IG51bWJlcjtcbiAgICAgICAgdG90YWxEZWJpdHM6IHtcbiAgICAgICAgICBjdXJyZW5jeVN5bWJvbDogQ3VycmVuY3lTeW1ib2w7XG4gICAgICAgICAgYW1vdW50OiBudW1iZXI7XG4gICAgICAgIH1bXTtcbiAgICAgICAgdHJhbnNhY3Rpb25zOiBTY3JhcGVkVHJhbnNhY3Rpb25bXTtcbiAgICAgIH1bXTtcbiAgICAgIGltbWlkaWF0ZURlYml0czogeyB0b3RhbERlYml0czogW107IGRlYml0RGF5czogW10gfTtcbiAgICB9W107XG4gICAgYmxvY2tlZENhcmRJbmQ6IGJvb2xlYW47XG4gIH07XG4gIHN0YXR1c0NvZGU6IDE7XG4gIHN0YXR1c0Rlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIHN0YXR1c1RpdGxlOiBzdHJpbmc7XG59XG5pbnRlcmZhY2UgQ2FyZFBlbmRpbmdUcmFuc2FjdGlvbkRldGFpbHMgZXh0ZW5kcyBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzRXJyb3Ige1xuICByZXN1bHQ6IHtcbiAgICBjYXJkc0xpc3Q6IHtcbiAgICAgIGNhcmRVbmlxdWVJRDogc3RyaW5nO1xuICAgICAgYXV0aERldGFsaXNMaXN0OiBTY3JhcGVkUGVuZGluZ1RyYW5zYWN0aW9uW107XG4gICAgfVtdO1xuICB9O1xuICBzdGF0dXNDb2RlOiAxO1xuICBzdGF0dXNEZXNjcmlwdGlvbjogc3RyaW5nO1xuICBzdGF0dXNUaXRsZTogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQ2FyZExldmVsRnJhbWUge1xuICBjYXJkVW5pcXVlSWQ6IHN0cmluZztcbiAgbmV4dFRvdGFsRGViaXQ/OiBudW1iZXI7XG4gIG5leHREZWJpdERhdGU/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBJc3N1ZWRDYXJkc0dyb3VwIHtcbiAgbmV4dFRvdGFsRGViaXRGb3JBY2NvdW50PzogbnVtYmVyO1xuICBuZXh0VG90YWxEZWJpdERhdGVGb3JBY2NvdW50Pzogc3RyaW5nIHwgbnVsbDtcbiAgZnJhbWVMaW1pdEZvckNhcmRBbW91bnQ/OiBudW1iZXI7XG4gIGNhcmRMZXZlbEZyYW1lcz86IENhcmRMZXZlbEZyYW1lW107XG59XG5cbmludGVyZmFjZSBGcmFtZXNSZXNwb25zZSB7XG4gIHJlc3VsdD86IHtcbiAgICBjYWxJc3N1ZWRDYXJkcz86IElzc3VlZENhcmRzR3JvdXA7XG4gICAgYmFua0lzc3VlZENhcmRzPzogSXNzdWVkQ2FyZHNHcm91cDtcbiAgfTtcbn1cblxuaW50ZXJmYWNlIEF1dGhNb2R1bGUge1xuICBhdXRoOiB7XG4gICAgY2FsQ29ubmVjdFRva2VuOiBzdHJpbmcgfCBudWxsO1xuICB9O1xufVxuXG5mdW5jdGlvbiBpc0F1dGhNb2R1bGUocmVzdWx0OiBhbnkpOiByZXN1bHQgaXMgQXV0aE1vZHVsZSB7XG4gIHJldHVybiBCb29sZWFuKHJlc3VsdD8uYXV0aD8uY2FsQ29ubmVjdFRva2VuICYmIFN0cmluZyhyZXN1bHQuYXV0aC5jYWxDb25uZWN0VG9rZW4pLnRyaW0oKSk7XG59XG5cbmZ1bmN0aW9uIGF1dGhNb2R1bGVPclVuZGVmaW5lZChyZXN1bHQ6IGFueSk6IEF1dGhNb2R1bGUgfCB1bmRlZmluZWQge1xuICByZXR1cm4gaXNBdXRoTW9kdWxlKHJlc3VsdCkgPyByZXN1bHQgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGlzUGVuZGluZyhcbiAgdHJhbnNhY3Rpb246IFNjcmFwZWRUcmFuc2FjdGlvbiB8IFNjcmFwZWRQZW5kaW5nVHJhbnNhY3Rpb24sXG4pOiB0cmFuc2FjdGlvbiBpcyBTY3JhcGVkUGVuZGluZ1RyYW5zYWN0aW9uIHtcbiAgcmV0dXJuICh0cmFuc2FjdGlvbiBhcyBTY3JhcGVkVHJhbnNhY3Rpb24pLmRlYkNyZERhdGUgPT09IHVuZGVmaW5lZDsgLy8gYW4gYXJiaXRyYXJ5IGZpZWxkIHRoYXQgb25seSBhcHBlYXJzIGluIGEgY29tcGxldGVkIHRyYW5zYWN0aW9uXG59XG5cbmZ1bmN0aW9uIGlzQ2FyZFRyYW5zYWN0aW9uRGV0YWlscyhcbiAgcmVzdWx0OiBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzIHwgQ2FyZFRyYW5zYWN0aW9uRGV0YWlsc0Vycm9yLFxuKTogcmVzdWx0IGlzIENhcmRUcmFuc2FjdGlvbkRldGFpbHMge1xuICByZXR1cm4gKHJlc3VsdCBhcyBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzKS5yZXN1bHQgIT09IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gaXNDYXJkUGVuZGluZ1RyYW5zYWN0aW9uRGV0YWlscyhcbiAgcmVzdWx0OiBDYXJkUGVuZGluZ1RyYW5zYWN0aW9uRGV0YWlscyB8IENhcmRUcmFuc2FjdGlvbkRldGFpbHNFcnJvcixcbik6IHJlc3VsdCBpcyBDYXJkUGVuZGluZ1RyYW5zYWN0aW9uRGV0YWlscyB7XG4gIHJldHVybiAocmVzdWx0IGFzIENhcmRQZW5kaW5nVHJhbnNhY3Rpb25EZXRhaWxzKS5yZXN1bHQgIT09IHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0TG9naW5GcmFtZShwYWdlOiBQYWdlKSB7XG4gIGxldCBmcmFtZTogRnJhbWUgfCBudWxsID0gbnVsbDtcbiAgZGVidWcoJ3dhaXQgdW50aWwgbG9naW4gZnJhbWUgZm91bmQnKTtcbiAgYXdhaXQgd2FpdFVudGlsKFxuICAgICgpID0+IHtcbiAgICAgIGZyYW1lID0gcGFnZS5mcmFtZXMoKS5maW5kKGYgPT4gZi51cmwoKS5pbmNsdWRlcygnY29ubmVjdCcpKSB8fCBudWxsO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSghIWZyYW1lKTtcbiAgICB9LFxuICAgICd3YWl0IGZvciBpZnJhbWUgd2l0aCBsb2dpbiBmb3JtJyxcbiAgICAxMDAwMCxcbiAgICAxMDAwLFxuICApO1xuXG4gIGlmICghZnJhbWUpIHtcbiAgICBkZWJ1ZygnZmFpbGVkIHRvIGZpbmQgbG9naW4gZnJhbWUgZm9yIDEwIHNlY29uZHMnKTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZhaWxlZCB0byBleHRyYWN0IGxvZ2luIGlmcmFtZScpO1xuICB9XG5cbiAgcmV0dXJuIGZyYW1lO1xufVxuXG5hc3luYyBmdW5jdGlvbiBoYXNJbnZhbGlkUGFzc3dvcmRFcnJvcihwYWdlOiBQYWdlKSB7XG4gIGNvbnN0IGZyYW1lID0gYXdhaXQgZ2V0TG9naW5GcmFtZShwYWdlKTtcbiAgY29uc3QgZXJyb3JGb3VuZCA9IGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKGZyYW1lLCAnZGl2LmdlbmVyYWwtZXJyb3IgPiBkaXYnKTtcbiAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3JGb3VuZFxuICAgID8gYXdhaXQgcGFnZUV2YWwoZnJhbWUsICdkaXYuZ2VuZXJhbC1lcnJvciA+IGRpdicsICcnLCBpdGVtID0+IHtcbiAgICAgICAgcmV0dXJuIChpdGVtIGFzIEhUTUxEaXZFbGVtZW50KS5pbm5lclRleHQ7XG4gICAgICB9KVxuICAgIDogJyc7XG4gIHJldHVybiBlcnJvck1lc3NhZ2UgPT09IEludmFsaWRQYXNzd29yZE1lc3NhZ2U7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhc0NoYW5nZVBhc3N3b3JkRm9ybShwYWdlOiBQYWdlKSB7XG4gIC8vIENoZWNrIGlmIGFueSBmcmFtZSBuYXZpZ2F0ZWQgdG8gdGhlIGNoYW5nZS1wYXNzd29yZCByb3V0ZVxuICBjb25zdCBjaGFuZ2VQYXNzd29yZEZyYW1lID0gcGFnZS5mcmFtZXMoKS5maW5kKGYgPT4ge1xuICAgIGNvbnN0IHVybCA9IGYudXJsKCk7XG4gICAgcmV0dXJuIHVybC5pbmNsdWRlcygnY29ubmVjdC5jYWwtb25saW5lLmNvLmlsJykgJiYgdXJsLmluY2x1ZGVzKENoYW5nZVBhc3N3b3JkVXJsKTtcbiAgfSk7XG4gIGlmIChjaGFuZ2VQYXNzd29yZEZyYW1lKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICB0cnkge1xuICAgIGNvbnN0IGZyYW1lID0gYXdhaXQgZ2V0TG9naW5GcmFtZShwYWdlKTtcblxuICAgIC8vIENoZWNrIGZvciB0aGUgY2hhbmdlLXBhc3N3b3JkIEFuZ3VsYXIgY29tcG9uZW50XG4gICAgaWYgKGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKGZyYW1lLCAnY2hhbmdlLXBhc3N3b3JkJykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciB0aGUgY2hhbmdlIHBhc3N3b3JkIHRpdGxlIGVsZW1lbnRcbiAgICBpZiAoYXdhaXQgZWxlbWVudFByZXNlbnRPblBhZ2UoZnJhbWUsICcuY2hhbmdlLXBhc3N3b3JkLXRpdGxlJykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGZvciB0aGUgY2hhbmdlIHBhc3N3b3JkIHN1YnRpdGxlIHRleHRcbiAgICBpZiAoYXdhaXQgZWxlbWVudFByZXNlbnRPblBhZ2UoZnJhbWUsICcuY2hhbmdlLXBhc3N3b3JkLXN1YnRpdGxlJykpIHtcbiAgICAgIGNvbnN0IHN1YnRpdGxlVGV4dCA9IGF3YWl0IHBhZ2VFdmFsKGZyYW1lLCAnLmNoYW5nZS1wYXNzd29yZC1zdWJ0aXRsZScsICcnLCBpdGVtID0+IHtcbiAgICAgICAgcmV0dXJuIChpdGVtIGFzIEhUTUxFbGVtZW50KS5pbm5lclRleHQudHJpbSgpO1xuICAgICAgfSk7XG4gICAgICBpZiAoc3VidGl0bGVUZXh0LmluY2x1ZGVzKENoYW5nZVBhc3N3b3JkU3VidGl0bGUpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIExlZ2FjeTogY2hlY2sgZm9yIHRoZSBvbGQgLmVyci1kZXNjIGJhc2VkIGNoYW5nZSBwYXNzd29yZCBtZXNzYWdlXG4gICAgY29uc3QgZXJyb3JGb3VuZCA9IGF3YWl0IGVsZW1lbnRQcmVzZW50T25QYWdlKGZyYW1lLCAnLmVyci1kZXNjJyk7XG4gICAgaWYgKGVycm9yRm91bmQpIHtcbiAgICAgIGNvbnN0IGVyclRleHQgPSBhd2FpdCBwYWdlRXZhbChmcmFtZSwgJy5lcnItZGVzYycsICcnLCBpdGVtID0+IHtcbiAgICAgICAgcmV0dXJuIChpdGVtIGFzIEhUTUxFbGVtZW50KS5pbm5lclRleHQudHJpbSgpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gZXJyVGV4dC5pbmNsdWRlcyhDaGFuZ2VQYXNzd29yZE1lc3NhZ2UpO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGRlYnVnKCdmYWlsZWQgdG8gY2hlY2sgY2hhbmdlIHBhc3N3b3JkIGZvcm0gaW4gbG9naW4gZnJhbWU6ICVzJywgKGUgYXMgRXJyb3IpLm1lc3NhZ2UpO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZ2V0UG9zc2libGVMb2dpblJlc3VsdHMoKSB7XG4gIGRlYnVnKCdyZXR1cm4gcG9zc2libGUgbG9naW4gcmVzdWx0cycpO1xuICBjb25zdCB1cmxzOiBMb2dpbk9wdGlvbnNbJ3Bvc3NpYmxlUmVzdWx0cyddID0ge1xuICAgIFtMb2dpblJlc3VsdHMuU3VjY2Vzc106IFsvZGFzaGJvYXJkL2ldLFxuICAgIFtMb2dpblJlc3VsdHMuSW52YWxpZFBhc3N3b3JkXTogW1xuICAgICAgYXN5bmMgKG9wdGlvbnM/OiB7IHBhZ2U/OiBQYWdlIH0pID0+IHtcbiAgICAgICAgY29uc3QgcGFnZSA9IG9wdGlvbnM/LnBhZ2U7XG4gICAgICAgIGlmICghcGFnZSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGFzSW52YWxpZFBhc3N3b3JkRXJyb3IocGFnZSk7XG4gICAgICB9LFxuICAgIF0sXG4gICAgLy8gW0xvZ2luUmVzdWx0cy5BY2NvdW50QmxvY2tlZF06IFtdLCAvLyBUT0RPIGFkZCB3aGVuIHJlYWNoaW5nIHRoaXMgc2NlbmFyaW9cbiAgICBbTG9naW5SZXN1bHRzLkNoYW5nZVBhc3N3b3JkXTogW1xuICAgICAgYXN5bmMgKG9wdGlvbnM/OiB7IHBhZ2U/OiBQYWdlIH0pID0+IHtcbiAgICAgICAgY29uc3QgcGFnZSA9IG9wdGlvbnM/LnBhZ2U7XG4gICAgICAgIGlmICghcGFnZSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGFzQ2hhbmdlUGFzc3dvcmRGb3JtKHBhZ2UpO1xuICAgICAgfSxcbiAgICBdLFxuICB9O1xuICByZXR1cm4gdXJscztcbn1cblxuZnVuY3Rpb24gY3JlYXRlTG9naW5GaWVsZHMoY3JlZGVudGlhbHM6IFNjcmFwZXJTcGVjaWZpY0NyZWRlbnRpYWxzKSB7XG4gIGRlYnVnKCdjcmVhdGUgbG9naW4gZmllbGRzIGZvciB1c2VybmFtZSBhbmQgcGFzc3dvcmQnKTtcbiAgcmV0dXJuIFtcbiAgICB7IHNlbGVjdG9yOiAnW2Zvcm1jb250cm9sbmFtZT1cInVzZXJOYW1lXCJdJywgdmFsdWU6IGNyZWRlbnRpYWxzLnVzZXJuYW1lIH0sXG4gICAgeyBzZWxlY3RvcjogJ1tmb3JtY29udHJvbG5hbWU9XCJwYXNzd29yZFwiXScsIHZhbHVlOiBjcmVkZW50aWFscy5wYXNzd29yZCB9LFxuICBdO1xufVxuXG5mdW5jdGlvbiBjb252ZXJ0UGFyc2VkRGF0YVRvVHJhbnNhY3Rpb25zKFxuICBkYXRhOiBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzW10sXG4gIHBlbmRpbmdEYXRhPzogQ2FyZFBlbmRpbmdUcmFuc2FjdGlvbkRldGFpbHMgfCBudWxsLFxuICBvcHRpb25zPzogU2NyYXBlck9wdGlvbnMsXG4pOiBUcmFuc2FjdGlvbltdIHtcbiAgY29uc3QgcGVuZGluZ1RyYW5zYWN0aW9ucyA9IHBlbmRpbmdEYXRhPy5yZXN1bHRcbiAgICA/IHBlbmRpbmdEYXRhLnJlc3VsdC5jYXJkc0xpc3QuZmxhdE1hcChjYXJkID0+IGNhcmQuYXV0aERldGFsaXNMaXN0KVxuICAgIDogW107XG5cbiAgY29uc3QgYmFua0FjY291bnRzID0gZGF0YS5mbGF0TWFwKG1vbnRoRGF0YSA9PiBtb250aERhdGEucmVzdWx0LmJhbmtBY2NvdW50cyk7XG4gIGNvbnN0IHJlZ3VsYXJEZWJpdERheXMgPSBiYW5rQWNjb3VudHMuZmxhdE1hcChhY2NvdW50cyA9PiBhY2NvdW50cy5kZWJpdERhdGVzKTtcbiAgY29uc3QgaW1tZWRpYXRlRGViaXREYXlzID0gYmFua0FjY291bnRzLmZsYXRNYXAoYWNjb3VudHMgPT4gYWNjb3VudHMuaW1taWRpYXRlRGViaXRzLmRlYml0RGF5cyk7XG4gIGNvbnN0IGNvbXBsZXRlZFRyYW5zYWN0aW9ucyA9IFsuLi5yZWd1bGFyRGViaXREYXlzLCAuLi5pbW1lZGlhdGVEZWJpdERheXNdLmZsYXRNYXAoXG4gICAgZGViaXREYXRlID0+IGRlYml0RGF0ZS50cmFuc2FjdGlvbnMsXG4gICk7XG5cbiAgY29uc3QgYWxsOiAoU2NyYXBlZFRyYW5zYWN0aW9uIHwgU2NyYXBlZFBlbmRpbmdUcmFuc2FjdGlvbilbXSA9IFsuLi5wZW5kaW5nVHJhbnNhY3Rpb25zLCAuLi5jb21wbGV0ZWRUcmFuc2FjdGlvbnNdO1xuXG4gIHJldHVybiBhbGwubWFwKHRyYW5zYWN0aW9uID0+IHtcbiAgICBjb25zdCBudW1PZlBheW1lbnRzID0gaXNQZW5kaW5nKHRyYW5zYWN0aW9uKSA/IHRyYW5zYWN0aW9uLm51bWJlck9mUGF5bWVudHMgOiB0cmFuc2FjdGlvbi5udW1PZlBheW1lbnRzO1xuICAgIGNvbnN0IGluc3RhbGxtZW50cyA9IG51bU9mUGF5bWVudHNcbiAgICAgID8ge1xuICAgICAgICAgIG51bWJlcjogaXNQZW5kaW5nKHRyYW5zYWN0aW9uKSA/IDEgOiB0cmFuc2FjdGlvbi5jdXJQYXltZW50TnVtLFxuICAgICAgICAgIHRvdGFsOiBudW1PZlBheW1lbnRzLFxuICAgICAgICB9XG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGRhdGUgPSBtb21lbnQodHJhbnNhY3Rpb24udHJuUHVyY2hhc2VEYXRlKTtcblxuICAgIGNvbnN0IGNoYXJnZWRBbW91bnQgPSAoaXNQZW5kaW5nKHRyYW5zYWN0aW9uKSA/IHRyYW5zYWN0aW9uLnRybkFtdCA6IHRyYW5zYWN0aW9uLmFtdEJlZm9yZUNvbnZBbmRJbmRleCkgKiAtMTtcbiAgICBjb25zdCBvcmlnaW5hbEFtb3VudCA9IHRyYW5zYWN0aW9uLnRybkFtdCAqICh0cmFuc2FjdGlvbi50cm5UeXBlQ29kZSA9PT0gVHJuVHlwZUNvZGUuY3JlZGl0ID8gMSA6IC0xKTtcblxuICAgIGNvbnN0IHJlc3VsdDogVHJhbnNhY3Rpb24gPSB7XG4gICAgICBpZGVudGlmaWVyOiAhaXNQZW5kaW5nKHRyYW5zYWN0aW9uKSA/IHRyYW5zYWN0aW9uLnRybkludElkIDogdW5kZWZpbmVkLFxuICAgICAgdHlwZTogW1RyblR5cGVDb2RlLnJlZ3VsYXIsIFRyblR5cGVDb2RlLnN0YW5kaW5nT3JkZXJdLmluY2x1ZGVzKHRyYW5zYWN0aW9uLnRyblR5cGVDb2RlKVxuICAgICAgICA/IFRyYW5zYWN0aW9uVHlwZXMuTm9ybWFsXG4gICAgICAgIDogVHJhbnNhY3Rpb25UeXBlcy5JbnN0YWxsbWVudHMsXG4gICAgICBzdGF0dXM6IGlzUGVuZGluZyh0cmFuc2FjdGlvbikgPyBUcmFuc2FjdGlvblN0YXR1c2VzLlBlbmRpbmcgOiBUcmFuc2FjdGlvblN0YXR1c2VzLkNvbXBsZXRlZCxcbiAgICAgIGRhdGU6IGluc3RhbGxtZW50cyA/IGRhdGUuYWRkKGluc3RhbGxtZW50cy5udW1iZXIgLSAxLCAnbW9udGgnKS50b0lTT1N0cmluZygpIDogZGF0ZS50b0lTT1N0cmluZygpLFxuICAgICAgcHJvY2Vzc2VkRGF0ZTogaXNQZW5kaW5nKHRyYW5zYWN0aW9uKSA/IGRhdGUudG9JU09TdHJpbmcoKSA6IG5ldyBEYXRlKHRyYW5zYWN0aW9uLmRlYkNyZERhdGUpLnRvSVNPU3RyaW5nKCksXG4gICAgICBvcmlnaW5hbEFtb3VudCxcbiAgICAgIG9yaWdpbmFsQ3VycmVuY3k6IHRyYW5zYWN0aW9uLnRybkN1cnJlbmN5U3ltYm9sLFxuICAgICAgY2hhcmdlZEFtb3VudCxcbiAgICAgIGNoYXJnZWRDdXJyZW5jeTogIWlzUGVuZGluZyh0cmFuc2FjdGlvbikgPyB0cmFuc2FjdGlvbi5kZWJDcmRDdXJyZW5jeVN5bWJvbCA6IHVuZGVmaW5lZCxcbiAgICAgIGRlc2NyaXB0aW9uOiB0cmFuc2FjdGlvbi5tZXJjaGFudE5hbWUsXG4gICAgICBtZW1vOiB0cmFuc2FjdGlvbi50cmFuc1R5cGVDb21tZW50RGV0YWlscy50b1N0cmluZygpLFxuICAgICAgY2F0ZWdvcnk6IHRyYW5zYWN0aW9uLmJyYW5jaENvZGVEZXNjLFxuICAgIH07XG5cbiAgICBpZiAoaW5zdGFsbG1lbnRzKSB7XG4gICAgICByZXN1bHQuaW5zdGFsbG1lbnRzID0gaW5zdGFsbG1lbnRzO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy5pbmNsdWRlUmF3VHJhbnNhY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5yYXdUcmFuc2FjdGlvbiA9IGdldFJhd1RyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9KTtcbn1cblxudHlwZSBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscyA9IHsgdXNlcm5hbWU6IHN0cmluZzsgcGFzc3dvcmQ6IHN0cmluZyB9O1xuXG5jbGFzcyBWaXNhQ2FsU2NyYXBlciBleHRlbmRzIEJhc2VTY3JhcGVyV2l0aEJyb3dzZXI8U2NyYXBlclNwZWNpZmljQ3JlZGVudGlhbHM+IHtcbiAgcHJpdmF0ZSBhdXRob3JpemF0aW9uOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSBhdXRoUmVxdWVzdFByb21pc2U6IFByb21pc2U8SFRUUFJlcXVlc3QgfCB1bmRlZmluZWQ+IHwgdW5kZWZpbmVkO1xuXG4gIG9wZW5Mb2dpblBvcHVwID0gYXN5bmMgKCkgPT4ge1xuICAgIGRlYnVnKCdvcGVuIGxvZ2luIHBvcHVwLCB3YWl0IHVudGlsIGxvZ2luIGJ1dHRvbiBhdmFpbGFibGUnKTtcbiAgICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQodGhpcy5wYWdlLCAnI2NjTG9naW5EZXNrdG9wQnRuJywgdHJ1ZSk7XG4gICAgZGVidWcoJ2NsaWNrIG9uIHRoZSBsb2dpbiBidXR0b24nKTtcbiAgICBhd2FpdCBjbGlja0J1dHRvbih0aGlzLnBhZ2UsICcjY2NMb2dpbkRlc2t0b3BCdG4nKTtcbiAgICBkZWJ1ZygnZ2V0IHRoZSBmcmFtZSB0aGF0IGhvbGRzIHRoZSBsb2dpbicpO1xuICAgIGNvbnN0IGZyYW1lID0gYXdhaXQgZ2V0TG9naW5GcmFtZSh0aGlzLnBhZ2UpO1xuICAgIGRlYnVnKCd3YWl0IHVudGlsIHRoZSBwYXNzd29yZCBsb2dpbiB0YWIgaGVhZGVyIGlzIGF2YWlsYWJsZScpO1xuICAgIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZChmcmFtZSwgJyNyZWd1bGFyLWxvZ2luJyk7XG4gICAgZGVidWcoJ25hdmlnYXRlIHRvIHRoZSBwYXNzd29yZCBsb2dpbiB0YWInKTtcbiAgICBhd2FpdCBjbGlja0J1dHRvbihmcmFtZSwgJyNyZWd1bGFyLWxvZ2luJyk7XG4gICAgZGVidWcoJ3dhaXQgdW50aWwgdGhlIHBhc3N3b3JkIGxvZ2luIHRhYiBpcyBhY3RpdmUnKTtcbiAgICBhd2FpdCB3YWl0VW50aWxFbGVtZW50Rm91bmQoZnJhbWUsICdyZWd1bGFyLWxvZ2luJyk7XG5cbiAgICByZXR1cm4gZnJhbWU7XG4gIH07XG5cbiAgYXN5bmMgZ2V0Q2FyZHMoKSB7XG4gICAgY29uc3QgaW5pdERhdGEgPSBhd2FpdCB3YWl0VW50aWwoXG4gICAgICAoKSA9PiBnZXRGcm9tU2Vzc2lvblN0b3JhZ2U8SW5pdFJlc3BvbnNlPih0aGlzLnBhZ2UsICdpbml0JyksXG4gICAgICAnZ2V0IGluaXQgZGF0YSBpbiBzZXNzaW9uIHN0b3JhZ2UnLFxuICAgICAgMTAwMDAsXG4gICAgICAxMDAwLFxuICAgICk7XG4gICAgaWYgKCFpbml0RGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgZmluZCBcImluaXRcIiBkYXRhIGluIHNlc3Npb24gc3RvcmFnZScpO1xuICAgIH1cbiAgICByZXR1cm4gaW5pdERhdGE/LnJlc3VsdC5jYXJkcy5tYXAoKHsgY2FyZFVuaXF1ZUlkLCBsYXN0NERpZ2l0cyB9KSA9PiAoeyBjYXJkVW5pcXVlSWQsIGxhc3Q0RGlnaXRzIH0pKTtcbiAgfVxuXG4gIGFzeW5jIGdldEF1dGhvcml6YXRpb25IZWFkZXIoKSB7XG4gICAgaWYgKCF0aGlzLmF1dGhvcml6YXRpb24pIHtcbiAgICAgIGRlYnVnKCdmZXRjaGluZyBhdXRob3JpemF0aW9uIGhlYWRlcicpO1xuICAgICAgY29uc3QgYXV0aE1vZHVsZSA9IGF3YWl0IHdhaXRVbnRpbChcbiAgICAgICAgYXN5bmMgKCkgPT4gYXV0aE1vZHVsZU9yVW5kZWZpbmVkKGF3YWl0IGdldEZyb21TZXNzaW9uU3RvcmFnZTxBdXRoTW9kdWxlPih0aGlzLnBhZ2UsICdhdXRoLW1vZHVsZScpKSxcbiAgICAgICAgJ2dldCBhdXRob3JpemF0aW9uIGhlYWRlciB3aXRoIHZhbGlkIHRva2VuIGluIHNlc3Npb24gc3RvcmFnZScsXG4gICAgICAgIDEwXzAwMCxcbiAgICAgICAgNTAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGBDQUxBdXRoU2NoZW1lICR7YXV0aE1vZHVsZS5hdXRoLmNhbENvbm5lY3RUb2tlbn1gO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hdXRob3JpemF0aW9uO1xuICB9XG5cbiAgYXN5bmMgZ2V0WFNpdGVJZCgpIHtcbiAgICAvKlxuICAgICAgSSBkb24ndCBrbm93IGlmIHRoZSBjb25zdGFudCBiZWxvdyB3aWxsIGNoYW5nZSBpbiB0aGUgZmVhdHVyZS5cbiAgICAgIElmIHNvLCB1c2UgdGhlIG5leHQgY29kZTpcblxuICAgICAgcmV0dXJuIHRoaXMucGFnZS5ldmFsdWF0ZSgoKSA9PiBuZXcgVXQoKS54U2l0ZUlkKTtcblxuICAgICAgVG8gZ2V0IHRoZSBjbGFzc25hbWUgc2VhcmNoIGZvciAneFNpdGVJZCcgaW4gdGhlIHBhZ2Ugc291cmNlXG4gICAgICBjbGFzcyBVdCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKF9lLCBvbiwgeW4pIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcmUgPSBfZSxcbiAgICAgICAgICAgIHRoaXMuY29uZmlnID0gb24sXG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzU2VydmljZSA9IHluLFxuICAgICAgICAgICAgdGhpcy54U2l0ZUlkID0gXCIwOTAzMTk4Ny0yNzNFLTIzMTEtOTA2Qy04QUY4NUIxN0M4RDlcIixcbiAgICAqL1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoJzA5MDMxOTg3LTI3M0UtMjMxMS05MDZDLThBRjg1QjE3QzhEOScpO1xuICB9XG5cbiAgZ2V0TG9naW5PcHRpb25zKGNyZWRlbnRpYWxzOiBTY3JhcGVyU3BlY2lmaWNDcmVkZW50aWFscyk6IExvZ2luT3B0aW9ucyB7XG4gICAgdGhpcy5hdXRoUmVxdWVzdFByb21pc2UgPSB0aGlzLnBhZ2VcbiAgICAgIC53YWl0Rm9yUmVxdWVzdChTU09fQVVUSE9SSVpBVElPTl9SRVFVRVNUX0VORFBPSU5ULCB7IHRpbWVvdXQ6IDEwXzAwMCB9KVxuICAgICAgLmNhdGNoKGUgPT4ge1xuICAgICAgICBkZWJ1ZygnZXJyb3Igd2hpbGUgd2FpdGluZyBmb3IgdGhlIHRva2VuIHJlcXVlc3QnLCBlKTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBsb2dpblVybDogYCR7TE9HSU5fVVJMfWAsXG4gICAgICBmaWVsZHM6IGNyZWF0ZUxvZ2luRmllbGRzKGNyZWRlbnRpYWxzKSxcbiAgICAgIHN1Ym1pdEJ1dHRvblNlbGVjdG9yOiAnYnV0dG9uW3R5cGU9XCJzdWJtaXRcIl0nLFxuICAgICAgcG9zc2libGVSZXN1bHRzOiBnZXRQb3NzaWJsZUxvZ2luUmVzdWx0cygpLFxuICAgICAgY2hlY2tSZWFkaW5lc3M6IGFzeW5jICgpID0+IHdhaXRVbnRpbEVsZW1lbnRGb3VuZCh0aGlzLnBhZ2UsICcjY2NMb2dpbkRlc2t0b3BCdG4nKSxcbiAgICAgIHByZUFjdGlvbjogdGhpcy5vcGVuTG9naW5Qb3B1cCxcbiAgICAgIHBvc3RBY3Rpb246IGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB3YWl0Rm9yTmF2aWdhdGlvbih0aGlzLnBhZ2UpO1xuICAgICAgICAgIGNvbnN0IGN1cnJlbnRVcmwgPSBhd2FpdCBnZXRDdXJyZW50VXJsKHRoaXMucGFnZSk7XG4gICAgICAgICAgaWYgKGN1cnJlbnRVcmwuZW5kc1dpdGgoJ3NpdGUtdHV0b3JpYWwnKSkge1xuICAgICAgICAgICAgYXdhaXQgY2xpY2tCdXR0b24odGhpcy5wYWdlLCAnYnV0dG9uLmJ0bi1jbG9zZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gYXdhaXQgdGhpcy5hdXRoUmVxdWVzdFByb21pc2U7XG4gICAgICAgICAgdGhpcy5hdXRob3JpemF0aW9uID0gU3RyaW5nKHJlcXVlc3Q/LmhlYWRlcnMoKS5hdXRob3JpemF0aW9uIHx8ICcnKS50cmltKCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zdCBjdXJyZW50VXJsID0gYXdhaXQgZ2V0Q3VycmVudFVybCh0aGlzLnBhZ2UpO1xuICAgICAgICAgIGlmIChjdXJyZW50VXJsLmVuZHNXaXRoKCdkYXNoYm9hcmQnKSkgcmV0dXJuO1xuICAgICAgICAgIGNvbnN0IHJlcXVpcmVzQ2hhbmdlUGFzc3dvcmQgPSBhd2FpdCBoYXNDaGFuZ2VQYXNzd29yZEZvcm0odGhpcy5wYWdlKTtcbiAgICAgICAgICBpZiAocmVxdWlyZXNDaGFuZ2VQYXNzd29yZCkgcmV0dXJuO1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB1c2VyQWdlbnQ6IGFwaUhlYWRlcnNbJ1VzZXItQWdlbnQnXSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaENhcmREYXRhKFxuICAgIGNhcmQ6IHsgY2FyZFVuaXF1ZUlkOiBzdHJpbmc7IGxhc3Q0RGlnaXRzOiBzdHJpbmcgfSxcbiAgICBzdGFydE1vbWVudDogbW9tZW50Lk1vbWVudCxcbiAgICBzdGFydERhdGU6IERhdGUsXG4gICAgZnV0dXJlTW9udGhzVG9TY3JhcGU6IG51bWJlcixcbiAgICBBdXRob3JpemF0aW9uOiBzdHJpbmcsXG4gICAgeFNpdGVJZDogc3RyaW5nLFxuICApOiBQcm9taXNlPFRyYW5zYWN0aW9uc0FjY291bnQ+IHtcbiAgICBkZWJ1ZygnZmV0Y2ggZnJhbWVzIChtaXNnYXJvdCkgZm9yIGNhcmQgJXMnLCBjYXJkLmNhcmRVbmlxdWVJZCk7XG4gICAgY29uc3QgZnJhbWVzID0gYXdhaXQgZmV0Y2hQb3N0PEZyYW1lc1Jlc3BvbnNlPihcbiAgICAgIEZSQU1FU19SRVFVRVNUX0VORFBPSU5ULFxuICAgICAgeyBjYXJkc0ZvckZyYW1lRGF0YTogW3sgY2FyZFVuaXF1ZUlkOiBjYXJkLmNhcmRVbmlxdWVJZCB9XSB9LFxuICAgICAge1xuICAgICAgICBBdXRob3JpemF0aW9uLFxuICAgICAgICAnWC1TaXRlLUlkJzogeFNpdGVJZCxcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgLi4uYXBpSGVhZGVycyxcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGRlYnVnKCdmcmFtZXMgcmVzcG9uc2UgZm9yIGNhcmQgJXM6ICVPJywgY2FyZC5jYXJkVW5pcXVlSWQsIGZyYW1lcyk7XG5cbiAgICAvLyBMb29rIGZvciBjYXJkLWxldmVsIGZyYW1lIGluIGJvdGggY2FsSXNzdWVkQ2FyZHMgYW5kIGJhbmtJc3N1ZWRDYXJkc1xuICAgIGNvbnN0IGJhbmtJc3N1ZWRGcmFtZSA9IGZyYW1lcy5yZXN1bHQ/LmJhbmtJc3N1ZWRDYXJkcz8uY2FyZExldmVsRnJhbWVzPy5maW5kKFxuICAgICAgKGY6IENhcmRMZXZlbEZyYW1lKSA9PiBmLmNhcmRVbmlxdWVJZCA9PT0gY2FyZC5jYXJkVW5pcXVlSWQsXG4gICAgKTtcblxuICAgIGNvbnN0IGNhbElzc3VlZEZyYW1lID0gZnJhbWVzLnJlc3VsdD8uY2FsSXNzdWVkQ2FyZHM/LmNhcmRMZXZlbEZyYW1lcz8uZmluZChcbiAgICAgIChmOiBDYXJkTGV2ZWxGcmFtZSkgPT4gZi5jYXJkVW5pcXVlSWQgPT09IGNhcmQuY2FyZFVuaXF1ZUlkLFxuICAgICk7XG5cbiAgICBsZXQgZnJhbWU6IENhcmRMZXZlbEZyYW1lIHwgdW5kZWZpbmVkO1xuICAgIGxldCBjYXJkVHlwZTogQ2FyZFR5cGU7XG4gICAgbGV0IGFjY291bnRHcm91cDogSXNzdWVkQ2FyZHNHcm91cCB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChiYW5rSXNzdWVkRnJhbWUpIHtcbiAgICAgIGZyYW1lID0gYmFua0lzc3VlZEZyYW1lO1xuICAgICAgY2FyZFR5cGUgPSBDYXJkVHlwZS5CYW5rSXNzdWVkO1xuICAgICAgYWNjb3VudEdyb3VwID0gZnJhbWVzLnJlc3VsdD8uYmFua0lzc3VlZENhcmRzO1xuICAgIH0gZWxzZSB7XG4gICAgICBmcmFtZSA9IGNhbElzc3VlZEZyYW1lO1xuICAgICAgY2FyZFR5cGUgPSBDYXJkVHlwZS5Db21wYW55SXNzdWVkO1xuICAgICAgYWNjb3VudEdyb3VwID0gZnJhbWVzLnJlc3VsdD8uY2FsSXNzdWVkQ2FyZHM7XG4gICAgfVxuXG4gICAgZGVidWcoJ3NlYXJjaGluZyBmb3IgZnJhbWUgZm9yIGNhcmQgJXMsIGZvdW5kOiAlTycsIGNhcmQuY2FyZFVuaXF1ZUlkLCBmcmFtZSk7XG4gICAgZGVidWcoJ2NhcmQgdHlwZSBmb3IgY2FyZCAlczogJXMnLCBjYXJkLmNhcmRVbmlxdWVJZCwgY2FyZFR5cGUpO1xuXG4gICAgY29uc3QgYmFsYW5jZURhdGU6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQgPSBmcmFtZT8ubmV4dERlYml0RGF0ZSA/PyBhY2NvdW50R3JvdXA/Lm5leHRUb3RhbERlYml0RGF0ZUZvckFjY291bnQ7XG5cbiAgICBjb25zdCBmaW5hbE1vbnRoVG9GZXRjaE1vbWVudCA9IG1vbWVudCgpLmFkZChmdXR1cmVNb250aHNUb1NjcmFwZSwgJ21vbnRoJyk7XG4gICAgY29uc3QgbW9udGhzID0gZmluYWxNb250aFRvRmV0Y2hNb21lbnQuZGlmZihzdGFydE1vbWVudCwgJ21vbnRocycpO1xuICAgIGNvbnN0IGFsbE1vbnRoc0RhdGE6IENhcmRUcmFuc2FjdGlvbkRldGFpbHNbXSA9IFtdO1xuXG4gICAgZGVidWcoYGZldGNoIHBlbmRpbmcgdHJhbnNhY3Rpb25zIGZvciBjYXJkICR7Y2FyZC5jYXJkVW5pcXVlSWR9YCk7XG4gICAgbGV0IHBlbmRpbmdEYXRhID0gYXdhaXQgZmV0Y2hQb3N0KFxuICAgICAgUEVORElOR19UUkFOU0FDVElPTlNfUkVRVUVTVF9FTkRQT0lOVCxcbiAgICAgIHsgY2FyZFVuaXF1ZUlEQXJyYXk6IFtjYXJkLmNhcmRVbmlxdWVJZF0gfSxcbiAgICAgIHtcbiAgICAgICAgQXV0aG9yaXphdGlvbixcbiAgICAgICAgJ1gtU2l0ZS1JZCc6IHhTaXRlSWQsXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgIC4uLmFwaUhlYWRlcnMsXG4gICAgICB9LFxuICAgICk7XG5cbiAgICBkZWJ1ZyhgZmV0Y2ggY29tcGxldGVkIHRyYW5zYWN0aW9ucyBmb3IgY2FyZCAke2NhcmQuY2FyZFVuaXF1ZUlkfWApO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IG1vbnRoczsgaSsrKSB7XG4gICAgICBjb25zdCBtb250aCA9IGZpbmFsTW9udGhUb0ZldGNoTW9tZW50LmNsb25lKCkuc3VidHJhY3QoaSwgJ21vbnRocycpO1xuICAgICAgY29uc3QgbW9udGhEYXRhID0gYXdhaXQgZmV0Y2hQb3N0KFxuICAgICAgICBUUkFOU0FDVElPTlNfUkVRVUVTVF9FTkRQT0lOVCxcbiAgICAgICAgeyBjYXJkVW5pcXVlSWQ6IGNhcmQuY2FyZFVuaXF1ZUlkLCBtb250aDogbW9udGguZm9ybWF0KCdNJyksIHllYXI6IG1vbnRoLmZvcm1hdCgnWVlZWScpIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBBdXRob3JpemF0aW9uLFxuICAgICAgICAgICdYLVNpdGUtSWQnOiB4U2l0ZUlkLFxuICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgLi4uYXBpSGVhZGVycyxcbiAgICAgICAgfSxcbiAgICAgICk7XG5cbiAgICAgIGlmIChtb250aERhdGE/LnN0YXR1c0NvZGUgIT09IDEpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgZmFpbGVkIHRvIGZldGNoIHRyYW5zYWN0aW9ucyBmb3IgY2FyZCAke2NhcmQubGFzdDREaWdpdHN9LiBNZXNzYWdlOiAke21vbnRoRGF0YT8udGl0bGUgfHwgJyd9YCxcbiAgICAgICAgKTtcblxuICAgICAgaWYgKCFpc0NhcmRUcmFuc2FjdGlvbkRldGFpbHMobW9udGhEYXRhKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21vbnRoRGF0YSBpcyBub3Qgb2YgdHlwZSBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzJyk7XG4gICAgICB9XG5cbiAgICAgIGFsbE1vbnRoc0RhdGEucHVzaChtb250aERhdGEpO1xuICAgIH1cblxuICAgIGlmIChwZW5kaW5nRGF0YT8uc3RhdHVzQ29kZSAhPT0gMSAmJiBwZW5kaW5nRGF0YT8uc3RhdHVzQ29kZSAhPT0gOTYpIHtcbiAgICAgIGRlYnVnKGBmYWlsZWQgdG8gZmV0Y2ggcGVuZGluZyB0cmFuc2FjdGlvbnMgZm9yIGNhcmQgJHtjYXJkLmxhc3Q0RGlnaXRzfS4gTWVzc2FnZTogJHtwZW5kaW5nRGF0YT8udGl0bGUgfHwgJyd9YCk7XG4gICAgICBwZW5kaW5nRGF0YSA9IG51bGw7XG4gICAgfSBlbHNlIGlmICghaXNDYXJkUGVuZGluZ1RyYW5zYWN0aW9uRGV0YWlscyhwZW5kaW5nRGF0YSkpIHtcbiAgICAgIGRlYnVnKCdwZW5kaW5nRGF0YSBpcyBub3Qgb2YgdHlwZSBDYXJkVHJhbnNhY3Rpb25EZXRhaWxzJyk7XG4gICAgICBwZW5kaW5nRGF0YSA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdHJhbnNhY3Rpb25zID0gY29udmVydFBhcnNlZERhdGFUb1RyYW5zYWN0aW9ucyhhbGxNb250aHNEYXRhLCBwZW5kaW5nRGF0YSwgdGhpcy5vcHRpb25zKTtcblxuICAgIGRlYnVnKCdmaWx0ZXIgb3V0IG9sZCB0cmFuc2FjdGlvbnMnKTtcbiAgICBjb25zdCB0eG5zID1cbiAgICAgICh0aGlzLm9wdGlvbnMub3V0cHV0RGF0YT8uZW5hYmxlVHJhbnNhY3Rpb25zRmlsdGVyQnlEYXRlID8/IHRydWUpXG4gICAgICAgID8gZmlsdGVyT2xkVHJhbnNhY3Rpb25zKHRyYW5zYWN0aW9ucywgbW9tZW50KHN0YXJ0RGF0ZSksIHRoaXMub3B0aW9ucy5jb21iaW5lSW5zdGFsbG1lbnRzIHx8IGZhbHNlKVxuICAgICAgICA6IHRyYW5zYWN0aW9ucztcblxuICAgIC8vIFVzZSBjYXJkLWxldmVsIGJhbGFuY2UgaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgZmFsbCBiYWNrIHRvIGFjY291bnQtbGV2ZWwgYmFsYW5jZVxuICAgIGNvbnN0IGJhbGFuY2VBbW91bnQgPSBmcmFtZT8ubmV4dFRvdGFsRGViaXQgPz8gYWNjb3VudEdyb3VwPy5uZXh0VG90YWxEZWJpdEZvckFjY291bnQ7XG4gICAgY29uc3QgcmVzdWx0OiBUcmFuc2FjdGlvbnNBY2NvdW50ID0ge1xuICAgICAgdHhucyxcbiAgICAgIGJhbGFuY2U6IGJhbGFuY2VBbW91bnQgIT0gbnVsbCA/IC1iYWxhbmNlQW1vdW50IDogdW5kZWZpbmVkLFxuICAgICAgYmFsYW5jZURhdGU6IGJhbGFuY2VEYXRlICE9IG51bGwgPyBiYWxhbmNlRGF0ZSA6IHVuZGVmaW5lZCxcbiAgICAgIGFjY291bnROdW1iZXI6IGNhcmQubGFzdDREaWdpdHMsXG4gICAgICBjYXJkVHlwZSxcbiAgICAgIGNhcmRGcmFtZTogYWNjb3VudEdyb3VwPy5mcmFtZUxpbWl0Rm9yQ2FyZEFtb3VudCxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFzeW5jIGZldGNoRGF0YSgpOiBQcm9taXNlPFNjcmFwZXJTY3JhcGluZ1Jlc3VsdD4ge1xuICAgIGNvbnN0IGRlZmF1bHRTdGFydE1vbWVudCA9IG1vbWVudCgpLnN1YnRyYWN0KDEsICd5ZWFycycpLnN1YnRyYWN0KDYsICdtb250aHMnKS5hZGQoMSwgJ2RheScpO1xuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IHRoaXMub3B0aW9ucy5zdGFydERhdGUgfHwgZGVmYXVsdFN0YXJ0TW9tZW50LnRvRGF0ZSgpO1xuICAgIGNvbnN0IHN0YXJ0TW9tZW50ID0gbW9tZW50Lm1heChkZWZhdWx0U3RhcnRNb21lbnQsIG1vbWVudChzdGFydERhdGUpKTtcbiAgICBkZWJ1ZyhgZmV0Y2ggdHJhbnNhY3Rpb25zIHN0YXJ0aW5nICR7c3RhcnRNb21lbnQuZm9ybWF0KCl9YCk7XG5cbiAgICBjb25zdCBbY2FyZHMsIHhTaXRlSWQsIEF1dGhvcml6YXRpb25dID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgdGhpcy5nZXRDYXJkcygpLFxuICAgICAgdGhpcy5nZXRYU2l0ZUlkKCksXG4gICAgICB0aGlzLmdldEF1dGhvcml6YXRpb25IZWFkZXIoKSxcbiAgICBdKTtcblxuICAgIGNvbnN0IGZ1dHVyZU1vbnRoc1RvU2NyYXBlID0gdGhpcy5vcHRpb25zLmZ1dHVyZU1vbnRoc1RvU2NyYXBlID8/IDE7XG5cbiAgICBjb25zdCBhY2NvdW50cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgY2FyZHMubWFwKGNhcmQgPT4gdGhpcy5mZXRjaENhcmREYXRhKGNhcmQsIHN0YXJ0TW9tZW50LCBzdGFydERhdGUsIGZ1dHVyZU1vbnRoc1RvU2NyYXBlLCBBdXRob3JpemF0aW9uLCB4U2l0ZUlkKSksXG4gICAgKTtcblxuICAgIGRlYnVnKCdyZXR1cm4gdGhlIHNjcmFwZWQgYWNjb3VudHMnKTtcblxuICAgIGRlYnVnKEpTT04uc3RyaW5naWZ5KGFjY291bnRzLCBudWxsLCAyKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICBhY2NvdW50cyxcbiAgICB9O1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFZpc2FDYWxTY3JhcGVyO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxJQUFBQSxPQUFBLEdBQUFDLHNCQUFBLENBQUFDLE9BQUE7QUFFQSxJQUFBQyxNQUFBLEdBQUFELE9BQUE7QUFDQSxJQUFBRSxxQkFBQSxHQUFBRixPQUFBO0FBQ0EsSUFBQUcsTUFBQSxHQUFBSCxPQUFBO0FBQ0EsSUFBQUksV0FBQSxHQUFBSixPQUFBO0FBQ0EsSUFBQUssUUFBQSxHQUFBTCxPQUFBO0FBQ0EsSUFBQU0sYUFBQSxHQUFBTixPQUFBO0FBQ0EsSUFBQU8sUUFBQSxHQUFBUCxPQUFBO0FBQ0EsSUFBQVEsY0FBQSxHQUFBUixPQUFBO0FBT0EsSUFBQVMsdUJBQUEsR0FBQVQsT0FBQTtBQUFzRyxTQUFBRCx1QkFBQVcsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUd0RyxNQUFNRyxVQUFVLEdBQUc7RUFDakIsWUFBWSxFQUNWLHVIQUF1SDtFQUN6SEMsTUFBTSxFQUFFLHNDQUFzQztFQUM5Q0MsT0FBTyxFQUFFLHNDQUFzQztFQUMvQyxpQkFBaUIsRUFBRSxxQ0FBcUM7RUFDeEQsZ0JBQWdCLEVB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