israeli-bank-scrapers
Version:
Provide scrapers for all major Israeli banks and credit card companies
288 lines (282 loc) • 38.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.LoginResults = exports.BaseScraperWithBrowser = void 0;
var _puppeteer = _interopRequireDefault(require("puppeteer"));
var _definitions = require("../definitions");
var _debug = require("../helpers/debug");
var _elementsInteractions = require("../helpers/elements-interactions");
var _navigation = require("../helpers/navigation");
var _baseScraper = require("./base-scraper");
var _errors = require("./errors");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const debug = (0, _debug.getDebug)('base-scraper-with-browser');
var LoginBaseResults = /*#__PURE__*/function (LoginBaseResults) {
LoginBaseResults["Success"] = "SUCCESS";
LoginBaseResults["UnknownError"] = "UNKNOWN_ERROR";
return LoginBaseResults;
}(LoginBaseResults || {});
const {
Timeout,
Generic,
General,
...rest
} = _errors.ScraperErrorTypes;
const LoginResults = exports.LoginResults = {
...rest,
...LoginBaseResults
};
async function getKeyByValue(object, value, page) {
const keys = Object.keys(object);
for (const key of keys) {
// @ts-ignore
const conditions = object[key];
for (const condition of conditions) {
let result = false;
if (condition instanceof RegExp) {
result = condition.test(value);
} else if (typeof condition === 'function') {
result = await condition({
page,
value
});
} else {
result = value.toLowerCase() === condition.toLowerCase();
}
if (result) {
// @ts-ignore
return Promise.resolve(key);
}
}
}
return Promise.resolve(LoginResults.UnknownError);
}
function createGeneralError() {
return {
success: false,
errorType: _errors.ScraperErrorTypes.General
};
}
async function safeCleanup(cleanup) {
try {
await cleanup();
} catch (e) {
debug(`Cleanup function failed: ${e.message}`);
}
}
class BaseScraperWithBrowser extends _baseScraper.BaseScraper {
cleanups = [];
defaultViewportSize = {
width: 1024,
height: 768
};
// NOTICE - it is discouraged to use bang (!) in general. It is used here because
// all the classes that inherit from this base assume is it mandatory.
getViewPort() {
return this.options.viewportSize ?? this.defaultViewportSize;
}
async initialize() {
await super.initialize();
debug('initialize scraper');
this.emitProgress(_definitions.ScraperProgressTypes.Initializing);
const page = await this.initializePage();
await page.setCacheEnabled(false); // Clear cache and avoid 300's response status
if (!page) {
debug('failed to initiate a browser page, exit');
return;
}
this.page = page;
this.cleanups.push(() => page.close());
if (this.options.defaultTimeout) {
this.page.setDefaultTimeout(this.options.defaultTimeout);
}
if (this.options.preparePage) {
debug("execute 'preparePage' interceptor provided in options");
await this.options.preparePage(this.page);
}
const viewport = this.getViewPort();
debug(`set viewport to width ${viewport.width}, height ${viewport.height}`);
await this.page.setViewport({
width: viewport.width,
height: viewport.height
});
this.page.on('requestfailed', request => {
debug('Request failed: %s %s', request.failure()?.errorText, request.url());
});
}
async initializePage() {
debug('initialize browser page');
if ('browserContext' in this.options) {
debug('Using the browser context provided in options');
return this.options.browserContext.newPage();
}
if ('browser' in this.options) {
debug('Using the browser instance provided in options');
const {
browser
} = this.options;
/**
* For backward compatibility, we will close the browser even if we didn't create it
*/
if (!this.options.skipCloseBrowser) {
this.cleanups.push(async () => {
debug('closing the browser');
await browser.close();
});
}
return browser.newPage();
}
const {
timeout,
args,
executablePath,
showBrowser
} = this.options;
const headless = !showBrowser;
debug(`launch a browser with headless mode = ${headless}`);
const browser = await _puppeteer.default.launch({
env: this.options.verbose ? {
DEBUG: '*',
...process.env
} : undefined,
headless,
executablePath,
args,
timeout
});
this.cleanups.push(async () => {
debug('closing the browser');
await browser.close();
});
if (this.options.prepareBrowser) {
debug("execute 'prepareBrowser' interceptor provided in options");
await this.options.prepareBrowser(browser);
}
debug('create a new browser page');
return browser.newPage();
}
async navigateTo(url, waitUntil = 'load', retries = this.options.navigationRetryCount ?? 0) {
const response = await this.page?.goto(url, {
waitUntil
});
if (response === null) {
// note: response will be null when navigating to same url while changing the hash part.
// the condition below will always accept null as valid result.
return;
}
if (!response) {
throw new Error(`Error while trying to navigate to url ${url}, response is undefined`);
}
if (!response.ok()) {
const status = response.status();
if (retries > 0) {
debug(`Failed to navigate to url ${url}, status code: ${status}, retrying ${retries} more times`);
await this.navigateTo(url, waitUntil, retries - 1);
} else {
throw new Error(`Failed to navigate to url ${url}, status code: ${status}`);
}
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getLoginOptions(_credentials) {
throw new Error(`getLoginOptions() is not created in ${this.options.companyId}`);
}
async fillInputs(pageOrFrame, fields) {
const modified = [...fields];
const input = modified.shift();
if (!input) {
return;
}
await (0, _elementsInteractions.fillInput)(pageOrFrame, input.selector, input.value);
if (modified.length) {
await this.fillInputs(pageOrFrame, modified);
}
}
async login(credentials) {
if (!credentials || !this.page) {
return createGeneralError();
}
debug('execute login process');
const loginOptions = this.getLoginOptions(credentials);
if (loginOptions.userAgent) {
debug('set custom user agent provided in options');
await this.page.setUserAgent(loginOptions.userAgent);
}
debug('navigate to login url');
await this.navigateTo(loginOptions.loginUrl, loginOptions.waitUntil);
if (loginOptions.checkReadiness) {
debug("execute 'checkReadiness' interceptor provided in login options");
await loginOptions.checkReadiness();
} else if (typeof loginOptions.submitButtonSelector === 'string') {
debug('wait until submit button is available');
await (0, _elementsInteractions.waitUntilElementFound)(this.page, loginOptions.submitButtonSelector);
}
let loginFrameOrPage = this.page;
if (loginOptions.preAction) {
debug("execute 'preAction' interceptor provided in login options");
loginFrameOrPage = (await loginOptions.preAction()) || this.page;
}
debug('fill login components input with relevant values');
await this.fillInputs(loginFrameOrPage, loginOptions.fields);
debug('click on login submit button');
if (typeof loginOptions.submitButtonSelector === 'string') {
await (0, _elementsInteractions.clickButton)(loginFrameOrPage, loginOptions.submitButtonSelector);
} else {
await loginOptions.submitButtonSelector();
}
this.emitProgress(_definitions.ScraperProgressTypes.LoggingIn);
if (loginOptions.postAction) {
debug("execute 'postAction' interceptor provided in login options");
await loginOptions.postAction();
} else {
debug('wait for page navigation');
await (0, _navigation.waitForNavigation)(this.page);
}
debug('check login result');
const current = await (0, _navigation.getCurrentUrl)(this.page, true);
const loginResult = await getKeyByValue(loginOptions.possibleResults, current, this.page);
debug(`handle login results ${loginResult}`);
return this.handleLoginResult(loginResult);
}
async terminate(_success) {
debug(`terminating browser with success = ${_success}`);
this.emitProgress(_definitions.ScraperProgressTypes.Terminating);
if (!_success && !!this.options.storeFailureScreenShotPath) {
debug(`create a snapshot before terminated in ${this.options.storeFailureScreenShotPath}`);
await this.page.screenshot({
path: this.options.storeFailureScreenShotPath,
fullPage: true
});
}
await Promise.all(this.cleanups.reverse().map(safeCleanup));
this.cleanups = [];
}
handleLoginResult(loginResult) {
switch (loginResult) {
case LoginResults.Success:
this.emitProgress(_definitions.ScraperProgressTypes.LoginSuccess);
return {
success: true
};
case LoginResults.InvalidPassword:
case LoginResults.UnknownError:
this.emitProgress(_definitions.ScraperProgressTypes.LoginFailed);
return {
success: false,
errorType: loginResult === LoginResults.InvalidPassword ? _errors.ScraperErrorTypes.InvalidPassword : _errors.ScraperErrorTypes.General,
errorMessage: `Login failed with ${loginResult} error`
};
case LoginResults.ChangePassword:
this.emitProgress(_definitions.ScraperProgressTypes.ChangePassword);
return {
success: false,
errorType: _errors.ScraperErrorTypes.ChangePassword
};
default:
throw new Error(`unexpected login result "${loginResult}"`);
}
}
}
exports.BaseScraperWithBrowser = BaseScraperWithBrowser;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcHVwcGV0ZWVyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfZGVmaW5pdGlvbnMiLCJfZGVidWciLCJfZWxlbWVudHNJbnRlcmFjdGlvbnMiLCJfbmF2aWdhdGlvbiIsIl9iYXNlU2NyYXBlciIsIl9lcnJvcnMiLCJlIiwiX19lc01vZHVsZSIsImRlZmF1bHQiLCJkZWJ1ZyIsImdldERlYnVnIiwiTG9naW5CYXNlUmVzdWx0cyIsIlRpbWVvdXQiLCJHZW5lcmljIiwiR2VuZXJhbCIsInJlc3QiLCJTY3JhcGVyRXJyb3JUeXBlcyIsIkxvZ2luUmVzdWx0cyIsImV4cG9ydHMiLCJnZXRLZXlCeVZhbHVlIiwib2JqZWN0IiwidmFsdWUiLCJwYWdlIiwia2V5cyIsIk9iamVjdCIsImtleSIsImNvbmRpdGlvbnMiLCJjb25kaXRpb24iLCJyZXN1bHQiLCJSZWdFeHAiLCJ0ZXN0IiwidG9Mb3dlckNhc2UiLCJQcm9taXNlIiwicmVzb2x2ZSIsIlVua25vd25FcnJvciIsImNyZWF0ZUdlbmVyYWxFcnJvciIsInN1Y2Nlc3MiLCJlcnJvclR5cGUiLCJzYWZlQ2xlYW51cCIsImNsZWFudXAiLCJtZXNzYWdlIiwiQmFzZVNjcmFwZXJXaXRoQnJvd3NlciIsIkJhc2VTY3JhcGVyIiwiY2xlYW51cHMiLCJkZWZhdWx0Vmlld3BvcnRTaXplIiwid2lkdGgiLCJoZWlnaHQiLCJnZXRWaWV3UG9ydCIsIm9wdGlvbnMiLCJ2aWV3cG9ydFNpemUiLCJpbml0aWFsaXplIiwiZW1pdFByb2dyZXNzIiwiU2NyYXBlclByb2dyZXNzVHlwZXMiLCJJbml0aWFsaXppbmciLCJpbml0aWFsaXplUGFnZSIsInNldENhY2hlRW5hYmxlZCIsInB1c2giLCJjbG9zZSIsImRlZmF1bHRUaW1lb3V0Iiwic2V0RGVmYXVsdFRpbWVvdXQiLCJwcmVwYXJlUGFnZSIsInZpZXdwb3J0Iiwic2V0Vmlld3BvcnQiLCJvbiIsInJlcXVlc3QiLCJmYWlsdXJlIiwiZXJyb3JUZXh0IiwidXJsIiwiYnJvd3NlckNvbnRleHQiLCJuZXdQYWdlIiwiYnJvd3NlciIsInNraXBDbG9zZUJyb3dzZXIiLCJ0aW1lb3V0IiwiYXJncyIsImV4ZWN1dGFibGVQYXRoIiwic2hvd0Jyb3dzZXIiLCJoZWFkbGVzcyIsInB1cHBldGVlciIsImxhdW5jaCIsImVudiIsInZlcmJvc2UiLCJERUJVRyIsInByb2Nlc3MiLCJ1bmRlZmluZWQiLCJwcmVwYXJlQnJvd3NlciIsIm5hdmlnYXRlVG8iLCJ3YWl0VW50aWwiLCJyZXRyaWVzIiwibmF2aWdhdGlvblJldHJ5Q291bnQiLCJyZXNwb25zZSIsImdvdG8iLCJFcnJvciIsIm9rIiwic3RhdHVzIiwiZ2V0TG9naW5PcHRpb25zIiwiX2NyZWRlbnRpYWxzIiwiY29tcGFueUlkIiwiZmlsbElucHV0cyIsInBhZ2VPckZyYW1lIiwiZmllbGRzIiwibW9kaWZpZWQiLCJpbnB1dCIsInNoaWZ0IiwiZmlsbElucHV0Iiwic2VsZWN0b3IiLCJsZW5ndGgiLCJsb2dpbiIsImNyZWRlbnRpYWxzIiwibG9naW5PcHRpb25zIiwidXNlckFnZW50Iiwic2V0VXNlckFnZW50IiwibG9naW5VcmwiLCJjaGVja1JlYWRpbmVzcyIsInN1Ym1pdEJ1dHRvblNlbGVjdG9yIiwid2FpdFVudGlsRWxlbWVudEZvdW5kIiwibG9naW5GcmFtZU9yUGFnZSIsInByZUFjdGlvbiIsImNsaWNrQnV0dG9uIiwiTG9nZ2luZ0luIiwicG9zdEFjdGlvbiIsIndhaXRGb3JOYXZpZ2F0aW9uIiwiY3VycmVudCIsImdldEN1cnJlbnRVcmwiLCJsb2dpblJlc3VsdCIsInBvc3NpYmxlUmVzdWx0cyIsImhhbmRsZUxvZ2luUmVzdWx0IiwidGVybWluYXRlIiwiX3N1Y2Nlc3MiLCJUZXJtaW5hdGluZyIsInN0b3JlRmFpbHVyZVNjcmVlblNob3RQYXRoIiwic2NyZWVuc2hvdCIsInBhdGgiLCJmdWxsUGFnZSIsImFsbCIsInJldmVyc2UiLCJtYXAiLCJTdWNjZXNzIiwiTG9naW5TdWNjZXNzIiwiSW52YWxpZFBhc3N3b3JkIiwiTG9naW5GYWlsZWQiLCJlcnJvck1lc3NhZ2UiLCJDaGFuZ2VQYXNzd29yZCJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zY3JhcGVycy9iYXNlLXNjcmFwZXItd2l0aC1icm93c2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwdXBwZXRlZXIsIHsgdHlwZSBGcmFtZSwgdHlwZSBQYWdlLCB0eXBlIFB1cHBldGVlckxpZmVDeWNsZUV2ZW50IH0gZnJvbSAncHVwcGV0ZWVyJztcbmltcG9ydCB7IFNjcmFwZXJQcm9ncmVzc1R5cGVzIH0gZnJvbSAnLi4vZGVmaW5pdGlvbnMnO1xuaW1wb3J0IHsgZ2V0RGVidWcgfSBmcm9tICcuLi9oZWxwZXJzL2RlYnVnJztcbmltcG9ydCB7IGNsaWNrQnV0dG9uLCBmaWxsSW5wdXQsIHdhaXRVbnRpbEVsZW1lbnRGb3VuZCB9IGZyb20gJy4uL2hlbHBlcnMvZWxlbWVudHMtaW50ZXJhY3Rpb25zJztcbmltcG9ydCB7IGdldEN1cnJlbnRVcmwsIHdhaXRGb3JOYXZpZ2F0aW9uIH0gZnJvbSAnLi4vaGVscGVycy9uYXZpZ2F0aW9uJztcbmltcG9ydCB7IEJhc2VTY3JhcGVyIH0gZnJvbSAnLi9iYXNlLXNjcmFwZXInO1xuaW1wb3J0IHsgU2NyYXBlckVycm9yVHlwZXMgfSBmcm9tICcuL2Vycm9ycyc7XG5pbXBvcnQgeyB0eXBlIFNjcmFwZXJDcmVkZW50aWFscywgdHlwZSBTY3JhcGVyU2NyYXBpbmdSZXN1bHQgfSBmcm9tICcuL2ludGVyZmFjZSc7XG5cbmNvbnN0IGRlYnVnID0gZ2V0RGVidWcoJ2Jhc2Utc2NyYXBlci13aXRoLWJyb3dzZXInKTtcblxuZW51bSBMb2dpbkJhc2VSZXN1bHRzIHtcbiAgU3VjY2VzcyA9ICdTVUNDRVNTJyxcbiAgVW5rbm93bkVycm9yID0gJ1VOS05PV05fRVJST1InLFxufVxuXG5jb25zdCB7IFRpbWVvdXQsIEdlbmVyaWMsIEdlbmVyYWwsIC4uLnJlc3QgfSA9IFNjcmFwZXJFcnJvclR5cGVzO1xuZXhwb3J0IGNvbnN0IExvZ2luUmVzdWx0cyA9IHtcbiAgLi4ucmVzdCxcbiAgLi4uTG9naW5CYXNlUmVzdWx0cyxcbn07XG5cbmV4cG9ydCB0eXBlIExvZ2luUmVzdWx0cyA9XG4gIHwgRXhjbHVkZTxTY3JhcGVyRXJyb3JUeXBlcywgU2NyYXBlckVycm9yVHlwZXMuVGltZW91dCB8IFNjcmFwZXJFcnJvclR5cGVzLkdlbmVyaWMgfCBTY3JhcGVyRXJyb3JUeXBlcy5HZW5lcmFsPlxuICB8IExvZ2luQmFzZVJlc3VsdHM7XG5cbmV4cG9ydCB0eXBlIFBvc3NpYmxlTG9naW5SZXN1bHRzID0ge1xuICBba2V5IGluIExvZ2luUmVzdWx0c10/OiAoc3RyaW5nIHwgUmVnRXhwIHwgKChvcHRpb25zPzogeyBwYWdlPzogUGFnZSB9KSA9PiBQcm9taXNlPGJvb2xlYW4+KSlbXTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9naW5PcHRpb25zIHtcbiAgbG9naW5Vcmw6IHN0cmluZztcbiAgY2hlY2tSZWFkaW5lc3M/OiAoKSA9PiBQcm9taXNlPHZvaWQ+O1xuICBmaWVsZHM6IHsgc2VsZWN0b3I6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9W107XG4gIHN1Ym1pdEJ1dHRvblNlbGVjdG9yOiBzdHJpbmcgfCAoKCkgPT4gUHJvbWlzZTx2b2lkPik7XG4gIHByZUFjdGlvbj86ICgpID0+IFByb21pc2U8RnJhbWUgfCB2b2lkPjtcbiAgcG9zdEFjdGlvbj86ICgpID0+IFByb21pc2U8dm9pZD47XG4gIHBvc3NpYmxlUmVzdWx0czogUG9zc2libGVMb2dpblJlc3VsdHM7XG4gIHVzZXJBZ2VudD86IHN0cmluZztcbiAgd2FpdFVudGlsPzogUHVwcGV0ZWVyTGlmZUN5Y2xlRXZlbnQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEtleUJ5VmFsdWUob2JqZWN0OiBQb3NzaWJsZUxvZ2luUmVzdWx0cywgdmFsdWU6IHN0cmluZywgcGFnZTogUGFnZSk6IFByb21pc2U8TG9naW5SZXN1bHRzPiB7XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhvYmplY3QpO1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBvYmplY3Rba2V5XTtcblxuICAgIGZvciAoY29uc3QgY29uZGl0aW9uIG9mIGNvbmRpdGlvbnMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBmYWxzZTtcblxuICAgICAgaWYgKGNvbmRpdGlvbiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICByZXN1bHQgPSBjb25kaXRpb24udGVzdCh2YWx1ZSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjb25kaXRpb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmVzdWx0ID0gYXdhaXQgY29uZGl0aW9uKHsgcGFnZSwgdmFsdWUgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQgPSB2YWx1ZS50b0xvd2VyQ2FzZSgpID09PSBjb25kaXRpb24udG9Mb3dlckNhc2UoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoa2V5KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKExvZ2luUmVzdWx0cy5Vbmtub3duRXJyb3IpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVHZW5lcmFsRXJyb3IoKTogU2NyYXBlclNjcmFwaW5nUmVzdWx0IHtcbiAgcmV0dXJuIHtcbiAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICBlcnJvclR5cGU6IFNjcmFwZXJFcnJvclR5cGVzLkdlbmVyYWwsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNhZmVDbGVhbnVwKGNsZWFudXA6ICgpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBjbGVhbnVwKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBkZWJ1ZyhgQ2xlYW51cCBmdW5jdGlvbiBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG4gIH1cbn1cblxuY2xhc3MgQmFzZVNjcmFwZXJXaXRoQnJvd3NlcjxUQ3JlZGVudGlhbHMgZXh0ZW5kcyBTY3JhcGVyQ3JlZGVudGlhbHM+IGV4dGVuZHMgQmFzZVNjcmFwZXI8VENyZWRlbnRpYWxzPiB7XG4gIHByaXZhdGUgY2xlYW51cHM6IEFycmF5PCgpID0+IFByb21pc2U8dm9pZD4+ID0gW107XG5cbiAgcHJpdmF0ZSBkZWZhdWx0Vmlld3BvcnRTaXplID0ge1xuICAgIHdpZHRoOiAxMDI0LFxuICAgIGhlaWdodDogNzY4LFxuICB9O1xuXG4gIC8vIE5PVElDRSAtIGl0IGlzIGRpc2NvdXJhZ2VkIHRvIHVzZSBiYW5nICghKSBpbiBnZW5lcmFsLiBJdCBpcyB1c2VkIGhlcmUgYmVjYXVzZVxuICAvLyBhbGwgdGhlIGNsYXNzZXMgdGhhdCBpbmhlcml0IGZyb20gdGhpcyBiYXNlIGFzc3VtZSBpcyBpdCBtYW5kYXRvcnkuXG4gIHByb3RlY3RlZCBwYWdlITogUGFnZTtcblxuICBwcm90ZWN0ZWQgZ2V0Vmlld1BvcnQoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy52aWV3cG9ydFNpemUgPz8gdGhpcy5kZWZhdWx0Vmlld3BvcnRTaXplO1xuICB9XG5cbiAgYXN5bmMgaW5pdGlhbGl6ZSgpIHtcbiAgICBhd2FpdCBzdXBlci5pbml0aWFsaXplKCk7XG4gICAgZGVidWcoJ2luaXRpYWxpemUgc2NyYXBlcicpO1xuICAgIHRoaXMuZW1pdFByb2dyZXNzKFNjcmFwZXJQcm9ncmVzc1R5cGVzLkluaXRpYWxpemluZyk7XG5cbiAgICBjb25zdCBwYWdlID0gYXdhaXQgdGhpcy5pbml0aWFsaXplUGFnZSgpO1xuICAgIGF3YWl0IHBhZ2Uuc2V0Q2FjaGVFbmFibGVkKGZhbHNlKTsgLy8gQ2xlYXIgY2FjaGUgYW5kIGF2b2lkIDMwMCdzIHJlc3BvbnNlIHN0YXR1c1xuXG4gICAgaWYgKCFwYWdlKSB7XG4gICAgICBkZWJ1ZygnZmFpbGVkIHRvIGluaXRpYXRlIGEgYnJvd3NlciBwYWdlLCBleGl0Jyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wYWdlID0gcGFnZTtcblxuICAgIHRoaXMuY2xlYW51cHMucHVzaCgoKSA9PiBwYWdlLmNsb3NlKCkpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5kZWZhdWx0VGltZW91dCkge1xuICAgICAgdGhpcy5wYWdlLnNldERlZmF1bHRUaW1lb3V0KHRoaXMub3B0aW9ucy5kZWZhdWx0VGltZW91dCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5wcmVwYXJlUGFnZSkge1xuICAgICAgZGVidWcoXCJleGVjdXRlICdwcmVwYXJlUGFnZScgaW50ZXJjZXB0b3IgcHJvdmlkZWQgaW4gb3B0aW9uc1wiKTtcbiAgICAgIGF3YWl0IHRoaXMub3B0aW9ucy5wcmVwYXJlUGFnZSh0aGlzLnBhZ2UpO1xuICAgIH1cblxuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy5nZXRWaWV3UG9ydCgpO1xuICAgIGRlYnVnKGBzZXQgdmlld3BvcnQgdG8gd2lkdGggJHt2aWV3cG9ydC53aWR0aH0sIGhlaWdodCAke3ZpZXdwb3J0LmhlaWdodH1gKTtcbiAgICBhd2FpdCB0aGlzLnBhZ2Uuc2V0Vmlld3BvcnQoe1xuICAgICAgd2lkdGg6IHZpZXdwb3J0LndpZHRoLFxuICAgICAgaGVpZ2h0OiB2aWV3cG9ydC5oZWlnaHQsXG4gICAgfSk7XG5cbiAgICB0aGlzLnBhZ2Uub24oJ3JlcXVlc3RmYWlsZWQnLCByZXF1ZXN0ID0+IHtcbiAgICAgIGRlYnVnKCdSZXF1ZXN0IGZhaWxlZDogJXMgJXMnLCByZXF1ZXN0LmZhaWx1cmUoKT8uZXJyb3JUZXh0LCByZXF1ZXN0LnVybCgpKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5pdGlhbGl6ZVBhZ2UoKSB7XG4gICAgZGVidWcoJ2luaXRpYWxpemUgYnJvd3NlciBwYWdlJyk7XG4gICAgaWYgKCdicm93c2VyQ29udGV4dCcgaW4gdGhpcy5vcHRpb25zKSB7XG4gICAgICBkZWJ1ZygnVXNpbmcgdGhlIGJyb3dzZXIgY29udGV4dCBwcm92aWRlZCBpbiBvcHRpb25zJyk7XG4gICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmJyb3dzZXJDb250ZXh0Lm5ld1BhZ2UoKTtcbiAgICB9XG5cbiAgICBpZiAoJ2Jyb3dzZXInIGluIHRoaXMub3B0aW9ucykge1xuICAgICAgZGVidWcoJ1VzaW5nIHRoZSBicm93c2VyIGluc3RhbmNlIHByb3ZpZGVkIGluIG9wdGlvbnMnKTtcbiAgICAgIGNvbnN0IHsgYnJvd3NlciB9ID0gdGhpcy5vcHRpb25zO1xuXG4gICAgICAvKipcbiAgICAgICAqIEZvciBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LCB3ZSB3aWxsIGNsb3NlIHRoZSBicm93c2VyIGV2ZW4gaWYgd2UgZGlkbid0IGNyZWF0ZSBpdFxuICAgICAgICovXG4gICAgICBpZiAoIXRoaXMub3B0aW9ucy5za2lwQ2xvc2VCcm93c2VyKSB7XG4gICAgICAgIHRoaXMuY2xlYW51cHMucHVzaChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgZGVidWcoJ2Nsb3NpbmcgdGhlIGJyb3dzZXInKTtcbiAgICAgICAgICBhd2FpdCBicm93c2VyLmNsb3NlKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYnJvd3Nlci5uZXdQYWdlKCk7XG4gICAgfVxuXG4gICAgY29uc3QgeyB0aW1lb3V0LCBhcmdzLCBleGVjdXRhYmxlUGF0aCwgc2hvd0Jyb3dzZXIgfSA9IHRoaXMub3B0aW9ucztcblxuICAgIGNvbnN0IGhlYWRsZXNzID0gIXNob3dCcm93c2VyO1xuICAgIGRlYnVnKGBsYXVuY2ggYSBicm93c2VyIHdpdGggaGVhZGxlc3MgbW9kZSA9ICR7aGVhZGxlc3N9YCk7XG5cbiAgICBjb25zdCBicm93c2VyID0gYXdhaXQgcHVwcGV0ZWVyLmxhdW5jaCh7XG4gICAgICBlbnY6IHRoaXMub3B0aW9ucy52ZXJib3NlID8geyBERUJVRzogJyonLCAuLi5wcm9jZXNzLmVudiB9IDogdW5kZWZpbmVkLFxuICAgICAgaGVhZGxlc3MsXG4gICAgICBleGVjdXRhYmxlUGF0aCxcbiAgICAgIGFyZ3MsXG4gICAgICB0aW1lb3V0LFxuICAgIH0pO1xuXG4gICAgdGhpcy5jbGVhbnVwcy5wdXNoKGFzeW5jICgpID0+IHtcbiAgICAgIGRlYnVnKCdjbG9zaW5nIHRoZSBicm93c2VyJyk7XG4gICAgICBhd2FpdCBicm93c2VyLmNsb3NlKCk7XG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLnByZXBhcmVCcm93c2VyKSB7XG4gICAgICBkZWJ1ZyhcImV4ZWN1dGUgJ3ByZXBhcmVCcm93c2VyJyBpbnRlcmNlcHRvciBwcm92aWRlZCBpbiBvcHRpb25zXCIpO1xuICAgICAgYXdhaXQgdGhpcy5vcHRpb25zLnByZXBhcmVCcm93c2VyKGJyb3dzZXIpO1xuICAgIH1cblxuICAgIGRlYnVnKCdjcmVhdGUgYSBuZXcgYnJvd3NlciBwYWdlJyk7XG4gICAgcmV0dXJuIGJyb3dzZXIubmV3UGFnZSgpO1xuICB9XG5cbiAgYXN5bmMgbmF2aWdhdGVUbyhcbiAgICB1cmw6IHN0cmluZyxcbiAgICB3YWl0VW50aWw6IFB1cHBldGVlckxpZmVDeWNsZUV2ZW50IHwgdW5kZWZpbmVkID0gJ2xvYWQnLFxuICAgIHJldHJpZXMgPSB0aGlzLm9wdGlvbnMubmF2aWdhdGlvblJldHJ5Q291bnQgPz8gMCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnBhZ2U/LmdvdG8odXJsLCB7IHdhaXRVbnRpbCB9KTtcbiAgICBpZiAocmVzcG9uc2UgPT09IG51bGwpIHtcbiAgICAgIC8vIG5vdGU6IHJlc3BvbnNlIHdpbGwgYmUgbnVsbCB3aGVuIG5hdmlnYXRpbmcgdG8gc2FtZSB1cmwgd2hpbGUgY2hhbmdpbmcgdGhlIGhhc2ggcGFydC5cbiAgICAgIC8vIHRoZSBjb25kaXRpb24gYmVsb3cgd2lsbCBhbHdheXMgYWNjZXB0IG51bGwgYXMgdmFsaWQgcmVzdWx0LlxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hpbGUgdHJ5aW5nIHRvIG5hdmlnYXRlIHRvIHVybCAke3VybH0sIHJlc3BvbnNlIGlzIHVuZGVmaW5lZGApO1xuICAgIH1cblxuICAgIGlmICghcmVzcG9uc2Uub2soKSkge1xuICAgICAgY29uc3Qgc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzKCk7XG4gICAgICBpZiAocmV0cmllcyA+IDApIHtcbiAgICAgICAgZGVidWcoYEZhaWxlZCB0byBuYXZpZ2F0ZSB0byB1cmwgJHt1cmx9LCBzdGF0dXMgY29kZTogJHtzdGF0dXN9LCByZXRyeWluZyAke3JldHJpZXN9IG1vcmUgdGltZXNgKTtcbiAgICAgICAgYXdhaXQgdGhpcy5uYXZpZ2F0ZVRvKHVybCwgd2FpdFVudGlsLCByZXRyaWVzIC0gMSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBuYXZpZ2F0ZSB0byB1cmwgJHt1cmx9LCBzdGF0dXMgY29kZTogJHtzdGF0dXN9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBnZXRMb2dpbk9wdGlvbnMoX2NyZWRlbnRpYWxzOiBTY3JhcGVyQ3JlZGVudGlhbHMpOiBMb2dpbk9wdGlvbnMge1xuICAgIHRocm93IG5ldyBFcnJvcihgZ2V0TG9naW5PcHRpb25zKCkgaXMgbm90IGNyZWF0ZWQgaW4gJHt0aGlzLm9wdGlvbnMuY29tcGFueUlkfWApO1xuICB9XG5cbiAgYXN5bmMgZmlsbElucHV0cyhwYWdlT3JGcmFtZTogUGFnZSB8IEZyYW1lLCBmaWVsZHM6IHsgc2VsZWN0b3I6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9W10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBtb2RpZmllZCA9IFsuLi5maWVsZHNdO1xuICAgIGNvbnN0IGlucHV0ID0gbW9kaWZpZWQuc2hpZnQoKTtcblxuICAgIGlmICghaW5wdXQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgZmlsbElucHV0KHBhZ2VPckZyYW1lLCBpbnB1dC5zZWxlY3RvciwgaW5wdXQudmFsdWUpO1xuICAgIGlmIChtb2RpZmllZC5sZW5ndGgpIHtcbiAgICAgIGF3YWl0IHRoaXMuZmlsbElucHV0cyhwYWdlT3JGcmFtZSwgbW9kaWZpZWQpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGxvZ2luKGNyZWRlbnRpYWxzOiBTY3JhcGVyQ3JlZGVudGlhbHMpOiBQcm9taXNlPFNjcmFwZXJTY3JhcGluZ1Jlc3VsdD4ge1xuICAgIGlmICghY3JlZGVudGlhbHMgfHwgIXRoaXMucGFnZSkge1xuICAgICAgcmV0dXJuIGNyZWF0ZUdlbmVyYWxFcnJvcigpO1xuICAgIH1cblxuICAgIGRlYnVnKCdleGVjdXRlIGxvZ2luIHByb2Nlc3MnKTtcbiAgICBjb25zdCBsb2dpbk9wdGlvbnMgPSB0aGlzLmdldExvZ2luT3B0aW9ucyhjcmVkZW50aWFscyk7XG5cbiAgICBpZiAobG9naW5PcHRpb25zLnVzZXJBZ2VudCkge1xuICAgICAgZGVidWcoJ3NldCBjdXN0b20gdXNlciBhZ2VudCBwcm92aWRlZCBpbiBvcHRpb25zJyk7XG4gICAgICBhd2FpdCB0aGlzLnBhZ2Uuc2V0VXNlckFnZW50KGxvZ2luT3B0aW9ucy51c2VyQWdlbnQpO1xuICAgIH1cblxuICAgIGRlYnVnKCduYXZpZ2F0ZSB0byBsb2dpbiB1cmwnKTtcbiAgICBhd2FpdCB0aGlzLm5hdmlnYXRlVG8obG9naW5PcHRpb25zLmxvZ2luVXJsLCBsb2dpbk9wdGlvbnMud2FpdFVudGlsKTtcbiAgICBpZiAobG9naW5PcHRpb25zLmNoZWNrUmVhZGluZXNzKSB7XG4gICAgICBkZWJ1ZyhcImV4ZWN1dGUgJ2NoZWNrUmVhZGluZXNzJyBpbnRlcmNlcHRvciBwcm92aWRlZCBpbiBsb2dpbiBvcHRpb25zXCIpO1xuICAgICAgYXdhaXQgbG9naW5PcHRpb25zLmNoZWNrUmVhZGluZXNzKCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgbG9naW5PcHRpb25zLnN1Ym1pdEJ1dHRvblNlbGVjdG9yID09PSAnc3RyaW5nJykge1xuICAgICAgZGVidWcoJ3dhaXQgdW50aWwgc3VibWl0IGJ1dHRvbiBpcyBhdmFpbGFibGUnKTtcbiAgICAgIGF3YWl0IHdhaXRVbnRpbEVsZW1lbnRGb3VuZCh0aGlzLnBhZ2UsIGxvZ2luT3B0aW9ucy5zdWJtaXRCdXR0b25TZWxlY3Rvcik7XG4gICAgfVxuXG4gICAgbGV0IGxvZ2luRnJhbWVPclBhZ2U6IFBhZ2UgfCBGcmFtZSB8IG51bGwgPSB0aGlzLnBhZ2U7XG4gICAgaWYgKGxvZ2luT3B0aW9ucy5wcmVBY3Rpb24pIHtcbiAgICAgIGRlYnVnKFwiZXhlY3V0ZSAncHJlQWN0aW9uJyBpbnRlcmNlcHRvciBwcm92aWRlZCBpbiBsb2dpbiBvcHRpb25zXCIpO1xuICAgICAgbG9naW5GcmFtZU9yUGFnZSA9IChhd2FpdCBsb2dpbk9wdGlvbnMucHJlQWN0aW9uKCkpIHx8IHRoaXMucGFnZTtcbiAgICB9XG5cbiAgICBkZWJ1ZygnZmlsbCBsb2dpbiBjb21wb25lbnRzIGlucHV0IHdpdGggcmVsZXZhbnQgdmFsdWVzJyk7XG4gICAgYXdhaXQgdGhpcy5maWxsSW5wdXRzKGxvZ2luRnJhbWVPclBhZ2UsIGxvZ2luT3B0aW9ucy5maWVsZHMpO1xuICAgIGRlYnVnKCdjbGljayBvbiBsb2dpbiBzdWJtaXQgYnV0dG9uJyk7XG4gICAgaWYgKHR5cGVvZiBsb2dpbk9wdGlvbnMuc3VibWl0QnV0dG9uU2VsZWN0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICBhd2FpdCBjbGlja0J1dHRvbihsb2dpbkZyYW1lT3JQYWdlLCBsb2dpbk9wdGlvbnMuc3VibWl0QnV0dG9uU2VsZWN0b3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBsb2dpbk9wdGlvbnMuc3VibWl0QnV0dG9uU2VsZWN0b3IoKTtcbiAgICB9XG4gICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuTG9nZ2luZ0luKTtcblxuICAgIGlmIChsb2dpbk9wdGlvbnMucG9zdEFjdGlvbikge1xuICAgICAgZGVidWcoXCJleGVjdXRlICdwb3N0QWN0aW9uJyBpbnRlcmNlcHRvciBwcm92aWRlZCBpbiBsb2dpbiBvcHRpb25zXCIpO1xuICAgICAgYXdhaXQgbG9naW5PcHRpb25zLnBvc3RBY3Rpb24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWcoJ3dhaXQgZm9yIHBhZ2UgbmF2aWdhdGlvbicpO1xuICAgICAgYXdhaXQgd2FpdEZvck5hdmlnYXRpb24odGhpcy5wYWdlKTtcbiAgICB9XG5cbiAgICBkZWJ1ZygnY2hlY2sgbG9naW4gcmVzdWx0Jyk7XG4gICAgY29uc3QgY3VycmVudCA9IGF3YWl0IGdldEN1cnJlbnRVcmwodGhpcy5wYWdlLCB0cnVlKTtcbiAgICBjb25zdCBsb2dpblJlc3VsdCA9IGF3YWl0IGdldEtleUJ5VmFsdWUobG9naW5PcHRpb25zLnBvc3NpYmxlUmVzdWx0cywgY3VycmVudCwgdGhpcy5wYWdlKTtcbiAgICBkZWJ1ZyhgaGFuZGxlIGxvZ2luIHJlc3VsdHMgJHtsb2dpblJlc3VsdH1gKTtcbiAgICByZXR1cm4gdGhpcy5oYW5kbGVMb2dpblJlc3VsdChsb2dpblJlc3VsdCk7XG4gIH1cblxuICBhc3luYyB0ZXJtaW5hdGUoX3N1Y2Nlc3M6IGJvb2xlYW4pIHtcbiAgICBkZWJ1ZyhgdGVybWluYXRpbmcgYnJvd3NlciB3aXRoIHN1Y2Nlc3MgPSAke19zdWNjZXNzfWApO1xuICAgIHRoaXMuZW1pdFByb2dyZXNzKFNjcmFwZXJQcm9ncmVzc1R5cGVzLlRlcm1pbmF0aW5nKTtcblxuICAgIGlmICghX3N1Y2Nlc3MgJiYgISF0aGlzLm9wdGlvbnMuc3RvcmVGYWlsdXJlU2NyZWVuU2hvdFBhdGgpIHtcbiAgICAgIGRlYnVnKGBjcmVhdGUgYSBzbmFwc2hvdCBiZWZvcmUgdGVybWluYXRlZCBpbiAke3RoaXMub3B0aW9ucy5zdG9yZUZhaWx1cmVTY3JlZW5TaG90UGF0aH1gKTtcbiAgICAgIGF3YWl0IHRoaXMucGFnZS5zY3JlZW5zaG90KHtcbiAgICAgICAgcGF0aDogdGhpcy5vcHRpb25zLnN0b3JlRmFpbHVyZVNjcmVlblNob3RQYXRoLFxuICAgICAgICBmdWxsUGFnZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuY2xlYW51cHMucmV2ZXJzZSgpLm1hcChzYWZlQ2xlYW51cCkpO1xuICAgIHRoaXMuY2xlYW51cHMgPSBbXTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlTG9naW5SZXN1bHQobG9naW5SZXN1bHQ6IExvZ2luUmVzdWx0cykge1xuICAgIHN3aXRjaCAobG9naW5SZXN1bHQpIHtcbiAgICAgIGNhc2UgTG9naW5SZXN1bHRzLlN1Y2Nlc3M6XG4gICAgICAgIHRoaXMuZW1pdFByb2dyZXNzKFNjcmFwZXJQcm9ncmVzc1R5cGVzLkxvZ2luU3VjY2Vzcyk7XG4gICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfTtcbiAgICAgIGNhc2UgTG9naW5SZXN1bHRzLkludmFsaWRQYXNzd29yZDpcbiAgICAgIGNhc2UgTG9naW5SZXN1bHRzLlVua25vd25FcnJvcjpcbiAgICAgICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuTG9naW5GYWlsZWQpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIGVycm9yVHlwZTpcbiAgICAgICAgICAgIGxvZ2luUmVzdWx0ID09PSBMb2dpblJlc3VsdHMuSW52YWxpZFBhc3N3b3JkXG4gICAgICAgICAgICAgID8gU2NyYXBlckVycm9yVHlwZXMuSW52YWxpZFBhc3N3b3JkXG4gICAgICAgICAgICAgIDogU2NyYXBlckVycm9yVHlwZXMuR2VuZXJhbCxcbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IGBMb2dpbiBmYWlsZWQgd2l0aCAke2xvZ2luUmVzdWx0fSBlcnJvcmAsXG4gICAgICAgIH07XG4gICAgICBjYXNlIExvZ2luUmVzdWx0cy5DaGFuZ2VQYXNzd29yZDpcbiAgICAgICAgdGhpcy5lbWl0UHJvZ3Jlc3MoU2NyYXBlclByb2dyZXNzVHlwZXMuQ2hhbmdlUGFzc3dvcmQpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIGVycm9yVHlwZTogU2NyYXBlckVycm9yVHlwZXMuQ2hhbmdlUGFzc3dvcmQsXG4gICAgICAgIH07XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuZXhwZWN0ZWQgbG9naW4gcmVzdWx0IFwiJHtsb2dpblJlc3VsdH1cImApO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgeyBCYXNlU2NyYXBlcldpdGhCcm93c2VyIH07XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLElBQUFBLFVBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFlBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLE1BQUEsR0FBQUYsT0FBQTtBQUNBLElBQUFHLHFCQUFBLEdBQUFILE9BQUE7QUFDQSxJQUFBSSxXQUFBLEdBQUFKLE9BQUE7QUFDQSxJQUFBSyxZQUFBLEdBQUFMLE9BQUE7QUFDQSxJQUFBTSxPQUFBLEdBQUFOLE9BQUE7QUFBNkMsU0FBQUQsdUJBQUFRLENBQUEsV0FBQUEsQ0FBQSxJQUFBQSxDQUFBLENBQUFDLFVBQUEsR0FBQUQsQ0FBQSxLQUFBRSxPQUFBLEVBQUFGLENBQUE7QUFHN0MsTUFBTUcsS0FBSyxHQUFHLElBQUFDLGVBQVEsRUFBQywyQkFBMkIsQ0FBQztBQUFDLElBRS9DQyxnQkFBZ0IsMEJBQWhCQSxnQkFBZ0I7RUFBaEJBLGdCQUFnQjtFQUFoQkEsZ0JBQWdCO0VBQUEsT0FBaEJBLGdCQUFn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