4216 lines
No EOL
391 KiB
JavaScript
4216 lines
No EOL
391 KiB
JavaScript
module.exports =
|
|
/******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId]) {
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
/******/
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, {
|
|
/******/ configurable: false,
|
|
/******/ enumerable: true,
|
|
/******/ get: getter
|
|
/******/ });
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "/";
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(__webpack_require__.s = 26);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("winston");
|
|
|
|
/***/ }),
|
|
/* 1 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
module.exports = {
|
|
handleErrorResponse: function handleErrorResponse(originalUrl, ip, error, res) {
|
|
logger.error('Error on ' + originalUrl, module.exports.useObjectPropertiesIfNoKeys(error));
|
|
|
|
var _module$exports$retur = module.exports.returnErrorMessageAndStatus(error),
|
|
_module$exports$retur2 = _slicedToArray(_module$exports$retur, 2),
|
|
status = _module$exports$retur2[0],
|
|
message = _module$exports$retur2[1];
|
|
|
|
res.status(status).json(module.exports.createErrorResponsePayload(status, message));
|
|
},
|
|
returnErrorMessageAndStatus: function returnErrorMessageAndStatus(error) {
|
|
var status = void 0,
|
|
message = void 0;
|
|
// check for daemon being turned off
|
|
if (error.code === 'ECONNREFUSED') {
|
|
status = 503;
|
|
message = 'Connection refused. The daemon may not be running.';
|
|
// fallback for everything else
|
|
} else {
|
|
status = 400;
|
|
if (error.message) {
|
|
message = error.message;
|
|
} else {
|
|
message = error;
|
|
};
|
|
};
|
|
return [status, message];
|
|
},
|
|
useObjectPropertiesIfNoKeys: function useObjectPropertiesIfNoKeys(err) {
|
|
if (Object.keys(err).length === 0) {
|
|
var newErrorObject = {};
|
|
Object.getOwnPropertyNames(err).forEach(function (key) {
|
|
newErrorObject[key] = err[key];
|
|
});
|
|
return newErrorObject;
|
|
}
|
|
return err;
|
|
},
|
|
createErrorResponsePayload: function createErrorResponsePayload(status, message) {
|
|
return {
|
|
status: status,
|
|
success: false,
|
|
message: message
|
|
};
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 2 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var Certificate = __webpack_require__(45);
|
|
var Channel = __webpack_require__(46);
|
|
var Claim = __webpack_require__(47);
|
|
var File = __webpack_require__(48);
|
|
var Request = __webpack_require__(49);
|
|
var User = __webpack_require__(50);
|
|
|
|
var Sequelize = __webpack_require__(13);
|
|
var logger = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(10),
|
|
database = _require.database,
|
|
username = _require.username,
|
|
password = _require.password;
|
|
|
|
// set sequelize options
|
|
|
|
|
|
var sequelize = new Sequelize(database, username, password, {
|
|
host: 'localhost',
|
|
dialect: 'mysql',
|
|
dialectOptions: { decimalNumbers: true },
|
|
logging: false,
|
|
pool: {
|
|
max: 5,
|
|
min: 0,
|
|
idle: 10000,
|
|
acquire: 10000
|
|
}
|
|
});
|
|
|
|
// establish mysql connection
|
|
sequelize.authenticate().then(function () {
|
|
logger.info('Sequelize has established mysql connection successfully.');
|
|
}).catch(function (err) {
|
|
logger.error('Sequelize was unable to connect to the database:', err);
|
|
});
|
|
|
|
// manually add each model to the db object (note: make this dynamic)
|
|
var db = {};
|
|
db['Certificate'] = sequelize.import('Certificate', Certificate);
|
|
db['Channel'] = sequelize.import('Channel', Channel);
|
|
db['Claim'] = sequelize.import('Claim', Claim);
|
|
db['File'] = sequelize.import('File', File);
|
|
db['Request'] = sequelize.import('Request', Request);
|
|
db['User'] = sequelize.import('User', User);
|
|
|
|
// run model.association for each model in the db object that has an association
|
|
logger.info('associating db models...');
|
|
Object.keys(db).forEach(function (modelName) {
|
|
if (db[modelName].associate) {
|
|
logger.info('Associating model:', modelName);
|
|
db[modelName].associate(db);
|
|
}
|
|
});
|
|
|
|
// add sequelize/Sequelize to db
|
|
db.sequelize = sequelize;
|
|
db.Sequelize = Sequelize;
|
|
// add an 'upsert' method to the db object
|
|
db.upsert = function (Model, values, condition, tableName) {
|
|
return Model.findOne({
|
|
where: condition
|
|
}).then(function (obj) {
|
|
if (obj) {
|
|
// update
|
|
logger.debug('updating record in db.' + tableName);
|
|
return obj.update(values);
|
|
} else {
|
|
// insert
|
|
logger.debug('creating record in db.' + tableName);
|
|
return Model.create(values);
|
|
}
|
|
}).catch(function (error) {
|
|
logger.error(tableName + '.upsert error', error);
|
|
throw error;
|
|
});
|
|
};
|
|
|
|
module.exports = db;
|
|
|
|
/***/ }),
|
|
/* 3 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
function SiteConfig() {
|
|
var _this = this;
|
|
|
|
this.analytics = {
|
|
googleId: 'default'
|
|
};
|
|
this.assetDefaults = {
|
|
description: 'An asset published on Spee.ch',
|
|
thumbnail: 'https://spee.ch/assets/img/video_thumb_default.png',
|
|
title: 'Spee.ch'
|
|
};
|
|
this.auth = {
|
|
sessionKey: 'default'
|
|
};
|
|
this.customComponents = {};
|
|
this.customContainers = {};
|
|
this.customPages = {};
|
|
this.details = {
|
|
description: 'Open-source, decentralized image and video sharing.',
|
|
host: 'default',
|
|
port: 3000,
|
|
title: 'Spee.ch',
|
|
twitter: '@spee_ch'
|
|
};
|
|
this.publishing = {
|
|
additionalClaimAddresses: [],
|
|
disabled: false,
|
|
disabledMessage: 'Please check back soon.',
|
|
primaryClaimAddress: 'default',
|
|
thumbnailChannel: 'default',
|
|
thumbnailChannelId: 'default',
|
|
uploadDirectory: '/home/lbry/Uploads'
|
|
};
|
|
this.routes = {};
|
|
this.update = function (config) {
|
|
if (!config) {
|
|
return console.log('No site config received.');
|
|
}
|
|
var analytics = config.analytics,
|
|
assetDefaults = config.assetDefaults,
|
|
auth = config.auth,
|
|
customComponents = config.customComponents,
|
|
customContainers = config.customContainers,
|
|
customPages = config.customPages,
|
|
details = config.details,
|
|
publishing = config.publishing,
|
|
routes = config.routes;
|
|
|
|
console.log('Configuring site details...');
|
|
_this.analytics = analytics;
|
|
_this.assetDefaults = assetDefaults;
|
|
_this.auth = auth;
|
|
_this.details = details;
|
|
_this.publishing = publishing;
|
|
_this.customComponents = customComponents;
|
|
_this.customContainers = customContainers;
|
|
_this.customPages = customPages;
|
|
_this.routes = routes;
|
|
};
|
|
};
|
|
|
|
module.exports = new SiteConfig();
|
|
|
|
/***/ }),
|
|
/* 4 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
var ua = __webpack_require__(55);
|
|
|
|
var _require = __webpack_require__(3),
|
|
googleId = _require.analytics.googleId,
|
|
title = _require.details.title;
|
|
|
|
function createServeEventParams(headers, ip, originalUrl) {
|
|
return {
|
|
eventCategory: 'client requests',
|
|
eventAction: 'serve request',
|
|
eventLabel: originalUrl,
|
|
ipOverride: ip,
|
|
userAgentOverride: headers['user-agent']
|
|
};
|
|
};
|
|
|
|
function createPublishTimingEventParams(category, variable, label, startTime, endTime) {
|
|
var duration = endTime - startTime;
|
|
return {
|
|
userTimingCategory: category,
|
|
userTimingVariableName: variable,
|
|
userTimingTime: duration,
|
|
userTimingLabel: label
|
|
};
|
|
};
|
|
|
|
function sendGoogleAnalyticsEvent(ip, params) {
|
|
var visitorId = ip.replace(/\./g, '-');
|
|
var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });
|
|
visitor.event(params, function (err) {
|
|
if (err) {
|
|
logger.error('Google Analytics Event Error >>', err);
|
|
}
|
|
});
|
|
};
|
|
|
|
function sendGoogleAnalyticsTiming(visitorId, params) {
|
|
var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });
|
|
visitor.timing(params, function (err) {
|
|
if (err) {
|
|
logger.error('Google Analytics Event Error >>', err);
|
|
}
|
|
logger.debug('Timing event successfully sent to google analytics');
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
sendGAServeEvent: function sendGAServeEvent(headers, ip, originalUrl) {
|
|
var params = createServeEventParams(headers, ip, originalUrl);
|
|
sendGoogleAnalyticsEvent(ip, params);
|
|
},
|
|
sendGATimingEvent: function sendGATimingEvent(category, variable, label, startTime, endTime) {
|
|
var params = createPublishTimingEventParams(category, variable, label, startTime, endTime);
|
|
sendGoogleAnalyticsTiming(title, params);
|
|
},
|
|
chooseGaLbrynetPublishLabel: function chooseGaLbrynetPublishLabel(_ref) {
|
|
var channelName = _ref.channel_name,
|
|
channelId = _ref.channel_id;
|
|
|
|
return channelName || channelId ? 'PUBLISH_IN_CHANNEL_CLAIM' : 'PUBLISH_ANONYMOUS_CLAIM';
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 5 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var axios = __webpack_require__(53);
|
|
var logger = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(54),
|
|
_require$api = _require.api,
|
|
apiHost = _require$api.apiHost,
|
|
apiPort = _require$api.apiPort;
|
|
|
|
var lbryApiUri = 'http://' + apiHost + ':' + apiPort;
|
|
|
|
var _require2 = __webpack_require__(4),
|
|
chooseGaLbrynetPublishLabel = _require2.chooseGaLbrynetPublishLabel,
|
|
sendGATimingEvent = _require2.sendGATimingEvent;
|
|
|
|
var handleLbrynetResponse = function handleLbrynetResponse(_ref, resolve, reject) {
|
|
var data = _ref.data;
|
|
|
|
logger.debug('lbry api data:', data);
|
|
if (data.result) {
|
|
// check for an error
|
|
if (data.result.error) {
|
|
logger.debug('Lbrynet api error:', data.result.error);
|
|
reject(new Error(data.result.error));
|
|
return;
|
|
};
|
|
resolve(data.result);
|
|
return;
|
|
}
|
|
// fallback in case it just timed out
|
|
reject(JSON.stringify(data));
|
|
};
|
|
|
|
module.exports = {
|
|
publishClaim: function publishClaim(publishParams) {
|
|
logger.debug('lbryApi >> Publishing claim to "' + publishParams.name + '"');
|
|
var gaStartTime = Date.now();
|
|
return new Promise(function (resolve, reject) {
|
|
axios.post(lbryApiUri, {
|
|
method: 'publish',
|
|
params: publishParams
|
|
}).then(function (response) {
|
|
sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now());
|
|
handleLbrynetResponse(response, resolve, reject);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getClaim: function getClaim(uri) {
|
|
logger.debug('lbryApi >> Getting Claim for "' + uri + '"');
|
|
var gaStartTime = Date.now();
|
|
return new Promise(function (resolve, reject) {
|
|
axios.post(lbryApiUri, {
|
|
method: 'get',
|
|
params: { uri: uri, timeout: 20 }
|
|
}).then(function (response) {
|
|
sendGATimingEvent('lbrynet', 'getClaim', 'GET', gaStartTime, Date.now());
|
|
handleLbrynetResponse(response, resolve, reject);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getClaimList: function getClaimList(claimName) {
|
|
logger.debug('lbryApi >> Getting claim_list for "' + claimName + '"');
|
|
var gaStartTime = Date.now();
|
|
return new Promise(function (resolve, reject) {
|
|
axios.post(lbryApiUri, {
|
|
method: 'claim_list',
|
|
params: { name: claimName }
|
|
}).then(function (response) {
|
|
sendGATimingEvent('lbrynet', 'getClaimList', 'CLAIM_LIST', gaStartTime, Date.now());
|
|
handleLbrynetResponse(response, resolve, reject);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
resolveUri: function resolveUri(uri) {
|
|
logger.debug('lbryApi >> Resolving URI for "' + uri + '"');
|
|
var gaStartTime = Date.now();
|
|
return new Promise(function (resolve, reject) {
|
|
axios.post(lbryApiUri, {
|
|
method: 'resolve',
|
|
params: { uri: uri }
|
|
}).then(function (_ref2) {
|
|
var data = _ref2.data;
|
|
|
|
sendGATimingEvent('lbrynet', 'resolveUri', 'RESOLVE', gaStartTime, Date.now());
|
|
if (data.result[uri].error) {
|
|
// check for errors
|
|
reject(data.result[uri].error);
|
|
} else {
|
|
// if no errors, resolve
|
|
resolve(data.result[uri]);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getDownloadDirectory: function getDownloadDirectory() {
|
|
logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...');
|
|
var gaStartTime = Date.now();
|
|
return new Promise(function (resolve, reject) {
|
|
axios.post(lbryApiUri, {
|
|
method: 'settings_get'
|
|
}).then(function (_ref3) {
|
|
var data = _ref3.data;
|
|
|
|
sendGATimingEvent('lbrynet', 'getDownloadDirectory', 'SETTINGS_GET', gaStartTime, Date.now());
|
|
if (data.result) {
|
|
resolve(data.result.download_directory);
|
|
} else {
|
|
return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.');
|
|
}
|
|
}).catch(function (error) {
|
|
logger.error('Lbrynet Error:', error);
|
|
resolve('/home/lbry/Downloads/');
|
|
});
|
|
});
|
|
},
|
|
createChannel: function createChannel(name) {
|
|
logger.debug('lbryApi >> Creating channel for ' + name + '...');
|
|
var gaStartTime = Date.now();
|
|
return new Promise(function (resolve, reject) {
|
|
axios.post(lbryApiUri, {
|
|
method: 'channel_new',
|
|
params: {
|
|
channel_name: name,
|
|
amount: 0.1
|
|
}
|
|
}).then(function (response) {
|
|
sendGATimingEvent('lbrynet', 'createChannel', 'CHANNEL_NEW', gaStartTime, Date.now());
|
|
handleLbrynetResponse(response, resolve, reject);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 6 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var db = __webpack_require__(2);
|
|
var logger = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(66),
|
|
returnPaginatedChannelClaims = _require.returnPaginatedChannelClaims;
|
|
|
|
var NO_CHANNEL = 'NO_CHANNEL';
|
|
var NO_CLAIM = 'NO_CLAIM';
|
|
var NO_FILE = 'NO_FILE';
|
|
|
|
module.exports = {
|
|
getClaimId: function getClaimId(channelName, channelClaimId, name, claimId) {
|
|
if (channelName) {
|
|
return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);
|
|
} else {
|
|
return module.exports.getClaimIdByClaim(name, claimId);
|
|
}
|
|
},
|
|
getClaimIdByClaim: function getClaimIdByClaim(claimName, claimId) {
|
|
logger.debug('getClaimIdByClaim(' + claimName + ', ' + claimId + ')');
|
|
return new Promise(function (resolve, reject) {
|
|
db.Claim.getLongClaimId(claimName, claimId).then(function (longClaimId) {
|
|
if (!longClaimId) {
|
|
resolve(NO_CLAIM);
|
|
}
|
|
resolve(longClaimId);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getClaimIdByChannel: function getClaimIdByChannel(channelName, channelClaimId, claimName) {
|
|
logger.debug('getClaimIdByChannel(' + channelName + ', ' + channelClaimId + ', ' + claimName + ')');
|
|
return new Promise(function (resolve, reject) {
|
|
db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id
|
|
.then(function (longChannelId) {
|
|
if (!longChannelId) {
|
|
return [null, null];
|
|
}
|
|
return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id
|
|
}).then(function (_ref) {
|
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
longChannelId = _ref2[0],
|
|
longClaimId = _ref2[1];
|
|
|
|
if (!longChannelId) {
|
|
return resolve(NO_CHANNEL);
|
|
}
|
|
if (!longClaimId) {
|
|
return resolve(NO_CLAIM);
|
|
}
|
|
resolve(longClaimId);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getChannelData: function getChannelData(channelName, channelClaimId, page) {
|
|
return new Promise(function (resolve, reject) {
|
|
// 1. get the long channel Id (make sure channel exists)
|
|
db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (longChannelClaimId) {
|
|
if (!longChannelClaimId) {
|
|
return [null, null, null];
|
|
}
|
|
// 2. get the short ID and all claims for that channel
|
|
return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]);
|
|
}).then(function (_ref3) {
|
|
var _ref4 = _slicedToArray(_ref3, 2),
|
|
longChannelClaimId = _ref4[0],
|
|
shortChannelClaimId = _ref4[1];
|
|
|
|
if (!longChannelClaimId) {
|
|
return resolve(NO_CHANNEL);
|
|
}
|
|
// 3. return all the channel information
|
|
resolve({
|
|
channelName: channelName,
|
|
longChannelClaimId: longChannelClaimId,
|
|
shortChannelClaimId: shortChannelClaimId
|
|
});
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getChannelClaims: function getChannelClaims(channelName, channelClaimId, page) {
|
|
return new Promise(function (resolve, reject) {
|
|
// 1. get the long channel Id (make sure channel exists)
|
|
db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (longChannelClaimId) {
|
|
if (!longChannelClaimId) {
|
|
return [null, null, null];
|
|
}
|
|
// 2. get the short ID and all claims for that channel
|
|
return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]);
|
|
}).then(function (_ref5) {
|
|
var _ref6 = _slicedToArray(_ref5, 2),
|
|
longChannelClaimId = _ref6[0],
|
|
channelClaimsArray = _ref6[1];
|
|
|
|
if (!longChannelClaimId) {
|
|
return resolve(NO_CHANNEL);
|
|
}
|
|
// 3. format the data for the view, including pagination
|
|
var paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page);
|
|
// 4. return all the channel information and contents
|
|
resolve(paginatedChannelViewData);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
getLocalFileRecord: function getLocalFileRecord(claimId, name) {
|
|
return db.File.findOne({ where: { claimId: claimId, name: name } }).then(function (file) {
|
|
if (!file) {
|
|
return NO_FILE;
|
|
}
|
|
return file.dataValues;
|
|
});
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 7 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var passport = __webpack_require__(43);
|
|
var localLoginStrategy = __webpack_require__(44);
|
|
var localSignupStrategy = __webpack_require__(52);
|
|
|
|
var _require = __webpack_require__(56),
|
|
serializeSpeechUser = _require.serializeSpeechUser,
|
|
deserializeSpeechUser = _require.deserializeSpeechUser;
|
|
|
|
passport.deserializeUser(deserializeSpeechUser);
|
|
passport.serializeUser(serializeSpeechUser);
|
|
passport.use('local-login', localLoginStrategy);
|
|
passport.use('local-signup', localSignupStrategy);
|
|
|
|
module.exports = passport;
|
|
|
|
/***/ }),
|
|
/* 8 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
var logger = __webpack_require__(0);
|
|
var db = __webpack_require__(2);
|
|
var lbryApi = __webpack_require__(5);
|
|
var publishHelpers = __webpack_require__(9);
|
|
|
|
var _require = __webpack_require__(3),
|
|
_require$publishing = _require.publishing,
|
|
primaryClaimAddress = _require$publishing.primaryClaimAddress,
|
|
additionalClaimAddresses = _require$publishing.additionalClaimAddresses;
|
|
|
|
var Sequelize = __webpack_require__(13);
|
|
var Op = Sequelize.Op;
|
|
|
|
module.exports = {
|
|
publish: function publish(publishParams, fileName, fileType) {
|
|
return new Promise(function (resolve, reject) {
|
|
var publishResults = void 0,
|
|
certificateId = void 0,
|
|
channelName = void 0;
|
|
// publish the file
|
|
return lbryApi.publishClaim(publishParams).then(function (tx) {
|
|
logger.info('Successfully published ' + publishParams.name + ' ' + fileName, tx);
|
|
publishResults = tx;
|
|
// get the channel information
|
|
if (publishParams.channel_name) {
|
|
logger.debug('this claim was published in channel: ' + publishParams.channel_name);
|
|
return db.Channel.findOne({
|
|
where: {
|
|
channelName: publishParams.channel_name
|
|
}
|
|
});
|
|
} else {
|
|
logger.debug('this claim was not published in a channel');
|
|
return null;
|
|
}
|
|
}).then(function (channel) {
|
|
// set channel information
|
|
certificateId = null;
|
|
channelName = null;
|
|
if (channel) {
|
|
certificateId = channel.channelClaimId;
|
|
channelName = channel.channelName;
|
|
}
|
|
logger.debug('certificateId: ' + certificateId);
|
|
}).then(function () {
|
|
// create the File record
|
|
var fileRecord = {
|
|
name: publishParams.name,
|
|
claimId: publishResults.claim_id,
|
|
title: publishParams.metadata.title,
|
|
description: publishParams.metadata.description,
|
|
address: publishParams.claim_address,
|
|
outpoint: publishResults.txid + ':' + publishResults.nout,
|
|
height: 0,
|
|
fileName: fileName,
|
|
filePath: publishParams.file_path,
|
|
fileType: fileType,
|
|
nsfw: publishParams.metadata.nsfw
|
|
};
|
|
// create the Claim record
|
|
var claimRecord = {
|
|
name: publishParams.name,
|
|
claimId: publishResults.claim_id,
|
|
title: publishParams.metadata.title,
|
|
description: publishParams.metadata.description,
|
|
address: publishParams.claim_address,
|
|
thumbnail: publishParams.metadata.thumbnail,
|
|
outpoint: publishResults.txid + ':' + publishResults.nout,
|
|
height: 0,
|
|
contentType: fileType,
|
|
nsfw: publishParams.metadata.nsfw,
|
|
amount: publishParams.bid,
|
|
certificateId: certificateId,
|
|
channelName: channelName
|
|
};
|
|
// upsert criteria
|
|
var upsertCriteria = {
|
|
name: publishParams.name,
|
|
claimId: publishResults.claim_id
|
|
};
|
|
// upsert the records
|
|
return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]);
|
|
}).then(function (_ref) {
|
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
file = _ref2[0],
|
|
claim = _ref2[1];
|
|
|
|
logger.debug('File and Claim records successfully created');
|
|
return Promise.all([file.setClaim(claim), claim.setFile(file)]);
|
|
}).then(function () {
|
|
logger.debug('File and Claim records successfully associated');
|
|
resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim;
|
|
}).catch(function (error) {
|
|
logger.error('PUBLISH ERROR', error);
|
|
publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file
|
|
reject(error);
|
|
});
|
|
});
|
|
},
|
|
claimNameIsAvailable: function claimNameIsAvailable(name) {
|
|
var claimAddresses = additionalClaimAddresses || [];
|
|
claimAddresses.push(primaryClaimAddress);
|
|
// find any records where the name is used
|
|
return db.Claim.findAll({
|
|
attributes: ['address'],
|
|
where: {
|
|
name: name,
|
|
address: _defineProperty({}, Op.or, claimAddresses)
|
|
}
|
|
}).then(function (result) {
|
|
if (result.length >= 1) {
|
|
throw new Error('That claim is already in use');
|
|
};
|
|
return name;
|
|
}).catch(function (error) {
|
|
throw error;
|
|
});
|
|
},
|
|
checkChannelAvailability: function checkChannelAvailability(name) {
|
|
return db.Channel.findAll({
|
|
where: { channelName: name }
|
|
}).then(function (result) {
|
|
if (result.length >= 1) {
|
|
throw new Error('That channel has already been claimed');
|
|
}
|
|
return name;
|
|
}).catch(function (error) {
|
|
throw error;
|
|
});
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 9 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
var fs = __webpack_require__(64);
|
|
|
|
var _require = __webpack_require__(3),
|
|
details = _require.details,
|
|
publishing = _require.publishing;
|
|
|
|
module.exports = {
|
|
parsePublishApiRequestBody: function parsePublishApiRequestBody(_ref) {
|
|
var name = _ref.name,
|
|
nsfw = _ref.nsfw,
|
|
license = _ref.license,
|
|
title = _ref.title,
|
|
description = _ref.description,
|
|
thumbnail = _ref.thumbnail;
|
|
|
|
// validate name
|
|
if (!name) {
|
|
throw new Error('no name field found in request');
|
|
}
|
|
var invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name);
|
|
if (invalidNameCharacters) {
|
|
throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"');
|
|
}
|
|
// optional parameters
|
|
nsfw = nsfw === 'true';
|
|
license = license || null;
|
|
title = title || null;
|
|
description = description || null;
|
|
thumbnail = thumbnail || null;
|
|
// return results
|
|
return {
|
|
name: name,
|
|
nsfw: nsfw,
|
|
license: license,
|
|
title: title,
|
|
description: description,
|
|
thumbnail: thumbnail
|
|
};
|
|
},
|
|
parsePublishApiRequestFiles: function parsePublishApiRequestFiles(_ref2) {
|
|
var file = _ref2.file,
|
|
thumbnail = _ref2.thumbnail;
|
|
|
|
// make sure a file was provided
|
|
if (!file) {
|
|
throw new Error('no file with key of [file] found in request');
|
|
}
|
|
if (!file.path) {
|
|
throw new Error('no file path found');
|
|
}
|
|
if (!file.type) {
|
|
throw new Error('no file type found');
|
|
}
|
|
if (!file.size) {
|
|
throw new Error('no file type found');
|
|
}
|
|
// validate the file name
|
|
if (/'/.test(file.name)) {
|
|
throw new Error('apostrophes are not allowed in the file name');
|
|
}
|
|
// validate the file
|
|
module.exports.validateFileTypeAndSize(file);
|
|
// return results
|
|
return {
|
|
fileName: file.name,
|
|
filePath: file.path,
|
|
fileType: file.type,
|
|
thumbnailFileName: thumbnail ? thumbnail.name : null,
|
|
thumbnailFilePath: thumbnail ? thumbnail.path : null,
|
|
thumbnailFileType: thumbnail ? thumbnail.type : null
|
|
};
|
|
},
|
|
validateFileTypeAndSize: function validateFileTypeAndSize(file) {
|
|
// check file type and size
|
|
switch (file.type) {
|
|
case 'image/jpeg':
|
|
case 'image/jpg':
|
|
case 'image/png':
|
|
if (file.size > 10000000) {
|
|
logger.debug('publish > file validation > .jpeg/.jpg/.png was too big');
|
|
throw new Error('Sorry, images are limited to 10 megabytes.');
|
|
}
|
|
break;
|
|
case 'image/gif':
|
|
if (file.size > 50000000) {
|
|
logger.debug('publish > file validation > .gif was too big');
|
|
throw new Error('Sorry, .gifs are limited to 50 megabytes.');
|
|
}
|
|
break;
|
|
case 'video/mp4':
|
|
if (file.size > 50000000) {
|
|
logger.debug('publish > file validation > .mp4 was too big');
|
|
throw new Error('Sorry, videos are limited to 50 megabytes.');
|
|
}
|
|
break;
|
|
default:
|
|
logger.debug('publish > file validation > unrecognized file type');
|
|
throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');
|
|
}
|
|
return file;
|
|
},
|
|
createBasicPublishParams: function createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail) {
|
|
logger.debug('Creating Publish Parameters');
|
|
// provide defaults for title
|
|
if (title === null || title.trim() === '') {
|
|
title = name;
|
|
}
|
|
// provide default for description
|
|
if (description === null || description.trim() === '') {
|
|
description = '';
|
|
}
|
|
// provide default for license
|
|
if (license === null || license.trim() === '') {
|
|
license = ' '; // default to empty string
|
|
}
|
|
// create the publish params
|
|
var publishParams = {
|
|
name: name,
|
|
file_path: filePath,
|
|
bid: 0.01,
|
|
metadata: {
|
|
description: description,
|
|
title: title,
|
|
author: details.title,
|
|
language: 'en',
|
|
license: license,
|
|
nsfw: nsfw
|
|
},
|
|
claim_address: publishing.primaryClaimAddress
|
|
};
|
|
// add thumbnail to channel if video
|
|
if (thumbnail) {
|
|
publishParams['metadata']['thumbnail'] = thumbnail;
|
|
}
|
|
return publishParams;
|
|
},
|
|
createThumbnailPublishParams: function createThumbnailPublishParams(thumbnailFilePath, claimName, license, nsfw) {
|
|
if (!thumbnailFilePath) {
|
|
return;
|
|
}
|
|
logger.debug('Creating Thumbnail Publish Parameters');
|
|
// create the publish params
|
|
return {
|
|
name: claimName + '-thumb',
|
|
file_path: thumbnailFilePath,
|
|
bid: 0.01,
|
|
metadata: {
|
|
title: claimName + ' thumbnail',
|
|
description: 'a thumbnail for ' + claimName,
|
|
author: details.title,
|
|
language: 'en',
|
|
license: license,
|
|
nsfw: nsfw
|
|
},
|
|
claim_address: publishing.primaryClaimAddress,
|
|
channel_name: publishing.thumbnailChannel,
|
|
channel_id: publishing.thumbnailChannelId
|
|
};
|
|
},
|
|
deleteTemporaryFile: function deleteTemporaryFile(filePath) {
|
|
fs.unlink(filePath, function (err) {
|
|
if (err) {
|
|
logger.error('error deleting temporary file ' + filePath);
|
|
throw err;
|
|
}
|
|
logger.debug('successfully deleted ' + filePath);
|
|
});
|
|
},
|
|
addGetResultsToFileData: function addGetResultsToFileData(fileInfo, getResult) {
|
|
fileInfo.fileName = getResult.file_name;
|
|
fileInfo.filePath = getResult.download_path;
|
|
return fileInfo;
|
|
},
|
|
createFileData: function createFileData(_ref3) {
|
|
var name = _ref3.name,
|
|
claimId = _ref3.claimId,
|
|
outpoint = _ref3.outpoint,
|
|
height = _ref3.height,
|
|
address = _ref3.address,
|
|
nsfw = _ref3.nsfw,
|
|
contentType = _ref3.contentType;
|
|
|
|
return {
|
|
name: name,
|
|
claimId: claimId,
|
|
outpoint: outpoint,
|
|
height: height,
|
|
address: address,
|
|
fileName: '',
|
|
filePath: '',
|
|
fileType: contentType,
|
|
nsfw: nsfw
|
|
};
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 10 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
function mysql() {
|
|
var _this = this;
|
|
|
|
this.database = 'default';
|
|
this.username = 'default';
|
|
this.password = 'default';
|
|
this.update = function (config) {
|
|
if (!config) {
|
|
return logger.warn('No MySQL config received.');
|
|
}
|
|
// configure credentials
|
|
logger.info('configuring mysql...');
|
|
var database = config.database,
|
|
username = config.username,
|
|
password = config.password;
|
|
|
|
_this.database = database;
|
|
_this.username = username;
|
|
_this.password = password;
|
|
};
|
|
};
|
|
|
|
module.exports = new mysql();
|
|
|
|
/***/ }),
|
|
/* 11 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("passport-local");
|
|
|
|
/***/ }),
|
|
/* 12 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = {
|
|
returnShortId: function returnShortId(claimsArray, longId) {
|
|
var claimIndex = void 0;
|
|
var shortId = longId.substring(0, 1); // default short id is the first letter
|
|
var shortIdLength = 0;
|
|
// find the index of this claim id
|
|
claimIndex = claimsArray.findIndex(function (element) {
|
|
return element.claimId === longId;
|
|
});
|
|
if (claimIndex < 0) {
|
|
throw new Error('claim id not found in claims list');
|
|
}
|
|
// get an array of all claims with lower height
|
|
var possibleMatches = claimsArray.slice(0, claimIndex);
|
|
// remove certificates with the same prefixes until none are left.
|
|
while (possibleMatches.length > 0) {
|
|
shortIdLength += 1;
|
|
shortId = longId.substring(0, shortIdLength);
|
|
possibleMatches = possibleMatches.filter(function (element) {
|
|
return element.claimId && element.claimId.substring(0, shortIdLength) === shortId;
|
|
});
|
|
}
|
|
return shortId;
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 13 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("sequelize");
|
|
|
|
/***/ }),
|
|
/* 14 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _react = __webpack_require__(15);
|
|
|
|
var _react2 = _interopRequireDefault(_react);
|
|
|
|
var _server = __webpack_require__(16);
|
|
|
|
var _redux = __webpack_require__(17);
|
|
|
|
var _reactRedux = __webpack_require__(18);
|
|
|
|
var _reactRouterDom = __webpack_require__(19);
|
|
|
|
var _spee = __webpack_require__(20);
|
|
|
|
var _renderFullPage = __webpack_require__(21);
|
|
|
|
var _renderFullPage2 = _interopRequireDefault(_renderFullPage);
|
|
|
|
var _reactHelmet = __webpack_require__(22);
|
|
|
|
var _reactHelmet2 = _interopRequireDefault(_reactHelmet);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
/*
|
|
^ note: to do this right, maybe
|
|
these should be passed in from the implementation (www.spee.ch) itself,
|
|
so that there are no conflicts between the SSR here and
|
|
the bundle sent to the server?
|
|
there might also be issues if this package uses a different version of spee.ch-components than www.spee.ch does?
|
|
*/
|
|
var siteConfig = __webpack_require__(3);
|
|
|
|
module.exports = function (req, res) {
|
|
var context = {};
|
|
|
|
// customize the reducer by passing in intial state configs
|
|
var MyReducers = (0, _spee.Reducers)(siteConfig);
|
|
var MyApp = (0, _spee.App)(siteConfig);
|
|
var MyGAListener = (0, _spee.GAListener)(siteConfig);
|
|
|
|
// create a new Redux store instance
|
|
var store = (0, _redux.createStore)(MyReducers);
|
|
|
|
// render component to a string
|
|
var html = (0, _server.renderToString)(_react2.default.createElement(
|
|
_reactRedux.Provider,
|
|
{ store: store },
|
|
_react2.default.createElement(
|
|
_reactRouterDom.StaticRouter,
|
|
{ location: req.url, context: context },
|
|
_react2.default.createElement(
|
|
MyGAListener,
|
|
null,
|
|
_react2.default.createElement(MyApp, null)
|
|
)
|
|
)
|
|
));
|
|
|
|
// get head tags from helmet
|
|
var helmet = _reactHelmet2.default.renderStatic();
|
|
|
|
// check for a redirect
|
|
if (context.url) {
|
|
// Somewhere a `<Redirect>` was rendered
|
|
return res.redirect(301, context.url);
|
|
} else {}
|
|
// we're good, send the response
|
|
|
|
|
|
// get the initial state from our Redux store
|
|
var preloadedState = store.getState();
|
|
|
|
// send the rendered page back to the client
|
|
res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));
|
|
|
|
console.log('hello from spee.ch handlePageRender.jsx');
|
|
};
|
|
|
|
/***/ }),
|
|
/* 15 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("react");
|
|
|
|
/***/ }),
|
|
/* 16 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("react-dom/server");
|
|
|
|
/***/ }),
|
|
/* 17 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("redux");
|
|
|
|
/***/ }),
|
|
/* 18 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("react-redux");
|
|
|
|
/***/ }),
|
|
/* 19 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("react-router-dom");
|
|
|
|
/***/ }),
|
|
/* 20 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("spee.ch-components");
|
|
|
|
/***/ }),
|
|
/* 21 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = function (helmet, html, preloadedState) {
|
|
// take the html and preloadedState and return the full page
|
|
return '\n <!DOCTYPE html>\n <html lang="en" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">\n <head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no">\n <meta http-equiv="X-UA-Compatible" content="ie=edge">\n <!--helmet-->\n ' + helmet.title.toString() + '\n ' + helmet.meta.toString() + '\n ' + helmet.link.toString() + '\n <!--style sheets-->\n <link rel="stylesheet" href="/assets/css/reset.css" type="text/css">\n <link rel="stylesheet" href="/assets/css/general.css" type="text/css">\n <link rel="stylesheet" href="/assets/css/mediaQueries.css" type="text/css">\n <!--google font-->\n <link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">\n </head>\n <body id="main-body">\n <div class="row row--tall flex-container--column">\n <div id="react-app" class="row row--tall flex-container--column">' + html + '</div>\n </div>\n <script>\n window.__PRELOADED_STATE__ = ' + JSON.stringify(preloadedState).replace(/</g, '\\<') + '\n </script>\n <script src="/bundle/bundle.js"></script>\n </body>\n </html>\n ';
|
|
};
|
|
|
|
/***/ }),
|
|
/* 22 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("react-helmet");
|
|
|
|
/***/ }),
|
|
/* 23 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(6),
|
|
getClaimId = _require.getClaimId,
|
|
getLocalFileRecord = _require.getLocalFileRecord;
|
|
|
|
var _require2 = __webpack_require__(1),
|
|
handleErrorResponse = _require2.handleErrorResponse;
|
|
|
|
var SERVE = 'SERVE';
|
|
var SHOW = 'SHOW';
|
|
var NO_FILE = 'NO_FILE';
|
|
var NO_CHANNEL = 'NO_CHANNEL';
|
|
var NO_CLAIM = 'NO_CLAIM';
|
|
|
|
function clientAcceptsHtml(_ref) {
|
|
var accept = _ref.accept;
|
|
|
|
return accept && accept.match(/text\/html/);
|
|
};
|
|
|
|
function requestIsFromBrowser(headers) {
|
|
return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);
|
|
};
|
|
|
|
function clientWantsAsset(_ref2) {
|
|
var accept = _ref2.accept,
|
|
range = _ref2.range;
|
|
|
|
var imageIsWanted = accept && accept.match(/image\/.*/) && !accept.match(/text\/html/) && !accept.match(/text\/\*/);
|
|
var videoIsWanted = accept && range;
|
|
return imageIsWanted || videoIsWanted;
|
|
};
|
|
|
|
function isValidClaimId(claimId) {
|
|
return claimId.length === 40 && !/[^A-Za-z0-9]/g.test(claimId);
|
|
};
|
|
|
|
function isValidShortId(claimId) {
|
|
return claimId.length === 1; // it should really evaluate the short url itself
|
|
};
|
|
|
|
function isValidShortIdOrClaimId(input) {
|
|
return isValidClaimId(input) || isValidShortId(input);
|
|
};
|
|
|
|
function serveAssetToClient(claimId, name, res) {
|
|
return getLocalFileRecord(claimId, name).then(function (fileRecord) {
|
|
// check that a local record was found
|
|
if (fileRecord === NO_FILE) {
|
|
return res.status(307).redirect('/api/claim/get/' + name + '/' + claimId);
|
|
}
|
|
// serve the file
|
|
var filePath = fileRecord.filePath,
|
|
fileType = fileRecord.fileType;
|
|
|
|
logger.verbose('serving file: ' + filePath);
|
|
var sendFileOptions = {
|
|
headers: {
|
|
'X-Content-Type-Options': 'nosniff',
|
|
'Content-Type': fileType || 'image/jpeg'
|
|
}
|
|
};
|
|
res.status(200).sendFile(filePath, sendFileOptions);
|
|
}).catch(function (error) {
|
|
throw error;
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
getClaimIdAndServeAsset: function getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) {
|
|
// get the claim Id and then serve the asset
|
|
getClaimId(channelName, channelClaimId, claimName, claimId).then(function (fullClaimId) {
|
|
if (fullClaimId === NO_CLAIM) {
|
|
return res.status(404).json({ success: false, message: 'no claim id could be found' });
|
|
} else if (fullClaimId === NO_CHANNEL) {
|
|
return res.status(404).json({ success: false, message: 'no channel id could be found' });
|
|
}
|
|
serveAssetToClient(fullClaimId, claimName, res);
|
|
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
// postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');
|
|
});
|
|
},
|
|
determineResponseType: function determineResponseType(hasFileExtension, headers) {
|
|
var responseType = void 0;
|
|
if (hasFileExtension) {
|
|
responseType = SERVE; // assume a serve request if file extension is present
|
|
if (clientAcceptsHtml(headers)) {
|
|
// if the request comes from a browser, change it to a show request
|
|
responseType = SHOW;
|
|
}
|
|
} else {
|
|
responseType = SHOW;
|
|
if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) {
|
|
// this is in case someone embeds a show url
|
|
logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');
|
|
responseType = SERVE;
|
|
}
|
|
}
|
|
return responseType;
|
|
},
|
|
flipClaimNameAndIdForBackwardsCompatibility: function flipClaimNameAndIdForBackwardsCompatibility(identifier, name) {
|
|
// this is a patch for backwards compatability with '/name/claim_id' url format
|
|
if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {
|
|
var tempName = name;
|
|
name = identifier;
|
|
identifier = tempName;
|
|
}
|
|
return [identifier, name];
|
|
},
|
|
logRequestData: function logRequestData(responseType, claimName, channelName, claimId) {
|
|
logger.debug('responseType ===', responseType);
|
|
logger.debug('claim name === ', claimName);
|
|
logger.debug('channel name ===', channelName);
|
|
logger.debug('claim id ===', claimId);
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 24 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
module.exports = {
|
|
REGEXP_INVALID_CLAIM: /[^A-Za-z0-9-]/g,
|
|
REGEXP_INVALID_CHANNEL: /[^A-Za-z0-9-@]/g,
|
|
REGEXP_ADDRESS: /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/,
|
|
CHANNEL_CHAR: '@',
|
|
parseIdentifier: function parseIdentifier(identifier) {
|
|
logger.debug('parsing identifier:', identifier);
|
|
var componentsRegex = new RegExp('([^:$#/]*)' + // value (stops at the first separator or end)
|
|
'([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
|
|
);
|
|
|
|
var _componentsRegex$exec = componentsRegex.exec(identifier).map(function (match) {
|
|
return match || null;
|
|
}),
|
|
_componentsRegex$exec2 = _slicedToArray(_componentsRegex$exec, 4),
|
|
proto = _componentsRegex$exec2[0],
|
|
value = _componentsRegex$exec2[1],
|
|
modifierSeperator = _componentsRegex$exec2[2],
|
|
modifier = _componentsRegex$exec2[3];
|
|
|
|
logger.debug(proto + ', ' + value + ', ' + modifierSeperator + ', ' + modifier);
|
|
|
|
// Validate and process name
|
|
if (!value) {
|
|
throw new Error('Check your url. No channel name provided before "' + modifierSeperator + '"');
|
|
}
|
|
var isChannel = value.startsWith(module.exports.CHANNEL_CHAR);
|
|
var channelName = isChannel ? value : null;
|
|
var claimId = void 0;
|
|
if (isChannel) {
|
|
if (!channelName) {
|
|
throw new Error('No channel name after @.');
|
|
}
|
|
var nameBadChars = channelName.match(module.exports.REGEXP_INVALID_CHANNEL);
|
|
if (nameBadChars) {
|
|
throw new Error('Invalid characters in channel name: ' + nameBadChars.join(', ') + '.');
|
|
}
|
|
} else {
|
|
claimId = value;
|
|
}
|
|
|
|
// Validate and process modifier
|
|
var channelClaimId = void 0;
|
|
if (modifierSeperator) {
|
|
if (!modifier) {
|
|
throw new Error('No modifier provided after separator "' + modifierSeperator + '"');
|
|
}
|
|
|
|
if (modifierSeperator === ':') {
|
|
channelClaimId = modifier;
|
|
} else {
|
|
throw new Error('The "' + modifierSeperator + '" modifier is not currently supported');
|
|
}
|
|
}
|
|
return {
|
|
isChannel: isChannel,
|
|
channelName: channelName,
|
|
channelClaimId: channelClaimId,
|
|
claimId: claimId
|
|
};
|
|
},
|
|
parseClaim: function parseClaim(claim) {
|
|
logger.debug('parsing name:', claim);
|
|
var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)
|
|
'([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
|
|
);
|
|
|
|
var _componentsRegex$exec3 = componentsRegex.exec(claim).map(function (match) {
|
|
return match || null;
|
|
}),
|
|
_componentsRegex$exec4 = _slicedToArray(_componentsRegex$exec3, 4),
|
|
proto = _componentsRegex$exec4[0],
|
|
claimName = _componentsRegex$exec4[1],
|
|
modifierSeperator = _componentsRegex$exec4[2],
|
|
modifier = _componentsRegex$exec4[3];
|
|
|
|
logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);
|
|
|
|
// Validate and process name
|
|
if (!claimName) {
|
|
throw new Error('No claim name provided before .');
|
|
}
|
|
var nameBadChars = claimName.match(module.exports.REGEXP_INVALID_CLAIM);
|
|
if (nameBadChars) {
|
|
throw new Error('Invalid characters in claim name: ' + nameBadChars.join(', ') + '.');
|
|
}
|
|
// Validate and process modifier
|
|
if (modifierSeperator) {
|
|
if (!modifier) {
|
|
throw new Error('No file extension provided after separator ' + modifierSeperator + '.');
|
|
}
|
|
if (modifierSeperator !== '.') {
|
|
throw new Error('The ' + modifierSeperator + ' modifier is not supported in the claim name');
|
|
}
|
|
}
|
|
// return results
|
|
return {
|
|
claimName: claimName
|
|
};
|
|
},
|
|
parseModifier: function parseModifier(claim) {
|
|
logger.debug('parsing modifier:', claim);
|
|
var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)
|
|
'([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)
|
|
);
|
|
|
|
var _componentsRegex$exec5 = componentsRegex.exec(claim).map(function (match) {
|
|
return match || null;
|
|
}),
|
|
_componentsRegex$exec6 = _slicedToArray(_componentsRegex$exec5, 4),
|
|
proto = _componentsRegex$exec6[0],
|
|
claimName = _componentsRegex$exec6[1],
|
|
modifierSeperator = _componentsRegex$exec6[2],
|
|
modifier = _componentsRegex$exec6[3];
|
|
|
|
logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);
|
|
// Validate and process modifier
|
|
var hasFileExtension = false;
|
|
if (modifierSeperator) {
|
|
hasFileExtension = true;
|
|
}
|
|
return {
|
|
hasFileExtension: hasFileExtension
|
|
};
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 25 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _react = __webpack_require__(15);
|
|
|
|
var _react2 = _interopRequireDefault(_react);
|
|
|
|
var _server = __webpack_require__(16);
|
|
|
|
var _redux = __webpack_require__(17);
|
|
|
|
var _reactRedux = __webpack_require__(18);
|
|
|
|
var _reactRouterDom = __webpack_require__(19);
|
|
|
|
var _renderFullPage = __webpack_require__(21);
|
|
|
|
var _renderFullPage2 = _interopRequireDefault(_renderFullPage);
|
|
|
|
var _reduxSaga = __webpack_require__(87);
|
|
|
|
var _reduxSaga2 = _interopRequireDefault(_reduxSaga);
|
|
|
|
var _effects = __webpack_require__(88);
|
|
|
|
var _spee = __webpack_require__(20);
|
|
|
|
var _reactHelmet = __webpack_require__(22);
|
|
|
|
var _reactHelmet2 = _interopRequireDefault(_reactHelmet);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
// configure the reducers by passing initial state configs
|
|
var siteConfig = __webpack_require__(3);
|
|
/*
|
|
^ note: to do this right, maybe
|
|
these should be passed in from the implementation (www.spee.ch) itself,
|
|
so that there are no conflicts between the SSR here and
|
|
the bundle sent to the server?
|
|
there might also be issues if this package uses a different version of spee.ch-components than www.spee.ch does?
|
|
*/
|
|
|
|
var MyReducers = (0, _spee.Reducers)(siteConfig);
|
|
var MyApp = (0, _spee.App)(siteConfig);
|
|
var MyGAListener = (0, _spee.GAListener)(siteConfig);
|
|
|
|
var returnSagaWithParams = function returnSagaWithParams(saga, params) {
|
|
return (/*#__PURE__*/regeneratorRuntime.mark(function _callee() {
|
|
return regeneratorRuntime.wrap(function _callee$(_context) {
|
|
while (1) {
|
|
switch (_context.prev = _context.next) {
|
|
case 0:
|
|
_context.next = 2;
|
|
return (0, _effects.call)(saga, params);
|
|
|
|
case 2:
|
|
case 'end':
|
|
return _context.stop();
|
|
}
|
|
}
|
|
}, _callee, this);
|
|
})
|
|
);
|
|
};
|
|
|
|
module.exports = function (req, res) {
|
|
var context = {};
|
|
|
|
// create and apply middleware
|
|
var sagaMiddleware = (0, _reduxSaga2.default)();
|
|
var middleware = (0, _redux.applyMiddleware)(sagaMiddleware);
|
|
|
|
// create a new Redux store instance
|
|
var store = (0, _redux.createStore)(MyReducers, middleware);
|
|
|
|
// create saga
|
|
var action = _spee.Actions.onHandleShowPageUri(req.params);
|
|
var saga = returnSagaWithParams(_spee.Sagas.handleShowPageUri, action);
|
|
|
|
// run the saga middleware
|
|
sagaMiddleware.run(saga).done.then(function () {
|
|
// render component to a string
|
|
var html = (0, _server.renderToString)(_react2.default.createElement(
|
|
_reactRedux.Provider,
|
|
{ store: store },
|
|
_react2.default.createElement(
|
|
_reactRouterDom.StaticRouter,
|
|
{ location: req.url, context: context },
|
|
_react2.default.createElement(
|
|
MyGAListener,
|
|
null,
|
|
_react2.default.createElement(MyApp, null)
|
|
)
|
|
)
|
|
));
|
|
|
|
// get head tags from helmet
|
|
var helmet = _reactHelmet2.default.renderStatic();
|
|
|
|
// check for a redirect
|
|
if (context.url) {
|
|
return res.redirect(301, context.url);
|
|
}
|
|
|
|
// get the initial state from our Redux store
|
|
var preloadedState = store.getState();
|
|
|
|
// send the rendered page back to the client
|
|
res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));
|
|
});
|
|
|
|
console.log('hello from spee.ch handleShowRender.jsx');
|
|
};
|
|
|
|
/***/ }),
|
|
/* 26 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
__webpack_require__(27);
|
|
__webpack_require__(28);
|
|
module.exports = __webpack_require__(29);
|
|
|
|
|
|
/***/ }),
|
|
/* 27 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("babel-polyfill");
|
|
|
|
/***/ }),
|
|
/* 28 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("whatwg-fetch");
|
|
|
|
/***/ }),
|
|
/* 29 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var Server = __webpack_require__(30);
|
|
|
|
var _exports = {
|
|
Server: Server
|
|
};
|
|
|
|
module.exports = _exports;
|
|
|
|
/***/ }),
|
|
/* 30 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
// app dependencies
|
|
var express = __webpack_require__(31);
|
|
var bodyParser = __webpack_require__(32);
|
|
var expressHandlebars = __webpack_require__(33);
|
|
var Handlebars = __webpack_require__(34);
|
|
var helmet = __webpack_require__(35);
|
|
var cookieSession = __webpack_require__(36);
|
|
var http = __webpack_require__(37);
|
|
var logger = __webpack_require__(0);
|
|
var requestLogger = __webpack_require__(38);
|
|
var Path = __webpack_require__(39);
|
|
var loggerConfig = __webpack_require__(40);
|
|
var mysqlConfig = __webpack_require__(10);
|
|
var siteConfig = __webpack_require__(3);
|
|
var slackConfig = __webpack_require__(41);
|
|
|
|
function Server() {
|
|
var _this = this;
|
|
|
|
this.configureLogger = function (userConfig) {
|
|
loggerConfig.update(userConfig);
|
|
};
|
|
this.configureMysql = function (userConfig) {
|
|
mysqlConfig.update(userConfig);
|
|
};
|
|
this.configureSite = function (userConfig) {
|
|
siteConfig.update(userConfig);
|
|
};
|
|
this.configureSlack = function (userConfig) {
|
|
slackConfig.update(userConfig);
|
|
};
|
|
this.configureModels = function () {
|
|
logger.debug('here is where you could add/overwrite the default models');
|
|
};
|
|
this.configureRoutes = function () {
|
|
logger.debug('here is where you could add/overwrite the default routes');
|
|
};
|
|
this.createApp = function () {
|
|
// create an Express application
|
|
var app = express();
|
|
|
|
// trust the proxy to get ip address for us
|
|
app.enable('trust proxy');
|
|
|
|
/* add middleware */
|
|
// set HTTP headers to protect against well-known web vulnerabilties
|
|
app.use(helmet());
|
|
// 'express.static' to serve static files from public directory
|
|
if (siteConfig.routes.publicFolder) {
|
|
// take in a different public folder, so it can serve it's own bundle if needed
|
|
var publicFolder = Path.resolve(process.cwd(), siteConfig.routes.publicFolder);
|
|
app.use(express.static(publicFolder));
|
|
logger.info('serving static files from custom path:', publicFolder);
|
|
} else {
|
|
var publicPath = Path.resolve(__dirname, 'public');
|
|
app.use(express.static(publicPath));
|
|
logger.info('serving static files from default path:', publicPath);
|
|
};
|
|
// 'body parser' for parsing application/json
|
|
app.use(bodyParser.json());
|
|
// 'body parser' for parsing application/x-www-form-urlencoded
|
|
app.use(bodyParser.urlencoded({ extended: true }));
|
|
|
|
// add custom middleware (note: build out to accept dynamically use what is in server/middleware/
|
|
app.use(requestLogger);
|
|
|
|
// configure passport
|
|
var speechPassport = __webpack_require__(7);
|
|
// initialize passport
|
|
var sessionKey = siteConfig.auth.sessionKey;
|
|
app.use(cookieSession({
|
|
name: 'session',
|
|
keys: [sessionKey],
|
|
maxAge: 24 * 60 * 60 * 1000 // i.e. 24 hours
|
|
}));
|
|
app.use(speechPassport.initialize());
|
|
app.use(speechPassport.session());
|
|
|
|
// configure handlebars & register it with express app
|
|
var hbs = expressHandlebars.create({
|
|
defaultLayout: 'embed',
|
|
handlebars: Handlebars
|
|
});
|
|
app.engine('handlebars', hbs.engine);
|
|
app.set('view engine', 'handlebars');
|
|
|
|
// set the routes on the app
|
|
__webpack_require__(57)(app);
|
|
__webpack_require__(62)(app);
|
|
__webpack_require__(81)(app);
|
|
__webpack_require__(85)(app);
|
|
__webpack_require__(90)(app);
|
|
|
|
_this.app = app;
|
|
};
|
|
this.initialize = function () {
|
|
_this.createApp();
|
|
_this.server = http.Server(_this.app);
|
|
};
|
|
this.start = function () {
|
|
var db = __webpack_require__(2);
|
|
var PORT = siteConfig.details.port;
|
|
// sync sequelize
|
|
db.sequelize.sync()
|
|
// start the server
|
|
.then(function () {
|
|
_this.server.listen(PORT, function () {
|
|
logger.info('Server is listening on PORT ' + PORT);
|
|
});
|
|
}).catch(function (error) {
|
|
logger.error('Startup Error:', error);
|
|
});
|
|
};
|
|
};
|
|
|
|
module.exports = Server;
|
|
|
|
/***/ }),
|
|
/* 31 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("express");
|
|
|
|
/***/ }),
|
|
/* 32 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("body-parser");
|
|
|
|
/***/ }),
|
|
/* 33 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("express-handlebars");
|
|
|
|
/***/ }),
|
|
/* 34 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("handlebars");
|
|
|
|
/***/ }),
|
|
/* 35 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("helmet");
|
|
|
|
/***/ }),
|
|
/* 36 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("cookie-session");
|
|
|
|
/***/ }),
|
|
/* 37 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("http");
|
|
|
|
/***/ }),
|
|
/* 38 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
var requestLogger = function requestLogger(req, res, next) {
|
|
// custom logging middleware to log all incoming http requests
|
|
logger.verbose('Request on ' + req.originalUrl + ' from ' + req.ip);
|
|
next();
|
|
};
|
|
|
|
module.exports = requestLogger;
|
|
|
|
/***/ }),
|
|
/* 39 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("path");
|
|
|
|
/***/ }),
|
|
/* 40 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
function LoggerConfig() {
|
|
var _this = this;
|
|
|
|
this.logLevel = 'debug';
|
|
this.update = function (config) {
|
|
if (!config) {
|
|
return logger.warn('No logger config received.');
|
|
}
|
|
logger.info('configuring winston logger...');
|
|
// update values with local config params
|
|
var logLevel = config.logLevel;
|
|
|
|
_this.logLevel = logLevel;
|
|
// configure the winston logger
|
|
logger.configure({
|
|
transports: [new logger.transports.Console({
|
|
level: _this.logLevel,
|
|
timestamp: false,
|
|
colorize: true,
|
|
prettyPrint: true,
|
|
handleExceptions: true,
|
|
humanReadableUnhandledException: true
|
|
})]
|
|
});
|
|
// test all the log levels
|
|
logger.info('testing winston log levels...');
|
|
logger.error('Level 0');
|
|
logger.warn('Level 1');
|
|
logger.info('Level 2');
|
|
logger.verbose('Level 3');
|
|
logger.debug('Level 4');
|
|
logger.silly('Level 5');
|
|
};
|
|
};
|
|
|
|
module.exports = new LoggerConfig();
|
|
|
|
/***/ }),
|
|
/* 41 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var winstonSlackWebHook = __webpack_require__(42).SlackWebHook;
|
|
var winston = __webpack_require__(0);
|
|
|
|
function SlackConfig() {
|
|
var _this = this;
|
|
|
|
this.slackWebHook = 'default';
|
|
this.slackErrorChannel = 'default';
|
|
this.slackInfoChannel = 'default';
|
|
this.update = function (config) {
|
|
if (!config) {
|
|
return winston.warn('No slack config received');
|
|
}
|
|
// update variables
|
|
winston.info('configuring slack logger...');
|
|
var slackWebHook = config.slackWebHook,
|
|
slackErrorChannel = config.slackErrorChannel,
|
|
slackInfoChannel = config.slackInfoChannel;
|
|
|
|
_this.slackWebHook = slackWebHook;
|
|
_this.slackErrorChannel = slackErrorChannel;
|
|
_this.slackInfoChannel = slackInfoChannel;
|
|
// update slack webhook settings
|
|
if (_this.slackWebHook) {
|
|
// add a transport for errors to slack
|
|
if (_this.slackErrorChannel) {
|
|
winston.add(winstonSlackWebHook, {
|
|
name: 'slack-errors-transport',
|
|
level: 'warn',
|
|
webhookUrl: _this.slackWebHook,
|
|
channel: _this.slackErrorChannel,
|
|
username: 'spee.ch',
|
|
iconEmoji: ':face_with_head_bandage:'
|
|
});
|
|
};
|
|
if (slackInfoChannel) {
|
|
winston.add(winstonSlackWebHook, {
|
|
name: 'slack-info-transport',
|
|
level: 'info',
|
|
webhookUrl: _this.slackWebHook,
|
|
channel: _this.slackInfoChannel,
|
|
username: 'spee.ch',
|
|
iconEmoji: ':nerd_face:'
|
|
});
|
|
};
|
|
// send test messages
|
|
winston.info('testing slack logger...');
|
|
winston.error('Slack "error" logging is online.');
|
|
winston.info('Slack "info" logging is online.');
|
|
} else {
|
|
winston.warn('Slack logging is not enabled because no slackWebHook config var provided.');
|
|
}
|
|
};
|
|
};
|
|
|
|
module.exports = new SlackConfig();
|
|
|
|
/***/ }),
|
|
/* 42 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("winston-slack-webhook");
|
|
|
|
/***/ }),
|
|
/* 43 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("passport");
|
|
|
|
/***/ }),
|
|
/* 44 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var PassportLocalStrategy = __webpack_require__(11).Strategy;
|
|
var logger = __webpack_require__(0);
|
|
var db = __webpack_require__(2);
|
|
|
|
var returnUserAndChannelInfo = function returnUserAndChannelInfo(userInstance) {
|
|
return new Promise(function (resolve, reject) {
|
|
var userInfo = {};
|
|
userInfo['id'] = userInstance.id;
|
|
userInfo['userName'] = userInstance.userName;
|
|
userInstance.getChannel().then(function (_ref) {
|
|
var channelName = _ref.channelName,
|
|
channelClaimId = _ref.channelClaimId;
|
|
|
|
userInfo['channelName'] = channelName;
|
|
userInfo['channelClaimId'] = channelClaimId;
|
|
return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName);
|
|
}).then(function (shortChannelId) {
|
|
userInfo['shortChannelId'] = shortChannelId;
|
|
resolve(userInfo);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = new PassportLocalStrategy({
|
|
usernameField: 'username',
|
|
passwordField: 'password'
|
|
}, function (username, password, done) {
|
|
return db.User.findOne({
|
|
where: { userName: username }
|
|
}).then(function (user) {
|
|
if (!user) {
|
|
logger.debug('no user found');
|
|
return done(null, false, { message: 'Incorrect username or password' });
|
|
}
|
|
return user.comparePassword(password).then(function (isMatch) {
|
|
if (!isMatch) {
|
|
logger.debug('incorrect password');
|
|
return done(null, false, { message: 'Incorrect username or password' });
|
|
}
|
|
logger.debug('Password was a match, returning User');
|
|
return returnUserAndChannelInfo(user).then(function (userInfo) {
|
|
return done(null, userInfo);
|
|
}).catch(function (error) {
|
|
return error;
|
|
});
|
|
}).catch(function (error) {
|
|
return error;
|
|
});
|
|
}).catch(function (error) {
|
|
return done(error);
|
|
});
|
|
});
|
|
|
|
/***/ }),
|
|
/* 45 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(12),
|
|
returnShortId = _require.returnShortId;
|
|
|
|
module.exports = function (sequelize, _ref) {
|
|
var STRING = _ref.STRING,
|
|
BOOLEAN = _ref.BOOLEAN,
|
|
INTEGER = _ref.INTEGER,
|
|
TEXT = _ref.TEXT,
|
|
DECIMAL = _ref.DECIMAL;
|
|
|
|
var Certificate = sequelize.define('Certificate', {
|
|
address: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
amount: {
|
|
type: DECIMAL(19, 8),
|
|
default: null
|
|
},
|
|
claimId: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
claimSequence: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
decodedClaim: {
|
|
type: BOOLEAN,
|
|
default: null
|
|
},
|
|
depth: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
effectiveAmount: {
|
|
type: DECIMAL(19, 8),
|
|
default: null
|
|
},
|
|
hasSignature: {
|
|
type: BOOLEAN,
|
|
default: null
|
|
},
|
|
height: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
hex: {
|
|
type: TEXT('long'),
|
|
default: null
|
|
},
|
|
name: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
nout: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
txid: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
validAtHeight: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
outpoint: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
valueVersion: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
claimType: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
certificateVersion: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
keyType: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
publicKey: {
|
|
type: TEXT('long'),
|
|
default: null
|
|
}
|
|
}, {
|
|
freezeTableName: true
|
|
});
|
|
|
|
Certificate.associate = function (db) {
|
|
Certificate.belongsTo(db.Channel, {
|
|
foreignKey: {
|
|
allowNull: true
|
|
}
|
|
});
|
|
};
|
|
|
|
Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {
|
|
var _this = this;
|
|
|
|
logger.debug('getShortChannelIdFromLongChannelId ' + channelName + ':' + longChannelId);
|
|
return new Promise(function (resolve, reject) {
|
|
_this.findAll({
|
|
where: { name: channelName },
|
|
order: [['height', 'ASC']]
|
|
}).then(function (result) {
|
|
switch (result.length) {
|
|
case 0:
|
|
throw new Error('No channel(s) found with that channel name');
|
|
default:
|
|
return resolve(returnShortId(result, longChannelId));
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {
|
|
var _this2 = this;
|
|
|
|
logger.debug('getLongChannelIdFromShortChannelId(' + channelName + ', ' + channelClaimId + ')');
|
|
return new Promise(function (resolve, reject) {
|
|
_this2.findAll({
|
|
where: {
|
|
name: channelName,
|
|
claimId: {
|
|
$like: channelClaimId + '%'
|
|
}
|
|
},
|
|
order: [['height', 'ASC']]
|
|
}).then(function (result) {
|
|
switch (result.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
default:
|
|
// note results must be sorted
|
|
return resolve(result[0].claimId);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Certificate.getLongChannelIdFromChannelName = function (channelName) {
|
|
var _this3 = this;
|
|
|
|
logger.debug('getLongChannelIdFromChannelName(' + channelName + ')');
|
|
return new Promise(function (resolve, reject) {
|
|
_this3.findAll({
|
|
where: { name: channelName },
|
|
order: [['effectiveAmount', 'DESC'], ['height', 'ASC']]
|
|
}).then(function (result) {
|
|
switch (result.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
default:
|
|
return resolve(result[0].claimId);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Certificate.validateLongChannelId = function (name, claimId) {
|
|
var _this4 = this;
|
|
|
|
logger.debug('validateLongChannelId(' + name + ', ' + claimId + ')');
|
|
return new Promise(function (resolve, reject) {
|
|
_this4.findOne({
|
|
where: { name: name, claimId: claimId }
|
|
}).then(function (result) {
|
|
if (!result) {
|
|
return resolve(null);
|
|
};
|
|
resolve(claimId);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Certificate.getLongChannelId = function (channelName, channelClaimId) {
|
|
logger.debug('getLongChannelId(' + channelName + ', ' + channelClaimId + ')');
|
|
if (channelClaimId && channelClaimId.length === 40) {
|
|
// if a full channel id is provided
|
|
return this.validateLongChannelId(channelName, channelClaimId);
|
|
} else if (channelClaimId && channelClaimId.length < 40) {
|
|
// if a short channel id is provided
|
|
return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId);
|
|
} else {
|
|
return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided
|
|
}
|
|
};
|
|
|
|
return Certificate;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 46 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = function (sequelize, _ref) {
|
|
var STRING = _ref.STRING;
|
|
|
|
var Channel = sequelize.define('Channel', {
|
|
channelName: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
channelClaimId: {
|
|
type: STRING,
|
|
allowNull: false
|
|
}
|
|
}, {
|
|
freezeTableName: true
|
|
});
|
|
|
|
Channel.associate = function (db) {
|
|
Channel.belongsTo(db.User);
|
|
Channel.hasOne(db.Certificate);
|
|
};
|
|
|
|
return Channel;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 47 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logger = __webpack_require__(0);
|
|
|
|
var _require = __webpack_require__(12),
|
|
returnShortId = _require.returnShortId;
|
|
|
|
var _require2 = __webpack_require__(3),
|
|
defaultThumbnail = _require2.assetDefaults.thumbnail,
|
|
host = _require2.details.host;
|
|
|
|
function determineFileExtensionFromContentType(contentType) {
|
|
switch (contentType) {
|
|
case 'image/jpeg':
|
|
case 'image/jpg':
|
|
return 'jpeg';
|
|
case 'image/png':
|
|
return 'png';
|
|
case 'image/gif':
|
|
return 'gif';
|
|
case 'video/mp4':
|
|
return 'mp4';
|
|
default:
|
|
logger.debug('setting unknown file type as file extension jpeg');
|
|
return 'jpeg';
|
|
}
|
|
};
|
|
|
|
function determineThumbnail(storedThumbnail, defaultThumbnail) {
|
|
if (storedThumbnail === '') {
|
|
return defaultThumbnail;
|
|
}
|
|
return storedThumbnail;
|
|
};
|
|
|
|
function prepareClaimData(claim) {
|
|
// logger.debug('preparing claim data based on resolved data:', claim);
|
|
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
|
|
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
|
|
claim['host'] = host;
|
|
return claim;
|
|
};
|
|
|
|
module.exports = function (sequelize, _ref) {
|
|
var STRING = _ref.STRING,
|
|
BOOLEAN = _ref.BOOLEAN,
|
|
INTEGER = _ref.INTEGER,
|
|
TEXT = _ref.TEXT,
|
|
DECIMAL = _ref.DECIMAL;
|
|
|
|
var Claim = sequelize.define('Claim', {
|
|
address: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
amount: {
|
|
type: DECIMAL(19, 8),
|
|
default: null
|
|
},
|
|
claimId: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
claimSequence: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
decodedClaim: {
|
|
type: BOOLEAN,
|
|
default: null
|
|
},
|
|
depth: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
effectiveAmount: {
|
|
type: DECIMAL(19, 8),
|
|
default: null
|
|
},
|
|
hasSignature: {
|
|
type: BOOLEAN,
|
|
default: null
|
|
},
|
|
height: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
hex: {
|
|
type: TEXT('long'),
|
|
default: null
|
|
},
|
|
name: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
nout: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
txid: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
validAtHeight: {
|
|
type: INTEGER,
|
|
default: null
|
|
},
|
|
outpoint: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
claimType: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
certificateId: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
author: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
description: {
|
|
type: TEXT('long'),
|
|
default: null
|
|
},
|
|
language: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
license: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
licenseUrl: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
nsfw: {
|
|
type: BOOLEAN,
|
|
default: null
|
|
},
|
|
preview: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
thumbnail: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
title: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
metadataVersion: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
contentType: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
source: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
sourceType: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
sourceVersion: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
streamVersion: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
valueVersion: {
|
|
type: STRING,
|
|
default: null
|
|
},
|
|
channelName: {
|
|
type: STRING,
|
|
allowNull: true,
|
|
default: null
|
|
}
|
|
}, {
|
|
freezeTableName: true
|
|
});
|
|
|
|
Claim.associate = function (db) {
|
|
Claim.belongsTo(db.File, {
|
|
foreignKey: {
|
|
allowNull: true
|
|
}
|
|
});
|
|
};
|
|
|
|
Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {
|
|
var _this = this;
|
|
|
|
logger.debug('Claim.getShortClaimIdFromLongClaimId for ' + claimName + '#' + claimId);
|
|
return new Promise(function (resolve, reject) {
|
|
_this.findAll({
|
|
where: { name: claimName },
|
|
order: [['height', 'ASC']]
|
|
}).then(function (result) {
|
|
switch (result.length) {
|
|
case 0:
|
|
throw new Error('No claim(s) found with that claim name');
|
|
default:
|
|
resolve(returnShortId(result, claimId));
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Claim.getAllChannelClaims = function (channelClaimId) {
|
|
var _this2 = this;
|
|
|
|
logger.debug('Claim.getAllChannelClaims for ' + channelClaimId);
|
|
return new Promise(function (resolve, reject) {
|
|
_this2.findAll({
|
|
where: { certificateId: channelClaimId },
|
|
order: [['height', 'ASC']],
|
|
raw: true // returns an array of only data, not an array of instances
|
|
}).then(function (channelClaimsArray) {
|
|
// logger.debug('channelclaimsarray length:', channelClaimsArray.length);
|
|
switch (channelClaimsArray.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
default:
|
|
channelClaimsArray.forEach(function (claim) {
|
|
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
|
|
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
|
|
return claim;
|
|
});
|
|
return resolve(channelClaimsArray);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {
|
|
var _this3 = this;
|
|
|
|
logger.debug('finding claim id for claim ' + claimName + ' from channel ' + channelClaimId);
|
|
return new Promise(function (resolve, reject) {
|
|
_this3.findAll({
|
|
where: { name: claimName, certificateId: channelClaimId },
|
|
order: [['id', 'ASC']]
|
|
}).then(function (result) {
|
|
switch (result.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
case 1:
|
|
return resolve(result[0].claimId);
|
|
default:
|
|
logger.error(result.length + ' records found for "' + claimName + '" in channel "' + channelClaimId + '"');
|
|
return resolve(result[0].claimId);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {
|
|
var _this4 = this;
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
_this4.findAll({
|
|
where: {
|
|
name: name,
|
|
claimId: {
|
|
$like: shortId + '%'
|
|
} },
|
|
order: [['height', 'ASC']]
|
|
}).then(function (result) {
|
|
switch (result.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
default:
|
|
// note results must be sorted
|
|
return resolve(result[0].claimId);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Claim.getTopFreeClaimIdByClaimName = function (name) {
|
|
var _this5 = this;
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
_this5.findAll({
|
|
where: { name: name },
|
|
order: [['effectiveAmount', 'DESC'], ['height', 'ASC']] // note: maybe height and effective amount need to switch?
|
|
}).then(function (result) {
|
|
logger.debug('length of result', result.length);
|
|
switch (result.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
default:
|
|
return resolve(result[0].dataValues.claimId);
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Claim.validateLongClaimId = function (name, claimId) {
|
|
var _this6 = this;
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
_this6.findOne({
|
|
where: { name: name, claimId: claimId }
|
|
}).then(function (result) {
|
|
if (!result) {
|
|
return resolve(null);
|
|
};
|
|
resolve(claimId);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
Claim.getLongClaimId = function (claimName, claimId) {
|
|
logger.debug('getLongClaimId(' + claimName + ', ' + claimId + ')');
|
|
if (claimId && claimId.length === 40) {
|
|
// if a full claim id is provided
|
|
return this.validateLongClaimId(claimName, claimId);
|
|
} else if (claimId && claimId.length < 40) {
|
|
return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided
|
|
} else {
|
|
return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided
|
|
}
|
|
};
|
|
|
|
Claim.resolveClaim = function (name, claimId) {
|
|
var _this7 = this;
|
|
|
|
logger.debug('Claim.resolveClaim: ' + name + ' ' + claimId);
|
|
return new Promise(function (resolve, reject) {
|
|
_this7.findAll({
|
|
where: { name: name, claimId: claimId }
|
|
}).then(function (claimArray) {
|
|
switch (claimArray.length) {
|
|
case 0:
|
|
return resolve(null);
|
|
case 1:
|
|
return resolve(prepareClaimData(claimArray[0].dataValues));
|
|
default:
|
|
logger.error('more than one record matches ' + name + '#' + claimId + ' in db.Claim');
|
|
return resolve(prepareClaimData(claimArray[0].dataValues));
|
|
}
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
return Claim;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 48 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = function (sequelize, _ref) {
|
|
var STRING = _ref.STRING,
|
|
BOOLEAN = _ref.BOOLEAN,
|
|
INTEGER = _ref.INTEGER;
|
|
|
|
var File = sequelize.define('File', {
|
|
name: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
claimId: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
address: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
outpoint: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
height: {
|
|
type: INTEGER,
|
|
allowNull: false,
|
|
default: 0
|
|
},
|
|
fileName: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
filePath: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
fileType: {
|
|
type: STRING
|
|
},
|
|
nsfw: {
|
|
type: BOOLEAN,
|
|
allowNull: false,
|
|
defaultValue: false
|
|
},
|
|
trendingEligible: {
|
|
type: BOOLEAN,
|
|
allowNull: false,
|
|
defaultValue: true
|
|
}
|
|
}, {
|
|
freezeTableName: true
|
|
});
|
|
|
|
File.associate = function (db) {
|
|
File.hasMany(db.Request);
|
|
File.hasOne(db.Claim);
|
|
};
|
|
|
|
File.getRecentClaims = function () {
|
|
return this.findAll({
|
|
where: { nsfw: false, trendingEligible: true },
|
|
order: [['createdAt', 'DESC']],
|
|
limit: 25
|
|
});
|
|
};
|
|
|
|
return File;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 49 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = function (sequelize, _ref) {
|
|
var STRING = _ref.STRING,
|
|
BOOLEAN = _ref.BOOLEAN,
|
|
TEXT = _ref.TEXT;
|
|
|
|
var Request = sequelize.define('Request', {
|
|
action: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
url: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
ipAddress: {
|
|
type: STRING,
|
|
allowNull: true
|
|
},
|
|
result: {
|
|
type: TEXT('long'),
|
|
allowNull: true,
|
|
default: null
|
|
}
|
|
}, {
|
|
freezeTableName: true
|
|
});
|
|
|
|
Request.associate = function (db) {
|
|
Request.belongsTo(db.File, {
|
|
foreignKey: {
|
|
allowNull: true
|
|
}
|
|
});
|
|
};
|
|
|
|
return Request;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 50 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var bcrypt = __webpack_require__(51);
|
|
var logger = __webpack_require__(0);
|
|
|
|
module.exports = function (sequelize, _ref) {
|
|
var STRING = _ref.STRING;
|
|
|
|
var User = sequelize.define('User', {
|
|
userName: {
|
|
type: STRING,
|
|
allowNull: false
|
|
},
|
|
password: {
|
|
type: STRING,
|
|
allowNull: false
|
|
}
|
|
}, {
|
|
freezeTableName: true
|
|
});
|
|
|
|
User.associate = function (db) {
|
|
User.hasOne(db.Channel);
|
|
};
|
|
|
|
User.prototype.comparePassword = function (password) {
|
|
return bcrypt.compare(password, this.password);
|
|
};
|
|
|
|
User.prototype.changePassword = function (newPassword) {
|
|
var _this = this;
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
// generate a salt string to use for hashing
|
|
bcrypt.genSalt(function (saltError, salt) {
|
|
if (saltError) {
|
|
logger.error('salt error', saltError);
|
|
reject(saltError);
|
|
return;
|
|
}
|
|
// generate a hashed version of the user's password
|
|
bcrypt.hash(newPassword, salt, function (hashError, hash) {
|
|
// if there is an error with the hash generation return the error
|
|
if (hashError) {
|
|
logger.error('hash error', hashError);
|
|
reject(hashError);
|
|
return;
|
|
}
|
|
// replace the current password with the new hash
|
|
_this.update({ password: hash }).then(function () {
|
|
resolve();
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
// pre-save hook method to hash the user's password before the user's info is saved to the db.
|
|
User.hook('beforeCreate', function (user, options) {
|
|
logger.debug('User.beforeCreate hook...');
|
|
return new Promise(function (resolve, reject) {
|
|
// generate a salt string to use for hashing
|
|
bcrypt.genSalt(function (saltError, salt) {
|
|
if (saltError) {
|
|
logger.error('salt error', saltError);
|
|
reject(saltError);
|
|
return;
|
|
}
|
|
// generate a hashed version of the user's password
|
|
bcrypt.hash(user.password, salt, function (hashError, hash) {
|
|
// if there is an error with the hash generation return the error
|
|
if (hashError) {
|
|
logger.error('hash error', hashError);
|
|
reject(hashError);
|
|
return;
|
|
}
|
|
// replace the password string with the hash password value
|
|
user.password = hash;
|
|
resolve();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
return User;
|
|
};
|
|
|
|
/***/ }),
|
|
/* 51 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("bcrypt");
|
|
|
|
/***/ }),
|
|
/* 52 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var PassportLocalStrategy = __webpack_require__(11).Strategy;
|
|
var lbryApi = __webpack_require__(5);
|
|
var logger = __webpack_require__(0);
|
|
var db = __webpack_require__(2);
|
|
|
|
module.exports = new PassportLocalStrategy({
|
|
usernameField: 'username',
|
|
passwordField: 'password'
|
|
}, function (username, password, done) {
|
|
logger.verbose('new channel signup request. user: ' + username + ' pass: ' + password + ' .');
|
|
var userInfo = {};
|
|
// server-side validaton of inputs (username, password)
|
|
|
|
// create the channel and retrieve the metadata
|
|
return lbryApi.createChannel('@' + username).then(function (tx) {
|
|
// create user record
|
|
var userData = {
|
|
userName: username,
|
|
password: password
|
|
};
|
|
logger.verbose('userData >', userData);
|
|
// create user record
|
|
var channelData = {
|
|
channelName: '@' + username,
|
|
channelClaimId: tx.claim_id
|
|
};
|
|
logger.verbose('channelData >', channelData);
|
|
// create certificate record
|
|
var certificateData = {
|
|
claimId: tx.claim_id,
|
|
name: '@' + username
|
|
// address,
|
|
};
|
|
logger.verbose('certificateData >', certificateData);
|
|
// save user and certificate to db
|
|
return Promise.all([db.User.create(userData), db.Channel.create(channelData), db.Certificate.create(certificateData)]);
|
|
}).then(function (_ref) {
|
|
var _ref2 = _slicedToArray(_ref, 3),
|
|
newUser = _ref2[0],
|
|
newChannel = _ref2[1],
|
|
newCertificate = _ref2[2];
|
|
|
|
logger.verbose('user and certificate successfully created');
|
|
// store the relevant newUser info to be passed back for req.User
|
|
userInfo['id'] = newUser.id;
|
|
userInfo['userName'] = newUser.userName;
|
|
userInfo['channelName'] = newChannel.channelName;
|
|
userInfo['channelClaimId'] = newChannel.channelClaimId;
|
|
// associate the instances
|
|
return Promise.all([newCertificate.setChannel(newChannel), newChannel.setUser(newUser)]);
|
|
}).then(function () {
|
|
logger.verbose('user and certificate successfully associated');
|
|
return db.Certificate.getShortChannelIdFromLongChannelId(userInfo.channelClaimId, userInfo.channelName);
|
|
}).then(function (shortChannelId) {
|
|
userInfo['shortChannelId'] = shortChannelId;
|
|
return done(null, userInfo);
|
|
}).catch(function (error) {
|
|
logger.error('signup error', error);
|
|
return done(error);
|
|
});
|
|
});
|
|
|
|
/***/ }),
|
|
/* 53 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("axios");
|
|
|
|
/***/ }),
|
|
/* 54 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var lbryConfig = {
|
|
api: {
|
|
apiHost: 'localhost',
|
|
apiPort: '5279'
|
|
}
|
|
};
|
|
|
|
module.exports = lbryConfig;
|
|
|
|
/***/ }),
|
|
/* 55 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("universal-analytics");
|
|
|
|
/***/ }),
|
|
/* 56 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
module.exports = {
|
|
serializeSpeechUser: function serializeSpeechUser(user, done) {
|
|
// returns user data to be serialized into session
|
|
console.log('serializing user');
|
|
done(null, user);
|
|
},
|
|
deserializeSpeechUser: function deserializeSpeechUser(user, done) {
|
|
// deserializes session and populates additional info to req.user
|
|
console.log('deserializing user');
|
|
done(null, user);
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 57 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var speechPassport = __webpack_require__(7);
|
|
var handleSignupRequest = __webpack_require__(58);
|
|
var handleLoginRequest = __webpack_require__(59);
|
|
var handleLogoutRequest = __webpack_require__(60);
|
|
var handleUserRequest = __webpack_require__(61);
|
|
|
|
module.exports = function (app) {
|
|
app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest);
|
|
app.post('/login', handleLoginRequest);
|
|
app.get('/logout', handleLogoutRequest);
|
|
app.get('/user', handleUserRequest);
|
|
};
|
|
|
|
/***/ }),
|
|
/* 58 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var signup = function signup(req, res) {
|
|
res.status(200).json({
|
|
success: true,
|
|
channelName: req.user.channelName,
|
|
channelClaimId: req.user.channelClaimId,
|
|
shortChannelId: req.user.shortChannelId
|
|
});
|
|
};
|
|
|
|
module.exports = signup;
|
|
|
|
/***/ }),
|
|
/* 59 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var speechPassport = __webpack_require__(7);
|
|
|
|
var login = function login(req, res, next) {
|
|
speechPassport.authenticate('local-login', function (err, user, info) {
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
if (!user) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: info.message
|
|
});
|
|
}
|
|
req.logIn(user, function (err) {
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
return res.status(200).json({
|
|
success: true,
|
|
channelName: req.user.channelName,
|
|
channelClaimId: req.user.channelClaimId,
|
|
shortChannelId: req.user.shortChannelId
|
|
});
|
|
});
|
|
})(req, res, next);
|
|
};
|
|
|
|
module.exports = login;
|
|
|
|
/***/ }),
|
|
/* 60 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var logout = function logout(req, res) {
|
|
req.logout();
|
|
res.status(200).json({ success: true, message: 'you successfully logged out' });
|
|
};
|
|
|
|
module.exports = logout;
|
|
|
|
/***/ }),
|
|
/* 61 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var user = function user(req, res) {
|
|
if (req.user) {
|
|
res.status(200).json({ success: true, data: req.user });
|
|
} else {
|
|
res.status(401).json({ success: false, message: 'user is not logged in' });
|
|
}
|
|
};
|
|
|
|
module.exports = user;
|
|
|
|
/***/ }),
|
|
/* 62 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var channelAvailability = __webpack_require__(63);
|
|
var channelClaims = __webpack_require__(65);
|
|
var channelData = __webpack_require__(67);
|
|
var channelShortId = __webpack_require__(68);
|
|
var claimAvailability = __webpack_require__(69);
|
|
var claimData = __webpack_require__(70);
|
|
var claimGet = __webpack_require__(71);
|
|
var claimLongId = __webpack_require__(72);
|
|
var claimPublish = __webpack_require__(73);
|
|
var claimResolve = __webpack_require__(75);
|
|
var claimShortId = __webpack_require__(76);
|
|
var claimList = __webpack_require__(77);
|
|
var fileAvailability = __webpack_require__(78);
|
|
|
|
var multipartMiddleware = __webpack_require__(79);
|
|
|
|
module.exports = function (app) {
|
|
// channel routes
|
|
app.get('/api/channel/availability/:name', channelAvailability);
|
|
app.get('/api/channel/short-id/:longId/:name', channelShortId);
|
|
app.get('/api/channel/data/:channelName/:channelClaimId', channelData);
|
|
app.get('/api/channel/claims/:channelName/:channelClaimId/:page', channelClaims);
|
|
// claim routes
|
|
app.get('/api/claim/list/:name', claimList);
|
|
app.get('/api/claim/get/:name/:claimId', claimGet);
|
|
app.get('/api/claim/availability/:name', claimAvailability);
|
|
app.get('/api/claim/resolve/:name/:claimId', claimResolve);
|
|
app.post('/api/claim/publish', multipartMiddleware, claimPublish);
|
|
app.get('/api/claim/short-id/:longId/:name', claimShortId);
|
|
app.post('/api/claim/long-id', claimLongId);
|
|
app.get('/api/claim/data/:claimName/:claimId', claimData);
|
|
// file routes
|
|
app.get('/api/file/availability/:name/:claimId', fileAvailability);
|
|
};
|
|
|
|
/***/ }),
|
|
/* 63 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(8),
|
|
checkChannelAvailability = _require.checkChannelAvailability;
|
|
|
|
var _require2 = __webpack_require__(4),
|
|
sendGATimingEvent = _require2.sendGATimingEvent;
|
|
|
|
var _require3 = __webpack_require__(1),
|
|
handleErrorResponse = _require3.handleErrorResponse;
|
|
|
|
/*
|
|
|
|
route to check whether site has published to a channel
|
|
|
|
*/
|
|
|
|
var channelAvailability = function channelAvailability(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
name = _ref.params.name;
|
|
|
|
var gaStartTime = Date.now();
|
|
checkChannelAvailability(name).then(function (availableName) {
|
|
res.status(200).json(availableName);
|
|
sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = channelAvailability;
|
|
|
|
/***/ }),
|
|
/* 64 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("fs");
|
|
|
|
/***/ }),
|
|
/* 65 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(6),
|
|
getChannelClaims = _require.getChannelClaims;
|
|
|
|
var _require2 = __webpack_require__(1),
|
|
handleErrorResponse = _require2.handleErrorResponse;
|
|
|
|
var NO_CHANNEL = 'NO_CHANNEL';
|
|
|
|
/*
|
|
|
|
route to get all claims for channel
|
|
|
|
*/
|
|
|
|
var channelClaims = function channelClaims(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
body = _ref.body,
|
|
params = _ref.params;
|
|
|
|
var channelName = params.channelName;
|
|
var channelClaimId = params.channelClaimId;
|
|
if (channelClaimId === 'none') channelClaimId = null;
|
|
var page = params.page;
|
|
getChannelClaims(channelName, channelClaimId, page).then(function (data) {
|
|
if (data === NO_CHANNEL) {
|
|
return res.status(404).json({ success: false, message: 'No matching channel was found' });
|
|
}
|
|
res.status(200).json({ success: true, data: data });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = channelClaims;
|
|
|
|
/***/ }),
|
|
/* 66 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var CLAIMS_PER_PAGE = 12;
|
|
|
|
module.exports = {
|
|
returnPaginatedChannelClaims: function returnPaginatedChannelClaims(channelName, longChannelClaimId, claims, page) {
|
|
var totalPages = module.exports.determineTotalPages(claims);
|
|
var paginationPage = module.exports.getPageFromQuery(page);
|
|
var viewData = {
|
|
channelName: channelName,
|
|
longChannelClaimId: longChannelClaimId,
|
|
claims: module.exports.extractPageFromClaims(claims, paginationPage),
|
|
previousPage: module.exports.determinePreviousPage(paginationPage),
|
|
currentPage: paginationPage,
|
|
nextPage: module.exports.determineNextPage(totalPages, paginationPage),
|
|
totalPages: totalPages,
|
|
totalResults: module.exports.determineTotalClaims(claims)
|
|
};
|
|
return viewData;
|
|
},
|
|
getPageFromQuery: function getPageFromQuery(page) {
|
|
if (page) {
|
|
return parseInt(page);
|
|
}
|
|
return 1;
|
|
},
|
|
extractPageFromClaims: function extractPageFromClaims(claims, pageNumber) {
|
|
if (!claims) {
|
|
return []; // if no claims, return this default
|
|
}
|
|
// logger.debug('claims is array?', Array.isArray(claims));
|
|
// logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber));
|
|
var claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE;
|
|
var claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE;
|
|
var pageOfClaims = claims.slice(claimStartIndex, claimEndIndex);
|
|
return pageOfClaims;
|
|
},
|
|
determineTotalPages: function determineTotalPages(claims) {
|
|
if (!claims) {
|
|
return 0;
|
|
} else {
|
|
var totalClaims = claims.length;
|
|
if (totalClaims < CLAIMS_PER_PAGE) {
|
|
return 1;
|
|
}
|
|
var fullPages = Math.floor(totalClaims / CLAIMS_PER_PAGE);
|
|
var remainder = totalClaims % CLAIMS_PER_PAGE;
|
|
if (remainder === 0) {
|
|
return fullPages;
|
|
}
|
|
return fullPages + 1;
|
|
}
|
|
},
|
|
determinePreviousPage: function determinePreviousPage(currentPage) {
|
|
if (currentPage === 1) {
|
|
return null;
|
|
}
|
|
return currentPage - 1;
|
|
},
|
|
determineNextPage: function determineNextPage(totalPages, currentPage) {
|
|
if (currentPage === totalPages) {
|
|
return null;
|
|
}
|
|
return currentPage + 1;
|
|
},
|
|
determineTotalClaims: function determineTotalClaims(claims) {
|
|
if (!claims) {
|
|
return 0;
|
|
}
|
|
return claims.length;
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 67 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(6),
|
|
getChannelData = _require.getChannelData;
|
|
|
|
var _require2 = __webpack_require__(1),
|
|
handleErrorResponse = _require2.handleErrorResponse;
|
|
|
|
var NO_CHANNEL = 'NO_CHANNEL';
|
|
|
|
/*
|
|
|
|
route to get data for a channel
|
|
|
|
*/
|
|
|
|
var channelData = function channelData(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
body = _ref.body,
|
|
params = _ref.params;
|
|
|
|
var channelName = params.channelName;
|
|
var channelClaimId = params.channelClaimId;
|
|
if (channelClaimId === 'none') channelClaimId = null;
|
|
getChannelData(channelName, channelClaimId, 0).then(function (data) {
|
|
if (data === NO_CHANNEL) {
|
|
return res.status(404).json({ success: false, message: 'No matching channel was found' });
|
|
}
|
|
res.status(200).json({ success: true, data: data });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = channelData;
|
|
|
|
/***/ }),
|
|
/* 68 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(1),
|
|
handleErrorResponse = _require.handleErrorResponse;
|
|
|
|
var db = __webpack_require__(2);
|
|
|
|
/*
|
|
|
|
route to get a short channel id from long channel Id
|
|
|
|
*/
|
|
|
|
var channelShortIdRoute = function channelShortIdRoute(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
params = _ref.params;
|
|
|
|
db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name).then(function (shortId) {
|
|
res.status(200).json(shortId);
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = channelShortIdRoute;
|
|
|
|
/***/ }),
|
|
/* 69 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(8),
|
|
claimNameIsAvailable = _require.claimNameIsAvailable;
|
|
|
|
var _require2 = __webpack_require__(4),
|
|
sendGATimingEvent = _require2.sendGATimingEvent;
|
|
|
|
var _require3 = __webpack_require__(1),
|
|
handleErrorResponse = _require3.handleErrorResponse;
|
|
|
|
/*
|
|
|
|
route to check whether this site published to a claim
|
|
|
|
*/
|
|
|
|
var claimAvailability = function claimAvailability(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
name = _ref.params.name;
|
|
|
|
var gaStartTime = Date.now();
|
|
claimNameIsAvailable(name).then(function (result) {
|
|
res.status(200).json(result);
|
|
sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimAvailability;
|
|
|
|
/***/ }),
|
|
/* 70 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(1),
|
|
handleErrorResponse = _require.handleErrorResponse;
|
|
|
|
var db = __webpack_require__(2);
|
|
|
|
/*
|
|
|
|
route to return data for a claim
|
|
|
|
*/
|
|
|
|
var claimData = function claimData(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
body = _ref.body,
|
|
params = _ref.params;
|
|
|
|
var claimName = params.claimName;
|
|
var claimId = params.claimId;
|
|
if (claimId === 'none') claimId = null;
|
|
db.Claim.resolveClaim(claimName, claimId).then(function (claimInfo) {
|
|
if (!claimInfo) {
|
|
return res.status(404).json({ success: false, message: 'No claim could be found' });
|
|
}
|
|
res.status(200).json({ success: true, data: claimInfo });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimData;
|
|
|
|
/***/ }),
|
|
/* 71 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var _require = __webpack_require__(5),
|
|
getClaim = _require.getClaim;
|
|
|
|
var _require2 = __webpack_require__(9),
|
|
addGetResultsToFileData = _require2.addGetResultsToFileData,
|
|
createFileData = _require2.createFileData;
|
|
|
|
var _require3 = __webpack_require__(1),
|
|
handleErrorResponse = _require3.handleErrorResponse;
|
|
|
|
var db = __webpack_require__(2);
|
|
|
|
/*
|
|
|
|
route to get a claim
|
|
|
|
*/
|
|
|
|
var claimGet = function claimGet(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
params = _ref.params;
|
|
|
|
var name = params.name;
|
|
var claimId = params.claimId;
|
|
// resolve the claim
|
|
db.Claim.resolveClaim(name, claimId).then(function (resolveResult) {
|
|
// make sure a claim actually exists at that uri
|
|
if (!resolveResult) {
|
|
throw new Error('No matching uri found in Claim table');
|
|
}
|
|
var fileData = createFileData(resolveResult);
|
|
// get the claim
|
|
return Promise.all([fileData, getClaim(name + '#' + claimId)]);
|
|
}).then(function (_ref2) {
|
|
var _ref3 = _slicedToArray(_ref2, 2),
|
|
fileData = _ref3[0],
|
|
getResult = _ref3[1];
|
|
|
|
fileData = addGetResultsToFileData(fileData, getResult);
|
|
return Promise.all([db.upsert(db.File, fileData, { name: name, claimId: claimId }, 'File'), getResult]);
|
|
}).then(function (_ref4) {
|
|
var _ref5 = _slicedToArray(_ref4, 2),
|
|
fileRecord = _ref5[0],
|
|
_ref5$ = _ref5[1],
|
|
message = _ref5$.message,
|
|
completed = _ref5$.completed;
|
|
|
|
res.status(200).json({ success: true, message: message, completed: completed });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimGet;
|
|
|
|
/***/ }),
|
|
/* 72 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(6),
|
|
getClaimId = _require.getClaimId;
|
|
|
|
var _require2 = __webpack_require__(1),
|
|
handleErrorResponse = _require2.handleErrorResponse;
|
|
|
|
var NO_CHANNEL = 'NO_CHANNEL';
|
|
var NO_CLAIM = 'NO_CLAIM';
|
|
|
|
/*
|
|
|
|
route to get a long claim id
|
|
|
|
*/
|
|
|
|
var claimLongId = function claimLongId(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
body = _ref.body,
|
|
params = _ref.params;
|
|
|
|
var channelName = body.channelName;
|
|
var channelClaimId = body.channelClaimId;
|
|
var claimName = body.claimName;
|
|
var claimId = body.claimId;
|
|
getClaimId(channelName, channelClaimId, claimName, claimId).then(function (result) {
|
|
if (result === NO_CHANNEL) {
|
|
return res.status(404).json({ success: false, message: 'No matching channel could be found' });
|
|
}
|
|
if (result === NO_CLAIM) {
|
|
return res.status(404).json({ success: false, message: 'No matching claim id could be found' });
|
|
}
|
|
res.status(200).json({ success: true, data: result });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimLongId;
|
|
|
|
/***/ }),
|
|
/* 73 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var _require = __webpack_require__(9),
|
|
createBasicPublishParams = _require.createBasicPublishParams,
|
|
createThumbnailPublishParams = _require.createThumbnailPublishParams,
|
|
parsePublishApiRequestBody = _require.parsePublishApiRequestBody,
|
|
parsePublishApiRequestFiles = _require.parsePublishApiRequestFiles;
|
|
|
|
var _require2 = __webpack_require__(8),
|
|
claimNameIsAvailable = _require2.claimNameIsAvailable,
|
|
publish = _require2.publish;
|
|
|
|
var _require3 = __webpack_require__(74),
|
|
authenticateUser = _require3.authenticateUser;
|
|
|
|
var _require4 = __webpack_require__(4),
|
|
sendGATimingEvent = _require4.sendGATimingEvent;
|
|
|
|
var _require5 = __webpack_require__(1),
|
|
handleErrorResponse = _require5.handleErrorResponse;
|
|
|
|
var _require6 = __webpack_require__(3),
|
|
host = _require6.details.host;
|
|
|
|
/*
|
|
|
|
route to publish a claim through the daemon
|
|
|
|
*/
|
|
|
|
var claimPublish = function claimPublish(_ref, res) {
|
|
var body = _ref.body,
|
|
files = _ref.files,
|
|
headers = _ref.headers,
|
|
ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
user = _ref.user;
|
|
|
|
// define variables
|
|
var channelName = void 0,
|
|
channelId = void 0,
|
|
channelPassword = void 0,
|
|
description = void 0,
|
|
fileName = void 0,
|
|
filePath = void 0,
|
|
fileType = void 0,
|
|
gaStartTime = void 0,
|
|
license = void 0,
|
|
name = void 0,
|
|
nsfw = void 0,
|
|
thumbnail = void 0,
|
|
thumbnailFileName = void 0,
|
|
thumbnailFilePath = void 0,
|
|
thumbnailFileType = void 0,
|
|
title = void 0;
|
|
// record the start time of the request
|
|
gaStartTime = Date.now();
|
|
// validate the body and files of the request
|
|
try {
|
|
var _parsePublishApiReque = parsePublishApiRequestBody(body);
|
|
// validateApiPublishRequest(body, files);
|
|
|
|
|
|
name = _parsePublishApiReque.name;
|
|
nsfw = _parsePublishApiReque.nsfw;
|
|
license = _parsePublishApiReque.license;
|
|
title = _parsePublishApiReque.title;
|
|
description = _parsePublishApiReque.description;
|
|
thumbnail = _parsePublishApiReque.thumbnail;
|
|
|
|
var _parsePublishApiReque2 = parsePublishApiRequestFiles(files);
|
|
|
|
fileName = _parsePublishApiReque2.fileName;
|
|
filePath = _parsePublishApiReque2.filePath;
|
|
fileType = _parsePublishApiReque2.fileType;
|
|
thumbnailFileName = _parsePublishApiReque2.thumbnailFileName;
|
|
thumbnailFilePath = _parsePublishApiReque2.thumbnailFilePath;
|
|
thumbnailFileType = _parsePublishApiReque2.thumbnailFileType;
|
|
channelName = body.channelName;
|
|
channelId = body.channelId;
|
|
channelPassword = body.channelPassword;
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
// check channel authorization
|
|
Promise.all([authenticateUser(channelName, channelId, channelPassword, user), claimNameIsAvailable(name), createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail), createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw)]).then(function (_ref2) {
|
|
var _ref3 = _slicedToArray(_ref2, 4),
|
|
_ref3$ = _ref3[0],
|
|
channelName = _ref3$.channelName,
|
|
channelClaimId = _ref3$.channelClaimId,
|
|
validatedClaimName = _ref3[1],
|
|
publishParams = _ref3[2],
|
|
thumbnailPublishParams = _ref3[3];
|
|
|
|
// add channel details to the publish params
|
|
if (channelName && channelClaimId) {
|
|
publishParams['channel_name'] = channelName;
|
|
publishParams['channel_id'] = channelClaimId;
|
|
}
|
|
// publish the thumbnail
|
|
if (thumbnailPublishParams) {
|
|
publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);
|
|
}
|
|
// publish the asset
|
|
return publish(publishParams, fileName, fileType);
|
|
}).then(function (result) {
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'publish completed successfully',
|
|
data: {
|
|
name: name,
|
|
claimId: result.claim_id,
|
|
url: host + '/' + result.claim_id + '/' + name,
|
|
lbryTx: result
|
|
}
|
|
});
|
|
// record the publish end time and send to google analytics
|
|
sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimPublish;
|
|
|
|
/***/ }),
|
|
/* 74 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var db = __webpack_require__(2);
|
|
var logger = __webpack_require__(0);
|
|
|
|
module.exports = {
|
|
authenticateUser: function authenticateUser(channelName, channelId, channelPassword, user) {
|
|
// case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided
|
|
if (!channelName && !channelId) {
|
|
return {
|
|
channelName: null,
|
|
channelClaimId: null
|
|
};
|
|
}
|
|
// case: channelName or channel Id are provided with user token
|
|
if (user) {
|
|
if (channelName && channelName !== user.channelName) {
|
|
throw new Error('the provided channel name does not match user credentials');
|
|
}
|
|
if (channelId && channelId !== user.channelClaimId) {
|
|
throw new Error('the provided channel id does not match user credentials');
|
|
}
|
|
return {
|
|
channelName: user.channelName,
|
|
channelClaimId: user.channelClaimId
|
|
};
|
|
}
|
|
// case: channelName or channel Id are provided with password instead of user token
|
|
if (!channelPassword) throw new Error('no channel password provided');
|
|
return module.exports.authenticateChannelCredentials(channelName, channelId, channelPassword);
|
|
},
|
|
authenticateChannelCredentials: function authenticateChannelCredentials(channelName, channelId, userPassword) {
|
|
return new Promise(function (resolve, reject) {
|
|
// hoisted variables
|
|
var channelData = void 0;
|
|
// build the params for finding the channel
|
|
var channelFindParams = {};
|
|
if (channelName) channelFindParams['channelName'] = channelName;
|
|
if (channelId) channelFindParams['channelClaimId'] = channelId;
|
|
// find the channel
|
|
db.Channel.findOne({
|
|
where: channelFindParams
|
|
}).then(function (channel) {
|
|
if (!channel) {
|
|
logger.debug('no channel found');
|
|
throw new Error('Authentication failed, you do not have access to that channel');
|
|
}
|
|
channelData = channel.get();
|
|
logger.debug('channel data:', channelData);
|
|
return db.User.findOne({
|
|
where: { userName: channelData.channelName.substring(1) }
|
|
});
|
|
}).then(function (user) {
|
|
if (!user) {
|
|
logger.debug('no user found');
|
|
throw new Error('Authentication failed, you do not have access to that channel');
|
|
}
|
|
return user.comparePassword(userPassword);
|
|
}).then(function (isMatch) {
|
|
if (!isMatch) {
|
|
logger.debug('incorrect password');
|
|
throw new Error('Authentication failed, you do not have access to that channel');
|
|
}
|
|
logger.debug('...password was a match...');
|
|
resolve(channelData);
|
|
}).catch(function (error) {
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
/* 75 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(5),
|
|
resolveUri = _require.resolveUri;
|
|
|
|
var _require2 = __webpack_require__(1),
|
|
handleErrorResponse = _require2.handleErrorResponse;
|
|
|
|
/*
|
|
|
|
route to run a resolve request on the daemon
|
|
|
|
*/
|
|
|
|
var claimResolve = function claimResolve(_ref, res) {
|
|
var headers = _ref.headers,
|
|
ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
params = _ref.params;
|
|
|
|
resolveUri(params.name + '#' + params.claimId).then(function (resolvedUri) {
|
|
res.status(200).json(resolvedUri);
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimResolve;
|
|
|
|
/***/ }),
|
|
/* 76 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(1),
|
|
handleErrorResponse = _require.handleErrorResponse;
|
|
|
|
var db = __webpack_require__(2);
|
|
|
|
/*
|
|
|
|
route to get a short claim id from long claim Id
|
|
|
|
*/
|
|
|
|
var claimShortId = function claimShortId(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
body = _ref.body,
|
|
params = _ref.params;
|
|
|
|
db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name).then(function (shortId) {
|
|
res.status(200).json({ success: true, data: shortId });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimShortId;
|
|
|
|
/***/ }),
|
|
/* 77 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(5),
|
|
getClaimList = _require.getClaimList;
|
|
|
|
var _require2 = __webpack_require__(1),
|
|
handleErrorResponse = _require2.handleErrorResponse;
|
|
|
|
/*
|
|
|
|
route to get list of claims
|
|
|
|
*/
|
|
|
|
var claimList = function claimList(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
params = _ref.params;
|
|
|
|
getClaimList(params.name).then(function (claimsList) {
|
|
res.status(200).json(claimsList);
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = claimList;
|
|
|
|
/***/ }),
|
|
/* 78 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(1),
|
|
handleErrorResponse = _require.handleErrorResponse;
|
|
|
|
var db = __webpack_require__(2);
|
|
|
|
/*
|
|
|
|
route to see if asset is available locally
|
|
|
|
*/
|
|
|
|
var fileAvailability = function fileAvailability(_ref, res) {
|
|
var ip = _ref.ip,
|
|
originalUrl = _ref.originalUrl,
|
|
params = _ref.params;
|
|
|
|
var name = params.name;
|
|
var claimId = params.claimId;
|
|
db.File.findOne({
|
|
where: {
|
|
name: name,
|
|
claimId: claimId
|
|
}
|
|
}).then(function (result) {
|
|
if (result) {
|
|
return res.status(200).json({ success: true, data: true });
|
|
}
|
|
res.status(200).json({ success: true, data: false });
|
|
}).catch(function (error) {
|
|
handleErrorResponse(originalUrl, ip, error, res);
|
|
});
|
|
};
|
|
|
|
module.exports = fileAvailability;
|
|
|
|
/***/ }),
|
|
/* 79 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var multipart = __webpack_require__(80);
|
|
|
|
var _require = __webpack_require__(3),
|
|
uploadDirectory = _require.publishing.uploadDirectory;
|
|
|
|
var multipartMiddleware = multipart({ uploadDir: uploadDirectory });
|
|
|
|
module.exports = multipartMiddleware;
|
|
|
|
/***/ }),
|
|
/* 80 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("connect-multiparty");
|
|
|
|
/***/ }),
|
|
/* 81 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var handlePageRequest = __webpack_require__(82);
|
|
var handleEmbedRequest = __webpack_require__(83);
|
|
var redirect = __webpack_require__(84);
|
|
|
|
module.exports = function (app) {
|
|
app.get('/', handlePageRequest);
|
|
app.get('/login', handlePageRequest);
|
|
app.get('/about', handlePageRequest);
|
|
app.get('/trending', redirect('/popular'));
|
|
app.get('/popular', handlePageRequest);
|
|
app.get('/new', handlePageRequest);
|
|
app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)
|
|
};
|
|
|
|
/***/ }),
|
|
/* 82 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var handlePageRender = __webpack_require__(14);
|
|
|
|
var sendReactApp = function sendReactApp(req, res) {
|
|
handlePageRender(req, res);
|
|
};
|
|
|
|
module.exports = sendReactApp;
|
|
|
|
/***/ }),
|
|
/* 83 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(3),
|
|
host = _require.details.host;
|
|
|
|
var sendEmbedPage = function sendEmbedPage(_ref, res) {
|
|
var params = _ref.params;
|
|
|
|
var claimId = params.claimId;
|
|
var name = params.name;
|
|
// get and render the content
|
|
res.status(200).render('embed', { layout: 'embed', host: host, claimId: claimId, name: name });
|
|
};
|
|
|
|
module.exports = sendEmbedPage;
|
|
|
|
/***/ }),
|
|
/* 84 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var redirect = function redirect(route) {
|
|
return function (req, res) {
|
|
res.status(301).redirect(route);
|
|
};
|
|
};
|
|
|
|
module.exports = redirect;
|
|
|
|
/***/ }),
|
|
/* 85 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var serveAssetByClaim = __webpack_require__(86);
|
|
var serveAssetByIdentifierAndClaim = __webpack_require__(89);
|
|
|
|
module.exports = function (app, db) {
|
|
app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);
|
|
app.get('/:claim', serveAssetByClaim);
|
|
};
|
|
|
|
/***/ }),
|
|
/* 86 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _require = __webpack_require__(4),
|
|
sendGAServeEvent = _require.sendGAServeEvent;
|
|
|
|
var _require2 = __webpack_require__(23),
|
|
determineResponseType = _require2.determineResponseType,
|
|
logRequestData = _require2.logRequestData,
|
|
getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;
|
|
|
|
var lbryUri = __webpack_require__(24);
|
|
var handleShowRender = __webpack_require__(25);
|
|
var SERVE = 'SERVE';
|
|
|
|
/*
|
|
|
|
route to serve an asset or the react app via the claim name only
|
|
|
|
*/
|
|
|
|
var serverAssetByClaim = function serverAssetByClaim(req, res) {
|
|
var headers = req.headers,
|
|
ip = req.ip,
|
|
originalUrl = req.originalUrl,
|
|
params = req.params;
|
|
// decide if this is a show request
|
|
|
|
var hasFileExtension = void 0;
|
|
try {
|
|
var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);
|
|
|
|
hasFileExtension = _lbryUri$parseModifie.hasFileExtension;
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
var responseType = determineResponseType(hasFileExtension, headers);
|
|
if (responseType !== SERVE) {
|
|
return handleShowRender(req, res);
|
|
}
|
|
// handle serve request
|
|
// send google analytics
|
|
sendGAServeEvent(headers, ip, originalUrl);
|
|
// parse the claim
|
|
var claimName = void 0;
|
|
try {
|
|
var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);
|
|
|
|
claimName = _lbryUri$parseClaim.claimName;
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
// log the request data for debugging
|
|
logRequestData(responseType, claimName, null, null);
|
|
// get the claim Id and then serve the asset
|
|
getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);
|
|
};
|
|
|
|
module.exports = serverAssetByClaim;
|
|
|
|
/***/ }),
|
|
/* 87 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("redux-saga");
|
|
|
|
/***/ }),
|
|
/* 88 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = require("redux-saga/effects");
|
|
|
|
/***/ }),
|
|
/* 89 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
|
|
|
var _require = __webpack_require__(4),
|
|
sendGAServeEvent = _require.sendGAServeEvent;
|
|
|
|
var _require2 = __webpack_require__(23),
|
|
determineResponseType = _require2.determineResponseType,
|
|
flipClaimNameAndIdForBackwardsCompatibility = _require2.flipClaimNameAndIdForBackwardsCompatibility,
|
|
logRequestData = _require2.logRequestData,
|
|
getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;
|
|
|
|
var lbryUri = __webpack_require__(24);
|
|
var handleShowRender = __webpack_require__(25);
|
|
|
|
var SERVE = 'SERVE';
|
|
|
|
/*
|
|
|
|
route to serve an asset or the react app via the claim name and an identifier
|
|
|
|
*/
|
|
|
|
var serverAssetByIdentifierAndClaim = function serverAssetByIdentifierAndClaim(req, res) {
|
|
var headers = req.headers,
|
|
ip = req.ip,
|
|
originalUrl = req.originalUrl,
|
|
params = req.params;
|
|
// decide if this is a show request
|
|
|
|
var hasFileExtension = void 0;
|
|
try {
|
|
var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);
|
|
|
|
hasFileExtension = _lbryUri$parseModifie.hasFileExtension;
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
var responseType = determineResponseType(hasFileExtension, headers);
|
|
if (responseType !== SERVE) {
|
|
return handleShowRender(req, res);
|
|
}
|
|
// handle serve request
|
|
// send google analytics
|
|
sendGAServeEvent(headers, ip, originalUrl);
|
|
// parse the claim
|
|
var claimName = void 0;
|
|
try {
|
|
var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);
|
|
|
|
claimName = _lbryUri$parseClaim.claimName;
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
// parse the identifier
|
|
var isChannel = void 0,
|
|
channelName = void 0,
|
|
channelClaimId = void 0,
|
|
claimId = void 0;
|
|
try {
|
|
var _lbryUri$parseIdentif = lbryUri.parseIdentifier(params.identifier);
|
|
|
|
isChannel = _lbryUri$parseIdentif.isChannel;
|
|
channelName = _lbryUri$parseIdentif.channelName;
|
|
channelClaimId = _lbryUri$parseIdentif.channelClaimId;
|
|
claimId = _lbryUri$parseIdentif.claimId;
|
|
} catch (error) {
|
|
return res.status(400).json({ success: false, message: error.message });
|
|
}
|
|
if (!isChannel) {
|
|
var _flipClaimNameAndIdFo = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);
|
|
|
|
var _flipClaimNameAndIdFo2 = _slicedToArray(_flipClaimNameAndIdFo, 2);
|
|
|
|
claimId = _flipClaimNameAndIdFo2[0];
|
|
claimName = _flipClaimNameAndIdFo2[1];
|
|
}
|
|
// log the request data for debugging
|
|
logRequestData(responseType, claimName, channelName, claimId);
|
|
// get the claim Id and then serve the asset
|
|
getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);
|
|
};
|
|
|
|
module.exports = serverAssetByIdentifierAndClaim;
|
|
|
|
/***/ }),
|
|
/* 90 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var handlePageRequest = __webpack_require__(91);
|
|
|
|
module.exports = function (app) {
|
|
app.get('*', handlePageRequest);
|
|
};
|
|
|
|
/***/ }),
|
|
/* 91 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var handlePageRender = __webpack_require__(14);
|
|
|
|
var sendReactApp = function sendReactApp(req, res) {
|
|
handlePageRender(req, res);
|
|
};
|
|
|
|
module.exports = sendReactApp;
|
|
|
|
/***/ })
|
|
/******/ ]);
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgZDIxMmJhMDBkOGRiMjE0N2E4YWQiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2luc3RvblwiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9jb25maWcvc2l0ZUNvbmZpZy5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9nb29nbGVBbmFseXRpY3MuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvbGJyeUFwaS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvY29udHJvbGxlcnMvc2VydmVDb250cm9sbGVyLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvY29udHJvbGxlcnMvcHVibGlzaENvbnRyb2xsZXIuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvcHVibGlzaEhlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL215c3FsQ29uZmlnLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInBhc3Nwb3J0LWxvY2FsXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvc2VxdWVsaXplSGVscGVycy5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJzZXF1ZWxpemVcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9oYW5kbGVQYWdlUmVuZGVyLmpzeCIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWFjdFwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LWRvbS9zZXJ2ZXJcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWR1eFwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LXJlZHV4XCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicmVhY3Qtcm91dGVyLWRvbVwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInNwZWUuY2gtY29tcG9uZW50c1wiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL3JlbmRlckZ1bGxQYWdlLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LWhlbG1ldFwiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL3NlcnZlSGVscGVycy5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9sYnJ5VXJpLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2hhbmRsZVNob3dSZW5kZXIuanN4Iiwid2VicGFjazovLy9leHRlcm5hbCBcImJhYmVsLXBvbHlmaWxsXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2hhdHdnLWZldGNoXCIiLCJ3ZWJwYWNrOi8vLy4vc3BlZWNoLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9pbmRleC5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJleHByZXNzXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiYm9keS1wYXJzZXJcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJleHByZXNzLWhhbmRsZWJhcnNcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJoYW5kbGViYXJzXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiaGVsbWV0XCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiY29va2llLXNlc3Npb25cIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJodHRwXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21pZGRsZXdhcmUvcmVxdWVzdExvZ2dlci5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJwYXRoXCIiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL2xvZ2dlckNvbmZpZy5qcyIsIndlYnBhY2s6Ly8vLi9jb25maWcvc2xhY2tDb25maWcuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2luc3Rvbi1zbGFjay13ZWJob29rXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicGFzc3BvcnRcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvc3BlZWNoUGFzc3BvcnQvbG9jYWwtbG9naW4uanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9jZXJ0aWZpY2F0ZS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL2NoYW5uZWwuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9jbGFpbS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL2ZpbGUuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9yZXF1ZXN0LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9tb2RlbHMvdXNlci5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJiY3J5cHRcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvc3BlZWNoUGFzc3BvcnQvbG9jYWwtc2lnbnVwLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcImF4aW9zXCIiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL2xicnlDb25maWcuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwidW5pdmVyc2FsLWFuYWx5dGljc1wiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2F1dGhIZWxwZXJzLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2F1dGgvc2lnbnVwLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC9sb2dpbi5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2F1dGgvbG9nb3V0LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC91c2VyLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxBdmFpbGFiaWxpdHkuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiZnNcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jaGFubmVsQ2xhaW1zLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2NoYW5uZWxQYWdpbmF0aW9uLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxEYXRhLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxTaG9ydElkLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltQXZhaWxhYmlsaXR5LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltRGF0YS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUdldC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUxvbmdJZC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbVB1Ymxpc2guanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2F1dGgvYXV0aGVudGljYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1SZXNvbHZlLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltU2hvcnRJZC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUxpc3QuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvZmlsZUF2YWlsYWJpbGl0eS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9tdWx0aXBhcnRNaWRkbGV3YXJlLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcImNvbm5lY3QtbXVsdGlwYXJ0eVwiIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvcGFnZXMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kUmVhY3RBcHAuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kRW1iZWRQYWdlLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvcGFnZXMvcmVkaXJlY3QuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hc3NldHMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hc3NldHMvc2VydmVBc3NldEJ5Q2xhaW0uanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicmVkdXgtc2FnYVwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlZHV4LXNhZ2EvZWZmZWN0c1wiIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXNzZXRzL3NlcnZlQXNzZXRCeUlkZW50aWZpZXJBbmRDbGFpbS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2ZhbGxiYWNrL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvZmFsbGJhY2svc2VuZFJlYWN0QXBwLmpzIl0sIm5hbWVzIjpbImxvZ2dlciIsInJlcXVpcmUiLCJtb2R1bGUiLCJleHBvcnRzIiwiaGFuZGxlRXJyb3JSZXNwb25zZSIsIm9yaWdpbmFsVXJsIiwiaXAiLCJlcnJvciIsInJlcyIsInVzZU9iamVjdFByb3BlcnRpZXNJZk5vS2V5cyIsInJldHVybkVycm9yTWVzc2FnZUFuZFN0YXR1cyIsInN0YXR1cyIsIm1lc3NhZ2UiLCJqc29uIiwiY3JlYXRlRXJyb3JSZXNwb25zZVBheWxvYWQiLCJjb2RlIiwiZXJyIiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsIm5ld0Vycm9yT2JqZWN0IiwiZ2V0T3duUHJvcGVydHlOYW1lcyIsImZvckVhY2giLCJrZXkiLCJzdWNjZXNzIiwiQ2VydGlmaWNhdGUiLCJDaGFubmVsIiwiQ2xhaW0iLCJGaWxlIiwiUmVxdWVzdCIsIlVzZXIiLCJTZXF1ZWxpemUiLCJkYXRhYmFzZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJzZXF1ZWxpemUiLCJob3N0IiwiZGlhbGVjdCIsImRpYWxlY3RPcHRpb25zIiwiZGVjaW1hbE51bWJlcnMiLCJsb2dnaW5nIiwicG9vbCIsIm1heCIsIm1pbiIsImlkbGUiLCJhY3F1aXJlIiwiYXV0aGVudGljYXRlIiwidGhlbiIsImluZm8iLCJjYXRjaCIsImRiIiwiaW1wb3J0IiwibW9kZWxOYW1lIiwiYXNzb2NpYXRlIiwidXBzZXJ0IiwiTW9kZWwiLCJ2YWx1ZXMiLCJjb25kaXRpb24iLCJ0YWJsZU5hbWUiLCJmaW5kT25lIiwid2hlcmUiLCJvYmoiLCJkZWJ1ZyIsInVwZGF0ZSIsImNyZWF0ZSIsIlNpdGVDb25maWciLCJhbmFseXRpY3MiLCJnb29nbGVJZCIsImFzc2V0RGVmYXVsdHMiLCJkZXNjcmlwdGlvbiIsInRodW1ibmFpbCIsInRpdGxlIiwiYXV0aCIsInNlc3Npb25LZXkiLCJjdXN0b21Db21wb25lbnRzIiwiY3VzdG9tQ29udGFpbmVycyIsImN1c3RvbVBhZ2VzIiwiZGV0YWlscyIsInBvcnQiLCJ0d2l0dGVyIiwicHVibGlzaGluZyIsImFkZGl0aW9uYWxDbGFpbUFkZHJlc3NlcyIsImRpc2FibGVkIiwiZGlzYWJsZWRNZXNzYWdlIiwicHJpbWFyeUNsYWltQWRkcmVzcyIsInRodW1ibmFpbENoYW5uZWwiLCJ0aHVtYm5haWxDaGFubmVsSWQiLCJ1cGxvYWREaXJlY3RvcnkiLCJyb3V0ZXMiLCJjb25maWciLCJjb25zb2xlIiwibG9nIiwidWEiLCJjcmVhdGVTZXJ2ZUV2ZW50UGFyYW1zIiwiaGVhZGVycyIsImV2ZW50Q2F0ZWdvcnkiLCJldmVudEFjdGlvbiIsImV2ZW50TGFiZWwiLCJpcE92ZXJyaWRlIiwidXNlckFnZW50T3ZlcnJpZGUiLCJjcmVhdGVQdWJsaXNoVGltaW5nRXZlbnRQYXJhbXMiLCJjYXRlZ29yeSIsInZhcmlhYmxlIiwibGFiZWwiLCJzdGFydFRpbWUiLCJlbmRUaW1lIiwiZHVyYXRpb24iLCJ1c2VyVGltaW5nQ2F0ZWdvcnkiLCJ1c2VyVGltaW5nVmFyaWFibGVOYW1lIiwidXNlclRpbWluZ1RpbWUiLCJ1c2VyVGltaW5nTGFiZWwiLCJzZW5kR29vZ2xlQW5hbHl0aWNzRXZlbnQiLCJwYXJhbXMiLCJ2aXNpdG9ySWQiLCJyZXBsYWNlIiwidmlzaXRvciIsInN0cmljdENpZEZvcm1hdCIsImh0dHBzIiwiZXZlbnQiLCJzZW5kR29vZ2xlQW5hbHl0aWNzVGltaW5nIiwidGltaW5nIiwic2VuZEdBU2VydmVFdmVudCIsInNlbmRHQVRpbWluZ0V2ZW50IiwiY2hvb3NlR2FMYnJ5bmV0UHVibGlzaExhYmVsIiwiY2hhbm5lbE5hbWUiLCJjaGFubmVsX25hbWUiLCJjaGFubmVsSWQiLCJjaGFubmVsX2lkIiwiYXhpb3MiLCJhcGkiLCJhcGlIb3N0IiwiYXBpUG9ydCIsImxicnlBcGlVcmkiLCJoYW5kbGVMYnJ5bmV0UmVzcG9uc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZGF0YSIsInJlc3VsdCIsIkVycm9yIiwiSlNPTiIsInN0cmluZ2lmeSIsInB1Ymxpc2hDbGFpbSIsInB1Ymxpc2hQYXJhbXMiLCJuYW1lIiwiZ2FTdGFydFRpbWUiLCJEYXRlIiwibm93IiwiUHJvbWlzZSIsInBvc3QiLCJtZXRob2QiLCJyZXNwb25zZSIsImdldENsYWltIiwidXJpIiwidGltZW91dCIsImdldENsYWltTGlzdCIsImNsYWltTmFtZSIsInJlc29sdmVVcmkiLCJnZXREb3dubG9hZERpcmVjdG9yeSIsImRvd25sb2FkX2RpcmVjdG9yeSIsImNyZWF0ZUNoYW5uZWwiLCJhbW91bnQiLCJyZXR1cm5QYWdpbmF0ZWRDaGFubmVsQ2xhaW1zIiwiTk9fQ0hBTk5FTCIsIk5PX0NMQUlNIiwiTk9fRklMRSIsImdldENsYWltSWQiLCJjaGFubmVsQ2xhaW1JZCIsImNsYWltSWQiLCJnZXRDbGFpbUlkQnlDaGFubmVsIiwiZ2V0Q2xhaW1JZEJ5Q2xhaW0iLCJnZXRMb25nQ2xhaW1JZCIsImxvbmdDbGFpbUlkIiwiZ2V0TG9uZ0NoYW5uZWxJZCIsImxvbmdDaGFubmVsSWQiLCJhbGwiLCJnZXRDbGFpbUlkQnlMb25nQ2hhbm5lbElkIiwiZ2V0Q2hhbm5lbERhdGEiLCJwYWdlIiwibG9uZ0NoYW5uZWxDbGFpbUlkIiwiZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZCIsInNob3J0Q2hhbm5lbENsYWltSWQiLCJnZXRDaGFubmVsQ2xhaW1zIiwiZ2V0QWxsQ2hhbm5lbENsYWltcyIsImNoYW5uZWxDbGFpbXNBcnJheSIsInBhZ2luYXRlZENoYW5uZWxWaWV3RGF0YSIsImdldExvY2FsRmlsZVJlY29yZCIsImZpbGUiLCJkYXRhVmFsdWVzIiwicGFzc3BvcnQiLCJsb2NhbExvZ2luU3RyYXRlZ3kiLCJsb2NhbFNpZ251cFN0cmF0ZWd5Iiwic2VyaWFsaXplU3BlZWNoVXNlciIsImRlc2VyaWFsaXplU3BlZWNoVXNlciIsImRlc2VyaWFsaXplVXNlciIsInNlcmlhbGl6ZVVzZXIiLCJ1c2UiLCJsYnJ5QXBpIiwicHVibGlzaEhlbHBlcnMiLCJPcCIsInB1Ymxpc2giLCJmaWxlTmFtZSIsImZpbGVUeXBlIiwicHVibGlzaFJlc3VsdHMiLCJjZXJ0aWZpY2F0ZUlkIiwidHgiLCJjaGFubmVsIiwiZmlsZVJlY29yZCIsImNsYWltX2lkIiwibWV0YWRhdGEiLCJhZGRyZXNzIiwiY2xhaW1fYWRkcmVzcyIsIm91dHBvaW50IiwidHhpZCIsIm5vdXQiLCJoZWlnaHQiLCJmaWxlUGF0aCIsImZpbGVfcGF0aCIsIm5zZnciLCJjbGFpbVJlY29yZCIsImNvbnRlbnRUeXBlIiwiYmlkIiwidXBzZXJ0Q3JpdGVyaWEiLCJjbGFpbSIsInNldENsYWltIiwic2V0RmlsZSIsImRlbGV0ZVRlbXBvcmFyeUZpbGUiLCJjbGFpbU5hbWVJc0F2YWlsYWJsZSIsImNsYWltQWRkcmVzc2VzIiwicHVzaCIsImZpbmRBbGwiLCJhdHRyaWJ1dGVzIiwib3IiLCJjaGVja0NoYW5uZWxBdmFpbGFiaWxpdHkiLCJmcyIsInBhcnNlUHVibGlzaEFwaVJlcXVlc3RCb2R5IiwibGljZW5zZSIsImludmFsaWROYW1lQ2hhcmFjdGVycyIsImV4ZWMiLCJwYXJzZVB1Ymxpc2hBcGlSZXF1ZXN0RmlsZXMiLCJwYXRoIiwidHlwZSIsInNpemUiLCJ0ZXN0IiwidmFsaWRhdGVGaWxlVHlwZUFuZFNpemUiLCJ0aHVtYm5haWxGaWxlTmFtZSIsInRodW1ibmFpbEZpbGVQYXRoIiwidGh1bWJuYWlsRmlsZVR5cGUiLCJjcmVhdGVCYXNpY1B1Ymxpc2hQYXJhbXMiLCJ0cmltIiwiYXV0aG9yIiwibGFuZ3VhZ2UiLCJjcmVhdGVUaHVtYm5haWxQdWJsaXNoUGFyYW1zIiwidW5saW5rIiwiYWRkR2V0UmVzdWx0c1RvRmlsZURhdGEiLCJmaWxlSW5mbyIsImdldFJlc3VsdCIsImZpbGVfbmFtZSIsImRvd25sb2FkX3BhdGgiLCJjcmVhdGVGaWxlRGF0YSIsIm15c3FsIiwid2FybiIsInJldHVyblNob3J0SWQiLCJjbGFpbXNBcnJheSIsImxvbmdJZCIsImNsYWltSW5kZXgiLCJzaG9ydElkIiwic3Vic3RyaW5nIiwic2hvcnRJZExlbmd0aCIsImZpbmRJbmRleCIsImVsZW1lbnQiLCJwb3NzaWJsZU1hdGNoZXMiLCJzbGljZSIsImZpbHRlciIsInNpdGVDb25maWciLCJyZXEiLCJjb250ZXh0IiwiTXlSZWR1Y2VycyIsIk15QXBwIiwiTXlHQUxpc3RlbmVyIiwic3RvcmUiLCJodG1sIiwidXJsIiwiaGVsbWV0IiwicmVuZGVyU3RhdGljIiwicmVkaXJlY3QiLCJwcmVsb2FkZWRTdGF0ZSIsImdldFN0YXRlIiwic2VuZCIsInRvU3RyaW5nIiwibWV0YSIsImxpbmsiLCJTRVJWRSIsIlNIT1ciLCJjbGllbnRBY2NlcHRzSHRtbCIsImFjY2VwdCIsIm1hdGNoIiwicmVxdWVzdElzRnJvbUJyb3dzZXIiLCJjbGllbnRXYW50c0Fzc2V0IiwicmFuZ2UiLCJpbWFnZUlzV2FudGVkIiwidmlkZW9Jc1dhbnRlZCIsImlzVmFsaWRDbGFpbUlkIiwiaXNWYWxpZFNob3J0SWQiLCJpc1ZhbGlkU2hvcnRJZE9yQ2xhaW1JZCIsImlucHV0Iiwic2VydmVBc3NldFRvQ2xpZW50IiwidmVyYm9zZSIsInNlbmRGaWxlT3B0aW9ucyIsInNlbmRGaWxlIiwiZ2V0Q2xhaW1JZEFuZFNlcnZlQXNzZXQiLCJmdWxsQ2xhaW1JZCIsImRldGVybWluZVJlc3BvbnNlVHlwZSIsImhhc0ZpbGVFeHRlbnNpb24iLCJyZXNwb25zZVR5cGUiLCJmbGlwQ2xhaW1OYW1lQW5kSWRGb3JCYWNrd2FyZHNDb21wYXRpYmlsaXR5IiwiaWRlbnRpZmllciIsInRlbXBOYW1lIiwibG9nUmVxdWVzdERhdGEiLCJSRUdFWFBfSU5WQUxJRF9DTEFJTSIsIlJFR0VYUF9JTlZBTElEX0NIQU5ORUwiLCJSRUdFWFBfQUREUkVTUyIsIkNIQU5ORUxfQ0hBUiIsInBhcnNlSWRlbnRpZmllciIsImNvbXBvbmVudHNSZWdleCIsIlJlZ0V4cCIsIm1hcCIsInByb3RvIiwidmFsdWUiLCJtb2RpZmllclNlcGVyYXRvciIsIm1vZGlmaWVyIiwiaXNDaGFubmVsIiwic3RhcnRzV2l0aCIsIm5hbWVCYWRDaGFycyIsImpvaW4iLCJwYXJzZUNsYWltIiwicGFyc2VNb2RpZmllciIsInJldHVyblNhZ2FXaXRoUGFyYW1zIiwic2FnYSIsInNhZ2FNaWRkbGV3YXJlIiwibWlkZGxld2FyZSIsImFjdGlvbiIsIm9uSGFuZGxlU2hvd1BhZ2VVcmkiLCJoYW5kbGVTaG93UGFnZVVyaSIsInJ1biIsImRvbmUiLCJTZXJ2ZXIiLCJleHByZXNzIiwiYm9keVBhcnNlciIsImV4cHJlc3NIYW5kbGViYXJzIiwiSGFuZGxlYmFycyIsImNvb2tpZVNlc3Npb24iLCJodHRwIiwicmVxdWVzdExvZ2dlciIsIlBhdGgiLCJsb2dnZXJDb25maWciLCJteXNxbENvbmZpZyIsInNsYWNrQ29uZmlnIiwiY29uZmlndXJlTG9nZ2VyIiwidXNlckNvbmZpZyIsImNvbmZpZ3VyZU15c3FsIiwiY29uZmlndXJlU2l0ZSIsImNvbmZpZ3VyZVNsYWNrIiwiY29uZmlndXJlTW9kZWxzIiwiY29uZmlndXJlUm91dGVzIiwiY3JlYXRlQXBwIiwiYXBwIiwiZW5hYmxlIiwicHVibGljRm9sZGVyIiwicHJvY2VzcyIsImN3ZCIsInN0YXRpYyIsInB1YmxpY1BhdGgiLCJfX2Rpcm5hbWUiLCJ1cmxlbmNvZGVkIiwiZXh0ZW5kZWQiLCJzcGVlY2hQYXNzcG9ydCIsIm1heEFnZSIsImluaXRpYWxpemUiLCJzZXNzaW9uIiwiaGJzIiwiZGVmYXVsdExheW91dCIsImhhbmRsZWJhcnMiLCJlbmdpbmUiLCJzZXQiLCJzZXJ2ZXIiLCJzdGFydCIsIlBPUlQiLCJzeW5jIiwibGlzdGVuIiwibmV4dCIsIkxvZ2dlckNvbmZpZyIsImxvZ0xldmVsIiwiY29uZmlndXJlIiwidHJhbnNwb3J0cyIsIkNvbnNvbGUiLCJsZXZlbCIsInRpbWVzdGFtcCIsImNvbG9yaXplIiwicHJldHR5UHJpbnQiLCJoYW5kbGVFeGNlcHRpb25zIiwiaHVtYW5SZWFkYWJsZVVuaGFuZGxlZEV4Y2VwdGlvbiIsInNpbGx5Iiwid2luc3RvblNsYWNrV2ViSG9vayIsIlNsYWNrV2ViSG9vayIsIndpbnN0b24iLCJTbGFja0NvbmZpZyIsInNsYWNrV2ViSG9vayIsInNsYWNrRXJyb3JDaGFubmVsIiwic2xhY2tJbmZvQ2hhbm5lbCIsImFkZCIsIndlYmhvb2tVcmwiLCJpY29uRW1vamkiLCJQYXNzcG9ydExvY2FsU3RyYXRlZ3kiLCJTdHJhdGVneSIsInJldHVyblVzZXJBbmRDaGFubmVsSW5mbyIsInVzZXJJbnN0YW5jZSIsInVzZXJJbmZvIiwiaWQiLCJ1c2VyTmFtZSIsImdldENoYW5uZWwiLCJzaG9ydENoYW5uZWxJZCIsInVzZXJuYW1lRmllbGQiLCJwYXNzd29yZEZpZWxkIiwidXNlciIsImNvbXBhcmVQYXNzd29yZCIsImlzTWF0Y2giLCJTVFJJTkciLCJCT09MRUFOIiwiSU5URUdFUiIsIlRFWFQiLCJERUNJTUFMIiwiZGVmaW5lIiwiZGVmYXVsdCIsImNsYWltU2VxdWVuY2UiLCJkZWNvZGVkQ2xhaW0iLCJkZXB0aCIsImVmZmVjdGl2ZUFtb3VudCIsImhhc1NpZ25hdHVyZSIsImhleCIsInZhbGlkQXRIZWlnaHQiLCJ2YWx1ZVZlcnNpb24iLCJjbGFpbVR5cGUiLCJjZXJ0aWZpY2F0ZVZlcnNpb24iLCJrZXlUeXBlIiwicHVibGljS2V5IiwiZnJlZXplVGFibGVOYW1lIiwiYmVsb25nc1RvIiwiZm9yZWlnbktleSIsImFsbG93TnVsbCIsIm9yZGVyIiwiZ2V0TG9uZ0NoYW5uZWxJZEZyb21TaG9ydENoYW5uZWxJZCIsIiRsaWtlIiwiZ2V0TG9uZ0NoYW5uZWxJZEZyb21DaGFubmVsTmFtZSIsInZhbGlkYXRlTG9uZ0NoYW5uZWxJZCIsImhhc09uZSIsImRlZmF1bHRUaHVtYm5haWwiLCJkZXRlcm1pbmVGaWxlRXh0ZW5zaW9uRnJvbUNvbnRlbnRUeXBlIiwiZGV0ZXJtaW5lVGh1bWJuYWlsIiwic3RvcmVkVGh1bWJuYWlsIiwicHJlcGFyZUNsYWltRGF0YSIsImxpY2Vuc2VVcmwiLCJwcmV2aWV3IiwibWV0YWRhdGFWZXJzaW9uIiwic291cmNlIiwic291cmNlVHlwZSIsInNvdXJjZVZlcnNpb24iLCJzdHJlYW1WZXJzaW9uIiwiZ2V0U2hvcnRDbGFpbUlkRnJvbUxvbmdDbGFpbUlkIiwicmF3IiwiZ2V0TG9uZ0NsYWltSWRGcm9tU2hvcnRDbGFpbUlkIiwiZ2V0VG9wRnJlZUNsYWltSWRCeUNsYWltTmFtZSIsInZhbGlkYXRlTG9uZ0NsYWltSWQiLCJyZXNvbHZlQ2xhaW0iLCJjbGFpbUFycmF5IiwiZGVmYXVsdFZhbHVlIiwidHJlbmRpbmdFbGlnaWJsZSIsImhhc01hbnkiLCJnZXRSZWNlbnRDbGFpbXMiLCJsaW1pdCIsImlwQWRkcmVzcyIsImJjcnlwdCIsInByb3RvdHlwZSIsImNvbXBhcmUiLCJjaGFuZ2VQYXNzd29yZCIsIm5ld1Bhc3N3b3JkIiwiZ2VuU2FsdCIsInNhbHRFcnJvciIsInNhbHQiLCJoYXNoIiwiaGFzaEVycm9yIiwiaG9vayIsIm9wdGlvbnMiLCJ1c2VyRGF0YSIsImNoYW5uZWxEYXRhIiwiY2VydGlmaWNhdGVEYXRhIiwibmV3VXNlciIsIm5ld0NoYW5uZWwiLCJuZXdDZXJ0aWZpY2F0ZSIsInNldENoYW5uZWwiLCJzZXRVc2VyIiwibGJyeUNvbmZpZyIsImhhbmRsZVNpZ251cFJlcXVlc3QiLCJoYW5kbGVMb2dpblJlcXVlc3QiLCJoYW5kbGVMb2dvdXRSZXF1ZXN0IiwiaGFuZGxlVXNlclJlcXVlc3QiLCJnZXQiLCJzaWdudXAiLCJsb2dpbiIsImxvZ0luIiwibG9nb3V0IiwiY2hhbm5lbEF2YWlsYWJpbGl0eSIsImNoYW5uZWxDbGFpbXMiLCJjaGFubmVsU2hvcnRJZCIsImNsYWltQXZhaWxhYmlsaXR5IiwiY2xhaW1EYXRhIiwiY2xhaW1HZXQiLCJjbGFpbUxvbmdJZCIsImNsYWltUHVibGlzaCIsImNsYWltUmVzb2x2ZSIsImNsYWltU2hvcnRJZCIsImNsYWltTGlzdCIsImZpbGVBdmFpbGFiaWxpdHkiLCJtdWx0aXBhcnRNaWRkbGV3YXJlIiwiYXZhaWxhYmxlTmFtZSIsImJvZHkiLCJDTEFJTVNfUEVSX1BBR0UiLCJjbGFpbXMiLCJ0b3RhbFBhZ2VzIiwiZGV0ZXJtaW5lVG90YWxQYWdlcyIsInBhZ2luYXRpb25QYWdlIiwiZ2V0UGFnZUZyb21RdWVyeSIsInZpZXdEYXRhIiwiZXh0cmFjdFBhZ2VGcm9tQ2xhaW1zIiwicHJldmlvdXNQYWdlIiwiZGV0ZXJtaW5lUHJldmlvdXNQYWdlIiwiY3VycmVudFBhZ2UiLCJuZXh0UGFnZSIsImRldGVybWluZU5leHRQYWdlIiwidG90YWxSZXN1bHRzIiwiZGV0ZXJtaW5lVG90YWxDbGFpbXMiLCJwYXJzZUludCIsInBhZ2VOdW1iZXIiLCJjbGFpbVN0YXJ0SW5kZXgiLCJjbGFpbUVuZEluZGV4IiwicGFnZU9mQ2xhaW1zIiwidG90YWxDbGFpbXMiLCJmdWxsUGFnZXMiLCJNYXRoIiwiZmxvb3IiLCJyZW1haW5kZXIiLCJjaGFubmVsU2hvcnRJZFJvdXRlIiwiY2xhaW1JbmZvIiwicmVzb2x2ZVJlc3VsdCIsImZpbGVEYXRhIiwiY29tcGxldGVkIiwiYXV0aGVudGljYXRlVXNlciIsImZpbGVzIiwiY2hhbm5lbFBhc3N3b3JkIiwidmFsaWRhdGVkQ2xhaW1OYW1lIiwidGh1bWJuYWlsUHVibGlzaFBhcmFtcyIsImxicnlUeCIsImF1dGhlbnRpY2F0ZUNoYW5uZWxDcmVkZW50aWFscyIsInVzZXJQYXNzd29yZCIsImNoYW5uZWxGaW5kUGFyYW1zIiwicmVzb2x2ZWRVcmkiLCJjbGFpbXNMaXN0IiwibXVsdGlwYXJ0IiwidXBsb2FkRGlyIiwiaGFuZGxlUGFnZVJlcXVlc3QiLCJoYW5kbGVFbWJlZFJlcXVlc3QiLCJoYW5kbGVQYWdlUmVuZGVyIiwic2VuZFJlYWN0QXBwIiwic2VuZEVtYmVkUGFnZSIsInJlbmRlciIsImxheW91dCIsInJvdXRlIiwic2VydmVBc3NldEJ5Q2xhaW0iLCJzZXJ2ZUFzc2V0QnlJZGVudGlmaWVyQW5kQ2xhaW0iLCJsYnJ5VXJpIiwiaGFuZGxlU2hvd1JlbmRlciIsInNlcnZlckFzc2V0QnlDbGFpbSIsInNlcnZlckFzc2V0QnlJZGVudGlmaWVyQW5kQ2xhaW0iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOztBQUVBO0FBQ0E7Ozs7Ozs7QUM3REEsb0M7Ozs7Ozs7Ozs7O0FDQUEsSUFBTUEsU0FBUyxtQkFBQUMsQ0FBUSxDQUFSLENBQWY7O0FBRUFDLE9BQU9DLE9BQVAsR0FBaUI7QUFDZkMsdUJBQXFCLDZCQUFVQyxXQUFWLEVBQXVCQyxFQUF2QixFQUEyQkMsS0FBM0IsRUFBa0NDLEdBQWxDLEVBQXVDO0FBQzFEUixXQUFPTyxL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TUUsbUJBQW1CLG1CQUFBempCLENBQVEsRUFBUixDQUF6Qjs7QUFFQSxJQUFNMGpCLGVBQWUsU0FBZkEsWUFBZSxDQUFDelMsR0FBRCxFQUFNMVEsR0FBTixFQUFjO0FBQ2pDa2pCLG1CQUFpQnhTLEdBQWpCLEVBQXNCMVEsR0FBdEI7QUFDRCxDQUZEOztBQUlBTixPQUFPQyxPQUFQLEdBQWlCd2pCLFlBQWpCLEMiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBUaGUgbW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCIvXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMjYpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svYm9vdHN0cmFwIGQyMTJiYTAwZDhkYjIxNDdhOGFkIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwid2luc3RvblwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcIndpbnN0b25cIlxuLy8gbW9kdWxlIGlkID0gMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBoYW5kbGVFcnJvclJlc3BvbnNlOiBmdW5jdGlvbiAob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKSB7XG4gICAgbG9nZ2VyLmVycm9yKGBFcnJvciBvbiAke29yaWdpbmFsVXJsfWAsIG1vZHVsZS5leHBvcnRzLnVzZU9iamVjdFByb3BlcnRpZXNJZk5vS2V5cyhlcnJvcikpO1xuICAgIGNvbnN0IFtzdGF0dXMsIG1lc3NhZ2VdID0gbW9kdWxlLmV4cG9ydHMucmV0dXJuRXJyb3JNZXNzYWdlQW5kU3RhdHVzKGVycm9yKTtcbiAgICByZXNcbiAgICAgIC5zdGF0dXMoc3RhdHVzKVxuICAgICAgLmpzb24obW9kdWxlLmV4cG9ydHMuY3JlYXRlRXJyb3JSZXNwb25zZVBheWxvYWQoc3RhdHVzLCBtZXNzYWdlKSk7XG4gIH0sXG4gIHJldHVybkVycm9yTWVzc2FnZUFuZFN0YXR1czogZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgbGV0IHN0YXR1cywgbWVzc2FnZTtcbiAgICAvLyBjaGVjayBmb3IgZGFlbW9uIGJlaW5nIHR1cm5lZCBvZmZcbiAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ0VDT05OUkVGVVNFRCcpIHtcbiAgICAgIHN0YXR1cyA9IDUwMztcbiAgICAgIG1lc3NhZ2UgPSAnQ29ubmVjdGlvbiByZWZ1c2VkLiAgVGhlIGRhZW1vbiBtYXkgbm90IGJlIHJ1bm5pbmcuJztcbiAgICAgIC8vIGZhbGxiYWNrIGZvciBldmVyeXRoaW5nIGVsc2VcbiAgICB9IGVsc2Uge1xuICAgICAgc3RhdHVzID0gNDAwO1xuICAgICAgaWYgKGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtZXNzYWdlID0gZXJyb3I7XG4gICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIFtzdGF0dXMsIG1lc3NhZ2VdO1xuICB9LFxuICB1c2VPYmplY3RQcm9wZXJ0aWVzSWZOb0tleXM6IGZ1bmN0aW9uIChlcnIpIHtcbiAgICBpZiAoT2JqZWN0LmtleXMoZXJyKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGxldCBuZXdFcnJvck9iamVjdCA9IHt9O1xuICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoZXJyKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgbmV3RXJyb3JPYmplY3Rba2V5XSA9IGVycltrZXldO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmV3RXJyb3JPYmplY3Q7XG4gICAgfVxuICAgIHJldHVybiBlcnI7XG4gIH0sXG4gIGNyZWF0ZUVycm9yUmVzcG9uc2VQYXlsb2FkIChzdGF0dXMsIG1lc3NhZ2UpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzLFxuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBtZXNzYWdlLFxuICAgIH07XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcyIsImNvbnN0IENlcnRpZmljYXRlID0gcmVxdWlyZSgnbW9kZWxzL2NlcnRpZmljYXRlLmpzJyk7XG5jb25zdCBDaGFubmVsID0gcmVxdWlyZSgnbW9kZWxzL2NoYW5uZWwuanMnKTtcbmNvbnN0IENsYWltID0gcmVxdWlyZSgnbW9kZWxzL2NsYWltLmpzJyk7XG5jb25zdCBGaWxlID0gcmVxdWlyZSgnbW9kZWxzL2ZpbGUuanMnKTtcbmNvbnN0IFJlcXVlc3QgPSByZXF1aXJlKCdtb2RlbHMvcmVxdWVzdC5qcycpO1xuY29uc3QgVXNlciA9IHJlcXVpcmUoJ21vZGVscy91c2VyLmpzJyk7XG5cbmNvbnN0IFNlcXVlbGl6ZSA9IHJlcXVpcmUoJ3NlcXVlbGl6ZScpO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5jb25zdCB7ZGF0YWJhc2UsIHVzZXJuYW1lLCBwYXNzd29yZH0gPSByZXF1aXJlKCdteXNxbENvbmZpZy5qcycpO1xuXG4vLyBzZXQgc2VxdWVsaXplIG9wdGlvbnNcbmNvbnN0IHNlcXVlbGl6ZSA9IG5ldyBTZXF1ZWxpemUoZGF0YWJhc2UsIHVzZXJuYW1lLCBwYXNzd29yZCwge1xuICBob3N0ICAgICAgICAgIDogJ2xvY2FsaG9zdCcsXG4gIGRpYWxlY3QgICAgICAgOiAnbXlzcWwnLFxuICBkaWFsZWN0T3B0aW9uczoge2RlY2ltYWxOdW1iZXJzOiB0cnVlfSxcbiAgbG9nZ2luZyAgICAgICA6IGZhbHNlLFxuICBwb29sICAgICAgICAgIDoge1xuICAgIG1heCAgICA6IDUsXG4gICAgbWluICAgIDogMCxcbiAgICBpZGxlICAgOiAxMDAwMCxcbiAgICBhY3F1aXJlOiAxMDAwMCxcbiAgfSxcbn0pO1xuXG4vLyBlc3RhYmxpc2ggbXlzcWwgY29ubmVjdGlvblxuc2VxdWVsaXplXG4gIC5hdXRoZW50aWNhdGUoKVxuICAudGhlbigoKSA9PiB7XG4gICAgbG9nZ2VyLmluZm8oJ1NlcXVlbGl6ZSBoYXMgZXN0YWJsaXNoZWQgbXlzcWwgY29ubmVjdGlvbiBzdWNjZXNzZnVsbHkuJyk7XG4gIH0pXG4gIC5jYXRjaChlcnIgPT4ge1xuICAgIGxvZ2dlci5lcnJvcignU2VxdWVsaXplIHdhcyB1bmFibGUgdG8gY29ubmVjdCB0byB0aGUgZGF0YWJhc2U6JywgZXJyKTtcbiAgfSk7XG5cbi8vIG1hbnVhbGx5IGFkZCBlYWNoIG1vZGVsIHRvIHRoZSBkYiBvYmplY3QgKG5vdGU6IG1ha2UgdGhpcyBkeW5hbWljKVxuY29uc3QgZGIgPSB7fTtcbmRiWydDZXJ0aWZpY2F0ZSddID0gc2VxdWVsaXplLmltcG9ydCgnQ2VydGlmaWNhdGUnLCBDZXJ0aWZpY2F0ZSk7XG5kYlsnQ2hhbm5lbCddID0gc2VxdWVsaXplLmltcG9ydCgnQ2hhbm5lbCcsIENoYW5uZWwpO1xuZGJbJ0NsYWltJ10gPSBzZXF1ZWxpemUuaW1wb3J0KCdDbGFpbScsIENsYWltKTtcbmRiWydGaWxlJ10gPSBzZXF1ZWxpemUuaW1wb3J0KCdGaWxlJywgRmlsZSk7XG5kYlsnUmVxdWVzdCddID0gc2VxdWVsaXplLmltcG9ydCgnUmVxdWVzdCcsIFJlcXVlc3QpO1xuZGJbJ1VzZXInXSA9IHNlcXVlbGl6ZS5pbXBvcnQoJ1VzZXInLCBVc2VyKTtcblxuLy8gcnVuIG1vZGVsLmFzc29jaWF0aW9uIGZvciBlYWNoIG1vZGVsIGluIHRoZSBkYiBvYmplY3QgdGhhdCBoYXMgYW4gYXNzb2NpYXRpb25cbmxvZ2dlci5pbmZvKCdhc3NvY2lhdGluZyBkYiBtb2RlbHMuLi4nKTtcbk9iamVjdC5rZXlzKGRiKS5mb3JFYWNoKG1vZGVsTmFtZSA9PiB7XG4gIGlmIChkYlttb2RlbE5hbWVdLmFzc29jaWF0ZSkge1xuICAgIGxvZ2dlci5pbmZvKCdBc3NvY2lhdGluZyBtb2RlbDonLCBtb2RlbE5hbWUpO1xuICAgIGRiW21vZGVsTmFtZV0uYXNzb2NpYXRlKGRiKTtcbiAgfVxufSk7XG5cbi8vIGFkZCBzZXF1ZWxpemUvU2VxdWVsaXplIHRvIGRiXG5kYi5zZXF1ZWxpemUgPSBzZXF1ZWxpemU7XG5kYi5TZXF1ZWxpemUgPSBTZXF1ZWxpemU7XG4vLyBhZGQgYW4gJ3Vwc2VydCcgbWV0aG9kIHRvIHRoZSBkYiBvYmplY3RcbmRiLnVwc2VydCA9IChNb2RlbCwgdmFsdWVzLCBjb25kaXRpb24sIHRhYmxlTmFtZSkgPT4ge1xuICByZXR1cm4gTW9kZWxcbiAgICAuZmluZE9uZSh7XG4gICAgICB3aGVyZTogY29uZGl0aW9uLFxuICAgIH0pXG4gICAgLnRoZW4ob2JqID0+IHtcbiAgICAgIGlmIChvYmopIHsgIC8vIHVwZGF0ZVxuICAgICAgICBsb2dnZXIuZGVidWcoYHVwZGF0aW5nIHJlY29yZCBpbiBkYi4ke3RhYmxlTmFtZX1gKTtcbiAgICAgICAgcmV0dXJuIG9iai51cGRhdGUodmFsdWVzKTtcbiAgICAgIH0gZWxzZSB7ICAvLyBpbnNlcnRcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBjcmVhdGluZyByZWNvcmQgaW4gZGIuJHt0YWJsZU5hbWV9YCk7XG4gICAgICAgIHJldHVybiBNb2RlbC5jcmVhdGUodmFsdWVzKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgJHt0YWJsZU5hbWV9LnVwc2VydCBlcnJvcmAsIGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBkYjtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9tb2RlbHMvaW5kZXguanMiLCJmdW5jdGlvbiBTaXRlQ29uZmlnICgpIHtcbiAgdGhpcy5hbmFseXRpY3MgPSB7XG4gICAgZ29vZ2xlSWQ6ICdkZWZhdWx0JyxcbiAgfTtcbiAgdGhpcy5hc3NldERlZmF1bHRzID0ge1xuICAgIGRlc2NyaXB0aW9uOiAnQW4gYXNzZXQgcHVibGlzaGVkIG9uIFNwZWUuY2gnLFxuICAgIHRodW1ibmFpbCAgOiAnaHR0cHM6Ly9zcGVlLmNoL2Fzc2V0cy9pbWcvdmlkZW9fdGh1bWJfZGVmYXVsdC5wbmcnLFxuICAgIHRpdGxlICAgICAgOiAnU3BlZS5jaCcsXG4gIH07XG4gIHRoaXMuYXV0aCA9IHtcbiAgICBzZXNzaW9uS2V5OiAnZGVmYXVsdCcsXG4gIH07XG4gIHRoaXMuY3VzdG9tQ29tcG9uZW50cyA9IHt9O1xuICB0aGlzLmN1c3RvbUNvbnRhaW5lcnMgPSB7fTtcbiAgdGhpcy5jdXN0b21QYWdlcyA9IHt9O1xuICB0aGlzLmRldGFpbHMgPSB7XG4gICAgZGVzY3JpcHRpb246ICdPcGVuLXNvdXJjZSwgZGVjZW50cmFsaXplZCBpbWFnZSBhbmQgdmlkZW8gc2hhcmluZy4nLFxuICAgIGhvc3QgICAgICAgOiAnZGVmYXVsdCcsXG4gICAgcG9ydCAgICAgICA6IDMwMDAsXG4gICAgdGl0bGUgICAgICA6ICdTcGVlLmNoJyxcbiAgICB0d2l0dGVyICAgIDogJ0BzcGVlX2NoJyxcbiAgfTtcbiAgdGhpcy5wdWJsaXNoaW5nID0ge1xuICAgIGFkZGl0aW9uYWxDbGFpbUFkZHJlc3NlczogW10sXG4gICAgZGlzYWJsZWQgICAgICAgICAgICAgICAgOiBmYWxzZSxcbiAgICBkaXNhYmxlZE1lc3NhZ2UgICAgICAgICA6ICdQbGVhc2UgY2hlY2sgYmFjayBzb29uLicsXG4gICAgcHJpbWFyeUNsYWltQWRkcmVzcyAgICAgOiAnZGVmYXVsdCcsXG4gICAgdGh1bWJuYWlsQ2hhbm5lbCAgICAgICAgOiAnZGVmYXVsdCcsXG4gICAgdGh1bWJuYWlsQ2hhbm5lbElkICAgICAgOiAnZGVmYXVsdCcsXG4gICAgdXBsb2FkRGlyZWN0b3J5ICAgICAgICAgOiAnL2hvbWUvbGJyeS9VcGxvYWRzJyxcbiAgfTtcbiAgdGhpcy5yb3V0ZXMgPSB7fTtcbiAgdGhpcy51cGRhdGUgPSAoY29uZmlnKSA9PiB7XG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHJldHVybiBjb25zb2xlLmxvZygnTm8gc2l0ZSBjb25maWcgcmVjZWl2ZWQuJyk7XG4gICAgfVxuICAgIGNvbnN0IHsgYW5hbHl0aWNzLCBhc3NldERlZmF1bHRzLCBhdXRoLCBjdXN0b21Db21wb25lbnRzLCBjdXN0b21Db250YWluZXJzLCBjdXN0b21QYWdlcywgZGV0YWlscywgcHVibGlzaGluZywgcm91dGVzIH0gPSBjb25maWc7XG4gICAgY29uc29sZS5sb2coJ0NvbmZpZ3VyaW5nIHNpdGUgZGV0YWlscy4uLicpO1xuICAgIHRoaXMuYW5hbHl0aWNzID0gYW5hbHl0aWNzO1xuICAgIHRoaXMuYXNzZXREZWZhdWx0cyA9IGFzc2V0RGVmYXVsdHM7XG4gICAgdGhpcy5hdXRoID0gYXV0aDtcbiAgICB0aGlzLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgIHRoaXMucHVibGlzaGluZyA9IHB1Ymxpc2hpbmc7XG4gICAgdGhpcy5jdXN0b21Db21wb25lbnRzID0gY3VzdG9tQ29tcG9uZW50cztcbiAgICB0aGlzLmN1c3RvbUNvbnRhaW5lcnMgPSBjdXN0b21Db250YWluZXJzO1xuICAgIHRoaXMuY3VzdG9tUGFnZXMgPSBjdXN0b21QYWdlcztcbiAgICB0aGlzLnJvdXRlcyA9IHJvdXRlcztcbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFNpdGVDb25maWcoKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL2NvbmZpZy9zaXRlQ29uZmlnLmpzIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgdWEgPSByZXF1aXJlKCd1bml2ZXJzYWwtYW5hbHl0aWNzJyk7XG5jb25zdCB7IGFuYWx5dGljcyA6IHsgZ29vZ2xlSWQgfSwgZGV0YWlsczogeyB0aXRsZSB9IH0gPSByZXF1aXJlKCcuLi8uLi9jb25maWcvc2l0ZUNvbmZpZy5qcycpO1xuXG5mdW5jdGlvbiBjcmVhdGVTZXJ2ZUV2ZW50UGFyYW1zIChoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwpIHtcbiAgcmV0dXJuIHtcbiAgICBldmVudENhdGVnb3J5ICAgIDogJ2NsaWVudCByZXF1ZXN0cycsXG4gICAgZXZlbnRBY3Rpb24gICAgICA6ICdzZXJ2ZSByZXF1ZXN0JyxcbiAgICBldmVudExhYmVsICAgICAgIDogb3JpZ2luYWxVcmwsXG4gICAgaXBPdmVycmlkZSAgICAgICA6IGlwLFxuICAgIHVzZXJBZ2VudE92ZXJyaWRlOiBoZWFkZXJzWyd1c2VyLWFnZW50J10sXG4gIH07XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVQdWJsaXNoVGltaW5nRXZlbnRQYXJhbXMgKGNhdGVnb3J5LCB2YXJpYWJsZSwgbGFiZWwsIHN0YXJ0VGltZSwgZW5kVGltZSkge1xuICBjb25zdCBkdXJhdGlvbiA9IGVuZFRpbWUgLSBzdGFydFRpbWU7XG4gIHJldHVybiB7XG4gICAgdXNlclRpbWluZ0NhdGVnb3J5ICAgIDogY2F0ZWdvcnksXG4gICAgdXNlclRpbWluZ1ZhcmlhYmxlTmFtZTogdmFyaWFibGUsXG4gICAgdXNlclRpbWluZ1RpbWUgICAgICAgIDogZHVyYXRpb24sXG4gICAgdXNlclRpbWluZ0xhYmVsICAgICAgIDogbGFiZWwsXG4gIH07XG59O1xuXG5mdW5jdGlvbiBzZW5kR29vZ2xlQW5hbHl0aWNzRXZlbnQgKGlwLCBwYXJhbXMpIHtcbiAgY29uc3QgdmlzaXRvcklkID0gaXAucmVwbGFjZSgvXFwuL2csICctJyk7XG4gIGNvbnN0IHZpc2l0b3IgPSB1YShnb29nbGVJZCwgdmlzaXRvcklkLCB7IHN0cmljdENpZEZvcm1hdDogZmFsc2UsIGh0dHBzOiB0cnVlIH0pO1xuICB2aXNpdG9yLmV2ZW50KHBhcmFtcywgKGVycikgPT4ge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignR29vZ2xlIEFuYWx5dGljcyBFdmVudCBFcnJvciA+PicsIGVycik7XG4gICAgfVxuICB9KTtcbn07XG5cbmZ1bmN0aW9uIHNlbmRHb29nbGVBbmFseXRpY3NUaW1pbmcgKHZpc2l0b3JJZCwgcGFyYW1zKSB7XG4gIGNvbnN0IHZpc2l0b3IgPSB1YShnb29nbGVJZCwgdmlzaXRvcklkLCB7IHN0cmljdENpZEZvcm1hdDogZmFsc2UsIGh0dHBzOiB0cnVlIH0pO1xuICB2aXNpdG9yLnRpbWluZyhwYXJhbXMsIChlcnIpID0+IHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0dvb2dsZSBBbmFseXRpY3MgRXZlbnQgRXJyb3IgPj4nLCBlcnIpO1xuICAgIH1cbiAgICBsb2dnZXIuZGVidWcoYFRpbWluZyBldmVudCBzdWNjZXNzZnVsbHkgc2VudCB0byBnb29nbGUgYW5hbHl0aWNzYCk7XG4gIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNlbmRHQVNlcnZlRXZlbnQgKGhlYWRlcnMsIGlwLCBvcmlnaW5hbFVybCkge1xuICAgIGNvbnN0IHBhcmFtcyA9IGNyZWF0ZVNlcnZlRXZlbnRQYXJhbXMoaGVhZGVycywgaXAsIG9yaWdpbmFsVXJsKTtcbiAgICBzZW5kR29vZ2xlQW5hbHl0aWNzRXZlbnQoaXAsIHBhcmFtcyk7XG4gIH0sXG4gIHNlbmRHQVRpbWluZ0V2ZW50IChjYXRlZ29yeSwgdmFyaWFibGUsIGxhYmVsLCBzdGFydFRpbWUsIGVuZFRpbWUpIHtcbiAgICBjb25zdCBwYXJhbXMgPSBjcmVhdGVQdWJsaXNoVGltaW5nRXZlbnRQYXJhbXMoY2F0ZWdvcnksIHZhcmlhYmxlLCBsYWJlbCwgc3RhcnRUaW1lLCBlbmRUaW1lKTtcbiAgICBzZW5kR29vZ2xlQW5hbHl0aWNzVGltaW5nKHRpdGxlLCBwYXJhbXMpO1xuICB9LFxuICBjaG9vc2VHYUxicnluZXRQdWJsaXNoTGFiZWwgKHsgY2hhbm5lbF9uYW1lOiBjaGFubmVsTmFtZSwgY2hhbm5lbF9pZDogY2hhbm5lbElkIH0pIHtcbiAgICByZXR1cm4gKGNoYW5uZWxOYW1lIHx8IGNoYW5uZWxJZCA/ICdQVUJMSVNIX0lOX0NIQU5ORUxfQ0xBSU0nIDogJ1BVQkxJU0hfQU5PTllNT1VTX0NMQUlNJyk7XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvZ29vZ2xlQW5hbHl0aWNzLmpzIiwiY29uc3QgYXhpb3MgPSByZXF1aXJlKCdheGlvcycpO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgeyBhcGk6IHsgYXBpSG9zdCwgYXBpUG9ydCB9IH0gPSByZXF1aXJlKCcuLi8uLi9jb25maWcvbGJyeUNvbmZpZy5qcycpO1xuY29uc3QgbGJyeUFwaVVyaSA9ICdodHRwOi8vJyArIGFwaUhvc3QgKyAnOicgKyBhcGlQb3J0O1xuY29uc3QgeyBjaG9vc2VHYUxicnluZXRQdWJsaXNoTGFiZWwsIHNlbmRHQVRpbWluZ0V2ZW50IH0gPSByZXF1aXJlKCcuL2dvb2dsZUFuYWx5dGljcy5qcycpO1xuXG5jb25zdCBoYW5kbGVMYnJ5bmV0UmVzcG9uc2UgPSAoeyBkYXRhIH0sIHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICBsb2dnZXIuZGVidWcoJ2xicnkgYXBpIGRhdGE6JywgZGF0YSk7XG4gIGlmIChkYXRhLnJlc3VsdCkge1xuICAgIC8vIGNoZWNrIGZvciBhbiBlcnJvclxuICAgIGlmIChkYXRhLnJlc3VsdC5lcnJvcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdMYnJ5bmV0IGFwaSBlcnJvcjonLCBkYXRhLnJlc3VsdC5lcnJvcik7XG4gICAgICByZWplY3QobmV3IEVycm9yKGRhdGEucmVzdWx0LmVycm9yKSk7XG4gICAgICByZXR1cm47XG4gICAgfTtcbiAgICByZXNvbHZlKGRhdGEucmVzdWx0KTtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gZmFsbGJhY2sgaW4gY2FzZSBpdCBqdXN0IHRpbWVkIG91dFxuICByZWplY3QoSlNPTi5zdHJpbmdpZnkoZGF0YSkpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHB1Ymxpc2hDbGFpbSAocHVibGlzaFBhcmFtcykge1xuICAgIGxvZ2dlci5kZWJ1ZyhgbGJyeUFwaSA+PiBQdWJsaXNoaW5nIGNsYWltIHRvIFwiJHtwdWJsaXNoUGFyYW1zLm5hbWV9XCJgKTtcbiAgICBjb25zdCBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGF4aW9zXG4gICAgICAgIC5wb3N0KGxicnlBcGlVcmksIHtcbiAgICAgICAgICBtZXRob2Q6ICdwdWJsaXNoJyxcbiAgICAgICAgICBwYXJhbXM6IHB1Ymxpc2hQYXJhbXMsXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICBzZW5kR0FUaW1pbmdFdmVudCgnbGJyeW5ldCcsICdwdWJsaXNoJywgY2hvb3NlR2FMYnJ5bmV0UHVibGlzaExhYmVsKHB1Ymxpc2hQYXJhbXMpLCBnYVN0YXJ0VGltZSwgRGF0ZS5ub3coKSk7XG4gICAgICAgICAgaGFuZGxlTGJyeW5ldFJlc3BvbnNlKHJlc3BvbnNlLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9LFxuICBnZXRDbGFpbSAodXJpKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBsYnJ5QXBpID4+IEdldHRpbmcgQ2xhaW0gZm9yIFwiJHt1cml9XCJgKTtcbiAgICBjb25zdCBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGF4aW9zXG4gICAgICAgIC5wb3N0KGxicnlBcGlVcmksIHtcbiAgICAgICAgICBtZXRob2Q6ICdnZXQnLFxuICAgICAgICAgIHBhcmFtczogeyB1cmksIHRpbWVvdXQ6IDIwIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICBzZW5kR0FUaW1pbmdFdmVudCgnbGJyeW5ldCcsICdnZXRDbGFpbScsICdHRVQnLCBnYVN0YXJ0VGltZSwgRGF0ZS5ub3coKSk7XG4gICAgICAgICAgaGFuZGxlTGJyeW5ldFJlc3BvbnNlKHJlc3BvbnNlLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9LFxuICBnZXRDbGFpbUxpc3QgKGNsYWltTmFtZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgbGJyeUFwaSA+PiBHZXR0aW5nIGNsYWltX2xpc3QgZm9yIFwiJHtjbGFpbU5hbWV9XCJgKTtcbiAgICBjb25zdCBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGF4aW9zXG4gICAgICAgIC5wb3N0KGxicnlBcGlVcmksIHtcbiAgICAgICAgICBtZXRob2Q6ICdjbGFpbV9saXN0JyxcbiAgICAgICAgICBwYXJhbXM6IHsgbmFtZTogY2xhaW1OYW1lIH0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICBzZW5kR0FUaW1pbmdFdmVudCgnbGJyeW5ldCcsICdnZXRDbGFpbUxpc3QnLCAnQ0xBSU1fTElTVCcsIGdhU3RhcnRUaW1lLCBEYXRlLm5vdygpKTtcbiAgICAgICAgICBoYW5kbGVMYnJ5bmV0UmVzcG9uc2UocmVzcG9uc2UsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH0sXG4gIHJlc29sdmVVcmkgKHVyaSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgbGJyeUFwaSA+PiBSZXNvbHZpbmcgVVJJIGZvciBcIiR7dXJpfVwiYCk7XG4gICAgY29uc3QgZ2FTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBheGlvc1xuICAgICAgICAucG9zdChsYnJ5QXBpVXJpLCB7XG4gICAgICAgICAgbWV0aG9kOiAncmVzb2x2ZScsXG4gICAgICAgICAgcGFyYW1zOiB7IHVyaSB9LFxuICAgICAgICB9KVxuICAgICAgICAudGhlbigoeyBkYXRhIH0pID0+IHtcbiAgICAgICAgICBzZW5kR0FUaW1pbmdFdmVudCgnbGJyeW5ldCcsICdyZXNvbHZlVXJpJywgJ1JFU09MVkUnLCBnYVN0YXJ0VGltZSwgRGF0ZS5ub3coKSk7XG4gICAgICAgICAgaWYgKGRhdGEucmVzdWx0W3VyaV0uZXJyb3IpIHsgIC8vIGNoZWNrIGZvciBlcnJvcnNcbiAgICAgICAgICAgIHJlamVjdChkYXRhLnJlc3VsdFt1cmldLmVycm9yKTtcbiAgICAgICAgICB9IGVsc2UgeyAgLy8gaWYgbm8gZXJyb3JzLCByZXNvbHZlXG4gICAgICAgICAgICByZXNvbHZlKGRhdGEucmVzdWx0W3VyaV0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfSxcbiAgZ2V0RG93bmxvYWREaXJlY3RvcnkgKCkge1xuICAgIGxvZ2dlci5kZWJ1ZygnbGJyeUFwaSA+PiBSZXRyaWV2aW5nIHRoZSBkb3dubG9hZCBkaXJlY3RvcnkgcGF0aCBmcm9tIGxicnkgZGFlbW9uLi4uJyk7XG4gICAgY29uc3QgZ2FTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBheGlvc1xuICAgICAgICAucG9zdChsYnJ5QXBpVXJpLCB7XG4gICAgICAgICAgbWV0aG9kOiAnc2V0dGluZ3NfZ2V0JyxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKHsgZGF0YSB9KSA9PiB7XG4gICAgICAgICAgc2VuZEdBVGltaW5nRXZlbnQoJ2xicnluZXQnLCAnZ2V0RG93bmxvYWREaXJlY3RvcnknLCAnU0VUVElOR1NfR0VUJywgZ2FTdGFydFRpbWUsIERhdGUubm93KCkpO1xuICAgICAgICAgIGlmIChkYXRhLnJlc3VsdCkge1xuICAgICAgICAgICAgcmVzb2x2ZShkYXRhLnJlc3VsdC5kb3dubG9hZF9kaXJlY3RvcnkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVycm9yKCdTdWNjZXNzZnVsbHkgY29ubmVjdGVkIHRvIGxicnkgZGFlbW9uLCBidXQgdW5hYmxlIHRvIHJldHJpZXZlIHRoZSBkb3dubG9hZCBkaXJlY3RvcnkuJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcignTGJyeW5ldCBFcnJvcjonLCBlcnJvcik7XG4gICAgICAgICAgcmVzb2x2ZSgnL2hvbWUvbGJyeS9Eb3dubG9hZHMvJyk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9LFxuICBjcmVhdGVDaGFubmVsIChuYW1lKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBsYnJ5QXBpID4+IENyZWF0aW5nIGNoYW5uZWwgZm9yICR7bmFtZX0uLi5gKTtcbiAgICBjb25zdCBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGF4aW9zXG4gICAgICAgIC5wb3N0KGxicnlBcGlVcmksIHtcbiAgICAgICAgICBtZXRob2Q6ICdjaGFubmVsX25ldycsXG4gICAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgICBjaGFubmVsX25hbWU6IG5hbWUsXG4gICAgICAgICAgICBhbW91bnQgICAgICA6IDAuMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgc2VuZEdBVGltaW5nRXZlbnQoJ2xicnluZXQnLCAnY3JlYXRlQ2hhbm5lbCcsICdDSEFOTkVMX05FVycsIGdhU3RhcnRUaW1lLCBEYXRlLm5vdygpKTtcbiAgICAgICAgICBoYW5kbGVMYnJ5bmV0UmVzcG9uc2UocmVzcG9uc2UsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvbGJyeUFwaS5qcyIsImNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5jb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5jb25zdCB7IHJldHVyblBhZ2luYXRlZENoYW5uZWxDbGFpbXMgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvY2hhbm5lbFBhZ2luYXRpb24uanMnKTtcblxuY29uc3QgTk9fQ0hBTk5FTCA9ICdOT19DSEFOTkVMJztcbmNvbnN0IE5PX0NMQUlNID0gJ05PX0NMQUlNJztcbmNvbnN0IE5PX0ZJTEUgPSAnTk9fRklMRSc7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBnZXRDbGFpbUlkIChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIG5hbWUsIGNsYWltSWQpIHtcbiAgICBpZiAoY2hhbm5lbE5hbWUpIHtcbiAgICAgIHJldHVybiBtb2R1bGUuZXhwb3J0cy5nZXRDbGFpbUlkQnlDaGFubmVsKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCwgbmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBtb2R1bGUuZXhwb3J0cy5nZXRDbGFpbUlkQnlDbGFpbShuYW1lLCBjbGFpbUlkKTtcbiAgICB9XG4gIH0sXG4gIGdldENsYWltSWRCeUNsYWltIChjbGFpbU5hbWUsIGNsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYGdldENsYWltSWRCeUNsYWltKCR7Y2xhaW1OYW1lfSwgJHtjbGFpbUlkfSlgKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZGIuQ2xhaW0uZ2V0TG9uZ0NsYWltSWQoY2xhaW1OYW1lLCBjbGFpbUlkKVxuICAgICAgICAudGhlbihsb25nQ2xhaW1JZCA9PiB7XG4gICAgICAgICAgaWYgKCFsb25nQ2xhaW1JZCkge1xuICAgICAgICAgICAgcmVzb2x2ZShOT19DTEFJTSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlc29sdmUobG9uZ0NsYWltSWQpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9LFxuICBnZXRDbGFpbUlkQnlDaGFubmVsIChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltTmFtZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgZ2V0Q2xhaW1JZEJ5Q2hhbm5lbCgke2NoYW5uZWxOYW1lfSwgJHtjaGFubmVsQ2xhaW1JZH0sICR7Y2xhaW1OYW1lfSlgKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZGIuQ2VydGlmaWNhdGUuZ2V0TG9uZ0NoYW5uZWxJZChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQpIC8vIDEuIGdldCB0aGUgbG9uZyBjaGFubmVsIGlkXG4gICAgICAgIC50aGVuKGxvbmdDaGFubmVsSWQgPT4ge1xuICAgICAgICAgIGlmICghbG9uZ0NoYW5uZWxJZCkge1xuICAgICAgICAgICAgcmV0dXJuIFtudWxsLCBudWxsXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtsb25nQ2hhbm5lbElkLCBkYi5DbGFpbS5nZXRDbGFpbUlkQnlMb25nQ2hhbm5lbElkKGxvbmdDaGFubmVsSWQsIGNsYWltTmFtZSldKTsgIC8vIDIuIGdldCB0aGUgbG9uZyBjbGFpbSBpZFxuICAgICAgICB9KVxuICAgICAgICAudGhlbigoW2xvbmdDaGFubmVsSWQsIGxvbmdDbGFpbUlkXSkgPT4ge1xuICAgICAgICAgIGlmICghbG9uZ0NoYW5uZWxJZCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoTk9fQ0hBTk5FTCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghbG9uZ0NsYWltSWQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKE5PX0NMQUlNKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzb2x2ZShsb25nQ2xhaW1JZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH0sXG4gIGdldENoYW5uZWxEYXRhIChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIHBhZ2UpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgLy8gMS4gZ2V0IHRoZSBsb25nIGNoYW5uZWwgSWQgKG1ha2Ugc3VyZSBjaGFubmVsIGV4aXN0cylcbiAgICAgIGRiLkNlcnRpZmljYXRlLmdldExvbmdDaGFubmVsSWQoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkKVxuICAgICAgICAudGhlbihsb25nQ2hhbm5lbENsYWltSWQgPT4ge1xuICAgICAgICAgIGlmICghbG9uZ0NoYW5uZWxDbGFpbUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gW251bGwsIG51bGwsIG51bGxdO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyAyLiBnZXQgdGhlIHNob3J0IElEIGFuZCBhbGwgY2xhaW1zIGZvciB0aGF0IGNoYW5uZWxcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW2xvbmdDaGFubmVsQ2xhaW1JZCwgZGIuQ2VydGlmaWNhdGUuZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZChsb25nQ2hhbm5lbENsYWltSWQsIGNoYW5uZWxOYW1lKV0pO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoW2xvbmdDaGFubmVsQ2xhaW1JZCwgc2hvcnRDaGFubmVsQ2xhaW1JZF0pID0+IHtcbiAgICAgICAgICBpZiAoIWxvbmdDaGFubmVsQ2xhaW1JZCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoTk9fQ0hBTk5FTCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIDMuIHJldHVybiBhbGwgdGhlIGNoYW5uZWwgaW5mb3JtYXRpb25cbiAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgIGNoYW5uZWxOYW1lLFxuICAgICAgICAgICAgbG9uZ0NoYW5uZWxDbGFpbUlkLFxuICAgICAgICAgICAgc2hvcnRDaGFubmVsQ2xhaW1JZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfSxcbiAgZ2V0Q2hhbm5lbENsYWltcyAoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkLCBwYWdlKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIDEuIGdldCB0aGUgbG9uZyBjaGFubmVsIElkIChtYWtlIHN1cmUgY2hhbm5lbCBleGlzdHMpXG4gICAgICBkYi5DZXJ0aWZpY2F0ZS5nZXRMb25nQ2hhbm5lbElkKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZClcbiAgICAgICAgLnRoZW4obG9uZ0NoYW5uZWxDbGFpbUlkID0+IHtcbiAgICAgICAgICBpZiAoIWxvbmdDaGFubmVsQ2xhaW1JZCkge1xuICAgICAgICAgICAgcmV0dXJuIFtudWxsLCBudWxsLCBudWxsXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gMi4gZ2V0IHRoZSBzaG9ydCBJRCBhbmQgYWxsIGNsYWltcyBmb3IgdGhhdCBjaGFubmVsXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtsb25nQ2hhbm5lbENsYWltSWQsIGRiLkNsYWltLmdldEFsbENoYW5uZWxDbGFpbXMobG9uZ0NoYW5uZWxDbGFpbUlkKV0pO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoW2xvbmdDaGFubmVsQ2xhaW1JZCwgY2hhbm5lbENsYWltc0FycmF5XSkgPT4ge1xuICAgICAgICAgIGlmICghbG9uZ0NoYW5uZWxDbGFpbUlkKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShOT19DSEFOTkVMKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gMy4gZm9ybWF0IHRoZSBkYXRhIGZvciB0aGUgdmlldywgaW5jbHVkaW5nIHBhZ2luYXRpb25cbiAgICAgICAgICBsZXQgcGFnaW5hdGVkQ2hhbm5lbFZpZXdEYXRhID0gcmV0dXJuUGFnaW5hdGVkQ2hhbm5lbENsYWltcyhjaGFubmVsTmFtZSwgbG9uZ0NoYW5uZWxDbGFpbUlkLCBjaGFubmVsQ2xhaW1zQXJyYXksIHBhZ2UpO1xuICAgICAgICAgIC8vIDQuIHJldHVybiBhbGwgdGhlIGNoYW5uZWwgaW5mb3JtYXRpb24gYW5kIGNvbnRlbnRzXG4gICAgICAgICAgcmVzb2x2ZShwYWdpbmF0ZWRDaGFubmVsVmlld0RhdGEpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9LFxuICBnZXRMb2NhbEZpbGVSZWNvcmQgKGNsYWltSWQsIG5hbWUpIHtcbiAgICByZXR1cm4gZGIuRmlsZS5maW5kT25lKHt3aGVyZToge2NsYWltSWQsIG5hbWV9fSlcbiAgICAgIC50aGVuKGZpbGUgPT4ge1xuICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICByZXR1cm4gTk9fRklMRTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmlsZS5kYXRhVmFsdWVzO1xuICAgICAgfSk7XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2NvbnRyb2xsZXJzL3NlcnZlQ29udHJvbGxlci5qcyIsImNvbnN0IHBhc3Nwb3J0ID0gcmVxdWlyZSgncGFzc3BvcnQnKTtcbmNvbnN0IGxvY2FsTG9naW5TdHJhdGVneSA9IHJlcXVpcmUoJy4vbG9jYWwtbG9naW4uanMnKTtcbmNvbnN0IGxvY2FsU2lnbnVwU3RyYXRlZ3kgPSByZXF1aXJlKCcuL2xvY2FsLXNpZ251cC5qcycpO1xuY29uc3QgeyBzZXJpYWxpemVTcGVlY2hVc2VyLCBkZXNlcmlhbGl6ZVNwZWVjaFVzZXIgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvYXV0aEhlbHBlcnMuanMnKTtcblxucGFzc3BvcnQuZGVzZXJpYWxpemVVc2VyKGRlc2VyaWFsaXplU3BlZWNoVXNlcik7XG5wYXNzcG9ydC5zZXJpYWxpemVVc2VyKHNlcmlhbGl6ZVNwZWVjaFVzZXIpO1xucGFzc3BvcnQudXNlKCdsb2NhbC1sb2dpbicsIGxvY2FsTG9naW5TdHJhdGVneSk7XG5wYXNzcG9ydC51c2UoJ2xvY2FsLXNpZ251cCcsIGxvY2FsU2lnbnVwU3RyYXRlZ3kpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHBhc3Nwb3J0O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3NwZWVjaFBhc3Nwb3J0L2luZGV4LmpzIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgZGIgPSByZXF1aXJlKCdtb2RlbHMnKTtcbmNvbnN0IGxicnlBcGkgPSByZXF1aXJlKCdoZWxwZXJzL2xicnlBcGkuanMnKTtcbmNvbnN0IHB1Ymxpc2hIZWxwZXJzID0gcmVxdWlyZSgnaGVscGVycy9wdWJsaXNoSGVscGVycy5qcycpO1xuY29uc3QgeyBwdWJsaXNoaW5nOiB7IHByaW1hcnlDbGFpbUFkZHJlc3MsIGFkZGl0aW9uYWxDbGFpbUFkZHJlc3NlcyB9IH0gPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5jb25zdCBTZXF1ZWxpemUgPSByZXF1aXJlKCdzZXF1ZWxpemUnKTtcbmNvbnN0IE9wID0gU2VxdWVsaXplLk9wO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgcHVibGlzaCAocHVibGlzaFBhcmFtcywgZmlsZU5hbWUsIGZpbGVUeXBlKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxldCBwdWJsaXNoUmVzdWx0cywgY2VydGlmaWNhdGVJZCwgY2hhbm5lbE5hbWU7XG4gICAgICAvLyBwdWJsaXNoIHRoZSBmaWxlXG4gICAgICByZXR1cm4gbGJyeUFwaS5wdWJsaXNoQ2xhaW0ocHVibGlzaFBhcmFtcylcbiAgICAgICAgLnRoZW4odHggPT4ge1xuICAgICAgICAgIGxvZ2dlci5pbmZvKGBTdWNjZXNzZnVsbHkgcHVibGlzaGVkICR7cHVibGlzaFBhcmFtcy5uYW1lfSAke2ZpbGVOYW1lfWAsIHR4KTtcbiAgICAgICAgICBwdWJsaXNoUmVzdWx0cyA9IHR4O1xuICAgICAgICAgIC8vIGdldCB0aGUgY2hhbm5lbCBpbmZvcm1hdGlvblxuICAgICAgICAgIGlmIChwdWJsaXNoUGFyYW1zLmNoYW5uZWxfbmFtZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGB0aGlzIGNsYWltIHdhcyBwdWJsaXNoZWQgaW4gY2hhbm5lbDogJHtwdWJsaXNoUGFyYW1zLmNoYW5uZWxfbmFtZX1gKTtcbiAgICAgICAgICAgIHJldHVybiBkYi5DaGFubmVsLmZpbmRPbmUoe1xuICAgICAgICAgICAgICB3aGVyZToge1xuICAgICAgICAgICAgICAgIGNoYW5uZWxOYW1lOiBwdWJsaXNoUGFyYW1zLmNoYW5uZWxfbmFtZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ3RoaXMgY2xhaW0gd2FzIG5vdCBwdWJsaXNoZWQgaW4gYSBjaGFubmVsJyk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKGNoYW5uZWwgPT4ge1xuICAgICAgICAvLyBzZXQgY2hhbm5lbCBpbmZvcm1hdGlvblxuICAgICAgICAgIGNlcnRpZmljYXRlSWQgPSBudWxsO1xuICAgICAgICAgIGNoYW5uZWxOYW1lID0gbnVsbDtcbiAgICAgICAgICBpZiAoY2hhbm5lbCkge1xuICAgICAgICAgICAgY2VydGlmaWNhdGVJZCA9IGNoYW5uZWwuY2hhbm5lbENsYWltSWQ7XG4gICAgICAgICAgICBjaGFubmVsTmFtZSA9IGNoYW5uZWwuY2hhbm5lbE5hbWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgY2VydGlmaWNhdGVJZDogJHtjZXJ0aWZpY2F0ZUlkfWApO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgRmlsZSByZWNvcmRcbiAgICAgICAgICBjb25zdCBmaWxlUmVjb3JkID0ge1xuICAgICAgICAgICAgbmFtZSAgICAgICA6IHB1Ymxpc2hQYXJhbXMubmFtZSxcbiAgICAgICAgICAgIGNsYWltSWQgICAgOiBwdWJsaXNoUmVzdWx0cy5jbGFpbV9pZCxcbiAgICAgICAgICAgIHRpdGxlICAgICAgOiBwdWJsaXNoUGFyYW1zLm1ldGFkYXRhLnRpdGxlLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHB1Ymxpc2hQYXJhbXMubWV0YWRhdGEuZGVzY3JpcHRpb24sXG4gICAgICAgICAgICBhZGRyZXNzICAgIDogcHVibGlzaFBhcmFtcy5jbGFpbV9hZGRyZXNzLFxuICAgICAgICAgICAgb3V0cG9pbnQgICA6IGAke3B1Ymxpc2hSZXN1bHRzLnR4aWR9OiR7cHVibGlzaFJlc3VsdHMubm91dH1gLFxuICAgICAgICAgICAgaGVpZ2h0ICAgICA6IDAsXG4gICAgICAgICAgICBmaWxlTmFtZSxcbiAgICAgICAgICAgIGZpbGVQYXRoICAgOiBwdWJsaXNoUGFyYW1zLmZpbGVfcGF0aCxcbiAgICAgICAgICAgIGZpbGVUeXBlLFxuICAgICAgICAgICAgbnNmdyAgICAgICA6IHB1Ymxpc2hQYXJhbXMubWV0YWRhdGEubnNmdyxcbiAgICAgICAgICB9O1xuICAgICAgICAgIC8vIGNyZWF0ZSB0aGUgQ2xhaW0gcmVjb3JkXG4gICAgICAgICAgY29uc3QgY2xhaW1SZWNvcmQgPSB7XG4gICAgICAgICAgICBuYW1lICAgICAgIDogcHVibGlzaFBhcmFtcy5uYW1lLFxuICAgICAgICAgICAgY2xhaW1JZCAgICA6IHB1Ymxpc2hSZXN1bHRzLmNsYWltX2lkLFxuICAgICAgICAgICAgdGl0bGUgICAgICA6IHB1Ymxpc2hQYXJhbXMubWV0YWRhdGEudGl0bGUsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogcHVibGlzaFBhcmFtcy5tZXRhZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGFkZHJlc3MgICAgOiBwdWJsaXNoUGFyYW1zLmNsYWltX2FkZHJlc3MsXG4gICAgICAgICAgICB0aHVtYm5haWwgIDogcHVibGlzaFBhcmFtcy5tZXRhZGF0YS50aHVtYm5haWwsXG4gICAgICAgICAgICBvdXRwb2ludCAgIDogYCR7cHVibGlzaFJlc3VsdHMudHhpZH06JHtwdWJsaXNoUmVzdWx0cy5ub3V0fWAsXG4gICAgICAgICAgICBoZWlnaHQgICAgIDogMCxcbiAgICAgICAgICAgIGNvbnRlbnRUeXBlOiBmaWxlVHlwZSxcbiAgICAgICAgICAgIG5zZncgICAgICAgOiBwdWJsaXNoUGFyYW1zLm1ldGFkYXRhLm5zZncsXG4gICAgICAgICAgICBhbW91bnQgICAgIDogcHVibGlzaFBhcmFtcy5iaWQsXG4gICAgICAgICAgICBjZXJ0aWZpY2F0ZUlkLFxuICAgICAgICAgICAgY2hhbm5lbE5hbWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgICAvLyB1cHNlcnQgY3JpdGVyaWFcbiAgICAgICAgICBjb25zdCB1cHNlcnRDcml0ZXJpYSA9IHtcbiAgICAgICAgICAgIG5hbWUgICA6IHB1Ymxpc2hQYXJhbXMubmFtZSxcbiAgICAgICAgICAgIGNsYWltSWQ6IHB1Ymxpc2hSZXN1bHRzLmNsYWltX2lkLFxuICAgICAgICAgIH07XG4gICAgICAgICAgLy8gdXBzZXJ0IHRoZSByZWNvcmRzXG4gICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtkYi51cHNlcnQoZGIuRmlsZSwgZmlsZVJlY29yZCwgdXBzZXJ0Q3JpdGVyaWEsICdGaWxlJyksIGRiLnVwc2VydChkYi5DbGFpbSwgY2xhaW1SZWNvcmQsIHVwc2VydENyaXRlcmlhLCAnQ2xhaW0nKV0pO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoW2ZpbGUsIGNsYWltXSkgPT4ge1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnRmlsZSBhbmQgQ2xhaW0gcmVjb3JkcyBzdWNjZXNzZnVsbHkgY3JlYXRlZCcpO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbZmlsZS5zZXRDbGFpbShjbGFpbSksIGNsYWltLnNldEZpbGUoZmlsZSldKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnRmlsZSBhbmQgQ2xhaW0gcmVjb3JkcyBzdWNjZXNzZnVsbHkgYXNzb2NpYXRlZCcpO1xuICAgICAgICAgIHJlc29sdmUocHVibGlzaFJlc3VsdHMpOyAvLyByZXNvbHZlIHRoZSBwcm9taXNlIHdpdGggdGhlIHJlc3VsdCBmcm9tIGxicnlBcGkucHVibGlzaENsYWltO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcignUFVCTElTSCBFUlJPUicsIGVycm9yKTtcbiAgICAgICAgICBwdWJsaXNoSGVscGVycy5kZWxldGVUZW1wb3JhcnlGaWxlKHB1Ymxpc2hQYXJhbXMuZmlsZV9wYXRoKTsgLy8gZGVsZXRlIHRoZSBsb2NhbCBmaWxlXG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH0sXG4gIGNsYWltTmFtZUlzQXZhaWxhYmxlIChuYW1lKSB7XG4gICAgY29uc3QgY2xhaW1BZGRyZXNzZXMgPSBhZGRpdGlvbmFsQ2xhaW1BZGRyZXNzZXMgfHwgW107XG4gICAgY2xhaW1BZGRyZXNzZXMucHVzaChwcmltYXJ5Q2xhaW1BZGRyZXNzKTtcbiAgICAvLyBmaW5kIGFueSByZWNvcmRzIHdoZXJlIHRoZSBuYW1lIGlzIHVzZWRcbiAgICByZXR1cm4gZGIuQ2xhaW1cbiAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgYXR0cmlidXRlczogWydhZGRyZXNzJ10sXG4gICAgICAgIHdoZXJlICAgICA6IHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGFkZHJlc3M6IHtcbiAgICAgICAgICAgIFtPcC5vcl06IGNsYWltQWRkcmVzc2VzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdC5sZW5ndGggPj0gMSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhhdCBjbGFpbSBpcyBhbHJlYWR5IGluIHVzZScpO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuICB9LFxuICBjaGVja0NoYW5uZWxBdmFpbGFiaWxpdHkgKG5hbWUpIHtcbiAgICByZXR1cm4gZGIuQ2hhbm5lbFxuICAgICAgLmZpbmRBbGwoe1xuICAgICAgICB3aGVyZTogeyBjaGFubmVsTmFtZTogbmFtZSB9LFxuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID49IDEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoYXQgY2hhbm5lbCBoYXMgYWxyZWFkeSBiZWVuIGNsYWltZWQnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgIH0pO1xuICB9LFxufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9jb250cm9sbGVycy9wdWJsaXNoQ29udHJvbGxlci5qcyIsImNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcbmNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKTtcblxuY29uc3QgeyBkZXRhaWxzLCBwdWJsaXNoaW5nIH0gPSByZXF1aXJlKCcuLi8uLi9jb25maWcvc2l0ZUNvbmZpZy5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgcGFyc2VQdWJsaXNoQXBpUmVxdWVzdEJvZHkgKHtuYW1lLCBuc2Z3LCBsaWNlbnNlLCB0aXRsZSwgZGVzY3JpcHRpb24sIHRodW1ibmFpbH0pIHtcbiAgICAvLyB2YWxpZGF0ZSBuYW1lXG4gICAgaWYgKCFuYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIG5hbWUgZmllbGQgZm91bmQgaW4gcmVxdWVzdCcpO1xuICAgIH1cbiAgICBjb25zdCBpbnZhbGlkTmFtZUNoYXJhY3RlcnMgPSAvW15BLVphLXowLTksLV0vLmV4ZWMobmFtZSk7XG4gICAgaWYgKGludmFsaWROYW1lQ2hhcmFjdGVycykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgY2xhaW0gbmFtZSB5b3UgcHJvdmlkZWQgaXMgbm90IGFsbG93ZWQuICBPbmx5IHRoZSBmb2xsb3dpbmcgY2hhcmFjdGVycyBhcmUgYWxsb3dlZDogQS1aLCBhLXosIDAtOSwgYW5kIFwiLVwiJyk7XG4gICAgfVxuICAgIC8vIG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAgICBuc2Z3ID0gKG5zZncgPT09ICd0cnVlJyk7XG4gICAgbGljZW5zZSA9IGxpY2Vuc2UgfHwgbnVsbDtcbiAgICB0aXRsZSA9IHRpdGxlIHx8IG51bGw7XG4gICAgZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbiB8fCBudWxsO1xuICAgIHRodW1ibmFpbCA9IHRodW1ibmFpbCB8fCBudWxsO1xuICAgIC8vIHJldHVybiByZXN1bHRzXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWUsXG4gICAgICBuc2Z3LFxuICAgICAgbGljZW5zZSxcbiAgICAgIHRpdGxlLFxuICAgICAgZGVzY3JpcHRpb24sXG4gICAgICB0aHVtYm5haWwsXG4gICAgfTtcbiAgfSxcbiAgcGFyc2VQdWJsaXNoQXBpUmVxdWVzdEZpbGVzICh7ZmlsZSwgdGh1bWJuYWlsfSkge1xuICAgIC8vIG1ha2Ugc3VyZSBhIGZpbGUgd2FzIHByb3ZpZGVkXG4gICAgaWYgKCFmaWxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIGZpbGUgd2l0aCBrZXkgb2YgW2ZpbGVdIGZvdW5kIGluIHJlcXVlc3QnKTtcbiAgICB9XG4gICAgaWYgKCFmaWxlLnBhdGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbm8gZmlsZSBwYXRoIGZvdW5kJyk7XG4gICAgfVxuICAgIGlmICghZmlsZS50eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIGZpbGUgdHlwZSBmb3VuZCcpO1xuICAgIH1cbiAgICBpZiAoIWZpbGUuc2l6ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBmaWxlIHR5cGUgZm91bmQnKTtcbiAgICB9XG4gICAgLy8gdmFsaWRhdGUgdGhlIGZpbGUgbmFtZVxuICAgIGlmICgvJy8udGVzdChmaWxlLm5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Fwb3N0cm9waGVzIGFyZSBub3QgYWxsb3dlZCBpbiB0aGUgZmlsZSBuYW1lJyk7XG4gICAgfVxuICAgIC8vIHZhbGlkYXRlIHRoZSBmaWxlXG4gICAgbW9kdWxlLmV4cG9ydHMudmFsaWRhdGVGaWxlVHlwZUFuZFNpemUoZmlsZSk7XG4gICAgLy8gcmV0dXJuIHJlc3VsdHNcbiAgICByZXR1cm4ge1xuICAgICAgZmlsZU5hbWUgICAgICAgICA6IGZpbGUubmFtZSxcbiAgICAgIGZpbGVQYXRoICAgICAgICAgOiBmaWxlLnBhdGgsXG4gICAgICBmaWxlVHlwZSAgICAgICAgIDogZmlsZS50eXBlLFxuICAgICAgdGh1bWJuYWlsRmlsZU5hbWU6ICh0aHVtYm5haWwgPyB0aHVtYm5haWwubmFtZSA6IG51bGwpLFxuICAgICAgdGh1bWJuYWlsRmlsZVBhdGg6ICh0aHVtYm5haWwgPyB0aHVtYm5haWwucGF0aCA6IG51bGwpLFxuICAgICAgdGh1bWJuYWlsRmlsZVR5cGU6ICh0aHVtYm5haWwgPyB0aHVtYm5haWwudHlwZSA6IG51bGwpLFxuICAgIH07XG4gIH0sXG4gIHZhbGlkYXRlRmlsZVR5cGVBbmRTaXplIChmaWxlKSB7XG4gICAgLy8gY2hlY2sgZmlsZSB0eXBlIGFuZCBzaXplXG4gICAgc3dpdGNoIChmaWxlLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2ltYWdlL2pwZWcnOlxuICAgICAgY2FzZSAnaW1hZ2UvanBnJzpcbiAgICAgIGNhc2UgJ2ltYWdlL3BuZyc6XG4gICAgICAgIGlmIChmaWxlLnNpemUgPiAxMDAwMDAwMCkge1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZygncHVibGlzaCA+IGZpbGUgdmFsaWRhdGlvbiA+IC5qcGVnLy5qcGcvLnBuZyB3YXMgdG9vIGJpZycpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU29ycnksIGltYWdlcyBhcmUgbGltaXRlZCB0byAxMCBtZWdhYnl0ZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbWFnZS9naWYnOlxuICAgICAgICBpZiAoZmlsZS5zaXplID4gNTAwMDAwMDApIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoJ3B1Ymxpc2ggPiBmaWxlIHZhbGlkYXRpb24gPiAuZ2lmIHdhcyB0b28gYmlnJyk7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTb3JyeSwgLmdpZnMgYXJlIGxpbWl0ZWQgdG8gNTAgbWVnYWJ5dGVzLicpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndmlkZW8vbXA0JzpcbiAgICAgICAgaWYgKGZpbGUuc2l6ZSA+IDUwMDAwMDAwKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKCdwdWJsaXNoID4gZmlsZSB2YWxpZGF0aW9uID4gLm1wNCB3YXMgdG9vIGJpZycpO1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU29ycnksIHZpZGVvcyBhcmUgbGltaXRlZCB0byA1MCBtZWdhYnl0ZXMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBsb2dnZXIuZGVidWcoJ3B1Ymxpc2ggPiBmaWxlIHZhbGlkYXRpb24gPiB1bnJlY29nbml6ZWQgZmlsZSB0eXBlJyk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlICcgKyBmaWxlLnR5cGUgKyAnIGNvbnRlbnQgdHlwZSBpcyBub3Qgc3VwcG9ydGVkLiAgT25seSwgLmpwZWcsIC5wbmcsIC5naWYsIGFuZCAubXA0IGZpbGVzIGFyZSBjdXJyZW50bHkgc3VwcG9ydGVkLicpO1xuICAgIH1cbiAgICByZXR1cm4gZmlsZTtcbiAgfSxcbiAgY3JlYXRlQmFzaWNQdWJsaXNoUGFyYW1zIChmaWxlUGF0aCwgbmFtZSwgdGl0bGUsIGRlc2NyaXB0aW9uLCBsaWNlbnNlLCBuc2Z3LCB0aHVtYm5haWwpIHtcbiAgICBsb2dnZXIuZGVidWcoYENyZWF0aW5nIFB1Ymxpc2ggUGFyYW1ldGVyc2ApO1xuICAgIC8vIHByb3ZpZGUgZGVmYXVsdHMgZm9yIHRpdGxlXG4gICAgaWYgKHRpdGxlID09PSBudWxsIHx8IHRpdGxlLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgIHRpdGxlID0gbmFtZTtcbiAgICB9XG4gICAgLy8gcHJvdmlkZSBkZWZhdWx0IGZvciBkZXNjcmlwdGlvblxuICAgIGlmIChkZXNjcmlwdGlvbiA9PT0gbnVsbCB8fCBkZXNjcmlwdGlvbi50cmltKCkgPT09ICcnKSB7XG4gICAgICBkZXNjcmlwdGlvbiA9ICcnO1xuICAgIH1cbiAgICAvLyBwcm92aWRlIGRlZmF1bHQgZm9yIGxpY2Vuc2VcbiAgICBpZiAobGljZW5zZSA9PT0gbnVsbCB8fCBsaWNlbnNlLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgIGxpY2Vuc2UgPSAnICc7ICAvLyBkZWZhdWx0IHRvIGVtcHR5IHN0cmluZ1xuICAgIH1cbiAgICAvLyBjcmVhdGUgdGhlIHB1Ymxpc2ggcGFyYW1zXG4gICAgY29uc3QgcHVibGlzaFBhcmFtcyA9IHtcbiAgICAgIG5hbWUsXG4gICAgICBmaWxlX3BhdGg6IGZpbGVQYXRoLFxuICAgICAgYmlkICAgICAgOiAwLjAxLFxuICAgICAgbWV0YWRhdGEgOiB7XG4gICAgICAgIGRlc2NyaXB0aW9uLFxuICAgICAgICB0aXRsZSxcbiAgICAgICAgYXV0aG9yICA6IGRldGFpbHMudGl0bGUsXG4gICAgICAgIGxhbmd1YWdlOiAnZW4nLFxuICAgICAgICBsaWNlbnNlLFxuICAgICAgICBuc2Z3LFxuICAgICAgfSxcbiAgICAgIGNsYWltX2FkZHJlc3M6IHB1Ymxpc2hpbmcucHJpbWFyeUNsYWltQWRkcmVzcyxcbiAgICB9O1xuICAgIC8vIGFkZCB0aHVtYm5haWwgdG8gY2hhbm5lbCBpZiB2aWRlb1xuICAgIGlmICh0aHVtYm5haWwpIHtcbiAgICAgIHB1Ymxpc2hQYXJhbXNbJ21ldGFkYXRhJ11bJ3RodW1ibmFpbCddID0gdGh1bWJuYWlsO1xuICAgIH1cbiAgICByZXR1cm4gcHVibGlzaFBhcmFtcztcbiAgfSxcbiAgY3JlYXRlVGh1bWJuYWlsUHVibGlzaFBhcmFtcyAodGh1bWJuYWlsRmlsZVBhdGgsIGNsYWltTmFtZSwgbGljZW5zZSwgbnNmdykge1xuICAgIGlmICghdGh1bWJuYWlsRmlsZVBhdGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbG9nZ2VyLmRlYnVnKGBDcmVhdGluZyBUaHVtYm5haWwgUHVibGlzaCBQYXJhbWV0ZXJzYCk7XG4gICAgLy8gY3JlYXRlIHRoZSBwdWJsaXNoIHBhcmFtc1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lICAgICA6IGAke2NsYWltTmFtZX0tdGh1bWJgLFxuICAgICAgZmlsZV9wYXRoOiB0aHVtYm5haWxGaWxlUGF0aCxcbiAgICAgIGJpZCAgICAgIDogMC4wMSxcbiAgICAgIG1ldGFkYXRhIDoge1xuICAgICAgICB0aXRsZSAgICAgIDogYCR7Y2xhaW1OYW1lfSB0aHVtYm5haWxgLFxuICAgICAgICBkZXNjcmlwdGlvbjogYGEgdGh1bWJuYWlsIGZvciAke2NsYWltTmFtZX1gLFxuICAgICAgICBhdXRob3IgICAgIDogZGV0YWlscy50aXRsZSxcbiAgICAgICAgbGFuZ3VhZ2UgICA6ICdlbicsXG4gICAgICAgIGxpY2Vuc2UsXG4gICAgICAgIG5zZncsXG4gICAgICB9LFxuICAgICAgY2xhaW1fYWRkcmVzczogcHVibGlzaGluZy5wcmltYXJ5Q2xhaW1BZGRyZXNzLFxuICAgICAgY2hhbm5lbF9uYW1lIDogcHVibGlzaGluZy50aHVtYm5haWxDaGFubmVsLFxuICAgICAgY2hhbm5lbF9pZCAgIDogcHVibGlzaGluZy50aHVtYm5haWxDaGFubmVsSWQsXG4gICAgfTtcbiAgfSxcbiAgZGVsZXRlVGVtcG9yYXJ5RmlsZSAoZmlsZVBhdGgpIHtcbiAgICBmcy51bmxpbmsoZmlsZVBhdGgsIGVyciA9PiB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgZXJyb3IgZGVsZXRpbmcgdGVtcG9yYXJ5IGZpbGUgJHtmaWxlUGF0aH1gKTtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgICAgbG9nZ2VyLmRlYnVnKGBzdWNjZXNzZnVsbHkgZGVsZXRlZCAke2ZpbGVQYXRofWApO1xuICAgIH0pO1xuICB9LFxuICBhZGRHZXRSZXN1bHRzVG9GaWxlRGF0YSAoZmlsZUluZm8sIGdldFJlc3VsdCkge1xuICAgIGZpbGVJbmZvLmZpbGVOYW1lID0gZ2V0UmVzdWx0LmZpbGVfbmFtZTtcbiAgICBmaWxlSW5mby5maWxlUGF0aCA9IGdldFJlc3VsdC5kb3dubG9hZF9wYXRoO1xuICAgIHJldHVybiBmaWxlSW5mbztcbiAgfSxcbiAgY3JlYXRlRmlsZURhdGEgKHsgbmFtZSwgY2xhaW1JZCwgb3V0cG9pbnQsIGhlaWdodCwgYWRkcmVzcywgbnNmdywgY29udGVudFR5cGUgfSkge1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lLFxuICAgICAgY2xhaW1JZCxcbiAgICAgIG91dHBvaW50LFxuICAgICAgaGVpZ2h0LFxuICAgICAgYWRkcmVzcyxcbiAgICAgIGZpbGVOYW1lOiAnJyxcbiAgICAgIGZpbGVQYXRoOiAnJyxcbiAgICAgIGZpbGVUeXBlOiBjb250ZW50VHlwZSxcbiAgICAgIG5zZncsXG4gICAgfTtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9wdWJsaXNoSGVscGVycy5qcyIsImNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcblxuZnVuY3Rpb24gbXlzcWwgKCkge1xuICB0aGlzLmRhdGFiYXNlID0gJ2RlZmF1bHQnO1xuICB0aGlzLnVzZXJuYW1lID0gJ2RlZmF1bHQnO1xuICB0aGlzLnBhc3N3b3JkID0gJ2RlZmF1bHQnO1xuICB0aGlzLnVwZGF0ZSA9IChjb25maWcpID0+IHtcbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgcmV0dXJuIGxvZ2dlci53YXJuKCdObyBNeVNRTCBjb25maWcgcmVjZWl2ZWQuJyk7XG4gICAgfVxuICAgIC8vIGNvbmZpZ3VyZSBjcmVkZW50aWFsc1xuICAgIGxvZ2dlci5pbmZvKCdjb25maWd1cmluZyBteXNxbC4uLicpO1xuICAgIGNvbnN0IHsgZGF0YWJhc2UsIHVzZXJuYW1lLCBwYXNzd29yZCB9ID0gY29uZmlnO1xuICAgIHRoaXMuZGF0YWJhc2UgPSBkYXRhYmFzZTtcbiAgICB0aGlzLnVzZXJuYW1lID0gdXNlcm5hbWU7XG4gICAgdGhpcy5wYXNzd29yZCA9IHBhc3N3b3JkO1xuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgbXlzcWwoKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL2NvbmZpZy9teXNxbENvbmZpZy5qcyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInBhc3Nwb3J0LWxvY2FsXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicGFzc3BvcnQtbG9jYWxcIlxuLy8gbW9kdWxlIGlkID0gMTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIHJldHVyblNob3J0SWQ6IGZ1bmN0aW9uIChjbGFpbXNBcnJheSwgbG9uZ0lkKSB7XG4gICAgbGV0IGNsYWltSW5kZXg7XG4gICAgbGV0IHNob3J0SWQgPSBsb25nSWQuc3Vic3RyaW5nKDAsIDEpOyAvLyBkZWZhdWx0IHNob3J0IGlkIGlzIHRoZSBmaXJzdCBsZXR0ZXJcbiAgICBsZXQgc2hvcnRJZExlbmd0aCA9IDA7XG4gICAgLy8gZmluZCB0aGUgaW5kZXggb2YgdGhpcyBjbGFpbSBpZFxuICAgIGNsYWltSW5kZXggPSBjbGFpbXNBcnJheS5maW5kSW5kZXgoZWxlbWVudCA9PiB7XG4gICAgICByZXR1cm4gZWxlbWVudC5jbGFpbUlkID09PSBsb25nSWQ7XG4gICAgfSk7XG4gICAgaWYgKGNsYWltSW5kZXggPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsYWltIGlkIG5vdCBmb3VuZCBpbiBjbGFpbXMgbGlzdCcpO1xuICAgIH1cbiAgICAvLyBnZXQgYW4gYXJyYXkgb2YgYWxsIGNsYWltcyB3aXRoIGxvd2VyIGhlaWdodFxuICAgIGxldCBwb3NzaWJsZU1hdGNoZXMgPSBjbGFpbXNBcnJheS5zbGljZSgwLCBjbGFpbUluZGV4KTtcbiAgICAvLyByZW1vdmUgY2VydGlmaWNhdGVzIHdpdGggdGhlIHNhbWUgcHJlZml4ZXMgdW50aWwgbm9uZSBhcmUgbGVmdC5cbiAgICB3aGlsZSAocG9zc2libGVNYXRjaGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHNob3J0SWRMZW5ndGggKz0gMTtcbiAgICAgIHNob3J0SWQgPSBsb25nSWQuc3Vic3RyaW5nKDAsIHNob3J0SWRMZW5ndGgpO1xuICAgICAgcG9zc2libGVNYXRjaGVzID0gcG9zc2libGVNYXRjaGVzLmZpbHRlcihlbGVtZW50ID0+IHtcbiAgICAgICAgcmV0dXJuIChlbGVtZW50LmNsYWltSWQgJiYgKGVsZW1lbnQuY2xhaW1JZC5zdWJzdHJpbmcoMCwgc2hvcnRJZExlbmd0aCkgPT09IHNob3J0SWQpKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gc2hvcnRJZDtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9zZXF1ZWxpemVIZWxwZXJzLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwic2VxdWVsaXplXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwic2VxdWVsaXplXCJcbi8vIG1vZHVsZSBpZCA9IDEzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyByZW5kZXJUb1N0cmluZyB9IGZyb20gJ3JlYWN0LWRvbS9zZXJ2ZXInO1xuaW1wb3J0IHsgY3JlYXRlU3RvcmUgfSBmcm9tICdyZWR1eCc7XG5pbXBvcnQgeyBQcm92aWRlciB9IGZyb20gJ3JlYWN0LXJlZHV4JztcbmltcG9ydCB7IFN0YXRpY1JvdXRlciB9IGZyb20gJ3JlYWN0LXJvdXRlci1kb20nO1xuaW1wb3J0IHsgUmVkdWNlcnMsIEdBTGlzdGVuZXIsIEFwcCB9IGZyb20gJ3NwZWUuY2gtY29tcG9uZW50cyc7XG4vKlxuICBeIG5vdGU6IHRvIGRvIHRoaXMgcmlnaHQsIG1heWJlXG4gIHRoZXNlIHNob3VsZCBiZSBwYXNzZWQgaW4gZnJvbSB0aGUgaW1wbGVtZW50YXRpb24gKHd3dy5zcGVlLmNoKSBpdHNlbGYsXG4gIHNvIHRoYXQgdGhlcmUgYXJlIG5vIGNvbmZsaWN0cyBiZXR3ZWVuIHRoZSBTU1IgaGVyZSBhbmRcbiAgdGhlIGJ1bmRsZSBzZW50IHRvIHRoZSBzZXJ2ZXI/XG4gIHRoZXJlIG1pZ2h0IGFsc28gYmUgaXNzdWVzIGlmIHRoaXMgcGFja2FnZSB1c2VzIGEgZGlmZmVyZW50IHZlcnNpb24gb2Ygc3BlZS5jaC1jb21wb25lbnRzIHRoYW4gd3d3LnNwZWUuY2ggZG9lcz9cbiovXG5pbXBvcnQgcmVuZGVyRnVsbFBhZ2UgZnJvbSAnLi9yZW5kZXJGdWxsUGFnZS5qcyc7XG5pbXBvcnQgSGVsbWV0IGZyb20gJ3JlYWN0LWhlbG1ldCc7XG5cbmNvbnN0IHNpdGVDb25maWcgPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKHJlcSwgcmVzKSA9PiB7XG4gIGxldCBjb250ZXh0ID0ge307XG5cbiAgLy8gY3VzdG9taXplIHRoZSByZWR1Y2VyIGJ5IHBhc3NpbmcgaW4gaW50aWFsIHN0YXRlIGNvbmZpZ3NcbiAgY29uc3QgTXlSZWR1Y2VycyA9IFJlZHVjZXJzKHNpdGVDb25maWcpO1xuICBjb25zdCBNeUFwcCA9IEFwcChzaXRlQ29uZmlnKTtcbiAgY29uc3QgTXlHQUxpc3RlbmVyID0gR0FMaXN0ZW5lcihzaXRlQ29uZmlnKTtcblxuICAvLyBjcmVhdGUgYSBuZXcgUmVkdXggc3RvcmUgaW5zdGFuY2VcbiAgY29uc3Qgc3RvcmUgPSBjcmVhdGVTdG9yZShNeVJlZHVjZXJzKTtcblxuICAvLyByZW5kZXIgY29tcG9uZW50IHRvIGEgc3RyaW5nXG4gIGNvbnN0IGh0bWwgPSByZW5kZXJUb1N0cmluZyhcbiAgICA8UHJvdmlkZXIgc3RvcmU9e3N0b3JlfT5cbiAgICAgIDxTdGF0aWNSb3V0ZXIgbG9jYXRpb249e3JlcS51cmx9IGNvbnRleHQ9e2NvbnRleHR9PlxuICAgICAgICA8TXlHQUxpc3RlbmVyPlxuICAgICAgICAgIDxNeUFwcCAvPlxuICAgICAgICA8L015R0FMaXN0ZW5lcj5cbiAgICAgIDwvU3RhdGljUm91dGVyPlxuICAgIDwvUHJvdmlkZXI+XG4gICk7XG5cbiAgLy8gZ2V0IGhlYWQgdGFncyBmcm9tIGhlbG1ldFxuICBjb25zdCBoZWxtZXQgPSBIZWxtZXQucmVuZGVyU3RhdGljKCk7XG5cbiAgLy8gY2hlY2sgZm9yIGEgcmVkaXJlY3RcbiAgaWYgKGNvbnRleHQudXJsKSB7XG4gICAgLy8gU29tZXdoZXJlIGEgYDxSZWRpcmVjdD5gIHdhcyByZW5kZXJlZFxuICAgIHJldHVybiByZXMucmVkaXJlY3QoMzAxLCBjb250ZXh0LnVybCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gd2UncmUgZ29vZCwgc2VuZCB0aGUgcmVzcG9uc2VcbiAgfVxuXG4gIC8vIGdldCB0aGUgaW5pdGlhbCBzdGF0ZSBmcm9tIG91ciBSZWR1eCBzdG9yZVxuICBjb25zdCBwcmVsb2FkZWRTdGF0ZSA9IHN0b3JlLmdldFN0YXRlKCk7XG5cbiAgLy8gc2VuZCB0aGUgcmVuZGVyZWQgcGFnZSBiYWNrIHRvIHRoZSBjbGllbnRcbiAgcmVzLnNlbmQocmVuZGVyRnVsbFBhZ2UoaGVsbWV0LCBodG1sLCBwcmVsb2FkZWRTdGF0ZSkpO1xuXG4gIGNvbnNvbGUubG9nKCdoZWxsbyBmcm9tIHNwZWUuY2ggaGFuZGxlUGFnZVJlbmRlci5qc3gnKTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9oYW5kbGVQYWdlUmVuZGVyLmpzeCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlYWN0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicmVhY3RcIlxuLy8gbW9kdWxlIGlkID0gMTVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicmVhY3QtZG9tL3NlcnZlclwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInJlYWN0LWRvbS9zZXJ2ZXJcIlxuLy8gbW9kdWxlIGlkID0gMTZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicmVkdXhcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJyZWR1eFwiXG4vLyBtb2R1bGUgaWQgPSAxN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWFjdC1yZWR1eFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInJlYWN0LXJlZHV4XCJcbi8vIG1vZHVsZSBpZCA9IDE4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlYWN0LXJvdXRlci1kb21cIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJyZWFjdC1yb3V0ZXItZG9tXCJcbi8vIG1vZHVsZSBpZCA9IDE5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInNwZWUuY2gtY29tcG9uZW50c1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInNwZWUuY2gtY29tcG9uZW50c1wiXG4vLyBtb2R1bGUgaWQgPSAyMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IChoZWxtZXQsIGh0bWwsIHByZWxvYWRlZFN0YXRlKSA9PiB7XG4gIC8vIHRha2UgdGhlIGh0bWwgYW5kIHByZWxvYWRlZFN0YXRlIGFuZCByZXR1cm4gdGhlIGZ1bGwgcGFnZVxuICByZXR1cm4gYFxuICAgIDwhRE9DVFlQRSBodG1sPlxuICAgIDxodG1sIGxhbmc9XCJlblwiIHByZWZpeD1cIm9nOiBodHRwOi8vb2dwLm1lL25zIyBmYjogaHR0cDovL29ncC5tZS9ucy9mYiNcIj5cbiAgICAgICAgPGhlYWQ+XG4gICAgICAgICAgICA8bWV0YSBjaGFyc2V0PVwiVVRGLThcIj5cbiAgICAgICAgICAgIDxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEsIHVzZXItc2NhbGFibGU9bm9cIj5cbiAgICAgICAgICAgIDxtZXRhIGh0dHAtZXF1aXY9XCJYLVVBLUNvbXBhdGlibGVcIiBjb250ZW50PVwiaWU9ZWRnZVwiPlxuICAgICAgICAgICAgPCEtLWhlbG1ldC0tPlxuICAgICAgICAgICAgJHtoZWxtZXQudGl0bGUudG9TdHJpbmcoKX1cbiAgICAgICAgICAgICR7aGVsbWV0Lm1ldGEudG9TdHJpbmcoKX1cbiAgICAgICAgICAgICR7aGVsbWV0LmxpbmsudG9TdHJpbmcoKX1cbiAgICAgICAgICAgIDwhLS1zdHlsZSBzaGVldHMtLT5cbiAgICAgICAgICAgIDxsaW5rIHJlbD1cInN0eWxlc2hlZXRcIiBocmVmPVwiL2Fzc2V0cy9jc3MvcmVzZXQuY3NzXCIgdHlwZT1cInRleHQvY3NzXCI+XG4gICAgICAgICAgICA8bGluayByZWw9XCJzdHlsZXNoZWV0XCIgaHJlZj1cIi9hc3NldHMvY3NzL2dlbmVyYWwuY3NzXCIgdHlwZT1cInRleHQvY3NzXCI+XG4gICAgICAgICAgICA8bGluayByZWw9XCJzdHlsZXNoZWV0XCIgaHJlZj1cIi9hc3NldHMvY3NzL21lZGlhUXVlcmllcy5jc3NcIiB0eXBlPVwidGV4dC9jc3NcIj5cbiAgICAgICAgICAgIDwhLS1nb29nbGUgZm9udC0tPlxuICAgICAgICAgICAgPGxpbmsgaHJlZj1cImh0dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT1Sb2JvdG86MzAwXCIgcmVsPVwic3R5bGVzaGVldFwiPlxuICAgICAgICA8L2hlYWQ+XG4gICAgICAgIDxib2R5IGlkPVwibWFpbi1ib2R5XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93IHJvdy0tdGFsbCBmbGV4LWNvbnRhaW5lci0tY29sdW1uXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBpZD1cInJlYWN0LWFwcFwiIGNsYXNzPVwicm93IHJvdy0tdGFsbCBmbGV4LWNvbnRhaW5lci0tY29sdW1uXCI+JHtodG1sfTwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8c2NyaXB0PlxuICAgICAgICAgICAgICAgIHdpbmRvdy5fX1BSRUxPQURFRF9TVEFURV9fID0gJHtKU09OLnN0cmluZ2lmeShwcmVsb2FkZWRTdGF0ZSkucmVwbGFjZSgvPC9nLCAnXFxcXFxcdTAwM2MnKX1cbiAgICAgICAgICAgIDwvc2NyaXB0PlxuICAgICAgICAgICAgPHNjcmlwdCBzcmM9XCIvYnVuZGxlL2J1bmRsZS5qc1wiPjwvc2NyaXB0PlxuICAgICAgICA8L2JvZHk+XG4gICAgPC9odG1sPlxuICBgO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9oZWxwZXJzL3JlbmRlckZ1bGxQYWdlLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicmVhY3QtaGVsbWV0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicmVhY3QtaGVsbWV0XCJcbi8vIG1vZHVsZSBpZCA9IDIyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcbmNvbnN0IHsgZ2V0Q2xhaW1JZCwgZ2V0TG9jYWxGaWxlUmVjb3JkIH0gPSByZXF1aXJlKCcuLi9jb250cm9sbGVycy9zZXJ2ZUNvbnRyb2xsZXIuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnLi9lcnJvckhhbmRsZXJzLmpzJyk7XG5cbmNvbnN0IFNFUlZFID0gJ1NFUlZFJztcbmNvbnN0IFNIT1cgPSAnU0hPVyc7XG5jb25zdCBOT19GSUxFID0gJ05PX0ZJTEUnO1xuY29uc3QgTk9fQ0hBTk5FTCA9ICdOT19DSEFOTkVMJztcbmNvbnN0IE5PX0NMQUlNID0gJ05PX0NMQUlNJztcblxuZnVuY3Rpb24gY2xpZW50QWNjZXB0c0h0bWwgKHthY2NlcHR9KSB7XG4gIHJldHVybiBhY2NlcHQgJiYgYWNjZXB0Lm1hdGNoKC90ZXh0XFwvaHRtbC8pO1xufTtcblxuZnVuY3Rpb24gcmVxdWVzdElzRnJvbUJyb3dzZXIgKGhlYWRlcnMpIHtcbiAgcmV0dXJuIGhlYWRlcnNbJ3VzZXItYWdlbnQnXSAmJiBoZWFkZXJzWyd1c2VyLWFnZW50J10ubWF0Y2goL01vemlsbGEvKTtcbn07XG5cbmZ1bmN0aW9uIGNsaWVudFdhbnRzQXNzZXQgKHthY2NlcHQsIHJhbmdlfSkge1xuICBjb25zdCBpbWFnZUlzV2FudGVkID0gYWNjZXB0ICYmIGFjY2VwdC5tYXRjaCgvaW1hZ2VcXC8uKi8pICYmICFhY2NlcHQubWF0Y2goL3RleHRcXC9odG1sLykgJiYgIWFjY2VwdC5tYXRjaCgvdGV4dFxcL1xcKi8pO1xuICBjb25zdCB2aWRlb0lzV2FudGVkID0gYWNjZXB0ICYmIHJhbmdlO1xuICByZXR1cm4gaW1hZ2VJc1dhbnRlZCB8fCB2aWRlb0lzV2FudGVkO1xufTtcblxuZnVuY3Rpb24gaXNWYWxpZENsYWltSWQgKGNsYWltSWQpIHtcbiAgcmV0dXJuICgoY2xhaW1JZC5sZW5ndGggPT09IDQwKSAmJiAhL1teQS1aYS16MC05XS9nLnRlc3QoY2xhaW1JZCkpO1xufTtcblxuZnVuY3Rpb24gaXNWYWxpZFNob3J0SWQgKGNsYWltSWQpIHtcbiAgcmV0dXJuIGNsYWltSWQubGVuZ3RoID09PSAxOyAgLy8gaXQgc2hvdWxkIHJlYWxseSBldmFsdWF0ZSB0aGUgc2hvcnQgdXJsIGl0c2VsZlxufTtcblxuZnVuY3Rpb24gaXNWYWxpZFNob3J0SWRPckNsYWltSWQgKGlucHV0KSB7XG4gIHJldHVybiAoaXNWYWxpZENsYWltSWQoaW5wdXQpIHx8IGlzVmFsaWRTaG9ydElkKGlucHV0KSk7XG59O1xuXG5mdW5jdGlvbiBzZXJ2ZUFzc2V0VG9DbGllbnQgKGNsYWltSWQsIG5hbWUsIHJlcykge1xuICByZXR1cm4gZ2V0TG9jYWxGaWxlUmVjb3JkKGNsYWltSWQsIG5hbWUpXG4gICAgLnRoZW4oZmlsZVJlY29yZCA9PiB7XG4gICAgICAvLyBjaGVjayB0aGF0IGEgbG9jYWwgcmVjb3JkIHdhcyBmb3VuZFxuICAgICAgaWYgKGZpbGVSZWNvcmQgPT09IE5PX0ZJTEUpIHtcbiAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoMzA3KS5yZWRpcmVjdChgL2FwaS9jbGFpbS9nZXQvJHtuYW1lfS8ke2NsYWltSWR9YCk7XG4gICAgICB9XG4gICAgICAvLyBzZXJ2ZSB0aGUgZmlsZVxuICAgICAgY29uc3Qge2ZpbGVQYXRoLCBmaWxlVHlwZX0gPSBmaWxlUmVjb3JkO1xuICAgICAgbG9nZ2VyLnZlcmJvc2UoYHNlcnZpbmcgZmlsZTogJHtmaWxlUGF0aH1gKTtcbiAgICAgIGNvbnN0IHNlbmRGaWxlT3B0aW9ucyA9IHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdYLUNvbnRlbnQtVHlwZS1PcHRpb25zJzogJ25vc25pZmYnLFxuICAgICAgICAgICdDb250ZW50LVR5cGUnICAgICAgICAgIDogZmlsZVR5cGUgfHwgJ2ltYWdlL2pwZWcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5zZW5kRmlsZShmaWxlUGF0aCwgc2VuZEZpbGVPcHRpb25zKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldCAoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkLCBjbGFpbU5hbWUsIGNsYWltSWQsIG9yaWdpbmFsVXJsLCBpcCwgcmVzKSB7XG4gICAgLy8gZ2V0IHRoZSBjbGFpbSBJZCBhbmQgdGhlbiBzZXJ2ZSB0aGUgYXNzZXRcbiAgICBnZXRDbGFpbUlkKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCwgY2xhaW1OYW1lLCBjbGFpbUlkKVxuICAgICAgLnRoZW4oZnVsbENsYWltSWQgPT4ge1xuICAgICAgICBpZiAoZnVsbENsYWltSWQgPT09IE5PX0NMQUlNKSB7XG4gICAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDA0KS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogJ25vIGNsYWltIGlkIGNvdWxkIGJlIGZvdW5kJ30pO1xuICAgICAgICB9IGVsc2UgaWYgKGZ1bGxDbGFpbUlkID09PSBOT19DSEFOTkVMKSB7XG4gICAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDA0KS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogJ25vIGNoYW5uZWwgaWQgY291bGQgYmUgZm91bmQnfSk7XG4gICAgICAgIH1cbiAgICAgICAgc2VydmVBc3NldFRvQ2xpZW50KGZ1bGxDbGFpbUlkLCBjbGFpbU5hbWUsIHJlcyk7XG4gICAgICAgIC8vIHBvc3RUb1N0YXRzKHJlc3BvbnNlVHlwZSwgb3JpZ2luYWxVcmwsIGlwLCBjbGFpbU5hbWUsIGZ1bGxDbGFpbUlkLCAnc3VjY2VzcycpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICAgICAgLy8gcG9zdFRvU3RhdHMocmVzcG9uc2VUeXBlLCBvcmlnaW5hbFVybCwgaXAsIGNsYWltTmFtZSwgZnVsbENsYWltSWQsICdmYWlsJyk7XG4gICAgICB9KTtcbiAgfSxcbiAgZGV0ZXJtaW5lUmVzcG9uc2VUeXBlIChoYXNGaWxlRXh0ZW5zaW9uLCBoZWFkZXJzKSB7XG4gICAgbGV0IHJlc3BvbnNlVHlwZTtcbiAgICBpZiAoaGFzRmlsZUV4dGVuc2lvbikge1xuICAgICAgcmVzcG9uc2VUeXBlID0gU0VSVkU7ICAvLyBhc3N1bWUgYSBzZXJ2ZSByZXF1ZXN0IGlmIGZpbGUgZXh0ZW5zaW9uIGlzIHByZXNlbnRcbiAgICAgIGlmIChjbGllbnRBY2NlcHRzSHRtbChoZWFkZXJzKSkgeyAgLy8gaWYgdGhlIHJlcXVlc3QgY29tZXMgZnJvbSBhIGJyb3dzZXIsIGNoYW5nZSBpdCB0byBhIHNob3cgcmVxdWVzdFxuICAgICAgICByZXNwb25zZVR5cGUgPSBTSE9XO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXNwb25zZVR5cGUgPSBTSE9XO1xuICAgICAgaWYgKGNsaWVudFdhbnRzQXNzZXQoaGVhZGVycykgJiYgcmVxdWVzdElzRnJvbUJyb3dzZXIoaGVhZGVycykpIHsgIC8vIHRoaXMgaXMgaW4gY2FzZSBzb21lb25lIGVtYmVkcyBhIHNob3cgdXJsXG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnU2hvdyByZXF1ZXN0IGNhbWUgZnJvbSBicm93c2VyIGJ1dCB3YW50cyBhbiBpbWFnZS92aWRlby4gQ2hhbmdpbmcgcmVzcG9uc2UgdG8gc2VydmUuLi4nKTtcbiAgICAgICAgcmVzcG9uc2VUeXBlID0gU0VSVkU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZVR5cGU7XG4gIH0sXG4gIGZsaXBDbGFpbU5hbWVBbmRJZEZvckJhY2t3YXJkc0NvbXBhdGliaWxpdHkgKGlkZW50aWZpZXIsIG5hbWUpIHtcbiAgICAvLyB0aGlzIGlzIGEgcGF0Y2ggZm9yIGJhY2t3YXJkcyBjb21wYXRhYmlsaXR5IHdpdGggJy9uYW1lL2NsYWltX2lkJyB1cmwgZm9ybWF0XG4gICAgaWYgKGlzVmFsaWRTaG9ydElkT3JDbGFpbUlkKG5hbWUpICYmICFpc1ZhbGlkU2hvcnRJZE9yQ2xhaW1JZChpZGVudGlmaWVyKSkge1xuICAgICAgY29uc3QgdGVtcE5hbWUgPSBuYW1lO1xuICAgICAgbmFtZSA9IGlkZW50aWZpZXI7XG4gICAgICBpZGVudGlmaWVyID0gdGVtcE5hbWU7XG4gICAgfVxuICAgIHJldHVybiBbaWRlbnRpZmllciwgbmFtZV07XG4gIH0sXG4gIGxvZ1JlcXVlc3REYXRhIChyZXNwb25zZVR5cGUsIGNsYWltTmFtZSwgY2hhbm5lbE5hbWUsIGNsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoJ3Jlc3BvbnNlVHlwZSA9PT0nLCByZXNwb25zZVR5cGUpO1xuICAgIGxvZ2dlci5kZWJ1ZygnY2xhaW0gbmFtZSA9PT0gJywgY2xhaW1OYW1lKTtcbiAgICBsb2dnZXIuZGVidWcoJ2NoYW5uZWwgbmFtZSA9PT0nLCBjaGFubmVsTmFtZSk7XG4gICAgbG9nZ2VyLmRlYnVnKCdjbGFpbSBpZCA9PT0nLCBjbGFpbUlkKTtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9zZXJ2ZUhlbHBlcnMuanMiLCJjb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBSRUdFWFBfSU5WQUxJRF9DTEFJTSAgOiAvW15BLVphLXowLTktXS9nLFxuICBSRUdFWFBfSU5WQUxJRF9DSEFOTkVMOiAvW15BLVphLXowLTktQF0vZyxcbiAgUkVHRVhQX0FERFJFU1MgICAgICAgIDogL15iKD89W14wT0lsXXszMiwzM30pWzAtOUEtWmEtel17MzIsMzN9JC8sXG4gIENIQU5ORUxfQ0hBUiAgICAgICAgICA6ICdAJyxcbiAgcGFyc2VJZGVudGlmaWVyICAgICAgIDogZnVuY3Rpb24gKGlkZW50aWZpZXIpIHtcbiAgICBsb2dnZXIuZGVidWcoJ3BhcnNpbmcgaWRlbnRpZmllcjonLCBpZGVudGlmaWVyKTtcbiAgICBjb25zdCBjb21wb25lbnRzUmVnZXggPSBuZXcgUmVnRXhwKFxuICAgICAgJyhbXjokIy9dKiknICsgLy8gdmFsdWUgKHN0b3BzIGF0IHRoZSBmaXJzdCBzZXBhcmF0b3Igb3IgZW5kKVxuICAgICAgJyhbOiQjXT8pKFteL10qKScgLy8gbW9kaWZpZXIgc2VwYXJhdG9yLCBtb2RpZmllciAoc3RvcHMgYXQgdGhlIGZpcnN0IHBhdGggc2VwYXJhdG9yIG9yIGVuZClcbiAgICApO1xuICAgIGNvbnN0IFtwcm90bywgdmFsdWUsIG1vZGlmaWVyU2VwZXJhdG9yLCBtb2RpZmllcl0gPSBjb21wb25lbnRzUmVnZXhcbiAgICAgIC5leGVjKGlkZW50aWZpZXIpXG4gICAgICAubWFwKG1hdGNoID0+IG1hdGNoIHx8IG51bGwpO1xuICAgIGxvZ2dlci5kZWJ1ZyhgJHtwcm90b30sICR7dmFsdWV9LCAke21vZGlmaWVyU2VwZXJhdG9yfSwgJHttb2RpZmllcn1gKTtcblxuICAgIC8vIFZhbGlkYXRlIGFuZCBwcm9jZXNzIG5hbWVcbiAgICBpZiAoIXZhbHVlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENoZWNrIHlvdXIgdXJsLiAgTm8gY2hhbm5lbCBuYW1lIHByb3ZpZGVkIGJlZm9yZSBcIiR7bW9kaWZpZXJTZXBlcmF0b3J9XCJgKTtcbiAgICB9XG4gICAgY29uc3QgaXNDaGFubmVsID0gdmFsdWUuc3RhcnRzV2l0aChtb2R1bGUuZXhwb3J0cy5DSEFOTkVMX0NIQVIpO1xuICAgIGNvbnN0IGNoYW5uZWxOYW1lID0gaXNDaGFubmVsID8gdmFsdWUgOiBudWxsO1xuICAgIGxldCBjbGFpbUlkO1xuICAgIGlmIChpc0NoYW5uZWwpIHtcbiAgICAgIGlmICghY2hhbm5lbE5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjaGFubmVsIG5hbWUgYWZ0ZXIgQC4nKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IG5hbWVCYWRDaGFycyA9IChjaGFubmVsTmFtZSkubWF0Y2gobW9kdWxlLmV4cG9ydHMuUkVHRVhQX0lOVkFMSURfQ0hBTk5FTCk7XG4gICAgICBpZiAobmFtZUJhZENoYXJzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBjaGFyYWN0ZXJzIGluIGNoYW5uZWwgbmFtZTogJHtuYW1lQmFkQ2hhcnMuam9pbignLCAnKX0uYCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNsYWltSWQgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvLyBWYWxpZGF0ZSBhbmQgcHJvY2VzcyBtb2RpZmllclxuICAgIGxldCBjaGFubmVsQ2xhaW1JZDtcbiAgICBpZiAobW9kaWZpZXJTZXBlcmF0b3IpIHtcbiAgICAgIGlmICghbW9kaWZpZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBtb2RpZmllciBwcm92aWRlZCBhZnRlciBzZXBhcmF0b3IgXCIke21vZGlmaWVyU2VwZXJhdG9yfVwiYCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChtb2RpZmllclNlcGVyYXRvciA9PT0gJzonKSB7XG4gICAgICAgIGNoYW5uZWxDbGFpbUlkID0gbW9kaWZpZXI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSBcIiR7bW9kaWZpZXJTZXBlcmF0b3J9XCIgbW9kaWZpZXIgaXMgbm90IGN1cnJlbnRseSBzdXBwb3J0ZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGlzQ2hhbm5lbCxcbiAgICAgIGNoYW5uZWxOYW1lLFxuICAgICAgY2hhbm5lbENsYWltSWQsXG4gICAgICBjbGFpbUlkLFxuICAgIH07XG4gIH0sXG4gIHBhcnNlQ2xhaW06IGZ1bmN0aW9uIChjbGFpbSkge1xuICAgIGxvZ2dlci5kZWJ1ZygncGFyc2luZyBuYW1lOicsIGNsYWltKTtcbiAgICBjb25zdCBjb21wb25lbnRzUmVnZXggPSBuZXcgUmVnRXhwKFxuICAgICAgJyhbXjokIy8uXSopJyArIC8vIG5hbWUgKHN0b3BzIGF0IHRoZSBmaXJzdCBtb2RpZmllcilcbiAgICAgICcoWzokIy5dPykoW14vXSopJyAvLyBtb2RpZmllciBzZXBhcmF0b3IsIG1vZGlmaWVyIChzdG9wcyBhdCB0aGUgZmlyc3QgcGF0aCBzZXBhcmF0b3Igb3IgZW5kKVxuICAgICk7XG4gICAgY29uc3QgW3Byb3RvLCBjbGFpbU5hbWUsIG1vZGlmaWVyU2VwZXJhdG9yLCBtb2RpZmllcl0gPSBjb21wb25lbnRzUmVnZXhcbiAgICAgIC5leGVjKGNsYWltKVxuICAgICAgLm1hcChtYXRjaCA9PiBtYXRjaCB8fCBudWxsKTtcbiAgICBsb2dnZXIuZGVidWcoYCR7cHJvdG99LCAke2NsYWltTmFtZX0sICR7bW9kaWZpZXJTZXBlcmF0b3J9LCAke21vZGlmaWVyfWApO1xuXG4gICAgLy8gVmFsaWRhdGUgYW5kIHByb2Nlc3MgbmFtZVxuICAgIGlmICghY2xhaW1OYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNsYWltIG5hbWUgcHJvdmlkZWQgYmVmb3JlIC4nKTtcbiAgICB9XG4gICAgY29uc3QgbmFtZUJhZENoYXJzID0gKGNsYWltTmFtZSkubWF0Y2gobW9kdWxlLmV4cG9ydHMuUkVHRVhQX0lOVkFMSURfQ0xBSU0pO1xuICAgIGlmIChuYW1lQmFkQ2hhcnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBjaGFyYWN0ZXJzIGluIGNsYWltIG5hbWU6ICR7bmFtZUJhZENoYXJzLmpvaW4oJywgJyl9LmApO1xuICAgIH1cbiAgICAvLyBWYWxpZGF0ZSBhbmQgcHJvY2VzcyBtb2RpZmllclxuICAgIGlmIChtb2RpZmllclNlcGVyYXRvcikge1xuICAgICAgaWYgKCFtb2RpZmllcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGZpbGUgZXh0ZW5zaW9uIHByb3ZpZGVkIGFmdGVyIHNlcGFyYXRvciAke21vZGlmaWVyU2VwZXJhdG9yfS5gKTtcbiAgICAgIH1cbiAgICAgIGlmIChtb2RpZmllclNlcGVyYXRvciAhPT0gJy4nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlICR7bW9kaWZpZXJTZXBlcmF0b3J9IG1vZGlmaWVyIGlzIG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGNsYWltIG5hbWVgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gcmV0dXJuIHJlc3VsdHNcbiAgICByZXR1cm4ge1xuICAgICAgY2xhaW1OYW1lLFxuICAgIH07XG4gIH0sXG4gIHBhcnNlTW9kaWZpZXI6IGZ1bmN0aW9uIChjbGFpbSkge1xuICAgIGxvZ2dlci5kZWJ1ZygncGFyc2luZyBtb2RpZmllcjonLCBjbGFpbSk7XG4gICAgY29uc3QgY29tcG9uZW50c1JlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICcoW146JCMvLl0qKScgKyAvLyBuYW1lIChzdG9wcyBhdCB0aGUgZmlyc3QgbW9kaWZpZXIpXG4gICAgICAnKFs6JCMuXT8pKFteL10qKScgLy8gbW9kaWZpZXIgc2VwYXJhdG9yLCBtb2RpZmllciAoc3RvcHMgYXQgdGhlIGZpcnN0IHBhdGggc2VwYXJhdG9yIG9yIGVuZClcbiAgICApO1xuICAgIGNvbnN0IFtwcm90bywgY2xhaW1OYW1lLCBtb2RpZmllclNlcGVyYXRvciwgbW9kaWZpZXJdID0gY29tcG9uZW50c1JlZ2V4XG4gICAgICAuZXhlYyhjbGFpbSlcbiAgICAgIC5tYXAobWF0Y2ggPT4gbWF0Y2ggfHwgbnVsbCk7XG4gICAgbG9nZ2VyLmRlYnVnKGAke3Byb3RvfSwgJHtjbGFpbU5hbWV9LCAke21vZGlmaWVyU2VwZXJhdG9yfSwgJHttb2RpZmllcn1gKTtcbiAgICAvLyBWYWxpZGF0ZSBhbmQgcHJvY2VzcyBtb2RpZmllclxuICAgIGxldCBoYXNGaWxlRXh0ZW5zaW9uID0gZmFsc2U7XG4gICAgaWYgKG1vZGlmaWVyU2VwZXJhdG9yKSB7XG4gICAgICBoYXNGaWxlRXh0ZW5zaW9uID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGhhc0ZpbGVFeHRlbnNpb24sXG4gICAgfTtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9sYnJ5VXJpLmpzIiwiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IHJlbmRlclRvU3RyaW5nIH0gZnJvbSAncmVhY3QtZG9tL3NlcnZlcic7XG5pbXBvcnQgeyBjcmVhdGVTdG9yZSwgYXBwbHlNaWRkbGV3YXJlIH0gZnJvbSAncmVkdXgnO1xuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tICdyZWFjdC1yZWR1eCc7XG5pbXBvcnQgeyBTdGF0aWNSb3V0ZXIgfSBmcm9tICdyZWFjdC1yb3V0ZXItZG9tJztcbmltcG9ydCByZW5kZXJGdWxsUGFnZSBmcm9tICcuL3JlbmRlckZ1bGxQYWdlJztcbmltcG9ydCBjcmVhdGVTYWdhTWlkZGxld2FyZSBmcm9tICdyZWR1eC1zYWdhJztcbmltcG9ydCB7IGNhbGwgfSBmcm9tICdyZWR1eC1zYWdhL2VmZmVjdHMnO1xuaW1wb3J0IHsgUmVkdWNlcnMsIEdBTGlzdGVuZXIsIEFwcCwgU2FnYXMsIEFjdGlvbnMgfSBmcm9tICdzcGVlLmNoLWNvbXBvbmVudHMnO1xuLypcbiAgXiBub3RlOiB0byBkbyB0aGlzIHJpZ2h0LCBtYXliZVxuICB0aGVzZSBzaG91bGQgYmUgcGFzc2VkIGluIGZyb20gdGhlIGltcGxlbWVudGF0aW9uICh3d3cuc3BlZS5jaCkgaXRzZWxmLFxuICBzbyB0aGF0IHRoZXJlIGFyZSBubyBjb25mbGljdHMgYmV0d2VlbiB0aGUgU1NSIGhlcmUgYW5kXG4gIHRoZSBidW5kbGUgc2VudCB0byB0aGUgc2VydmVyP1xuICB0aGVyZSBtaWdodCBhbHNvIGJlIGlzc3VlcyBpZiB0aGlzIHBhY2thZ2UgdXNlcyBhIGRpZmZlcmVudCB2ZXJzaW9uIG9mIHNwZWUuY2gtY29tcG9uZW50cyB0aGFuIHd3dy5zcGVlLmNoIGRvZXM/XG4qL1xuaW1wb3J0IEhlbG1ldCBmcm9tICdyZWFjdC1oZWxtZXQnO1xuXG4vLyBjb25maWd1cmUgdGhlIHJlZHVjZXJzIGJ5IHBhc3NpbmcgaW5pdGlhbCBzdGF0ZSBjb25maWdzXG5jb25zdCBzaXRlQ29uZmlnID0gcmVxdWlyZSgnc2l0ZUNvbmZpZy5qcycpO1xuY29uc3QgTXlSZWR1Y2VycyA9IFJlZHVjZXJzKHNpdGVDb25maWcpO1xuY29uc3QgTXlBcHAgPSBBcHAoc2l0ZUNvbmZpZyk7XG5jb25zdCBNeUdBTGlzdGVuZXIgPSBHQUxpc3RlbmVyKHNpdGVDb25maWcpO1xuXG5jb25zdCByZXR1cm5TYWdhV2l0aFBhcmFtcyA9IChzYWdhLCBwYXJhbXMpID0+IHtcbiAgcmV0dXJuIGZ1bmN0aW9uICogKCkge1xuICAgIHlpZWxkIGNhbGwoc2FnYSwgcGFyYW1zKTtcbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gKHJlcSwgcmVzKSA9PiB7XG4gIGxldCBjb250ZXh0ID0ge307XG5cbiAgLy8gY3JlYXRlIGFuZCBhcHBseSBtaWRkbGV3YXJlXG4gIGNvbnN0IHNhZ2FNaWRkbGV3YXJlID0gY3JlYXRlU2FnYU1pZGRsZXdhcmUoKTtcbiAgY29uc3QgbWlkZGxld2FyZSA9IGFwcGx5TWlkZGxld2FyZShzYWdhTWlkZGxld2FyZSk7XG5cbiAgLy8gY3JlYXRlIGEgbmV3IFJlZHV4IHN0b3JlIGluc3RhbmNlXG4gIGNvbnN0IHN0b3JlID0gY3JlYXRlU3RvcmUoTXlSZWR1Y2VycywgbWlkZGxld2FyZSk7XG5cbiAgLy8gY3JlYXRlIHNhZ2FcbiAgY29uc3QgYWN0aW9uID0gQWN0aW9ucy5vbkhhbmRsZVNob3dQYWdlVXJpKHJlcS5wYXJhbXMpO1xuICBjb25zdCBzYWdhID0gcmV0dXJuU2FnYVdpdGhQYXJhbXMoU2FnYXMuaGFuZGxlU2hvd1BhZ2VVcmksIGFjdGlvbik7XG5cbiAgLy8gcnVuIHRoZSBzYWdhIG1pZGRsZXdhcmVcbiAgc2FnYU1pZGRsZXdhcmVcbiAgICAucnVuKHNhZ2EpXG4gICAgLmRvbmVcbiAgICAudGhlbigoKSA9PiB7XG4gICAgICAvLyByZW5kZXIgY29tcG9uZW50IHRvIGEgc3RyaW5nXG4gICAgICBjb25zdCBodG1sID0gcmVuZGVyVG9TdHJpbmcoXG4gICAgICAgIDxQcm92aWRlciBzdG9yZT17c3RvcmV9PlxuICAgICAgICAgIDxTdGF0aWNSb3V0ZXIgbG9jYXRpb249e3JlcS51cmx9IGNvbnRleHQ9e2NvbnRleHR9PlxuICAgICAgICAgICAgPE15R0FMaXN0ZW5lcj5cbiAgICAgICAgICAgICAgPE15QXBwIC8+XG4gICAgICAgICAgICA8L015R0FMaXN0ZW5lcj5cbiAgICAgICAgICA8L1N0YXRpY1JvdXRlcj5cbiAgICAgICAgPC9Qcm92aWRlcj5cbiAgICAgICk7XG5cbiAgICAgIC8vIGdldCBoZWFkIHRhZ3MgZnJvbSBoZWxtZXRcbiAgICAgIGNvbnN0IGhlbG1ldCA9IEhlbG1ldC5yZW5kZXJTdGF0aWMoKTtcblxuICAgICAgLy8gY2hlY2sgZm9yIGEgcmVkaXJlY3RcbiAgICAgIGlmIChjb250ZXh0LnVybCkge1xuICAgICAgICByZXR1cm4gcmVzLnJlZGlyZWN0KDMwMSwgY29udGV4dC51cmwpO1xuICAgICAgfVxuXG4gICAgICAvLyBnZXQgdGhlIGluaXRpYWwgc3RhdGUgZnJvbSBvdXIgUmVkdXggc3RvcmVcbiAgICAgIGNvbnN0IHByZWxvYWRlZFN0YXRlID0gc3RvcmUuZ2V0U3RhdGUoKTtcblxuICAgICAgLy8gc2VuZCB0aGUgcmVuZGVyZWQgcGFnZSBiYWNrIHRvIHRoZSBjbGllbnRcbiAgICAgIHJlcy5zZW5kKHJlbmRlckZ1bGxQYWdlKGhlbG1ldCwgaHRtbCwgcHJlbG9hZGVkU3RhdGUpKTtcbiAgICB9KTtcblxuICBjb25zb2xlLmxvZygnaGVsbG8gZnJvbSBzcGVlLmNoIGhhbmRsZVNob3dSZW5kZXIuanN4Jyk7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvaGFuZGxlU2hvd1JlbmRlci5qc3giLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJiYWJlbC1wb2x5ZmlsbFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImJhYmVsLXBvbHlmaWxsXCJcbi8vIG1vZHVsZSBpZCA9IDI3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIndoYXR3Zy1mZXRjaFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcIndoYXR3Zy1mZXRjaFwiXG4vLyBtb2R1bGUgaWQgPSAyOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCBTZXJ2ZXIgPSByZXF1aXJlKCcuL3NlcnZlcicpO1xuXG5jb25zdCBleHBvcnRzID0ge1xuICBTZXJ2ZXIsXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHM7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcGVlY2guanMiLCIvLyBhcHAgZGVwZW5kZW5jaWVzXG5jb25zdCBleHByZXNzID0gcmVxdWlyZSgnZXhwcmVzcycpO1xuY29uc3QgYm9keVBhcnNlciA9IHJlcXVpcmUoJ2JvZHktcGFyc2VyJyk7XG5jb25zdCBleHByZXNzSGFuZGxlYmFycyA9IHJlcXVpcmUoJ2V4cHJlc3MtaGFuZGxlYmFycycpO1xuY29uc3QgSGFuZGxlYmFycyA9IHJlcXVpcmUoJ2hhbmRsZWJhcnMnKTtcbmNvbnN0IGhlbG1ldCA9IHJlcXVpcmUoJ2hlbG1ldCcpO1xuY29uc3QgY29va2llU2Vzc2lvbiA9IHJlcXVpcmUoJ2Nvb2tpZS1zZXNzaW9uJyk7XG5jb25zdCBodHRwID0gcmVxdWlyZSgnaHR0cCcpO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgcmVxdWVzdExvZ2dlciA9IHJlcXVpcmUoJ21pZGRsZXdhcmUvcmVxdWVzdExvZ2dlci5qcycpO1xuY29uc3QgUGF0aCA9IHJlcXVpcmUoJ3BhdGgnKTtcbmNvbnN0IGxvZ2dlckNvbmZpZyA9IHJlcXVpcmUoJ2xvZ2dlckNvbmZpZy5qcycpO1xuY29uc3QgbXlzcWxDb25maWcgPSByZXF1aXJlKCdteXNxbENvbmZpZy5qcycpO1xuY29uc3Qgc2l0ZUNvbmZpZyA9IHJlcXVpcmUoJ3NpdGVDb25maWcuanMnKTtcbmNvbnN0IHNsYWNrQ29uZmlnID0gcmVxdWlyZSgnc2xhY2tDb25maWcuanMnKTtcblxuZnVuY3Rpb24gU2VydmVyICgpIHtcbiAgdGhpcy5jb25maWd1cmVMb2dnZXIgPSAodXNlckNvbmZpZykgPT4ge1xuICAgIGxvZ2dlckNvbmZpZy51cGRhdGUodXNlckNvbmZpZyk7XG4gIH07XG4gIHRoaXMuY29uZmlndXJlTXlzcWwgPSAodXNlckNvbmZpZykgPT4ge1xuICAgIG15c3FsQ29uZmlnLnVwZGF0ZSh1c2VyQ29uZmlnKTtcbiAgfTtcbiAgdGhpcy5jb25maWd1cmVTaXRlID0gKHVzZXJDb25maWcpID0+IHtcbiAgICBzaXRlQ29uZmlnLnVwZGF0ZSh1c2VyQ29uZmlnKTtcbiAgfTtcbiAgdGhpcy5jb25maWd1cmVTbGFjayA9ICh1c2VyQ29uZmlnKSA9PiB7XG4gICAgc2xhY2tDb25maWcudXBkYXRlKHVzZXJDb25maWcpO1xuICB9O1xuICB0aGlzLmNvbmZpZ3VyZU1vZGVscyA9ICgpID0+IHtcbiAgICBsb2dnZXIuZGVidWcoJ2hlcmUgaXMgd2hlcmUgeW91IGNvdWxkIGFkZC9vdmVyd3JpdGUgdGhlIGRlZmF1bHQgbW9kZWxzJylcbiAgfTtcbiAgdGhpcy5jb25maWd1cmVSb3V0ZXMgPSAoKSA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKCdoZXJlIGlzIHdoZXJlIHlvdSBjb3VsZCBhZGQvb3ZlcndyaXRlIHRoZSBkZWZhdWx0IHJvdXRlcycpXG4gIH07XG4gIHRoaXMuY3JlYXRlQXBwID0gKCkgPT4ge1xuICAgIC8vIGNyZWF0ZSBhbiBFeHByZXNzIGFwcGxpY2F0aW9uXG4gICAgY29uc3QgYXBwID0gZXhwcmVzcygpO1xuXG4gICAgLy8gdHJ1c3QgdGhlIHByb3h5IHRvIGdldCBpcCBhZGRyZXNzIGZvciB1c1xuICAgIGFwcC5lbmFibGUoJ3RydXN0IHByb3h5Jyk7XG5cbiAgICAvKiBhZGQgbWlkZGxld2FyZSAqL1xuICAgIC8vIHNldCBIVFRQIGhlYWRlcnMgdG8gcHJvdGVjdCBhZ2FpbnN0IHdlbGwta25vd24gd2ViIHZ1bG5lcmFiaWx0aWVzXG4gICAgYXBwLnVzZShoZWxtZXQoKSk7XG4gICAgLy8gJ2V4cHJlc3Muc3RhdGljJyB0byBzZXJ2ZSBzdGF0aWMgZmlsZXMgZnJvbSBwdWJsaWMgZGlyZWN0b3J5XG4gICAgaWYgKHNpdGVDb25maWcucm91dGVzLnB1YmxpY0ZvbGRlcikge1xuICAgICAgLy8gdGFrZSBpbiBhIGRpZmZlcmVudCBwdWJsaWMgZm9sZGVyLCBzbyBpdCBjYW4gc2VydmUgaXQncyBvd24gYnVuZGxlIGlmIG5lZWRlZFxuICAgICAgY29uc3QgcHVibGljRm9sZGVyID0gUGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIHNpdGVDb25maWcucm91dGVzLnB1YmxpY0ZvbGRlcik7XG4gICAgICBhcHAudXNlKGV4cHJlc3Muc3RhdGljKHB1YmxpY0ZvbGRlcikpO1xuICAgICAgbG9nZ2VyLmluZm8oJ3NlcnZpbmcgc3RhdGljIGZpbGVzIGZyb20gY3VzdG9tIHBhdGg6JywgcHVibGljRm9sZGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcHVibGljUGF0aCA9IFBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICdwdWJsaWMnKTtcbiAgICAgIGFwcC51c2UoZXhwcmVzcy5zdGF0aWMocHVibGljUGF0aCkpO1xuICAgICAgbG9nZ2VyLmluZm8oJ3NlcnZpbmcgc3RhdGljIGZpbGVzIGZyb20gZGVmYXVsdCBwYXRoOicsIHB1YmxpY1BhdGgpO1xuICAgIH07XG4gICAgLy8gJ2JvZHkgcGFyc2VyJyBmb3IgcGFyc2luZyBhcHBsaWNhdGlvbi9qc29uXG4gICAgYXBwLnVzZShib2R5UGFyc2VyLmpzb24oKSk7XG4gICAgLy8gJ2JvZHkgcGFyc2VyJyBmb3IgcGFyc2luZyBhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcbiAgICBhcHAudXNlKGJvZHlQYXJzZXIudXJsZW5jb2RlZCh7IGV4dGVuZGVkOiB0cnVlIH0pKTtcblxuICAgIC8vIGFkZCBjdXN0b20gbWlkZGxld2FyZSAobm90ZTogYnVpbGQgb3V0IHRvIGFjY2VwdCBkeW5hbWljYWxseSB1c2Ugd2hhdCBpcyBpbiBzZXJ2ZXIvbWlkZGxld2FyZS9cbiAgICBhcHAudXNlKHJlcXVlc3RMb2dnZXIpO1xuXG4gICAgLy8gY29uZmlndXJlIHBhc3Nwb3J0XG4gICAgY29uc3Qgc3BlZWNoUGFzc3BvcnQgPSByZXF1aXJlKCdzcGVlY2hQYXNzcG9ydCcpO1xuICAgIC8vIGluaXRpYWxpemUgcGFzc3BvcnRcbiAgICBjb25zdCBzZXNzaW9uS2V5ID0gc2l0ZUNvbmZpZy5hdXRoLnNlc3Npb25LZXk7XG4gICAgYXBwLnVzZShjb29raWVTZXNzaW9uKHtcbiAgICAgIG5hbWUgIDogJ3Nlc3Npb24nLFxuICAgICAga2V5cyAgOiBbc2Vzc2lvbktleV0sXG4gICAgICBtYXhBZ2U6IDI0ICogNjAgKiA2MCAqIDEwMDAsIC8vIGkuZS4gMjQgaG91cnNcbiAgICB9KSk7XG4gICAgYXBwLnVzZShzcGVlY2hQYXNzcG9ydC5pbml0aWFsaXplKCkpO1xuICAgIGFwcC51c2Uoc3BlZWNoUGFzc3BvcnQuc2Vzc2lvbigpKTtcblxuICAgIC8vIGNvbmZpZ3VyZSBoYW5kbGViYXJzICYgcmVnaXN0ZXIgaXQgd2l0aCBleHByZXNzIGFwcFxuICAgIGNvbnN0IGhicyA9IGV4cHJlc3NIYW5kbGViYXJzLmNyZWF0ZSh7XG4gICAgICBkZWZhdWx0TGF5b3V0OiAnZW1iZWQnLFxuICAgICAgaGFuZGxlYmFycyAgIDogSGFuZGxlYmFycyxcbiAgICB9KTtcbiAgICBhcHAuZW5naW5lKCdoYW5kbGViYXJzJywgaGJzLmVuZ2luZSk7XG4gICAgYXBwLnNldCgndmlldyBlbmdpbmUnLCAnaGFuZGxlYmFycycpO1xuXG4gICAgLy8gc2V0IHRoZSByb3V0ZXMgb24gdGhlIGFwcFxuICAgIHJlcXVpcmUoJy4vcm91dGVzL2F1dGgvJykoYXBwKTtcbiAgICByZXF1aXJlKCcuL3JvdXRlcy9hcGkvJykoYXBwKTtcbiAgICByZXF1aXJlKCcuL3JvdXRlcy9wYWdlcy8nKShhcHApO1xuICAgIHJlcXVpcmUoJy4vcm91dGVzL2Fzc2V0cy8nKShhcHApO1xuICAgIHJlcXVpcmUoJy4vcm91dGVzL2ZhbGxiYWNrLycpKGFwcCk7XG5cbiAgICB0aGlzLmFwcCA9IGFwcDtcbiAgfTtcbiAgdGhpcy5pbml0aWFsaXplID0gKCkgPT4ge1xuICAgIHRoaXMuY3JlYXRlQXBwKCk7XG4gICAgdGhpcy5zZXJ2ZXIgPSBodHRwLlNlcnZlcih0aGlzLmFwcCk7XG4gIH07XG4gIHRoaXMuc3RhcnQgPSAoKSA9PiB7XG4gICAgY29uc3QgZGIgPSByZXF1aXJlKCdtb2RlbHMnKTtcbiAgICBjb25zdCBQT1JUID0gc2l0ZUNvbmZpZy5kZXRhaWxzLnBvcnQ7XG4gICAgLy8gc3luYyBzZXF1ZWxpemVcbiAgICBkYi5zZXF1ZWxpemUuc3luYygpXG4gICAgLy8gc3RhcnQgdGhlIHNlcnZlclxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNlcnZlci5saXN0ZW4oUE9SVCwgKCkgPT4ge1xuICAgICAgICAgIGxvZ2dlci5pbmZvKGBTZXJ2ZXIgaXMgbGlzdGVuaW5nIG9uIFBPUlQgJHtQT1JUfWApO1xuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihgU3RhcnR1cCBFcnJvcjpgLCBlcnJvcik7XG4gICAgICB9KTtcbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gU2VydmVyO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2luZGV4LmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiZXhwcmVzc1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImV4cHJlc3NcIlxuLy8gbW9kdWxlIGlkID0gMzFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiYm9keS1wYXJzZXJcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJib2R5LXBhcnNlclwiXG4vLyBtb2R1bGUgaWQgPSAzMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJleHByZXNzLWhhbmRsZWJhcnNcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJleHByZXNzLWhhbmRsZWJhcnNcIlxuLy8gbW9kdWxlIGlkID0gMzNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiaGFuZGxlYmFyc1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImhhbmRsZWJhcnNcIlxuLy8gbW9kdWxlIGlkID0gMzRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiaGVsbWV0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiaGVsbWV0XCJcbi8vIG1vZHVsZSBpZCA9IDM1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImNvb2tpZS1zZXNzaW9uXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiY29va2llLXNlc3Npb25cIlxuLy8gbW9kdWxlIGlkID0gMzZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiaHR0cFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImh0dHBcIlxuLy8gbW9kdWxlIGlkID0gMzdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5jb25zdCByZXF1ZXN0TG9nZ2VyID0gKHJlcSwgcmVzLCBuZXh0KSA9PiB7ICAvLyBjdXN0b20gbG9nZ2luZyBtaWRkbGV3YXJlIHRvIGxvZyBhbGwgaW5jb21pbmcgaHR0cCByZXF1ZXN0c1xuICBsb2dnZXIudmVyYm9zZShgUmVxdWVzdCBvbiAke3JlcS5vcmlnaW5hbFVybH0gZnJvbSAke3JlcS5pcH1gKTtcbiAgbmV4dCgpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1ZXN0TG9nZ2VyO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21pZGRsZXdhcmUvcmVxdWVzdExvZ2dlci5qcyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInBhdGhcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJwYXRoXCJcbi8vIG1vZHVsZSBpZCA9IDM5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcblxuZnVuY3Rpb24gTG9nZ2VyQ29uZmlnICgpIHtcbiAgdGhpcy5sb2dMZXZlbCA9ICdkZWJ1Zyc7XG4gIHRoaXMudXBkYXRlID0gKGNvbmZpZykgPT4ge1xuICAgIGlmICghY29uZmlnKSB7XG4gICAgICByZXR1cm4gbG9nZ2VyLndhcm4oJ05vIGxvZ2dlciBjb25maWcgcmVjZWl2ZWQuJyk7XG4gICAgfVxuICAgIGxvZ2dlci5pbmZvKCdjb25maWd1cmluZyB3aW5zdG9uIGxvZ2dlci4uLicpO1xuICAgIC8vIHVwZGF0ZSB2YWx1ZXMgd2l0aCBsb2NhbCBjb25maWcgcGFyYW1zXG4gICAgY29uc3Qge2xvZ0xldmVsfSA9IGNvbmZpZztcbiAgICB0aGlzLmxvZ0xldmVsID0gbG9nTGV2ZWw7XG4gICAgLy8gY29uZmlndXJlIHRoZSB3aW5zdG9uIGxvZ2dlclxuICAgIGxvZ2dlci5jb25maWd1cmUoe1xuICAgICAgdHJhbnNwb3J0czogW1xuICAgICAgICBuZXcgKGxvZ2dlci50cmFuc3BvcnRzLkNvbnNvbGUpKHtcbiAgICAgICAgICBsZXZlbCAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0aGlzLmxvZ0xldmVsLFxuICAgICAgICAgIHRpbWVzdGFtcCAgICAgICAgICAgICAgICAgICAgICA6IGZhbHNlLFxuICAgICAgICAgIGNvbG9yaXplICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgcHJldHR5UHJpbnQgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICBoYW5kbGVFeGNlcHRpb25zICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgIGh1bWFuUmVhZGFibGVVbmhhbmRsZWRFeGNlcHRpb246IHRydWUsXG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICB9KTtcbiAgICAvLyB0ZXN0IGFsbCB0aGUgbG9nIGxldmVsc1xuICAgIGxvZ2dlci5pbmZvKCd0ZXN0aW5nIHdpbnN0b24gbG9nIGxldmVscy4uLicpO1xuICAgIGxvZ2dlci5lcnJvcignTGV2ZWwgMCcpO1xuICAgIGxvZ2dlci53YXJuKCdMZXZlbCAxJyk7XG4gICAgbG9nZ2VyLmluZm8oJ0xldmVsIDInKTtcbiAgICBsb2dnZXIudmVyYm9zZSgnTGV2ZWwgMycpO1xuICAgIGxvZ2dlci5kZWJ1ZygnTGV2ZWwgNCcpO1xuICAgIGxvZ2dlci5zaWxseSgnTGV2ZWwgNScpO1xuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgTG9nZ2VyQ29uZmlnKCk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9jb25maWcvbG9nZ2VyQ29uZmlnLmpzIiwiY29uc3Qgd2luc3RvblNsYWNrV2ViSG9vayA9IHJlcXVpcmUoJ3dpbnN0b24tc2xhY2std2ViaG9vaycpLlNsYWNrV2ViSG9vaztcbmNvbnN0IHdpbnN0b24gPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbmZ1bmN0aW9uIFNsYWNrQ29uZmlnICgpIHtcbiAgdGhpcy5zbGFja1dlYkhvb2sgICAgICA9ICdkZWZhdWx0JztcbiAgdGhpcy5zbGFja0Vycm9yQ2hhbm5lbCA9ICdkZWZhdWx0JztcbiAgdGhpcy5zbGFja0luZm9DaGFubmVsICA9ICdkZWZhdWx0JztcbiAgdGhpcy51cGRhdGUgPSAoY29uZmlnKSA9PiB7XG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHJldHVybiB3aW5zdG9uLndhcm4oJ05vIHNsYWNrIGNvbmZpZyByZWNlaXZlZCcpO1xuICAgIH1cbiAgICAvLyB1cGRhdGUgdmFyaWFibGVzXG4gICAgd2luc3Rvbi5pbmZvKCdjb25maWd1cmluZyBzbGFjayBsb2dnZXIuLi4nKTtcbiAgICBjb25zdCB7c2xhY2tXZWJIb29rLCBzbGFja0Vycm9yQ2hhbm5lbCwgc2xhY2tJbmZvQ2hhbm5lbH0gPSBjb25maWc7XG4gICAgdGhpcy5zbGFja1dlYkhvb2sgPSBzbGFja1dlYkhvb2s7XG4gICAgdGhpcy5zbGFja0Vycm9yQ2hhbm5lbCA9IHNsYWNrRXJyb3JDaGFubmVsO1xuICAgIHRoaXMuc2xhY2tJbmZvQ2hhbm5lbCA9IHNsYWNrSW5mb0NoYW5uZWw7XG4gICAgLy8gdXBkYXRlIHNsYWNrIHdlYmhvb2sgc2V0dGluZ3NcbiAgICBpZiAodGhpcy5zbGFja1dlYkhvb2spIHtcbiAgICAgIC8vIGFkZCBhIHRyYW5zcG9ydCBmb3IgZXJyb3JzIHRvIHNsYWNrXG4gICAgICBpZiAodGhpcy5zbGFja0Vycm9yQ2hhbm5lbCkge1xuICAgICAgICB3aW5zdG9uLmFkZCh3aW5zdG9uU2xhY2tXZWJIb29rLCB7XG4gICAgICAgICAgbmFtZSAgICAgIDogJ3NsYWNrLWVycm9ycy10cmFuc3BvcnQnLFxuICAgICAgICAgIGxldmVsICAgICA6ICd3YXJuJyxcbiAgICAgICAgICB3ZWJob29rVXJsOiB0aGlzLnNsYWNrV2ViSG9vayxcbiAgICAgICAgICBjaGFubmVsICAgOiB0aGlzLnNsYWNrRXJyb3JDaGFubmVsLFxuICAgICAgICAgIHVzZXJuYW1lICA6ICdzcGVlLmNoJyxcbiAgICAgICAgICBpY29uRW1vamkgOiAnOmZhY2Vfd2l0aF9oZWFkX2JhbmRhZ2U6JyxcbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgICAgaWYgKHNsYWNrSW5mb0NoYW5uZWwpIHtcbiAgICAgICAgd2luc3Rvbi5hZGQod2luc3RvblNsYWNrV2ViSG9vaywge1xuICAgICAgICAgIG5hbWUgICAgICA6ICdzbGFjay1pbmZvLXRyYW5zcG9ydCcsXG4gICAgICAgICAgbGV2ZWwgICAgIDogJ2luZm8nLFxuICAgICAgICAgIHdlYmhvb2tVcmw6IHRoaXMuc2xhY2tXZWJIb29rLFxuICAgICAgICAgIGNoYW5uZWwgICA6IHRoaXMuc2xhY2tJbmZvQ2hhbm5lbCxcbiAgICAgICAgICB1c2VybmFtZSAgOiAnc3BlZS5jaCcsXG4gICAgICAgICAgaWNvbkVtb2ppIDogJzpuZXJkX2ZhY2U6JyxcbiAgICAgICAgfSk7XG4gICAgICB9O1xuICAgICAgLy8gc2VuZCB0ZXN0IG1lc3NhZ2VzXG4gICAgICB3aW5zdG9uLmluZm8oJ3Rlc3Rpbmcgc2xhY2sgbG9nZ2VyLi4uJyk7XG4gICAgICB3aW5zdG9uLmVycm9yKCdTbGFjayBcImVycm9yXCIgbG9nZ2luZyBpcyBvbmxpbmUuJyk7XG4gICAgICB3aW5zdG9uLmluZm8oJ1NsYWNrIFwiaW5mb1wiIGxvZ2dpbmcgaXMgb25saW5lLicpO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aW5zdG9uLndhcm4oJ1NsYWNrIGxvZ2dpbmcgaXMgbm90IGVuYWJsZWQgYmVjYXVzZSBubyBzbGFja1dlYkhvb2sgY29uZmlnIHZhciBwcm92aWRlZC4nKTtcbiAgICB9XG4gIH07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBTbGFja0NvbmZpZygpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vY29uZmlnL3NsYWNrQ29uZmlnLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwid2luc3Rvbi1zbGFjay13ZWJob29rXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwid2luc3Rvbi1zbGFjay13ZWJob29rXCJcbi8vIG1vZHVsZSBpZCA9IDQyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInBhc3Nwb3J0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicGFzc3BvcnRcIlxuLy8gbW9kdWxlIGlkID0gNDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgUGFzc3BvcnRMb2NhbFN0cmF0ZWd5ID0gcmVxdWlyZSgncGFzc3BvcnQtbG9jYWwnKS5TdHJhdGVneTtcbmNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcbmNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5cbmNvbnN0IHJldHVyblVzZXJBbmRDaGFubmVsSW5mbyA9ICh1c2VySW5zdGFuY2UpID0+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgdXNlckluZm8gPSB7fTtcbiAgICB1c2VySW5mb1snaWQnXSA9IHVzZXJJbnN0YW5jZS5pZDtcbiAgICB1c2VySW5mb1sndXNlck5hbWUnXSA9IHVzZXJJbnN0YW5jZS51c2VyTmFtZTtcbiAgICB1c2VySW5zdGFuY2VcbiAgICAgIC5nZXRDaGFubmVsKClcbiAgICAgIC50aGVuKCh7Y2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkfSkgPT4ge1xuICAgICAgICB1c2VySW5mb1snY2hhbm5lbE5hbWUnXSA9IGNoYW5uZWxOYW1lO1xuICAgICAgICB1c2VySW5mb1snY2hhbm5lbENsYWltSWQnXSA9IGNoYW5uZWxDbGFpbUlkO1xuICAgICAgICByZXR1cm4gZGIuQ2VydGlmaWNhdGUuZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZChjaGFubmVsQ2xhaW1JZCwgY2hhbm5lbE5hbWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHNob3J0Q2hhbm5lbElkID0+IHtcbiAgICAgICAgdXNlckluZm9bJ3Nob3J0Q2hhbm5lbElkJ10gPSBzaG9ydENoYW5uZWxJZDtcbiAgICAgICAgcmVzb2x2ZSh1c2VySW5mbyk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFBhc3Nwb3J0TG9jYWxTdHJhdGVneShcbiAge1xuICAgIHVzZXJuYW1lRmllbGQ6ICd1c2VybmFtZScsXG4gICAgcGFzc3dvcmRGaWVsZDogJ3Bhc3N3b3JkJyxcbiAgfSxcbiAgKHVzZXJuYW1lLCBwYXNzd29yZCwgZG9uZSkgPT4ge1xuICAgIHJldHVybiBkYi5Vc2VyXG4gICAgICAuZmluZE9uZSh7XG4gICAgICAgIHdoZXJlOiB7dXNlck5hbWU6IHVzZXJuYW1lfSxcbiAgICAgIH0pXG4gICAgICAudGhlbih1c2VyID0+IHtcbiAgICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKCdubyB1c2VyIGZvdW5kJyk7XG4gICAgICAgICAgcmV0dXJuIGRvbmUobnVsbCwgZmFsc2UsIHttZXNzYWdlOiAnSW5jb3JyZWN0IHVzZXJuYW1lIG9yIHBhc3N3b3JkJ30pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1c2VyLmNvbXBhcmVQYXNzd29yZChwYXNzd29yZClcbiAgICAgICAgICAudGhlbihpc01hdGNoID0+IHtcbiAgICAgICAgICAgIGlmICghaXNNYXRjaCkge1xuICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoJ2luY29ycmVjdCBwYXNzd29yZCcpO1xuICAgICAgICAgICAgICByZXR1cm4gZG9uZShudWxsLCBmYWxzZSwge21lc3NhZ2U6ICdJbmNvcnJlY3QgdXNlcm5hbWUgb3IgcGFzc3dvcmQnfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ1Bhc3N3b3JkIHdhcyBhIG1hdGNoLCByZXR1cm5pbmcgVXNlcicpO1xuICAgICAgICAgICAgcmV0dXJuIHJldHVyblVzZXJBbmRDaGFubmVsSW5mbyh1c2VyKVxuICAgICAgICAgICAgICAudGhlbih1c2VySW5mbyA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRvbmUobnVsbCwgdXNlckluZm8pO1xuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHJldHVybiBkb25lKGVycm9yKTtcbiAgICAgIH0pO1xuICB9LFxuKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9sb2NhbC1sb2dpbi5qcyIsImNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcbmNvbnN0IHsgcmV0dXJuU2hvcnRJZCB9ID0gcmVxdWlyZSgnLi4vaGVscGVycy9zZXF1ZWxpemVIZWxwZXJzLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKHNlcXVlbGl6ZSwgeyBTVFJJTkcsIEJPT0xFQU4sIElOVEVHRVIsIFRFWFQsIERFQ0lNQUwgfSkgPT4ge1xuICBjb25zdCBDZXJ0aWZpY2F0ZSA9IHNlcXVlbGl6ZS5kZWZpbmUoXG4gICAgJ0NlcnRpZmljYXRlJyxcbiAgICB7XG4gICAgICBhZGRyZXNzOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBhbW91bnQ6IHtcbiAgICAgICAgdHlwZSAgIDogREVDSU1BTCgxOSwgOCksXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2xhaW1JZDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2xhaW1TZXF1ZW5jZToge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGRlY29kZWRDbGFpbToge1xuICAgICAgICB0eXBlICAgOiBCT09MRUFOLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGRlcHRoOiB7XG4gICAgICAgIHR5cGUgICA6IElOVEVHRVIsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgZWZmZWN0aXZlQW1vdW50OiB7XG4gICAgICAgIHR5cGUgICA6IERFQ0lNQUwoMTksIDgpLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGhhc1NpZ25hdHVyZToge1xuICAgICAgICB0eXBlICAgOiBCT09MRUFOLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGhlaWdodDoge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGhleDoge1xuICAgICAgICB0eXBlICAgOiBURVhUKCdsb25nJyksXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbmFtZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbm91dDoge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHR4aWQ6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHZhbGlkQXRIZWlnaHQ6IHtcbiAgICAgICAgdHlwZSAgIDogSU5URUdFUixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBvdXRwb2ludDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgdmFsdWVWZXJzaW9uOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBjbGFpbVR5cGU6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGNlcnRpZmljYXRlVmVyc2lvbjoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAga2V5VHlwZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgcHVibGljS2V5OiB7XG4gICAgICAgIHR5cGUgICA6IFRFWFQoJ2xvbmcnKSxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgfSxcbiAgICB7XG4gICAgICBmcmVlemVUYWJsZU5hbWU6IHRydWUsXG4gICAgfVxuICApO1xuXG4gIENlcnRpZmljYXRlLmFzc29jaWF0ZSA9IGRiID0+IHtcbiAgICBDZXJ0aWZpY2F0ZS5iZWxvbmdzVG8oZGIuQ2hhbm5lbCwge1xuICAgICAgZm9yZWlnbktleToge1xuICAgICAgICBhbGxvd051bGw6IHRydWUsXG4gICAgICB9LFxuICAgIH0pO1xuICB9O1xuXG4gIENlcnRpZmljYXRlLmdldFNob3J0Q2hhbm5lbElkRnJvbUxvbmdDaGFubmVsSWQgPSBmdW5jdGlvbiAobG9uZ0NoYW5uZWxJZCwgY2hhbm5lbE5hbWUpIHtcbiAgICBsb2dnZXIuZGVidWcoYGdldFNob3J0Q2hhbm5lbElkRnJvbUxvbmdDaGFubmVsSWQgJHtjaGFubmVsTmFtZX06JHtsb25nQ2hhbm5lbElkfWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZToge25hbWU6IGNoYW5uZWxOYW1lfSxcbiAgICAgICAgICBvcmRlcjogW1snaGVpZ2h0JywgJ0FTQyddXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKHJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjaGFubmVsKHMpIGZvdW5kIHdpdGggdGhhdCBjaGFubmVsIG5hbWUnKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJldHVyblNob3J0SWQocmVzdWx0LCBsb25nQ2hhbm5lbElkKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIENlcnRpZmljYXRlLmdldExvbmdDaGFubmVsSWRGcm9tU2hvcnRDaGFubmVsSWQgPSBmdW5jdGlvbiAoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBnZXRMb25nQ2hhbm5lbElkRnJvbVNob3J0Q2hhbm5lbElkKCR7Y2hhbm5lbE5hbWV9LCAke2NoYW5uZWxDbGFpbUlkfSlgKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpc1xuICAgICAgICAuZmluZEFsbCh7XG4gICAgICAgICAgd2hlcmU6IHtcbiAgICAgICAgICAgIG5hbWUgICA6IGNoYW5uZWxOYW1lLFxuICAgICAgICAgICAgY2xhaW1JZDoge1xuICAgICAgICAgICAgICAkbGlrZTogYCR7Y2hhbm5lbENsYWltSWR9JWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgb3JkZXI6IFtbJ2hlaWdodCcsICdBU0MnXV0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgc3dpdGNoIChyZXN1bHQubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgZGVmYXVsdDogLy8gbm90ZSByZXN1bHRzIG11c3QgYmUgc29ydGVkXG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc3VsdFswXS5jbGFpbUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2VydGlmaWNhdGUuZ2V0TG9uZ0NoYW5uZWxJZEZyb21DaGFubmVsTmFtZSA9IGZ1bmN0aW9uIChjaGFubmVsTmFtZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgZ2V0TG9uZ0NoYW5uZWxJZEZyb21DaGFubmVsTmFtZSgke2NoYW5uZWxOYW1lfSlgKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpc1xuICAgICAgICAuZmluZEFsbCh7XG4gICAgICAgICAgd2hlcmU6IHsgbmFtZTogY2hhbm5lbE5hbWUgfSxcbiAgICAgICAgICBvcmRlcjogW1snZWZmZWN0aXZlQW1vdW50JywgJ0RFU0MnXSwgWydoZWlnaHQnLCAnQVNDJ11dLFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIHN3aXRjaCAocmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc3VsdFswXS5jbGFpbUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2VydGlmaWNhdGUudmFsaWRhdGVMb25nQ2hhbm5lbElkID0gZnVuY3Rpb24gKG5hbWUsIGNsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYHZhbGlkYXRlTG9uZ0NoYW5uZWxJZCgke25hbWV9LCAke2NsYWltSWR9KWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLmZpbmRPbmUoe1xuICAgICAgICB3aGVyZToge25hbWUsIGNsYWltSWR9LFxuICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXNvbHZlKGNsYWltSWQpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIENlcnRpZmljYXRlLmdldExvbmdDaGFubmVsSWQgPSBmdW5jdGlvbiAoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBnZXRMb25nQ2hhbm5lbElkKCR7Y2hhbm5lbE5hbWV9LCAke2NoYW5uZWxDbGFpbUlkfSlgKTtcbiAgICBpZiAoY2hhbm5lbENsYWltSWQgJiYgKGNoYW5uZWxDbGFpbUlkLmxlbmd0aCA9PT0gNDApKSB7ICAvLyBpZiBhIGZ1bGwgY2hhbm5lbCBpZCBpcyBwcm92aWRlZFxuICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVMb25nQ2hhbm5lbElkKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCk7XG4gICAgfSBlbHNlIGlmIChjaGFubmVsQ2xhaW1JZCAmJiBjaGFubmVsQ2xhaW1JZC5sZW5ndGggPCA0MCkgeyAgLy8gaWYgYSBzaG9ydCBjaGFubmVsIGlkIGlzIHByb3ZpZGVkXG4gICAgICByZXR1cm4gdGhpcy5nZXRMb25nQ2hhbm5lbElkRnJvbVNob3J0Q2hhbm5lbElkKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmdldExvbmdDaGFubmVsSWRGcm9tQ2hhbm5lbE5hbWUoY2hhbm5lbE5hbWUpOyAgLy8gaWYgbm8gY2hhbm5lbCBpZCBwcm92aWRlZFxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gQ2VydGlmaWNhdGU7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21vZGVscy9jZXJ0aWZpY2F0ZS5qcyIsIm1vZHVsZS5leHBvcnRzID0gKHNlcXVlbGl6ZSwgeyBTVFJJTkcgfSkgPT4ge1xuICBjb25zdCBDaGFubmVsID0gc2VxdWVsaXplLmRlZmluZShcbiAgICAnQ2hhbm5lbCcsXG4gICAge1xuICAgICAgY2hhbm5lbE5hbWU6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgICAgY2hhbm5lbENsYWltSWQ6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgZnJlZXplVGFibGVOYW1lOiB0cnVlLFxuICAgIH1cbiAgKTtcblxuICBDaGFubmVsLmFzc29jaWF0ZSA9IGRiID0+IHtcbiAgICBDaGFubmVsLmJlbG9uZ3NUbyhkYi5Vc2VyKTtcbiAgICBDaGFubmVsLmhhc09uZShkYi5DZXJ0aWZpY2F0ZSk7XG4gIH07XG5cbiAgcmV0dXJuIENoYW5uZWw7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21vZGVscy9jaGFubmVsLmpzIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgeyByZXR1cm5TaG9ydElkIH0gPSByZXF1aXJlKCcuLi9oZWxwZXJzL3NlcXVlbGl6ZUhlbHBlcnMuanMnKTtcbmNvbnN0IHsgYXNzZXREZWZhdWx0czogeyB0aHVtYm5haWw6IGRlZmF1bHRUaHVtYm5haWwgfSwgZGV0YWlsczogeyBob3N0IH0gfSA9IHJlcXVpcmUoJy4uLy4uL2NvbmZpZy9zaXRlQ29uZmlnLmpzJyk7XG5cbmZ1bmN0aW9uIGRldGVybWluZUZpbGVFeHRlbnNpb25Gcm9tQ29udGVudFR5cGUgKGNvbnRlbnRUeXBlKSB7XG4gIHN3aXRjaCAoY29udGVudFR5cGUpIHtcbiAgICBjYXNlICdpbWFnZS9qcGVnJzpcbiAgICBjYXNlICdpbWFnZS9qcGcnOlxuICAgICAgcmV0dXJuICdqcGVnJztcbiAgICBjYXNlICdpbWFnZS9wbmcnOlxuICAgICAgcmV0dXJuICdwbmcnO1xuICAgIGNhc2UgJ2ltYWdlL2dpZic6XG4gICAgICByZXR1cm4gJ2dpZic7XG4gICAgY2FzZSAndmlkZW8vbXA0JzpcbiAgICAgIHJldHVybiAnbXA0JztcbiAgICBkZWZhdWx0OlxuICAgICAgbG9nZ2VyLmRlYnVnKCdzZXR0aW5nIHVua25vd24gZmlsZSB0eXBlIGFzIGZpbGUgZXh0ZW5zaW9uIGpwZWcnKTtcbiAgICAgIHJldHVybiAnanBlZyc7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGRldGVybWluZVRodW1ibmFpbCAoc3RvcmVkVGh1bWJuYWlsLCBkZWZhdWx0VGh1bWJuYWlsKSB7XG4gIGlmIChzdG9yZWRUaHVtYm5haWwgPT09ICcnKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRUaHVtYm5haWw7XG4gIH1cbiAgcmV0dXJuIHN0b3JlZFRodW1ibmFpbDtcbn07XG5cbmZ1bmN0aW9uIHByZXBhcmVDbGFpbURhdGEgKGNsYWltKSB7XG4gIC8vIGxvZ2dlci5kZWJ1ZygncHJlcGFyaW5nIGNsYWltIGRhdGEgYmFzZWQgb24gcmVzb2x2ZWQgZGF0YTonLCBjbGFpbSk7XG4gIGNsYWltWyd0aHVtYm5haWwnXSA9IGRldGVybWluZVRodW1ibmFpbChjbGFpbS50aHVtYm5haWwsIGRlZmF1bHRUaHVtYm5haWwpO1xuICBjbGFpbVsnZmlsZUV4dCddID0gZGV0ZXJtaW5lRmlsZUV4dGVuc2lvbkZyb21Db250ZW50VHlwZShjbGFpbS5jb250ZW50VHlwZSk7XG4gIGNsYWltWydob3N0J10gPSBob3N0O1xuICByZXR1cm4gY2xhaW07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IChzZXF1ZWxpemUsIHsgU1RSSU5HLCBCT09MRUFOLCBJTlRFR0VSLCBURVhULCBERUNJTUFMIH0pID0+IHtcbiAgY29uc3QgQ2xhaW0gPSBzZXF1ZWxpemUuZGVmaW5lKFxuICAgICdDbGFpbScsXG4gICAge1xuICAgICAgYWRkcmVzczoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgYW1vdW50OiB7XG4gICAgICAgIHR5cGUgICA6IERFQ0lNQUwoMTksIDgpLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGNsYWltSWQ6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGNsYWltU2VxdWVuY2U6IHtcbiAgICAgICAgdHlwZSAgIDogSU5URUdFUixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBkZWNvZGVkQ2xhaW06IHtcbiAgICAgICAgdHlwZSAgIDogQk9PTEVBTixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBkZXB0aDoge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGVmZmVjdGl2ZUFtb3VudDoge1xuICAgICAgICB0eXBlICAgOiBERUNJTUFMKDE5LCA4KSxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBoYXNTaWduYXR1cmU6IHtcbiAgICAgICAgdHlwZSAgIDogQk9PTEVBTixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBoZWlnaHQ6IHtcbiAgICAgICAgdHlwZSAgIDogSU5URUdFUixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBoZXg6IHtcbiAgICAgICAgdHlwZSAgIDogVEVYVCgnbG9uZycpLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIG5hbWU6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIG5vdXQ6IHtcbiAgICAgICAgdHlwZSAgIDogSU5URUdFUixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICB0eGlkOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICB2YWxpZEF0SGVpZ2h0OiB7XG4gICAgICAgIHR5cGUgICA6IElOVEVHRVIsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgb3V0cG9pbnQ6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGNsYWltVHlwZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2VydGlmaWNhdGVJZDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgYXV0aG9yOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBkZXNjcmlwdGlvbjoge1xuICAgICAgICB0eXBlICAgOiBURVhUKCdsb25nJyksXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbGFuZ3VhZ2U6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGxpY2Vuc2U6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGxpY2Vuc2VVcmw6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIG5zZnc6IHtcbiAgICAgICAgdHlwZSAgIDogQk9PTEVBTixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBwcmV2aWV3OiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICB0aHVtYm5haWw6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHRpdGxlOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBtZXRhZGF0YVZlcnNpb246IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGNvbnRlbnRUeXBlOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBzb3VyY2U6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHNvdXJjZVR5cGU6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHNvdXJjZVZlcnNpb246IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHN0cmVhbVZlcnNpb246IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHZhbHVlVmVyc2lvbjoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2hhbm5lbE5hbWU6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogdHJ1ZSxcbiAgICAgICAgZGVmYXVsdCAgOiBudWxsLFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGZyZWV6ZVRhYmxlTmFtZTogdHJ1ZSxcbiAgICB9XG4gICk7XG5cbiAgQ2xhaW0uYXNzb2NpYXRlID0gZGIgPT4ge1xuICAgIENsYWltLmJlbG9uZ3NUbyhkYi5GaWxlLCB7XG4gICAgICBmb3JlaWduS2V5OiB7XG4gICAgICAgIGFsbG93TnVsbDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH07XG5cbiAgQ2xhaW0uZ2V0U2hvcnRDbGFpbUlkRnJvbUxvbmdDbGFpbUlkID0gZnVuY3Rpb24gKGNsYWltSWQsIGNsYWltTmFtZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgQ2xhaW0uZ2V0U2hvcnRDbGFpbUlkRnJvbUxvbmdDbGFpbUlkIGZvciAke2NsYWltTmFtZX0jJHtjbGFpbUlkfWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZTogeyBuYW1lOiBjbGFpbU5hbWUgfSxcbiAgICAgICAgICBvcmRlcjogW1snaGVpZ2h0JywgJ0FTQyddXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKHJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjbGFpbShzKSBmb3VuZCB3aXRoIHRoYXQgY2xhaW0gbmFtZScpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXR1cm5TaG9ydElkKHJlc3VsdCwgY2xhaW1JZCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBDbGFpbS5nZXRBbGxDaGFubmVsQ2xhaW1zID0gZnVuY3Rpb24gKGNoYW5uZWxDbGFpbUlkKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBDbGFpbS5nZXRBbGxDaGFubmVsQ2xhaW1zIGZvciAke2NoYW5uZWxDbGFpbUlkfWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZTogeyBjZXJ0aWZpY2F0ZUlkOiBjaGFubmVsQ2xhaW1JZCB9LFxuICAgICAgICAgIG9yZGVyOiBbWydoZWlnaHQnLCAnQVNDJ11dLFxuICAgICAgICAgIHJhdyAgOiB0cnVlLCAgLy8gcmV0dXJucyBhbiBhcnJheSBvZiBvbmx5IGRhdGEsIG5vdCBhbiBhcnJheSBvZiBpbnN0YW5jZXNcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oY2hhbm5lbENsYWltc0FycmF5ID0+IHtcbiAgICAgICAgICAvLyBsb2dnZXIuZGVidWcoJ2NoYW5uZWxjbGFpbXNhcnJheSBsZW5ndGg6JywgY2hhbm5lbENsYWltc0FycmF5Lmxlbmd0aCk7XG4gICAgICAgICAgc3dpdGNoIChjaGFubmVsQ2xhaW1zQXJyYXkubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgY2hhbm5lbENsYWltc0FycmF5LmZvckVhY2goY2xhaW0gPT4ge1xuICAgICAgICAgICAgICAgIGNsYWltWydmaWxlRXh0J10gPSBkZXRlcm1pbmVGaWxlRXh0ZW5zaW9uRnJvbUNvbnRlbnRUeXBlKGNsYWltLmNvbnRlbnRUeXBlKTtcbiAgICAgICAgICAgICAgICBjbGFpbVsndGh1bWJuYWlsJ10gPSBkZXRlcm1pbmVUaHVtYm5haWwoY2xhaW0udGh1bWJuYWlsLCBkZWZhdWx0VGh1bWJuYWlsKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xhaW07XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShjaGFubmVsQ2xhaW1zQXJyYXkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBDbGFpbS5nZXRDbGFpbUlkQnlMb25nQ2hhbm5lbElkID0gZnVuY3Rpb24gKGNoYW5uZWxDbGFpbUlkLCBjbGFpbU5hbWUpIHtcbiAgICBsb2dnZXIuZGVidWcoYGZpbmRpbmcgY2xhaW0gaWQgZm9yIGNsYWltICR7Y2xhaW1OYW1lfSBmcm9tIGNoYW5uZWwgJHtjaGFubmVsQ2xhaW1JZH1gKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpc1xuICAgICAgICAuZmluZEFsbCh7XG4gICAgICAgICAgd2hlcmU6IHsgbmFtZTogY2xhaW1OYW1lLCBjZXJ0aWZpY2F0ZUlkOiBjaGFubmVsQ2xhaW1JZCB9LFxuICAgICAgICAgIG9yZGVyOiBbWydpZCcsICdBU0MnXV0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgc3dpdGNoIChyZXN1bHQubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXN1bHRbMF0uY2xhaW1JZCk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoYCR7cmVzdWx0Lmxlbmd0aH0gcmVjb3JkcyBmb3VuZCBmb3IgXCIke2NsYWltTmFtZX1cIiBpbiBjaGFubmVsIFwiJHtjaGFubmVsQ2xhaW1JZH1cImApO1xuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXN1bHRbMF0uY2xhaW1JZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIENsYWltLmdldExvbmdDbGFpbUlkRnJvbVNob3J0Q2xhaW1JZCA9IGZ1bmN0aW9uIChuYW1lLCBzaG9ydElkKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXNcbiAgICAgICAgLmZpbmRBbGwoe1xuICAgICAgICAgIHdoZXJlOiB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgY2xhaW1JZDoge1xuICAgICAgICAgICAgICAkbGlrZTogYCR7c2hvcnRJZH0lYCxcbiAgICAgICAgICAgIH19LFxuICAgICAgICAgIG9yZGVyOiBbWydoZWlnaHQnLCAnQVNDJ11dLFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIHN3aXRjaCAocmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6IC8vIG5vdGUgcmVzdWx0cyBtdXN0IGJlIHNvcnRlZFxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXN1bHRbMF0uY2xhaW1JZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIENsYWltLmdldFRvcEZyZWVDbGFpbUlkQnlDbGFpbU5hbWUgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZTogeyBuYW1lIH0sXG4gICAgICAgICAgb3JkZXI6IFtbJ2VmZmVjdGl2ZUFtb3VudCcsICdERVNDJ10sIFsnaGVpZ2h0JywgJ0FTQyddXSwgIC8vIG5vdGU6IG1heWJlIGhlaWdodCBhbmQgZWZmZWN0aXZlIGFtb3VudCBuZWVkIHRvIHN3aXRjaD9cbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoJ2xlbmd0aCBvZiByZXN1bHQnLCByZXN1bHQubGVuZ3RoKTtcbiAgICAgICAgICBzd2l0Y2ggKHJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShyZXN1bHRbMF0uZGF0YVZhbHVlcy5jbGFpbUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2xhaW0udmFsaWRhdGVMb25nQ2xhaW1JZCA9IGZ1bmN0aW9uIChuYW1lLCBjbGFpbUlkKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZmluZE9uZSh7XG4gICAgICAgIHdoZXJlOiB7bmFtZSwgY2xhaW1JZH0sXG4gICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIGlmICghcmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJlc29sdmUoY2xhaW1JZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2xhaW0uZ2V0TG9uZ0NsYWltSWQgPSBmdW5jdGlvbiAoY2xhaW1OYW1lLCBjbGFpbUlkKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBnZXRMb25nQ2xhaW1JZCgke2NsYWltTmFtZX0sICR7Y2xhaW1JZH0pYCk7XG4gICAgaWYgKGNsYWltSWQgJiYgKGNsYWltSWQubGVuZ3RoID09PSA0MCkpIHsgIC8vIGlmIGEgZnVsbCBjbGFpbSBpZCBpcyBwcm92aWRlZFxuICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVMb25nQ2xhaW1JZChjbGFpbU5hbWUsIGNsYWltSWQpO1xuICAgIH0gZWxzZSBpZiAoY2xhaW1JZCAmJiBjbGFpbUlkLmxlbmd0aCA8IDQwKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRMb25nQ2xhaW1JZEZyb21TaG9ydENsYWltSWQoY2xhaW1OYW1lLCBjbGFpbUlkKTsgIC8vIGlmIGEgc2hvcnQgY2xhaW0gaWQgaXMgcHJvdmlkZWRcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VG9wRnJlZUNsYWltSWRCeUNsYWltTmFtZShjbGFpbU5hbWUpOyAgLy8gaWYgbm8gY2xhaW0gaWQgaXMgcHJvdmlkZWRcbiAgICB9XG4gIH07XG5cbiAgQ2xhaW0ucmVzb2x2ZUNsYWltID0gZnVuY3Rpb24gKG5hbWUsIGNsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYENsYWltLnJlc29sdmVDbGFpbTogJHtuYW1lfSAke2NsYWltSWR9YCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXNcbiAgICAgICAgLmZpbmRBbGwoe1xuICAgICAgICAgIHdoZXJlOiB7IG5hbWUsIGNsYWltSWQgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oY2xhaW1BcnJheSA9PiB7XG4gICAgICAgICAgc3dpdGNoIChjbGFpbUFycmF5Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocHJlcGFyZUNsYWltRGF0YShjbGFpbUFycmF5WzBdLmRhdGFWYWx1ZXMpKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgbW9yZSB0aGFuIG9uZSByZWNvcmQgbWF0Y2hlcyAke25hbWV9IyR7Y2xhaW1JZH0gaW4gZGIuQ2xhaW1gKTtcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocHJlcGFyZUNsYWltRGF0YShjbGFpbUFycmF5WzBdLmRhdGFWYWx1ZXMpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIENsYWltO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9tb2RlbHMvY2xhaW0uanMiLCJtb2R1bGUuZXhwb3J0cyA9IChzZXF1ZWxpemUsIHsgU1RSSU5HLCBCT09MRUFOLCBJTlRFR0VSIH0pID0+IHtcbiAgY29uc3QgRmlsZSA9IHNlcXVlbGl6ZS5kZWZpbmUoXG4gICAgJ0ZpbGUnLFxuICAgIHtcbiAgICAgIG5hbWU6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgICAgY2xhaW1JZDoge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBhZGRyZXNzOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIG91dHBvaW50OiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIGhlaWdodDoge1xuICAgICAgICB0eXBlICAgICA6IElOVEVHRVIsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICAgIGRlZmF1bHQgIDogMCxcbiAgICAgIH0sXG4gICAgICBmaWxlTmFtZToge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBmaWxlUGF0aDoge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBmaWxlVHlwZToge1xuICAgICAgICB0eXBlOiBTVFJJTkcsXG4gICAgICB9LFxuICAgICAgbnNmdzoge1xuICAgICAgICB0eXBlICAgICAgICA6IEJPT0xFQU4sXG4gICAgICAgIGFsbG93TnVsbCAgIDogZmFsc2UsXG4gICAgICAgIGRlZmF1bHRWYWx1ZTogZmFsc2UsXG4gICAgICB9LFxuICAgICAgdHJlbmRpbmdFbGlnaWJsZToge1xuICAgICAgICB0eXBlICAgICAgICA6IEJPT0xFQU4sXG4gICAgICAgIGFsbG93TnVsbCAgIDogZmFsc2UsXG4gICAgICAgIGRlZmF1bHRWYWx1ZTogdHJ1ZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICB7XG4gICAgICBmcmVlemVUYWJsZU5hbWU6IHRydWUsXG4gICAgfVxuICApO1xuXG4gIEZpbGUuYXNzb2NpYXRlID0gZGIgPT4ge1xuICAgIEZpbGUuaGFzTWFueShkYi5SZXF1ZXN0KTtcbiAgICBGaWxlLmhhc09uZShkYi5DbGFpbSk7XG4gIH07XG5cbiAgRmlsZS5nZXRSZWNlbnRDbGFpbXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmluZEFsbCh7XG4gICAgICB3aGVyZTogeyBuc2Z3OiBmYWxzZSwgdHJlbmRpbmdFbGlnaWJsZTogdHJ1ZSB9LFxuICAgICAgb3JkZXI6IFtbJ2NyZWF0ZWRBdCcsICdERVNDJ11dLFxuICAgICAgbGltaXQ6IDI1LFxuICAgIH0pO1xuICB9O1xuXG4gIHJldHVybiBGaWxlO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9tb2RlbHMvZmlsZS5qcyIsIm1vZHVsZS5leHBvcnRzID0gKHNlcXVlbGl6ZSwgeyBTVFJJTkcsIEJPT0xFQU4sIFRFWFQgfSkgPT4ge1xuICBjb25zdCBSZXF1ZXN0ID0gc2VxdWVsaXplLmRlZmluZShcbiAgICAnUmVxdWVzdCcsXG4gICAge1xuICAgICAgYWN0aW9uOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIHVybDoge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBpcEFkZHJlc3M6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgICByZXN1bHQ6IHtcbiAgICAgICAgdHlwZSAgICAgOiBURVhUKCdsb25nJyksXG4gICAgICAgIGFsbG93TnVsbDogdHJ1ZSxcbiAgICAgICAgZGVmYXVsdCAgOiBudWxsLFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGZyZWV6ZVRhYmxlTmFtZTogdHJ1ZSxcbiAgICB9XG4gICk7XG5cbiAgUmVxdWVzdC5hc3NvY2lhdGUgPSBkYiA9PiB7XG4gICAgUmVxdWVzdC5iZWxvbmdzVG8oZGIuRmlsZSwge1xuICAgICAgZm9yZWlnbktleToge1xuICAgICAgICBhbGxvd051bGw6IHRydWUsXG4gICAgICB9LFxuICAgIH0pO1xuICB9O1xuXG4gIHJldHVybiBSZXF1ZXN0O1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9tb2RlbHMvcmVxdWVzdC5qcyIsIid1c2Ugc3RyaWN0JztcbmNvbnN0IGJjcnlwdCA9IHJlcXVpcmUoJ2JjcnlwdCcpO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IChzZXF1ZWxpemUsIHsgU1RSSU5HIH0pID0+IHtcbiAgY29uc3QgVXNlciA9IHNlcXVlbGl6ZS5kZWZpbmUoXG4gICAgJ1VzZXInLFxuICAgIHtcbiAgICAgIHVzZXJOYW1lOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIHBhc3N3b3JkOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGZyZWV6ZVRhYmxlTmFtZTogdHJ1ZSxcbiAgICB9XG4gICk7XG5cbiAgVXNlci5hc3NvY2lhdGUgPSBkYiA9PiB7XG4gICAgVXNlci5oYXNPbmUoZGIuQ2hhbm5lbCk7XG4gIH07XG5cbiAgVXNlci5wcm90b3R5cGUuY29tcGFyZVBhc3N3b3JkID0gZnVuY3Rpb24gKHBhc3N3b3JkKSB7XG4gICAgcmV0dXJuIGJjcnlwdC5jb21wYXJlKHBhc3N3b3JkLCB0aGlzLnBhc3N3b3JkKTtcbiAgfTtcblxuICBVc2VyLnByb3RvdHlwZS5jaGFuZ2VQYXNzd29yZCA9IGZ1bmN0aW9uIChuZXdQYXNzd29yZCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBnZW5lcmF0ZSBhIHNhbHQgc3RyaW5nIHRvIHVzZSBmb3IgaGFzaGluZ1xuICAgICAgYmNyeXB0LmdlblNhbHQoKHNhbHRFcnJvciwgc2FsdCkgPT4ge1xuICAgICAgICBpZiAoc2FsdEVycm9yKSB7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKCdzYWx0IGVycm9yJywgc2FsdEVycm9yKTtcbiAgICAgICAgICByZWplY3Qoc2FsdEVycm9yKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gZ2VuZXJhdGUgYSBoYXNoZWQgdmVyc2lvbiBvZiB0aGUgdXNlcidzIHBhc3N3b3JkXG4gICAgICAgIGJjcnlwdC5oYXNoKG5ld1Bhc3N3b3JkLCBzYWx0LCAoaGFzaEVycm9yLCBoYXNoKSA9PiB7XG4gICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYW4gZXJyb3Igd2l0aCB0aGUgaGFzaCBnZW5lcmF0aW9uIHJldHVybiB0aGUgZXJyb3JcbiAgICAgICAgICBpZiAoaGFzaEVycm9yKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ2hhc2ggZXJyb3InLCBoYXNoRXJyb3IpO1xuICAgICAgICAgICAgcmVqZWN0KGhhc2hFcnJvcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIHJlcGxhY2UgdGhlIGN1cnJlbnQgcGFzc3dvcmQgd2l0aCB0aGUgbmV3IGhhc2hcbiAgICAgICAgICB0aGlzXG4gICAgICAgICAgICAudXBkYXRlKHtwYXNzd29yZDogaGFzaH0pXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gcHJlLXNhdmUgaG9vayBtZXRob2QgdG8gaGFzaCB0aGUgdXNlcidzIHBhc3N3b3JkIGJlZm9yZSB0aGUgdXNlcidzIGluZm8gaXMgc2F2ZWQgdG8gdGhlIGRiLlxuICBVc2VyLmhvb2soJ2JlZm9yZUNyZWF0ZScsICh1c2VyLCBvcHRpb25zKSA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKCdVc2VyLmJlZm9yZUNyZWF0ZSBob29rLi4uJyk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIGdlbmVyYXRlIGEgc2FsdCBzdHJpbmcgdG8gdXNlIGZvciBoYXNoaW5nXG4gICAgICBiY3J5cHQuZ2VuU2FsdCgoc2FsdEVycm9yLCBzYWx0KSA9PiB7XG4gICAgICAgIGlmIChzYWx0RXJyb3IpIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ3NhbHQgZXJyb3InLCBzYWx0RXJyb3IpO1xuICAgICAgICAgIHJlamVjdChzYWx0RXJyb3IpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBnZW5lcmF0ZSBhIGhhc2hlZCB2ZXJzaW9uIG9mIHRoZSB1c2VyJ3MgcGFzc3dvcmRcbiAgICAgICAgYmNyeXB0Lmhhc2godXNlci5wYXNzd29yZCwgc2FsdCwgKGhhc2hFcnJvciwgaGFzaCkgPT4ge1xuICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIGFuIGVycm9yIHdpdGggdGhlIGhhc2ggZ2VuZXJhdGlvbiByZXR1cm4gdGhlIGVycm9yXG4gICAgICAgICAgaWYgKGhhc2hFcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdoYXNoIGVycm9yJywgaGFzaEVycm9yKTtcbiAgICAgICAgICAgIHJlamVjdChoYXNoRXJyb3IpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyByZXBsYWNlIHRoZSBwYXNzd29yZCBzdHJpbmcgd2l0aCB0aGUgaGFzaCBwYXNzd29yZCB2YWx1ZVxuICAgICAgICAgIHVzZXIucGFzc3dvcmQgPSBoYXNoO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIFVzZXI7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21vZGVscy91c2VyLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiYmNyeXB0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiYmNyeXB0XCJcbi8vIG1vZHVsZSBpZCA9IDUxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImNvbnN0IFBhc3Nwb3J0TG9jYWxTdHJhdGVneSA9IHJlcXVpcmUoJ3Bhc3Nwb3J0LWxvY2FsJykuU3RyYXRlZ3k7XG5jb25zdCBsYnJ5QXBpID0gcmVxdWlyZSgnLi4vaGVscGVycy9sYnJ5QXBpLmpzJyk7XG5jb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5jb25zdCBkYiA9IHJlcXVpcmUoJ21vZGVscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBQYXNzcG9ydExvY2FsU3RyYXRlZ3koXG4gIHtcbiAgICB1c2VybmFtZUZpZWxkOiAndXNlcm5hbWUnLFxuICAgIHBhc3N3b3JkRmllbGQ6ICdwYXNzd29yZCcsXG4gIH0sXG4gICh1c2VybmFtZSwgcGFzc3dvcmQsIGRvbmUpID0+IHtcbiAgICBsb2dnZXIudmVyYm9zZShgbmV3IGNoYW5uZWwgc2lnbnVwIHJlcXVlc3QuIHVzZXI6ICR7dXNlcm5hbWV9IHBhc3M6ICR7cGFzc3dvcmR9IC5gKTtcbiAgICBsZXQgdXNlckluZm8gPSB7fTtcbiAgICAvLyBzZXJ2ZXItc2lkZSB2YWxpZGF0b24gb2YgaW5wdXRzICh1c2VybmFtZSwgcGFzc3dvcmQpXG5cbiAgICAvLyBjcmVhdGUgdGhlIGNoYW5uZWwgYW5kIHJldHJpZXZlIHRoZSBtZXRhZGF0YVxuICAgIHJldHVybiBsYnJ5QXBpLmNyZWF0ZUNoYW5uZWwoYEAke3VzZXJuYW1lfWApXG4gICAgICAudGhlbih0eCA9PiB7XG4gICAgICAgIC8vIGNyZWF0ZSB1c2VyIHJlY29yZFxuICAgICAgICBjb25zdCB1c2VyRGF0YSA9IHtcbiAgICAgICAgICB1c2VyTmFtZTogdXNlcm5hbWUsXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhc3N3b3JkLFxuICAgICAgICB9O1xuICAgICAgICBsb2dnZXIudmVyYm9zZSgndXNlckRhdGEgPicsIHVzZXJEYXRhKTtcbiAgICAgICAgLy8gY3JlYXRlIHVzZXIgcmVjb3JkXG4gICAgICAgIGNvbnN0IGNoYW5uZWxEYXRhID0ge1xuICAgICAgICAgIGNoYW5uZWxOYW1lICAgOiBgQCR7dXNlcm5hbWV9YCxcbiAgICAgICAgICBjaGFubmVsQ2xhaW1JZDogdHguY2xhaW1faWQsXG4gICAgICAgIH07XG4gICAgICAgIGxvZ2dlci52ZXJib3NlKCdjaGFubmVsRGF0YSA+JywgY2hhbm5lbERhdGEpO1xuICAgICAgICAvLyBjcmVhdGUgY2VydGlmaWNhdGUgcmVjb3JkXG4gICAgICAgIGNvbnN0IGNlcnRpZmljYXRlRGF0YSA9IHtcbiAgICAgICAgICBjbGFpbUlkOiB0eC5jbGFpbV9pZCxcbiAgICAgICAgICBuYW1lICAgOiBgQCR7dXNlcm5hbWV9YCxcbiAgICAgICAgICAvLyBhZGRyZXNzLFxuICAgICAgICB9O1xuICAgICAgICBsb2dnZXIudmVyYm9zZSgnY2VydGlmaWNhdGVEYXRhID4nLCBjZXJ0aWZpY2F0ZURhdGEpO1xuICAgICAgICAvLyBzYXZlIHVzZXIgYW5kIGNlcnRpZmljYXRlIHRvIGRiXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbZGIuVXNlci5jcmVhdGUodXNlckRhdGEpLCBkYi5DaGFubmVsLmNyZWF0ZShjaGFubmVsRGF0YSksIGRiLkNlcnRpZmljYXRlLmNyZWF0ZShjZXJ0aWZpY2F0ZURhdGEpXSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKFtuZXdVc2VyLCBuZXdDaGFubmVsLCBuZXdDZXJ0aWZpY2F0ZV0pID0+IHtcbiAgICAgICAgbG9nZ2VyLnZlcmJvc2UoJ3VzZXIgYW5kIGNlcnRpZmljYXRlIHN1Y2Nlc3NmdWxseSBjcmVhdGVkJyk7XG4gICAgICAgIC8vIHN0b3JlIHRoZSByZWxldmFudCBuZXdVc2VyIGluZm8gdG8gYmUgcGFzc2VkIGJhY2sgZm9yIHJlcS5Vc2VyXG4gICAgICAgIHVzZXJJbmZvWydpZCddID0gbmV3VXNlci5pZDtcbiAgICAgICAgdXNlckluZm9bJ3VzZXJOYW1lJ10gPSBuZXdVc2VyLnVzZXJOYW1lO1xuICAgICAgICB1c2VySW5mb1snY2hhbm5lbE5hbWUnXSA9IG5ld0NoYW5uZWwuY2hhbm5lbE5hbWU7XG4gICAgICAgIHVzZXJJbmZvWydjaGFubmVsQ2xhaW1JZCddID0gbmV3Q2hhbm5lbC5jaGFubmVsQ2xhaW1JZDtcbiAgICAgICAgLy8gYXNzb2NpYXRlIHRoZSBpbnN0YW5jZXNcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtuZXdDZXJ0aWZpY2F0ZS5zZXRDaGFubmVsKG5ld0NoYW5uZWwpLCBuZXdDaGFubmVsLnNldFVzZXIobmV3VXNlcildKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGxvZ2dlci52ZXJib3NlKCd1c2VyIGFuZCBjZXJ0aWZpY2F0ZSBzdWNjZXNzZnVsbHkgYXNzb2NpYXRlZCcpO1xuICAgICAgICByZXR1cm4gZGIuQ2VydGlmaWNhdGUuZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZCh1c2VySW5mby5jaGFubmVsQ2xhaW1JZCwgdXNlckluZm8uY2hhbm5lbE5hbWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHNob3J0Q2hhbm5lbElkID0+IHtcbiAgICAgICAgdXNlckluZm9bJ3Nob3J0Q2hhbm5lbElkJ10gPSBzaG9ydENoYW5uZWxJZDtcbiAgICAgICAgcmV0dXJuIGRvbmUobnVsbCwgdXNlckluZm8pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGxvZ2dlci5lcnJvcignc2lnbnVwIGVycm9yJywgZXJyb3IpO1xuICAgICAgICByZXR1cm4gZG9uZShlcnJvcik7XG4gICAgICB9KTtcbiAgfVxuKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9sb2NhbC1zaWdudXAuanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJheGlvc1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImF4aW9zXCJcbi8vIG1vZHVsZSBpZCA9IDUzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImNvbnN0IGxicnlDb25maWcgPSB7XG4gIGFwaToge1xuICAgIGFwaUhvc3Q6ICdsb2NhbGhvc3QnLFxuICAgIGFwaVBvcnQ6ICc1Mjc5JyxcbiAgfSxcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gbGJyeUNvbmZpZztcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL2NvbmZpZy9sYnJ5Q29uZmlnLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwidW5pdmVyc2FsLWFuYWx5dGljc1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInVuaXZlcnNhbC1hbmFseXRpY3NcIlxuLy8gbW9kdWxlIGlkID0gNTVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNlcmlhbGl6ZVNwZWVjaFVzZXIgKHVzZXIsIGRvbmUpIHsgIC8vIHJldHVybnMgdXNlciBkYXRhIHRvIGJlIHNlcmlhbGl6ZWQgaW50byBzZXNzaW9uXG4gICAgY29uc29sZS5sb2coJ3NlcmlhbGl6aW5nIHVzZXInKTtcbiAgICBkb25lKG51bGwsIHVzZXIpO1xuICB9LFxuICBkZXNlcmlhbGl6ZVNwZWVjaFVzZXIgKHVzZXIsIGRvbmUpIHsgIC8vIGRlc2VyaWFsaXplcyBzZXNzaW9uIGFuZCBwb3B1bGF0ZXMgYWRkaXRpb25hbCBpbmZvIHRvIHJlcS51c2VyXG4gICAgY29uc29sZS5sb2coJ2Rlc2VyaWFsaXppbmcgdXNlcicpO1xuICAgIGRvbmUobnVsbCwgdXNlcik7XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvYXV0aEhlbHBlcnMuanMiLCJjb25zdCBzcGVlY2hQYXNzcG9ydCA9IHJlcXVpcmUoJ3NwZWVjaFBhc3Nwb3J0Jyk7XG5jb25zdCBoYW5kbGVTaWdudXBSZXF1ZXN0ID0gcmVxdWlyZSgnLi9zaWdudXAnKTtcbmNvbnN0IGhhbmRsZUxvZ2luUmVxdWVzdCA9IHJlcXVpcmUoJy4vbG9naW4nKTtcbmNvbnN0IGhhbmRsZUxvZ291dFJlcXVlc3QgPSByZXF1aXJlKCcuL2xvZ291dCcpO1xuY29uc3QgaGFuZGxlVXNlclJlcXVlc3QgPSByZXF1aXJlKCcuL3VzZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoYXBwKSA9PiB7XG4gIGFwcC5wb3N0KCcvc2lnbnVwJywgc3BlZWNoUGFzc3BvcnQuYXV0aGVudGljYXRlKCdsb2NhbC1zaWdudXAnKSwgaGFuZGxlU2lnbnVwUmVxdWVzdCk7XG4gIGFwcC5wb3N0KCcvbG9naW4nLCBoYW5kbGVMb2dpblJlcXVlc3QpO1xuICBhcHAuZ2V0KCcvbG9nb3V0JywgaGFuZGxlTG9nb3V0UmVxdWVzdCk7XG4gIGFwcC5nZXQoJy91c2VyJywgaGFuZGxlVXNlclJlcXVlc3QpO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXV0aC9pbmRleC5qcyIsImNvbnN0IHNpZ251cCA9IChyZXEsIHJlcykgPT4ge1xuICByZXMuc3RhdHVzKDIwMCkuanNvbih7XG4gICAgc3VjY2VzcyAgICAgICA6IHRydWUsXG4gICAgY2hhbm5lbE5hbWUgICA6IHJlcS51c2VyLmNoYW5uZWxOYW1lLFxuICAgIGNoYW5uZWxDbGFpbUlkOiByZXEudXNlci5jaGFubmVsQ2xhaW1JZCxcbiAgICBzaG9ydENoYW5uZWxJZDogcmVxLnVzZXIuc2hvcnRDaGFubmVsSWQsXG4gIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzaWdudXA7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2F1dGgvc2lnbnVwLmpzIiwiY29uc3Qgc3BlZWNoUGFzc3BvcnQgPSByZXF1aXJlKCdzcGVlY2hQYXNzcG9ydCcpO1xuXG5jb25zdCBsb2dpbiA9IChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICBzcGVlY2hQYXNzcG9ydC5hdXRoZW50aWNhdGUoJ2xvY2FsLWxvZ2luJywgKGVyciwgdXNlciwgaW5mbykgPT4ge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIHJldHVybiBuZXh0KGVycik7XG4gICAgfVxuICAgIGlmICghdXNlcikge1xuICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtcbiAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgIG1lc3NhZ2U6IGluZm8ubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXEubG9nSW4odXNlciwgKGVycikgPT4ge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICByZXR1cm4gbmV4dChlcnIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtcbiAgICAgICAgc3VjY2VzcyAgICAgICA6IHRydWUsXG4gICAgICAgIGNoYW5uZWxOYW1lICAgOiByZXEudXNlci5jaGFubmVsTmFtZSxcbiAgICAgICAgY2hhbm5lbENsYWltSWQ6IHJlcS51c2VyLmNoYW5uZWxDbGFpbUlkLFxuICAgICAgICBzaG9ydENoYW5uZWxJZDogcmVxLnVzZXIuc2hvcnRDaGFubmVsSWQsXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSkocmVxLCByZXMsIG5leHQpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBsb2dpbjtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXV0aC9sb2dpbi5qcyIsImNvbnN0IGxvZ291dCA9IChyZXEsIHJlcykgPT4ge1xuICByZXEubG9nb3V0KCk7XG4gIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBtZXNzYWdlOiAneW91IHN1Y2Nlc3NmdWxseSBsb2dnZWQgb3V0J30pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBsb2dvdXQ7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2F1dGgvbG9nb3V0LmpzIiwiY29uc3QgdXNlciA9IChyZXEsIHJlcykgPT4ge1xuICBpZiAocmVxLnVzZXIpIHtcbiAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZSwgZGF0YTogcmVxLnVzZXJ9KTtcbiAgfSBlbHNlIHtcbiAgICByZXMuc3RhdHVzKDQwMSkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICd1c2VyIGlzIG5vdCBsb2dnZWQgaW4nfSk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gdXNlcjtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXV0aC91c2VyLmpzIiwiY29uc3QgY2hhbm5lbEF2YWlsYWJpbGl0eSA9IHJlcXVpcmUoJy4vY2hhbm5lbEF2YWlsYWJpbGl0eScpO1xuY29uc3QgY2hhbm5lbENsYWltcyA9IHJlcXVpcmUoJy4vY2hhbm5lbENsYWltcycpO1xuY29uc3QgY2hhbm5lbERhdGEgPSByZXF1aXJlKCcuL2NoYW5uZWxEYXRhJyk7XG5jb25zdCBjaGFubmVsU2hvcnRJZCA9IHJlcXVpcmUoJy4vY2hhbm5lbFNob3J0SWQnKTtcbmNvbnN0IGNsYWltQXZhaWxhYmlsaXR5ID0gcmVxdWlyZSgnLi9jbGFpbUF2YWlsYWJpbGl0eScpO1xuY29uc3QgY2xhaW1EYXRhID0gcmVxdWlyZSgnLi9jbGFpbURhdGEnKTtcbmNvbnN0IGNsYWltR2V0ID0gcmVxdWlyZSgnLi9jbGFpbUdldCcpO1xuY29uc3QgY2xhaW1Mb25nSWQgPSByZXF1aXJlKCcuL2NsYWltTG9uZ0lkJyk7XG5jb25zdCBjbGFpbVB1Ymxpc2ggPSByZXF1aXJlKCcuL2NsYWltUHVibGlzaCcpO1xuY29uc3QgY2xhaW1SZXNvbHZlID0gcmVxdWlyZSgnLi9jbGFpbVJlc29sdmUnKTtcbmNvbnN0IGNsYWltU2hvcnRJZCA9IHJlcXVpcmUoJy4vY2xhaW1TaG9ydElkJyk7XG5jb25zdCBjbGFpbUxpc3QgPSByZXF1aXJlKCcuL2NsYWltTGlzdCcpO1xuY29uc3QgZmlsZUF2YWlsYWJpbGl0eSA9IHJlcXVpcmUoJy4vZmlsZUF2YWlsYWJpbGl0eScpO1xuXG5jb25zdCBtdWx0aXBhcnRNaWRkbGV3YXJlID0gcmVxdWlyZSgnaGVscGVycy9tdWx0aXBhcnRNaWRkbGV3YXJlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKGFwcCkgPT4ge1xuICAvLyBjaGFubmVsIHJvdXRlc1xuICBhcHAuZ2V0KCcvYXBpL2NoYW5uZWwvYXZhaWxhYmlsaXR5LzpuYW1lJywgY2hhbm5lbEF2YWlsYWJpbGl0eSk7XG4gIGFwcC5nZXQoJy9hcGkvY2hhbm5lbC9zaG9ydC1pZC86bG9uZ0lkLzpuYW1lJywgY2hhbm5lbFNob3J0SWQpO1xuICBhcHAuZ2V0KCcvYXBpL2NoYW5uZWwvZGF0YS86Y2hhbm5lbE5hbWUvOmNoYW5uZWxDbGFpbUlkJywgY2hhbm5lbERhdGEpO1xuICBhcHAuZ2V0KCcvYXBpL2NoYW5uZWwvY2xhaW1zLzpjaGFubmVsTmFtZS86Y2hhbm5lbENsYWltSWQvOnBhZ2UnLCBjaGFubmVsQ2xhaW1zKTtcbiAgLy8gY2xhaW0gcm91dGVzXG4gIGFwcC5nZXQoJy9hcGkvY2xhaW0vbGlzdC86bmFtZScsIGNsYWltTGlzdCk7XG4gIGFwcC5nZXQoJy9hcGkvY2xhaW0vZ2V0LzpuYW1lLzpjbGFpbUlkJywgY2xhaW1HZXQpO1xuICBhcHAuZ2V0KCcvYXBpL2NsYWltL2F2YWlsYWJpbGl0eS86bmFtZScsIGNsYWltQXZhaWxhYmlsaXR5KTtcbiAgYXBwLmdldCgnL2FwaS9jbGFpbS9yZXNvbHZlLzpuYW1lLzpjbGFpbUlkJywgY2xhaW1SZXNvbHZlKTtcbiAgYXBwLnBvc3QoJy9hcGkvY2xhaW0vcHVibGlzaCcsIG11bHRpcGFydE1pZGRsZXdhcmUsIGNsYWltUHVibGlzaCk7XG4gIGFwcC5nZXQoJy9hcGkvY2xhaW0vc2hvcnQtaWQvOmxvbmdJZC86bmFtZScsIGNsYWltU2hvcnRJZCk7XG4gIGFwcC5wb3N0KCcvYXBpL2NsYWltL2xvbmctaWQnLCBjbGFpbUxvbmdJZCk7XG4gIGFwcC5nZXQoJy9hcGkvY2xhaW0vZGF0YS86Y2xhaW1OYW1lLzpjbGFpbUlkJywgY2xhaW1EYXRhKTtcbiAgLy8gZmlsZSByb3V0ZXNcbiAgYXBwLmdldCgnL2FwaS9maWxlL2F2YWlsYWJpbGl0eS86bmFtZS86Y2xhaW1JZCcsIGZpbGVBdmFpbGFiaWxpdHkpO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXBpL2luZGV4LmpzIiwiY29uc3QgeyBjaGVja0NoYW5uZWxBdmFpbGFiaWxpdHkgfSA9IHJlcXVpcmUoJ2NvbnRyb2xsZXJzL3B1Ymxpc2hDb250cm9sbGVyLmpzJyk7XG5jb25zdCB7IHNlbmRHQVRpbWluZ0V2ZW50IH0gPSByZXF1aXJlKCdoZWxwZXJzL2dvb2dsZUFuYWx5dGljcy5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcblxuLypcblxuICByb3V0ZSB0byBjaGVjayB3aGV0aGVyIHNpdGUgaGFzIHB1Ymxpc2hlZCB0byBhIGNoYW5uZWxcblxuKi9cblxuY29uc3QgY2hhbm5lbEF2YWlsYWJpbGl0eSA9ICh7IGlwLCBvcmlnaW5hbFVybCwgcGFyYW1zOiB7IG5hbWUgfSB9LCByZXMpID0+IHtcbiAgY29uc3QgZ2FTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICBjaGVja0NoYW5uZWxBdmFpbGFiaWxpdHkobmFtZSlcbiAgICAudGhlbihhdmFpbGFibGVOYW1lID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKGF2YWlsYWJsZU5hbWUpO1xuICAgICAgc2VuZEdBVGltaW5nRXZlbnQoJ2VuZC10by1lbmQnLCAnY2xhaW0gbmFtZSBhdmFpbGFiaWxpdHknLCBuYW1lLCBnYVN0YXJ0VGltZSwgRGF0ZS5ub3coKSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjaGFubmVsQXZhaWxhYmlsaXR5O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2hhbm5lbEF2YWlsYWJpbGl0eS5qcyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImZzXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiZnNcIlxuLy8gbW9kdWxlIGlkID0gNjRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgeyBnZXRDaGFubmVsQ2xhaW1zIH0gPSByZXF1aXJlKCdjb250cm9sbGVycy9zZXJ2ZUNvbnRyb2xsZXIuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5cbmNvbnN0IE5PX0NIQU5ORUwgPSAnTk9fQ0hBTk5FTCc7XG5cbi8qXG5cbiAgcm91dGUgdG8gZ2V0IGFsbCBjbGFpbXMgZm9yIGNoYW5uZWxcblxuKi9cblxuY29uc3QgY2hhbm5lbENsYWltcyA9ICh7IGlwLCBvcmlnaW5hbFVybCwgYm9keSwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICBjb25zdCBjaGFubmVsTmFtZSA9IHBhcmFtcy5jaGFubmVsTmFtZTtcbiAgbGV0IGNoYW5uZWxDbGFpbUlkID0gcGFyYW1zLmNoYW5uZWxDbGFpbUlkO1xuICBpZiAoY2hhbm5lbENsYWltSWQgPT09ICdub25lJykgY2hhbm5lbENsYWltSWQgPSBudWxsO1xuICBjb25zdCBwYWdlID0gcGFyYW1zLnBhZ2U7XG4gIGdldENoYW5uZWxDbGFpbXMoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkLCBwYWdlKVxuICAgIC50aGVuKGRhdGEgPT4ge1xuICAgICAgaWYgKGRhdGEgPT09IE5PX0NIQU5ORUwpIHtcbiAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDA0KS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogJ05vIG1hdGNoaW5nIGNoYW5uZWwgd2FzIGZvdW5kJ30pO1xuICAgICAgfVxuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWUsIGRhdGF9KTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNoYW5uZWxDbGFpbXM7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jaGFubmVsQ2xhaW1zLmpzIiwiY29uc3QgQ0xBSU1TX1BFUl9QQUdFID0gMTI7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICByZXR1cm5QYWdpbmF0ZWRDaGFubmVsQ2xhaW1zIChjaGFubmVsTmFtZSwgbG9uZ0NoYW5uZWxDbGFpbUlkLCBjbGFpbXMsIHBhZ2UpIHtcbiAgICBjb25zdCB0b3RhbFBhZ2VzID0gbW9kdWxlLmV4cG9ydHMuZGV0ZXJtaW5lVG90YWxQYWdlcyhjbGFpbXMpO1xuICAgIGNvbnN0IHBhZ2luYXRpb25QYWdlID0gbW9kdWxlLmV4cG9ydHMuZ2V0UGFnZUZyb21RdWVyeShwYWdlKTtcbiAgICBjb25zdCB2aWV3RGF0YSA9IHtcbiAgICAgIGNoYW5uZWxOYW1lICAgICAgIDogY2hhbm5lbE5hbWUsXG4gICAgICBsb25nQ2hhbm5lbENsYWltSWQ6IGxvbmdDaGFubmVsQ2xhaW1JZCxcbiAgICAgIGNsYWltcyAgICAgICAgICAgIDogbW9kdWxlLmV4cG9ydHMuZXh0cmFjdFBhZ2VGcm9tQ2xhaW1zKGNsYWltcywgcGFnaW5hdGlvblBhZ2UpLFxuICAgICAgcHJldmlvdXNQYWdlICAgICAgOiBtb2R1bGUuZXhwb3J0cy5kZXRlcm1pbmVQcmV2aW91c1BhZ2UocGFnaW5hdGlvblBhZ2UpLFxuICAgICAgY3VycmVudFBhZ2UgICAgICAgOiBwYWdpbmF0aW9uUGFnZSxcbiAgICAgIG5leHRQYWdlICAgICAgICAgIDogbW9kdWxlLmV4cG9ydHMuZGV0ZXJtaW5lTmV4dFBhZ2UodG90YWxQYWdlcywgcGFnaW5hdGlvblBhZ2UpLFxuICAgICAgdG90YWxQYWdlcyAgICAgICAgOiB0b3RhbFBhZ2VzLFxuICAgICAgdG90YWxSZXN1bHRzICAgICAgOiBtb2R1bGUuZXhwb3J0cy5kZXRlcm1pbmVUb3RhbENsYWltcyhjbGFpbXMpLFxuICAgIH07XG4gICAgcmV0dXJuIHZpZXdEYXRhO1xuICB9LFxuICBnZXRQYWdlRnJvbVF1ZXJ5IChwYWdlKSB7XG4gICAgaWYgKHBhZ2UpIHtcbiAgICAgIHJldHVybiBwYXJzZUludChwYWdlKTtcbiAgICB9XG4gICAgcmV0dXJuIDE7XG4gIH0sXG4gIGV4dHJhY3RQYWdlRnJvbUNsYWltcyAoY2xhaW1zLCBwYWdlTnVtYmVyKSB7XG4gICAgaWYgKCFjbGFpbXMpIHtcbiAgICAgIHJldHVybiBbXTsgIC8vIGlmIG5vIGNsYWltcywgcmV0dXJuIHRoaXMgZGVmYXVsdFxuICAgIH1cbiAgICAvLyBsb2dnZXIuZGVidWcoJ2NsYWltcyBpcyBhcnJheT8nLCBBcnJheS5pc0FycmF5KGNsYWltcykpO1xuICAgIC8vIGxvZ2dlci5kZWJ1ZyhgcGFnZU51bWJlciAke3BhZ2VOdW1iZXJ9IGlzIG51bWJlcj9gLCBOdW1iZXIuaXNJbnRlZ2VyKHBhZ2VOdW1iZXIpKTtcbiAgICBjb25zdCBjbGFpbVN0YXJ0SW5kZXggPSAocGFnZU51bWJlciAtIDEpICogQ0xBSU1TX1BFUl9QQUdFO1xuICAgIGNvbnN0IGNsYWltRW5kSW5kZXggPSBjbGFpbVN0YXJ0SW5kZXggKyBDTEFJTVNfUEVSX1BBR0U7XG4gICAgY29uc3QgcGFnZU9mQ2xhaW1zID0gY2xhaW1zLnNsaWNlKGNsYWltU3RhcnRJbmRleCwgY2xhaW1FbmRJbmRleCk7XG4gICAgcmV0dXJuIHBhZ2VPZkNsYWltcztcbiAgfSxcbiAgZGV0ZXJtaW5lVG90YWxQYWdlcyAoY2xhaW1zKSB7XG4gICAgaWYgKCFjbGFpbXMpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB0b3RhbENsYWltcyA9IGNsYWltcy5sZW5ndGg7XG4gICAgICBpZiAodG90YWxDbGFpbXMgPCBDTEFJTVNfUEVSX1BBR0UpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG4gICAgICBjb25zdCBmdWxsUGFnZXMgPSBNYXRoLmZsb29yKHRvdGFsQ2xhaW1zIC8gQ0xBSU1TX1BFUl9QQUdFKTtcbiAgICAgIGNvbnN0IHJlbWFpbmRlciA9IHRvdGFsQ2xhaW1zICUgQ0xBSU1TX1BFUl9QQUdFO1xuICAgICAgaWYgKHJlbWFpbmRlciA9PT0gMCkge1xuICAgICAgICByZXR1cm4gZnVsbFBhZ2VzO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZ1bGxQYWdlcyArIDE7XG4gICAgfVxuICB9LFxuICBkZXRlcm1pbmVQcmV2aW91c1BhZ2UgKGN1cnJlbnRQYWdlKSB7XG4gICAgaWYgKGN1cnJlbnRQYWdlID09PSAxKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnJlbnRQYWdlIC0gMTtcbiAgfSxcbiAgZGV0ZXJtaW5lTmV4dFBhZ2UgKHRvdGFsUGFnZXMsIGN1cnJlbnRQYWdlKSB7XG4gICAgaWYgKGN1cnJlbnRQYWdlID09PSB0b3RhbFBhZ2VzKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGN1cnJlbnRQYWdlICsgMTtcbiAgfSxcbiAgZGV0ZXJtaW5lVG90YWxDbGFpbXMgKGNsYWltcykge1xuICAgIGlmICghY2xhaW1zKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgcmV0dXJuIGNsYWltcy5sZW5ndGg7XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvY2hhbm5lbFBhZ2luYXRpb24uanMiLCJjb25zdCB7IGdldENoYW5uZWxEYXRhIH0gPSByZXF1aXJlKCdjb250cm9sbGVycy9zZXJ2ZUNvbnRyb2xsZXIuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5cbmNvbnN0IE5PX0NIQU5ORUwgPSAnTk9fQ0hBTk5FTCc7XG5cbi8qXG5cbiAgcm91dGUgdG8gZ2V0IGRhdGEgZm9yIGEgY2hhbm5lbFxuXG4qL1xuXG5jb25zdCBjaGFubmVsRGF0YSA9ICh7IGlwLCBvcmlnaW5hbFVybCwgYm9keSwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICBjb25zdCBjaGFubmVsTmFtZSA9IHBhcmFtcy5jaGFubmVsTmFtZTtcbiAgbGV0IGNoYW5uZWxDbGFpbUlkID0gcGFyYW1zLmNoYW5uZWxDbGFpbUlkO1xuICBpZiAoY2hhbm5lbENsYWltSWQgPT09ICdub25lJykgY2hhbm5lbENsYWltSWQgPSBudWxsO1xuICBnZXRDaGFubmVsRGF0YShjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIDApXG4gICAgLnRoZW4oZGF0YSA9PiB7XG4gICAgICBpZiAoZGF0YSA9PT0gTk9fQ0hBTk5FTCkge1xuICAgICAgICByZXR1cm4gcmVzLnN0YXR1cyg0MDQpLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBtZXNzYWdlOiAnTm8gbWF0Y2hpbmcgY2hhbm5lbCB3YXMgZm91bmQnfSk7XG4gICAgICB9XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZSwgZGF0YX0pO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2hhbm5lbERhdGE7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jaGFubmVsRGF0YS5qcyIsImNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5jb25zdCBkYiA9IHJlcXVpcmUoJ21vZGVscycpO1xuXG4vKlxuXG5yb3V0ZSB0byBnZXQgYSBzaG9ydCBjaGFubmVsIGlkIGZyb20gbG9uZyBjaGFubmVsIElkXG5cbiovXG5cbmNvbnN0IGNoYW5uZWxTaG9ydElkUm91dGUgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtcyB9LCByZXMpID0+IHtcbiAgZGIuQ2VydGlmaWNhdGUuZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZChwYXJhbXMubG9uZ0lkLCBwYXJhbXMubmFtZSlcbiAgICAudGhlbihzaG9ydElkID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHNob3J0SWQpO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2hhbm5lbFNob3J0SWRSb3V0ZTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxTaG9ydElkLmpzIiwiY29uc3QgeyBjbGFpbU5hbWVJc0F2YWlsYWJsZSB9ID0gcmVxdWlyZSgnY29udHJvbGxlcnMvcHVibGlzaENvbnRyb2xsZXIuanMnKTtcbmNvbnN0IHsgc2VuZEdBVGltaW5nRXZlbnQgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZ29vZ2xlQW5hbHl0aWNzLmpzJyk7XG5jb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuXG4vKlxuXG4gIHJvdXRlIHRvIGNoZWNrIHdoZXRoZXIgdGhpcyBzaXRlIHB1Ymxpc2hlZCB0byBhIGNsYWltXG5cbiovXG5cbmNvbnN0IGNsYWltQXZhaWxhYmlsaXR5ID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXM6IHsgbmFtZSB9IH0sIHJlcykgPT4ge1xuICBjb25zdCBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gIGNsYWltTmFtZUlzQXZhaWxhYmxlKG5hbWUpXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHJlc3VsdCk7XG4gICAgICBzZW5kR0FUaW1pbmdFdmVudCgnZW5kLXRvLWVuZCcsICdjbGFpbSBuYW1lIGF2YWlsYWJpbGl0eScsIG5hbWUsIGdhU3RhcnRUaW1lLCBEYXRlLm5vdygpKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYWltQXZhaWxhYmlsaXR5O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1BdmFpbGFiaWxpdHkuanMiLCJjb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuY29uc3QgZGIgPSByZXF1aXJlKCdtb2RlbHMnKTtcblxuLypcblxuICByb3V0ZSB0byByZXR1cm4gZGF0YSBmb3IgYSBjbGFpbVxuXG4qL1xuXG5jb25zdCBjbGFpbURhdGEgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIGJvZHksIHBhcmFtcyB9LCByZXMpID0+IHtcbiAgY29uc3QgY2xhaW1OYW1lID0gcGFyYW1zLmNsYWltTmFtZTtcbiAgbGV0IGNsYWltSWQgPSBwYXJhbXMuY2xhaW1JZDtcbiAgaWYgKGNsYWltSWQgPT09ICdub25lJykgY2xhaW1JZCA9IG51bGw7XG4gIGRiLkNsYWltLnJlc29sdmVDbGFpbShjbGFpbU5hbWUsIGNsYWltSWQpXG4gICAgLnRoZW4oY2xhaW1JbmZvID0+IHtcbiAgICAgIGlmICghY2xhaW1JbmZvKSB7XG4gICAgICAgIHJldHVybiByZXMuc3RhdHVzKDQwNCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICdObyBjbGFpbSBjb3VsZCBiZSBmb3VuZCd9KTtcbiAgICAgIH1cbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiBjbGFpbUluZm99KTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYWltRGF0YTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltRGF0YS5qcyIsImNvbnN0IHsgZ2V0Q2xhaW0gfSA9IHJlcXVpcmUoJ2hlbHBlcnMvbGJyeUFwaS5qcycpO1xuY29uc3QgeyBhZGRHZXRSZXN1bHRzVG9GaWxlRGF0YSwgY3JlYXRlRmlsZURhdGEgfSA9IHJlcXVpcmUoJy4uLy4uL2hlbHBlcnMvcHVibGlzaEhlbHBlcnMuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5jb25zdCBkYiA9IHJlcXVpcmUoJ21vZGVscycpO1xuXG4vKlxuXG4gIHJvdXRlIHRvIGdldCBhIGNsYWltXG5cbiovXG5cbmNvbnN0IGNsYWltR2V0ID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGNvbnN0IG5hbWUgPSBwYXJhbXMubmFtZTtcbiAgY29uc3QgY2xhaW1JZCA9IHBhcmFtcy5jbGFpbUlkO1xuICAvLyByZXNvbHZlIHRoZSBjbGFpbVxuICBkYi5DbGFpbS5yZXNvbHZlQ2xhaW0obmFtZSwgY2xhaW1JZClcbiAgICAudGhlbihyZXNvbHZlUmVzdWx0ID0+IHtcbiAgICAgIC8vIG1ha2Ugc3VyZSBhIGNsYWltIGFjdHVhbGx5IGV4aXN0cyBhdCB0aGF0IHVyaVxuICAgICAgaWYgKCFyZXNvbHZlUmVzdWx0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gbWF0Y2hpbmcgdXJpIGZvdW5kIGluIENsYWltIHRhYmxlJyk7XG4gICAgICB9XG4gICAgICBsZXQgZmlsZURhdGEgPSBjcmVhdGVGaWxlRGF0YShyZXNvbHZlUmVzdWx0KTtcbiAgICAgIC8vIGdldCB0aGUgY2xhaW1cbiAgICAgIHJldHVybiBQcm9taXNlLmFsbChbZmlsZURhdGEsIGdldENsYWltKGAke25hbWV9IyR7Y2xhaW1JZH1gKV0pO1xuICAgIH0pXG4gICAgLnRoZW4oKFsgZmlsZURhdGEsIGdldFJlc3VsdCBdKSA9PiB7XG4gICAgICBmaWxlRGF0YSA9IGFkZEdldFJlc3VsdHNUb0ZpbGVEYXRhKGZpbGVEYXRhLCBnZXRSZXN1bHQpO1xuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtkYi51cHNlcnQoZGIuRmlsZSwgZmlsZURhdGEsIHtuYW1lLCBjbGFpbUlkfSwgJ0ZpbGUnKSwgZ2V0UmVzdWx0XSk7XG4gICAgfSlcbiAgICAudGhlbigoWyBmaWxlUmVjb3JkLCB7bWVzc2FnZSwgY29tcGxldGVkfSBdKSA9PiB7XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7IHN1Y2Nlc3M6IHRydWUsIG1lc3NhZ2UsIGNvbXBsZXRlZCB9KTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYWltR2V0O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1HZXQuanMiLCJjb25zdCB7IGdldENsYWltSWQgfSA9IHJlcXVpcmUoJ2NvbnRyb2xsZXJzL3NlcnZlQ29udHJvbGxlci5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcblxuY29uc3QgTk9fQ0hBTk5FTCA9ICdOT19DSEFOTkVMJztcbmNvbnN0IE5PX0NMQUlNID0gJ05PX0NMQUlNJztcblxuLypcblxuICByb3V0ZSB0byBnZXQgYSBsb25nIGNsYWltIGlkXG5cbiovXG5cbmNvbnN0IGNsYWltTG9uZ0lkID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBib2R5LCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGNvbnN0IGNoYW5uZWxOYW1lID0gYm9keS5jaGFubmVsTmFtZTtcbiAgY29uc3QgY2hhbm5lbENsYWltSWQgPSBib2R5LmNoYW5uZWxDbGFpbUlkO1xuICBjb25zdCBjbGFpbU5hbWUgPSBib2R5LmNsYWltTmFtZTtcbiAgY29uc3QgY2xhaW1JZCA9IGJvZHkuY2xhaW1JZDtcbiAgZ2V0Q2xhaW1JZChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltTmFtZSwgY2xhaW1JZClcbiAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgaWYgKHJlc3VsdCA9PT0gTk9fQ0hBTk5FTCkge1xuICAgICAgICByZXR1cm4gcmVzLnN0YXR1cyg0MDQpLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBtZXNzYWdlOiAnTm8gbWF0Y2hpbmcgY2hhbm5lbCBjb3VsZCBiZSBmb3VuZCd9KTtcbiAgICAgIH1cbiAgICAgIGlmIChyZXN1bHQgPT09IE5PX0NMQUlNKSB7XG4gICAgICAgIHJldHVybiByZXMuc3RhdHVzKDQwNCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICdObyBtYXRjaGluZyBjbGFpbSBpZCBjb3VsZCBiZSBmb3VuZCd9KTtcbiAgICAgIH1cbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiByZXN1bHR9KTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYWltTG9uZ0lkO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1Mb25nSWQuanMiLCJjb25zdCB7IGNyZWF0ZUJhc2ljUHVibGlzaFBhcmFtcywgY3JlYXRlVGh1bWJuYWlsUHVibGlzaFBhcmFtcywgcGFyc2VQdWJsaXNoQXBpUmVxdWVzdEJvZHksIHBhcnNlUHVibGlzaEFwaVJlcXVlc3RGaWxlcyB9ID0gcmVxdWlyZSgnaGVscGVycy9wdWJsaXNoSGVscGVycy5qcycpO1xuY29uc3QgeyBjbGFpbU5hbWVJc0F2YWlsYWJsZSwgcHVibGlzaCB9ID0gcmVxdWlyZSgnY29udHJvbGxlcnMvcHVibGlzaENvbnRyb2xsZXIuanMnKTtcbmNvbnN0IHsgYXV0aGVudGljYXRlVXNlciB9ID0gcmVxdWlyZSgnYXV0aC9hdXRoZW50aWNhdGlvbi5qcycpO1xuY29uc3QgeyBzZW5kR0FUaW1pbmdFdmVudCB9ID0gcmVxdWlyZSgnaGVscGVycy9nb29nbGVBbmFseXRpY3MuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5jb25zdCB7IGRldGFpbHM6IHsgaG9zdCB9IH0gPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5cbi8qXG5cbiAgcm91dGUgdG8gcHVibGlzaCBhIGNsYWltIHRocm91Z2ggdGhlIGRhZW1vblxuXG4qL1xuXG5jb25zdCBjbGFpbVB1Ymxpc2ggPSAoeyBib2R5LCBmaWxlcywgaGVhZGVycywgaXAsIG9yaWdpbmFsVXJsLCB1c2VyIH0sIHJlcykgPT4ge1xuICAvLyBkZWZpbmUgdmFyaWFibGVzXG4gIGxldCAgY2hhbm5lbE5hbWUsIGNoYW5uZWxJZCwgY2hhbm5lbFBhc3N3b3JkLCBkZXNjcmlwdGlvbiwgZmlsZU5hbWUsIGZpbGVQYXRoLCBmaWxlVHlwZSwgZ2FTdGFydFRpbWUsIGxpY2Vuc2UsIG5hbWUsIG5zZncsIHRodW1ibmFpbCwgdGh1bWJuYWlsRmlsZU5hbWUsIHRodW1ibmFpbEZpbGVQYXRoLCB0aHVtYm5haWxGaWxlVHlwZSwgdGl0bGU7XG4gIC8vIHJlY29yZCB0aGUgc3RhcnQgdGltZSBvZiB0aGUgcmVxdWVzdFxuICBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gIC8vIHZhbGlkYXRlIHRoZSBib2R5IGFuZCBmaWxlcyBvZiB0aGUgcmVxdWVzdFxuICB0cnkge1xuICAgIC8vIHZhbGlkYXRlQXBpUHVibGlzaFJlcXVlc3QoYm9keSwgZmlsZXMpO1xuICAgICh7bmFtZSwgbnNmdywgbGljZW5zZSwgdGl0bGUsIGRlc2NyaXB0aW9uLCB0aHVtYm5haWx9ID0gcGFyc2VQdWJsaXNoQXBpUmVxdWVzdEJvZHkoYm9keSkpO1xuICAgICh7ZmlsZU5hbWUsIGZpbGVQYXRoLCBmaWxlVHlwZSwgdGh1bWJuYWlsRmlsZU5hbWUsIHRodW1ibmFpbEZpbGVQYXRoLCB0aHVtYm5haWxGaWxlVHlwZX0gPSBwYXJzZVB1Ymxpc2hBcGlSZXF1ZXN0RmlsZXMoZmlsZXMpKTtcbiAgICAoe2NoYW5uZWxOYW1lLCBjaGFubmVsSWQsIGNoYW5uZWxQYXNzd29yZH0gPSBib2R5KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZXR1cm4gcmVzLnN0YXR1cyg0MDApLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBtZXNzYWdlOiBlcnJvci5tZXNzYWdlfSk7XG4gIH1cbiAgLy8gY2hlY2sgY2hhbm5lbCBhdXRob3JpemF0aW9uXG4gIFByb21pc2VcbiAgICAuYWxsKFtcbiAgICAgIGF1dGhlbnRpY2F0ZVVzZXIoY2hhbm5lbE5hbWUsIGNoYW5uZWxJZCwgY2hhbm5lbFBhc3N3b3JkLCB1c2VyKSxcbiAgICAgIGNsYWltTmFtZUlzQXZhaWxhYmxlKG5hbWUpLFxuICAgICAgY3JlYXRlQmFzaWNQdWJsaXNoUGFyYW1zKGZpbGVQYXRoLCBuYW1lLCB0aXRsZSwgZGVzY3JpcHRpb24sIGxpY2Vuc2UsIG5zZncsIHRodW1ibmFpbCksXG4gICAgICBjcmVhdGVUaHVtYm5haWxQdWJsaXNoUGFyYW1zKHRodW1ibmFpbEZpbGVQYXRoLCBuYW1lLCBsaWNlbnNlLCBuc2Z3KSxcbiAgICBdKVxuICAgIC50aGVuKChbe2NoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZH0sIHZhbGlkYXRlZENsYWltTmFtZSwgcHVibGlzaFBhcmFtcywgdGh1bWJuYWlsUHVibGlzaFBhcmFtc10pID0+IHtcbiAgICAgIC8vIGFkZCBjaGFubmVsIGRldGFpbHMgdG8gdGhlIHB1Ymxpc2ggcGFyYW1zXG4gICAgICBpZiAoY2hhbm5lbE5hbWUgJiYgY2hhbm5lbENsYWltSWQpIHtcbiAgICAgICAgcHVibGlzaFBhcmFtc1snY2hhbm5lbF9uYW1lJ10gPSBjaGFubmVsTmFtZTtcbiAgICAgICAgcHVibGlzaFBhcmFtc1snY2hhbm5lbF9pZCddID0gY2hhbm5lbENsYWltSWQ7XG4gICAgICB9XG4gICAgICAvLyBwdWJsaXNoIHRoZSB0aHVtYm5haWxcbiAgICAgIGlmICh0aHVtYm5haWxQdWJsaXNoUGFyYW1zKSB7XG4gICAgICAgIHB1Ymxpc2godGh1bWJuYWlsUHVibGlzaFBhcmFtcywgdGh1bWJuYWlsRmlsZU5hbWUsIHRodW1ibmFpbEZpbGVUeXBlKTtcbiAgICAgIH1cbiAgICAgIC8vIHB1Ymxpc2ggdGhlIGFzc2V0XG4gICAgICByZXR1cm4gcHVibGlzaChwdWJsaXNoUGFyYW1zLCBmaWxlTmFtZSwgZmlsZVR5cGUpO1xuICAgIH0pXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtcbiAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgbWVzc2FnZTogJ3B1Ymxpc2ggY29tcGxldGVkIHN1Y2Nlc3NmdWxseScsXG4gICAgICAgIGRhdGEgICA6IHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGNsYWltSWQ6IHJlc3VsdC5jbGFpbV9pZCxcbiAgICAgICAgICB1cmwgICAgOiBgJHtob3N0fS8ke3Jlc3VsdC5jbGFpbV9pZH0vJHtuYW1lfWAsXG4gICAgICAgICAgbGJyeVR4IDogcmVzdWx0LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICAvLyByZWNvcmQgdGhlIHB1Ymxpc2ggZW5kIHRpbWUgYW5kIHNlbmQgdG8gZ29vZ2xlIGFuYWx5dGljc1xuICAgICAgc2VuZEdBVGltaW5nRXZlbnQoJ2VuZC10by1lbmQnLCAncHVibGlzaCcsIGZpbGVUeXBlLCBnYVN0YXJ0VGltZSwgRGF0ZS5ub3coKSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFpbVB1Ymxpc2g7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbVB1Ymxpc2guanMiLCJjb25zdCBkYiA9IHJlcXVpcmUoJ21vZGVscycpO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgYXV0aGVudGljYXRlVXNlciAoY2hhbm5lbE5hbWUsIGNoYW5uZWxJZCwgY2hhbm5lbFBhc3N3b3JkLCB1c2VyKSB7XG4gICAgLy8gY2FzZTogbm8gY2hhbm5lbE5hbWUgb3IgY2hhbm5lbCBJZCBhcmUgcHJvdmlkZWQgKGFub255bW91cyksIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB1c2VyIHRva2VuIGlzIHByb3ZpZGVkXG4gICAgaWYgKCFjaGFubmVsTmFtZSAmJiAhY2hhbm5lbElkKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjaGFubmVsTmFtZSAgIDogbnVsbCxcbiAgICAgICAgY2hhbm5lbENsYWltSWQ6IG51bGwsXG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBjYXNlOiBjaGFubmVsTmFtZSBvciBjaGFubmVsIElkIGFyZSBwcm92aWRlZCB3aXRoIHVzZXIgdG9rZW5cbiAgICBpZiAodXNlcikge1xuICAgICAgaWYgKGNoYW5uZWxOYW1lICYmIGNoYW5uZWxOYW1lICE9PSB1c2VyLmNoYW5uZWxOYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIHByb3ZpZGVkIGNoYW5uZWwgbmFtZSBkb2VzIG5vdCBtYXRjaCB1c2VyIGNyZWRlbnRpYWxzJyk7XG4gICAgICB9XG4gICAgICBpZiAoY2hhbm5lbElkICYmIGNoYW5uZWxJZCAhPT0gdXNlci5jaGFubmVsQ2xhaW1JZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RoZSBwcm92aWRlZCBjaGFubmVsIGlkIGRvZXMgbm90IG1hdGNoIHVzZXIgY3JlZGVudGlhbHMnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNoYW5uZWxOYW1lICAgOiB1c2VyLmNoYW5uZWxOYW1lLFxuICAgICAgICBjaGFubmVsQ2xhaW1JZDogdXNlci5jaGFubmVsQ2xhaW1JZCxcbiAgICAgIH07XG4gICAgfVxuICAgIC8vIGNhc2U6IGNoYW5uZWxOYW1lIG9yIGNoYW5uZWwgSWQgYXJlIHByb3ZpZGVkIHdpdGggcGFzc3dvcmQgaW5zdGVhZCBvZiB1c2VyIHRva2VuXG4gICAgaWYgKCFjaGFubmVsUGFzc3dvcmQpIHRocm93IG5ldyBFcnJvcignbm8gY2hhbm5lbCBwYXNzd29yZCBwcm92aWRlZCcpO1xuICAgIHJldHVybiBtb2R1bGUuZXhwb3J0cy5hdXRoZW50aWNhdGVDaGFubmVsQ3JlZGVudGlhbHMoY2hhbm5lbE5hbWUsIGNoYW5uZWxJZCwgY2hhbm5lbFBhc3N3b3JkKTtcbiAgfSxcbiAgYXV0aGVudGljYXRlQ2hhbm5lbENyZWRlbnRpYWxzIChjaGFubmVsTmFtZSwgY2hhbm5lbElkLCB1c2VyUGFzc3dvcmQpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgLy8gaG9pc3RlZCB2YXJpYWJsZXNcbiAgICAgIGxldCBjaGFubmVsRGF0YTtcbiAgICAgIC8vIGJ1aWxkIHRoZSBwYXJhbXMgZm9yIGZpbmRpbmcgdGhlIGNoYW5uZWxcbiAgICAgIGxldCBjaGFubmVsRmluZFBhcmFtcyA9IHt9O1xuICAgICAgaWYgKGNoYW5uZWxOYW1lKSBjaGFubmVsRmluZFBhcmFtc1snY2hhbm5lbE5hbWUnXSA9IGNoYW5uZWxOYW1lO1xuICAgICAgaWYgKGNoYW5uZWxJZCkgY2hhbm5lbEZpbmRQYXJhbXNbJ2NoYW5uZWxDbGFpbUlkJ10gPSBjaGFubmVsSWQ7XG4gICAgICAvLyBmaW5kIHRoZSBjaGFubmVsXG4gICAgICBkYi5DaGFubmVsXG4gICAgICAgIC5maW5kT25lKHtcbiAgICAgICAgICB3aGVyZTogY2hhbm5lbEZpbmRQYXJhbXMsXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKGNoYW5uZWwgPT4ge1xuICAgICAgICAgIGlmICghY2hhbm5lbCkge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKCdubyBjaGFubmVsIGZvdW5kJyk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1dGhlbnRpY2F0aW9uIGZhaWxlZCwgeW91IGRvIG5vdCBoYXZlIGFjY2VzcyB0byB0aGF0IGNoYW5uZWwnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY2hhbm5lbERhdGEgPSBjaGFubmVsLmdldCgpO1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnY2hhbm5lbCBkYXRhOicsIGNoYW5uZWxEYXRhKTtcbiAgICAgICAgICByZXR1cm4gZGIuVXNlci5maW5kT25lKHtcbiAgICAgICAgICAgIHdoZXJlOiB7IHVzZXJOYW1lOiBjaGFubmVsRGF0YS5jaGFubmVsTmFtZS5zdWJzdHJpbmcoMSkgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4odXNlciA9PiB7XG4gICAgICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ25vIHVzZXIgZm91bmQnKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQXV0aGVudGljYXRpb24gZmFpbGVkLCB5b3UgZG8gbm90IGhhdmUgYWNjZXNzIHRvIHRoYXQgY2hhbm5lbCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdXNlci5jb21wYXJlUGFzc3dvcmQodXNlclBhc3N3b3JkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oaXNNYXRjaCA9PiB7XG4gICAgICAgICAgaWYgKCFpc01hdGNoKSB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ2luY29ycmVjdCBwYXNzd29yZCcpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRoZW50aWNhdGlvbiBmYWlsZWQsIHlvdSBkbyBub3QgaGF2ZSBhY2Nlc3MgdG8gdGhhdCBjaGFubmVsJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnLi4ucGFzc3dvcmQgd2FzIGEgbWF0Y2guLi4nKTtcbiAgICAgICAgICByZXNvbHZlKGNoYW5uZWxEYXRhKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvYXV0aC9hdXRoZW50aWNhdGlvbi5qcyIsImNvbnN0IHsgcmVzb2x2ZVVyaSB9ID0gcmVxdWlyZSgnaGVscGVycy9sYnJ5QXBpLmpzJyk7XG5jb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuXG4vKlxuXG4gIHJvdXRlIHRvIHJ1biBhIHJlc29sdmUgcmVxdWVzdCBvbiB0aGUgZGFlbW9uXG5cbiovXG5cbmNvbnN0IGNsYWltUmVzb2x2ZSA9ICh7IGhlYWRlcnMsIGlwLCBvcmlnaW5hbFVybCwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICByZXNvbHZlVXJpKGAke3BhcmFtcy5uYW1lfSMke3BhcmFtcy5jbGFpbUlkfWApXG4gICAgLnRoZW4ocmVzb2x2ZWRVcmkgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24ocmVzb2x2ZWRVcmkpO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1SZXNvbHZlO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1SZXNvbHZlLmpzIiwiY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcbmNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5cbi8qXG5cbiAgcm91dGUgdG8gZ2V0IGEgc2hvcnQgY2xhaW0gaWQgZnJvbSBsb25nIGNsYWltIElkXG5cbiovXG5cbmNvbnN0IGNsYWltU2hvcnRJZCA9ICh7IGlwLCBvcmlnaW5hbFVybCwgYm9keSwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICBkYi5DbGFpbS5nZXRTaG9ydENsYWltSWRGcm9tTG9uZ0NsYWltSWQocGFyYW1zLmxvbmdJZCwgcGFyYW1zLm5hbWUpXG4gICAgLnRoZW4oc2hvcnRJZCA9PiB7XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZSwgZGF0YTogc2hvcnRJZH0pO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1TaG9ydElkO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1TaG9ydElkLmpzIiwiY29uc3QgeyBnZXRDbGFpbUxpc3QgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvbGJyeUFwaS5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcblxuLypcblxuICByb3V0ZSB0byBnZXQgbGlzdCBvZiBjbGFpbXNcblxuKi9cblxuY29uc3QgY2xhaW1MaXN0ID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGdldENsYWltTGlzdChwYXJhbXMubmFtZSlcbiAgICAudGhlbihjbGFpbXNMaXN0ID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKGNsYWltc0xpc3QpO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1MaXN0O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1MaXN0LmpzIiwiY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcbmNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5cbi8qXG5cbiAgcm91dGUgdG8gc2VlIGlmIGFzc2V0IGlzIGF2YWlsYWJsZSBsb2NhbGx5XG5cbiovXG5cbmNvbnN0IGZpbGVBdmFpbGFiaWxpdHkgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtcyB9LCByZXMpID0+IHtcbiAgY29uc3QgbmFtZSA9IHBhcmFtcy5uYW1lO1xuICBjb25zdCBjbGFpbUlkID0gcGFyYW1zLmNsYWltSWQ7XG4gIGRiLkZpbGVcbiAgICAuZmluZE9uZSh7XG4gICAgICB3aGVyZToge1xuICAgICAgICBuYW1lLFxuICAgICAgICBjbGFpbUlkLFxuICAgICAgfSxcbiAgICB9KVxuICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgIHJldHVybiByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZSwgZGF0YTogdHJ1ZX0pO1xuICAgICAgfVxuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWUsIGRhdGE6IGZhbHNlfSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmaWxlQXZhaWxhYmlsaXR5O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvZmlsZUF2YWlsYWJpbGl0eS5qcyIsImNvbnN0IG11bHRpcGFydCA9IHJlcXVpcmUoJ2Nvbm5lY3QtbXVsdGlwYXJ0eScpO1xuY29uc3QgeyBwdWJsaXNoaW5nOiB7IHVwbG9hZERpcmVjdG9yeSB9IH0gPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5jb25zdCBtdWx0aXBhcnRNaWRkbGV3YXJlID0gbXVsdGlwYXJ0KHt1cGxvYWREaXI6IHVwbG9hZERpcmVjdG9yeX0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG11bHRpcGFydE1pZGRsZXdhcmU7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9tdWx0aXBhcnRNaWRkbGV3YXJlLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiY29ubmVjdC1tdWx0aXBhcnR5XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiY29ubmVjdC1tdWx0aXBhcnR5XCJcbi8vIG1vZHVsZSBpZCA9IDgwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImNvbnN0IGhhbmRsZVBhZ2VSZXF1ZXN0ID0gcmVxdWlyZSgnLi9zZW5kUmVhY3RBcHAnKTtcbmNvbnN0IGhhbmRsZUVtYmVkUmVxdWVzdCA9IHJlcXVpcmUoJy4vc2VuZEVtYmVkUGFnZScpO1xuY29uc3QgcmVkaXJlY3QgPSByZXF1aXJlKCcuL3JlZGlyZWN0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKGFwcCkgPT4ge1xuICBhcHAuZ2V0KCcvJywgaGFuZGxlUGFnZVJlcXVlc3QpO1xuICBhcHAuZ2V0KCcvbG9naW4nLCBoYW5kbGVQYWdlUmVxdWVzdCk7XG4gIGFwcC5nZXQoJy9hYm91dCcsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL3RyZW5kaW5nJywgcmVkaXJlY3QoJy9wb3B1bGFyJykpO1xuICBhcHAuZ2V0KCcvcG9wdWxhcicsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL25ldycsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL2VtYmVkLzpjbGFpbUlkLzpuYW1lJywgaGFuZGxlRW1iZWRSZXF1ZXN0KTsgIC8vIHJvdXRlIHRvIHNlbmQgZW1iZWRhYmxlIHZpZGVvIHBsYXllciAoZm9yIHR3aXR0ZXIpXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9pbmRleC5qcyIsImNvbnN0IGhhbmRsZVBhZ2VSZW5kZXIgPSByZXF1aXJlKCdoZWxwZXJzL2hhbmRsZVBhZ2VSZW5kZXIuanN4Jyk7XG5cbmNvbnN0IHNlbmRSZWFjdEFwcCA9IChyZXEsIHJlcykgPT4ge1xuICBoYW5kbGVQYWdlUmVuZGVyKHJlcSwgcmVzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2VuZFJlYWN0QXBwO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kUmVhY3RBcHAuanMiLCJjb25zdCB7IGRldGFpbHM6IHsgaG9zdCB9IH0gPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5cbmNvbnN0IHNlbmRFbWJlZFBhZ2UgPSAoeyBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGNvbnN0IGNsYWltSWQgPSBwYXJhbXMuY2xhaW1JZDtcbiAgY29uc3QgbmFtZSA9IHBhcmFtcy5uYW1lO1xuICAvLyBnZXQgYW5kIHJlbmRlciB0aGUgY29udGVudFxuICByZXMuc3RhdHVzKDIwMCkucmVuZGVyKCdlbWJlZCcsIHsgbGF5b3V0OiAnZW1iZWQnLCBob3N0LCBjbGFpbUlkLCBuYW1lIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzZW5kRW1iZWRQYWdlO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kRW1iZWRQYWdlLmpzIiwiY29uc3QgcmVkaXJlY3QgPSAocm91dGUpID0+IHtcbiAgcmV0dXJuIChyZXEsIHJlcykgPT4ge1xuICAgIHJlcy5zdGF0dXMoMzAxKS5yZWRpcmVjdChyb3V0ZSk7XG4gIH07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlZGlyZWN0O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9yZWRpcmVjdC5qcyIsImNvbnN0IHNlcnZlQXNzZXRCeUNsYWltID0gcmVxdWlyZSgnLi9zZXJ2ZUFzc2V0QnlDbGFpbScpO1xuY29uc3Qgc2VydmVBc3NldEJ5SWRlbnRpZmllckFuZENsYWltID0gcmVxdWlyZSgnLi9zZXJ2ZUFzc2V0QnlJZGVudGlmaWVyQW5kQ2xhaW0nKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoYXBwLCBkYikgPT4ge1xuICBhcHAuZ2V0KCcvOmlkZW50aWZpZXIvOmNsYWltJywgc2VydmVBc3NldEJ5SWRlbnRpZmllckFuZENsYWltKTtcbiAgYXBwLmdldCgnLzpjbGFpbScsIHNlcnZlQXNzZXRCeUNsYWltKTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2Fzc2V0cy9pbmRleC5qcyIsImNvbnN0IHsgc2VuZEdBU2VydmVFdmVudCB9ID0gcmVxdWlyZSgnaGVscGVycy9nb29nbGVBbmFseXRpY3MnKTtcbmNvbnN0IHsgZGV0ZXJtaW5lUmVzcG9uc2VUeXBlLCBsb2dSZXF1ZXN0RGF0YSwgZ2V0Q2xhaW1JZEFuZFNlcnZlQXNzZXQgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvc2VydmVIZWxwZXJzLmpzJyk7XG5jb25zdCBsYnJ5VXJpID0gcmVxdWlyZSgnaGVscGVycy9sYnJ5VXJpLmpzJyk7XG5jb25zdCBoYW5kbGVTaG93UmVuZGVyID0gcmVxdWlyZSgnaGVscGVycy9oYW5kbGVTaG93UmVuZGVyLmpzeCcpO1xuY29uc3QgU0VSVkUgPSAnU0VSVkUnO1xuXG4vKlxuXG4gIHJvdXRlIHRvIHNlcnZlIGFuIGFzc2V0IG9yIHRoZSByZWFjdCBhcHAgdmlhIHRoZSBjbGFpbSBuYW1lIG9ubHlcblxuKi9cblxuY29uc3Qgc2VydmVyQXNzZXRCeUNsYWltID0gKHJlcSwgcmVzKSA9PiB7XG4gIGNvbnN0IHsgaGVhZGVycywgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXMgfSA9IHJlcTtcbiAgLy8gZGVjaWRlIGlmIHRoaXMgaXMgYSBzaG93IHJlcXVlc3RcbiAgbGV0IGhhc0ZpbGVFeHRlbnNpb247XG4gIHRyeSB7XG4gICAgKHsgaGFzRmlsZUV4dGVuc2lvbiB9ID0gbGJyeVVyaS5wYXJzZU1vZGlmaWVyKHBhcmFtcy5jbGFpbSkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KTtcbiAgfVxuICBsZXQgcmVzcG9uc2VUeXBlID0gZGV0ZXJtaW5lUmVzcG9uc2VUeXBlKGhhc0ZpbGVFeHRlbnNpb24sIGhlYWRlcnMpO1xuICBpZiAocmVzcG9uc2VUeXBlICE9PSBTRVJWRSkge1xuICAgIHJldHVybiBoYW5kbGVTaG93UmVuZGVyKHJlcSwgcmVzKTtcbiAgfVxuICAvLyBoYW5kbGUgc2VydmUgcmVxdWVzdFxuICAvLyBzZW5kIGdvb2dsZSBhbmFseXRpY3NcbiAgc2VuZEdBU2VydmVFdmVudChoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwpO1xuICAvLyBwYXJzZSB0aGUgY2xhaW1cbiAgbGV0IGNsYWltTmFtZTtcbiAgdHJ5IHtcbiAgICAoe2NsYWltTmFtZX0gPSBsYnJ5VXJpLnBhcnNlQ2xhaW0ocGFyYW1zLmNsYWltKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pO1xuICB9XG4gIC8vIGxvZyB0aGUgcmVxdWVzdCBkYXRhIGZvciBkZWJ1Z2dpbmdcbiAgbG9nUmVxdWVzdERhdGEocmVzcG9uc2VUeXBlLCBjbGFpbU5hbWUsIG51bGwsIG51bGwpO1xuICAvLyBnZXQgdGhlIGNsYWltIElkIGFuZCB0aGVuIHNlcnZlIHRoZSBhc3NldFxuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldChudWxsLCBudWxsLCBjbGFpbU5hbWUsIG51bGwsIG9yaWdpbmFsVXJsLCBpcCwgcmVzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2VydmVyQXNzZXRCeUNsYWltO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hc3NldHMvc2VydmVBc3NldEJ5Q2xhaW0uanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWR1eC1zYWdhXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicmVkdXgtc2FnYVwiXG4vLyBtb2R1bGUgaWQgPSA4N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWR1eC1zYWdhL2VmZmVjdHNcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJyZWR1eC1zYWdhL2VmZmVjdHNcIlxuLy8gbW9kdWxlIGlkID0gODhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgeyBzZW5kR0FTZXJ2ZUV2ZW50IH0gPSByZXF1aXJlKCdoZWxwZXJzL2dvb2dsZUFuYWx5dGljcycpO1xuY29uc3Qge1xuICBkZXRlcm1pbmVSZXNwb25zZVR5cGUsXG4gIGZsaXBDbGFpbU5hbWVBbmRJZEZvckJhY2t3YXJkc0NvbXBhdGliaWxpdHksXG4gIGxvZ1JlcXVlc3REYXRhLFxuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldCxcbn0gPSByZXF1aXJlKCdoZWxwZXJzL3NlcnZlSGVscGVycy5qcycpO1xuY29uc3QgbGJyeVVyaSA9IHJlcXVpcmUoJ2hlbHBlcnMvbGJyeVVyaS5qcycpO1xuY29uc3QgaGFuZGxlU2hvd1JlbmRlciA9IHJlcXVpcmUoJ2hlbHBlcnMvaGFuZGxlU2hvd1JlbmRlci5qc3gnKTtcblxuY29uc3QgU0VSVkUgPSAnU0VSVkUnO1xuXG4vKlxuXG4gIHJvdXRlIHRvIHNlcnZlIGFuIGFzc2V0IG9yIHRoZSByZWFjdCBhcHAgdmlhIHRoZSBjbGFpbSBuYW1lIGFuZCBhbiBpZGVudGlmaWVyXG5cbiovXG5cbmNvbnN0IHNlcnZlckFzc2V0QnlJZGVudGlmaWVyQW5kQ2xhaW0gPSAocmVxLCByZXMpID0+IHtcbiAgY29uc3QgeyBoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtcyB9ID0gcmVxO1xuICAvLyBkZWNpZGUgaWYgdGhpcyBpcyBhIHNob3cgcmVxdWVzdFxuICBsZXQgaGFzRmlsZUV4dGVuc2lvbjtcbiAgdHJ5IHtcbiAgICAoeyBoYXNGaWxlRXh0ZW5zaW9uIH0gPSBsYnJ5VXJpLnBhcnNlTW9kaWZpZXIocGFyYW1zLmNsYWltKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pO1xuICB9XG4gIGxldCByZXNwb25zZVR5cGUgPSBkZXRlcm1pbmVSZXNwb25zZVR5cGUoaGFzRmlsZUV4dGVuc2lvbiwgaGVhZGVycyk7XG4gIGlmIChyZXNwb25zZVR5cGUgIT09IFNFUlZFKSB7XG4gICAgcmV0dXJuIGhhbmRsZVNob3dSZW5kZXIocmVxLCByZXMpO1xuICB9XG4gIC8vIGhhbmRsZSBzZXJ2ZSByZXF1ZXN0XG4gIC8vIHNlbmQgZ29vZ2xlIGFuYWx5dGljc1xuICBzZW5kR0FTZXJ2ZUV2ZW50KGhlYWRlcnMsIGlwLCBvcmlnaW5hbFVybCk7XG4gIC8vIHBhcnNlIHRoZSBjbGFpbVxuICBsZXQgY2xhaW1OYW1lO1xuICB0cnkge1xuICAgICh7IGNsYWltTmFtZSB9ID0gbGJyeVVyaS5wYXJzZUNsYWltKHBhcmFtcy5jbGFpbSkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KTtcbiAgfVxuICAvLyBwYXJzZSB0aGUgaWRlbnRpZmllclxuICBsZXQgaXNDaGFubmVsLCBjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltSWQ7XG4gIHRyeSB7XG4gICAgKHsgaXNDaGFubmVsLCBjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltSWQgfSA9IGxicnlVcmkucGFyc2VJZGVudGlmaWVyKHBhcmFtcy5pZGVudGlmaWVyKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pO1xuICB9XG4gIGlmICghaXNDaGFubmVsKSB7XG4gICAgW2NsYWltSWQsIGNsYWltTmFtZV0gPSBmbGlwQ2xhaW1OYW1lQW5kSWRGb3JCYWNrd2FyZHNDb21wYXRpYmlsaXR5KGNsYWltSWQsIGNsYWltTmFtZSk7XG4gIH1cbiAgLy8gbG9nIHRoZSByZXF1ZXN0IGRhdGEgZm9yIGRlYnVnZ2luZ1xuICBsb2dSZXF1ZXN0RGF0YShyZXNwb25zZVR5cGUsIGNsYWltTmFtZSwgY2hhbm5lbE5hbWUsIGNsYWltSWQpO1xuICAvLyBnZXQgdGhlIGNsYWltIElkIGFuZCB0aGVuIHNlcnZlIHRoZSBhc3NldFxuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltTmFtZSwgY2xhaW1JZCwgb3JpZ2luYWxVcmwsIGlwLCByZXMpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzZXJ2ZXJBc3NldEJ5SWRlbnRpZmllckFuZENsYWltO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hc3NldHMvc2VydmVBc3NldEJ5SWRlbnRpZmllckFuZENsYWltLmpzIiwiY29uc3QgaGFuZGxlUGFnZVJlcXVlc3QgPSByZXF1aXJlKCcuL3NlbmRSZWFjdEFwcCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IChhcHApID0+IHtcbiAgYXBwLmdldCgnKicsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2ZhbGxiYWNrL2luZGV4LmpzIiwiY29uc3QgaGFuZGxlUGFnZVJlbmRlciA9IHJlcXVpcmUoJ2hlbHBlcnMvaGFuZGxlUGFnZVJlbmRlci5qc3gnKTtcblxuY29uc3Qgc2VuZFJlYWN0QXBwID0gKHJlcSwgcmVzKSA9PiB7XG4gIGhhbmRsZVBhZ2VSZW5kZXIocmVxLCByZXMpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzZW5kUmVhY3RBcHA7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2ZhbGxiYWNrL3NlbmRSZWFjdEFwcC5qcyJdLCJzb3VyY2VSb290IjoiIn0=
|