diff --git a/index.js b/index.js index 2539a036..0a9fca28 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,4198 @@ -module.exports=function(e){function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}var t={};return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n(n.s=26)}([function(e,n){e.exports=require("winston")},function(e,n,t){"use strict";var r=function(){function e(e,n){var t=[],r=!0,a=!1,i=void 0;try{for(var o,l=e[Symbol.iterator]();!(r=(o=l.next()).done)&&(t.push(o.value),!n||t.length!==n);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&l.return&&l.return()}finally{if(a)throw i}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=t(0);e.exports={handleErrorResponse:function(n,t,i,o){a.error("Error on "+n,e.exports.useObjectPropertiesIfNoKeys(i));var l=e.exports.returnErrorMessageAndStatus(i),s=r(l,2),u=s[0],c=s[1];o.status(u).json(e.exports.createErrorResponsePayload(u,c))},returnErrorMessageAndStatus:function(e){var n=void 0,t=void 0;return"ECONNREFUSED"===e.code?(n=503,t="Connection refused. The daemon may not be running."):(n=400,t=e.message?e.message:e),[n,t]},useObjectPropertiesIfNoKeys:function(e){if(0===Object.keys(e).length){var n={};return Object.getOwnPropertyNames(e).forEach(function(t){n[t]=e[t]}),n}return e},createErrorResponsePayload:function(e,n){return{status:e,success:!1,message:n}}}},function(e,n,t){"use strict";var r=t(45),a=t(46),i=t(47),o=t(48),l=t(49),s=t(50),u=t(13),c=t(0),d=t(10),f=d.database,h=d.username,m=d.password,p=new u(f,h,m,{host:"localhost",dialect:"mysql",dialectOptions:{decimalNumbers:!0},logging:!1,pool:{max:5,min:0,idle:1e4,acquire:1e4}});p.authenticate().then(function(){c.info("Sequelize has established mysql connection successfully.")}).catch(function(e){c.error("Sequelize was unable to connect to the database:",e)});var g={};g.Certificate=p.import("Certificate",r),g.Channel=p.import("Channel",a),g.Claim=p.import("Claim",i),g.File=p.import("File",o),g.Request=p.import("Request",l),g.User=p.import("User",s),c.info("associating db models..."),Object.keys(g).forEach(function(e){g[e].associate&&(c.info("Associating model:",e),g[e].associate(g))}),g.sequelize=p,g.Sequelize=u,g.upsert=function(e,n,t,r){return e.findOne({where:t}).then(function(t){return t?(c.debug("updating record in db."+r),t.update(n)):(c.debug("creating record in db."+r),e.create(n))}).catch(function(e){throw c.error(r+".upsert error",e),e})},e.exports=g},function(e,n,t){"use strict";function r(){var e=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={components:{},containers:{},pages:{}},this.details={description:"Open-source, decentralized image and video sharing.",host:"default",port:3e3,title:"Spee.ch",twitter:"@spee_ch"},this.publishing={additionalClaimAddresses:[],disabled:!1,disabledMessage:"Please check back soon.",primaryClaimAddress:"default",thumbnailChannel:"default",thumbnailChannelId:"default",uploadDirectory:"/home/lbry/Uploads"},this.routes={},this.update=function(n){if(!n)return console.log("No site config received.");var t=n.analytics,r=n.assetDefaults,a=n.auth,i=n.customComponents,o=n.details,l=n.publishing,s=n.routes;console.log("Configuring site details..."),e.analytics=t,e.assetDefaults=r,e.auth=a,e.details=o,e.publishing=l,e.customComponents=i,e.routes=s}}e.exports=new r},function(e,n,t){"use strict";function r(e,n,t){return{eventCategory:"client requests",eventAction:"serve request",eventLabel:t,ipOverride:n,userAgentOverride:e["user-agent"]}}function a(e,n,t,r,a){return{userTimingCategory:e,userTimingVariableName:n,userTimingTime:a-r,userTimingLabel:t}}function i(e,n){var t=e.replace(/\./g,"-");s(c,t,{strictCidFormat:!1,https:!0}).event(n,function(e){e&&l.error("Google Analytics Event Error >>",e)})}function o(e,n){s(c,e,{strictCidFormat:!1,https:!0}).timing(n,function(e){e&&l.error("Google Analytics Event Error >>",e),l.debug("Timing event successfully sent to google analytics")})}var l=t(0),s=t(55),u=t(3),c=u.analytics.googleId,d=u.details.title;e.exports={sendGAServeEvent:function(e,n,t){i(n,r(e,n,t))},sendGATimingEvent:function(e,n,t,r,i){var l=a(e,n,t,r,i);o(d,l)},chooseGaLbrynetPublishLabel:function(e){var n=e.channel_name,t=e.channel_id;return n||t?"PUBLISH_IN_CHANNEL_CLAIM":"PUBLISH_ANONYMOUS_CLAIM"}}},function(e,n,t){"use strict";var r=t(53),a=t(0),i=t(54),o=i.api,l=o.apiHost,s=o.apiPort,u="http://"+l+":"+s,c=t(4),d=c.chooseGaLbrynetPublishLabel,f=c.sendGATimingEvent,h=function(e,n,t){var r=e.data;if(a.debug("lbry api data:",r),r.result)return r.result.error?(a.debug("Lbrynet api error:",r.result.error),void t(new Error(r.result.error))):void n(r.result);t(JSON.stringify(r))};e.exports={publishClaim:function(e){a.debug('lbryApi >> Publishing claim to "'+e.name+'"');var n=Date.now();return new Promise(function(t,a){r.post(u,{method:"publish",params:e}).then(function(r){f("lbrynet","publish",d(e),n,Date.now()),h(r,t,a)}).catch(function(e){a(e)})})},getClaim:function(e){a.debug('lbryApi >> Getting Claim for "'+e+'"');var n=Date.now();return new Promise(function(t,a){r.post(u,{method:"get",params:{uri:e,timeout:20}}).then(function(e){f("lbrynet","getClaim","GET",n,Date.now()),h(e,t,a)}).catch(function(e){a(e)})})},getClaimList:function(e){a.debug('lbryApi >> Getting claim_list for "'+e+'"');var n=Date.now();return new Promise(function(t,a){r.post(u,{method:"claim_list",params:{name:e}}).then(function(e){f("lbrynet","getClaimList","CLAIM_LIST",n,Date.now()),h(e,t,a)}).catch(function(e){a(e)})})},resolveUri:function(e){a.debug('lbryApi >> Resolving URI for "'+e+'"');var n=Date.now();return new Promise(function(t,a){r.post(u,{method:"resolve",params:{uri:e}}).then(function(r){var i=r.data;f("lbrynet","resolveUri","RESOLVE",n,Date.now()),i.result[e].error?a(i.result[e].error):t(i.result[e])}).catch(function(e){a(e)})})},getDownloadDirectory:function(){a.debug("lbryApi >> Retrieving the download directory path from lbry daemon...");var e=Date.now();return new Promise(function(n,t){r.post(u,{method:"settings_get"}).then(function(t){var r=t.data;if(f("lbrynet","getDownloadDirectory","SETTINGS_GET",e,Date.now()),!r.result)return new Error("Successfully connected to lbry daemon, but unable to retrieve the download directory.");n(r.result.download_directory)}).catch(function(e){a.error("Lbrynet Error:",e),n("/home/lbry/Downloads/")})})},createChannel:function(e){a.debug("lbryApi >> Creating channel for "+e+"...");var n=Date.now();return new Promise(function(t,a){r.post(u,{method:"channel_new",params:{channel_name:e,amount:.1}}).then(function(e){f("lbrynet","createChannel","CHANNEL_NEW",n,Date.now()),h(e,t,a)}).catch(function(e){a(e)})})}}},function(e,n,t){"use strict";var r=function(){function e(e,n){var t=[],r=!0,a=!1,i=void 0;try{for(var o,l=e[Symbol.iterator]();!(r=(o=l.next()).done)&&(t.push(o.value),!n||t.length!==n);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&l.return&&l.return()}finally{if(a)throw i}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),a=t(2),i=t(0),o=t(66),l=o.returnPaginatedChannelClaims;e.exports={getClaimId:function(n,t,r,a){return n?e.exports.getClaimIdByChannel(n,t,r):e.exports.getClaimIdByClaim(r,a)},getClaimIdByClaim:function(e,n){return i.debug("getClaimIdByClaim("+e+", "+n+")"),new Promise(function(t,r){a.Claim.getLongClaimId(e,n).then(function(e){e||t("NO_CLAIM"),t(e)}).catch(function(e){r(e)})})},getClaimIdByChannel:function(e,n,t){return i.debug("getClaimIdByChannel("+e+", "+n+", "+t+")"),new Promise(function(i,o){a.Certificate.getLongChannelId(e,n).then(function(e){return e?Promise.all([e,a.Claim.getClaimIdByLongChannelId(e,t)]):[null,null]}).then(function(e){var n=r(e,2),t=n[0],a=n[1];return t?a?void i(a):i("NO_CLAIM"):i("NO_CHANNEL")}).catch(function(e){o(e)})})},getChannelData:function(e,n,t){return new Promise(function(t,i){a.Certificate.getLongChannelId(e,n).then(function(n){return n?Promise.all([n,a.Certificate.getShortChannelIdFromLongChannelId(n,e)]):[null,null,null]}).then(function(n){var a=r(n,2),i=a[0],o=a[1];if(!i)return t("NO_CHANNEL");t({channelName:e,longChannelClaimId:i,shortChannelClaimId:o})}).catch(function(e){i(e)})})},getChannelClaims:function(e,n,t){return new Promise(function(i,o){a.Certificate.getLongChannelId(e,n).then(function(e){return e?Promise.all([e,a.Claim.getAllChannelClaims(e)]):[null,null,null]}).then(function(n){var a=r(n,2),o=a[0],s=a[1];if(!o)return i("NO_CHANNEL");var u=l(e,o,s,t);i(u)}).catch(function(e){o(e)})})},getLocalFileRecord:function(e,n){return a.File.findOne({where:{claimId:e,name:n}}).then(function(e){return e?e.dataValues:"NO_FILE"})}}},function(e,n,t){"use strict";var r=t(43),a=t(44),i=t(52),o=t(56),l=o.serializeSpeechUser,s=o.deserializeSpeechUser;r.deserializeUser(s),r.serializeUser(l),r.use("local-login",a),r.use("local-signup",i),e.exports=r},function(e,n,t){"use strict";function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}var a=function(){function e(e,n){var t=[],r=!0,a=!1,i=void 0;try{for(var o,l=e[Symbol.iterator]();!(r=(o=l.next()).done)&&(t.push(o.value),!n||t.length!==n);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&l.return&&l.return()}finally{if(a)throw i}}return t}return function(n,t){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=t(0),o=t(2),l=t(5),s=t(9),u=t(3),c=u.publishing,d=c.primaryClaimAddress,f=c.additionalClaimAddresses,h=t(13),m=h.Op;e.exports={publish:function(e,n,t){return new Promise(function(r,u){var c=void 0,d=void 0,f=void 0;return l.publishClaim(e).then(function(t){return i.info("Successfully published "+e.name+" "+n,t),c=t,e.channel_name?(i.debug("this claim was published in channel: "+e.channel_name),o.Channel.findOne({where:{channelName:e.channel_name}})):(i.debug("this claim was not published in a channel"),null)}).then(function(e){d=null,f=null,e&&(d=e.channelClaimId,f=e.channelName),i.debug("certificateId: "+d)}).then(function(){var r={name:e.name,claimId:c.claim_id,title:e.metadata.title,description:e.metadata.description,address:e.claim_address,outpoint:c.txid+":"+c.nout,height:0,fileName:n,filePath:e.file_path,fileType:t,nsfw:e.metadata.nsfw},a={name:e.name,claimId:c.claim_id,title:e.metadata.title,description:e.metadata.description,address:e.claim_address,thumbnail:e.metadata.thumbnail,outpoint:c.txid+":"+c.nout,height:0,contentType:t,nsfw:e.metadata.nsfw,amount:e.bid,certificateId:d,channelName:f},i={name:e.name,claimId:c.claim_id};return Promise.all([o.upsert(o.File,r,i,"File"),o.upsert(o.Claim,a,i,"Claim")])}).then(function(e){var n=a(e,2),t=n[0],r=n[1];return i.debug("File and Claim records successfully created"),Promise.all([t.setClaim(r),r.setFile(t)])}).then(function(){i.debug("File and Claim records successfully associated"),r(c)}).catch(function(n){i.error("PUBLISH ERROR",n),s.deleteTemporaryFile(e.file_path),u(n)})})},claimNameIsAvailable:function(e){var n=f||[];return n.push(d),o.Claim.findAll({attributes:["address"],where:{name:e,address:r({},m.or,n)}}).then(function(n){if(n.length>=1)throw new Error("That claim is already in use");return e}).catch(function(e){throw e})},checkChannelAvailability:function(e){return o.Channel.findAll({where:{channelName:e}}).then(function(n){if(n.length>=1)throw new Error("That channel has already been claimed");return e}).catch(function(e){throw e})}}},function(e,n,t){"use strict";var r=t(0),a=t(64),i=t(3),o=i.details,l=i.publishing;e.exports={parsePublishApiRequestBody:function(e){var n=e.name,t=e.nsfw,r=e.license,a=e.title,i=e.description,o=e.thumbnail;if(!n)throw new Error("no name field found in request");if(/[^A-Za-z0-9,-]/.exec(n))throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and "-"');return t="true"===t,r=r||null,a=a||null,i=i||null,o=o||null,{name:n,nsfw:t,license:r,title:a,description:i,thumbnail:o}},parsePublishApiRequestFiles:function(n){var t=n.file,r=n.thumbnail;if(!t)throw new Error("no file with key of [file] found in request");if(!t.path)throw new Error("no file path found");if(!t.type)throw new Error("no file type found");if(!t.size)throw new Error("no file type found");if(/'/.test(t.name))throw new Error("apostrophes are not allowed in the file name");return e.exports.validateFileTypeAndSize(t),{fileName:t.name,filePath:t.path,fileType:t.type,thumbnailFileName:r?r.name:null,thumbnailFilePath:r?r.path:null,thumbnailFileType:r?r.type:null}},validateFileTypeAndSize:function(e){switch(e.type){case"image/jpeg":case"image/jpg":case"image/png":if(e.size>1e7)throw r.debug("publish > file validation > .jpeg/.jpg/.png was too big"),new Error("Sorry, images are limited to 10 megabytes.");break;case"image/gif":if(e.size>5e7)throw r.debug("publish > file validation > .gif was too big"),new Error("Sorry, .gifs are limited to 50 megabytes.");break;case"video/mp4":if(e.size>5e7)throw r.debug("publish > file validation > .mp4 was too big"),new Error("Sorry, videos are limited to 50 megabytes.");break;default:throw r.debug("publish > file validation > unrecognized file type"),new Error("The "+e.type+" content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.")}return e},createBasicPublishParams:function(e,n,t,a,i,s,u){r.debug("Creating Publish Parameters"),null!==t&&""!==t.trim()||(t=n),null!==a&&""!==a.trim()||(a=""),null!==i&&""!==i.trim()||(i=" ");var c={name:n,file_path:e,bid:.01,metadata:{description:a,title:t,author:o.title,language:"en",license:i,nsfw:s},claim_address:l.primaryClaimAddress};return u&&(c.metadata.thumbnail=u),c},createThumbnailPublishParams:function(e,n,t,a){if(e)return r.debug("Creating Thumbnail Publish Parameters"),{name:n+"-thumb",file_path:e,bid:.01,metadata:{title:n+" thumbnail",description:"a thumbnail for "+n,author:o.title,language:"en",license:t,nsfw:a},claim_address:l.primaryClaimAddress,channel_name:l.thumbnailChannel,channel_id:l.thumbnailChannelId}},deleteTemporaryFile:function(e){a.unlink(e,function(n){if(n)throw r.error("error deleting temporary file "+e),n;r.debug("successfully deleted "+e)})},addGetResultsToFileData:function(e,n){return e.fileName=n.file_name,e.filePath=n.download_path,e},createFileData:function(e){var n=e.name,t=e.claimId,r=e.outpoint,a=e.height,i=e.address,o=e.nsfw;return{name:n,claimId:t,outpoint:r,height:a,address:i,fileName:"",filePath:"",fileType:e.contentType,nsfw:o}}}},function(e,n,t){"use strict";function r(){var e=this;this.database="default",this.username="default",this.password="default",this.update=function(n){if(!n)return a.warn("No MySQL config received.");a.info("configuring mysql...");var t=n.database,r=n.username,i=n.password;e.database=t,e.username=r,e.password=i}}var a=t(0);e.exports=new r},function(e,n){e.exports=require("passport-local")},function(e,n,t){"use strict";e.exports={returnShortId:function(e,n){var t=void 0,r=n.substring(0,1),a=0;if((t=e.findIndex(function(e){return e.claimId===n}))<0)throw new Error("claim id not found in claims list");for(var i=e.slice(0,t);i.length>0;)a+=1,r=n.substring(0,a),i=i.filter(function(e){return e.claimId&&e.claimId.substring(0,a)===r});return r}}},function(e,n){e.exports=require("sequelize")},function(e,n,t){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}var a=t(15),i=r(a),o=t(16),l=t(17),s=t(18),u=t(19),c=t(20),d=t(21),f=r(d),h=t(22),m=r(h);e.exports=function(e,n){var t={},r=(0,l.createStore)(c.Reducers),a=(0,o.renderToString)(i.default.createElement(s.Provider,{store:r},i.default.createElement(u.StaticRouter,{location:e.url,context:t},i.default.createElement(c.GAListener,null,i.default.createElement(c.App,null))))),d=m.default.renderStatic();if(t.url)return n.redirect(301,t.url);var h=r.getState();n.send((0,f.default)(d,a,h))}},function(e,n){e.exports=require("react")},function(e,n){e.exports=require("react-dom/server")},function(e,n){e.exports=require("redux")},function(e,n){e.exports=require("react-redux")},function(e,n){e.exports=require("react-router-dom")},function(e,n){e.exports=require("spee.ch-components")},function(e,n,t){"use strict";e.exports=function(e,n,t){return'\n \n \n \n \n \n \n \x3c!--helmet--\x3e\n '+e.title.toString()+"\n "+e.meta.toString()+"\n "+e.link.toString()+'\n \x3c!--style sheets--\x3e\n \n \n \n \x3c!--google font--\x3e\n \n \n \n
\n
'+n+"
\n
\n \n \n \n \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); +var customizedReducers = (0, _spee.Reducers)(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)(customizedReducers, 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( + _spee.GAListener, + null, + _react2.default.createElement(_spee.App, 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.configureSiteDetails = function (userConfig) { + siteConfig.update(userConfig); + }; + this.configureSlack = function (userConfig) { + slackConfig.update(userConfig); + }; + this.configureClientBundle = function () { + logger.debug('configure the client here by passing in the bundle and configuring it, or better yet: taking in the components to use dynamically from here.'); + }; + 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('/static', express.static(publicFolder)); + logger.info('serving static files from custom path:', publicFolder); + } else { + var publicPath = Path.resolve(__dirname, 'public'); + app.use('/static', 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgODJlYmYyY2EzMDEyOTg0OWU0ZWYiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2luc3RvblwiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9jb25maWcvc2l0ZUNvbmZpZy5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9nb29nbGVBbmFseXRpY3MuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvbGJyeUFwaS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvY29udHJvbGxlcnMvc2VydmVDb250cm9sbGVyLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9zcGVlY2hQYXNzcG9ydC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvY29udHJvbGxlcnMvcHVibGlzaENvbnRyb2xsZXIuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvcHVibGlzaEhlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL215c3FsQ29uZmlnLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInBhc3Nwb3J0LWxvY2FsXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2hlbHBlcnMvc2VxdWVsaXplSGVscGVycy5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJzZXF1ZWxpemVcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9oYW5kbGVQYWdlUmVuZGVyLmpzeCIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWFjdFwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LWRvbS9zZXJ2ZXJcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWR1eFwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LXJlZHV4XCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicmVhY3Qtcm91dGVyLWRvbVwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInNwZWUuY2gtY29tcG9uZW50c1wiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL3JlbmRlckZ1bGxQYWdlLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlYWN0LWhlbG1ldFwiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL3NlcnZlSGVscGVycy5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9sYnJ5VXJpLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2hhbmRsZVNob3dSZW5kZXIuanN4Iiwid2VicGFjazovLy9leHRlcm5hbCBcImJhYmVsLXBvbHlmaWxsXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2hhdHdnLWZldGNoXCIiLCJ3ZWJwYWNrOi8vLy4vc3BlZWNoLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9pbmRleC5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJleHByZXNzXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiYm9keS1wYXJzZXJcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJleHByZXNzLWhhbmRsZWJhcnNcIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJoYW5kbGViYXJzXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiaGVsbWV0XCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiY29va2llLXNlc3Npb25cIiIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJodHRwXCIiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21pZGRsZXdhcmUvcmVxdWVzdExvZ2dlci5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJwYXRoXCIiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL2xvZ2dlckNvbmZpZy5qcyIsIndlYnBhY2s6Ly8vLi9jb25maWcvc2xhY2tDb25maWcuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwid2luc3Rvbi1zbGFjay13ZWJob29rXCIiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicGFzc3BvcnRcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvc3BlZWNoUGFzc3BvcnQvbG9jYWwtbG9naW4uanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9jZXJ0aWZpY2F0ZS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL2NoYW5uZWwuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9jbGFpbS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvbW9kZWxzL2ZpbGUuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL21vZGVscy9yZXF1ZXN0LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9tb2RlbHMvdXNlci5qcyIsIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJiY3J5cHRcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvc3BlZWNoUGFzc3BvcnQvbG9jYWwtc2lnbnVwLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcImF4aW9zXCIiLCJ3ZWJwYWNrOi8vLy4vY29uZmlnL2xicnlDb25maWcuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwidW5pdmVyc2FsLWFuYWx5dGljc1wiIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2F1dGhIZWxwZXJzLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC9pbmRleC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2F1dGgvc2lnbnVwLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC9sb2dpbi5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2F1dGgvbG9nb3V0LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXV0aC91c2VyLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxBdmFpbGFiaWxpdHkuanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwiZnNcIiIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jaGFubmVsQ2xhaW1zLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9oZWxwZXJzL2NoYW5uZWxQYWdpbmF0aW9uLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxEYXRhLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxTaG9ydElkLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltQXZhaWxhYmlsaXR5LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltRGF0YS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUdldC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUxvbmdJZC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbVB1Ymxpc2guanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL2F1dGgvYXV0aGVudGljYXRpb24uanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1SZXNvbHZlLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltU2hvcnRJZC5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUxpc3QuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hcGkvZmlsZUF2YWlsYWJpbGl0eS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvaGVscGVycy9tdWx0aXBhcnRNaWRkbGV3YXJlLmpzIiwid2VicGFjazovLy9leHRlcm5hbCBcImNvbm5lY3QtbXVsdGlwYXJ0eVwiIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvcGFnZXMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kUmVhY3RBcHAuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kRW1iZWRQYWdlLmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvcGFnZXMvcmVkaXJlY3QuanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hc3NldHMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vLy4vc2VydmVyL3JvdXRlcy9hc3NldHMvc2VydmVBc3NldEJ5Q2xhaW0uanMiLCJ3ZWJwYWNrOi8vL2V4dGVybmFsIFwicmVkdXgtc2FnYVwiIiwid2VicGFjazovLy9leHRlcm5hbCBcInJlZHV4LXNhZ2EvZWZmZWN0c1wiIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvYXNzZXRzL3NlcnZlQXNzZXRCeUlkZW50aWZpZXJBbmRDbGFpbS5qcyIsIndlYnBhY2s6Ly8vLi9zZXJ2ZXIvcm91dGVzL2ZhbGxiYWNrL2luZGV4LmpzIiwid2VicGFjazovLy8uL3NlcnZlci9yb3V0ZXMvZmFsbGJhY2svc2VuZFJlYWN0QXBwLmpzIl0sIm5hbWVzIjpbImxvZ2dlciIsInJlcXVpcmUiLCJtb2R1bGUiLCJleHBvcnRzIiwiaGFuZGxlRXJyb3JSZXNwb25zZSIsIm9yaWdpbmFsVXJsIiwiaXAiLCJlcnJvciIsInJlcyIsInVzZU9iamVjdFByb3BlcnRpZXNJZk5vS2V5cyIsInJldHVybkVycm9yTWVzc2FnZUFuZFN0YXR1cyIsInN0YXR1cyIsIm1lc3NhZ2UiLCJqc29uIiwiY3JlYXRlRXJyb3JSZXNwb25zZVBheWxvYWQiLCJjb2RlIiwiZXJyIiwiT2JqZWN0Iiwia2V5cyIsImxlbmd0aCIsIm5ld0Vycm9yT2JqZWN0IiwiZ2V0T3duUHJvcGVydHlOYW1lcyIsImZvckVhY2giLCJrZXkiLCJzdWNjZXNzIiwiQ2VydGlmaWNhdGUiLCJDaGFubmVsIiwiQ2xhaW0iLCJGaWxlIiwiUmVxdWVzdCIsIlVzZXIiLCJTZXF1ZWxpemUiLCJkYXRhYmFzZSIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJzZXF1ZWxpemUiLCJob3N0IiwiZGlhbGVjdCIsImRpYWxlY3RPcHRpb25zIiwiZGVjaW1hbE51bWJlcnMiLCJsb2dnaW5nIiwicG9vbCIsIm1heCIsIm1pbiIsImlkbGUiLCJhY3F1aXJlIiwiYXV0aGVudGljYXRlIiwidGhlbiIsImluZm8iLCJjYXRjaCIsImRiIiwiaW1wb3J0IiwibW9kZWxOYW1lIiwiYXNzb2NpYXRlIiwidXBzZXJ0IiwiTW9kZWwiLCJ2YWx1ZXMiLCJjb25kaXRpb24iLCJ0YWJsZU5hbWUiLCJmaW5kT25lIiwid2hlcmUiLCJvYmoiLCJkZWJ1ZyIsInVwZGF0ZSIsImNyZWF0ZSIsIlNpdGVDb25maWciLCJhbmFseXRpY3MiLCJnb29nbGVJZCIsImFzc2V0RGVmYXVsdHMiLCJkZXNjcmlwdGlvbiIsInRodW1ibmFpbCIsInRpdGxlIiwiYXV0aCIsInNlc3Npb25LZXkiLCJjdXN0b21Db21wb25lbnRzIiwiY29tcG9uZW50cyIsImNvbnRhaW5lcnMiLCJwYWdlcyIsImRldGFpbHMiLCJwb3J0IiwidHdpdHRlciIsInB1Ymxpc2hpbmciLCJhZGRpdGlvbmFsQ2xhaW1BZGRyZXNzZXMiLCJkaXNhYmxlZCIsImRpc2FibGVkTWVzc2FnZSIsInByaW1hcnlDbGFpbUFkZHJlc3MiLCJ0aHVtYm5haWxDaGFubmVsIiwidGh1bWJuYWlsQ2hhbm5lbElkIiwidXBsb2FkRGlyZWN0b3J5Iiwicm91dGVzIiwiY29uZmlnIiwiY29uc29sZSIsImxvZyIsInVhIiwiY3JlYXRlU2VydmVFdmVudFBhcmFtcyIsImhlYWRlcnMiLCJldmVudENhdGVnb3J5IiwiZXZlbnRBY3Rpb24iLCJldmVudExhYmVsIiwiaXBPdmVycmlkZSIsInVzZXJBZ2VudE92ZXJyaWRlIiwiY3JlYXRlUHVibGlzaFRpbWluZ0V2ZW50UGFyYW1zIiwiY2F0ZWdvcnkiLCJ2YXJpYWJsZSIsImxhYmVsIiwic3RhcnRUaW1lIiwiZW5kVGltZSIsImR1cmF0aW9uIiwidXNlclRpbWluZ0NhdGVnb3J5IiwidXNlclRpbWluZ1ZhcmlhYmxlTmFtZSIsInVzZXJUaW1pbmdUaW1lIiwidXNlclRpbWluZ0xhYmVsIiwic2VuZEdvb2dsZUFuYWx5dGljc0V2ZW50IiwicGFyYW1zIiwidmlzaXRvcklkIiwicmVwbGFjZSIsInZpc2l0b3IiLCJzdHJpY3RDaWRGb3JtYXQiLCJodHRwcyIsImV2ZW50Iiwic2VuZEdvb2dsZUFuYWx5dGljc1RpbWluZyIsInRpbWluZyIsInNlbmRHQVNlcnZlRXZlbnQiLCJzZW5kR0FUaW1pbmdFdmVudCIsImNob29zZUdhTGJyeW5ldFB1Ymxpc2hMYWJlbCIsImNoYW5uZWxOYW1lIiwiY2hhbm5lbF9uYW1lIiwiY2hhbm5lbElkIiwiY2hhbm5lbF9pZCIsImF4aW9zIiwiYXBpIiwiYXBpSG9zdCIsImFwaVBvcnQiLCJsYnJ5QXBpVXJpIiwiaGFuZGxlTGJyeW5ldFJlc3BvbnNlIiwicmVzb2x2ZSIsInJlamVjdCIsImRhdGEiLCJyZXN1bHQiLCJFcnJvciIsIkpTT04iLCJzdHJpbmdpZnkiLCJwdWJsaXNoQ2xhaW0iLCJwdWJsaXNoUGFyYW1zIiwibmFtZSIsImdhU3RhcnRUaW1lIiwiRGF0ZSIsIm5vdyIsIlByb21pc2UiLCJwb3N0IiwibWV0aG9kIiwicmVzcG9uc2UiLCJnZXRDbGFpbSIsInVyaSIsInRpbWVvdXQiLCJnZXRDbGFpbUxpc3QiLCJjbGFpbU5hbWUiLCJyZXNvbHZlVXJpIiwiZ2V0RG93bmxvYWREaXJlY3RvcnkiLCJkb3dubG9hZF9kaXJlY3RvcnkiLCJjcmVhdGVDaGFubmVsIiwiYW1vdW50IiwicmV0dXJuUGFnaW5hdGVkQ2hhbm5lbENsYWltcyIsIk5PX0NIQU5ORUwiLCJOT19DTEFJTSIsIk5PX0ZJTEUiLCJnZXRDbGFpbUlkIiwiY2hhbm5lbENsYWltSWQiLCJjbGFpbUlkIiwiZ2V0Q2xhaW1JZEJ5Q2hhbm5lbCIsImdldENsYWltSWRCeUNsYWltIiwiZ2V0TG9uZ0NsYWltSWQiLCJsb25nQ2xhaW1JZCIsImdldExvbmdDaGFubmVsSWQiLCJsb25nQ2hhbm5lbElkIiwiYWxsIiwiZ2V0Q2xhaW1JZEJ5TG9uZ0NoYW5uZWxJZCIsImdldENoYW5uZWxEYXRhIiwicGFnZSIsImxvbmdDaGFubmVsQ2xhaW1JZCIsImdldFNob3J0Q2hhbm5lbElkRnJvbUxvbmdDaGFubmVsSWQiLCJzaG9ydENoYW5uZWxDbGFpbUlkIiwiZ2V0Q2hhbm5lbENsYWltcyIsImdldEFsbENoYW5uZWxDbGFpbXMiLCJjaGFubmVsQ2xhaW1zQXJyYXkiLCJwYWdpbmF0ZWRDaGFubmVsVmlld0RhdGEiLCJnZXRMb2NhbEZpbGVSZWNvcmQiLCJmaWxlIiwiZGF0YVZhbHVlcyIsInBhc3Nwb3J0IiwibG9jYWxMb2dpblN0cmF0ZWd5IiwibG9jYWxTaWdudXBTdHJhdGVneSIsInNlcmlhbGl6ZVNwZWVjaFVzZXIiLCJkZXNlcmlhbGl6ZVNwZWVjaFVzZXIiLCJkZXNlcmlhbGl6ZVVzZXIiLCJzZXJpYWxpemVVc2VyIiwidXNlIiwibGJyeUFwaSIsInB1Ymxpc2hIZWxwZXJzIiwiT3AiLCJwdWJsaXNoIiwiZmlsZU5hbWUiLCJmaWxlVHlwZSIsInB1Ymxpc2hSZXN1bHRzIiwiY2VydGlmaWNhdGVJZCIsInR4IiwiY2hhbm5lbCIsImZpbGVSZWNvcmQiLCJjbGFpbV9pZCIsIm1ldGFkYXRhIiwiYWRkcmVzcyIsImNsYWltX2FkZHJlc3MiLCJvdXRwb2ludCIsInR4aWQiLCJub3V0IiwiaGVpZ2h0IiwiZmlsZVBhdGgiLCJmaWxlX3BhdGgiLCJuc2Z3IiwiY2xhaW1SZWNvcmQiLCJjb250ZW50VHlwZSIsImJpZCIsInVwc2VydENyaXRlcmlhIiwiY2xhaW0iLCJzZXRDbGFpbSIsInNldEZpbGUiLCJkZWxldGVUZW1wb3JhcnlGaWxlIiwiY2xhaW1OYW1lSXNBdmFpbGFibGUiLCJjbGFpbUFkZHJlc3NlcyIsInB1c2giLCJmaW5kQWxsIiwiYXR0cmlidXRlcyIsIm9yIiwiY2hlY2tDaGFubmVsQXZhaWxhYmlsaXR5IiwiZnMiLCJwYXJzZVB1Ymxpc2hBcGlSZXF1ZXN0Qm9keSIsImxpY2Vuc2UiLCJpbnZhbGlkTmFtZUNoYXJhY3RlcnMiLCJleGVjIiwicGFyc2VQdWJsaXNoQXBpUmVxdWVzdEZpbGVzIiwicGF0aCIsInR5cGUiLCJzaXplIiwidGVzdCIsInZhbGlkYXRlRmlsZVR5cGVBbmRTaXplIiwidGh1bWJuYWlsRmlsZU5hbWUiLCJ0aHVtYm5haWxGaWxlUGF0aCIsInRodW1ibmFpbEZpbGVUeXBlIiwiY3JlYXRlQmFzaWNQdWJsaXNoUGFyYW1zIiwidHJpbSIsImF1dGhvciIsImxhbmd1YWdlIiwiY3JlYXRlVGh1bWJuYWlsUHVibGlzaFBhcmFtcyIsInVubGluayIsImFkZEdldFJlc3VsdHNUb0ZpbGVEYXRhIiwiZmlsZUluZm8iLCJnZXRSZXN1bHQiLCJmaWxlX25hbWUiLCJkb3dubG9hZF9wYXRoIiwiY3JlYXRlRmlsZURhdGEiLCJteXNxbCIsIndhcm4iLCJyZXR1cm5TaG9ydElkIiwiY2xhaW1zQXJyYXkiLCJsb25nSWQiLCJjbGFpbUluZGV4Iiwic2hvcnRJZCIsInN1YnN0cmluZyIsInNob3J0SWRMZW5ndGgiLCJmaW5kSW5kZXgiLCJlbGVtZW50IiwicG9zc2libGVNYXRjaGVzIiwic2xpY2UiLCJmaWx0ZXIiLCJzaXRlQ29uZmlnIiwicmVxIiwiY29udGV4dCIsImN1c3RvbWl6ZWRSZWR1Y2VycyIsInN0b3JlIiwiaHRtbCIsInVybCIsImhlbG1ldCIsInJlbmRlclN0YXRpYyIsInJlZGlyZWN0IiwicHJlbG9hZGVkU3RhdGUiLCJnZXRTdGF0ZSIsInNlbmQiLCJ0b1N0cmluZyIsIm1ldGEiLCJsaW5rIiwiU0VSVkUiLCJTSE9XIiwiY2xpZW50QWNjZXB0c0h0bWwiLCJhY2NlcHQiLCJtYXRjaCIsInJlcXVlc3RJc0Zyb21Ccm93c2VyIiwiY2xpZW50V2FudHNBc3NldCIsInJhbmdlIiwiaW1hZ2VJc1dhbnRlZCIsInZpZGVvSXNXYW50ZWQiLCJpc1ZhbGlkQ2xhaW1JZCIsImlzVmFsaWRTaG9ydElkIiwiaXNWYWxpZFNob3J0SWRPckNsYWltSWQiLCJpbnB1dCIsInNlcnZlQXNzZXRUb0NsaWVudCIsInZlcmJvc2UiLCJzZW5kRmlsZU9wdGlvbnMiLCJzZW5kRmlsZSIsImdldENsYWltSWRBbmRTZXJ2ZUFzc2V0IiwiZnVsbENsYWltSWQiLCJkZXRlcm1pbmVSZXNwb25zZVR5cGUiLCJoYXNGaWxlRXh0ZW5zaW9uIiwicmVzcG9uc2VUeXBlIiwiZmxpcENsYWltTmFtZUFuZElkRm9yQmFja3dhcmRzQ29tcGF0aWJpbGl0eSIsImlkZW50aWZpZXIiLCJ0ZW1wTmFtZSIsImxvZ1JlcXVlc3REYXRhIiwiUkVHRVhQX0lOVkFMSURfQ0xBSU0iLCJSRUdFWFBfSU5WQUxJRF9DSEFOTkVMIiwiUkVHRVhQX0FERFJFU1MiLCJDSEFOTkVMX0NIQVIiLCJwYXJzZUlkZW50aWZpZXIiLCJjb21wb25lbnRzUmVnZXgiLCJSZWdFeHAiLCJtYXAiLCJwcm90byIsInZhbHVlIiwibW9kaWZpZXJTZXBlcmF0b3IiLCJtb2RpZmllciIsImlzQ2hhbm5lbCIsInN0YXJ0c1dpdGgiLCJuYW1lQmFkQ2hhcnMiLCJqb2luIiwicGFyc2VDbGFpbSIsInBhcnNlTW9kaWZpZXIiLCJyZXR1cm5TYWdhV2l0aFBhcmFtcyIsInNhZ2EiLCJzYWdhTWlkZGxld2FyZSIsIm1pZGRsZXdhcmUiLCJhY3Rpb24iLCJvbkhhbmRsZVNob3dQYWdlVXJpIiwiaGFuZGxlU2hvd1BhZ2VVcmkiLCJydW4iLCJkb25lIiwiU2VydmVyIiwiZXhwcmVzcyIsImJvZHlQYXJzZXIiLCJleHByZXNzSGFuZGxlYmFycyIsIkhhbmRsZWJhcnMiLCJjb29raWVTZXNzaW9uIiwiaHR0cCIsInJlcXVlc3RMb2dnZXIiLCJQYXRoIiwibG9nZ2VyQ29uZmlnIiwibXlzcWxDb25maWciLCJzbGFja0NvbmZpZyIsImNvbmZpZ3VyZUxvZ2dlciIsInVzZXJDb25maWciLCJjb25maWd1cmVNeXNxbCIsImNvbmZpZ3VyZVNpdGVEZXRhaWxzIiwiY29uZmlndXJlU2xhY2siLCJjb25maWd1cmVDbGllbnRCdW5kbGUiLCJjb25maWd1cmVNb2RlbHMiLCJjb25maWd1cmVSb3V0ZXMiLCJjcmVhdGVBcHAiLCJhcHAiLCJlbmFibGUiLCJwdWJsaWNGb2xkZXIiLCJwcm9jZXNzIiwiY3dkIiwic3RhdGljIiwicHVibGljUGF0aCIsIl9fZGlybmFtZSIsInVybGVuY29kZWQiLCJleHRlbmRlZCIsInNwZWVjaFBhc3Nwb3J0IiwibWF4QWdlIiwiaW5pdGlhbGl6ZSIsInNlc3Npb24iLCJoYnMiLCJkZWZhdWx0TGF5b3V0IiwiaGFuZGxlYmFycyIsImVuZ2luZSIsInNldCIsInNlcnZlciIsInN0YXJ0IiwiUE9SVCIsInN5bmMiLCJsaXN0ZW4iLCJuZXh0IiwiTG9nZ2VyQ29uZmlnIiwibG9nTGV2ZWwiLCJjb25maWd1cmUiLCJ0cmFuc3BvcnRzIiwiQ29uc29sZSIsImxldmVsIiwidGltZXN0YW1wIiwiY29sb3JpemUiLCJwcmV0dHlQcmludCIsImhhbmRsZUV4Y2VwdGlvbnMiLCJodW1hblJlYWRhYmxlVW5oYW5kbGVkRXhjZXB0aW9uIiwic2lsbHkiLCJ3aW5zdG9uU2xhY2tXZWJIb29rIiwiU2xhY2tXZWJIb29rIiwid2luc3RvbiIsIlNsYWNrQ29uZmlnIiwic2xhY2tXZWJIb29rIiwic2xhY2tFcnJvckNoYW5uZWwiLCJzbGFja0luZm9DaGFubmVsIiwiYWRkIiwid2ViaG9va1VybCIsImljb25FbW9qaSIsIlBhc3Nwb3J0TG9jYWxTdHJhdGVneSIsIlN0cmF0ZWd5IiwicmV0dXJuVXNlckFuZENoYW5uZWxJbmZvIiwidXNlckluc3RhbmNlIiwidXNlckluZm8iLCJpZCIsInVzZXJOYW1lIiwiZ2V0Q2hhbm5lbCIsInNob3J0Q2hhbm5lbElkIiwidXNlcm5hbWVGaWVsZCIsInBhc3N3b3JkRmllbGQiLCJ1c2VyIiwiY29tcGFyZVBhc3N3b3JkIiwiaXNNYXRjaCIsIlNUUklORyIsIkJPT0xFQU4iLCJJTlRFR0VSIiwiVEVYVCIsIkRFQ0lNQUwiLCJkZWZpbmUiLCJkZWZhdWx0IiwiY2xhaW1TZXF1ZW5jZSIsImRlY29kZWRDbGFpbSIsImRlcHRoIiwiZWZmZWN0aXZlQW1vdW50IiwiaGFzU2lnbmF0dXJlIiwiaGV4IiwidmFsaWRBdEhlaWdodCIsInZhbHVlVmVyc2lvbiIsImNsYWltVHlwZSIsImNlcnRpZmljYXRlVmVyc2lvbiIsImtleVR5cGUiLCJwdWJsaWNLZXkiLCJmcmVlemVUYWJsZU5hbWUiLCJiZWxvbmdzVG8iLCJmb3JlaWduS2V5IiwiYWxsb3dOdWxsIiwib3JkZXIiLCJnZXRMb25nQ2hhbm5lbElkRnJvbVNob3J0Q2hhbm5lbElkIiwiJGxpa2UiLCJnZXRMb25nQ2hhbm5lbElkRnJvbUNoYW5uZWxOYW1lIiwidmFsaWRhdGVMb25nQ2hhbm5lbElkIiwiaGFzT25lIiwiZGVmYXVsdFRodW1ibmFpbCIsImRldGVybWluZUZpbGVFeHRlbnNpb25Gcm9tQ29udGVudFR5cGUiLCJkZXRlcm1pbmVUaHVtYm5haWwiLCJzdG9yZWRUaHVtYm5haWwiLCJwcmVwYXJlQ2xhaW1EYXRhIiwibGljZW5zZVVybCIsInByZXZpZXciLCJtZXRhZGF0YVZlcnNpb24iLCJzb3VyY2UiLCJzb3VyY2VUeXBlIiwic291cmNlVmVyc2lvbiIsInN0cmVhbVZlcnNpb24iLCJnZXRTaG9ydENsYWltSWRGcm9tTG9uZ0NsYWltSWQiLCJyYXciLCJnZXRMb25nQ2xhaW1JZEZyb21TaG9ydENsYWltSWQiLCJnZXRUb3BGcmVlQ2xhaW1JZEJ5Q2xhaW1OYW1lIiwidmFsaWRhdGVMb25nQ2xhaW1JZCIsInJlc29sdmVDbGFpbSIsImNsYWltQXJyYXkiLCJkZWZhdWx0VmFsdWUiLCJ0cmVuZGluZ0VsaWdpYmxlIiwiaGFzTWFueSIsImdldFJlY2VudENsYWltcyIsImxpbWl0IiwiaXBBZGRyZXNzIiwiYmNyeXB0IiwicHJvdG90eXBlIiwiY29tcGFyZSIsImNoYW5nZVBhc3N3b3JkIiwibmV3UGFzc3dvcmQiLCJnZW5TYWx0Iiwic2FsdEVycm9yIiwic2FsdCIsImhhc2giLCJoYXNoRXJyb3IiLCJob29rIiwib3B0aW9ucyIsInVzZXJEYXRhIiwiY2hhbm5lbERhdGEiLCJjZXJ0aWZpY2F0ZURhdGEiLCJuZXdVc2VyIiwibmV3Q2hhbm5lbCIsIm5ld0NlcnRpZmljYXRlIiwic2V0Q2hhbm5lbCIsInNldFVzZXIiLCJsYnJ5Q29uZmlnIiwiaGFuZGxlU2lnbnVwUmVxdWVzdCIsImhhbmRsZUxvZ2luUmVxdWVzdCIsImhhbmRsZUxvZ291dFJlcXVlc3QiLCJoYW5kbGVVc2VyUmVxdWVzdCIsImdldCIsInNpZ251cCIsImxvZ2luIiwibG9nSW4iLCJsb2dvdXQiLCJjaGFubmVsQXZhaWxhYmlsaXR5IiwiY2hhbm5lbENsYWltcyIsImNoYW5uZWxTaG9ydElkIiwiY2xhaW1BdmFpbGFiaWxpdHkiLCJjbGFpbURhdGEiLCJjbGFpbUdldCIsImNsYWltTG9uZ0lkIiwiY2xhaW1QdWJsaXNoIiwiY2xhaW1SZXNvbHZlIiwiY2xhaW1TaG9ydElkIiwiY2xhaW1MaXN0IiwiZmlsZUF2YWlsYWJpbGl0eSIsIm11bHRpcGFydE1pZGRsZXdhcmUiLCJhdmFpbGFibGVOYW1lIiwiYm9keSIsIkNMQUlNU19QRVJfUEFHRSIsImNsYWltcyIsInRvdGFsUGFnZXMiLCJkZXRlcm1pbmVUb3RhbFBhZ2VzIiwicGFnaW5hdGlvblBhZ2UiLCJnZXRQYWdlRnJvbVF1ZXJ5Iiwidmlld0RhdGEiLCJleHRyYWN0UGFnZUZyb21DbGFpbXMiLCJwcmV2aW91c1BhZ2UiLCJkZXRlcm1pbmVQcmV2aW91c1BhZ2UiLCJjdXJyZW50UGFnZSIsIm5leHRQYWdlIiwiZGV0ZXJtaW5lTmV4dFBhZ2UiLCJ0b3RhbFJlc3VsdHMiLCJkZXRlcm1pbmVUb3RhbENsYWltcyIsInBhcnNlSW50IiwicGFnZU51bWJlciIsImNsYWltU3RhcnRJbmRleCIsImNsYWltRW5kSW5kZXgiLCJwYWdlT2ZDbGFpbXMiLCJ0b3RhbENsYWltcyIsImZ1bGxQYWdlcyIsIk1hdGgiLCJmbG9vciIsInJlbWFpbmRlciIsImNoYW5uZWxTaG9ydElkUm91dGUiLCJjbGFpbUluZm8iLCJyZXNvbHZlUmVzdWx0IiwiZmlsZURhdGEiLCJjb21wbGV0ZWQiLCJhdXRoZW50aWNhdGVVc2VyIiwiZmlsZXMiLCJjaGFubmVsUGFzc3dvcmQiLCJ2YWxpZGF0ZWRDbGFpbU5hbWUiLCJ0aHVtYm5haWxQdWJsaXNoUGFyYW1zIiwibGJyeVR4IiwiYXV0aGVudGljYXRlQ2hhbm5lbENyZWRlbnRpYWxzIiwidXNlclBhc3N3b3JkIiwiY2hhbm5lbEZpbmRQYXJhbXMiLCJyZXNvbHZlZFVyaSIsImNsYWltc0xpc3QiLCJtdWx0aXBhcnQiLCJ1cGxvYWREaXIiLCJoYW5kbGVQYWdlUmVxdWVzdCIsImhhbmRsZUVtYmVkUmVxdWVzdCIsImhhbmRsZVBhZ2VSZW5kZXIiLCJzZW5kUmVhY3RBcHAiLCJzZW5kRW1iZWRQYWdlIiwicmVuZGVyIiwibGF5b3V0Iiwicm91dGUiLCJzZXJ2ZUFzc2V0QnlDbGFpbSIsInNlcnZlQXNzZXRCeUlkZW50aWZpZXJBbmRDbGFpbSIsImxicnlVcmkiLCJoYW5kbGVTaG93UmVuZGVyIiwic2VydmVyQXNzZXRCeUNsYWltIiwic2VydmVyQXNzZXRCeUlkZW50aWZpZXJBbmRDbGFpbSJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7OztBQzdEQSxvQzs7Ozs7Ozs7Ozs7QUNBQSxJQUFNQSxTQUFTLG1CQUFBQyxDQUFRLENBQVIsQ0FBZjs7QUFFQUMsT0FBT0MsT0FBUCxHQUFpQjtBQUNmQyx1QkFBcUIsNkJBQVVDLFdBQVYsRUFBdUJDLEVBQXZCLEVBQTJCQyxLQUEzQixFQUFrQ0MsR0FBbEMsRUFB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bW9kdWxlIGNhY2hlXG4gXHR2YXIgaW5zdGFsbGVkTW9kdWxlcyA9IHt9O1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCIvXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMjYpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHdlYnBhY2svYm9vdHN0cmFwIDgyZWJmMmNhMzAxMjk4NDllNGVmIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwid2luc3RvblwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcIndpbnN0b25cIlxuLy8gbW9kdWxlIGlkID0gMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBoYW5kbGVFcnJvclJlc3BvbnNlOiBmdW5jdGlvbiAob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKSB7XG4gICAgbG9nZ2VyLmVycm9yKGBFcnJvciBvbiAke29yaWdpbmFsVXJsfWAsIG1vZHVsZS5leHBvcnRzLnVzZU9iamVjdFByb3BlcnRpZXNJZk5vS2V5cyhlcnJvcikpO1xuICAgIGNvbnN0IFtzdGF0dXMsIG1lc3NhZ2VdID0gbW9kdWxlLmV4cG9ydHMucmV0dXJuRXJyb3JNZXNzYWdlQW5kU3RhdHVzKGVycm9yKTtcbiAgICByZXNcbiAgICAgIC5zdGF0dXMoc3RhdHVzKVxuICAgICAgLmpzb24obW9kdWxlLmV4cG9ydHMuY3JlYXRlRXJyb3JSZXNwb25zZVBheWxvYWQoc3RhdHVzLCBtZXNzYWdlKSk7XG4gIH0sXG4gIHJldHVybkVycm9yTWVzc2FnZUFuZFN0YXR1czogZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgbGV0IHN0YXR1cywgbWVzc2FnZTtcbiAgICAvLyBjaGVjayBmb3IgZGFlbW9uIGJlaW5nIHR1cm5lZCBvZmZcbiAgICBpZiAoZXJyb3IuY29kZSA9PT0gJ0VDT05OUkVGVVNFRCcpIHtcbiAgICAgIHN0YXR1cyA9IDUwMztcbiAgICAgIG1lc3NhZ2UgPSAnQ29ubmVjdGlvbiByZWZ1c2VkLiAgVGhlIGRhZW1vbiBtYXkgbm90IGJlIHJ1bm5pbmcuJztcbiAgICAgIC8vIGZhbGxiYWNrIGZvciBldmVyeXRoaW5nIGVsc2VcbiAgICB9IGVsc2Uge1xuICAgICAgc3RhdHVzID0gNDAwO1xuICAgICAgaWYgKGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtZXNzYWdlID0gZXJyb3I7XG4gICAgICB9O1xuICAgIH07XG4gICAgcmV0dXJuIFtzdGF0dXMsIG1lc3NhZ2VdO1xuICB9LFxuICB1c2VPYmplY3RQcm9wZXJ0aWVzSWZOb0tleXM6IGZ1bmN0aW9uIChlcnIpIHtcbiAgICBpZiAoT2JqZWN0LmtleXMoZXJyKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGxldCBuZXdFcnJvck9iamVjdCA9IHt9O1xuICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoZXJyKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgbmV3RXJyb3JPYmplY3Rba2V5XSA9IGVycltrZXldO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmV3RXJyb3JPYmplY3Q7XG4gICAgfVxuICAgIHJldHVybiBlcnI7XG4gIH0sXG4gIGNyZWF0ZUVycm9yUmVzcG9uc2VQYXlsb2FkIChzdGF0dXMsIG1lc3NhZ2UpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhdHVzLFxuICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICBtZXNzYWdlLFxuICAgIH07XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcyIsImNvbnN0IENlcnRpZmljYXRlID0gcmVxdWlyZSgnbW9kZWxzL2NlcnRpZmljYXRlLmpzJyk7XG5jb25zdCBDaGFubmVsID0gcmVxdWlyZSgnbW9kZWxzL2NoYW5uZWwuanMnKTtcbmNvbnN0IENsYWltID0gcmVxdWlyZSgnbW9kZWxzL2NsYWltLmpzJyk7XG5jb25zdCBGaWxlID0gcmVxdWlyZSgnbW9kZWxzL2ZpbGUuanMnKTtcbmNvbnN0IFJlcXVlc3QgPSByZXF1aXJlKCdtb2RlbHMvcmVxdWVzdC5qcycpO1xuY29uc3QgVXNlciA9IHJlcXVpcmUoJ21vZGVscy91c2VyLmpzJyk7XG5cbmNvbnN0IFNlcXVlbGl6ZSA9IHJlcXVpcmUoJ3NlcXVlbGl6ZScpO1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5jb25zdCB7ZGF0YWJhc2UsIHVzZXJuYW1lLCBwYXNzd29yZH0gPSByZXF1aXJlKCdteXNxbENvbmZpZy5qcycpO1xuXG4vLyBzZXQgc2VxdWVsaXplIG9wdGlvbnNcbmNvbnN0IHNlcXVlbGl6ZSA9IG5ldyBTZXF1ZWxpemUoZGF0YWJhc2UsIHVzZXJuYW1lLCBwYXNzd29yZCwge1xuICBob3N0ICAgICAgICAgIDogJ2xvY2FsaG9zdCcsXG4gIGRpYWxlY3QgICAgICAgOiAnbXlzcWwnLFxuICBkaWFsZWN0T3B0aW9uczoge2RlY2ltYWxOdW1iZXJzOiB0cnVlfSxcbiAgbG9nZ2luZyAgICAgICA6IGZhbHNlLFxuICBwb29sICAgICAgICAgIDoge1xuICAgIG1heCAgICA6IDUsXG4gICAgbWluICAgIDogMCxcbiAgICBpZGxlICAgOiAxMDAwMCxcbiAgICBhY3F1aXJlOiAxMDAwMCxcbiAgfSxcbn0pO1xuXG4vLyBlc3RhYmxpc2ggbXlzcWwgY29ubmVjdGlvblxuc2VxdWVsaXplXG4gIC5hdXRoZW50aWNhdGUoKVxuICAudGhlbigoKSA9PiB7XG4gICAgbG9nZ2VyLmluZm8oJ1NlcXVlbGl6ZSBoYXMgZXN0YWJsaXNoZWQgbXlzcWwgY29ubmVjdGlvbiBzdWNjZXNzZnVsbHkuJyk7XG4gIH0pXG4gIC5jYXRjaChlcnIgPT4ge1xuICAgIGxvZ2dlci5lcnJvcignU2VxdWVsaXplIHdhcyB1bmFibGUgdG8gY29ubmVjdCB0byB0aGUgZGF0YWJhc2U6JywgZXJyKTtcbiAgfSk7XG5cbi8vIG1hbnVhbGx5IGFkZCBlYWNoIG1vZGVsIHRvIHRoZSBkYiBvYmplY3QgKG5vdGU6IG1ha2UgdGhpcyBkeW5hbWljKVxuY29uc3QgZGIgPSB7fTtcbmRiWydDZXJ0aWZpY2F0ZSddID0gc2VxdWVsaXplLmltcG9ydCgnQ2VydGlmaWNhdGUnLCBDZXJ0aWZpY2F0ZSk7XG5kYlsnQ2hhbm5lbCddID0gc2VxdWVsaXplLmltcG9ydCgnQ2hhbm5lbCcsIENoYW5uZWwpO1xuZGJbJ0NsYWltJ10gPSBzZXF1ZWxpemUuaW1wb3J0KCdDbGFpbScsIENsYWltKTtcbmRiWydGaWxlJ10gPSBzZXF1ZWxpemUuaW1wb3J0KCdGaWxlJywgRmlsZSk7XG5kYlsnUmVxdWVzdCddID0gc2VxdWVsaXplLmltcG9ydCgnUmVxdWVzdCcsIFJlcXVlc3QpO1xuZGJbJ1VzZXInXSA9IHNlcXVlbGl6ZS5pbXBvcnQoJ1VzZXInLCBVc2VyKTtcblxuLy8gcnVuIG1vZGVsLmFzc29jaWF0aW9uIGZvciBlYWNoIG1vZGVsIGluIHRoZSBkYiBvYmplY3QgdGhhdCBoYXMgYW4gYXNzb2NpYXRpb25cbmxvZ2dlci5pbmZvKCdhc3NvY2lhdGluZyBkYiBtb2RlbHMuLi4nKTtcbk9iamVjdC5rZXlzKGRiKS5mb3JFYWNoKG1vZGVsTmFtZSA9PiB7XG4gIGlmIChkYlttb2RlbE5hbWVdLmFzc29jaWF0ZSkge1xuICAgIGxvZ2dlci5pbmZvKCdBc3NvY2lhdGluZyBtb2RlbDonLCBtb2RlbE5hbWUpO1xuICAgIGRiW21vZGVsTmFtZV0uYXNzb2NpYXRlKGRiKTtcbiAgfVxufSk7XG5cbi8vIGFkZCBzZXF1ZWxpemUvU2VxdWVsaXplIHRvIGRiXG5kYi5zZXF1ZWxpemUgPSBzZXF1ZWxpemU7XG5kYi5TZXF1ZWxpemUgPSBTZXF1ZWxpemU7XG4vLyBhZGQgYW4gJ3Vwc2VydCcgbWV0aG9kIHRvIHRoZSBkYiBvYmplY3RcbmRiLnVwc2VydCA9IChNb2RlbCwgdmFsdWVzLCBjb25kaXRpb24sIHRhYmxlTmFtZSkgPT4ge1xuICByZXR1cm4gTW9kZWxcbiAgICAuZmluZE9uZSh7XG4gICAgICB3aGVyZTogY29uZGl0aW9uLFxuICAgIH0pXG4gICAgLnRoZW4ob2JqID0+IHtcbiAgICAgIGlmIChvYmopIHsgIC8vIHVwZGF0ZVxuICAgICAgICBsb2dnZXIuZGVidWcoYHVwZGF0aW5nIHJlY29yZCBpbiBkYi4ke3RhYmxlTmFtZX1gKTtcbiAgICAgICAgcmV0dXJuIG9iai51cGRhdGUodmFsdWVzKTtcbiAgICAgIH0gZWxzZSB7ICAvLyBpbnNlcnRcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBjcmVhdGluZyByZWNvcmQgaW4gZGIuJHt0YWJsZU5hbWV9YCk7XG4gICAgICAgIHJldHVybiBNb2RlbC5jcmVhdGUodmFsdWVzKTtcbiAgICAgIH1cbiAgICB9KVxuICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgJHt0YWJsZU5hbWV9LnVwc2VydCBlcnJvcmAsIGVycm9yKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBkYjtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9tb2RlbHMvaW5kZXguanMiLCJmdW5jdGlvbiBTaXRlQ29uZmlnICgpIHtcbiAgdGhpcy5hbmFseXRpY3MgPSB7XG4gICAgZ29vZ2xlSWQ6ICdkZWZhdWx0JyxcbiAgfTtcbiAgdGhpcy5hc3NldERlZmF1bHRzID0ge1xuICAgIGRlc2NyaXB0aW9uOiAnQW4gYXNzZXQgcHVibGlzaGVkIG9uIFNwZWUuY2gnLFxuICAgIHRodW1ibmFpbCAgOiAnaHR0cHM6Ly9zcGVlLmNoL2Fzc2V0cy9pbWcvdmlkZW9fdGh1bWJfZGVmYXVsdC5wbmcnLFxuICAgIHRpdGxlICAgICAgOiAnU3BlZS5jaCcsXG4gIH07XG4gIHRoaXMuYXV0aCA9IHtcbiAgICBzZXNzaW9uS2V5OiAnZGVmYXVsdCcsXG4gIH07XG4gIHRoaXMuY3VzdG9tQ29tcG9uZW50cyA9IHtcbiAgICBjb21wb25lbnRzOiB7fSxcbiAgICBjb250YWluZXJzOiB7fSxcbiAgICBwYWdlcyAgICAgOiB7fSxcbiAgfTtcbiAgdGhpcy5kZXRhaWxzID0ge1xuICAgIGRlc2NyaXB0aW9uOiAnT3Blbi1zb3VyY2UsIGRlY2VudHJhbGl6ZWQgaW1hZ2UgYW5kIHZpZGVvIHNoYXJpbmcuJyxcbiAgICBob3N0ICAgICAgIDogJ2RlZmF1bHQnLFxuICAgIHBvcnQgICAgICAgOiAzMDAwLFxuICAgIHRpdGxlICAgICAgOiAnU3BlZS5jaCcsXG4gICAgdHdpdHRlciAgICA6ICdAc3BlZV9jaCcsXG4gIH07XG4gIHRoaXMucHVibGlzaGluZyA9IHtcbiAgICBhZGRpdGlvbmFsQ2xhaW1BZGRyZXNzZXM6IFtdLFxuICAgIGRpc2FibGVkICAgICAgICAgICAgICAgIDogZmFsc2UsXG4gICAgZGlzYWJsZWRNZXNzYWdlICAgICAgICAgOiAnUGxlYXNlIGNoZWNrIGJhY2sgc29vbi4nLFxuICAgIHByaW1hcnlDbGFpbUFkZHJlc3MgICAgIDogJ2RlZmF1bHQnLFxuICAgIHRodW1ibmFpbENoYW5uZWwgICAgICAgIDogJ2RlZmF1bHQnLFxuICAgIHRodW1ibmFpbENoYW5uZWxJZCAgICAgIDogJ2RlZmF1bHQnLFxuICAgIHVwbG9hZERpcmVjdG9yeSAgICAgICAgIDogJy9ob21lL2xicnkvVXBsb2FkcycsXG4gIH07XG4gIHRoaXMucm91dGVzID0ge307XG4gIHRoaXMudXBkYXRlID0gKGNvbmZpZykgPT4ge1xuICAgIGlmICghY29uZmlnKSB7XG4gICAgICByZXR1cm4gY29uc29sZS5sb2coJ05vIHNpdGUgY29uZmlnIHJlY2VpdmVkLicpO1xuICAgIH1cbiAgICBjb25zdCB7IGFuYWx5dGljcywgYXNzZXREZWZhdWx0cywgYXV0aCwgY3VzdG9tQ29tcG9uZW50cywgZGV0YWlscywgcHVibGlzaGluZywgcm91dGVzIH0gPSBjb25maWc7XG4gICAgY29uc29sZS5sb2coJ0NvbmZpZ3VyaW5nIHNpdGUgZGV0YWlscy4uLicpO1xuICAgIHRoaXMuYW5hbHl0aWNzID0gYW5hbHl0aWNzO1xuICAgIHRoaXMuYXNzZXREZWZhdWx0cyA9IGFzc2V0RGVmYXVsdHM7XG4gICAgdGhpcy5hdXRoID0gYXV0aDtcbiAgICB0aGlzLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgIHRoaXMucHVibGlzaGluZyA9IHB1Ymxpc2hpbmc7XG4gICAgdGhpcy5jdXN0b21Db21wb25lbnRzID0gY3VzdG9tQ29tcG9uZW50cztcbiAgICB0aGlzLnJvdXRlcyA9IHJvdXRlcztcbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFNpdGVDb25maWcoKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL2NvbmZpZy9zaXRlQ29uZmlnLmpzIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgdWEgPSByZXF1aXJlKCd1bml2ZXJzYWwtYW5hbHl0aWNzJyk7XG5jb25zdCB7IGFuYWx5dGljcyA6IHsgZ29vZ2xlSWQgfSwgZGV0YWlsczogeyB0aXRsZSB9IH0gPSByZXF1aXJlKCcuLi8uLi9jb25maWcvc2l0ZUNvbmZpZy5qcycpO1xuXG5mdW5jdGlvbiBjcmVhdGVTZXJ2ZUV2ZW50UGFyYW1zIChoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwpIHtcbiAgcmV0dXJuIHtcbiAgICBldmVudENhdGVnb3J5ICAgIDogJ2NsaWVudCByZXF1ZXN0cycsXG4gICAgZXZlbnRBY3Rpb24gICAgICA6ICdzZXJ2ZSByZXF1ZXN0JyxcbiAgICBldmVudExhYmVsICAgICAgIDogb3JpZ2luYWxVcmwsXG4gICAgaXBPdmVycmlkZSAgICAgICA6IGlwLFxuICAgIHVzZXJBZ2VudE92ZXJyaWRlOiBoZWFkZXJzWyd1c2VyLWFnZW50J10sXG4gIH07XG59O1xuXG5mdW5jdGlvbiBjcmVhdGVQdWJsaXNoVGltaW5nRXZlbnRQYXJhbXMgKGNhdGVnb3J5LCB2YXJpYWJsZSwgbGFiZWwsIHN0YXJ0VGltZSwgZW5kVGltZSkge1xuICBjb25zdCBkdXJhdGlvbiA9IGVuZFRpbWUgLSBzdGFydFRpbWU7XG4gIHJldHVybiB7XG4gICAgdXNlclRpbWluZ0NhdGVnb3J5ICAgIDogY2F0ZWdvcnksXG4gICAgdXNlclRpbWluZ1ZhcmlhYmxlTmFtZTogdmFyaWFibGUsXG4gICAgdXNlclRpbWluZ1RpbWUgICAgICAgIDogZHVyYXRpb24sXG4gICAgdXNlclRpbWluZ0xhYmVsICAgICAgIDogbGFiZWwsXG4gIH07XG59O1xuXG5mdW5jdGlvbiBzZW5kR29vZ2xlQW5hbHl0aWNzRXZlbnQgKGlwLCBwYXJhbXMpIHtcbiAgY29uc3QgdmlzaXRvcklkID0gaXAucmVwbGFjZSgvXFwuL2csICctJyk7XG4gIGNvbnN0IHZpc2l0b3IgPSB1YShnb29nbGVJZCwgdmlzaXRvcklkLCB7IHN0cmljdENpZEZvcm1hdDogZmFsc2UsIGh0dHBzOiB0cnVlIH0pO1xuICB2aXNpdG9yLmV2ZW50KHBhcmFtcywgKGVycikgPT4ge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignR29vZ2xlIEFuYWx5dGljcyBFdmVudCBFcnJvciA+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+IHtcbiAgICAgICAgcmV0dXJuIChlbGVtZW50LmNsYWltSWQgJiYgKGVsZW1lbnQuY2xhaW1JZC5zdWJzdHJpbmcoMCwgc2hvcnRJZExlbmd0aCkgPT09IHNob3J0SWQpKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gc2hvcnRJZDtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9zZXF1ZWxpemVIZWxwZXJzLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwic2VxdWVsaXplXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwic2VxdWVsaXplXCJcbi8vIG1vZHVsZSBpZCA9IDEzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyByZW5kZXJUb1N0cmluZyB9IGZyb20gJ3JlYWN0LWRvbS9zZXJ2ZXInO1xuaW1wb3J0IHsgY3JlYXRlU3RvcmUgfSBmcm9tICdyZWR1eCc7XG5pbXBvcnQgeyBQcm92aWRlciB9IGZyb20gJ3JlYWN0LXJlZHV4JztcbmltcG9ydCB7IFN0YXRpY1JvdXRlciB9IGZyb20gJ3JlYWN0LXJvdXRlci1kb20nO1xuaW1wb3J0IHsgUmVkdWNlcnMsIEdBTGlzdGVuZXIsIEFwcCB9IGZyb20gJ3NwZWUuY2gtY29tcG9uZW50cyc7XG5pbXBvcnQgcmVuZGVyRnVsbFBhZ2UgZnJvbSAnLi9yZW5kZXJGdWxsUGFnZS5qcyc7XG5pbXBvcnQgSGVsbWV0IGZyb20gJ3JlYWN0LWhlbG1ldCc7XG5cbmNvbnN0IHNpdGVDb25maWcgPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKHJlcSwgcmVzKSA9PiB7XG4gIGxldCBjb250ZXh0ID0ge307XG5cbiAgLy8gY3VzdG9taXplIHRoZSByZWR1Y2VyIGJ5IHBhc3NpbmcgaW4gaW50aWFsIHN0YXRlIGNvbmZpZ3NcbiAgY29uc3QgY3VzdG9taXplZFJlZHVjZXJzID0gUmVkdWNlcnMoc2l0ZUNvbmZpZyk7XG5cbiAgLy8gY3JlYXRlIGEgbmV3IFJlZHV4IHN0b3JlIGluc3RhbmNlXG4gIGNvbnN0IHN0b3JlID0gY3JlYXRlU3RvcmUoY3VzdG9taXplZFJlZHVjZXJzKTtcblxuICAvLyByZW5kZXIgY29tcG9uZW50IHRvIGEgc3RyaW5nXG4gIGNvbnN0IGh0bWwgPSByZW5kZXJUb1N0cmluZyhcbiAgICA8UHJvdmlkZXIgc3RvcmU9e3N0b3JlfT5cbiAgICAgIDxTdGF0aWNSb3V0ZXIgbG9jYXRpb249e3JlcS51cmx9IGNvbnRleHQ9e2NvbnRleHR9PlxuICAgICAgICA8R0FMaXN0ZW5lcj5cbiAgICAgICAgICA8QXBwIC8+XG4gICAgICAgIDwvR0FMaXN0ZW5lcj5cbiAgICAgIDwvU3RhdGljUm91dGVyPlxuICAgIDwvUHJvdmlkZXI+XG4gICk7XG5cbiAgLy8gZ2V0IGhlYWQgdGFncyBmcm9tIGhlbG1ldFxuICBjb25zdCBoZWxtZXQgPSBIZWxtZXQucmVuZGVyU3RhdGljKCk7XG5cbiAgLy8gY2hlY2sgZm9yIGEgcmVkaXJlY3RcbiAgaWYgKGNvbnRleHQudXJsKSB7XG4gICAgLy8gU29tZXdoZXJlIGEgYDxSZWRpcmVjdD5gIHdhcyByZW5kZXJlZFxuICAgIHJldHVybiByZXMucmVkaXJlY3QoMzAxLCBjb250ZXh0LnVybCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gd2UncmUgZ29vZCwgc2VuZCB0aGUgcmVzcG9uc2VcbiAgfVxuXG4gIC8vIGdldCB0aGUgaW5pdGlhbCBzdGF0ZSBmcm9tIG91ciBSZWR1eCBzdG9yZVxuICBjb25zdCBwcmVsb2FkZWRTdGF0ZSA9IHN0b3JlLmdldFN0YXRlKCk7XG5cbiAgLy8gc2VuZCB0aGUgcmVuZGVyZWQgcGFnZSBiYWNrIHRvIHRoZSBjbGllbnRcbiAgcmVzLnNlbmQocmVuZGVyRnVsbFBhZ2UoaGVsbWV0LCBodG1sLCBwcmVsb2FkZWRTdGF0ZSkpO1xuXG4gIGNvbnNvbGUubG9nKCdoZWxsbyBmcm9tIHNwZWUuY2ggaGFuZGxlUGFnZVJlbmRlci5qc3gnKTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9oYW5kbGVQYWdlUmVuZGVyLmpzeCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlYWN0XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicmVhY3RcIlxuLy8gbW9kdWxlIGlkID0gMTVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicmVhY3QtZG9tL3NlcnZlclwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInJlYWN0LWRvbS9zZXJ2ZXJcIlxuLy8gbW9kdWxlIGlkID0gMTZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicmVkdXhcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJyZWR1eFwiXG4vLyBtb2R1bGUgaWQgPSAxN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWFjdC1yZWR1eFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInJlYWN0LXJlZHV4XCJcbi8vIG1vZHVsZSBpZCA9IDE4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlYWN0LXJvdXRlci1kb21cIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJyZWFjdC1yb3V0ZXItZG9tXCJcbi8vIG1vZHVsZSBpZCA9IDE5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInNwZWUuY2gtY29tcG9uZW50c1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInNwZWUuY2gtY29tcG9uZW50c1wiXG4vLyBtb2R1bGUgaWQgPSAyMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IChoZWxtZXQsIGh0bWwsIHByZWxvYWRlZFN0YXRlKSA9PiB7XG4gIC8vIHRha2UgdGhlIGh0bWwgYW5kIHByZWxvYWRlZFN0YXRlIGFuZCByZXR1cm4gdGhlIGZ1bGwgcGFnZVxuICByZXR1cm4gYFxuICAgIDwhRE9DVFlQRSBodG1sPlxuICAgIDxodG1sIGxhbmc9XCJlblwiIHByZWZpeD1cIm9nOiBodHRwOi8vb2dwLm1lL25zIyBmYjogaHR0cDovL29ncC5tZS9ucy9mYiNcIj5cbiAgICAgICAgPGhlYWQ+XG4gICAgICAgICAgICA8bWV0YSBjaGFyc2V0PVwiVVRGLThcIj5cbiAgICAgICAgICAgIDxtZXRhIG5hbWU9XCJ2aWV3cG9ydFwiIGNvbnRlbnQ9XCJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEsIHVzZXItc2NhbGFibGU9bm9cIj5cbiAgICAgICAgICAgIDxtZXRhIGh0dHAtZXF1aXY9XCJYLVVBLUNvbXBhdGlibGVcIiBjb250ZW50PVwiaWU9ZWRnZVwiPlxuICAgICAgICAgICAgPCEtLWhlbG1ldC0tPlxuICAgICAgICAgICAgJHtoZWxtZXQudGl0bGUudG9TdHJpbmcoKX1cbiAgICAgICAgICAgICR7aGVsbWV0Lm1ldGEudG9TdHJpbmcoKX1cbiAgICAgICAgICAgICR7aGVsbWV0LmxpbmsudG9TdHJpbmcoKX1cbiAgICAgICAgICAgIDwhLS1zdHlsZSBzaGVldHMtLT5cbiAgICAgICAgICAgIDxsaW5rIHJlbD1cInN0eWxlc2hlZXRcIiBocmVmPVwiL3N0YXRpYy9hc3NldHMvY3NzL3Jlc2V0LmNzc1wiIHR5cGU9XCJ0ZXh0L2Nzc1wiPlxuICAgICAgICAgICAgPGxpbmsgcmVsPVwic3R5bGVzaGVldFwiIGhyZWY9XCIvc3RhdGljL2Fzc2V0cy9jc3MvZ2VuZXJhbC5jc3NcIiB0eXBlPVwidGV4dC9jc3NcIj5cbiAgICAgICAgICAgIDxsaW5rIHJlbD1cInN0eWxlc2hlZXRcIiBocmVmPVwiL3N0YXRpYy9hc3NldHMvY3NzL21lZGlhUXVlcmllcy5jc3NcIiB0eXBlPVwidGV4dC9jc3NcIj5cbiAgICAgICAgICAgIDwhLS1nb29nbGUgZm9udC0tPlxuICAgICAgICAgICAgPGxpbmsgaHJlZj1cImh0dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT1Sb2JvdG86MzAwXCIgcmVsPVwic3R5bGVzaGVldFwiPlxuICAgICAgICA8L2hlYWQ+XG4gICAgICAgIDxib2R5IGlkPVwibWFpbi1ib2R5XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93IHJvdy0tdGFsbCBmbGV4LWNvbnRhaW5lci0tY29sdW1uXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBpZD1cInJlYWN0LWFwcFwiIGNsYXNzPVwicm93IHJvdy0tdGFsbCBmbGV4LWNvbnRhaW5lci0tY29sdW1uXCI+JHtodG1sfTwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8c2NyaXB0PlxuICAgICAgICAgICAgICAgIHdpbmRvdy5fX1BSRUxPQURFRF9TVEFURV9fID0gJHtKU09OLnN0cmluZ2lmeShwcmVsb2FkZWRTdGF0ZSkucmVwbGFjZSgvPC9nLCAnXFxcXFxcdTAwM2MnKX1cbiAgICAgICAgICAgIDwvc2NyaXB0PlxuICAgICAgICAgICAgPHNjcmlwdCBzcmM9XCIvc3RhdGljL2J1bmRsZS9idW5kbGUuanNcIj48L3NjcmlwdD5cbiAgICAgICAgPC9ib2R5PlxuICAgIDwvaHRtbD5cbiAgYDtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9yZW5kZXJGdWxsUGFnZS5qcyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlYWN0LWhlbG1ldFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInJlYWN0LWhlbG1ldFwiXG4vLyBtb2R1bGUgaWQgPSAyMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5jb25zdCB7IGdldENsYWltSWQsIGdldExvY2FsRmlsZVJlY29yZCB9ID0gcmVxdWlyZSgnLi4vY29udHJvbGxlcnMvc2VydmVDb250cm9sbGVyLmpzJyk7XG5jb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJy4vZXJyb3JIYW5kbGVycy5qcycpO1xuXG5jb25zdCBTRVJWRSA9ICdTRVJWRSc7XG5jb25zdCBTSE9XID0gJ1NIT1cnO1xuY29uc3QgTk9fRklMRSA9ICdOT19GSUxFJztcbmNvbnN0IE5PX0NIQU5ORUwgPSAnTk9fQ0hBTk5FTCc7XG5jb25zdCBOT19DTEFJTSA9ICdOT19DTEFJTSc7XG5cbmZ1bmN0aW9uIGNsaWVudEFjY2VwdHNIdG1sICh7YWNjZXB0fSkge1xuICByZXR1cm4gYWNjZXB0ICYmIGFjY2VwdC5tYXRjaCgvdGV4dFxcL2h0bWwvKTtcbn07XG5cbmZ1bmN0aW9uIHJlcXVlc3RJc0Zyb21Ccm93c2VyIChoZWFkZXJzKSB7XG4gIHJldHVybiBoZWFkZXJzWyd1c2VyLWFnZW50J10gJiYgaGVhZGVyc1sndXNlci1hZ2VudCddLm1hdGNoKC9Nb3ppbGxhLyk7XG59O1xuXG5mdW5jdGlvbiBjbGllbnRXYW50c0Fzc2V0ICh7YWNjZXB0LCByYW5nZX0pIHtcbiAgY29uc3QgaW1hZ2VJc1dhbnRlZCA9IGFjY2VwdCAmJiBhY2NlcHQubWF0Y2goL2ltYWdlXFwvLiovKSAmJiAhYWNjZXB0Lm1hdGNoKC90ZXh0XFwvaHRtbC8pICYmICFhY2NlcHQubWF0Y2goL3RleHRcXC9cXCovKTtcbiAgY29uc3QgdmlkZW9Jc1dhbnRlZCA9IGFjY2VwdCAmJiByYW5nZTtcbiAgcmV0dXJuIGltYWdlSXNXYW50ZWQgfHwgdmlkZW9Jc1dhbnRlZDtcbn07XG5cbmZ1bmN0aW9uIGlzVmFsaWRDbGFpbUlkIChjbGFpbUlkKSB7XG4gIHJldHVybiAoKGNsYWltSWQubGVuZ3RoID09PSA0MCkgJiYgIS9bXkEtWmEtejAtOV0vZy50ZXN0KGNsYWltSWQpKTtcbn07XG5cbmZ1bmN0aW9uIGlzVmFsaWRTaG9ydElkIChjbGFpbUlkKSB7XG4gIHJldHVybiBjbGFpbUlkLmxlbmd0aCA9PT0gMTsgIC8vIGl0IHNob3VsZCByZWFsbHkgZXZhbHVhdGUgdGhlIHNob3J0IHVybCBpdHNlbGZcbn07XG5cbmZ1bmN0aW9uIGlzVmFsaWRTaG9ydElkT3JDbGFpbUlkIChpbnB1dCkge1xuICByZXR1cm4gKGlzVmFsaWRDbGFpbUlkKGlucHV0KSB8fCBpc1ZhbGlkU2hvcnRJZChpbnB1dCkpO1xufTtcblxuZnVuY3Rpb24gc2VydmVBc3NldFRvQ2xpZW50IChjbGFpbUlkLCBuYW1lLCByZXMpIHtcbiAgcmV0dXJuIGdldExvY2FsRmlsZVJlY29yZChjbGFpbUlkLCBuYW1lKVxuICAgIC50aGVuKGZpbGVSZWNvcmQgPT4ge1xuICAgICAgLy8gY2hlY2sgdGhhdCBhIGxvY2FsIHJlY29yZCB3YXMgZm91bmRcbiAgICAgIGlmIChmaWxlUmVjb3JkID09PSBOT19GSUxFKSB7XG4gICAgICAgIHJldHVybiByZXMuc3RhdHVzKDMwNykucmVkaXJlY3QoYC9hcGkvY2xhaW0vZ2V0LyR7bmFtZX0vJHtjbGFpbUlkfWApO1xuICAgICAgfVxuICAgICAgLy8gc2VydmUgdGhlIGZpbGVcbiAgICAgIGNvbnN0IHtmaWxlUGF0aCwgZmlsZVR5cGV9ID0gZmlsZVJlY29yZDtcbiAgICAgIGxvZ2dlci52ZXJib3NlKGBzZXJ2aW5nIGZpbGU6ICR7ZmlsZVBhdGh9YCk7XG4gICAgICBjb25zdCBzZW5kRmlsZU9wdGlvbnMgPSB7XG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAnWC1Db250ZW50LVR5cGUtT3B0aW9ucyc6ICdub3NuaWZmJyxcbiAgICAgICAgICAnQ29udGVudC1UeXBlJyAgICAgICAgICA6IGZpbGVUeXBlIHx8ICdpbWFnZS9qcGVnJyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICByZXMuc3RhdHVzKDIwMCkuc2VuZEZpbGUoZmlsZVBhdGgsIHNlbmRGaWxlT3B0aW9ucyk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZ2V0Q2xhaW1JZEFuZFNlcnZlQXNzZXQgKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCwgY2xhaW1OYW1lLCBjbGFpbUlkLCBvcmlnaW5hbFVybCwgaXAsIHJlcykge1xuICAgIC8vIGdldCB0aGUgY2xhaW0gSWQgYW5kIHRoZW4gc2VydmUgdGhlIGFzc2V0XG4gICAgZ2V0Q2xhaW1JZChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltTmFtZSwgY2xhaW1JZClcbiAgICAgIC50aGVuKGZ1bGxDbGFpbUlkID0+IHtcbiAgICAgICAgaWYgKGZ1bGxDbGFpbUlkID09PSBOT19DTEFJTSkge1xuICAgICAgICAgIHJldHVybiByZXMuc3RhdHVzKDQwNCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICdubyBjbGFpbSBpZCBjb3VsZCBiZSBmb3VuZCd9KTtcbiAgICAgICAgfSBlbHNlIGlmIChmdWxsQ2xhaW1JZCA9PT0gTk9fQ0hBTk5FTCkge1xuICAgICAgICAgIHJldHVybiByZXMuc3RhdHVzKDQwNCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICdubyBjaGFubmVsIGlkIGNvdWxkIGJlIGZvdW5kJ30pO1xuICAgICAgICB9XG4gICAgICAgIHNlcnZlQXNzZXRUb0NsaWVudChmdWxsQ2xhaW1JZCwgY2xhaW1OYW1lLCByZXMpO1xuICAgICAgICAvLyBwb3N0VG9TdGF0cyhyZXNwb25zZVR5cGUsIG9yaWdpbmFsVXJsLCBpcCwgY2xhaW1OYW1lLCBmdWxsQ2xhaW1JZCwgJ3N1Y2Nlc3MnKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgICAgIC8vIHBvc3RUb1N0YXRzKHJlc3BvbnNlVHlwZSwgb3JpZ2luYWxVcmwsIGlwLCBjbGFpbU5hbWUsIGZ1bGxDbGFpbUlkLCAnZmFpbCcpO1xuICAgICAgfSk7XG4gIH0sXG4gIGRldGVybWluZVJlc3BvbnNlVHlwZSAoaGFzRmlsZUV4dGVuc2lvbiwgaGVhZGVycykge1xuICAgIGxldCByZXNwb25zZVR5cGU7XG4gICAgaWYgKGhhc0ZpbGVFeHRlbnNpb24pIHtcbiAgICAgIHJlc3BvbnNlVHlwZSA9IFNFUlZFOyAgLy8gYXNzdW1lIGEgc2VydmUgcmVxdWVzdCBpZiBmaWxlIGV4dGVuc2lvbiBpcyBwcmVzZW50XG4gICAgICBpZiAoY2xpZW50QWNjZXB0c0h0bWwoaGVhZGVycykpIHsgIC8vIGlmIHRoZSByZXF1ZXN0IGNvbWVzIGZyb20gYSBicm93c2VyLCBjaGFuZ2UgaXQgdG8gYSBzaG93IHJlcXVlc3RcbiAgICAgICAgcmVzcG9uc2VUeXBlID0gU0hPVztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmVzcG9uc2VUeXBlID0gU0hPVztcbiAgICAgIGlmIChjbGllbnRXYW50c0Fzc2V0KGhlYWRlcnMpICYmIHJlcXVlc3RJc0Zyb21Ccm93c2VyKGhlYWRlcnMpKSB7ICAvLyB0aGlzIGlzIGluIGNhc2Ugc29tZW9uZSBlbWJlZHMgYSBzaG93IHVybFxuICAgICAgICBsb2dnZXIuZGVidWcoJ1Nob3cgcmVxdWVzdCBjYW1lIGZyb20gYnJvd3NlciBidXQgd2FudHMgYW4gaW1hZ2UvdmlkZW8uIENoYW5naW5nIHJlc3BvbnNlIHRvIHNlcnZlLi4uJyk7XG4gICAgICAgIHJlc3BvbnNlVHlwZSA9IFNFUlZFO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzcG9uc2VUeXBlO1xuICB9LFxuICBmbGlwQ2xhaW1OYW1lQW5kSWRGb3JCYWNrd2FyZHNDb21wYXRpYmlsaXR5IChpZGVudGlmaWVyLCBuYW1lKSB7XG4gICAgLy8gdGhpcyBpcyBhIHBhdGNoIGZvciBiYWNrd2FyZHMgY29tcGF0YWJpbGl0eSB3aXRoICcvbmFtZS9jbGFpbV9pZCcgdXJsIGZvcm1hdFxuICAgIGlmIChpc1ZhbGlkU2hvcnRJZE9yQ2xhaW1JZChuYW1lKSAmJiAhaXNWYWxpZFNob3J0SWRPckNsYWltSWQoaWRlbnRpZmllcikpIHtcbiAgICAgIGNvbnN0IHRlbXBOYW1lID0gbmFtZTtcbiAgICAgIG5hbWUgPSBpZGVudGlmaWVyO1xuICAgICAgaWRlbnRpZmllciA9IHRlbXBOYW1lO1xuICAgIH1cbiAgICByZXR1cm4gW2lkZW50aWZpZXIsIG5hbWVdO1xuICB9LFxuICBsb2dSZXF1ZXN0RGF0YSAocmVzcG9uc2VUeXBlLCBjbGFpbU5hbWUsIGNoYW5uZWxOYW1lLCBjbGFpbUlkKSB7XG4gICAgbG9nZ2VyLmRlYnVnKCdyZXNwb25zZVR5cGUgPT09JywgcmVzcG9uc2VUeXBlKTtcbiAgICBsb2dnZXIuZGVidWcoJ2NsYWltIG5hbWUgPT09ICcsIGNsYWltTmFtZSk7XG4gICAgbG9nZ2VyLmRlYnVnKCdjaGFubmVsIG5hbWUgPT09JywgY2hhbm5lbE5hbWUpO1xuICAgIGxvZ2dlci5kZWJ1ZygnY2xhaW0gaWQgPT09JywgY2xhaW1JZCk7XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvc2VydmVIZWxwZXJzLmpzIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgUkVHRVhQX0lOVkFMSURfQ0xBSU0gIDogL1teQS1aYS16MC05LV0vZyxcbiAgUkVHRVhQX0lOVkFMSURfQ0hBTk5FTDogL1teQS1aYS16MC05LUBdL2csXG4gIFJFR0VYUF9BRERSRVNTICAgICAgICA6IC9eYig/PVteME9JbF17MzIsMzN9KVswLTlBLVphLXpdezMyLDMzfSQvLFxuICBDSEFOTkVMX0NIQVIgICAgICAgICAgOiAnQCcsXG4gIHBhcnNlSWRlbnRpZmllciAgICAgICA6IGZ1bmN0aW9uIChpZGVudGlmaWVyKSB7XG4gICAgbG9nZ2VyLmRlYnVnKCdwYXJzaW5nIGlkZW50aWZpZXI6JywgaWRlbnRpZmllcik7XG4gICAgY29uc3QgY29tcG9uZW50c1JlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICcoW146JCMvXSopJyArIC8vIHZhbHVlIChzdG9wcyBhdCB0aGUgZmlyc3Qgc2VwYXJhdG9yIG9yIGVuZClcbiAgICAgICcoWzokI10/KShbXi9dKiknIC8vIG1vZGlmaWVyIHNlcGFyYXRvciwgbW9kaWZpZXIgKHN0b3BzIGF0IHRoZSBmaXJzdCBwYXRoIHNlcGFyYXRvciBvciBlbmQpXG4gICAgKTtcbiAgICBjb25zdCBbcHJvdG8sIHZhbHVlLCBtb2RpZmllclNlcGVyYXRvciwgbW9kaWZpZXJdID0gY29tcG9uZW50c1JlZ2V4XG4gICAgICAuZXhlYyhpZGVudGlmaWVyKVxuICAgICAgLm1hcChtYXRjaCA9PiBtYXRjaCB8fCBudWxsKTtcbiAgICBsb2dnZXIuZGVidWcoYCR7cHJvdG99LCAke3ZhbHVlfSwgJHttb2RpZmllclNlcGVyYXRvcn0sICR7bW9kaWZpZXJ9YCk7XG5cbiAgICAvLyBWYWxpZGF0ZSBhbmQgcHJvY2VzcyBuYW1lXG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDaGVjayB5b3VyIHVybC4gIE5vIGNoYW5uZWwgbmFtZSBwcm92aWRlZCBiZWZvcmUgXCIke21vZGlmaWVyU2VwZXJhdG9yfVwiYCk7XG4gICAgfVxuICAgIGNvbnN0IGlzQ2hhbm5lbCA9IHZhbHVlLnN0YXJ0c1dpdGgobW9kdWxlLmV4cG9ydHMuQ0hBTk5FTF9DSEFSKTtcbiAgICBjb25zdCBjaGFubmVsTmFtZSA9IGlzQ2hhbm5lbCA/IHZhbHVlIDogbnVsbDtcbiAgICBsZXQgY2xhaW1JZDtcbiAgICBpZiAoaXNDaGFubmVsKSB7XG4gICAgICBpZiAoIWNoYW5uZWxOYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gY2hhbm5lbCBuYW1lIGFmdGVyIEAuJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBuYW1lQmFkQ2hhcnMgPSAoY2hhbm5lbE5hbWUpLm1hdGNoKG1vZHVsZS5leHBvcnRzLlJFR0VYUF9JTlZBTElEX0NIQU5ORUwpO1xuICAgICAgaWYgKG5hbWVCYWRDaGFycykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgY2hhcmFjdGVycyBpbiBjaGFubmVsIG5hbWU6ICR7bmFtZUJhZENoYXJzLmpvaW4oJywgJyl9LmApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjbGFpbUlkID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgYW5kIHByb2Nlc3MgbW9kaWZpZXJcbiAgICBsZXQgY2hhbm5lbENsYWltSWQ7XG4gICAgaWYgKG1vZGlmaWVyU2VwZXJhdG9yKSB7XG4gICAgICBpZiAoIW1vZGlmaWVyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gbW9kaWZpZXIgcHJvdmlkZWQgYWZ0ZXIgc2VwYXJhdG9yIFwiJHttb2RpZmllclNlcGVyYXRvcn1cImApO1xuICAgICAgfVxuXG4gICAgICBpZiAobW9kaWZpZXJTZXBlcmF0b3IgPT09ICc6Jykge1xuICAgICAgICBjaGFubmVsQ2xhaW1JZCA9IG1vZGlmaWVyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgXCIke21vZGlmaWVyU2VwZXJhdG9yfVwiIG1vZGlmaWVyIGlzIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBpc0NoYW5uZWwsXG4gICAgICBjaGFubmVsTmFtZSxcbiAgICAgIGNoYW5uZWxDbGFpbUlkLFxuICAgICAgY2xhaW1JZCxcbiAgICB9O1xuICB9LFxuICBwYXJzZUNsYWltOiBmdW5jdGlvbiAoY2xhaW0pIHtcbiAgICBsb2dnZXIuZGVidWcoJ3BhcnNpbmcgbmFtZTonLCBjbGFpbSk7XG4gICAgY29uc3QgY29tcG9uZW50c1JlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICcoW146JCMvLl0qKScgKyAvLyBuYW1lIChzdG9wcyBhdCB0aGUgZmlyc3QgbW9kaWZpZXIpXG4gICAgICAnKFs6JCMuXT8pKFteL10qKScgLy8gbW9kaWZpZXIgc2VwYXJhdG9yLCBtb2RpZmllciAoc3RvcHMgYXQgdGhlIGZpcnN0IHBhdGggc2VwYXJhdG9yIG9yIGVuZClcbiAgICApO1xuICAgIGNvbnN0IFtwcm90bywgY2xhaW1OYW1lLCBtb2RpZmllclNlcGVyYXRvciwgbW9kaWZpZXJdID0gY29tcG9uZW50c1JlZ2V4XG4gICAgICAuZXhlYyhjbGFpbSlcbiAgICAgIC5tYXAobWF0Y2ggPT4gbWF0Y2ggfHwgbnVsbCk7XG4gICAgbG9nZ2VyLmRlYnVnKGAke3Byb3RvfSwgJHtjbGFpbU5hbWV9LCAke21vZGlmaWVyU2VwZXJhdG9yfSwgJHttb2RpZmllcn1gKTtcblxuICAgIC8vIFZhbGlkYXRlIGFuZCBwcm9jZXNzIG5hbWVcbiAgICBpZiAoIWNsYWltTmFtZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjbGFpbSBuYW1lIHByb3ZpZGVkIGJlZm9yZSAuJyk7XG4gICAgfVxuICAgIGNvbnN0IG5hbWVCYWRDaGFycyA9IChjbGFpbU5hbWUpLm1hdGNoKG1vZHVsZS5leHBvcnRzLlJFR0VYUF9JTlZBTElEX0NMQUlNKTtcbiAgICBpZiAobmFtZUJhZENoYXJzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgY2hhcmFjdGVycyBpbiBjbGFpbSBuYW1lOiAke25hbWVCYWRDaGFycy5qb2luKCcsICcpfS5gKTtcbiAgICB9XG4gICAgLy8gVmFsaWRhdGUgYW5kIHByb2Nlc3MgbW9kaWZpZXJcbiAgICBpZiAobW9kaWZpZXJTZXBlcmF0b3IpIHtcbiAgICAgIGlmICghbW9kaWZpZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBmaWxlIGV4dGVuc2lvbiBwcm92aWRlZCBhZnRlciBzZXBhcmF0b3IgJHttb2RpZmllclNlcGVyYXRvcn0uYCk7XG4gICAgICB9XG4gICAgICBpZiAobW9kaWZpZXJTZXBlcmF0b3IgIT09ICcuJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSAke21vZGlmaWVyU2VwZXJhdG9yfSBtb2RpZmllciBpcyBub3Qgc3VwcG9ydGVkIGluIHRoZSBjbGFpbSBuYW1lYCk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIHJldHVybiByZXN1bHRzXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsYWltTmFtZSxcbiAgICB9O1xuICB9LFxuICBwYXJzZU1vZGlmaWVyOiBmdW5jdGlvbiAoY2xhaW0pIHtcbiAgICBsb2dnZXIuZGVidWcoJ3BhcnNpbmcgbW9kaWZpZXI6JywgY2xhaW0pO1xuICAgIGNvbnN0IGNvbXBvbmVudHNSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgICAnKFteOiQjLy5dKiknICsgLy8gbmFtZSAoc3RvcHMgYXQgdGhlIGZpcnN0IG1vZGlmaWVyKVxuICAgICAgJyhbOiQjLl0/KShbXi9dKiknIC8vIG1vZGlmaWVyIHNlcGFyYXRvciwgbW9kaWZpZXIgKHN0b3BzIGF0IHRoZSBmaXJzdCBwYXRoIHNlcGFyYXRvciBvciBlbmQpXG4gICAgKTtcbiAgICBjb25zdCBbcHJvdG8sIGNsYWltTmFtZSwgbW9kaWZpZXJTZXBlcmF0b3IsIG1vZGlmaWVyXSA9IGNvbXBvbmVudHNSZWdleFxuICAgICAgLmV4ZWMoY2xhaW0pXG4gICAgICAubWFwKG1hdGNoID0+IG1hdGNoIHx8IG51bGwpO1xuICAgIGxvZ2dlci5kZWJ1ZyhgJHtwcm90b30sICR7Y2xhaW1OYW1lfSwgJHttb2RpZmllclNlcGVyYXRvcn0sICR7bW9kaWZpZXJ9YCk7XG4gICAgLy8gVmFsaWRhdGUgYW5kIHByb2Nlc3MgbW9kaWZpZXJcbiAgICBsZXQgaGFzRmlsZUV4dGVuc2lvbiA9IGZhbHNlO1xuICAgIGlmIChtb2RpZmllclNlcGVyYXRvcikge1xuICAgICAgaGFzRmlsZUV4dGVuc2lvbiA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBoYXNGaWxlRXh0ZW5zaW9uLFxuICAgIH07XG4gIH0sXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL2hlbHBlcnMvbGJyeVVyaS5qcyIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyByZW5kZXJUb1N0cmluZyB9IGZyb20gJ3JlYWN0LWRvbS9zZXJ2ZXInO1xuaW1wb3J0IHsgY3JlYXRlU3RvcmUsIGFwcGx5TWlkZGxld2FyZSB9IGZyb20gJ3JlZHV4JztcbmltcG9ydCB7IFByb3ZpZGVyIH0gZnJvbSAncmVhY3QtcmVkdXgnO1xuaW1wb3J0IHsgU3RhdGljUm91dGVyIH0gZnJvbSAncmVhY3Qtcm91dGVyLWRvbSc7XG5pbXBvcnQgcmVuZGVyRnVsbFBhZ2UgZnJvbSAnLi9yZW5kZXJGdWxsUGFnZSc7XG5pbXBvcnQgY3JlYXRlU2FnYU1pZGRsZXdhcmUgZnJvbSAncmVkdXgtc2FnYSc7XG5pbXBvcnQgeyBjYWxsIH0gZnJvbSAncmVkdXgtc2FnYS9lZmZlY3RzJztcbmltcG9ydCB7IFJlZHVjZXJzLCBHQUxpc3RlbmVyLCBBcHAsIFNhZ2FzLCBBY3Rpb25zIH0gZnJvbSAnc3BlZS5jaC1jb21wb25lbnRzJztcblxuaW1wb3J0IEhlbG1ldCBmcm9tICdyZWFjdC1oZWxtZXQnO1xuXG4vLyBjb25maWd1cmUgdGhlIHJlZHVjZXJzIGJ5IHBhc3NpbmcgaW5pdGlhbCBzdGF0ZSBjb25maWdzXG5jb25zdCBzaXRlQ29uZmlnID0gcmVxdWlyZSgnc2l0ZUNvbmZpZy5qcycpO1xuY29uc3QgY3VzdG9taXplZFJlZHVjZXJzID0gUmVkdWNlcnMoc2l0ZUNvbmZpZyk7XG5cbmNvbnN0IHJldHVyblNhZ2FXaXRoUGFyYW1zID0gKHNhZ2EsIHBhcmFtcykgPT4ge1xuICByZXR1cm4gZnVuY3Rpb24gKiAoKSB7XG4gICAgeWllbGQgY2FsbChzYWdhLCBwYXJhbXMpO1xuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSAocmVxLCByZXMpID0+IHtcbiAgbGV0IGNvbnRleHQgPSB7fTtcblxuICAvLyBjcmVhdGUgYW5kIGFwcGx5IG1pZGRsZXdhcmVcbiAgY29uc3Qgc2FnYU1pZGRsZXdhcmUgPSBjcmVhdGVTYWdhTWlkZGxld2FyZSgpO1xuICBjb25zdCBtaWRkbGV3YXJlID0gYXBwbHlNaWRkbGV3YXJlKHNhZ2FNaWRkbGV3YXJlKTtcblxuICAvLyBjcmVhdGUgYSBuZXcgUmVkdXggc3RvcmUgaW5zdGFuY2VcbiAgY29uc3Qgc3RvcmUgPSBjcmVhdGVTdG9yZShjdXN0b21pemVkUmVkdWNlcnMsIG1pZGRsZXdhcmUpO1xuXG4gIC8vIGNyZWF0ZSBzYWdhXG4gIGNvbnN0IGFjdGlvbiA9IEFjdGlvbnMub25IYW5kbGVTaG93UGFnZVVyaShyZXEucGFyYW1zKTtcbiAgY29uc3Qgc2FnYSA9IHJldHVyblNhZ2FXaXRoUGFyYW1zKFNhZ2FzLmhhbmRsZVNob3dQYWdlVXJpLCBhY3Rpb24pO1xuXG4gIC8vIHJ1biB0aGUgc2FnYSBtaWRkbGV3YXJlXG4gIHNhZ2FNaWRkbGV3YXJlXG4gICAgLnJ1bihzYWdhKVxuICAgIC5kb25lXG4gICAgLnRoZW4oKCkgPT4ge1xuICAgICAgLy8gcmVuZGVyIGNvbXBvbmVudCB0byBhIHN0cmluZ1xuICAgICAgY29uc3QgaHRtbCA9IHJlbmRlclRvU3RyaW5nKFxuICAgICAgICA8UHJvdmlkZXIgc3RvcmU9e3N0b3JlfT5cbiAgICAgICAgICA8U3RhdGljUm91dGVyIGxvY2F0aW9uPXtyZXEudXJsfSBjb250ZXh0PXtjb250ZXh0fT5cbiAgICAgICAgICAgIDxHQUxpc3RlbmVyPlxuICAgICAgICAgICAgICA8QXBwIC8+XG4gICAgICAgICAgICA8L0dBTGlzdGVuZXI+XG4gICAgICAgICAgPC9TdGF0aWNSb3V0ZXI+XG4gICAgICAgIDwvUHJvdmlkZXI+XG4gICAgICApO1xuXG4gICAgICAvLyBnZXQgaGVhZCB0YWdzIGZyb20gaGVsbWV0XG4gICAgICBjb25zdCBoZWxtZXQgPSBIZWxtZXQucmVuZGVyU3RhdGljKCk7XG5cbiAgICAgIC8vIGNoZWNrIGZvciBhIHJlZGlyZWN0XG4gICAgICBpZiAoY29udGV4dC51cmwpIHtcbiAgICAgICAgcmV0dXJuIHJlcy5yZWRpcmVjdCgzMDEsIGNvbnRleHQudXJsKTtcbiAgICAgIH1cblxuICAgICAgLy8gZ2V0IHRoZSBpbml0aWFsIHN0YXRlIGZyb20gb3VyIFJlZHV4IHN0b3JlXG4gICAgICBjb25zdCBwcmVsb2FkZWRTdGF0ZSA9IHN0b3JlLmdldFN0YXRlKCk7XG5cbiAgICAgIC8vIHNlbmQgdGhlIHJlbmRlcmVkIHBhZ2UgYmFjayB0byB0aGUgY2xpZW50XG4gICAgICByZXMuc2VuZChyZW5kZXJGdWxsUGFnZShoZWxtZXQsIGh0bWwsIHByZWxvYWRlZFN0YXRlKSk7XG4gICAgfSk7XG5cbiAgY29uc29sZS5sb2coJ2hlbGxvIGZyb20gc3BlZS5jaCBoYW5kbGVTaG93UmVuZGVyLmpzeCcpO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9oZWxwZXJzL2hhbmRsZVNob3dSZW5kZXIuanN4IiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiYmFiZWwtcG9seWZpbGxcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJiYWJlbC1wb2x5ZmlsbFwiXG4vLyBtb2R1bGUgaWQgPSAyN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJ3aGF0d2ctZmV0Y2hcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJ3aGF0d2ctZmV0Y2hcIlxuLy8gbW9kdWxlIGlkID0gMjhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgU2VydmVyID0gcmVxdWlyZSgnLi9zZXJ2ZXInKTtcblxuY29uc3QgZXhwb3J0cyA9IHtcbiAgU2VydmVyLFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3BlZWNoLmpzIiwiLy8gYXBwIGRlcGVuZGVuY2llc1xuY29uc3QgZXhwcmVzcyA9IHJlcXVpcmUoJ2V4cHJlc3MnKTtcbmNvbnN0IGJvZHlQYXJzZXIgPSByZXF1aXJlKCdib2R5LXBhcnNlcicpO1xuY29uc3QgZXhwcmVzc0hhbmRsZWJhcnMgPSByZXF1aXJlKCdleHByZXNzLWhhbmRsZWJhcnMnKTtcbmNvbnN0IEhhbmRsZWJhcnMgPSByZXF1aXJlKCdoYW5kbGViYXJzJyk7XG5jb25zdCBoZWxtZXQgPSByZXF1aXJlKCdoZWxtZXQnKTtcbmNvbnN0IGNvb2tpZVNlc3Npb24gPSByZXF1aXJlKCdjb29raWUtc2Vzc2lvbicpO1xuY29uc3QgaHR0cCA9IHJlcXVpcmUoJ2h0dHAnKTtcbmNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcbmNvbnN0IHJlcXVlc3RMb2dnZXIgPSByZXF1aXJlKCdtaWRkbGV3YXJlL3JlcXVlc3RMb2dnZXIuanMnKTtcbmNvbnN0IFBhdGggPSByZXF1aXJlKCdwYXRoJyk7XG5jb25zdCBsb2dnZXJDb25maWcgPSByZXF1aXJlKCdsb2dnZXJDb25maWcuanMnKTtcbmNvbnN0IG15c3FsQ29uZmlnID0gcmVxdWlyZSgnbXlzcWxDb25maWcuanMnKTtcbmNvbnN0IHNpdGVDb25maWcgPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5jb25zdCBzbGFja0NvbmZpZyA9IHJlcXVpcmUoJ3NsYWNrQ29uZmlnLmpzJyk7XG5cbmZ1bmN0aW9uIFNlcnZlciAoKSB7XG4gIHRoaXMuY29uZmlndXJlTG9nZ2VyID0gKHVzZXJDb25maWcpID0+IHtcbiAgICBsb2dnZXJDb25maWcudXBkYXRlKHVzZXJDb25maWcpO1xuICB9O1xuICB0aGlzLmNvbmZpZ3VyZU15c3FsID0gKHVzZXJDb25maWcpID0+IHtcbiAgICBteXNxbENvbmZpZy51cGRhdGUodXNlckNvbmZpZyk7XG4gIH07XG4gIHRoaXMuY29uZmlndXJlU2l0ZURldGFpbHMgPSAodXNlckNvbmZpZykgPT4ge1xuICAgIHNpdGVDb25maWcudXBkYXRlKHVzZXJDb25maWcpO1xuICB9O1xuICB0aGlzLmNvbmZpZ3VyZVNsYWNrID0gKHVzZXJDb25maWcpID0+IHtcbiAgICBzbGFja0NvbmZpZy51cGRhdGUodXNlckNvbmZpZyk7XG4gIH07XG4gIHRoaXMuY29uZmlndXJlQ2xpZW50QnVuZGxlID0gKCkgPT4ge1xuICAgIGxvZ2dlci5kZWJ1ZygnY29uZmlndXJlIHRoZSBjbGllbnQgaGVyZSBieSBwYXNzaW5nIGluIHRoZSBidW5kbGUgYW5kIGNvbmZpZ3VyaW5nIGl0LCBvciBiZXR0ZXIgeWV0OiB0YWtpbmcgaW4gdGhlIGNvbXBvbmVudHMgdG8gdXNlIGR5bmFtaWNhbGx5IGZyb20gaGVyZS4nKTtcbiAgfTtcbiAgdGhpcy5jb25maWd1cmVNb2RlbHMgPSAoKSA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKCdoZXJlIGlzIHdoZXJlIHlvdSBjb3VsZCBhZGQvb3ZlcndyaXRlIHRoZSBkZWZhdWx0IG1vZGVscycpXG4gIH07XG4gIHRoaXMuY29uZmlndXJlUm91dGVzID0gKCkgPT4ge1xuICAgIGxvZ2dlci5kZWJ1ZygnaGVyZSBpcyB3aGVyZSB5b3UgY291bGQgYWRkL292ZXJ3cml0ZSB0aGUgZGVmYXVsdCByb3V0ZXMnKVxuICB9O1xuICB0aGlzLmNyZWF0ZUFwcCA9ICgpID0+IHtcbiAgICAvLyBjcmVhdGUgYW4gRXhwcmVzcyBhcHBsaWNhdGlvblxuICAgIGNvbnN0IGFwcCA9IGV4cHJlc3MoKTtcblxuICAgIC8vIHRydXN0IHRoZSBwcm94eSB0byBnZXQgaXAgYWRkcmVzcyBmb3IgdXNcbiAgICBhcHAuZW5hYmxlKCd0cnVzdCBwcm94eScpO1xuXG4gICAgLyogYWRkIG1pZGRsZXdhcmUgKi9cbiAgICAvLyBzZXQgSFRUUCBoZWFkZXJzIHRvIHByb3RlY3QgYWdhaW5zdCB3ZWxsLWtub3duIHdlYiB2dWxuZXJhYmlsdGllc1xuICAgIGFwcC51c2UoaGVsbWV0KCkpO1xuICAgIC8vICdleHByZXNzLnN0YXRpYycgdG8gc2VydmUgc3RhdGljIGZpbGVzIGZyb20gcHVibGljIGRpcmVjdG9yeVxuICAgIGlmIChzaXRlQ29uZmlnLnJvdXRlcy5wdWJsaWNGb2xkZXIpIHtcbiAgICAgIC8vIHRha2UgaW4gYSBkaWZmZXJlbnQgcHVibGljIGZvbGRlciwgc28gaXQgY2FuIHNlcnZlIGl0J3Mgb3duIGJ1bmRsZSBpZiBuZWVkZWRcbiAgICAgIGNvbnN0IHB1YmxpY0ZvbGRlciA9IFBhdGgucmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCBzaXRlQ29uZmlnLnJvdXRlcy5wdWJsaWNGb2xkZXIpO1xuICAgICAgYXBwLnVzZSgnL3N0YXRpYycsIGV4cHJlc3Muc3RhdGljKHB1YmxpY0ZvbGRlcikpO1xuICAgICAgbG9nZ2VyLmluZm8oJ3NlcnZpbmcgc3RhdGljIGZpbGVzIGZyb20gY3VzdG9tIHBhdGg6JywgcHVibGljRm9sZGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcHVibGljUGF0aCA9IFBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICdwdWJsaWMnKTtcbiAgICAgIGFwcC51c2UoJy9zdGF0aWMnLCBleHByZXNzLnN0YXRpYyhwdWJsaWNQYXRoKSk7XG4gICAgICBsb2dnZXIuaW5mbygnc2VydmluZyBzdGF0aWMgZmlsZXMgZnJvbSBkZWZhdWx0IHBhdGg6JywgcHVibGljUGF0aCk7XG4gICAgfTtcbiAgICAvLyAnYm9keSBwYXJzZXInIGZvciBwYXJzaW5nIGFwcGxpY2F0aW9uL2pzb25cbiAgICBhcHAudXNlKGJvZHlQYXJzZXIuanNvbigpKTtcbiAgICAvLyAnYm9keSBwYXJzZXInIGZvciBwYXJzaW5nIGFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZFxuICAgIGFwcC51c2UoYm9keVBhcnNlci51cmxlbmNvZGVkKHsgZXh0ZW5kZWQ6IHRydWUgfSkpO1xuXG4gICAgLy8gYWRkIGN1c3RvbSBtaWRkbGV3YXJlIChub3RlOiBidWlsZCBvdXQgdG8gYWNjZXB0IGR5bmFtaWNhbGx5IHVzZSB3aGF0IGlzIGluIHNlcnZlci9taWRkbGV3YXJlL1xuICAgIGFwcC51c2UocmVxdWVzdExvZ2dlcik7XG5cbiAgICAvLyBjb25maWd1cmUgcGFzc3BvcnRcbiAgICBjb25zdCBzcGVlY2hQYXNzcG9ydCA9IHJlcXVpcmUoJ3NwZWVjaFBhc3Nwb3J0Jyk7XG4gICAgLy8gaW5pdGlhbGl6ZSBwYXNzcG9ydFxuICAgIGNvbnN0IHNlc3Npb25LZXkgPSBzaXRlQ29uZmlnLmF1dGguc2Vzc2lvbktleTtcbiAgICBhcHAudXNlKGNvb2tpZVNlc3Npb24oe1xuICAgICAgbmFtZSAgOiAnc2Vzc2lvbicsXG4gICAgICBrZXlzICA6IFtzZXNzaW9uS2V5XSxcbiAgICAgIG1heEFnZTogMjQgKiA2MCAqIDYwICogMTAwMCwgLy8gaS5lLiAyNCBob3Vyc1xuICAgIH0pKTtcbiAgICBhcHAudXNlKHNwZWVjaFBhc3Nwb3J0LmluaXRpYWxpemUoKSk7XG4gICAgYXBwLnVzZShzcGVlY2hQYXNzcG9ydC5zZXNzaW9uKCkpO1xuXG4gICAgLy8gY29uZmlndXJlIGhhbmRsZWJhcnMgJiByZWdpc3RlciBpdCB3aXRoIGV4cHJlc3MgYXBwXG4gICAgY29uc3QgaGJzID0gZXhwcmVzc0hhbmRsZWJhcnMuY3JlYXRlKHtcbiAgICAgIGRlZmF1bHRMYXlvdXQ6ICdlbWJlZCcsXG4gICAgICBoYW5kbGViYXJzICAgOiBIYW5kbGViYXJzLFxuICAgIH0pO1xuICAgIGFwcC5lbmdpbmUoJ2hhbmRsZWJhcnMnLCBoYnMuZW5naW5lKTtcbiAgICBhcHAuc2V0KCd2aWV3IGVuZ2luZScsICdoYW5kbGViYXJzJyk7XG5cbiAgICAvLyBzZXQgdGhlIHJvdXRlcyBvbiB0aGUgYXBwXG4gICAgcmVxdWlyZSgnLi9yb3V0ZXMvYXV0aC8nKShhcHApO1xuICAgIHJlcXVpcmUoJy4vcm91dGVzL2FwaS8nKShhcHApO1xuICAgIHJlcXVpcmUoJy4vcm91dGVzL3BhZ2VzLycpKGFwcCk7XG4gICAgcmVxdWlyZSgnLi9yb3V0ZXMvYXNzZXRzLycpKGFwcCk7XG4gICAgcmVxdWlyZSgnLi9yb3V0ZXMvZmFsbGJhY2svJykoYXBwKTtcblxuICAgIHRoaXMuYXBwID0gYXBwO1xuICB9O1xuICB0aGlzLmluaXRpYWxpemUgPSAoKSA9PiB7XG4gICAgdGhpcy5jcmVhdGVBcHAoKTtcbiAgICB0aGlzLnNlcnZlciA9IGh0dHAuU2VydmVyKHRoaXMuYXBwKTtcbiAgfTtcbiAgdGhpcy5zdGFydCA9ICgpID0+IHtcbiAgICBjb25zdCBkYiA9IHJlcXVpcmUoJ21vZGVscycpO1xuICAgIGNvbnN0IFBPUlQgPSBzaXRlQ29uZmlnLmRldGFpbHMucG9ydDtcbiAgICAvLyBzeW5jIHNlcXVlbGl6ZVxuICAgIGRiLnNlcXVlbGl6ZS5zeW5jKClcbiAgICAvLyBzdGFydCB0aGUgc2VydmVyXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2VydmVyLmxpc3RlbihQT1JULCAoKSA9PiB7XG4gICAgICAgICAgbG9nZ2VyLmluZm8oYFNlcnZlciBpcyBsaXN0ZW5pbmcgb24gUE9SVCAke1BPUlR9YCk7XG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKGBTdGFydHVwIEVycm9yOmAsIGVycm9yKTtcbiAgICAgIH0pO1xuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTZXJ2ZXI7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaW5kZXguanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJleHByZXNzXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiZXhwcmVzc1wiXG4vLyBtb2R1bGUgaWQgPSAzMVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJib2R5LXBhcnNlclwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImJvZHktcGFyc2VyXCJcbi8vIG1vZHVsZSBpZCA9IDMyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImV4cHJlc3MtaGFuZGxlYmFyc1wiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcImV4cHJlc3MtaGFuZGxlYmFyc1wiXG4vLyBtb2R1bGUgaWQgPSAzM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJoYW5kbGViYXJzXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiaGFuZGxlYmFyc1wiXG4vLyBtb2R1bGUgaWQgPSAzNFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJoZWxtZXRcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJoZWxtZXRcIlxuLy8gbW9kdWxlIGlkID0gMzVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiY29va2llLXNlc3Npb25cIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJjb29raWUtc2Vzc2lvblwiXG4vLyBtb2R1bGUgaWQgPSAzNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJodHRwXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiaHR0cFwiXG4vLyBtb2R1bGUgaWQgPSAzN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbmNvbnN0IHJlcXVlc3RMb2dnZXIgPSAocmVxLCByZXMsIG5leHQpID0+IHsgIC8vIGN1c3RvbSBsb2dnaW5nIG1pZGRsZXdhcmUgdG8gbG9nIGFsbCBpbmNvbWluZyBodHRwIHJlcXVlc3RzXG4gIGxvZ2dlci52ZXJib3NlKGBSZXF1ZXN0IG9uICR7cmVxLm9yaWdpbmFsVXJsfSBmcm9tICR7cmVxLmlwfWApO1xuICBuZXh0KCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVlc3RMb2dnZXI7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvbWlkZGxld2FyZS9yZXF1ZXN0TG9nZ2VyLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicGF0aFwiKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyBleHRlcm5hbCBcInBhdGhcIlxuLy8gbW9kdWxlIGlkID0gMzlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuXG5mdW5jdGlvbiBMb2dnZXJDb25maWcgKCkge1xuICB0aGlzLmxvZ0xldmVsID0gJ2RlYnVnJztcbiAgdGhpcy51cGRhdGUgPSAoY29uZmlnKSA9PiB7XG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgIHJldHVybiBsb2dnZXIud2FybignTm8gbG9nZ2VyIGNvbmZpZyByZWNlaXZlZC4nKTtcbiAgICB9XG4gICAgbG9nZ2VyLmluZm8oJ2NvbmZpZ3VyaW5nIHdpbnN0b24gbG9nZ2VyLi4uJyk7XG4gICAgLy8gdXBkYXRlIHZhbHVlcyB3aXRoIGxvY2FsIGNvbmZpZyBwYXJhbXNcbiAgICBjb25zdCB7bG9nTGV2ZWx9ID0gY29uZmlnO1xuICAgIHRoaXMubG9nTGV2ZWwgPSBsb2dMZXZlbDtcbiAgICAvLyBjb25maWd1cmUgdGhlIHdpbnN0b24gbG9nZ2VyXG4gICAgbG9nZ2VyLmNvbmZpZ3VyZSh7XG4gICAgICB0cmFuc3BvcnRzOiBbXG4gICAgICAgIG5ldyAobG9nZ2VyLnRyYW5zcG9ydHMuQ29uc29sZSkoe1xuICAgICAgICAgIGxldmVsICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRoaXMubG9nTGV2ZWwsXG4gICAgICAgICAgdGltZXN0YW1wICAgICAgICAgICAgICAgICAgICAgIDogZmFsc2UsXG4gICAgICAgICAgY29sb3JpemUgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICBwcmV0dHlQcmludCAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgIGhhbmRsZUV4Y2VwdGlvbnMgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgaHVtYW5SZWFkYWJsZVVuaGFuZGxlZEV4Y2VwdGlvbjogdHJ1ZSxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH0pO1xuICAgIC8vIHRlc3QgYWxsIHRoZSBsb2cgbGV2ZWxzXG4gICAgbG9nZ2VyLmluZm8oJ3Rlc3Rpbmcgd2luc3RvbiBsb2cgbGV2ZWxzLi4uJyk7XG4gICAgbG9nZ2VyLmVycm9yKCdMZXZlbCAwJyk7XG4gICAgbG9nZ2VyLndhcm4oJ0xldmVsIDEnKTtcbiAgICBsb2dnZXIuaW5mbygnTGV2ZWwgMicpO1xuICAgIGxvZ2dlci52ZXJib3NlKCdMZXZlbCAzJyk7XG4gICAgbG9nZ2VyLmRlYnVnKCdMZXZlbCA0Jyk7XG4gICAgbG9nZ2VyLnNpbGx5KCdMZXZlbCA1Jyk7XG4gIH07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBMb2dnZXJDb25maWcoKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL2NvbmZpZy9sb2dnZXJDb25maWcuanMiLCJjb25zdCB3aW5zdG9uU2xhY2tXZWJIb29rID0gcmVxdWlyZSgnd2luc3Rvbi1zbGFjay13ZWJob29rJykuU2xhY2tXZWJIb29rO1xuY29uc3Qgd2luc3RvbiA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcblxuZnVuY3Rpb24gU2xhY2tDb25maWcgKCkge1xuICB0aGlzLnNsYWNrV2ViSG9vayAgICAgID0gJ2RlZmF1bHQnO1xuICB0aGlzLnNsYWNrRXJyb3JDaGFubmVsID0gJ2RlZmF1bHQnO1xuICB0aGlzLnNsYWNrSW5mb0NoYW5uZWwgID0gJ2RlZmF1bHQnO1xuICB0aGlzLnVwZGF0ZSA9IChjb25maWcpID0+IHtcbiAgICBpZiAoIWNvbmZpZykge1xuICAgICAgcmV0dXJuIHdpbnN0b24ud2FybignTm8gc2xhY2sgY29uZmlnIHJlY2VpdmVkJyk7XG4gICAgfVxuICAgIC8vIHVwZGF0ZSB2YXJpYWJsZXNcbiAgICB3aW5zdG9uLmluZm8oJ2NvbmZpZ3VyaW5nIHNsYWNrIGxvZ2dlci4uLicpO1xuICAgIGNvbnN0IHtzbGFja1dlYkhvb2ssIHNsYWNrRXJyb3JDaGFubmVsLCBzbGFja0luZm9DaGFubmVsfSA9IGNvbmZpZztcbiAgICB0aGlzLnNsYWNrV2ViSG9vayA9IHNsYWNrV2ViSG9vaztcbiAgICB0aGlzLnNsYWNrRXJyb3JDaGFubmVsID0gc2xhY2tFcnJvckNoYW5uZWw7XG4gICAgdGhpcy5zbGFja0luZm9DaGFubmVsID0gc2xhY2tJbmZvQ2hhbm5lbDtcbiAgICAvLyB1cGRhdGUgc2xhY2sgd2ViaG9vayBzZXR0aW5nc1xuICAgIGlmICh0aGlzLnNsYWNrV2ViSG9vaykge1xuICAgICAgLy8gYWRkIGEgdHJhbnNwb3J0IGZvciBlcnJvcnMgdG8gc2xhY2tcbiAgICAgIGlmICh0aGlzLnNsYWNrRXJyb3JDaGFubmVsKSB7XG4gICAgICAgIHdpbnN0b24uYWRkKHdpbnN0b25TbGFja1dlYkhvb2ssIHtcbiAgICAgICAgICBuYW1lICAgICAgOiAnc2xhY2stZXJyb3JzLXRyYW5zcG9ydCcsXG4gICAgICAgICAgbGV2ZWwgICAgIDogJ3dhcm4nLFxuICAgICAgICAgIHdlYmhvb2tVcmw6IHRoaXMuc2xhY2tXZWJIb29rLFxuICAgICAgICAgIGNoYW5uZWwgICA6IHRoaXMuc2xhY2tFcnJvckNoYW5uZWwsXG4gICAgICAgICAgdXNlcm5hbWUgIDogJ3NwZWUuY2gnLFxuICAgICAgICAgIGljb25FbW9qaSA6ICc6ZmFjZV93aXRoX2hlYWRfYmFuZGFnZTonLFxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgICBpZiAoc2xhY2tJbmZvQ2hhbm5lbCkge1xuICAgICAgICB3aW5zdG9uLmFkZCh3aW5zdG9uU2xhY2tXZWJIb29rLCB7XG4gICAgICAgICAgbmFtZSAgICAgIDogJ3NsYWNrLWluZm8tdHJhbnNwb3J0JyxcbiAgICAgICAgICBsZXZlbCAgICAgOiAnaW5mbycsXG4gICAgICAgICAgd2ViaG9va1VybDogdGhpcy5zbGFja1dlYkhvb2ssXG4gICAgICAgICAgY2hhbm5lbCAgIDogdGhpcy5zbGFja0luZm9DaGFubmVsLFxuICAgICAgICAgIHVzZXJuYW1lICA6ICdzcGVlLmNoJyxcbiAgICAgICAgICBpY29uRW1vamkgOiAnOm5lcmRfZmFjZTonLFxuICAgICAgICB9KTtcbiAgICAgIH07XG4gICAgICAvLyBzZW5kIHRlc3QgbWVzc2FnZXNcbiAgICAgIHdpbnN0b24uaW5mbygndGVzdGluZyBzbGFjayBsb2dnZXIuLi4nKTtcbiAgICAgIHdpbnN0b24uZXJyb3IoJ1NsYWNrIFwiZXJyb3JcIiBsb2dnaW5nIGlzIG9ubGluZS4nKTtcbiAgICAgIHdpbnN0b24uaW5mbygnU2xhY2sgXCJpbmZvXCIgbG9nZ2luZyBpcyBvbmxpbmUuJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpbnN0b24ud2FybignU2xhY2sgbG9nZ2luZyBpcyBub3QgZW5hYmxlZCBiZWNhdXNlIG5vIHNsYWNrV2ViSG9vayBjb25maWcgdmFyIHByb3ZpZGVkLicpO1xuICAgIH1cbiAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFNsYWNrQ29uZmlnKCk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9jb25maWcvc2xhY2tDb25maWcuanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJ3aW5zdG9uLXNsYWNrLXdlYmhvb2tcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJ3aW5zdG9uLXNsYWNrLXdlYmhvb2tcIlxuLy8gbW9kdWxlIGlkID0gNDJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicGFzc3BvcnRcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJwYXNzcG9ydFwiXG4vLyBtb2R1bGUgaWQgPSA0M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCBQYXNzcG9ydExvY2FsU3RyYXRlZ3kgPSByZXF1aXJlKCdwYXNzcG9ydC1sb2NhbCcpLlN0cmF0ZWd5O1xuY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgZGIgPSByZXF1aXJlKCdtb2RlbHMnKTtcblxuY29uc3QgcmV0dXJuVXNlckFuZENoYW5uZWxJbmZvID0gKHVzZXJJbnN0YW5jZSkgPT4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGxldCB1c2VySW5mbyA9IHt9O1xuICAgIHVzZXJJbmZvWydpZCddID0gdXNlckluc3RhbmNlLmlkO1xuICAgIHVzZXJJbmZvWyd1c2VyTmFtZSddID0gdXNlckluc3RhbmNlLnVzZXJOYW1lO1xuICAgIHVzZXJJbnN0YW5jZVxuICAgICAgLmdldENoYW5uZWwoKVxuICAgICAgLnRoZW4oKHtjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWR9KSA9PiB7XG4gICAgICAgIHVzZXJJbmZvWydjaGFubmVsTmFtZSddID0gY2hhbm5lbE5hbWU7XG4gICAgICAgIHVzZXJJbmZvWydjaGFubmVsQ2xhaW1JZCddID0gY2hhbm5lbENsYWltSWQ7XG4gICAgICAgIHJldHVybiBkYi5DZXJ0aWZpY2F0ZS5nZXRTaG9ydENoYW5uZWxJZEZyb21Mb25nQ2hhbm5lbElkKGNoYW5uZWxDbGFpbUlkLCBjaGFubmVsTmFtZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oc2hvcnRDaGFubmVsSWQgPT4ge1xuICAgICAgICB1c2VySW5mb1snc2hvcnRDaGFubmVsSWQnXSA9IHNob3J0Q2hhbm5lbElkO1xuICAgICAgICByZXNvbHZlKHVzZXJJbmZvKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgfSk7XG4gIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgUGFzc3BvcnRMb2NhbFN0cmF0ZWd5KFxuICB7XG4gICAgdXNlcm5hbWVGaWVsZDogJ3VzZXJuYW1lJyxcbiAgICBwYXNzd29yZEZpZWxkOiAncGFzc3dvcmQnLFxuICB9LFxuICAodXNlcm5hbWUsIHBhc3N3b3JkLCBkb25lKSA9PiB7XG4gICAgcmV0dXJuIGRiLlVzZXJcbiAgICAgIC5maW5kT25lKHtcbiAgICAgICAgd2hlcmU6IHt1c2VyTmFtZTogdXNlcm5hbWV9LFxuICAgICAgfSlcbiAgICAgIC50aGVuKHVzZXIgPT4ge1xuICAgICAgICBpZiAoIXVzZXIpIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoJ25vIHVzZXIgZm91bmQnKTtcbiAgICAgICAgICByZXR1cm4gZG9uZShudWxsLCBmYWxzZSwge21lc3NhZ2U6ICdJbmNvcnJlY3QgdXNlcm5hbWUgb3IgcGFzc3dvcmQnfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVzZXIuY29tcGFyZVBhc3N3b3JkKHBhc3N3b3JkKVxuICAgICAgICAgIC50aGVuKGlzTWF0Y2ggPT4ge1xuICAgICAgICAgICAgaWYgKCFpc01hdGNoKSB7XG4gICAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnaW5jb3JyZWN0IHBhc3N3b3JkJyk7XG4gICAgICAgICAgICAgIHJldHVybiBkb25lKG51bGwsIGZhbHNlLCB7bWVzc2FnZTogJ0luY29ycmVjdCB1c2VybmFtZSBvciBwYXNzd29yZCd9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnUGFzc3dvcmQgd2FzIGEgbWF0Y2gsIHJldHVybmluZyBVc2VyJyk7XG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuVXNlckFuZENoYW5uZWxJbmZvKHVzZXIpXG4gICAgICAgICAgICAgIC50aGVuKHVzZXJJbmZvID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZG9uZShudWxsLCB1c2VySW5mbyk7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgcmV0dXJuIGRvbmUoZXJyb3IpO1xuICAgICAgfSk7XG4gIH0sXG4pO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3NwZWVjaFBhc3Nwb3J0L2xvY2FsLWxvZ2luLmpzIiwiY29uc3QgbG9nZ2VyID0gcmVxdWlyZSgnd2luc3RvbicpO1xuY29uc3QgeyByZXR1cm5TaG9ydElkIH0gPSByZXF1aXJlKCcuLi9oZWxwZXJzL3NlcXVlbGl6ZUhlbHBlcnMuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoc2VxdWVsaXplLCB7IFNUUklORywgQk9PTEVBTiwgSU5URUdFUiwgVEVYVCwgREVDSU1BTCB9KSA9PiB7XG4gIGNvbnN0IENlcnRpZmljYXRlID0gc2VxdWVsaXplLmRlZmluZShcbiAgICAnQ2VydGlmaWNhdGUnLFxuICAgIHtcbiAgICAgIGFkZHJlc3M6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGFtb3VudDoge1xuICAgICAgICB0eXBlICAgOiBERUNJTUFMKDE5LCA4KSxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBjbGFpbUlkOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBjbGFpbVNlcXVlbmNlOiB7XG4gICAgICAgIHR5cGUgICA6IElOVEVHRVIsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgZGVjb2RlZENsYWltOiB7XG4gICAgICAgIHR5cGUgICA6IEJPT0xFQU4sXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgZGVwdGg6IHtcbiAgICAgICAgdHlwZSAgIDogSU5URUdFUixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBlZmZlY3RpdmVBbW91bnQ6IHtcbiAgICAgICAgdHlwZSAgIDogREVDSU1BTCgxOSwgOCksXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgaGFzU2lnbmF0dXJlOiB7XG4gICAgICAgIHR5cGUgICA6IEJPT0xFQU4sXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgaGVpZ2h0OiB7XG4gICAgICAgIHR5cGUgICA6IElOVEVHRVIsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgaGV4OiB7XG4gICAgICAgIHR5cGUgICA6IFRFWFQoJ2xvbmcnKSxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBuYW1lOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBub3V0OiB7XG4gICAgICAgIHR5cGUgICA6IElOVEVHRVIsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgdHhpZDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgdmFsaWRBdEhlaWdodDoge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIG91dHBvaW50OiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICB2YWx1ZVZlcnNpb246IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGNsYWltVHlwZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2VydGlmaWNhdGVWZXJzaW9uOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBrZXlUeXBlOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBwdWJsaWNLZXk6IHtcbiAgICAgICAgdHlwZSAgIDogVEVYVCgnbG9uZycpLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGZyZWV6ZVRhYmxlTmFtZTogdHJ1ZSxcbiAgICB9XG4gICk7XG5cbiAgQ2VydGlmaWNhdGUuYXNzb2NpYXRlID0gZGIgPT4ge1xuICAgIENlcnRpZmljYXRlLmJlbG9uZ3NUbyhkYi5DaGFubmVsLCB7XG4gICAgICBmb3JlaWduS2V5OiB7XG4gICAgICAgIGFsbG93TnVsbDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH07XG5cbiAgQ2VydGlmaWNhdGUuZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZCA9IGZ1bmN0aW9uIChsb25nQ2hhbm5lbElkLCBjaGFubmVsTmFtZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgZ2V0U2hvcnRDaGFubmVsSWRGcm9tTG9uZ0NoYW5uZWxJZCAke2NoYW5uZWxOYW1lfToke2xvbmdDaGFubmVsSWR9YCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXNcbiAgICAgICAgLmZpbmRBbGwoe1xuICAgICAgICAgIHdoZXJlOiB7bmFtZTogY2hhbm5lbE5hbWV9LFxuICAgICAgICAgIG9yZGVyOiBbWydoZWlnaHQnLCAnQVNDJ11dLFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIHN3aXRjaCAocmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNoYW5uZWwocykgZm91bmQgd2l0aCB0aGF0IGNoYW5uZWwgbmFtZScpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmV0dXJuU2hvcnRJZChyZXN1bHQsIGxvbmdDaGFubmVsSWQpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2VydGlmaWNhdGUuZ2V0TG9uZ0NoYW5uZWxJZEZyb21TaG9ydENoYW5uZWxJZCA9IGZ1bmN0aW9uIChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYGdldExvbmdDaGFubmVsSWRGcm9tU2hvcnRDaGFubmVsSWQoJHtjaGFubmVsTmFtZX0sICR7Y2hhbm5lbENsYWltSWR9KWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZToge1xuICAgICAgICAgICAgbmFtZSAgIDogY2hhbm5lbE5hbWUsXG4gICAgICAgICAgICBjbGFpbUlkOiB7XG4gICAgICAgICAgICAgICRsaWtlOiBgJHtjaGFubmVsQ2xhaW1JZH0lYCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBvcmRlcjogW1snaGVpZ2h0JywgJ0FTQyddXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKHJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICBkZWZhdWx0OiAvLyBub3RlIHJlc3VsdHMgbXVzdCBiZSBzb3J0ZWRcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzdWx0WzBdLmNsYWltSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBDZXJ0aWZpY2F0ZS5nZXRMb25nQ2hhbm5lbElkRnJvbUNoYW5uZWxOYW1lID0gZnVuY3Rpb24gKGNoYW5uZWxOYW1lKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBnZXRMb25nQ2hhbm5lbElkRnJvbUNoYW5uZWxOYW1lKCR7Y2hhbm5lbE5hbWV9KWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZTogeyBuYW1lOiBjaGFubmVsTmFtZSB9LFxuICAgICAgICAgIG9yZGVyOiBbWydlZmZlY3RpdmVBbW91bnQnLCAnREVTQyddLCBbJ2hlaWdodCcsICdBU0MnXV0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgc3dpdGNoIChyZXN1bHQubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzdWx0WzBdLmNsYWltSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBDZXJ0aWZpY2F0ZS52YWxpZGF0ZUxvbmdDaGFubmVsSWQgPSBmdW5jdGlvbiAobmFtZSwgY2xhaW1JZCkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgdmFsaWRhdGVMb25nQ2hhbm5lbElkKCR7bmFtZX0sICR7Y2xhaW1JZH0pYCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuZmluZE9uZSh7XG4gICAgICAgIHdoZXJlOiB7bmFtZSwgY2xhaW1JZH0sXG4gICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIGlmICghcmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgICAgICAgICB9O1xuICAgICAgICAgIHJlc29sdmUoY2xhaW1JZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2VydGlmaWNhdGUuZ2V0TG9uZ0NoYW5uZWxJZCA9IGZ1bmN0aW9uIChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYGdldExvbmdDaGFubmVsSWQoJHtjaGFubmVsTmFtZX0sICR7Y2hhbm5lbENsYWltSWR9KWApO1xuICAgIGlmIChjaGFubmVsQ2xhaW1JZCAmJiAoY2hhbm5lbENsYWltSWQubGVuZ3RoID09PSA0MCkpIHsgIC8vIGlmIGEgZnVsbCBjaGFubmVsIGlkIGlzIHByb3ZpZGVkXG4gICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUxvbmdDaGFubmVsSWQoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkKTtcbiAgICB9IGVsc2UgaWYgKGNoYW5uZWxDbGFpbUlkICYmIGNoYW5uZWxDbGFpbUlkLmxlbmd0aCA8IDQwKSB7ICAvLyBpZiBhIHNob3J0IGNoYW5uZWwgaWQgaXMgcHJvdmlkZWRcbiAgICAgIHJldHVybiB0aGlzLmdldExvbmdDaGFubmVsSWRGcm9tU2hvcnRDaGFubmVsSWQoY2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0TG9uZ0NoYW5uZWxJZEZyb21DaGFubmVsTmFtZShjaGFubmVsTmFtZSk7ICAvLyBpZiBubyBjaGFubmVsIGlkIHByb3ZpZGVkXG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBDZXJ0aWZpY2F0ZTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvbW9kZWxzL2NlcnRpZmljYXRlLmpzIiwibW9kdWxlLmV4cG9ydHMgPSAoc2VxdWVsaXplLCB7IFNUUklORyB9KSA9PiB7XG4gIGNvbnN0IENoYW5uZWwgPSBzZXF1ZWxpemUuZGVmaW5lKFxuICAgICdDaGFubmVsJyxcbiAgICB7XG4gICAgICBjaGFubmVsTmFtZToge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBjaGFubmVsQ2xhaW1JZDoge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICB7XG4gICAgICBmcmVlemVUYWJsZU5hbWU6IHRydWUsXG4gICAgfVxuICApO1xuXG4gIENoYW5uZWwuYXNzb2NpYXRlID0gZGIgPT4ge1xuICAgIENoYW5uZWwuYmVsb25nc1RvKGRiLlVzZXIpO1xuICAgIENoYW5uZWwuaGFzT25lKGRiLkNlcnRpZmljYXRlKTtcbiAgfTtcblxuICByZXR1cm4gQ2hhbm5lbDtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvbW9kZWxzL2NoYW5uZWwuanMiLCJjb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5jb25zdCB7IHJldHVyblNob3J0SWQgfSA9IHJlcXVpcmUoJy4uL2hlbHBlcnMvc2VxdWVsaXplSGVscGVycy5qcycpO1xuY29uc3QgeyBhc3NldERlZmF1bHRzOiB7IHRodW1ibmFpbDogZGVmYXVsdFRodW1ibmFpbCB9LCBkZXRhaWxzOiB7IGhvc3QgfSB9ID0gcmVxdWlyZSgnLi4vLi4vY29uZmlnL3NpdGVDb25maWcuanMnKTtcblxuZnVuY3Rpb24gZGV0ZXJtaW5lRmlsZUV4dGVuc2lvbkZyb21Db250ZW50VHlwZSAoY29udGVudFR5cGUpIHtcbiAgc3dpdGNoIChjb250ZW50VHlwZSkge1xuICAgIGNhc2UgJ2ltYWdlL2pwZWcnOlxuICAgIGNhc2UgJ2ltYWdlL2pwZyc6XG4gICAgICByZXR1cm4gJ2pwZWcnO1xuICAgIGNhc2UgJ2ltYWdlL3BuZyc6XG4gICAgICByZXR1cm4gJ3BuZyc7XG4gICAgY2FzZSAnaW1hZ2UvZ2lmJzpcbiAgICAgIHJldHVybiAnZ2lmJztcbiAgICBjYXNlICd2aWRlby9tcDQnOlxuICAgICAgcmV0dXJuICdtcDQnO1xuICAgIGRlZmF1bHQ6XG4gICAgICBsb2dnZXIuZGVidWcoJ3NldHRpbmcgdW5rbm93biBmaWxlIHR5cGUgYXMgZmlsZSBleHRlbnNpb24ganBlZycpO1xuICAgICAgcmV0dXJuICdqcGVnJztcbiAgfVxufTtcblxuZnVuY3Rpb24gZGV0ZXJtaW5lVGh1bWJuYWlsIChzdG9yZWRUaHVtYm5haWwsIGRlZmF1bHRUaHVtYm5haWwpIHtcbiAgaWYgKHN0b3JlZFRodW1ibmFpbCA9PT0gJycpIHtcbiAgICByZXR1cm4gZGVmYXVsdFRodW1ibmFpbDtcbiAgfVxuICByZXR1cm4gc3RvcmVkVGh1bWJuYWlsO1xufTtcblxuZnVuY3Rpb24gcHJlcGFyZUNsYWltRGF0YSAoY2xhaW0pIHtcbiAgLy8gbG9nZ2VyLmRlYnVnKCdwcmVwYXJpbmcgY2xhaW0gZGF0YSBiYXNlZCBvbiByZXNvbHZlZCBkYXRhOicsIGNsYWltKTtcbiAgY2xhaW1bJ3RodW1ibmFpbCddID0gZGV0ZXJtaW5lVGh1bWJuYWlsKGNsYWltLnRodW1ibmFpbCwgZGVmYXVsdFRodW1ibmFpbCk7XG4gIGNsYWltWydmaWxlRXh0J10gPSBkZXRlcm1pbmVGaWxlRXh0ZW5zaW9uRnJvbUNvbnRlbnRUeXBlKGNsYWltLmNvbnRlbnRUeXBlKTtcbiAgY2xhaW1bJ2hvc3QnXSA9IGhvc3Q7XG4gIHJldHVybiBjbGFpbTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gKHNlcXVlbGl6ZSwgeyBTVFJJTkcsIEJPT0xFQU4sIElOVEVHRVIsIFRFWFQsIERFQ0lNQUwgfSkgPT4ge1xuICBjb25zdCBDbGFpbSA9IHNlcXVlbGl6ZS5kZWZpbmUoXG4gICAgJ0NsYWltJyxcbiAgICB7XG4gICAgICBhZGRyZXNzOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBhbW91bnQ6IHtcbiAgICAgICAgdHlwZSAgIDogREVDSU1BTCgxOSwgOCksXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2xhaW1JZDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2xhaW1TZXF1ZW5jZToge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGRlY29kZWRDbGFpbToge1xuICAgICAgICB0eXBlICAgOiBCT09MRUFOLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGRlcHRoOiB7XG4gICAgICAgIHR5cGUgICA6IElOVEVHRVIsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgZWZmZWN0aXZlQW1vdW50OiB7XG4gICAgICAgIHR5cGUgICA6IERFQ0lNQUwoMTksIDgpLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGhhc1NpZ25hdHVyZToge1xuICAgICAgICB0eXBlICAgOiBCT09MRUFOLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGhlaWdodDoge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGhleDoge1xuICAgICAgICB0eXBlICAgOiBURVhUKCdsb25nJyksXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbmFtZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbm91dDoge1xuICAgICAgICB0eXBlICAgOiBJTlRFR0VSLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHR4aWQ6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHZhbGlkQXRIZWlnaHQ6IHtcbiAgICAgICAgdHlwZSAgIDogSU5URUdFUixcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBvdXRwb2ludDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY2xhaW1UeXBlOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBjZXJ0aWZpY2F0ZUlkOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBhdXRob3I6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIGRlc2NyaXB0aW9uOiB7XG4gICAgICAgIHR5cGUgICA6IFRFWFQoJ2xvbmcnKSxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBsYW5ndWFnZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbGljZW5zZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbGljZW5zZVVybDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgbnNmdzoge1xuICAgICAgICB0eXBlICAgOiBCT09MRUFOLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHByZXZpZXc6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHRodW1ibmFpbDoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgdGl0bGU6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIG1ldGFkYXRhVmVyc2lvbjoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgY29udGVudFR5cGU6IHtcbiAgICAgICAgdHlwZSAgIDogU1RSSU5HLFxuICAgICAgICBkZWZhdWx0OiBudWxsLFxuICAgICAgfSxcbiAgICAgIHNvdXJjZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgc291cmNlVHlwZToge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgc291cmNlVmVyc2lvbjoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgc3RyZWFtVmVyc2lvbjoge1xuICAgICAgICB0eXBlICAgOiBTVFJJTkcsXG4gICAgICAgIGRlZmF1bHQ6IG51bGwsXG4gICAgICB9LFxuICAgICAgdmFsdWVWZXJzaW9uOiB7XG4gICAgICAgIHR5cGUgICA6IFNUUklORyxcbiAgICAgICAgZGVmYXVsdDogbnVsbCxcbiAgICAgIH0sXG4gICAgICBjaGFubmVsTmFtZToge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiB0cnVlLFxuICAgICAgICBkZWZhdWx0ICA6IG51bGwsXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgZnJlZXplVGFibGVOYW1lOiB0cnVlLFxuICAgIH1cbiAgKTtcblxuICBDbGFpbS5hc3NvY2lhdGUgPSBkYiA9PiB7XG4gICAgQ2xhaW0uYmVsb25nc1RvKGRiLkZpbGUsIHtcbiAgICAgIGZvcmVpZ25LZXk6IHtcbiAgICAgICAgYWxsb3dOdWxsOiB0cnVlLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfTtcblxuICBDbGFpbS5nZXRTaG9ydENsYWltSWRGcm9tTG9uZ0NsYWltSWQgPSBmdW5jdGlvbiAoY2xhaW1JZCwgY2xhaW1OYW1lKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBDbGFpbS5nZXRTaG9ydENsYWltSWRGcm9tTG9uZ0NsYWltSWQgZm9yICR7Y2xhaW1OYW1lfSMke2NsYWltSWR9YCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXNcbiAgICAgICAgLmZpbmRBbGwoe1xuICAgICAgICAgIHdoZXJlOiB7IG5hbWU6IGNsYWltTmFtZSB9LFxuICAgICAgICAgIG9yZGVyOiBbWydoZWlnaHQnLCAnQVNDJ11dLFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIHN3aXRjaCAocmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNsYWltKHMpIGZvdW5kIHdpdGggdGhhdCBjbGFpbSBuYW1lJyk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICByZXNvbHZlKHJldHVyblNob3J0SWQocmVzdWx0LCBjbGFpbUlkKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIENsYWltLmdldEFsbENoYW5uZWxDbGFpbXMgPSBmdW5jdGlvbiAoY2hhbm5lbENsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYENsYWltLmdldEFsbENoYW5uZWxDbGFpbXMgZm9yICR7Y2hhbm5lbENsYWltSWR9YCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXNcbiAgICAgICAgLmZpbmRBbGwoe1xuICAgICAgICAgIHdoZXJlOiB7IGNlcnRpZmljYXRlSWQ6IGNoYW5uZWxDbGFpbUlkIH0sXG4gICAgICAgICAgb3JkZXI6IFtbJ2hlaWdodCcsICdBU0MnXV0sXG4gICAgICAgICAgcmF3ICA6IHRydWUsICAvLyByZXR1cm5zIGFuIGFycmF5IG9mIG9ubHkgZGF0YSwgbm90IGFuIGFycmF5IG9mIGluc3RhbmNlc1xuICAgICAgICB9KVxuICAgICAgICAudGhlbihjaGFubmVsQ2xhaW1zQXJyYXkgPT4ge1xuICAgICAgICAgIC8vIGxvZ2dlci5kZWJ1ZygnY2hhbm5lbGNsYWltc2FycmF5IGxlbmd0aDonLCBjaGFubmVsQ2xhaW1zQXJyYXkubGVuZ3RoKTtcbiAgICAgICAgICBzd2l0Y2ggKGNoYW5uZWxDbGFpbXNBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICBjaGFubmVsQ2xhaW1zQXJyYXkuZm9yRWFjaChjbGFpbSA9PiB7XG4gICAgICAgICAgICAgICAgY2xhaW1bJ2ZpbGVFeHQnXSA9IGRldGVybWluZUZpbGVFeHRlbnNpb25Gcm9tQ29udGVudFR5cGUoY2xhaW0uY29udGVudFR5cGUpO1xuICAgICAgICAgICAgICAgIGNsYWltWyd0aHVtYm5haWwnXSA9IGRldGVybWluZVRodW1ibmFpbChjbGFpbS50aHVtYm5haWwsIGRlZmF1bHRUaHVtYm5haWwpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjbGFpbTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKGNoYW5uZWxDbGFpbXNBcnJheSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIENsYWltLmdldENsYWltSWRCeUxvbmdDaGFubmVsSWQgPSBmdW5jdGlvbiAoY2hhbm5lbENsYWltSWQsIGNsYWltTmFtZSkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgZmluZGluZyBjbGFpbSBpZCBmb3IgY2xhaW0gJHtjbGFpbU5hbWV9IGZyb20gY2hhbm5lbCAke2NoYW5uZWxDbGFpbUlkfWApO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzXG4gICAgICAgIC5maW5kQWxsKHtcbiAgICAgICAgICB3aGVyZTogeyBuYW1lOiBjbGFpbU5hbWUsIGNlcnRpZmljYXRlSWQ6IGNoYW5uZWxDbGFpbUlkIH0sXG4gICAgICAgICAgb3JkZXI6IFtbJ2lkJywgJ0FTQyddXSxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKHJlc3VsdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc3VsdFswXS5jbGFpbUlkKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihgJHtyZXN1bHQubGVuZ3RofSByZWNvcmRzIGZvdW5kIGZvciBcIiR7Y2xhaW1OYW1lfVwiIGluIGNoYW5uZWwgXCIke2NoYW5uZWxDbGFpbUlkfVwiYCk7XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc3VsdFswXS5jbGFpbUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2xhaW0uZ2V0TG9uZ0NsYWltSWRGcm9tU2hvcnRDbGFpbUlkID0gZnVuY3Rpb24gKG5hbWUsIHNob3J0SWQpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpc1xuICAgICAgICAuZmluZEFsbCh7XG4gICAgICAgICAgd2hlcmU6IHtcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBjbGFpbUlkOiB7XG4gICAgICAgICAgICAgICRsaWtlOiBgJHtzaG9ydElkfSVgLFxuICAgICAgICAgICAgfX0sXG4gICAgICAgICAgb3JkZXI6IFtbJ2hlaWdodCcsICdBU0MnXV0sXG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgc3dpdGNoIChyZXN1bHQubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgZGVmYXVsdDogLy8gbm90ZSByZXN1bHRzIG11c3QgYmUgc29ydGVkXG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc3VsdFswXS5jbGFpbUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2xhaW0uZ2V0VG9wRnJlZUNsYWltSWRCeUNsYWltTmFtZSA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXNcbiAgICAgICAgLmZpbmRBbGwoe1xuICAgICAgICAgIHdoZXJlOiB7IG5hbWUgfSxcbiAgICAgICAgICBvcmRlcjogW1snZWZmZWN0aXZlQW1vdW50JywgJ0RFU0MnXSwgWydoZWlnaHQnLCAnQVNDJ11dLCAgLy8gbm90ZTogbWF5YmUgaGVpZ2h0IGFuZCBlZmZlY3RpdmUgYW1vdW50IG5lZWQgdG8gc3dpdGNoP1xuICAgICAgICB9KVxuICAgICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnbGVuZ3RoIG9mIHJlc3VsdCcsIHJlc3VsdC5sZW5ndGgpO1xuICAgICAgICAgIHN3aXRjaCAocmVzdWx0Lmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKHJlc3VsdFswXS5kYXRhVmFsdWVzLmNsYWltSWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBDbGFpbS52YWxpZGF0ZUxvbmdDbGFpbUlkID0gZnVuY3Rpb24gKG5hbWUsIGNsYWltSWQpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpcy5maW5kT25lKHtcbiAgICAgICAgd2hlcmU6IHtuYW1lLCBjbGFpbUlkfSxcbiAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgIH07XG4gICAgICAgICAgcmVzb2x2ZShjbGFpbUlkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBDbGFpbS5nZXRMb25nQ2xhaW1JZCA9IGZ1bmN0aW9uIChjbGFpbU5hbWUsIGNsYWltSWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYGdldExvbmdDbGFpbUlkKCR7Y2xhaW1OYW1lfSwgJHtjbGFpbUlkfSlgKTtcbiAgICBpZiAoY2xhaW1JZCAmJiAoY2xhaW1JZC5sZW5ndGggPT09IDQwKSkgeyAgLy8gaWYgYSBmdWxsIGNsYWltIGlkIGlzIHByb3ZpZGVkXG4gICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZUxvbmdDbGFpbUlkKGNsYWltTmFtZSwgY2xhaW1JZCk7XG4gICAgfSBlbHNlIGlmIChjbGFpbUlkICYmIGNsYWltSWQubGVuZ3RoIDwgNDApIHtcbiAgICAgIHJldHVybiB0aGlzLmdldExvbmdDbGFpbUlkRnJvbVNob3J0Q2xhaW1JZChjbGFpbU5hbWUsIGNsYWltSWQpOyAgLy8gaWYgYSBzaG9ydCBjbGFpbSBpZCBpcyBwcm92aWRlZFxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRUb3BGcmVlQ2xhaW1JZEJ5Q2xhaW1OYW1lKGNsYWltTmFtZSk7ICAvLyBpZiBubyBjbGFpbSBpZCBpcyBwcm92aWRlZFxuICAgIH1cbiAgfTtcblxuICBDbGFpbS5yZXNvbHZlQ2xhaW0gPSBmdW5jdGlvbiAobmFtZSwgY2xhaW1JZCkge1xuICAgIGxvZ2dlci5kZWJ1ZyhgQ2xhaW0ucmVzb2x2ZUNsYWltOiAke25hbWV9ICR7Y2xhaW1JZH1gKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdGhpc1xuICAgICAgICAuZmluZEFsbCh7XG4gICAgICAgICAgd2hlcmU6IHsgbmFtZSwgY2xhaW1JZCB9LFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihjbGFpbUFycmF5ID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKGNsYWltQXJyYXkubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgIHJldHVybiByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShwcmVwYXJlQ2xhaW1EYXRhKGNsYWltQXJyYXlbMF0uZGF0YVZhbHVlcykpO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKGBtb3JlIHRoYW4gb25lIHJlY29yZCBtYXRjaGVzICR7bmFtZX0jJHtjbGFpbUlkfSBpbiBkYi5DbGFpbWApO1xuICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShwcmVwYXJlQ2xhaW1EYXRhKGNsYWltQXJyYXlbMF0uZGF0YVZhbHVlcykpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gQ2xhaW07XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21vZGVscy9jbGFpbS5qcyIsIm1vZHVsZS5leHBvcnRzID0gKHNlcXVlbGl6ZSwgeyBTVFJJTkcsIEJPT0xFQU4sIElOVEVHRVIgfSkgPT4ge1xuICBjb25zdCBGaWxlID0gc2VxdWVsaXplLmRlZmluZShcbiAgICAnRmlsZScsXG4gICAge1xuICAgICAgbmFtZToge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICBjbGFpbUlkOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIGFkZHJlc3M6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgICAgb3V0cG9pbnQ6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgICAgaGVpZ2h0OiB7XG4gICAgICAgIHR5cGUgICAgIDogSU5URUdFUixcbiAgICAgICAgYWxsb3dOdWxsOiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdCAgOiAwLFxuICAgICAgfSxcbiAgICAgIGZpbGVOYW1lOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIGZpbGVQYXRoOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIGZpbGVUeXBlOiB7XG4gICAgICAgIHR5cGU6IFNUUklORyxcbiAgICAgIH0sXG4gICAgICBuc2Z3OiB7XG4gICAgICAgIHR5cGUgICAgICAgIDogQk9PTEVBTixcbiAgICAgICAgYWxsb3dOdWxsICAgOiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgICB0cmVuZGluZ0VsaWdpYmxlOiB7XG4gICAgICAgIHR5cGUgICAgICAgIDogQk9PTEVBTixcbiAgICAgICAgYWxsb3dOdWxsICAgOiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICAgICAgfSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGZyZWV6ZVRhYmxlTmFtZTogdHJ1ZSxcbiAgICB9XG4gICk7XG5cbiAgRmlsZS5hc3NvY2lhdGUgPSBkYiA9PiB7XG4gICAgRmlsZS5oYXNNYW55KGRiLlJlcXVlc3QpO1xuICAgIEZpbGUuaGFzT25lKGRiLkNsYWltKTtcbiAgfTtcblxuICBGaWxlLmdldFJlY2VudENsYWltcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5maW5kQWxsKHtcbiAgICAgIHdoZXJlOiB7IG5zZnc6IGZhbHNlLCB0cmVuZGluZ0VsaWdpYmxlOiB0cnVlIH0sXG4gICAgICBvcmRlcjogW1snY3JlYXRlZEF0JywgJ0RFU0MnXV0sXG4gICAgICBsaW1pdDogMjUsXG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIEZpbGU7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21vZGVscy9maWxlLmpzIiwibW9kdWxlLmV4cG9ydHMgPSAoc2VxdWVsaXplLCB7IFNUUklORywgQk9PTEVBTiwgVEVYVCB9KSA9PiB7XG4gIGNvbnN0IFJlcXVlc3QgPSBzZXF1ZWxpemUuZGVmaW5lKFxuICAgICdSZXF1ZXN0JyxcbiAgICB7XG4gICAgICBhY3Rpb246IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgICAgdXJsOiB7XG4gICAgICAgIHR5cGUgICAgIDogU1RSSU5HLFxuICAgICAgICBhbGxvd051bGw6IGZhbHNlLFxuICAgICAgfSxcbiAgICAgIGlwQWRkcmVzczoge1xuICAgICAgICB0eXBlICAgICA6IFNUUklORyxcbiAgICAgICAgYWxsb3dOdWxsOiB0cnVlLFxuICAgICAgfSxcbiAgICAgIHJlc3VsdDoge1xuICAgICAgICB0eXBlICAgICA6IFRFWFQoJ2xvbmcnKSxcbiAgICAgICAgYWxsb3dOdWxsOiB0cnVlLFxuICAgICAgICBkZWZhdWx0ICA6IG51bGwsXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgZnJlZXplVGFibGVOYW1lOiB0cnVlLFxuICAgIH1cbiAgKTtcblxuICBSZXF1ZXN0LmFzc29jaWF0ZSA9IGRiID0+IHtcbiAgICBSZXF1ZXN0LmJlbG9uZ3NUbyhkYi5GaWxlLCB7XG4gICAgICBmb3JlaWduS2V5OiB7XG4gICAgICAgIGFsbG93TnVsbDogdHJ1ZSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIFJlcXVlc3Q7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL21vZGVscy9yZXF1ZXN0LmpzIiwiJ3VzZSBzdHJpY3QnO1xuY29uc3QgYmNyeXB0ID0gcmVxdWlyZSgnYmNyeXB0Jyk7XG5jb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKHNlcXVlbGl6ZSwgeyBTVFJJTkcgfSkgPT4ge1xuICBjb25zdCBVc2VyID0gc2VxdWVsaXplLmRlZmluZShcbiAgICAnVXNlcicsXG4gICAge1xuICAgICAgdXNlck5hbWU6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgICAgcGFzc3dvcmQ6IHtcbiAgICAgICAgdHlwZSAgICAgOiBTVFJJTkcsXG4gICAgICAgIGFsbG93TnVsbDogZmFsc2UsXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgZnJlZXplVGFibGVOYW1lOiB0cnVlLFxuICAgIH1cbiAgKTtcblxuICBVc2VyLmFzc29jaWF0ZSA9IGRiID0+IHtcbiAgICBVc2VyLmhhc09uZShkYi5DaGFubmVsKTtcbiAgfTtcblxuICBVc2VyLnByb3RvdHlwZS5jb21wYXJlUGFzc3dvcmQgPSBmdW5jdGlvbiAocGFzc3dvcmQpIHtcbiAgICByZXR1cm4gYmNyeXB0LmNvbXBhcmUocGFzc3dvcmQsIHRoaXMucGFzc3dvcmQpO1xuICB9O1xuXG4gIFVzZXIucHJvdG90eXBlLmNoYW5nZVBhc3N3b3JkID0gZnVuY3Rpb24gKG5ld1Bhc3N3b3JkKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIC8vIGdlbmVyYXRlIGEgc2FsdCBzdHJpbmcgdG8gdXNlIGZvciBoYXNoaW5nXG4gICAgICBiY3J5cHQuZ2VuU2FsdCgoc2FsdEVycm9yLCBzYWx0KSA9PiB7XG4gICAgICAgIGlmIChzYWx0RXJyb3IpIHtcbiAgICAgICAgICBsb2dnZXIuZXJyb3IoJ3NhbHQgZXJyb3InLCBzYWx0RXJyb3IpO1xuICAgICAgICAgIHJlamVjdChzYWx0RXJyb3IpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBnZW5lcmF0ZSBhIGhhc2hlZCB2ZXJzaW9uIG9mIHRoZSB1c2VyJ3MgcGFzc3dvcmRcbiAgICAgICAgYmNyeXB0Lmhhc2gobmV3UGFzc3dvcmQsIHNhbHQsIChoYXNoRXJyb3IsIGhhc2gpID0+IHtcbiAgICAgICAgICAvLyBpZiB0aGVyZSBpcyBhbiBlcnJvciB3aXRoIHRoZSBoYXNoIGdlbmVyYXRpb24gcmV0dXJuIHRoZSBlcnJvclxuICAgICAgICAgIGlmIChoYXNoRXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignaGFzaCBlcnJvcicsIGhhc2hFcnJvcik7XG4gICAgICAgICAgICByZWplY3QoaGFzaEVycm9yKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gcmVwbGFjZSB0aGUgY3VycmVudCBwYXNzd29yZCB3aXRoIHRoZSBuZXcgaGFzaFxuICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgIC51cGRhdGUoe3Bhc3N3b3JkOiBoYXNofSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBwcmUtc2F2ZSBob29rIG1ldGhvZCB0byBoYXNoIHRoZSB1c2VyJ3MgcGFzc3dvcmQgYmVmb3JlIHRoZSB1c2VyJ3MgaW5mbyBpcyBzYXZlZCB0byB0aGUgZGIuXG4gIFVzZXIuaG9vaygnYmVmb3JlQ3JlYXRlJywgKHVzZXIsIG9wdGlvbnMpID0+IHtcbiAgICBsb2dnZXIuZGVidWcoJ1VzZXIuYmVmb3JlQ3JlYXRlIGhvb2suLi4nKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgLy8gZ2VuZXJhdGUgYSBzYWx0IHN0cmluZyB0byB1c2UgZm9yIGhhc2hpbmdcbiAgICAgIGJjcnlwdC5nZW5TYWx0KChzYWx0RXJyb3IsIHNhbHQpID0+IHtcbiAgICAgICAgaWYgKHNhbHRFcnJvcikge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcignc2FsdCBlcnJvcicsIHNhbHRFcnJvcik7XG4gICAgICAgICAgcmVqZWN0KHNhbHRFcnJvcik7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIGdlbmVyYXRlIGEgaGFzaGVkIHZlcnNpb24gb2YgdGhlIHVzZXIncyBwYXNzd29yZFxuICAgICAgICBiY3J5cHQuaGFzaCh1c2VyLnBhc3N3b3JkLCBzYWx0LCAoaGFzaEVycm9yLCBoYXNoKSA9PiB7XG4gICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYW4gZXJyb3Igd2l0aCB0aGUgaGFzaCBnZW5lcmF0aW9uIHJldHVybiB0aGUgZXJyb3JcbiAgICAgICAgICBpZiAoaGFzaEVycm9yKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ2hhc2ggZXJyb3InLCBoYXNoRXJyb3IpO1xuICAgICAgICAgICAgcmVqZWN0KGhhc2hFcnJvcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIHJlcGxhY2UgdGhlIHBhc3N3b3JkIHN0cmluZyB3aXRoIHRoZSBoYXNoIHBhc3N3b3JkIHZhbHVlXG4gICAgICAgICAgdXNlci5wYXNzd29yZCA9IGhhc2g7XG4gICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gVXNlcjtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvbW9kZWxzL3VzZXIuanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJiY3J5cHRcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJiY3J5cHRcIlxuLy8gbW9kdWxlIGlkID0gNTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgUGFzc3BvcnRMb2NhbFN0cmF0ZWd5ID0gcmVxdWlyZSgncGFzc3BvcnQtbG9jYWwnKS5TdHJhdGVneTtcbmNvbnN0IGxicnlBcGkgPSByZXF1aXJlKCcuLi9oZWxwZXJzL2xicnlBcGkuanMnKTtcbmNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoJ3dpbnN0b24nKTtcbmNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFBhc3Nwb3J0TG9jYWxTdHJhdGVneShcbiAge1xuICAgIHVzZXJuYW1lRmllbGQ6ICd1c2VybmFtZScsXG4gICAgcGFzc3dvcmRGaWVsZDogJ3Bhc3N3b3JkJyxcbiAgfSxcbiAgKHVzZXJuYW1lLCBwYXNzd29yZCwgZG9uZSkgPT4ge1xuICAgIGxvZ2dlci52ZXJib3NlKGBuZXcgY2hhbm5lbCBzaWdudXAgcmVxdWVzdC4gdXNlcjogJHt1c2VybmFtZX0gcGFzczogJHtwYXNzd29yZH0gLmApO1xuICAgIGxldCB1c2VySW5mbyA9IHt9O1xuICAgIC8vIHNlcnZlci1zaWRlIHZhbGlkYXRvbiBvZiBpbnB1dHMgKHVzZXJuYW1lLCBwYXNzd29yZClcblxuICAgIC8vIGNyZWF0ZSB0aGUgY2hhbm5lbCBhbmQgcmV0cmlldmUgdGhlIG1ldGFkYXRhXG4gICAgcmV0dXJuIGxicnlBcGkuY3JlYXRlQ2hhbm5lbChgQCR7dXNlcm5hbWV9YClcbiAgICAgIC50aGVuKHR4ID0+IHtcbiAgICAgICAgLy8gY3JlYXRlIHVzZXIgcmVjb3JkXG4gICAgICAgIGNvbnN0IHVzZXJEYXRhID0ge1xuICAgICAgICAgIHVzZXJOYW1lOiB1c2VybmFtZSxcbiAgICAgICAgICBwYXNzd29yZDogcGFzc3dvcmQsXG4gICAgICAgIH07XG4gICAgICAgIGxvZ2dlci52ZXJib3NlKCd1c2VyRGF0YSA+JywgdXNlckRhdGEpO1xuICAgICAgICAvLyBjcmVhdGUgdXNlciByZWNvcmRcbiAgICAgICAgY29uc3QgY2hhbm5lbERhdGEgPSB7XG4gICAgICAgICAgY2hhbm5lbE5hbWUgICA6IGBAJHt1c2VybmFtZX1gLFxuICAgICAgICAgIGNoYW5uZWxDbGFpbUlkOiB0eC5jbGFpbV9pZCxcbiAgICAgICAgfTtcbiAgICAgICAgbG9nZ2VyLnZlcmJvc2UoJ2NoYW5uZWxEYXRhID4nLCBjaGFubmVsRGF0YSk7XG4gICAgICAgIC8vIGNyZWF0ZSBjZXJ0aWZpY2F0ZSByZWNvcmRcbiAgICAgICAgY29uc3QgY2VydGlmaWNhdGVEYXRhID0ge1xuICAgICAgICAgIGNsYWltSWQ6IHR4LmNsYWltX2lkLFxuICAgICAgICAgIG5hbWUgICA6IGBAJHt1c2VybmFtZX1gLFxuICAgICAgICAgIC8vIGFkZHJlc3MsXG4gICAgICAgIH07XG4gICAgICAgIGxvZ2dlci52ZXJib3NlKCdjZXJ0aWZpY2F0ZURhdGEgPicsIGNlcnRpZmljYXRlRGF0YSk7XG4gICAgICAgIC8vIHNhdmUgdXNlciBhbmQgY2VydGlmaWNhdGUgdG8gZGJcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtkYi5Vc2VyLmNyZWF0ZSh1c2VyRGF0YSksIGRiLkNoYW5uZWwuY3JlYXRlKGNoYW5uZWxEYXRhKSwgZGIuQ2VydGlmaWNhdGUuY3JlYXRlKGNlcnRpZmljYXRlRGF0YSldKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoW25ld1VzZXIsIG5ld0NoYW5uZWwsIG5ld0NlcnRpZmljYXRlXSkgPT4ge1xuICAgICAgICBsb2dnZXIudmVyYm9zZSgndXNlciBhbmQgY2VydGlmaWNhdGUgc3VjY2Vzc2Z1bGx5IGNyZWF0ZWQnKTtcbiAgICAgICAgLy8gc3RvcmUgdGhlIHJlbGV2YW50IG5ld1VzZXIgaW5mbyB0byBiZSBwYXNzZWQgYmFjayBmb3IgcmVxLlVzZXJcbiAgICAgICAgdXNlckluZm9bJ2lkJ10gPSBuZXdVc2VyLmlkO1xuICAgICAgICB1c2VySW5mb1sndXNlck5hbWUnXSA9IG5ld1VzZXIudXNlck5hbWU7XG4gICAgICAgIHVzZXJJbmZvWydjaGFubmVsTmFtZSddID0gbmV3Q2hhbm5lbC5jaGFubmVsTmFtZTtcbiAgICAgICAgdXNlckluZm9bJ2NoYW5uZWxDbGFpbUlkJ10gPSBuZXdDaGFubmVsLmNoYW5uZWxDbGFpbUlkO1xuICAgICAgICAvLyBhc3NvY2lhdGUgdGhlIGluc3RhbmNlc1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW25ld0NlcnRpZmljYXRlLnNldENoYW5uZWwobmV3Q2hhbm5lbCksIG5ld0NoYW5uZWwuc2V0VXNlcihuZXdVc2VyKV0pO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgbG9nZ2VyLnZlcmJvc2UoJ3VzZXIgYW5kIGNlcnRpZmljYXRlIHN1Y2Nlc3NmdWxseSBhc3NvY2lhdGVkJyk7XG4gICAgICAgIHJldHVybiBkYi5DZXJ0aWZpY2F0ZS5nZXRTaG9ydENoYW5uZWxJZEZyb21Mb25nQ2hhbm5lbElkKHVzZXJJbmZvLmNoYW5uZWxDbGFpbUlkLCB1c2VySW5mby5jaGFubmVsTmFtZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oc2hvcnRDaGFubmVsSWQgPT4ge1xuICAgICAgICB1c2VySW5mb1snc2hvcnRDaGFubmVsSWQnXSA9IHNob3J0Q2hhbm5lbElkO1xuICAgICAgICByZXR1cm4gZG9uZShudWxsLCB1c2VySW5mbyk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdzaWdudXAgZXJyb3InLCBlcnJvcik7XG4gICAgICAgIHJldHVybiBkb25lKGVycm9yKTtcbiAgICAgIH0pO1xuICB9XG4pO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3NwZWVjaFBhc3Nwb3J0L2xvY2FsLXNpZ251cC5qcyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImF4aW9zXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiYXhpb3NcIlxuLy8gbW9kdWxlIGlkID0gNTNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgbGJyeUNvbmZpZyA9IHtcbiAgYXBpOiB7XG4gICAgYXBpSG9zdDogJ2xvY2FsaG9zdCcsXG4gICAgYXBpUG9ydDogJzUyNzknLFxuICB9LFxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBsYnJ5Q29uZmlnO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vY29uZmlnL2xicnlDb25maWcuanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJ1bml2ZXJzYWwtYW5hbHl0aWNzXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwidW5pdmVyc2FsLWFuYWx5dGljc1wiXG4vLyBtb2R1bGUgaWQgPSA1NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2VyaWFsaXplU3BlZWNoVXNlciAodXNlciwgZG9uZSkgeyAgLy8gcmV0dXJucyB1c2VyIGRhdGEgdG8gYmUgc2VyaWFsaXplZCBpbnRvIHNlc3Npb25cbiAgICBjb25zb2xlLmxvZygnc2VyaWFsaXppbmcgdXNlcicpO1xuICAgIGRvbmUobnVsbCwgdXNlcik7XG4gIH0sXG4gIGRlc2VyaWFsaXplU3BlZWNoVXNlciAodXNlciwgZG9uZSkgeyAgLy8gZGVzZXJpYWxpemVzIHNlc3Npb24gYW5kIHBvcHVsYXRlcyBhZGRpdGlvbmFsIGluZm8gdG8gcmVxLnVzZXJcbiAgICBjb25zb2xlLmxvZygnZGVzZXJpYWxpemluZyB1c2VyJyk7XG4gICAgZG9uZShudWxsLCB1c2VyKTtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9hdXRoSGVscGVycy5qcyIsImNvbnN0IHNwZWVjaFBhc3Nwb3J0ID0gcmVxdWlyZSgnc3BlZWNoUGFzc3BvcnQnKTtcbmNvbnN0IGhhbmRsZVNpZ251cFJlcXVlc3QgPSByZXF1aXJlKCcuL3NpZ251cCcpO1xuY29uc3QgaGFuZGxlTG9naW5SZXF1ZXN0ID0gcmVxdWlyZSgnLi9sb2dpbicpO1xuY29uc3QgaGFuZGxlTG9nb3V0UmVxdWVzdCA9IHJlcXVpcmUoJy4vbG9nb3V0Jyk7XG5jb25zdCBoYW5kbGVVc2VyUmVxdWVzdCA9IHJlcXVpcmUoJy4vdXNlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IChhcHApID0+IHtcbiAgYXBwLnBvc3QoJy9zaWdudXAnLCBzcGVlY2hQYXNzcG9ydC5hdXRoZW50aWNhdGUoJ2xvY2FsLXNpZ251cCcpLCBoYW5kbGVTaWdudXBSZXF1ZXN0KTtcbiAgYXBwLnBvc3QoJy9sb2dpbicsIGhhbmRsZUxvZ2luUmVxdWVzdCk7XG4gIGFwcC5nZXQoJy9sb2dvdXQnLCBoYW5kbGVMb2dvdXRSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL3VzZXInLCBoYW5kbGVVc2VyUmVxdWVzdCk7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hdXRoL2luZGV4LmpzIiwiY29uc3Qgc2lnbnVwID0gKHJlcSwgcmVzKSA9PiB7XG4gIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtcbiAgICBzdWNjZXNzICAgICAgIDogdHJ1ZSxcbiAgICBjaGFubmVsTmFtZSAgIDogcmVxLnVzZXIuY2hhbm5lbE5hbWUsXG4gICAgY2hhbm5lbENsYWltSWQ6IHJlcS51c2VyLmNoYW5uZWxDbGFpbUlkLFxuICAgIHNob3J0Q2hhbm5lbElkOiByZXEudXNlci5zaG9ydENoYW5uZWxJZCxcbiAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHNpZ251cDtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXV0aC9zaWdudXAuanMiLCJjb25zdCBzcGVlY2hQYXNzcG9ydCA9IHJlcXVpcmUoJ3NwZWVjaFBhc3Nwb3J0Jyk7XG5cbmNvbnN0IGxvZ2luID0gKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gIHNwZWVjaFBhc3Nwb3J0LmF1dGhlbnRpY2F0ZSgnbG9jYWwtbG9naW4nLCAoZXJyLCB1c2VyLCBpbmZvKSA9PiB7XG4gICAgaWYgKGVycikge1xuICAgICAgcmV0dXJuIG5leHQoZXJyKTtcbiAgICB9XG4gICAgaWYgKCF1c2VyKSB7XG4gICAgICByZXR1cm4gcmVzLnN0YXR1cyg0MDApLmpzb24oe1xuICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgbWVzc2FnZTogaW5mby5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJlcS5sb2dJbih1c2VyLCAoZXJyKSA9PiB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJldHVybiBuZXh0KGVycik7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzLnN0YXR1cygyMDApLmpzb24oe1xuICAgICAgICBzdWNjZXNzICAgICAgIDogdHJ1ZSxcbiAgICAgICAgY2hhbm5lbE5hbWUgICA6IHJlcS51c2VyLmNoYW5uZWxOYW1lLFxuICAgICAgICBjaGFubmVsQ2xhaW1JZDogcmVxLnVzZXIuY2hhbm5lbENsYWltSWQsXG4gICAgICAgIHNob3J0Q2hhbm5lbElkOiByZXEudXNlci5zaG9ydENoYW5uZWxJZCxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KShyZXEsIHJlcywgbmV4dCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGxvZ2luO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hdXRoL2xvZ2luLmpzIiwiY29uc3QgbG9nb3V0ID0gKHJlcSwgcmVzKSA9PiB7XG4gIHJlcS5sb2dvdXQoKTtcbiAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWUsIG1lc3NhZ2U6ICd5b3Ugc3VjY2Vzc2Z1bGx5IGxvZ2dlZCBvdXQnfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGxvZ291dDtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXV0aC9sb2dvdXQuanMiLCJjb25zdCB1c2VyID0gKHJlcSwgcmVzKSA9PiB7XG4gIGlmIChyZXEudXNlcikge1xuICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiByZXEudXNlcn0pO1xuICB9IGVsc2Uge1xuICAgIHJlcy5zdGF0dXMoNDAxKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogJ3VzZXIgaXMgbm90IGxvZ2dlZCBpbid9KTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB1c2VyO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hdXRoL3VzZXIuanMiLCJjb25zdCBjaGFubmVsQXZhaWxhYmlsaXR5ID0gcmVxdWlyZSgnLi9jaGFubmVsQXZhaWxhYmlsaXR5Jyk7XG5jb25zdCBjaGFubmVsQ2xhaW1zID0gcmVxdWlyZSgnLi9jaGFubmVsQ2xhaW1zJyk7XG5jb25zdCBjaGFubmVsRGF0YSA9IHJlcXVpcmUoJy4vY2hhbm5lbERhdGEnKTtcbmNvbnN0IGNoYW5uZWxTaG9ydElkID0gcmVxdWlyZSgnLi9jaGFubmVsU2hvcnRJZCcpO1xuY29uc3QgY2xhaW1BdmFpbGFiaWxpdHkgPSByZXF1aXJlKCcuL2NsYWltQXZhaWxhYmlsaXR5Jyk7XG5jb25zdCBjbGFpbURhdGEgPSByZXF1aXJlKCcuL2NsYWltRGF0YScpO1xuY29uc3QgY2xhaW1HZXQgPSByZXF1aXJlKCcuL2NsYWltR2V0Jyk7XG5jb25zdCBjbGFpbUxvbmdJZCA9IHJlcXVpcmUoJy4vY2xhaW1Mb25nSWQnKTtcbmNvbnN0IGNsYWltUHVibGlzaCA9IHJlcXVpcmUoJy4vY2xhaW1QdWJsaXNoJyk7XG5jb25zdCBjbGFpbVJlc29sdmUgPSByZXF1aXJlKCcuL2NsYWltUmVzb2x2ZScpO1xuY29uc3QgY2xhaW1TaG9ydElkID0gcmVxdWlyZSgnLi9jbGFpbVNob3J0SWQnKTtcbmNvbnN0IGNsYWltTGlzdCA9IHJlcXVpcmUoJy4vY2xhaW1MaXN0Jyk7XG5jb25zdCBmaWxlQXZhaWxhYmlsaXR5ID0gcmVxdWlyZSgnLi9maWxlQXZhaWxhYmlsaXR5Jyk7XG5cbmNvbnN0IG11bHRpcGFydE1pZGRsZXdhcmUgPSByZXF1aXJlKCdoZWxwZXJzL211bHRpcGFydE1pZGRsZXdhcmUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoYXBwKSA9PiB7XG4gIC8vIGNoYW5uZWwgcm91dGVzXG4gIGFwcC5nZXQoJy9hcGkvY2hhbm5lbC9hdmFpbGFiaWxpdHkvOm5hbWUnLCBjaGFubmVsQXZhaWxhYmlsaXR5KTtcbiAgYXBwLmdldCgnL2FwaS9jaGFubmVsL3Nob3J0LWlkLzpsb25nSWQvOm5hbWUnLCBjaGFubmVsU2hvcnRJZCk7XG4gIGFwcC5nZXQoJy9hcGkvY2hhbm5lbC9kYXRhLzpjaGFubmVsTmFtZS86Y2hhbm5lbENsYWltSWQnLCBjaGFubmVsRGF0YSk7XG4gIGFwcC5nZXQoJy9hcGkvY2hhbm5lbC9jbGFpbXMvOmNoYW5uZWxOYW1lLzpjaGFubmVsQ2xhaW1JZC86cGFnZScsIGNoYW5uZWxDbGFpbXMpO1xuICAvLyBjbGFpbSByb3V0ZXNcbiAgYXBwLmdldCgnL2FwaS9jbGFpbS9saXN0LzpuYW1lJywgY2xhaW1MaXN0KTtcbiAgYXBwLmdldCgnL2FwaS9jbGFpbS9nZXQvOm5hbWUvOmNsYWltSWQnLCBjbGFpbUdldCk7XG4gIGFwcC5nZXQoJy9hcGkvY2xhaW0vYXZhaWxhYmlsaXR5LzpuYW1lJywgY2xhaW1BdmFpbGFiaWxpdHkpO1xuICBhcHAuZ2V0KCcvYXBpL2NsYWltL3Jlc29sdmUvOm5hbWUvOmNsYWltSWQnLCBjbGFpbVJlc29sdmUpO1xuICBhcHAucG9zdCgnL2FwaS9jbGFpbS9wdWJsaXNoJywgbXVsdGlwYXJ0TWlkZGxld2FyZSwgY2xhaW1QdWJsaXNoKTtcbiAgYXBwLmdldCgnL2FwaS9jbGFpbS9zaG9ydC1pZC86bG9uZ0lkLzpuYW1lJywgY2xhaW1TaG9ydElkKTtcbiAgYXBwLnBvc3QoJy9hcGkvY2xhaW0vbG9uZy1pZCcsIGNsYWltTG9uZ0lkKTtcbiAgYXBwLmdldCgnL2FwaS9jbGFpbS9kYXRhLzpjbGFpbU5hbWUvOmNsYWltSWQnLCBjbGFpbURhdGEpO1xuICAvLyBmaWxlIHJvdXRlc1xuICBhcHAuZ2V0KCcvYXBpL2ZpbGUvYXZhaWxhYmlsaXR5LzpuYW1lLzpjbGFpbUlkJywgZmlsZUF2YWlsYWJpbGl0eSk7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvaW5kZXguanMiLCJjb25zdCB7IGNoZWNrQ2hhbm5lbEF2YWlsYWJpbGl0eSB9ID0gcmVxdWlyZSgnY29udHJvbGxlcnMvcHVibGlzaENvbnRyb2xsZXIuanMnKTtcbmNvbnN0IHsgc2VuZEdBVGltaW5nRXZlbnQgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZ29vZ2xlQW5hbHl0aWNzLmpzJyk7XG5jb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuXG4vKlxuXG4gIHJvdXRlIHRvIGNoZWNrIHdoZXRoZXIgc2l0ZSBoYXMgcHVibGlzaGVkIHRvIGEgY2hhbm5lbFxuXG4qL1xuXG5jb25zdCBjaGFubmVsQXZhaWxhYmlsaXR5ID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXM6IHsgbmFtZSB9IH0sIHJlcykgPT4ge1xuICBjb25zdCBnYVN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gIGNoZWNrQ2hhbm5lbEF2YWlsYWJpbGl0eShuYW1lKVxuICAgIC50aGVuKGF2YWlsYWJsZU5hbWUgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oYXZhaWxhYmxlTmFtZSk7XG4gICAgICBzZW5kR0FUaW1pbmdFdmVudCgnZW5kLXRvLWVuZCcsICdjbGFpbSBuYW1lIGF2YWlsYWJpbGl0eScsIG5hbWUsIGdhU3RhcnRUaW1lLCBEYXRlLm5vdygpKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNoYW5uZWxBdmFpbGFiaWxpdHk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jaGFubmVsQXZhaWxhYmlsaXR5LmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiZnNcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJmc1wiXG4vLyBtb2R1bGUgaWQgPSA2NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJjb25zdCB7IGdldENoYW5uZWxDbGFpbXMgfSA9IHJlcXVpcmUoJ2NvbnRyb2xsZXJzL3NlcnZlQ29udHJvbGxlci5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcblxuY29uc3QgTk9fQ0hBTk5FTCA9ICdOT19DSEFOTkVMJztcblxuLypcblxuICByb3V0ZSB0byBnZXQgYWxsIGNsYWltcyBmb3IgY2hhbm5lbFxuXG4qL1xuXG5jb25zdCBjaGFubmVsQ2xhaW1zID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBib2R5LCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGNvbnN0IGNoYW5uZWxOYW1lID0gcGFyYW1zLmNoYW5uZWxOYW1lO1xuICBsZXQgY2hhbm5lbENsYWltSWQgPSBwYXJhbXMuY2hhbm5lbENsYWltSWQ7XG4gIGlmIChjaGFubmVsQ2xhaW1JZCA9PT0gJ25vbmUnKSBjaGFubmVsQ2xhaW1JZCA9IG51bGw7XG4gIGNvbnN0IHBhZ2UgPSBwYXJhbXMucGFnZTtcbiAgZ2V0Q2hhbm5lbENsYWltcyhjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIHBhZ2UpXG4gICAgLnRoZW4oZGF0YSA9PiB7XG4gICAgICBpZiAoZGF0YSA9PT0gTk9fQ0hBTk5FTCkge1xuICAgICAgICByZXR1cm4gcmVzLnN0YXR1cyg0MDQpLmpzb24oe3N1Y2Nlc3M6IGZhbHNlLCBtZXNzYWdlOiAnTm8gbWF0Y2hpbmcgY2hhbm5lbCB3YXMgZm91bmQnfSk7XG4gICAgICB9XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZSwgZGF0YX0pO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2hhbm5lbENsYWltcztcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxDbGFpbXMuanMiLCJjb25zdCBDTEFJTVNfUEVSX1BBR0UgPSAxMjtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHJldHVyblBhZ2luYXRlZENoYW5uZWxDbGFpbXMgKGNoYW5uZWxOYW1lLCBsb25nQ2hhbm5lbENsYWltSWQsIGNsYWltcywgcGFnZSkge1xuICAgIGNvbnN0IHRvdGFsUGFnZXMgPSBtb2R1bGUuZXhwb3J0cy5kZXRlcm1pbmVUb3RhbFBhZ2VzKGNsYWltcyk7XG4gICAgY29uc3QgcGFnaW5hdGlvblBhZ2UgPSBtb2R1bGUuZXhwb3J0cy5nZXRQYWdlRnJvbVF1ZXJ5KHBhZ2UpO1xuICAgIGNvbnN0IHZpZXdEYXRhID0ge1xuICAgICAgY2hhbm5lbE5hbWUgICAgICAgOiBjaGFubmVsTmFtZSxcbiAgICAgIGxvbmdDaGFubmVsQ2xhaW1JZDogbG9uZ0NoYW5uZWxDbGFpbUlkLFxuICAgICAgY2xhaW1zICAgICAgICAgICAgOiBtb2R1bGUuZXhwb3J0cy5leHRyYWN0UGFnZUZyb21DbGFpbXMoY2xhaW1zLCBwYWdpbmF0aW9uUGFnZSksXG4gICAgICBwcmV2aW91c1BhZ2UgICAgICA6IG1vZHVsZS5leHBvcnRzLmRldGVybWluZVByZXZpb3VzUGFnZShwYWdpbmF0aW9uUGFnZSksXG4gICAgICBjdXJyZW50UGFnZSAgICAgICA6IHBhZ2luYXRpb25QYWdlLFxuICAgICAgbmV4dFBhZ2UgICAgICAgICAgOiBtb2R1bGUuZXhwb3J0cy5kZXRlcm1pbmVOZXh0UGFnZSh0b3RhbFBhZ2VzLCBwYWdpbmF0aW9uUGFnZSksXG4gICAgICB0b3RhbFBhZ2VzICAgICAgICA6IHRvdGFsUGFnZXMsXG4gICAgICB0b3RhbFJlc3VsdHMgICAgICA6IG1vZHVsZS5leHBvcnRzLmRldGVybWluZVRvdGFsQ2xhaW1zKGNsYWltcyksXG4gICAgfTtcbiAgICByZXR1cm4gdmlld0RhdGE7XG4gIH0sXG4gIGdldFBhZ2VGcm9tUXVlcnkgKHBhZ2UpIHtcbiAgICBpZiAocGFnZSkge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KHBhZ2UpO1xuICAgIH1cbiAgICByZXR1cm4gMTtcbiAgfSxcbiAgZXh0cmFjdFBhZ2VGcm9tQ2xhaW1zIChjbGFpbXMsIHBhZ2VOdW1iZXIpIHtcbiAgICBpZiAoIWNsYWltcykge1xuICAgICAgcmV0dXJuIFtdOyAgLy8gaWYgbm8gY2xhaW1zLCByZXR1cm4gdGhpcyBkZWZhdWx0XG4gICAgfVxuICAgIC8vIGxvZ2dlci5kZWJ1ZygnY2xhaW1zIGlzIGFycmF5PycsIEFycmF5LmlzQXJyYXkoY2xhaW1zKSk7XG4gICAgLy8gbG9nZ2VyLmRlYnVnKGBwYWdlTnVtYmVyICR7cGFnZU51bWJlcn0gaXMgbnVtYmVyP2AsIE51bWJlci5pc0ludGVnZXIocGFnZU51bWJlcikpO1xuICAgIGNvbnN0IGNsYWltU3RhcnRJbmRleCA9IChwYWdlTnVtYmVyIC0gMSkgKiBDTEFJTVNfUEVSX1BBR0U7XG4gICAgY29uc3QgY2xhaW1FbmRJbmRleCA9IGNsYWltU3RhcnRJbmRleCArIENMQUlNU19QRVJfUEFHRTtcbiAgICBjb25zdCBwYWdlT2ZDbGFpbXMgPSBjbGFpbXMuc2xpY2UoY2xhaW1TdGFydEluZGV4LCBjbGFpbUVuZEluZGV4KTtcbiAgICByZXR1cm4gcGFnZU9mQ2xhaW1zO1xuICB9LFxuICBkZXRlcm1pbmVUb3RhbFBhZ2VzIChjbGFpbXMpIHtcbiAgICBpZiAoIWNsYWltcykge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRvdGFsQ2xhaW1zID0gY2xhaW1zLmxlbmd0aDtcbiAgICAgIGlmICh0b3RhbENsYWltcyA8IENMQUlNU19QRVJfUEFHRSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGZ1bGxQYWdlcyA9IE1hdGguZmxvb3IodG90YWxDbGFpbXMgLyBDTEFJTVNfUEVSX1BBR0UpO1xuICAgICAgY29uc3QgcmVtYWluZGVyID0gdG90YWxDbGFpbXMgJSBDTEFJTVNfUEVSX1BBR0U7XG4gICAgICBpZiAocmVtYWluZGVyID09PSAwKSB7XG4gICAgICAgIHJldHVybiBmdWxsUGFnZXM7XG4gICAgICB9XG4gICAgICByZXR1cm4gZnVsbFBhZ2VzICsgMTtcbiAgICB9XG4gIH0sXG4gIGRldGVybWluZVByZXZpb3VzUGFnZSAoY3VycmVudFBhZ2UpIHtcbiAgICBpZiAoY3VycmVudFBhZ2UgPT09IDEpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gY3VycmVudFBhZ2UgLSAxO1xuICB9LFxuICBkZXRlcm1pbmVOZXh0UGFnZSAodG90YWxQYWdlcywgY3VycmVudFBhZ2UpIHtcbiAgICBpZiAoY3VycmVudFBhZ2UgPT09IHRvdGFsUGFnZXMpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gY3VycmVudFBhZ2UgKyAxO1xuICB9LFxuICBkZXRlcm1pbmVUb3RhbENsYWltcyAoY2xhaW1zKSB7XG4gICAgaWYgKCFjbGFpbXMpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICByZXR1cm4gY2xhaW1zLmxlbmd0aDtcbiAgfSxcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9jaGFubmVsUGFnaW5hdGlvbi5qcyIsImNvbnN0IHsgZ2V0Q2hhbm5lbERhdGEgfSA9IHJlcXVpcmUoJ2NvbnRyb2xsZXJzL3NlcnZlQ29udHJvbGxlci5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcblxuY29uc3QgTk9fQ0hBTk5FTCA9ICdOT19DSEFOTkVMJztcblxuLypcblxuICByb3V0ZSB0byBnZXQgZGF0YSBmb3IgYSBjaGFubmVsXG5cbiovXG5cbmNvbnN0IGNoYW5uZWxEYXRhID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBib2R5LCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGNvbnN0IGNoYW5uZWxOYW1lID0gcGFyYW1zLmNoYW5uZWxOYW1lO1xuICBsZXQgY2hhbm5lbENsYWltSWQgPSBwYXJhbXMuY2hhbm5lbENsYWltSWQ7XG4gIGlmIChjaGFubmVsQ2xhaW1JZCA9PT0gJ25vbmUnKSBjaGFubmVsQ2xhaW1JZCA9IG51bGw7XG4gIGdldENoYW5uZWxEYXRhKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCwgMClcbiAgICAudGhlbihkYXRhID0+IHtcbiAgICAgIGlmIChkYXRhID09PSBOT19DSEFOTkVMKSB7XG4gICAgICAgIHJldHVybiByZXMuc3RhdHVzKDQwNCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICdObyBtYXRjaGluZyBjaGFubmVsIHdhcyBmb3VuZCd9KTtcbiAgICAgIH1cbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhfSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjaGFubmVsRGF0YTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXBpL2NoYW5uZWxEYXRhLmpzIiwiY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcbmNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5cbi8qXG5cbnJvdXRlIHRvIGdldCBhIHNob3J0IGNoYW5uZWwgaWQgZnJvbSBsb25nIGNoYW5uZWwgSWRcblxuKi9cblxuY29uc3QgY2hhbm5lbFNob3J0SWRSb3V0ZSA9ICh7IGlwLCBvcmlnaW5hbFVybCwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICBkYi5DZXJ0aWZpY2F0ZS5nZXRTaG9ydENoYW5uZWxJZEZyb21Mb25nQ2hhbm5lbElkKHBhcmFtcy5sb25nSWQsIHBhcmFtcy5uYW1lKVxuICAgIC50aGVuKHNob3J0SWQgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oc2hvcnRJZCk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjaGFubmVsU2hvcnRJZFJvdXRlO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2hhbm5lbFNob3J0SWQuanMiLCJjb25zdCB7IGNsYWltTmFtZUlzQXZhaWxhYmxlIH0gPSByZXF1aXJlKCdjb250cm9sbGVycy9wdWJsaXNoQ29udHJvbGxlci5qcycpO1xuY29uc3QgeyBzZW5kR0FUaW1pbmdFdmVudCB9ID0gcmVxdWlyZSgnaGVscGVycy9nb29nbGVBbmFseXRpY3MuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5cbi8qXG5cbiAgcm91dGUgdG8gY2hlY2sgd2hldGhlciB0aGlzIHNpdGUgcHVibGlzaGVkIHRvIGEgY2xhaW1cblxuKi9cblxuY29uc3QgY2xhaW1BdmFpbGFiaWxpdHkgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtczogeyBuYW1lIH0gfSwgcmVzKSA9PiB7XG4gIGNvbnN0IGdhU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgY2xhaW1OYW1lSXNBdmFpbGFibGUobmFtZSlcbiAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24ocmVzdWx0KTtcbiAgICAgIHNlbmRHQVRpbWluZ0V2ZW50KCdlbmQtdG8tZW5kJywgJ2NsYWltIG5hbWUgYXZhaWxhYmlsaXR5JywgbmFtZSwgZ2FTdGFydFRpbWUsIERhdGUubm93KCkpO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1BdmFpbGFiaWxpdHk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUF2YWlsYWJpbGl0eS5qcyIsImNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5jb25zdCBkYiA9IHJlcXVpcmUoJ21vZGVscycpO1xuXG4vKlxuXG4gIHJvdXRlIHRvIHJldHVybiBkYXRhIGZvciBhIGNsYWltXG5cbiovXG5cbmNvbnN0IGNsYWltRGF0YSA9ICh7IGlwLCBvcmlnaW5hbFVybCwgYm9keSwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICBjb25zdCBjbGFpbU5hbWUgPSBwYXJhbXMuY2xhaW1OYW1lO1xuICBsZXQgY2xhaW1JZCA9IHBhcmFtcy5jbGFpbUlkO1xuICBpZiAoY2xhaW1JZCA9PT0gJ25vbmUnKSBjbGFpbUlkID0gbnVsbDtcbiAgZGIuQ2xhaW0ucmVzb2x2ZUNsYWltKGNsYWltTmFtZSwgY2xhaW1JZClcbiAgICAudGhlbihjbGFpbUluZm8gPT4ge1xuICAgICAgaWYgKCFjbGFpbUluZm8pIHtcbiAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDA0KS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogJ05vIGNsYWltIGNvdWxkIGJlIGZvdW5kJ30pO1xuICAgICAgfVxuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWUsIGRhdGE6IGNsYWltSW5mb30pO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1EYXRhO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hcGkvY2xhaW1EYXRhLmpzIiwiY29uc3QgeyBnZXRDbGFpbSB9ID0gcmVxdWlyZSgnaGVscGVycy9sYnJ5QXBpLmpzJyk7XG5jb25zdCB7IGFkZEdldFJlc3VsdHNUb0ZpbGVEYXRhLCBjcmVhdGVGaWxlRGF0YSB9ID0gcmVxdWlyZSgnLi4vLi4vaGVscGVycy9wdWJsaXNoSGVscGVycy5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcbmNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5cbi8qXG5cbiAgcm91dGUgdG8gZ2V0IGEgY2xhaW1cblxuKi9cblxuY29uc3QgY2xhaW1HZXQgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtcyB9LCByZXMpID0+IHtcbiAgY29uc3QgbmFtZSA9IHBhcmFtcy5uYW1lO1xuICBjb25zdCBjbGFpbUlkID0gcGFyYW1zLmNsYWltSWQ7XG4gIC8vIHJlc29sdmUgdGhlIGNsYWltXG4gIGRiLkNsYWltLnJlc29sdmVDbGFpbShuYW1lLCBjbGFpbUlkKVxuICAgIC50aGVuKHJlc29sdmVSZXN1bHQgPT4ge1xuICAgICAgLy8gbWFrZSBzdXJlIGEgY2xhaW0gYWN0dWFsbHkgZXhpc3RzIGF0IHRoYXQgdXJpXG4gICAgICBpZiAoIXJlc29sdmVSZXN1bHQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBtYXRjaGluZyB1cmkgZm91bmQgaW4gQ2xhaW0gdGFibGUnKTtcbiAgICAgIH1cbiAgICAgIGxldCBmaWxlRGF0YSA9IGNyZWF0ZUZpbGVEYXRhKHJlc29sdmVSZXN1bHQpO1xuICAgICAgLy8gZ2V0IHRoZSBjbGFpbVxuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtmaWxlRGF0YSwgZ2V0Q2xhaW0oYCR7bmFtZX0jJHtjbGFpbUlkfWApXSk7XG4gICAgfSlcbiAgICAudGhlbigoWyBmaWxlRGF0YSwgZ2V0UmVzdWx0IF0pID0+IHtcbiAgICAgIGZpbGVEYXRhID0gYWRkR2V0UmVzdWx0c1RvRmlsZURhdGEoZmlsZURhdGEsIGdldFJlc3VsdCk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW2RiLnVwc2VydChkYi5GaWxlLCBmaWxlRGF0YSwge25hbWUsIGNsYWltSWR9LCAnRmlsZScpLCBnZXRSZXN1bHRdKTtcbiAgICB9KVxuICAgIC50aGVuKChbIGZpbGVSZWNvcmQsIHttZXNzYWdlLCBjb21wbGV0ZWR9IF0pID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHsgc3VjY2VzczogdHJ1ZSwgbWVzc2FnZSwgY29tcGxldGVkIH0pO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1HZXQ7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUdldC5qcyIsImNvbnN0IHsgZ2V0Q2xhaW1JZCB9ID0gcmVxdWlyZSgnY29udHJvbGxlcnMvc2VydmVDb250cm9sbGVyLmpzJyk7XG5jb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuXG5jb25zdCBOT19DSEFOTkVMID0gJ05PX0NIQU5ORUwnO1xuY29uc3QgTk9fQ0xBSU0gPSAnTk9fQ0xBSU0nO1xuXG4vKlxuXG4gIHJvdXRlIHRvIGdldCBhIGxvbmcgY2xhaW0gaWRcblxuKi9cblxuY29uc3QgY2xhaW1Mb25nSWQgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIGJvZHksIHBhcmFtcyB9LCByZXMpID0+IHtcbiAgY29uc3QgY2hhbm5lbE5hbWUgPSBib2R5LmNoYW5uZWxOYW1lO1xuICBjb25zdCBjaGFubmVsQ2xhaW1JZCA9IGJvZHkuY2hhbm5lbENsYWltSWQ7XG4gIGNvbnN0IGNsYWltTmFtZSA9IGJvZHkuY2xhaW1OYW1lO1xuICBjb25zdCBjbGFpbUlkID0gYm9keS5jbGFpbUlkO1xuICBnZXRDbGFpbUlkKGNoYW5uZWxOYW1lLCBjaGFubmVsQ2xhaW1JZCwgY2xhaW1OYW1lLCBjbGFpbUlkKVxuICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICBpZiAocmVzdWx0ID09PSBOT19DSEFOTkVMKSB7XG4gICAgICAgIHJldHVybiByZXMuc3RhdHVzKDQwNCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6ICdObyBtYXRjaGluZyBjaGFubmVsIGNvdWxkIGJlIGZvdW5kJ30pO1xuICAgICAgfVxuICAgICAgaWYgKHJlc3VsdCA9PT0gTk9fQ0xBSU0pIHtcbiAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoNDA0KS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogJ05vIG1hdGNoaW5nIGNsYWltIGlkIGNvdWxkIGJlIGZvdW5kJ30pO1xuICAgICAgfVxuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe3N1Y2Nlc3M6IHRydWUsIGRhdGE6IHJlc3VsdH0pO1xuICAgIH0pXG4gICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgIGhhbmRsZUVycm9yUmVzcG9uc2Uob3JpZ2luYWxVcmwsIGlwLCBlcnJvciwgcmVzKTtcbiAgICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhaW1Mb25nSWQ7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUxvbmdJZC5qcyIsImNvbnN0IHsgY3JlYXRlQmFzaWNQdWJsaXNoUGFyYW1zLCBjcmVhdGVUaHVtYm5haWxQdWJsaXNoUGFyYW1zLCBwYXJzZVB1Ymxpc2hBcGlSZXF1ZXN0Qm9keSwgcGFyc2VQdWJsaXNoQXBpUmVxdWVzdEZpbGVzIH0gPSByZXF1aXJlKCdoZWxwZXJzL3B1Ymxpc2hIZWxwZXJzLmpzJyk7XG5jb25zdCB7IGNsYWltTmFtZUlzQXZhaWxhYmxlLCBwdWJsaXNoIH0gPSByZXF1aXJlKCdjb250cm9sbGVycy9wdWJsaXNoQ29udHJvbGxlci5qcycpO1xuY29uc3QgeyBhdXRoZW50aWNhdGVVc2VyIH0gPSByZXF1aXJlKCdhdXRoL2F1dGhlbnRpY2F0aW9uLmpzJyk7XG5jb25zdCB7IHNlbmRHQVRpbWluZ0V2ZW50IH0gPSByZXF1aXJlKCdoZWxwZXJzL2dvb2dsZUFuYWx5dGljcy5qcycpO1xuY29uc3QgeyBoYW5kbGVFcnJvclJlc3BvbnNlIH0gPSByZXF1aXJlKCdoZWxwZXJzL2Vycm9ySGFuZGxlcnMuanMnKTtcbmNvbnN0IHsgZGV0YWlsczogeyBob3N0IH0gfSA9IHJlcXVpcmUoJ3NpdGVDb25maWcuanMnKTtcblxuLypcblxuICByb3V0ZSB0byBwdWJsaXNoIGEgY2xhaW0gdGhyb3VnaCB0aGUgZGFlbW9uXG5cbiovXG5cbmNvbnN0IGNsYWltUHVibGlzaCA9ICh7IGJvZHksIGZpbGVzLCBoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwsIHVzZXIgfSwgcmVzKSA9PiB7XG4gIC8vIGRlZmluZSB2YXJpYWJsZXNcbiAgbGV0ICBjaGFubmVsTmFtZSwgY2hhbm5lbElkLCBjaGFubmVsUGFzc3dvcmQsIGRlc2NyaXB0aW9uLCBmaWxlTmFtZSwgZmlsZVBhdGgsIGZpbGVUeXBlLCBnYVN0YXJ0VGltZSwgbGljZW5zZSwgbmFtZSwgbnNmdywgdGh1bWJuYWlsLCB0aHVtYm5haWxGaWxlTmFtZSwgdGh1bWJuYWlsRmlsZVBhdGgsIHRodW1ibmFpbEZpbGVUeXBlLCB0aXRsZTtcbiAgLy8gcmVjb3JkIHRoZSBzdGFydCB0aW1lIG9mIHRoZSByZXF1ZXN0XG4gIGdhU3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgLy8gdmFsaWRhdGUgdGhlIGJvZHkgYW5kIGZpbGVzIG9mIHRoZSByZXF1ZXN0XG4gIHRyeSB7XG4gICAgLy8gdmFsaWRhdGVBcGlQdWJsaXNoUmVxdWVzdChib2R5LCBmaWxlcyk7XG4gICAgKHtuYW1lLCBuc2Z3LCBsaWNlbnNlLCB0aXRsZSwgZGVzY3JpcHRpb24sIHRodW1ibmFpbH0gPSBwYXJzZVB1Ymxpc2hBcGlSZXF1ZXN0Qm9keShib2R5KSk7XG4gICAgKHtmaWxlTmFtZSwgZmlsZVBhdGgsIGZpbGVUeXBlLCB0aHVtYm5haWxGaWxlTmFtZSwgdGh1bWJuYWlsRmlsZVBhdGgsIHRodW1ibmFpbEZpbGVUeXBlfSA9IHBhcnNlUHVibGlzaEFwaVJlcXVlc3RGaWxlcyhmaWxlcykpO1xuICAgICh7Y2hhbm5lbE5hbWUsIGNoYW5uZWxJZCwgY2hhbm5lbFBhc3N3b3JkfSA9IGJvZHkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KTtcbiAgfVxuICAvLyBjaGVjayBjaGFubmVsIGF1dGhvcml6YXRpb25cbiAgUHJvbWlzZVxuICAgIC5hbGwoW1xuICAgICAgYXV0aGVudGljYXRlVXNlcihjaGFubmVsTmFtZSwgY2hhbm5lbElkLCBjaGFubmVsUGFzc3dvcmQsIHVzZXIpLFxuICAgICAgY2xhaW1OYW1lSXNBdmFpbGFibGUobmFtZSksXG4gICAgICBjcmVhdGVCYXNpY1B1Ymxpc2hQYXJhbXMoZmlsZVBhdGgsIG5hbWUsIHRpdGxlLCBkZXNjcmlwdGlvbiwgbGljZW5zZSwgbnNmdywgdGh1bWJuYWlsKSxcbiAgICAgIGNyZWF0ZVRodW1ibmFpbFB1Ymxpc2hQYXJhbXModGh1bWJuYWlsRmlsZVBhdGgsIG5hbWUsIGxpY2Vuc2UsIG5zZncpLFxuICAgIF0pXG4gICAgLnRoZW4oKFt7Y2hhbm5lbE5hbWUsIGNoYW5uZWxDbGFpbUlkfSwgdmFsaWRhdGVkQ2xhaW1OYW1lLCBwdWJsaXNoUGFyYW1zLCB0aHVtYm5haWxQdWJsaXNoUGFyYW1zXSkgPT4ge1xuICAgICAgLy8gYWRkIGNoYW5uZWwgZGV0YWlscyB0byB0aGUgcHVibGlzaCBwYXJhbXNcbiAgICAgIGlmIChjaGFubmVsTmFtZSAmJiBjaGFubmVsQ2xhaW1JZCkge1xuICAgICAgICBwdWJsaXNoUGFyYW1zWydjaGFubmVsX25hbWUnXSA9IGNoYW5uZWxOYW1lO1xuICAgICAgICBwdWJsaXNoUGFyYW1zWydjaGFubmVsX2lkJ10gPSBjaGFubmVsQ2xhaW1JZDtcbiAgICAgIH1cbiAgICAgIC8vIHB1Ymxpc2ggdGhlIHRodW1ibmFpbFxuICAgICAgaWYgKHRodW1ibmFpbFB1Ymxpc2hQYXJhbXMpIHtcbiAgICAgICAgcHVibGlzaCh0aHVtYm5haWxQdWJsaXNoUGFyYW1zLCB0aHVtYm5haWxGaWxlTmFtZSwgdGh1bWJuYWlsRmlsZVR5cGUpO1xuICAgICAgfVxuICAgICAgLy8gcHVibGlzaCB0aGUgYXNzZXRcbiAgICAgIHJldHVybiBwdWJsaXNoKHB1Ymxpc2hQYXJhbXMsIGZpbGVOYW1lLCBmaWxlVHlwZSk7XG4gICAgfSlcbiAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oe1xuICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICBtZXNzYWdlOiAncHVibGlzaCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5JyxcbiAgICAgICAgZGF0YSAgIDoge1xuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgY2xhaW1JZDogcmVzdWx0LmNsYWltX2lkLFxuICAgICAgICAgIHVybCAgICA6IGAke2hvc3R9LyR7cmVzdWx0LmNsYWltX2lkfS8ke25hbWV9YCxcbiAgICAgICAgICBsYnJ5VHggOiByZXN1bHQsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIC8vIHJlY29yZCB0aGUgcHVibGlzaCBlbmQgdGltZSBhbmQgc2VuZCB0byBnb29nbGUgYW5hbHl0aWNzXG4gICAgICBzZW5kR0FUaW1pbmdFdmVudCgnZW5kLXRvLWVuZCcsICdwdWJsaXNoJywgZmlsZVR5cGUsIGdhU3RhcnRUaW1lLCBEYXRlLm5vdygpKTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYWltUHVibGlzaDtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9yb3V0ZXMvYXBpL2NsYWltUHVibGlzaC5qcyIsImNvbnN0IGRiID0gcmVxdWlyZSgnbW9kZWxzJyk7XG5jb25zdCBsb2dnZXIgPSByZXF1aXJlKCd3aW5zdG9uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBhdXRoZW50aWNhdGVVc2VyIChjaGFubmVsTmFtZSwgY2hhbm5lbElkLCBjaGFubmVsUGFzc3dvcmQsIHVzZXIpIHtcbiAgICAvLyBjYXNlOiBubyBjaGFubmVsTmFtZSBvciBjaGFubmVsIElkIGFyZSBwcm92aWRlZCAoYW5vbnltb3VzKSwgcmVnYXJkbGVzcyBvZiB3aGV0aGVyIHVzZXIgdG9rZW4gaXMgcHJvdmlkZWRcbiAgICBpZiAoIWNoYW5uZWxOYW1lICYmICFjaGFubmVsSWQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNoYW5uZWxOYW1lICAgOiBudWxsLFxuICAgICAgICBjaGFubmVsQ2xhaW1JZDogbnVsbCxcbiAgICAgIH07XG4gICAgfVxuICAgIC8vIGNhc2U6IGNoYW5uZWxOYW1lIG9yIGNoYW5uZWwgSWQgYXJlIHByb3ZpZGVkIHdpdGggdXNlciB0b2tlblxuICAgIGlmICh1c2VyKSB7XG4gICAgICBpZiAoY2hhbm5lbE5hbWUgJiYgY2hhbm5lbE5hbWUgIT09IHVzZXIuY2hhbm5lbE5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0aGUgcHJvdmlkZWQgY2hhbm5lbCBuYW1lIGRvZXMgbm90IG1hdGNoIHVzZXIgY3JlZGVudGlhbHMnKTtcbiAgICAgIH1cbiAgICAgIGlmIChjaGFubmVsSWQgJiYgY2hhbm5lbElkICE9PSB1c2VyLmNoYW5uZWxDbGFpbUlkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIHByb3ZpZGVkIGNoYW5uZWwgaWQgZG9lcyBub3QgbWF0Y2ggdXNlciBjcmVkZW50aWFscycpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgY2hhbm5lbE5hbWUgICA6IHVzZXIuY2hhbm5lbE5hbWUsXG4gICAgICAgIGNoYW5uZWxDbGFpbUlkOiB1c2VyLmNoYW5uZWxDbGFpbUlkLFxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gY2FzZTogY2hhbm5lbE5hbWUgb3IgY2hhbm5lbCBJZCBhcmUgcHJvdmlkZWQgd2l0aCBwYXNzd29yZCBpbnN0ZWFkIG9mIHVzZXIgdG9rZW5cbiAgICBpZiAoIWNoYW5uZWxQYXNzd29yZCkgdGhyb3cgbmV3IEVycm9yKCdubyBjaGFubmVsIHBhc3N3b3JkIHByb3ZpZGVkJyk7XG4gICAgcmV0dXJuIG1vZHVsZS5leHBvcnRzLmF1dGhlbnRpY2F0ZUNoYW5uZWxDcmVkZW50aWFscyhjaGFubmVsTmFtZSwgY2hhbm5lbElkLCBjaGFubmVsUGFzc3dvcmQpO1xuICB9LFxuICBhdXRoZW50aWNhdGVDaGFubmVsQ3JlZGVudGlhbHMgKGNoYW5uZWxOYW1lLCBjaGFubmVsSWQsIHVzZXJQYXNzd29yZCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAvLyBob2lzdGVkIHZhcmlhYmxlc1xuICAgICAgbGV0IGNoYW5uZWxEYXRhO1xuICAgICAgLy8gYnVpbGQgdGhlIHBhcmFtcyBmb3IgZmluZGluZyB0aGUgY2hhbm5lbFxuICAgICAgbGV0IGNoYW5uZWxGaW5kUGFyYW1zID0ge307XG4gICAgICBpZiAoY2hhbm5lbE5hbWUpIGNoYW5uZWxGaW5kUGFyYW1zWydjaGFubmVsTmFtZSddID0gY2hhbm5lbE5hbWU7XG4gICAgICBpZiAoY2hhbm5lbElkKSBjaGFubmVsRmluZFBhcmFtc1snY2hhbm5lbENsYWltSWQnXSA9IGNoYW5uZWxJZDtcbiAgICAgIC8vIGZpbmQgdGhlIGNoYW5uZWxcbiAgICAgIGRiLkNoYW5uZWxcbiAgICAgICAgLmZpbmRPbmUoe1xuICAgICAgICAgIHdoZXJlOiBjaGFubmVsRmluZFBhcmFtcyxcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4oY2hhbm5lbCA9PiB7XG4gICAgICAgICAgaWYgKCFjaGFubmVsKSB7XG4gICAgICAgICAgICBsb2dnZXIuZGVidWcoJ25vIGNoYW5uZWwgZm91bmQnKTtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQXV0aGVudGljYXRpb24gZmFpbGVkLCB5b3UgZG8gbm90IGhhdmUgYWNjZXNzIHRvIHRoYXQgY2hhbm5lbCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjaGFubmVsRGF0YSA9IGNoYW5uZWwuZ2V0KCk7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKCdjaGFubmVsIGRhdGE6JywgY2hhbm5lbERhdGEpO1xuICAgICAgICAgIHJldHVybiBkYi5Vc2VyLmZpbmRPbmUoe1xuICAgICAgICAgICAgd2hlcmU6IHsgdXNlck5hbWU6IGNoYW5uZWxEYXRhLmNoYW5uZWxOYW1lLnN1YnN0cmluZygxKSB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbih1c2VyID0+IHtcbiAgICAgICAgICBpZiAoIXVzZXIpIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1Zygnbm8gdXNlciBmb3VuZCcpO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRoZW50aWNhdGlvbiBmYWlsZWQsIHlvdSBkbyBub3QgaGF2ZSBhY2Nlc3MgdG8gdGhhdCBjaGFubmVsJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB1c2VyLmNvbXBhcmVQYXNzd29yZCh1c2VyUGFzc3dvcmQpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbihpc01hdGNoID0+IHtcbiAgICAgICAgICBpZiAoIWlzTWF0Y2gpIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnaW5jb3JyZWN0IHBhc3N3b3JkJyk7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0F1dGhlbnRpY2F0aW9uIGZhaWxlZCwgeW91IGRvIG5vdCBoYXZlIGFjY2VzcyB0byB0aGF0IGNoYW5uZWwnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKCcuLi5wYXNzd29yZCB3YXMgYSBtYXRjaC4uLicpO1xuICAgICAgICAgIHJlc29sdmUoY2hhbm5lbERhdGEpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9LFxufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NlcnZlci9hdXRoL2F1dGhlbnRpY2F0aW9uLmpzIiwiY29uc3QgeyByZXNvbHZlVXJpIH0gPSByZXF1aXJlKCdoZWxwZXJzL2xicnlBcGkuanMnKTtcbmNvbnN0IHsgaGFuZGxlRXJyb3JSZXNwb25zZSB9ID0gcmVxdWlyZSgnaGVscGVycy9lcnJvckhhbmRsZXJzLmpzJyk7XG5cbi8qXG5cbiAgcm91dGUgdG8gcnVuIGEgcmVzb2x2ZSByZXF1ZXN0IG9uIHRoZSBkYWVtb25cblxuKi9cblxuY29uc3QgY2xhaW1SZXNvbHZlID0gKHsgaGVhZGVycywgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIHJlc29sdmVVcmkoYCR7cGFyYW1zLm5hbWV9IyR7cGFyYW1zLmNsYWltSWR9YClcbiAgICAudGhlbihyZXNvbHZlZFVyaSA9PiB7XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbihyZXNvbHZlZFVyaSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFpbVJlc29sdmU7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbVJlc29sdmUuanMiLCJjb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuY29uc3QgZGIgPSByZXF1aXJlKCdtb2RlbHMnKTtcblxuLypcblxuICByb3V0ZSB0byBnZXQgYSBzaG9ydCBjbGFpbSBpZCBmcm9tIGxvbmcgY2xhaW0gSWRcblxuKi9cblxuY29uc3QgY2xhaW1TaG9ydElkID0gKHsgaXAsIG9yaWdpbmFsVXJsLCBib2R5LCBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGRiLkNsYWltLmdldFNob3J0Q2xhaW1JZEZyb21Mb25nQ2xhaW1JZChwYXJhbXMubG9uZ0lkLCBwYXJhbXMubmFtZSlcbiAgICAudGhlbihzaG9ydElkID0+IHtcbiAgICAgIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiBzaG9ydElkfSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFpbVNob3J0SWQ7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbVNob3J0SWQuanMiLCJjb25zdCB7IGdldENsYWltTGlzdCB9ID0gcmVxdWlyZSgnaGVscGVycy9sYnJ5QXBpLmpzJyk7XG5jb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuXG4vKlxuXG4gIHJvdXRlIHRvIGdldCBsaXN0IG9mIGNsYWltc1xuXG4qL1xuXG5jb25zdCBjbGFpbUxpc3QgPSAoeyBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtcyB9LCByZXMpID0+IHtcbiAgZ2V0Q2xhaW1MaXN0KHBhcmFtcy5uYW1lKVxuICAgIC50aGVuKGNsYWltc0xpc3QgPT4ge1xuICAgICAgcmVzLnN0YXR1cygyMDApLmpzb24oY2xhaW1zTGlzdCk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgaGFuZGxlRXJyb3JSZXNwb25zZShvcmlnaW5hbFVybCwgaXAsIGVycm9yLCByZXMpO1xuICAgIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFpbUxpc3Q7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9jbGFpbUxpc3QuanMiLCJjb25zdCB7IGhhbmRsZUVycm9yUmVzcG9uc2UgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvZXJyb3JIYW5kbGVycy5qcycpO1xuY29uc3QgZGIgPSByZXF1aXJlKCdtb2RlbHMnKTtcblxuLypcblxuICByb3V0ZSB0byBzZWUgaWYgYXNzZXQgaXMgYXZhaWxhYmxlIGxvY2FsbHlcblxuKi9cblxuY29uc3QgZmlsZUF2YWlsYWJpbGl0eSA9ICh7IGlwLCBvcmlnaW5hbFVybCwgcGFyYW1zIH0sIHJlcykgPT4ge1xuICBjb25zdCBuYW1lID0gcGFyYW1zLm5hbWU7XG4gIGNvbnN0IGNsYWltSWQgPSBwYXJhbXMuY2xhaW1JZDtcbiAgZGIuRmlsZVxuICAgIC5maW5kT25lKHtcbiAgICAgIHdoZXJlOiB7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIGNsYWltSWQsXG4gICAgICB9LFxuICAgIH0pXG4gICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIHJlcy5zdGF0dXMoMjAwKS5qc29uKHtzdWNjZXNzOiB0cnVlLCBkYXRhOiB0cnVlfSk7XG4gICAgICB9XG4gICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7c3VjY2VzczogdHJ1ZSwgZGF0YTogZmFsc2V9KTtcbiAgICB9KVxuICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICBoYW5kbGVFcnJvclJlc3BvbnNlKG9yaWdpbmFsVXJsLCBpcCwgZXJyb3IsIHJlcyk7XG4gICAgfSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZpbGVBdmFpbGFiaWxpdHk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2FwaS9maWxlQXZhaWxhYmlsaXR5LmpzIiwiY29uc3QgbXVsdGlwYXJ0ID0gcmVxdWlyZSgnY29ubmVjdC1tdWx0aXBhcnR5Jyk7XHJcbmNvbnN0IHsgcHVibGlzaGluZzogeyB1cGxvYWREaXJlY3RvcnkgfSB9ID0gcmVxdWlyZSgnc2l0ZUNvbmZpZy5qcycpO1xyXG5jb25zdCBtdWx0aXBhcnRNaWRkbGV3YXJlID0gbXVsdGlwYXJ0KHt1cGxvYWREaXI6IHVwbG9hZERpcmVjdG9yeX0pO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBtdWx0aXBhcnRNaWRkbGV3YXJlO1xyXG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvaGVscGVycy9tdWx0aXBhcnRNaWRkbGV3YXJlLmpzIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwiY29ubmVjdC1tdWx0aXBhcnR5XCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwiY29ubmVjdC1tdWx0aXBhcnR5XCJcbi8vIG1vZHVsZSBpZCA9IDgwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsImNvbnN0IGhhbmRsZVBhZ2VSZXF1ZXN0ID0gcmVxdWlyZSgnLi9zZW5kUmVhY3RBcHAnKTtcbmNvbnN0IGhhbmRsZUVtYmVkUmVxdWVzdCA9IHJlcXVpcmUoJy4vc2VuZEVtYmVkUGFnZScpO1xuY29uc3QgcmVkaXJlY3QgPSByZXF1aXJlKCcuL3JlZGlyZWN0Jyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKGFwcCkgPT4ge1xuICBhcHAuZ2V0KCcvJywgaGFuZGxlUGFnZVJlcXVlc3QpO1xuICBhcHAuZ2V0KCcvbG9naW4nLCBoYW5kbGVQYWdlUmVxdWVzdCk7XG4gIGFwcC5nZXQoJy9hYm91dCcsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL3RyZW5kaW5nJywgcmVkaXJlY3QoJy9wb3B1bGFyJykpO1xuICBhcHAuZ2V0KCcvcG9wdWxhcicsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL25ldycsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcbiAgYXBwLmdldCgnL2VtYmVkLzpjbGFpbUlkLzpuYW1lJywgaGFuZGxlRW1iZWRSZXF1ZXN0KTsgIC8vIHJvdXRlIHRvIHNlbmQgZW1iZWRhYmxlIHZpZGVvIHBsYXllciAoZm9yIHR3aXR0ZXIpXG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9pbmRleC5qcyIsImNvbnN0IGhhbmRsZVBhZ2VSZW5kZXIgPSByZXF1aXJlKCdoZWxwZXJzL2hhbmRsZVBhZ2VSZW5kZXIuanN4Jyk7XG5cbmNvbnN0IHNlbmRSZWFjdEFwcCA9IChyZXEsIHJlcykgPT4ge1xuICBoYW5kbGVQYWdlUmVuZGVyKHJlcSwgcmVzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2VuZFJlYWN0QXBwO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kUmVhY3RBcHAuanMiLCJjb25zdCB7IGRldGFpbHM6IHsgaG9zdCB9IH0gPSByZXF1aXJlKCdzaXRlQ29uZmlnLmpzJyk7XG5cbmNvbnN0IHNlbmRFbWJlZFBhZ2UgPSAoeyBwYXJhbXMgfSwgcmVzKSA9PiB7XG4gIGNvbnN0IGNsYWltSWQgPSBwYXJhbXMuY2xhaW1JZDtcbiAgY29uc3QgbmFtZSA9IHBhcmFtcy5uYW1lO1xuICAvLyBnZXQgYW5kIHJlbmRlciB0aGUgY29udGVudFxuICByZXMuc3RhdHVzKDIwMCkucmVuZGVyKCdlbWJlZCcsIHsgbGF5b3V0OiAnZW1iZWQnLCBob3N0LCBjbGFpbUlkLCBuYW1lIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzZW5kRW1iZWRQYWdlO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9zZW5kRW1iZWRQYWdlLmpzIiwiY29uc3QgcmVkaXJlY3QgPSAocm91dGUpID0+IHtcbiAgcmV0dXJuIChyZXEsIHJlcykgPT4ge1xuICAgIHJlcy5zdGF0dXMoMzAxKS5yZWRpcmVjdChyb3V0ZSk7XG4gIH07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlZGlyZWN0O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9wYWdlcy9yZWRpcmVjdC5qcyIsImNvbnN0IHNlcnZlQXNzZXRCeUNsYWltID0gcmVxdWlyZSgnLi9zZXJ2ZUFzc2V0QnlDbGFpbScpO1xuY29uc3Qgc2VydmVBc3NldEJ5SWRlbnRpZmllckFuZENsYWltID0gcmVxdWlyZSgnLi9zZXJ2ZUFzc2V0QnlJZGVudGlmaWVyQW5kQ2xhaW0nKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoYXBwLCBkYikgPT4ge1xuICBhcHAuZ2V0KCcvOmlkZW50aWZpZXIvOmNsYWltJywgc2VydmVBc3NldEJ5SWRlbnRpZmllckFuZENsYWltKTtcbiAgYXBwLmdldCgnLzpjbGFpbScsIHNlcnZlQXNzZXRCeUNsYWltKTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zZXJ2ZXIvcm91dGVzL2Fzc2V0cy9pbmRleC5qcyIsImNvbnN0IHsgc2VuZEdBU2VydmVFdmVudCB9ID0gcmVxdWlyZSgnaGVscGVycy9nb29nbGVBbmFseXRpY3MnKTtcbmNvbnN0IHsgZGV0ZXJtaW5lUmVzcG9uc2VUeXBlLCBsb2dSZXF1ZXN0RGF0YSwgZ2V0Q2xhaW1JZEFuZFNlcnZlQXNzZXQgfSA9IHJlcXVpcmUoJ2hlbHBlcnMvc2VydmVIZWxwZXJzLmpzJyk7XG5jb25zdCBsYnJ5VXJpID0gcmVxdWlyZSgnaGVscGVycy9sYnJ5VXJpLmpzJyk7XG5jb25zdCBoYW5kbGVTaG93UmVuZGVyID0gcmVxdWlyZSgnaGVscGVycy9oYW5kbGVTaG93UmVuZGVyLmpzeCcpO1xuY29uc3QgU0VSVkUgPSAnU0VSVkUnO1xuXG4vKlxuXG4gIHJvdXRlIHRvIHNlcnZlIGFuIGFzc2V0IG9yIHRoZSByZWFjdCBhcHAgdmlhIHRoZSBjbGFpbSBuYW1lIG9ubHlcblxuKi9cblxuY29uc3Qgc2VydmVyQXNzZXRCeUNsYWltID0gKHJlcSwgcmVzKSA9PiB7XG4gIGNvbnN0IHsgaGVhZGVycywgaXAsIG9yaWdpbmFsVXJsLCBwYXJhbXMgfSA9IHJlcTtcbiAgLy8gZGVjaWRlIGlmIHRoaXMgaXMgYSBzaG93IHJlcXVlc3RcbiAgbGV0IGhhc0ZpbGVFeHRlbnNpb247XG4gIHRyeSB7XG4gICAgKHsgaGFzRmlsZUV4dGVuc2lvbiB9ID0gbGJyeVVyaS5wYXJzZU1vZGlmaWVyKHBhcmFtcy5jbGFpbSkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KTtcbiAgfVxuICBsZXQgcmVzcG9uc2VUeXBlID0gZGV0ZXJtaW5lUmVzcG9uc2VUeXBlKGhhc0ZpbGVFeHRlbnNpb24sIGhlYWRlcnMpO1xuICBpZiAocmVzcG9uc2VUeXBlICE9PSBTRVJWRSkge1xuICAgIHJldHVybiBoYW5kbGVTaG93UmVuZGVyKHJlcSwgcmVzKTtcbiAgfVxuICAvLyBoYW5kbGUgc2VydmUgcmVxdWVzdFxuICAvLyBzZW5kIGdvb2dsZSBhbmFseXRpY3NcbiAgc2VuZEdBU2VydmVFdmVudChoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwpO1xuICAvLyBwYXJzZSB0aGUgY2xhaW1cbiAgbGV0IGNsYWltTmFtZTtcbiAgdHJ5IHtcbiAgICAoe2NsYWltTmFtZX0gPSBsYnJ5VXJpLnBhcnNlQ2xhaW0ocGFyYW1zLmNsYWltKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pO1xuICB9XG4gIC8vIGxvZyB0aGUgcmVxdWVzdCBkYXRhIGZvciBkZWJ1Z2dpbmdcbiAgbG9nUmVxdWVzdERhdGEocmVzcG9uc2VUeXBlLCBjbGFpbU5hbWUsIG51bGwsIG51bGwpO1xuICAvLyBnZXQgdGhlIGNsYWltIElkIGFuZCB0aGVuIHNlcnZlIHRoZSBhc3NldFxuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldChudWxsLCBudWxsLCBjbGFpbU5hbWUsIG51bGwsIG9yaWdpbmFsVXJsLCBpcCwgcmVzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2VydmVyQXNzZXRCeUNsYWltO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hc3NldHMvc2VydmVBc3NldEJ5Q2xhaW0uanMiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWR1eC1zYWdhXCIpO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIGV4dGVybmFsIFwicmVkdXgtc2FnYVwiXG4vLyBtb2R1bGUgaWQgPSA4N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWR1eC1zYWdhL2VmZmVjdHNcIik7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gZXh0ZXJuYWwgXCJyZWR1eC1zYWdhL2VmZmVjdHNcIlxuLy8gbW9kdWxlIGlkID0gODhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiY29uc3QgeyBzZW5kR0FTZXJ2ZUV2ZW50IH0gPSByZXF1aXJlKCdoZWxwZXJzL2dvb2dsZUFuYWx5dGljcycpO1xuY29uc3Qge1xuICBkZXRlcm1pbmVSZXNwb25zZVR5cGUsXG4gIGZsaXBDbGFpbU5hbWVBbmRJZEZvckJhY2t3YXJkc0NvbXBhdGliaWxpdHksXG4gIGxvZ1JlcXVlc3REYXRhLFxuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldCxcbn0gPSByZXF1aXJlKCdoZWxwZXJzL3NlcnZlSGVscGVycy5qcycpO1xuY29uc3QgbGJyeVVyaSA9IHJlcXVpcmUoJ2hlbHBlcnMvbGJyeVVyaS5qcycpO1xuY29uc3QgaGFuZGxlU2hvd1JlbmRlciA9IHJlcXVpcmUoJ2hlbHBlcnMvaGFuZGxlU2hvd1JlbmRlci5qc3gnKTtcblxuY29uc3QgU0VSVkUgPSAnU0VSVkUnO1xuXG4vKlxuXG4gIHJvdXRlIHRvIHNlcnZlIGFuIGFzc2V0IG9yIHRoZSByZWFjdCBhcHAgdmlhIHRoZSBjbGFpbSBuYW1lIGFuZCBhbiBpZGVudGlmaWVyXG5cbiovXG5cbmNvbnN0IHNlcnZlckFzc2V0QnlJZGVudGlmaWVyQW5kQ2xhaW0gPSAocmVxLCByZXMpID0+IHtcbiAgY29uc3QgeyBoZWFkZXJzLCBpcCwgb3JpZ2luYWxVcmwsIHBhcmFtcyB9ID0gcmVxO1xuICAvLyBkZWNpZGUgaWYgdGhpcyBpcyBhIHNob3cgcmVxdWVzdFxuICBsZXQgaGFzRmlsZUV4dGVuc2lvbjtcbiAgdHJ5IHtcbiAgICAoeyBoYXNGaWxlRXh0ZW5zaW9uIH0gPSBsYnJ5VXJpLnBhcnNlTW9kaWZpZXIocGFyYW1zLmNsYWltKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pO1xuICB9XG4gIGxldCByZXNwb25zZVR5cGUgPSBkZXRlcm1pbmVSZXNwb25zZVR5cGUoaGFzRmlsZUV4dGVuc2lvbiwgaGVhZGVycyk7XG4gIGlmIChyZXNwb25zZVR5cGUgIT09IFNFUlZFKSB7XG4gICAgcmV0dXJuIGhhbmRsZVNob3dSZW5kZXIocmVxLCByZXMpO1xuICB9XG4gIC8vIGhhbmRsZSBzZXJ2ZSByZXF1ZXN0XG4gIC8vIHNlbmQgZ29vZ2xlIGFuYWx5dGljc1xuICBzZW5kR0FTZXJ2ZUV2ZW50KGhlYWRlcnMsIGlwLCBvcmlnaW5hbFVybCk7XG4gIC8vIHBhcnNlIHRoZSBjbGFpbVxuICBsZXQgY2xhaW1OYW1lO1xuICB0cnkge1xuICAgICh7IGNsYWltTmFtZSB9ID0gbGJyeVVyaS5wYXJzZUNsYWltKHBhcmFtcy5jbGFpbSkpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJldHVybiByZXMuc3RhdHVzKDQwMCkuanNvbih7c3VjY2VzczogZmFsc2UsIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2V9KTtcbiAgfVxuICAvLyBwYXJzZSB0aGUgaWRlbnRpZmllclxuICBsZXQgaXNDaGFubmVsLCBjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltSWQ7XG4gIHRyeSB7XG4gICAgKHsgaXNDaGFubmVsLCBjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltSWQgfSA9IGxicnlVcmkucGFyc2VJZGVudGlmaWVyKHBhcmFtcy5pZGVudGlmaWVyKSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlcy5zdGF0dXMoNDAwKS5qc29uKHtzdWNjZXNzOiBmYWxzZSwgbWVzc2FnZTogZXJyb3IubWVzc2FnZX0pO1xuICB9XG4gIGlmICghaXNDaGFubmVsKSB7XG4gICAgW2NsYWltSWQsIGNsYWltTmFtZV0gPSBmbGlwQ2xhaW1OYW1lQW5kSWRGb3JCYWNrd2FyZHNDb21wYXRpYmlsaXR5KGNsYWltSWQsIGNsYWltTmFtZSk7XG4gIH1cbiAgLy8gbG9nIHRoZSByZXF1ZXN0IGRhdGEgZm9yIGRlYnVnZ2luZ1xuICBsb2dSZXF1ZXN0RGF0YShyZXNwb25zZVR5cGUsIGNsYWltTmFtZSwgY2hhbm5lbE5hbWUsIGNsYWltSWQpO1xuICAvLyBnZXQgdGhlIGNsYWltIElkIGFuZCB0aGVuIHNlcnZlIHRoZSBhc3NldFxuICBnZXRDbGFpbUlkQW5kU2VydmVBc3NldChjaGFubmVsTmFtZSwgY2hhbm5lbENsYWltSWQsIGNsYWltTmFtZSwgY2xhaW1JZCwgb3JpZ2luYWxVcmwsIGlwLCByZXMpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzZXJ2ZXJBc3NldEJ5SWRlbnRpZmllckFuZENsYWltO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9hc3NldHMvc2VydmVBc3NldEJ5SWRlbnRpZmllckFuZENsYWltLmpzIiwiY29uc3QgaGFuZGxlUGFnZVJlcXVlc3QgPSByZXF1aXJlKCcuL3NlbmRSZWFjdEFwcCcpO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSAoYXBwKSA9PiB7XHJcbiAgYXBwLmdldCgnKicsIGhhbmRsZVBhZ2VSZXF1ZXN0KTtcclxufTtcclxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9mYWxsYmFjay9pbmRleC5qcyIsImNvbnN0IGhhbmRsZVBhZ2VSZW5kZXIgPSByZXF1aXJlKCdoZWxwZXJzL2hhbmRsZVBhZ2VSZW5kZXIuanN4Jyk7XG5cbmNvbnN0IHNlbmRSZWFjdEFwcCA9IChyZXEsIHJlcykgPT4ge1xuICBoYW5kbGVQYWdlUmVuZGVyKHJlcSwgcmVzKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gc2VuZFJlYWN0QXBwO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc2VydmVyL3JvdXRlcy9mYWxsYmFjay9zZW5kUmVhY3RBcHAuanMiXSwic291cmNlUm9vdCI6IiJ9 \ No newline at end of file diff --git a/index.js.map b/index.js.map index e3976587..b73e3880 100644 --- a/index.js.map +++ b/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///index.js","webpack:///webpack/bootstrap 997e9b26fb4c0319bb2a","webpack:///external \"winston\"","webpack:///./server/helpers/errorHandlers.js","webpack:///./server/models/index.js","webpack:///./config/siteConfig.js","webpack:///./server/helpers/googleAnalytics.js","webpack:///./server/helpers/lbryApi.js","webpack:///./server/controllers/serveController.js","webpack:///./server/speechPassport/index.js","webpack:///./server/controllers/publishController.js","webpack:///./server/helpers/publishHelpers.js","webpack:///./config/mysqlConfig.js","webpack:///external \"passport-local\"","webpack:///./server/helpers/sequelizeHelpers.js","webpack:///external \"sequelize\"","webpack:///./server/helpers/handlePageRender.jsx","webpack:///external \"react\"","webpack:///external \"react-dom/server\"","webpack:///external \"redux\"","webpack:///external \"react-redux\"","webpack:///external \"react-router-dom\"","webpack:///external \"spee.ch-components\"","webpack:///./server/helpers/renderFullPage.js","webpack:///external \"react-helmet\"","webpack:///./server/helpers/serveHelpers.js","webpack:///./server/helpers/lbryUri.js","webpack:///./server/helpers/handleShowRender.jsx","webpack:///external \"babel-polyfill\"","webpack:///external \"whatwg-fetch\"","webpack:///./speech.js","webpack:///./server/index.js","webpack:///external \"express\"","webpack:///external \"body-parser\"","webpack:///external \"express-handlebars\"","webpack:///external \"handlebars\"","webpack:///external \"helmet\"","webpack:///external \"cookie-session\"","webpack:///external \"http\"","webpack:///./server/middleware/requestLogger.js","webpack:///external \"path\"","webpack:///./config/loggerConfig.js","webpack:///./config/slackConfig.js","webpack:///external \"winston-slack-webhook\"","webpack:///external \"passport\"","webpack:///./server/speechPassport/local-login.js","webpack:///./server/models/certificate.js","webpack:///./server/models/channel.js","webpack:///./server/models/claim.js","webpack:///./server/models/file.js","webpack:///./server/models/request.js","webpack:///./server/models/user.js","webpack:///external \"bcrypt\"","webpack:///./server/speechPassport/local-signup.js","webpack:///external \"axios\"","webpack:///./config/lbryConfig.js","webpack:///external \"universal-analytics\"","webpack:///./server/helpers/authHelpers.js","webpack:///./server/routes/auth/index.js","webpack:///./server/routes/auth/signup.js","webpack:///./server/routes/auth/login.js","webpack:///./server/routes/auth/logout.js","webpack:///./server/routes/auth/user.js","webpack:///./server/routes/api/index.js","webpack:///./server/routes/api/channelAvailability.js","webpack:///external \"fs\"","webpack:///./server/routes/api/channelClaims.js","webpack:///./server/helpers/channelPagination.js","webpack:///./server/routes/api/channelData.js","webpack:///./server/routes/api/channelShortId.js","webpack:///./server/routes/api/claimAvailability.js","webpack:///./server/routes/api/claimData.js","webpack:///./server/routes/api/claimGet.js","webpack:///./server/routes/api/claimLongId.js","webpack:///./server/routes/api/claimPublish.js","webpack:///./server/auth/authentication.js","webpack:///./server/routes/api/claimResolve.js","webpack:///./server/routes/api/claimShortId.js","webpack:///./server/routes/api/claimList.js","webpack:///./server/routes/api/fileAvailability.js","webpack:///./server/helpers/multipartMiddleware.js","webpack:///external \"connect-multiparty\"","webpack:///./server/routes/pages/index.js","webpack:///./server/routes/pages/sendReactApp.js","webpack:///./server/routes/pages/sendEmbedPage.js","webpack:///./server/routes/pages/redirect.js","webpack:///./server/routes/assets/index.js","webpack:///./server/routes/assets/serveAssetByClaim.js","webpack:///external \"redux-saga\"","webpack:///external \"redux-saga/effects\"","webpack:///./server/routes/assets/serveAssetByIdentifierAndClaim.js","webpack:///./server/routes/fallback/index.js","webpack:///./server/routes/fallback/sendReactApp.js"],"names":["module","exports","modules","__webpack_require__","moduleId","installedModules","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","require","_slicedToArray","sliceIterator","arr","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","value","length","err","Array","isArray","TypeError","logger","handleErrorResponse","originalUrl","ip","error","res","useObjectPropertiesIfNoKeys","_module$exports$retur","returnErrorMessageAndStatus","_module$exports$retur2","status","message","json","createErrorResponsePayload","code","keys","newErrorObject","getOwnPropertyNames","forEach","key","success","Certificate","Channel","Claim","File","Request","User","Sequelize","_require","database","username","password","sequelize","host","dialect","dialectOptions","decimalNumbers","logging","pool","max","min","idle","acquire","authenticate","then","info","catch","db","import","modelName","associate","upsert","Model","values","condition","tableName","findOne","where","obj","debug","update","create","SiteConfig","_this","this","analytics","googleId","assetDefaults","description","thumbnail","title","auth","sessionKey","customComponents","components","containers","pages","details","port","twitter","publishing","additionalClaimAddresses","disabled","disabledMessage","primaryClaimAddress","thumbnailChannel","thumbnailChannelId","uploadDirectory","routes","config","console","log","createServeEventParams","headers","eventCategory","eventAction","eventLabel","ipOverride","userAgentOverride","createPublishTimingEventParams","category","variable","label","startTime","endTime","userTimingCategory","userTimingVariableName","userTimingTime","userTimingLabel","sendGoogleAnalyticsEvent","params","visitorId","replace","ua","strictCidFormat","https","event","sendGoogleAnalyticsTiming","timing","sendGAServeEvent","sendGATimingEvent","chooseGaLbrynetPublishLabel","_ref","channelName","channel_name","channelId","channel_id","axios","_require$api","api","apiHost","apiPort","lbryApiUri","_require2","handleLbrynetResponse","resolve","reject","data","result","Error","JSON","stringify","publishClaim","publishParams","gaStartTime","Date","now","Promise","post","method","response","getClaim","uri","timeout","getClaimList","claimName","resolveUri","_ref2","getDownloadDirectory","_ref3","download_directory","createChannel","amount","returnPaginatedChannelClaims","getClaimId","channelClaimId","claimId","getClaimIdByChannel","getClaimIdByClaim","getLongClaimId","longClaimId","getLongChannelId","longChannelId","all","getClaimIdByLongChannelId","getChannelData","page","longChannelClaimId","getShortChannelIdFromLongChannelId","_ref4","shortChannelClaimId","getChannelClaims","getAllChannelClaims","_ref5","_ref6","channelClaimsArray","paginatedChannelViewData","getLocalFileRecord","file","dataValues","passport","localLoginStrategy","localSignupStrategy","serializeSpeechUser","deserializeSpeechUser","deserializeUser","serializeUser","use","_defineProperty","writable","lbryApi","publishHelpers","_require$publishing","Op","publish","fileName","fileType","publishResults","certificateId","tx","channel","fileRecord","claim_id","metadata","address","claim_address","outpoint","txid","nout","height","filePath","file_path","nsfw","claimRecord","contentType","bid","upsertCriteria","claim","setClaim","setFile","deleteTemporaryFile","claimNameIsAvailable","claimAddresses","findAll","attributes","or","checkChannelAvailability","fs","parsePublishApiRequestBody","license","exec","parsePublishApiRequestFiles","path","type","size","test","validateFileTypeAndSize","thumbnailFileName","thumbnailFilePath","thumbnailFileType","createBasicPublishParams","trim","author","language","createThumbnailPublishParams","unlink","addGetResultsToFileData","fileInfo","getResult","file_name","download_path","createFileData","mysql","warn","returnShortId","claimsArray","longId","claimIndex","shortId","substring","shortIdLength","findIndex","element","possibleMatches","slice","filter","_interopRequireDefault","default","_react","_react2","_server","_redux","_reactRedux","_reactRouterDom","_spee","_renderFullPage","_renderFullPage2","_reactHelmet","_reactHelmet2","req","context","store","createStore","Reducers","html","renderToString","createElement","Provider","StaticRouter","location","url","GAListener","App","helmet","renderStatic","redirect","preloadedState","getState","send","toString","meta","link","clientAcceptsHtml","accept","match","requestIsFromBrowser","clientWantsAsset","range","imageIsWanted","videoIsWanted","isValidClaimId","isValidShortId","isValidShortIdOrClaimId","input","serveAssetToClient","NO_FILE","verbose","sendFileOptions","X-Content-Type-Options","Content-Type","sendFile","getClaimIdAndServeAsset","fullClaimId","determineResponseType","hasFileExtension","responseType","flipClaimNameAndIdForBackwardsCompatibility","identifier","tempName","logRequestData","REGEXP_INVALID_CLAIM","REGEXP_INVALID_CHANNEL","REGEXP_ADDRESS","CHANNEL_CHAR","parseIdentifier","componentsRegex","RegExp","_componentsRegex$exec","map","_componentsRegex$exec2","proto","modifierSeperator","modifier","isChannel","startsWith","nameBadChars","join","parseClaim","_componentsRegex$exec3","_componentsRegex$exec4","parseModifier","_componentsRegex$exec5","_componentsRegex$exec6","_reduxSaga","_reduxSaga2","_effects","returnSagaWithParams","saga","regeneratorRuntime","mark","_callee","wrap","_context","prev","stop","sagaMiddleware","middleware","applyMiddleware","action","Actions","onHandleShowPageUri","Sagas","handleShowPageUri","run","Server","configureLogger","userConfig","loggerConfig","configureMysql","mysqlConfig","configureSiteDetails","siteConfig","configureSlack","slackConfig","configureClientBundle","configureModels","configureRoutes","createApp","app","express","enable","publicFolder","Path","process","cwd","static","publicPath","__dirname","bodyParser","urlencoded","extended","requestLogger","speechPassport","cookieSession","maxAge","initialize","session","hbs","expressHandlebars","defaultLayout","handlebars","Handlebars","engine","set","server","http","start","PORT","sync","listen","LoggerConfig","logLevel","configure","transports","Console","level","timestamp","colorize","prettyPrint","handleExceptions","humanReadableUnhandledException","silly","SlackConfig","slackWebHook","slackErrorChannel","slackInfoChannel","winston","add","winstonSlackWebHook","webhookUrl","iconEmoji","SlackWebHook","PassportLocalStrategy","Strategy","returnUserAndChannelInfo","userInstance","userInfo","id","userName","getChannel","shortChannelId","usernameField","passwordField","user","comparePassword","isMatch","STRING","BOOLEAN","INTEGER","TEXT","DECIMAL","define","claimSequence","decodedClaim","depth","effectiveAmount","hasSignature","hex","validAtHeight","valueVersion","claimType","certificateVersion","keyType","publicKey","freezeTableName","belongsTo","foreignKey","allowNull","order","getLongChannelIdFromShortChannelId","_this2","$like","getLongChannelIdFromChannelName","_this3","validateLongChannelId","_this4","hasOne","determineFileExtensionFromContentType","determineThumbnail","storedThumbnail","defaultThumbnail","prepareClaimData","licenseUrl","preview","metadataVersion","source","sourceType","sourceVersion","streamVersion","getShortClaimIdFromLongClaimId","raw","getLongClaimIdFromShortClaimId","getTopFreeClaimIdByClaimName","_this5","validateLongClaimId","_this6","resolveClaim","_this7","claimArray","defaultValue","trendingEligible","hasMany","getRecentClaims","limit","ipAddress","bcrypt","compare","changePassword","newPassword","genSalt","saltError","salt","hash","hashError","hook","options","userData","channelData","certificateData","newUser","newChannel","newCertificate","setChannel","setUser","lbryConfig","handleSignupRequest","handleLoginRequest","handleLogoutRequest","handleUserRequest","signup","login","logIn","logout","channelAvailability","channelClaims","channelShortId","claimAvailability","claimData","claimGet","claimLongId","claimPublish","claimResolve","claimShortId","claimList","fileAvailability","multipartMiddleware","_require3","availableName","body","claims","totalPages","determineTotalPages","paginationPage","getPageFromQuery","extractPageFromClaims","previousPage","determinePreviousPage","currentPage","nextPage","determineNextPage","totalResults","determineTotalClaims","parseInt","pageNumber","claimStartIndex","claimEndIndex","totalClaims","fullPages","Math","floor","channelShortIdRoute","claimInfo","resolveResult","fileData","_ref5$","completed","authenticateUser","_require4","_require5","_require6","files","channelPassword","_parsePublishApiReque","_parsePublishApiReque2","_ref3$","thumbnailPublishParams","lbryTx","authenticateChannelCredentials","userPassword","channelFindParams","resolvedUri","claimsList","multipart","uploadDir","handlePageRequest","handleEmbedRequest","handlePageRender","sendReactApp","sendEmbedPage","render","layout","route","serveAssetByClaim","serveAssetByIdentifierAndClaim","lbryUri","handleShowRender","serverAssetByClaim","serverAssetByIdentifierAndClaim","_lbryUri$parseIdentif","_flipClaimNameAndIdFo","_flipClaimNameAndIdFo2"],"mappings":"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","file":"index.js","sourcesContent":["module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"/\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 26);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"winston\");\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar logger = __webpack_require__(0);\n\nmodule.exports = {\n handleErrorResponse: function handleErrorResponse(originalUrl, ip, error, res) {\n logger.error('Error on ' + originalUrl, module.exports.useObjectPropertiesIfNoKeys(error));\n\n var _module$exports$retur = module.exports.returnErrorMessageAndStatus(error),\n _module$exports$retur2 = _slicedToArray(_module$exports$retur, 2),\n status = _module$exports$retur2[0],\n message = _module$exports$retur2[1];\n\n res.status(status).json(module.exports.createErrorResponsePayload(status, message));\n },\n returnErrorMessageAndStatus: function returnErrorMessageAndStatus(error) {\n var status = void 0,\n message = void 0;\n // check for daemon being turned off\n if (error.code === 'ECONNREFUSED') {\n status = 503;\n message = 'Connection refused. The daemon may not be running.';\n // fallback for everything else\n } else {\n status = 400;\n if (error.message) {\n message = error.message;\n } else {\n message = error;\n };\n };\n return [status, message];\n },\n useObjectPropertiesIfNoKeys: function useObjectPropertiesIfNoKeys(err) {\n if (Object.keys(err).length === 0) {\n var newErrorObject = {};\n Object.getOwnPropertyNames(err).forEach(function (key) {\n newErrorObject[key] = err[key];\n });\n return newErrorObject;\n }\n return err;\n },\n createErrorResponsePayload: function createErrorResponsePayload(status, message) {\n return {\n status: status,\n success: false,\n message: message\n };\n }\n};\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar Certificate = __webpack_require__(45);\nvar Channel = __webpack_require__(46);\nvar Claim = __webpack_require__(47);\nvar File = __webpack_require__(48);\nvar Request = __webpack_require__(49);\nvar User = __webpack_require__(50);\n\nvar Sequelize = __webpack_require__(13);\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(10),\n database = _require.database,\n username = _require.username,\n password = _require.password;\n\n// set sequelize options\n\n\nvar sequelize = new Sequelize(database, username, password, {\n host: 'localhost',\n dialect: 'mysql',\n dialectOptions: { decimalNumbers: true },\n logging: false,\n pool: {\n max: 5,\n min: 0,\n idle: 10000,\n acquire: 10000\n }\n});\n\n// establish mysql connection\nsequelize.authenticate().then(function () {\n logger.info('Sequelize has established mysql connection successfully.');\n}).catch(function (err) {\n logger.error('Sequelize was unable to connect to the database:', err);\n});\n\n// manually add each model to the db object (note: make this dynamic)\nvar db = {};\ndb['Certificate'] = sequelize.import('Certificate', Certificate);\ndb['Channel'] = sequelize.import('Channel', Channel);\ndb['Claim'] = sequelize.import('Claim', Claim);\ndb['File'] = sequelize.import('File', File);\ndb['Request'] = sequelize.import('Request', Request);\ndb['User'] = sequelize.import('User', User);\n\n// run model.association for each model in the db object that has an association\nlogger.info('associating db models...');\nObject.keys(db).forEach(function (modelName) {\n if (db[modelName].associate) {\n logger.info('Associating model:', modelName);\n db[modelName].associate(db);\n }\n});\n\n// add sequelize/Sequelize to db\ndb.sequelize = sequelize;\ndb.Sequelize = Sequelize;\n// add an 'upsert' method to the db object\ndb.upsert = function (Model, values, condition, tableName) {\n return Model.findOne({\n where: condition\n }).then(function (obj) {\n if (obj) {\n // update\n logger.debug('updating record in db.' + tableName);\n return obj.update(values);\n } else {\n // insert\n logger.debug('creating record in db.' + tableName);\n return Model.create(values);\n }\n }).catch(function (error) {\n logger.error(tableName + '.upsert error', error);\n throw error;\n });\n};\n\nmodule.exports = db;\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nfunction SiteConfig() {\n var _this = this;\n\n this.analytics = {\n googleId: 'default'\n };\n this.assetDefaults = {\n description: 'An asset published on Spee.ch',\n thumbnail: 'https://spee.ch/assets/img/video_thumb_default.png',\n title: 'Spee.ch'\n };\n this.auth = {\n sessionKey: 'default'\n };\n this.customComponents = {\n components: {},\n containers: {},\n pages: {}\n };\n this.details = {\n description: 'Open-source, decentralized image and video sharing.',\n host: 'default',\n port: 3000,\n title: 'Spee.ch',\n twitter: '@spee_ch'\n };\n this.publishing = {\n additionalClaimAddresses: [],\n disabled: false,\n disabledMessage: 'Please check back soon.',\n primaryClaimAddress: 'default',\n thumbnailChannel: 'default',\n thumbnailChannelId: 'default',\n uploadDirectory: '/home/lbry/Uploads'\n };\n this.routes = {};\n this.update = function (config) {\n if (!config) {\n return console.log('No site config received.');\n }\n var analytics = config.analytics,\n assetDefaults = config.assetDefaults,\n auth = config.auth,\n customComponents = config.customComponents,\n details = config.details,\n publishing = config.publishing,\n routes = config.routes;\n\n console.log('Configuring site details...');\n _this.analytics = analytics;\n _this.assetDefaults = assetDefaults;\n _this.auth = auth;\n _this.details = details;\n _this.publishing = publishing;\n _this.customComponents = customComponents;\n _this.routes = routes;\n };\n};\n\nmodule.exports = new SiteConfig();\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\nvar ua = __webpack_require__(55);\n\nvar _require = __webpack_require__(3),\n googleId = _require.analytics.googleId,\n title = _require.details.title;\n\nfunction createServeEventParams(headers, ip, originalUrl) {\n return {\n eventCategory: 'client requests',\n eventAction: 'serve request',\n eventLabel: originalUrl,\n ipOverride: ip,\n userAgentOverride: headers['user-agent']\n };\n};\n\nfunction createPublishTimingEventParams(category, variable, label, startTime, endTime) {\n var duration = endTime - startTime;\n return {\n userTimingCategory: category,\n userTimingVariableName: variable,\n userTimingTime: duration,\n userTimingLabel: label\n };\n};\n\nfunction sendGoogleAnalyticsEvent(ip, params) {\n var visitorId = ip.replace(/\\./g, '-');\n var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.event(params, function (err) {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n });\n};\n\nfunction sendGoogleAnalyticsTiming(visitorId, params) {\n var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.timing(params, function (err) {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n logger.debug('Timing event successfully sent to google analytics');\n });\n};\n\nmodule.exports = {\n sendGAServeEvent: function sendGAServeEvent(headers, ip, originalUrl) {\n var params = createServeEventParams(headers, ip, originalUrl);\n sendGoogleAnalyticsEvent(ip, params);\n },\n sendGATimingEvent: function sendGATimingEvent(category, variable, label, startTime, endTime) {\n var params = createPublishTimingEventParams(category, variable, label, startTime, endTime);\n sendGoogleAnalyticsTiming(title, params);\n },\n chooseGaLbrynetPublishLabel: function chooseGaLbrynetPublishLabel(_ref) {\n var channelName = _ref.channel_name,\n channelId = _ref.channel_id;\n\n return channelName || channelId ? 'PUBLISH_IN_CHANNEL_CLAIM' : 'PUBLISH_ANONYMOUS_CLAIM';\n }\n};\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar axios = __webpack_require__(53);\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(54),\n _require$api = _require.api,\n apiHost = _require$api.apiHost,\n apiPort = _require$api.apiPort;\n\nvar lbryApiUri = 'http://' + apiHost + ':' + apiPort;\n\nvar _require2 = __webpack_require__(4),\n chooseGaLbrynetPublishLabel = _require2.chooseGaLbrynetPublishLabel,\n sendGATimingEvent = _require2.sendGATimingEvent;\n\nvar handleLbrynetResponse = function handleLbrynetResponse(_ref, resolve, reject) {\n var data = _ref.data;\n\n logger.debug('lbry api data:', data);\n if (data.result) {\n // check for an error\n if (data.result.error) {\n logger.debug('Lbrynet api error:', data.result.error);\n reject(new Error(data.result.error));\n return;\n };\n resolve(data.result);\n return;\n }\n // fallback in case it just timed out\n reject(JSON.stringify(data));\n};\n\nmodule.exports = {\n publishClaim: function publishClaim(publishParams) {\n logger.debug('lbryApi >> Publishing claim to \"' + publishParams.name + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'publish',\n params: publishParams\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getClaim: function getClaim(uri) {\n logger.debug('lbryApi >> Getting Claim for \"' + uri + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'get',\n params: { uri: uri, timeout: 20 }\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'getClaim', 'GET', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getClaimList: function getClaimList(claimName) {\n logger.debug('lbryApi >> Getting claim_list for \"' + claimName + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'claim_list',\n params: { name: claimName }\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'getClaimList', 'CLAIM_LIST', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n resolveUri: function resolveUri(uri) {\n logger.debug('lbryApi >> Resolving URI for \"' + uri + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'resolve',\n params: { uri: uri }\n }).then(function (_ref2) {\n var data = _ref2.data;\n\n sendGATimingEvent('lbrynet', 'resolveUri', 'RESOLVE', gaStartTime, Date.now());\n if (data.result[uri].error) {\n // check for errors\n reject(data.result[uri].error);\n } else {\n // if no errors, resolve\n resolve(data.result[uri]);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getDownloadDirectory: function getDownloadDirectory() {\n logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'settings_get'\n }).then(function (_ref3) {\n var data = _ref3.data;\n\n sendGATimingEvent('lbrynet', 'getDownloadDirectory', 'SETTINGS_GET', gaStartTime, Date.now());\n if (data.result) {\n resolve(data.result.download_directory);\n } else {\n return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.');\n }\n }).catch(function (error) {\n logger.error('Lbrynet Error:', error);\n resolve('/home/lbry/Downloads/');\n });\n });\n },\n createChannel: function createChannel(name) {\n logger.debug('lbryApi >> Creating channel for ' + name + '...');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'channel_new',\n params: {\n channel_name: name,\n amount: 0.1\n }\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'createChannel', 'CHANNEL_NEW', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n }\n};\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar db = __webpack_require__(2);\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(66),\n returnPaginatedChannelClaims = _require.returnPaginatedChannelClaims;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\nvar NO_CLAIM = 'NO_CLAIM';\nvar NO_FILE = 'NO_FILE';\n\nmodule.exports = {\n getClaimId: function getClaimId(channelName, channelClaimId, name, claimId) {\n if (channelName) {\n return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);\n } else {\n return module.exports.getClaimIdByClaim(name, claimId);\n }\n },\n getClaimIdByClaim: function getClaimIdByClaim(claimName, claimId) {\n logger.debug('getClaimIdByClaim(' + claimName + ', ' + claimId + ')');\n return new Promise(function (resolve, reject) {\n db.Claim.getLongClaimId(claimName, claimId).then(function (longClaimId) {\n if (!longClaimId) {\n resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getClaimIdByChannel: function getClaimIdByChannel(channelName, channelClaimId, claimName) {\n logger.debug('getClaimIdByChannel(' + channelName + ', ' + channelClaimId + ', ' + claimName + ')');\n return new Promise(function (resolve, reject) {\n db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id\n .then(function (longChannelId) {\n if (!longChannelId) {\n return [null, null];\n }\n return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id\n }).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n longChannelId = _ref2[0],\n longClaimId = _ref2[1];\n\n if (!longChannelId) {\n return resolve(NO_CHANNEL);\n }\n if (!longClaimId) {\n return resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getChannelData: function getChannelData(channelName, channelClaimId, page) {\n return new Promise(function (resolve, reject) {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (longChannelClaimId) {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]);\n }).then(function (_ref3) {\n var _ref4 = _slicedToArray(_ref3, 2),\n longChannelClaimId = _ref4[0],\n shortChannelClaimId = _ref4[1];\n\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. return all the channel information\n resolve({\n channelName: channelName,\n longChannelClaimId: longChannelClaimId,\n shortChannelClaimId: shortChannelClaimId\n });\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getChannelClaims: function getChannelClaims(channelName, channelClaimId, page) {\n return new Promise(function (resolve, reject) {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (longChannelClaimId) {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]);\n }).then(function (_ref5) {\n var _ref6 = _slicedToArray(_ref5, 2),\n longChannelClaimId = _ref6[0],\n channelClaimsArray = _ref6[1];\n\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. format the data for the view, including pagination\n var paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page);\n // 4. return all the channel information and contents\n resolve(paginatedChannelViewData);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getLocalFileRecord: function getLocalFileRecord(claimId, name) {\n return db.File.findOne({ where: { claimId: claimId, name: name } }).then(function (file) {\n if (!file) {\n return NO_FILE;\n }\n return file.dataValues;\n });\n }\n};\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar passport = __webpack_require__(43);\nvar localLoginStrategy = __webpack_require__(44);\nvar localSignupStrategy = __webpack_require__(52);\n\nvar _require = __webpack_require__(56),\n serializeSpeechUser = _require.serializeSpeechUser,\n deserializeSpeechUser = _require.deserializeSpeechUser;\n\npassport.deserializeUser(deserializeSpeechUser);\npassport.serializeUser(serializeSpeechUser);\npassport.use('local-login', localLoginStrategy);\npassport.use('local-signup', localSignupStrategy);\n\nmodule.exports = passport;\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nfunction _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; }\n\nvar logger = __webpack_require__(0);\nvar db = __webpack_require__(2);\nvar lbryApi = __webpack_require__(5);\nvar publishHelpers = __webpack_require__(9);\n\nvar _require = __webpack_require__(3),\n _require$publishing = _require.publishing,\n primaryClaimAddress = _require$publishing.primaryClaimAddress,\n additionalClaimAddresses = _require$publishing.additionalClaimAddresses;\n\nvar Sequelize = __webpack_require__(13);\nvar Op = Sequelize.Op;\n\nmodule.exports = {\n publish: function publish(publishParams, fileName, fileType) {\n return new Promise(function (resolve, reject) {\n var publishResults = void 0,\n certificateId = void 0,\n channelName = void 0;\n // publish the file\n return lbryApi.publishClaim(publishParams).then(function (tx) {\n logger.info('Successfully published ' + publishParams.name + ' ' + fileName, tx);\n publishResults = tx;\n // get the channel information\n if (publishParams.channel_name) {\n logger.debug('this claim was published in channel: ' + publishParams.channel_name);\n return db.Channel.findOne({\n where: {\n channelName: publishParams.channel_name\n }\n });\n } else {\n logger.debug('this claim was not published in a channel');\n return null;\n }\n }).then(function (channel) {\n // set channel information\n certificateId = null;\n channelName = null;\n if (channel) {\n certificateId = channel.channelClaimId;\n channelName = channel.channelName;\n }\n logger.debug('certificateId: ' + certificateId);\n }).then(function () {\n // create the File record\n var fileRecord = {\n name: publishParams.name,\n claimId: publishResults.claim_id,\n title: publishParams.metadata.title,\n description: publishParams.metadata.description,\n address: publishParams.claim_address,\n outpoint: publishResults.txid + ':' + publishResults.nout,\n height: 0,\n fileName: fileName,\n filePath: publishParams.file_path,\n fileType: fileType,\n nsfw: publishParams.metadata.nsfw\n };\n // create the Claim record\n var claimRecord = {\n name: publishParams.name,\n claimId: publishResults.claim_id,\n title: publishParams.metadata.title,\n description: publishParams.metadata.description,\n address: publishParams.claim_address,\n thumbnail: publishParams.metadata.thumbnail,\n outpoint: publishResults.txid + ':' + publishResults.nout,\n height: 0,\n contentType: fileType,\n nsfw: publishParams.metadata.nsfw,\n amount: publishParams.bid,\n certificateId: certificateId,\n channelName: channelName\n };\n // upsert criteria\n var upsertCriteria = {\n name: publishParams.name,\n claimId: publishResults.claim_id\n };\n // upsert the records\n return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]);\n }).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n file = _ref2[0],\n claim = _ref2[1];\n\n logger.debug('File and Claim records successfully created');\n return Promise.all([file.setClaim(claim), claim.setFile(file)]);\n }).then(function () {\n logger.debug('File and Claim records successfully associated');\n resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim;\n }).catch(function (error) {\n logger.error('PUBLISH ERROR', error);\n publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file\n reject(error);\n });\n });\n },\n claimNameIsAvailable: function claimNameIsAvailable(name) {\n var claimAddresses = additionalClaimAddresses || [];\n claimAddresses.push(primaryClaimAddress);\n // find any records where the name is used\n return db.Claim.findAll({\n attributes: ['address'],\n where: {\n name: name,\n address: _defineProperty({}, Op.or, claimAddresses)\n }\n }).then(function (result) {\n if (result.length >= 1) {\n throw new Error('That claim is already in use');\n };\n return name;\n }).catch(function (error) {\n throw error;\n });\n },\n checkChannelAvailability: function checkChannelAvailability(name) {\n return db.Channel.findAll({\n where: { channelName: name }\n }).then(function (result) {\n if (result.length >= 1) {\n throw new Error('That channel has already been claimed');\n }\n return name;\n }).catch(function (error) {\n throw error;\n });\n }\n};\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\nvar fs = __webpack_require__(64);\n\nvar _require = __webpack_require__(3),\n details = _require.details,\n publishing = _require.publishing;\n\nmodule.exports = {\n parsePublishApiRequestBody: function parsePublishApiRequestBody(_ref) {\n var name = _ref.name,\n nsfw = _ref.nsfw,\n license = _ref.license,\n title = _ref.title,\n description = _ref.description,\n thumbnail = _ref.thumbnail;\n\n // validate name\n if (!name) {\n throw new Error('no name field found in request');\n }\n var invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name);\n if (invalidNameCharacters) {\n throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and \"-\"');\n }\n // optional parameters\n nsfw = nsfw === 'true';\n license = license || null;\n title = title || null;\n description = description || null;\n thumbnail = thumbnail || null;\n // return results\n return {\n name: name,\n nsfw: nsfw,\n license: license,\n title: title,\n description: description,\n thumbnail: thumbnail\n };\n },\n parsePublishApiRequestFiles: function parsePublishApiRequestFiles(_ref2) {\n var file = _ref2.file,\n thumbnail = _ref2.thumbnail;\n\n // make sure a file was provided\n if (!file) {\n throw new Error('no file with key of [file] found in request');\n }\n if (!file.path) {\n throw new Error('no file path found');\n }\n if (!file.type) {\n throw new Error('no file type found');\n }\n if (!file.size) {\n throw new Error('no file type found');\n }\n // validate the file name\n if (/'/.test(file.name)) {\n throw new Error('apostrophes are not allowed in the file name');\n }\n // validate the file\n module.exports.validateFileTypeAndSize(file);\n // return results\n return {\n fileName: file.name,\n filePath: file.path,\n fileType: file.type,\n thumbnailFileName: thumbnail ? thumbnail.name : null,\n thumbnailFilePath: thumbnail ? thumbnail.path : null,\n thumbnailFileType: thumbnail ? thumbnail.type : null\n };\n },\n validateFileTypeAndSize: function validateFileTypeAndSize(file) {\n // check file type and size\n switch (file.type) {\n case 'image/jpeg':\n case 'image/jpg':\n case 'image/png':\n if (file.size > 10000000) {\n logger.debug('publish > file validation > .jpeg/.jpg/.png was too big');\n throw new Error('Sorry, images are limited to 10 megabytes.');\n }\n break;\n case 'image/gif':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .gif was too big');\n throw new Error('Sorry, .gifs are limited to 50 megabytes.');\n }\n break;\n case 'video/mp4':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .mp4 was too big');\n throw new Error('Sorry, videos are limited to 50 megabytes.');\n }\n break;\n default:\n logger.debug('publish > file validation > unrecognized file type');\n throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');\n }\n return file;\n },\n createBasicPublishParams: function createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail) {\n logger.debug('Creating Publish Parameters');\n // provide defaults for title\n if (title === null || title.trim() === '') {\n title = name;\n }\n // provide default for description\n if (description === null || description.trim() === '') {\n description = '';\n }\n // provide default for license\n if (license === null || license.trim() === '') {\n license = ' '; // default to empty string\n }\n // create the publish params\n var publishParams = {\n name: name,\n file_path: filePath,\n bid: 0.01,\n metadata: {\n description: description,\n title: title,\n author: details.title,\n language: 'en',\n license: license,\n nsfw: nsfw\n },\n claim_address: publishing.primaryClaimAddress\n };\n // add thumbnail to channel if video\n if (thumbnail) {\n publishParams['metadata']['thumbnail'] = thumbnail;\n }\n return publishParams;\n },\n createThumbnailPublishParams: function createThumbnailPublishParams(thumbnailFilePath, claimName, license, nsfw) {\n if (!thumbnailFilePath) {\n return;\n }\n logger.debug('Creating Thumbnail Publish Parameters');\n // create the publish params\n return {\n name: claimName + '-thumb',\n file_path: thumbnailFilePath,\n bid: 0.01,\n metadata: {\n title: claimName + ' thumbnail',\n description: 'a thumbnail for ' + claimName,\n author: details.title,\n language: 'en',\n license: license,\n nsfw: nsfw\n },\n claim_address: publishing.primaryClaimAddress,\n channel_name: publishing.thumbnailChannel,\n channel_id: publishing.thumbnailChannelId\n };\n },\n deleteTemporaryFile: function deleteTemporaryFile(filePath) {\n fs.unlink(filePath, function (err) {\n if (err) {\n logger.error('error deleting temporary file ' + filePath);\n throw err;\n }\n logger.debug('successfully deleted ' + filePath);\n });\n },\n addGetResultsToFileData: function addGetResultsToFileData(fileInfo, getResult) {\n fileInfo.fileName = getResult.file_name;\n fileInfo.filePath = getResult.download_path;\n return fileInfo;\n },\n createFileData: function createFileData(_ref3) {\n var name = _ref3.name,\n claimId = _ref3.claimId,\n outpoint = _ref3.outpoint,\n height = _ref3.height,\n address = _ref3.address,\n nsfw = _ref3.nsfw,\n contentType = _ref3.contentType;\n\n return {\n name: name,\n claimId: claimId,\n outpoint: outpoint,\n height: height,\n address: address,\n fileName: '',\n filePath: '',\n fileType: contentType,\n nsfw: nsfw\n };\n }\n};\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nfunction mysql() {\n var _this = this;\n\n this.database = 'default';\n this.username = 'default';\n this.password = 'default';\n this.update = function (config) {\n if (!config) {\n return logger.warn('No MySQL config received.');\n }\n // configure credentials\n logger.info('configuring mysql...');\n var database = config.database,\n username = config.username,\n password = config.password;\n\n _this.database = database;\n _this.username = username;\n _this.password = password;\n };\n};\n\nmodule.exports = new mysql();\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"passport-local\");\n\n/***/ }),\n/* 12 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = {\n returnShortId: function returnShortId(claimsArray, longId) {\n var claimIndex = void 0;\n var shortId = longId.substring(0, 1); // default short id is the first letter\n var shortIdLength = 0;\n // find the index of this claim id\n claimIndex = claimsArray.findIndex(function (element) {\n return element.claimId === longId;\n });\n if (claimIndex < 0) {\n throw new Error('claim id not found in claims list');\n }\n // get an array of all claims with lower height\n var possibleMatches = claimsArray.slice(0, claimIndex);\n // remove certificates with the same prefixes until none are left.\n while (possibleMatches.length > 0) {\n shortIdLength += 1;\n shortId = longId.substring(0, shortIdLength);\n possibleMatches = possibleMatches.filter(function (element) {\n return element.claimId && element.claimId.substring(0, shortIdLength) === shortId;\n });\n }\n return shortId;\n }\n};\n\n/***/ }),\n/* 13 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"sequelize\");\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _react = __webpack_require__(15);\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _server = __webpack_require__(16);\n\nvar _redux = __webpack_require__(17);\n\nvar _reactRedux = __webpack_require__(18);\n\nvar _reactRouterDom = __webpack_require__(19);\n\nvar _spee = __webpack_require__(20);\n\nvar _renderFullPage = __webpack_require__(21);\n\nvar _renderFullPage2 = _interopRequireDefault(_renderFullPage);\n\nvar _reactHelmet = __webpack_require__(22);\n\nvar _reactHelmet2 = _interopRequireDefault(_reactHelmet);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nmodule.exports = function (req, res) {\n var context = {};\n\n // create a new Redux store instance\n var store = (0, _redux.createStore)(_spee.Reducers);\n\n // render component to a string\n var html = (0, _server.renderToString)(_react2.default.createElement(\n _reactRedux.Provider,\n { store: store },\n _react2.default.createElement(\n _reactRouterDom.StaticRouter,\n { location: req.url, context: context },\n _react2.default.createElement(\n _spee.GAListener,\n null,\n _react2.default.createElement(_spee.App, null)\n )\n )\n ));\n\n // get head tags from helmet\n var helmet = _reactHelmet2.default.renderStatic();\n\n // check for a redirect\n if (context.url) {\n // Somewhere a `` was rendered\n return res.redirect(301, context.url);\n } else {}\n // we're good, send the response\n\n\n // get the initial state from our Redux store\n var preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));\n};\n\n/***/ }),\n/* 15 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react\");\n\n/***/ }),\n/* 16 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-dom/server\");\n\n/***/ }),\n/* 17 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"redux\");\n\n/***/ }),\n/* 18 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-redux\");\n\n/***/ }),\n/* 19 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-router-dom\");\n\n/***/ }),\n/* 20 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"spee.ch-components\");\n\n/***/ }),\n/* 21 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (helmet, html, preloadedState) {\n // take the html and preloadedState and return the full page\n return '\\n \\n \\n \\n \\n \\n \\n \\n ' + helmet.title.toString() + '\\n ' + helmet.meta.toString() + '\\n ' + helmet.link.toString() + '\\n \\n \\n \\n \\n \\n \\n \\n \\n
\\n
' + html + '
\\n
\\n \\n \\n \\n \\n ';\n};\n\n/***/ }),\n/* 22 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-helmet\");\n\n/***/ }),\n/* 23 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(6),\n getClaimId = _require.getClaimId,\n getLocalFileRecord = _require.getLocalFileRecord;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar SERVE = 'SERVE';\nvar SHOW = 'SHOW';\nvar NO_FILE = 'NO_FILE';\nvar NO_CHANNEL = 'NO_CHANNEL';\nvar NO_CLAIM = 'NO_CLAIM';\n\nfunction clientAcceptsHtml(_ref) {\n var accept = _ref.accept;\n\n return accept && accept.match(/text\\/html/);\n};\n\nfunction requestIsFromBrowser(headers) {\n return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);\n};\n\nfunction clientWantsAsset(_ref2) {\n var accept = _ref2.accept,\n range = _ref2.range;\n\n var imageIsWanted = accept && accept.match(/image\\/.*/) && !accept.match(/text\\/html/) && !accept.match(/text\\/\\*/);\n var videoIsWanted = accept && range;\n return imageIsWanted || videoIsWanted;\n};\n\nfunction isValidClaimId(claimId) {\n return claimId.length === 40 && !/[^A-Za-z0-9]/g.test(claimId);\n};\n\nfunction isValidShortId(claimId) {\n return claimId.length === 1; // it should really evaluate the short url itself\n};\n\nfunction isValidShortIdOrClaimId(input) {\n return isValidClaimId(input) || isValidShortId(input);\n};\n\nfunction serveAssetToClient(claimId, name, res) {\n return getLocalFileRecord(claimId, name).then(function (fileRecord) {\n // check that a local record was found\n if (fileRecord === NO_FILE) {\n return res.status(307).redirect('/api/claim/get/' + name + '/' + claimId);\n }\n // serve the file\n var filePath = fileRecord.filePath,\n fileType = fileRecord.fileType;\n\n logger.verbose('serving file: ' + filePath);\n var sendFileOptions = {\n headers: {\n 'X-Content-Type-Options': 'nosniff',\n 'Content-Type': fileType || 'image/jpeg'\n }\n };\n res.status(200).sendFile(filePath, sendFileOptions);\n }).catch(function (error) {\n throw error;\n });\n};\n\nmodule.exports = {\n getClaimIdAndServeAsset: function getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) {\n // get the claim Id and then serve the asset\n getClaimId(channelName, channelClaimId, claimName, claimId).then(function (fullClaimId) {\n if (fullClaimId === NO_CLAIM) {\n return res.status(404).json({ success: false, message: 'no claim id could be found' });\n } else if (fullClaimId === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'no channel id could be found' });\n }\n serveAssetToClient(fullClaimId, claimName, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');\n });\n },\n determineResponseType: function determineResponseType(hasFileExtension, headers) {\n var responseType = void 0;\n if (hasFileExtension) {\n responseType = SERVE; // assume a serve request if file extension is present\n if (clientAcceptsHtml(headers)) {\n // if the request comes from a browser, change it to a show request\n responseType = SHOW;\n }\n } else {\n responseType = SHOW;\n if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) {\n // this is in case someone embeds a show url\n logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');\n responseType = SERVE;\n }\n }\n return responseType;\n },\n flipClaimNameAndIdForBackwardsCompatibility: function flipClaimNameAndIdForBackwardsCompatibility(identifier, name) {\n // this is a patch for backwards compatability with '/name/claim_id' url format\n if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {\n var tempName = name;\n name = identifier;\n identifier = tempName;\n }\n return [identifier, name];\n },\n logRequestData: function logRequestData(responseType, claimName, channelName, claimId) {\n logger.debug('responseType ===', responseType);\n logger.debug('claim name === ', claimName);\n logger.debug('channel name ===', channelName);\n logger.debug('claim id ===', claimId);\n }\n};\n\n/***/ }),\n/* 24 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar logger = __webpack_require__(0);\n\nmodule.exports = {\n REGEXP_INVALID_CLAIM: /[^A-Za-z0-9-]/g,\n REGEXP_INVALID_CHANNEL: /[^A-Za-z0-9-@]/g,\n REGEXP_ADDRESS: /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/,\n CHANNEL_CHAR: '@',\n parseIdentifier: function parseIdentifier(identifier) {\n logger.debug('parsing identifier:', identifier);\n var componentsRegex = new RegExp('([^:$#/]*)' + // value (stops at the first separator or end)\n '([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n\n var _componentsRegex$exec = componentsRegex.exec(identifier).map(function (match) {\n return match || null;\n }),\n _componentsRegex$exec2 = _slicedToArray(_componentsRegex$exec, 4),\n proto = _componentsRegex$exec2[0],\n value = _componentsRegex$exec2[1],\n modifierSeperator = _componentsRegex$exec2[2],\n modifier = _componentsRegex$exec2[3];\n\n logger.debug(proto + ', ' + value + ', ' + modifierSeperator + ', ' + modifier);\n\n // Validate and process name\n if (!value) {\n throw new Error('Check your url. No channel name provided before \"' + modifierSeperator + '\"');\n }\n var isChannel = value.startsWith(module.exports.CHANNEL_CHAR);\n var channelName = isChannel ? value : null;\n var claimId = void 0;\n if (isChannel) {\n if (!channelName) {\n throw new Error('No channel name after @.');\n }\n var nameBadChars = channelName.match(module.exports.REGEXP_INVALID_CHANNEL);\n if (nameBadChars) {\n throw new Error('Invalid characters in channel name: ' + nameBadChars.join(', ') + '.');\n }\n } else {\n claimId = value;\n }\n\n // Validate and process modifier\n var channelClaimId = void 0;\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error('No modifier provided after separator \"' + modifierSeperator + '\"');\n }\n\n if (modifierSeperator === ':') {\n channelClaimId = modifier;\n } else {\n throw new Error('The \"' + modifierSeperator + '\" modifier is not currently supported');\n }\n }\n return {\n isChannel: isChannel,\n channelName: channelName,\n channelClaimId: channelClaimId,\n claimId: claimId\n };\n },\n parseClaim: function parseClaim(claim) {\n logger.debug('parsing name:', claim);\n var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n\n var _componentsRegex$exec3 = componentsRegex.exec(claim).map(function (match) {\n return match || null;\n }),\n _componentsRegex$exec4 = _slicedToArray(_componentsRegex$exec3, 4),\n proto = _componentsRegex$exec4[0],\n claimName = _componentsRegex$exec4[1],\n modifierSeperator = _componentsRegex$exec4[2],\n modifier = _componentsRegex$exec4[3];\n\n logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);\n\n // Validate and process name\n if (!claimName) {\n throw new Error('No claim name provided before .');\n }\n var nameBadChars = claimName.match(module.exports.REGEXP_INVALID_CLAIM);\n if (nameBadChars) {\n throw new Error('Invalid characters in claim name: ' + nameBadChars.join(', ') + '.');\n }\n // Validate and process modifier\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error('No file extension provided after separator ' + modifierSeperator + '.');\n }\n if (modifierSeperator !== '.') {\n throw new Error('The ' + modifierSeperator + ' modifier is not supported in the claim name');\n }\n }\n // return results\n return {\n claimName: claimName\n };\n },\n parseModifier: function parseModifier(claim) {\n logger.debug('parsing modifier:', claim);\n var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n\n var _componentsRegex$exec5 = componentsRegex.exec(claim).map(function (match) {\n return match || null;\n }),\n _componentsRegex$exec6 = _slicedToArray(_componentsRegex$exec5, 4),\n proto = _componentsRegex$exec6[0],\n claimName = _componentsRegex$exec6[1],\n modifierSeperator = _componentsRegex$exec6[2],\n modifier = _componentsRegex$exec6[3];\n\n logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);\n // Validate and process modifier\n var hasFileExtension = false;\n if (modifierSeperator) {\n hasFileExtension = true;\n }\n return {\n hasFileExtension: hasFileExtension\n };\n }\n};\n\n/***/ }),\n/* 25 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _react = __webpack_require__(15);\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _server = __webpack_require__(16);\n\nvar _redux = __webpack_require__(17);\n\nvar _reactRedux = __webpack_require__(18);\n\nvar _reactRouterDom = __webpack_require__(19);\n\nvar _renderFullPage = __webpack_require__(21);\n\nvar _renderFullPage2 = _interopRequireDefault(_renderFullPage);\n\nvar _reduxSaga = __webpack_require__(87);\n\nvar _reduxSaga2 = _interopRequireDefault(_reduxSaga);\n\nvar _effects = __webpack_require__(88);\n\nvar _spee = __webpack_require__(20);\n\nvar _reactHelmet = __webpack_require__(22);\n\nvar _reactHelmet2 = _interopRequireDefault(_reactHelmet);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar returnSagaWithParams = function returnSagaWithParams(saga, params) {\n return (/*#__PURE__*/regeneratorRuntime.mark(function _callee() {\n return regeneratorRuntime.wrap(function _callee$(_context) {\n while (1) {\n switch (_context.prev = _context.next) {\n case 0:\n _context.next = 2;\n return (0, _effects.call)(saga, params);\n\n case 2:\n case 'end':\n return _context.stop();\n }\n }\n }, _callee, this);\n })\n );\n};\n\nmodule.exports = function (req, res) {\n var context = {};\n\n // create and apply middleware\n var sagaMiddleware = (0, _reduxSaga2.default)();\n var middleware = (0, _redux.applyMiddleware)(sagaMiddleware);\n\n // create a new Redux store instance\n var store = (0, _redux.createStore)(_spee.Reducers, middleware);\n\n // create saga\n var action = _spee.Actions.onHandleShowPageUri(req.params);\n var saga = returnSagaWithParams(_spee.Sagas.handleShowPageUri, action);\n\n // run the saga middleware\n sagaMiddleware.run(saga).done.then(function () {\n // render component to a string\n var html = (0, _server.renderToString)(_react2.default.createElement(\n _reactRedux.Provider,\n { store: store },\n _react2.default.createElement(\n _reactRouterDom.StaticRouter,\n { location: req.url, context: context },\n _react2.default.createElement(\n _spee.GAListener,\n null,\n _react2.default.createElement(_spee.App, null)\n )\n )\n ));\n\n // get head tags from helmet\n var helmet = _reactHelmet2.default.renderStatic();\n\n // check for a redirect\n if (context.url) {\n return res.redirect(301, context.url);\n }\n\n // get the initial state from our Redux store\n var preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));\n });\n};\n\n/***/ }),\n/* 26 */\n/***/ (function(module, exports, __webpack_require__) {\n\n__webpack_require__(27);\n__webpack_require__(28);\nmodule.exports = __webpack_require__(29);\n\n\n/***/ }),\n/* 27 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"babel-polyfill\");\n\n/***/ }),\n/* 28 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"whatwg-fetch\");\n\n/***/ }),\n/* 29 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar Server = __webpack_require__(30);\n\nvar _exports = {\n Server: Server\n};\n\nmodule.exports = _exports;\n\n/***/ }),\n/* 30 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n// app dependencies\nvar express = __webpack_require__(31);\nvar bodyParser = __webpack_require__(32);\nvar expressHandlebars = __webpack_require__(33);\nvar Handlebars = __webpack_require__(34);\nvar helmet = __webpack_require__(35);\nvar cookieSession = __webpack_require__(36);\nvar http = __webpack_require__(37);\nvar logger = __webpack_require__(0);\nvar requestLogger = __webpack_require__(38);\nvar Path = __webpack_require__(39);\nvar loggerConfig = __webpack_require__(40);\nvar mysqlConfig = __webpack_require__(10);\nvar siteConfig = __webpack_require__(3);\nvar slackConfig = __webpack_require__(41);\n\nfunction Server() {\n var _this = this;\n\n this.configureLogger = function (userConfig) {\n loggerConfig.update(userConfig);\n };\n this.configureMysql = function (userConfig) {\n mysqlConfig.update(userConfig);\n };\n this.configureSiteDetails = function (userConfig) {\n siteConfig.update(userConfig);\n };\n this.configureSlack = function (userConfig) {\n slackConfig.update(userConfig);\n };\n this.configureClientBundle = function () {\n logger.debug('configure the client here by passing in the bundle and configuring it, or better yet: taking in the components to use dynamically from here.');\n };\n this.configureModels = function () {\n logger.debug('here is where you could add/overwrite the default models');\n };\n this.configureRoutes = function () {\n logger.debug('here is where you could add/overwrite the default routes');\n };\n this.createApp = function () {\n // create an Express application\n var app = express();\n\n // trust the proxy to get ip address for us\n app.enable('trust proxy');\n\n /* add middleware */\n // set HTTP headers to protect against well-known web vulnerabilties\n app.use(helmet());\n // 'express.static' to serve static files from public directory\n if (siteConfig.routes.publicFolder) {\n // take in a different public folder, so it can serve it's own bundle if needed\n var publicFolder = Path.resolve(process.cwd(), siteConfig.routes.publicFolder);\n app.use('/static', express.static(publicFolder));\n logger.info('serving static files from custom path:', publicFolder);\n } else {\n var publicPath = Path.resolve(__dirname, 'public');\n app.use('/static', express.static(publicPath));\n logger.info('serving static files from default path:', publicPath);\n };\n // 'body parser' for parsing application/json\n app.use(bodyParser.json());\n // 'body parser' for parsing application/x-www-form-urlencoded\n app.use(bodyParser.urlencoded({ extended: true }));\n\n // add custom middleware (note: build out to accept dynamically use what is in server/middleware/\n app.use(requestLogger);\n\n // configure passport\n var speechPassport = __webpack_require__(7);\n // initialize passport\n var sessionKey = siteConfig.auth.sessionKey;\n app.use(cookieSession({\n name: 'session',\n keys: [sessionKey],\n maxAge: 24 * 60 * 60 * 1000 // i.e. 24 hours\n }));\n app.use(speechPassport.initialize());\n app.use(speechPassport.session());\n\n // configure handlebars & register it with express app\n var hbs = expressHandlebars.create({\n defaultLayout: 'embed',\n handlebars: Handlebars\n });\n app.engine('handlebars', hbs.engine);\n app.set('view engine', 'handlebars');\n\n // set the routes on the app\n __webpack_require__(57)(app);\n __webpack_require__(62)(app);\n __webpack_require__(81)(app);\n __webpack_require__(85)(app);\n __webpack_require__(90)(app);\n\n _this.app = app;\n };\n this.initialize = function () {\n _this.createApp();\n _this.server = http.Server(_this.app);\n };\n this.start = function () {\n var db = __webpack_require__(2);\n var PORT = siteConfig.details.port;\n // sync sequelize\n db.sequelize.sync()\n // start the server\n .then(function () {\n _this.server.listen(PORT, function () {\n logger.info('Server is listening on PORT ' + PORT);\n });\n }).catch(function (error) {\n logger.error('Startup Error:', error);\n });\n };\n};\n\nmodule.exports = Server;\n\n/***/ }),\n/* 31 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"express\");\n\n/***/ }),\n/* 32 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"body-parser\");\n\n/***/ }),\n/* 33 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"express-handlebars\");\n\n/***/ }),\n/* 34 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"handlebars\");\n\n/***/ }),\n/* 35 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"helmet\");\n\n/***/ }),\n/* 36 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"cookie-session\");\n\n/***/ }),\n/* 37 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"http\");\n\n/***/ }),\n/* 38 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar requestLogger = function requestLogger(req, res, next) {\n // custom logging middleware to log all incoming http requests\n logger.verbose('Request on ' + req.originalUrl + ' from ' + req.ip);\n next();\n};\n\nmodule.exports = requestLogger;\n\n/***/ }),\n/* 39 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"path\");\n\n/***/ }),\n/* 40 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nfunction LoggerConfig() {\n var _this = this;\n\n this.logLevel = 'debug';\n this.update = function (config) {\n if (!config) {\n return logger.warn('No logger config received.');\n }\n logger.info('configuring winston logger...');\n // update values with local config params\n var logLevel = config.logLevel;\n\n _this.logLevel = logLevel;\n // configure the winston logger\n logger.configure({\n transports: [new logger.transports.Console({\n level: _this.logLevel,\n timestamp: false,\n colorize: true,\n prettyPrint: true,\n handleExceptions: true,\n humanReadableUnhandledException: true\n })]\n });\n // test all the log levels\n logger.info('testing winston log levels...');\n logger.error('Level 0');\n logger.warn('Level 1');\n logger.info('Level 2');\n logger.verbose('Level 3');\n logger.debug('Level 4');\n logger.silly('Level 5');\n };\n};\n\nmodule.exports = new LoggerConfig();\n\n/***/ }),\n/* 41 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar winstonSlackWebHook = __webpack_require__(42).SlackWebHook;\nvar winston = __webpack_require__(0);\n\nfunction SlackConfig() {\n var _this = this;\n\n this.slackWebHook = 'default';\n this.slackErrorChannel = 'default';\n this.slackInfoChannel = 'default';\n this.update = function (config) {\n if (!config) {\n return winston.warn('No slack config received');\n }\n // update variables\n winston.info('configuring slack logger...');\n var slackWebHook = config.slackWebHook,\n slackErrorChannel = config.slackErrorChannel,\n slackInfoChannel = config.slackInfoChannel;\n\n _this.slackWebHook = slackWebHook;\n _this.slackErrorChannel = slackErrorChannel;\n _this.slackInfoChannel = slackInfoChannel;\n // update slack webhook settings\n if (_this.slackWebHook) {\n // add a transport for errors to slack\n if (_this.slackErrorChannel) {\n winston.add(winstonSlackWebHook, {\n name: 'slack-errors-transport',\n level: 'warn',\n webhookUrl: _this.slackWebHook,\n channel: _this.slackErrorChannel,\n username: 'spee.ch',\n iconEmoji: ':face_with_head_bandage:'\n });\n };\n if (slackInfoChannel) {\n winston.add(winstonSlackWebHook, {\n name: 'slack-info-transport',\n level: 'info',\n webhookUrl: _this.slackWebHook,\n channel: _this.slackInfoChannel,\n username: 'spee.ch',\n iconEmoji: ':nerd_face:'\n });\n };\n // send test messages\n winston.info('testing slack logger...');\n winston.error('Slack \"error\" logging is online.');\n winston.info('Slack \"info\" logging is online.');\n } else {\n winston.warn('Slack logging is not enabled because no slackWebHook config var provided.');\n }\n };\n};\n\nmodule.exports = new SlackConfig();\n\n/***/ }),\n/* 42 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"winston-slack-webhook\");\n\n/***/ }),\n/* 43 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"passport\");\n\n/***/ }),\n/* 44 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar PassportLocalStrategy = __webpack_require__(11).Strategy;\nvar logger = __webpack_require__(0);\nvar db = __webpack_require__(2);\n\nvar returnUserAndChannelInfo = function returnUserAndChannelInfo(userInstance) {\n return new Promise(function (resolve, reject) {\n var userInfo = {};\n userInfo['id'] = userInstance.id;\n userInfo['userName'] = userInstance.userName;\n userInstance.getChannel().then(function (_ref) {\n var channelName = _ref.channelName,\n channelClaimId = _ref.channelClaimId;\n\n userInfo['channelName'] = channelName;\n userInfo['channelClaimId'] = channelClaimId;\n return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName);\n }).then(function (shortChannelId) {\n userInfo['shortChannelId'] = shortChannelId;\n resolve(userInfo);\n }).catch(function (error) {\n reject(error);\n });\n });\n};\n\nmodule.exports = new PassportLocalStrategy({\n usernameField: 'username',\n passwordField: 'password'\n}, function (username, password, done) {\n return db.User.findOne({\n where: { userName: username }\n }).then(function (user) {\n if (!user) {\n logger.debug('no user found');\n return done(null, false, { message: 'Incorrect username or password' });\n }\n return user.comparePassword(password).then(function (isMatch) {\n if (!isMatch) {\n logger.debug('incorrect password');\n return done(null, false, { message: 'Incorrect username or password' });\n }\n logger.debug('Password was a match, returning User');\n return returnUserAndChannelInfo(user).then(function (userInfo) {\n return done(null, userInfo);\n }).catch(function (error) {\n return error;\n });\n }).catch(function (error) {\n return error;\n });\n }).catch(function (error) {\n return done(error);\n });\n});\n\n/***/ }),\n/* 45 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(12),\n returnShortId = _require.returnShortId;\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n INTEGER = _ref.INTEGER,\n TEXT = _ref.TEXT,\n DECIMAL = _ref.DECIMAL;\n\n var Certificate = sequelize.define('Certificate', {\n address: {\n type: STRING,\n default: null\n },\n amount: {\n type: DECIMAL(19, 8),\n default: null\n },\n claimId: {\n type: STRING,\n default: null\n },\n claimSequence: {\n type: INTEGER,\n default: null\n },\n decodedClaim: {\n type: BOOLEAN,\n default: null\n },\n depth: {\n type: INTEGER,\n default: null\n },\n effectiveAmount: {\n type: DECIMAL(19, 8),\n default: null\n },\n hasSignature: {\n type: BOOLEAN,\n default: null\n },\n height: {\n type: INTEGER,\n default: null\n },\n hex: {\n type: TEXT('long'),\n default: null\n },\n name: {\n type: STRING,\n default: null\n },\n nout: {\n type: INTEGER,\n default: null\n },\n txid: {\n type: STRING,\n default: null\n },\n validAtHeight: {\n type: INTEGER,\n default: null\n },\n outpoint: {\n type: STRING,\n default: null\n },\n valueVersion: {\n type: STRING,\n default: null\n },\n claimType: {\n type: STRING,\n default: null\n },\n certificateVersion: {\n type: STRING,\n default: null\n },\n keyType: {\n type: STRING,\n default: null\n },\n publicKey: {\n type: TEXT('long'),\n default: null\n }\n }, {\n freezeTableName: true\n });\n\n Certificate.associate = function (db) {\n Certificate.belongsTo(db.Channel, {\n foreignKey: {\n allowNull: true\n }\n });\n };\n\n Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {\n var _this = this;\n\n logger.debug('getShortChannelIdFromLongChannelId ' + channelName + ':' + longChannelId);\n return new Promise(function (resolve, reject) {\n _this.findAll({\n where: { name: channelName },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n throw new Error('No channel(s) found with that channel name');\n default:\n return resolve(returnShortId(result, longChannelId));\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {\n var _this2 = this;\n\n logger.debug('getLongChannelIdFromShortChannelId(' + channelName + ', ' + channelClaimId + ')');\n return new Promise(function (resolve, reject) {\n _this2.findAll({\n where: {\n name: channelName,\n claimId: {\n $like: channelClaimId + '%'\n }\n },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n // note results must be sorted\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromChannelName = function (channelName) {\n var _this3 = this;\n\n logger.debug('getLongChannelIdFromChannelName(' + channelName + ')');\n return new Promise(function (resolve, reject) {\n _this3.findAll({\n where: { name: channelName },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.validateLongChannelId = function (name, claimId) {\n var _this4 = this;\n\n logger.debug('validateLongChannelId(' + name + ', ' + claimId + ')');\n return new Promise(function (resolve, reject) {\n _this4.findOne({\n where: { name: name, claimId: claimId }\n }).then(function (result) {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelId = function (channelName, channelClaimId) {\n logger.debug('getLongChannelId(' + channelName + ', ' + channelClaimId + ')');\n if (channelClaimId && channelClaimId.length === 40) {\n // if a full channel id is provided\n return this.validateLongChannelId(channelName, channelClaimId);\n } else if (channelClaimId && channelClaimId.length < 40) {\n // if a short channel id is provided\n return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId);\n } else {\n return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided\n }\n };\n\n return Certificate;\n};\n\n/***/ }),\n/* 46 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING;\n\n var Channel = sequelize.define('Channel', {\n channelName: {\n type: STRING,\n allowNull: false\n },\n channelClaimId: {\n type: STRING,\n allowNull: false\n }\n }, {\n freezeTableName: true\n });\n\n Channel.associate = function (db) {\n Channel.belongsTo(db.User);\n Channel.hasOne(db.Certificate);\n };\n\n return Channel;\n};\n\n/***/ }),\n/* 47 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(12),\n returnShortId = _require.returnShortId;\n\nvar _require2 = __webpack_require__(3),\n defaultThumbnail = _require2.assetDefaults.thumbnail,\n host = _require2.details.host;\n\nfunction determineFileExtensionFromContentType(contentType) {\n switch (contentType) {\n case 'image/jpeg':\n case 'image/jpg':\n return 'jpeg';\n case 'image/png':\n return 'png';\n case 'image/gif':\n return 'gif';\n case 'video/mp4':\n return 'mp4';\n default:\n logger.debug('setting unknown file type as file extension jpeg');\n return 'jpeg';\n }\n};\n\nfunction determineThumbnail(storedThumbnail, defaultThumbnail) {\n if (storedThumbnail === '') {\n return defaultThumbnail;\n }\n return storedThumbnail;\n};\n\nfunction prepareClaimData(claim) {\n // logger.debug('preparing claim data based on resolved data:', claim);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['host'] = host;\n return claim;\n};\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n INTEGER = _ref.INTEGER,\n TEXT = _ref.TEXT,\n DECIMAL = _ref.DECIMAL;\n\n var Claim = sequelize.define('Claim', {\n address: {\n type: STRING,\n default: null\n },\n amount: {\n type: DECIMAL(19, 8),\n default: null\n },\n claimId: {\n type: STRING,\n default: null\n },\n claimSequence: {\n type: INTEGER,\n default: null\n },\n decodedClaim: {\n type: BOOLEAN,\n default: null\n },\n depth: {\n type: INTEGER,\n default: null\n },\n effectiveAmount: {\n type: DECIMAL(19, 8),\n default: null\n },\n hasSignature: {\n type: BOOLEAN,\n default: null\n },\n height: {\n type: INTEGER,\n default: null\n },\n hex: {\n type: TEXT('long'),\n default: null\n },\n name: {\n type: STRING,\n default: null\n },\n nout: {\n type: INTEGER,\n default: null\n },\n txid: {\n type: STRING,\n default: null\n },\n validAtHeight: {\n type: INTEGER,\n default: null\n },\n outpoint: {\n type: STRING,\n default: null\n },\n claimType: {\n type: STRING,\n default: null\n },\n certificateId: {\n type: STRING,\n default: null\n },\n author: {\n type: STRING,\n default: null\n },\n description: {\n type: TEXT('long'),\n default: null\n },\n language: {\n type: STRING,\n default: null\n },\n license: {\n type: STRING,\n default: null\n },\n licenseUrl: {\n type: STRING,\n default: null\n },\n nsfw: {\n type: BOOLEAN,\n default: null\n },\n preview: {\n type: STRING,\n default: null\n },\n thumbnail: {\n type: STRING,\n default: null\n },\n title: {\n type: STRING,\n default: null\n },\n metadataVersion: {\n type: STRING,\n default: null\n },\n contentType: {\n type: STRING,\n default: null\n },\n source: {\n type: STRING,\n default: null\n },\n sourceType: {\n type: STRING,\n default: null\n },\n sourceVersion: {\n type: STRING,\n default: null\n },\n streamVersion: {\n type: STRING,\n default: null\n },\n valueVersion: {\n type: STRING,\n default: null\n },\n channelName: {\n type: STRING,\n allowNull: true,\n default: null\n }\n }, {\n freezeTableName: true\n });\n\n Claim.associate = function (db) {\n Claim.belongsTo(db.File, {\n foreignKey: {\n allowNull: true\n }\n });\n };\n\n Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {\n var _this = this;\n\n logger.debug('Claim.getShortClaimIdFromLongClaimId for ' + claimName + '#' + claimId);\n return new Promise(function (resolve, reject) {\n _this.findAll({\n where: { name: claimName },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n throw new Error('No claim(s) found with that claim name');\n default:\n resolve(returnShortId(result, claimId));\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getAllChannelClaims = function (channelClaimId) {\n var _this2 = this;\n\n logger.debug('Claim.getAllChannelClaims for ' + channelClaimId);\n return new Promise(function (resolve, reject) {\n _this2.findAll({\n where: { certificateId: channelClaimId },\n order: [['height', 'ASC']],\n raw: true // returns an array of only data, not an array of instances\n }).then(function (channelClaimsArray) {\n // logger.debug('channelclaimsarray length:', channelClaimsArray.length);\n switch (channelClaimsArray.length) {\n case 0:\n return resolve(null);\n default:\n channelClaimsArray.forEach(function (claim) {\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n return claim;\n });\n return resolve(channelClaimsArray);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {\n var _this3 = this;\n\n logger.debug('finding claim id for claim ' + claimName + ' from channel ' + channelClaimId);\n return new Promise(function (resolve, reject) {\n _this3.findAll({\n where: { name: claimName, certificateId: channelClaimId },\n order: [['id', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(result[0].claimId);\n default:\n logger.error(result.length + ' records found for \"' + claimName + '\" in channel \"' + channelClaimId + '\"');\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {\n var _this4 = this;\n\n return new Promise(function (resolve, reject) {\n _this4.findAll({\n where: {\n name: name,\n claimId: {\n $like: shortId + '%'\n } },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n // note results must be sorted\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getTopFreeClaimIdByClaimName = function (name) {\n var _this5 = this;\n\n return new Promise(function (resolve, reject) {\n _this5.findAll({\n where: { name: name },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']] // note: maybe height and effective amount need to switch?\n }).then(function (result) {\n logger.debug('length of result', result.length);\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].dataValues.claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.validateLongClaimId = function (name, claimId) {\n var _this6 = this;\n\n return new Promise(function (resolve, reject) {\n _this6.findOne({\n where: { name: name, claimId: claimId }\n }).then(function (result) {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimId = function (claimName, claimId) {\n logger.debug('getLongClaimId(' + claimName + ', ' + claimId + ')');\n if (claimId && claimId.length === 40) {\n // if a full claim id is provided\n return this.validateLongClaimId(claimName, claimId);\n } else if (claimId && claimId.length < 40) {\n return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided\n } else {\n return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided\n }\n };\n\n Claim.resolveClaim = function (name, claimId) {\n var _this7 = this;\n\n logger.debug('Claim.resolveClaim: ' + name + ' ' + claimId);\n return new Promise(function (resolve, reject) {\n _this7.findAll({\n where: { name: name, claimId: claimId }\n }).then(function (claimArray) {\n switch (claimArray.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(prepareClaimData(claimArray[0].dataValues));\n default:\n logger.error('more than one record matches ' + name + '#' + claimId + ' in db.Claim');\n return resolve(prepareClaimData(claimArray[0].dataValues));\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n return Claim;\n};\n\n/***/ }),\n/* 48 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n INTEGER = _ref.INTEGER;\n\n var File = sequelize.define('File', {\n name: {\n type: STRING,\n allowNull: false\n },\n claimId: {\n type: STRING,\n allowNull: false\n },\n address: {\n type: STRING,\n allowNull: false\n },\n outpoint: {\n type: STRING,\n allowNull: false\n },\n height: {\n type: INTEGER,\n allowNull: false,\n default: 0\n },\n fileName: {\n type: STRING,\n allowNull: false\n },\n filePath: {\n type: STRING,\n allowNull: false\n },\n fileType: {\n type: STRING\n },\n nsfw: {\n type: BOOLEAN,\n allowNull: false,\n defaultValue: false\n },\n trendingEligible: {\n type: BOOLEAN,\n allowNull: false,\n defaultValue: true\n }\n }, {\n freezeTableName: true\n });\n\n File.associate = function (db) {\n File.hasMany(db.Request);\n File.hasOne(db.Claim);\n };\n\n File.getRecentClaims = function () {\n return this.findAll({\n where: { nsfw: false, trendingEligible: true },\n order: [['createdAt', 'DESC']],\n limit: 25\n });\n };\n\n return File;\n};\n\n/***/ }),\n/* 49 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n TEXT = _ref.TEXT;\n\n var Request = sequelize.define('Request', {\n action: {\n type: STRING,\n allowNull: false\n },\n url: {\n type: STRING,\n allowNull: false\n },\n ipAddress: {\n type: STRING,\n allowNull: true\n },\n result: {\n type: TEXT('long'),\n allowNull: true,\n default: null\n }\n }, {\n freezeTableName: true\n });\n\n Request.associate = function (db) {\n Request.belongsTo(db.File, {\n foreignKey: {\n allowNull: true\n }\n });\n };\n\n return Request;\n};\n\n/***/ }),\n/* 50 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar bcrypt = __webpack_require__(51);\nvar logger = __webpack_require__(0);\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING;\n\n var User = sequelize.define('User', {\n userName: {\n type: STRING,\n allowNull: false\n },\n password: {\n type: STRING,\n allowNull: false\n }\n }, {\n freezeTableName: true\n });\n\n User.associate = function (db) {\n User.hasOne(db.Channel);\n };\n\n User.prototype.comparePassword = function (password) {\n return bcrypt.compare(password, this.password);\n };\n\n User.prototype.changePassword = function (newPassword) {\n var _this = this;\n\n return new Promise(function (resolve, reject) {\n // generate a salt string to use for hashing\n bcrypt.genSalt(function (saltError, salt) {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(newPassword, salt, function (hashError, hash) {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the current password with the new hash\n _this.update({ password: hash }).then(function () {\n resolve();\n }).catch(function (error) {\n reject(error);\n });\n });\n });\n });\n };\n\n // pre-save hook method to hash the user's password before the user's info is saved to the db.\n User.hook('beforeCreate', function (user, options) {\n logger.debug('User.beforeCreate hook...');\n return new Promise(function (resolve, reject) {\n // generate a salt string to use for hashing\n bcrypt.genSalt(function (saltError, salt) {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(user.password, salt, function (hashError, hash) {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the password string with the hash password value\n user.password = hash;\n resolve();\n });\n });\n });\n });\n\n return User;\n};\n\n/***/ }),\n/* 51 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"bcrypt\");\n\n/***/ }),\n/* 52 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar PassportLocalStrategy = __webpack_require__(11).Strategy;\nvar lbryApi = __webpack_require__(5);\nvar logger = __webpack_require__(0);\nvar db = __webpack_require__(2);\n\nmodule.exports = new PassportLocalStrategy({\n usernameField: 'username',\n passwordField: 'password'\n}, function (username, password, done) {\n logger.verbose('new channel signup request. user: ' + username + ' pass: ' + password + ' .');\n var userInfo = {};\n // server-side validaton of inputs (username, password)\n\n // create the channel and retrieve the metadata\n return lbryApi.createChannel('@' + username).then(function (tx) {\n // create user record\n var userData = {\n userName: username,\n password: password\n };\n logger.verbose('userData >', userData);\n // create user record\n var channelData = {\n channelName: '@' + username,\n channelClaimId: tx.claim_id\n };\n logger.verbose('channelData >', channelData);\n // create certificate record\n var certificateData = {\n claimId: tx.claim_id,\n name: '@' + username\n // address,\n };\n logger.verbose('certificateData >', certificateData);\n // save user and certificate to db\n return Promise.all([db.User.create(userData), db.Channel.create(channelData), db.Certificate.create(certificateData)]);\n }).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 3),\n newUser = _ref2[0],\n newChannel = _ref2[1],\n newCertificate = _ref2[2];\n\n logger.verbose('user and certificate successfully created');\n // store the relevant newUser info to be passed back for req.User\n userInfo['id'] = newUser.id;\n userInfo['userName'] = newUser.userName;\n userInfo['channelName'] = newChannel.channelName;\n userInfo['channelClaimId'] = newChannel.channelClaimId;\n // associate the instances\n return Promise.all([newCertificate.setChannel(newChannel), newChannel.setUser(newUser)]);\n }).then(function () {\n logger.verbose('user and certificate successfully associated');\n return db.Certificate.getShortChannelIdFromLongChannelId(userInfo.channelClaimId, userInfo.channelName);\n }).then(function (shortChannelId) {\n userInfo['shortChannelId'] = shortChannelId;\n return done(null, userInfo);\n }).catch(function (error) {\n logger.error('signup error', error);\n return done(error);\n });\n});\n\n/***/ }),\n/* 53 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"axios\");\n\n/***/ }),\n/* 54 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar lbryConfig = {\n api: {\n apiHost: 'localhost',\n apiPort: '5279'\n }\n};\n\nmodule.exports = lbryConfig;\n\n/***/ }),\n/* 55 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"universal-analytics\");\n\n/***/ }),\n/* 56 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = {\n serializeSpeechUser: function serializeSpeechUser(user, done) {\n // returns user data to be serialized into session\n console.log('serializing user');\n done(null, user);\n },\n deserializeSpeechUser: function deserializeSpeechUser(user, done) {\n // deserializes session and populates additional info to req.user\n console.log('deserializing user');\n done(null, user);\n }\n};\n\n/***/ }),\n/* 57 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar speechPassport = __webpack_require__(7);\nvar handleSignupRequest = __webpack_require__(58);\nvar handleLoginRequest = __webpack_require__(59);\nvar handleLogoutRequest = __webpack_require__(60);\nvar handleUserRequest = __webpack_require__(61);\n\nmodule.exports = function (app) {\n app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest);\n app.post('/login', handleLoginRequest);\n app.get('/logout', handleLogoutRequest);\n app.get('/user', handleUserRequest);\n};\n\n/***/ }),\n/* 58 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar signup = function signup(req, res) {\n res.status(200).json({\n success: true,\n channelName: req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId\n });\n};\n\nmodule.exports = signup;\n\n/***/ }),\n/* 59 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar speechPassport = __webpack_require__(7);\n\nvar login = function login(req, res, next) {\n speechPassport.authenticate('local-login', function (err, user, info) {\n if (err) {\n return next(err);\n }\n if (!user) {\n return res.status(400).json({\n success: false,\n message: info.message\n });\n }\n req.logIn(user, function (err) {\n if (err) {\n return next(err);\n }\n return res.status(200).json({\n success: true,\n channelName: req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId\n });\n });\n })(req, res, next);\n};\n\nmodule.exports = login;\n\n/***/ }),\n/* 60 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logout = function logout(req, res) {\n req.logout();\n res.status(200).json({ success: true, message: 'you successfully logged out' });\n};\n\nmodule.exports = logout;\n\n/***/ }),\n/* 61 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar user = function user(req, res) {\n if (req.user) {\n res.status(200).json({ success: true, data: req.user });\n } else {\n res.status(401).json({ success: false, message: 'user is not logged in' });\n }\n};\n\nmodule.exports = user;\n\n/***/ }),\n/* 62 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar channelAvailability = __webpack_require__(63);\nvar channelClaims = __webpack_require__(65);\nvar channelData = __webpack_require__(67);\nvar channelShortId = __webpack_require__(68);\nvar claimAvailability = __webpack_require__(69);\nvar claimData = __webpack_require__(70);\nvar claimGet = __webpack_require__(71);\nvar claimLongId = __webpack_require__(72);\nvar claimPublish = __webpack_require__(73);\nvar claimResolve = __webpack_require__(75);\nvar claimShortId = __webpack_require__(76);\nvar claimList = __webpack_require__(77);\nvar fileAvailability = __webpack_require__(78);\n\nvar multipartMiddleware = __webpack_require__(79);\n\nmodule.exports = function (app) {\n // channel routes\n app.get('/api/channel/availability/:name', channelAvailability);\n app.get('/api/channel/short-id/:longId/:name', channelShortId);\n app.get('/api/channel/data/:channelName/:channelClaimId', channelData);\n app.get('/api/channel/claims/:channelName/:channelClaimId/:page', channelClaims);\n // claim routes\n app.get('/api/claim/list/:name', claimList);\n app.get('/api/claim/get/:name/:claimId', claimGet);\n app.get('/api/claim/availability/:name', claimAvailability);\n app.get('/api/claim/resolve/:name/:claimId', claimResolve);\n app.post('/api/claim/publish', multipartMiddleware, claimPublish);\n app.get('/api/claim/short-id/:longId/:name', claimShortId);\n app.post('/api/claim/long-id', claimLongId);\n app.get('/api/claim/data/:claimName/:claimId', claimData);\n // file routes\n app.get('/api/file/availability/:name/:claimId', fileAvailability);\n};\n\n/***/ }),\n/* 63 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(8),\n checkChannelAvailability = _require.checkChannelAvailability;\n\nvar _require2 = __webpack_require__(4),\n sendGATimingEvent = _require2.sendGATimingEvent;\n\nvar _require3 = __webpack_require__(1),\n handleErrorResponse = _require3.handleErrorResponse;\n\n/*\n\n route to check whether site has published to a channel\n\n*/\n\nvar channelAvailability = function channelAvailability(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n name = _ref.params.name;\n\n var gaStartTime = Date.now();\n checkChannelAvailability(name).then(function (availableName) {\n res.status(200).json(availableName);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelAvailability;\n\n/***/ }),\n/* 64 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"fs\");\n\n/***/ }),\n/* 65 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(6),\n getChannelClaims = _require.getChannelClaims;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get all claims for channel\n\n*/\n\nvar channelClaims = function channelClaims(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var channelName = params.channelName;\n var channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n var page = params.page;\n getChannelClaims(channelName, channelClaimId, page).then(function (data) {\n if (data === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'No matching channel was found' });\n }\n res.status(200).json({ success: true, data: data });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelClaims;\n\n/***/ }),\n/* 66 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar CLAIMS_PER_PAGE = 12;\n\nmodule.exports = {\n returnPaginatedChannelClaims: function returnPaginatedChannelClaims(channelName, longChannelClaimId, claims, page) {\n var totalPages = module.exports.determineTotalPages(claims);\n var paginationPage = module.exports.getPageFromQuery(page);\n var viewData = {\n channelName: channelName,\n longChannelClaimId: longChannelClaimId,\n claims: module.exports.extractPageFromClaims(claims, paginationPage),\n previousPage: module.exports.determinePreviousPage(paginationPage),\n currentPage: paginationPage,\n nextPage: module.exports.determineNextPage(totalPages, paginationPage),\n totalPages: totalPages,\n totalResults: module.exports.determineTotalClaims(claims)\n };\n return viewData;\n },\n getPageFromQuery: function getPageFromQuery(page) {\n if (page) {\n return parseInt(page);\n }\n return 1;\n },\n extractPageFromClaims: function extractPageFromClaims(claims, pageNumber) {\n if (!claims) {\n return []; // if no claims, return this default\n }\n // logger.debug('claims is array?', Array.isArray(claims));\n // logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber));\n var claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE;\n var claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE;\n var pageOfClaims = claims.slice(claimStartIndex, claimEndIndex);\n return pageOfClaims;\n },\n determineTotalPages: function determineTotalPages(claims) {\n if (!claims) {\n return 0;\n } else {\n var totalClaims = claims.length;\n if (totalClaims < CLAIMS_PER_PAGE) {\n return 1;\n }\n var fullPages = Math.floor(totalClaims / CLAIMS_PER_PAGE);\n var remainder = totalClaims % CLAIMS_PER_PAGE;\n if (remainder === 0) {\n return fullPages;\n }\n return fullPages + 1;\n }\n },\n determinePreviousPage: function determinePreviousPage(currentPage) {\n if (currentPage === 1) {\n return null;\n }\n return currentPage - 1;\n },\n determineNextPage: function determineNextPage(totalPages, currentPage) {\n if (currentPage === totalPages) {\n return null;\n }\n return currentPage + 1;\n },\n determineTotalClaims: function determineTotalClaims(claims) {\n if (!claims) {\n return 0;\n }\n return claims.length;\n }\n};\n\n/***/ }),\n/* 67 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(6),\n getChannelData = _require.getChannelData;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get data for a channel\n\n*/\n\nvar channelData = function channelData(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var channelName = params.channelName;\n var channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n getChannelData(channelName, channelClaimId, 0).then(function (data) {\n if (data === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'No matching channel was found' });\n }\n res.status(200).json({ success: true, data: data });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelData;\n\n/***/ }),\n/* 68 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\nroute to get a short channel id from long channel Id\n\n*/\n\nvar channelShortIdRoute = function channelShortIdRoute(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name).then(function (shortId) {\n res.status(200).json(shortId);\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelShortIdRoute;\n\n/***/ }),\n/* 69 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(8),\n claimNameIsAvailable = _require.claimNameIsAvailable;\n\nvar _require2 = __webpack_require__(4),\n sendGATimingEvent = _require2.sendGATimingEvent;\n\nvar _require3 = __webpack_require__(1),\n handleErrorResponse = _require3.handleErrorResponse;\n\n/*\n\n route to check whether this site published to a claim\n\n*/\n\nvar claimAvailability = function claimAvailability(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n name = _ref.params.name;\n\n var gaStartTime = Date.now();\n claimNameIsAvailable(name).then(function (result) {\n res.status(200).json(result);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimAvailability;\n\n/***/ }),\n/* 70 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to return data for a claim\n\n*/\n\nvar claimData = function claimData(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var claimName = params.claimName;\n var claimId = params.claimId;\n if (claimId === 'none') claimId = null;\n db.Claim.resolveClaim(claimName, claimId).then(function (claimInfo) {\n if (!claimInfo) {\n return res.status(404).json({ success: false, message: 'No claim could be found' });\n }\n res.status(200).json({ success: true, data: claimInfo });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimData;\n\n/***/ }),\n/* 71 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar _require = __webpack_require__(5),\n getClaim = _require.getClaim;\n\nvar _require2 = __webpack_require__(9),\n addGetResultsToFileData = _require2.addGetResultsToFileData,\n createFileData = _require2.createFileData;\n\nvar _require3 = __webpack_require__(1),\n handleErrorResponse = _require3.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to get a claim\n\n*/\n\nvar claimGet = function claimGet(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n var name = params.name;\n var claimId = params.claimId;\n // resolve the claim\n db.Claim.resolveClaim(name, claimId).then(function (resolveResult) {\n // make sure a claim actually exists at that uri\n if (!resolveResult) {\n throw new Error('No matching uri found in Claim table');\n }\n var fileData = createFileData(resolveResult);\n // get the claim\n return Promise.all([fileData, getClaim(name + '#' + claimId)]);\n }).then(function (_ref2) {\n var _ref3 = _slicedToArray(_ref2, 2),\n fileData = _ref3[0],\n getResult = _ref3[1];\n\n fileData = addGetResultsToFileData(fileData, getResult);\n return Promise.all([db.upsert(db.File, fileData, { name: name, claimId: claimId }, 'File'), getResult]);\n }).then(function (_ref4) {\n var _ref5 = _slicedToArray(_ref4, 2),\n fileRecord = _ref5[0],\n _ref5$ = _ref5[1],\n message = _ref5$.message,\n completed = _ref5$.completed;\n\n res.status(200).json({ success: true, message: message, completed: completed });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimGet;\n\n/***/ }),\n/* 72 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(6),\n getClaimId = _require.getClaimId;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\nvar NO_CLAIM = 'NO_CLAIM';\n\n/*\n\n route to get a long claim id\n\n*/\n\nvar claimLongId = function claimLongId(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var channelName = body.channelName;\n var channelClaimId = body.channelClaimId;\n var claimName = body.claimName;\n var claimId = body.claimId;\n getClaimId(channelName, channelClaimId, claimName, claimId).then(function (result) {\n if (result === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'No matching channel could be found' });\n }\n if (result === NO_CLAIM) {\n return res.status(404).json({ success: false, message: 'No matching claim id could be found' });\n }\n res.status(200).json({ success: true, data: result });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimLongId;\n\n/***/ }),\n/* 73 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar _require = __webpack_require__(9),\n createBasicPublishParams = _require.createBasicPublishParams,\n createThumbnailPublishParams = _require.createThumbnailPublishParams,\n parsePublishApiRequestBody = _require.parsePublishApiRequestBody,\n parsePublishApiRequestFiles = _require.parsePublishApiRequestFiles;\n\nvar _require2 = __webpack_require__(8),\n claimNameIsAvailable = _require2.claimNameIsAvailable,\n publish = _require2.publish;\n\nvar _require3 = __webpack_require__(74),\n authenticateUser = _require3.authenticateUser;\n\nvar _require4 = __webpack_require__(4),\n sendGATimingEvent = _require4.sendGATimingEvent;\n\nvar _require5 = __webpack_require__(1),\n handleErrorResponse = _require5.handleErrorResponse;\n\nvar _require6 = __webpack_require__(3),\n host = _require6.details.host;\n\n/*\n\n route to publish a claim through the daemon\n\n*/\n\nvar claimPublish = function claimPublish(_ref, res) {\n var body = _ref.body,\n files = _ref.files,\n headers = _ref.headers,\n ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n user = _ref.user;\n\n // define variables\n var channelName = void 0,\n channelId = void 0,\n channelPassword = void 0,\n description = void 0,\n fileName = void 0,\n filePath = void 0,\n fileType = void 0,\n gaStartTime = void 0,\n license = void 0,\n name = void 0,\n nsfw = void 0,\n thumbnail = void 0,\n thumbnailFileName = void 0,\n thumbnailFilePath = void 0,\n thumbnailFileType = void 0,\n title = void 0;\n // record the start time of the request\n gaStartTime = Date.now();\n // validate the body and files of the request\n try {\n var _parsePublishApiReque = parsePublishApiRequestBody(body);\n // validateApiPublishRequest(body, files);\n\n\n name = _parsePublishApiReque.name;\n nsfw = _parsePublishApiReque.nsfw;\n license = _parsePublishApiReque.license;\n title = _parsePublishApiReque.title;\n description = _parsePublishApiReque.description;\n thumbnail = _parsePublishApiReque.thumbnail;\n\n var _parsePublishApiReque2 = parsePublishApiRequestFiles(files);\n\n fileName = _parsePublishApiReque2.fileName;\n filePath = _parsePublishApiReque2.filePath;\n fileType = _parsePublishApiReque2.fileType;\n thumbnailFileName = _parsePublishApiReque2.thumbnailFileName;\n thumbnailFilePath = _parsePublishApiReque2.thumbnailFilePath;\n thumbnailFileType = _parsePublishApiReque2.thumbnailFileType;\n channelName = body.channelName;\n channelId = body.channelId;\n channelPassword = body.channelPassword;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n // check channel authorization\n 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) {\n var _ref3 = _slicedToArray(_ref2, 4),\n _ref3$ = _ref3[0],\n channelName = _ref3$.channelName,\n channelClaimId = _ref3$.channelClaimId,\n validatedClaimName = _ref3[1],\n publishParams = _ref3[2],\n thumbnailPublishParams = _ref3[3];\n\n // add channel details to the publish params\n if (channelName && channelClaimId) {\n publishParams['channel_name'] = channelName;\n publishParams['channel_id'] = channelClaimId;\n }\n // publish the thumbnail\n if (thumbnailPublishParams) {\n publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);\n }\n // publish the asset\n return publish(publishParams, fileName, fileType);\n }).then(function (result) {\n res.status(200).json({\n success: true,\n message: 'publish completed successfully',\n data: {\n name: name,\n claimId: result.claim_id,\n url: host + '/' + result.claim_id + '/' + name,\n lbryTx: result\n }\n });\n // record the publish end time and send to google analytics\n sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimPublish;\n\n/***/ }),\n/* 74 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar db = __webpack_require__(2);\nvar logger = __webpack_require__(0);\n\nmodule.exports = {\n authenticateUser: function authenticateUser(channelName, channelId, channelPassword, user) {\n // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided\n if (!channelName && !channelId) {\n return {\n channelName: null,\n channelClaimId: null\n };\n }\n // case: channelName or channel Id are provided with user token\n if (user) {\n if (channelName && channelName !== user.channelName) {\n throw new Error('the provided channel name does not match user credentials');\n }\n if (channelId && channelId !== user.channelClaimId) {\n throw new Error('the provided channel id does not match user credentials');\n }\n return {\n channelName: user.channelName,\n channelClaimId: user.channelClaimId\n };\n }\n // case: channelName or channel Id are provided with password instead of user token\n if (!channelPassword) throw new Error('no channel password provided');\n return module.exports.authenticateChannelCredentials(channelName, channelId, channelPassword);\n },\n authenticateChannelCredentials: function authenticateChannelCredentials(channelName, channelId, userPassword) {\n return new Promise(function (resolve, reject) {\n // hoisted variables\n var channelData = void 0;\n // build the params for finding the channel\n var channelFindParams = {};\n if (channelName) channelFindParams['channelName'] = channelName;\n if (channelId) channelFindParams['channelClaimId'] = channelId;\n // find the channel\n db.Channel.findOne({\n where: channelFindParams\n }).then(function (channel) {\n if (!channel) {\n logger.debug('no channel found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n channelData = channel.get();\n logger.debug('channel data:', channelData);\n return db.User.findOne({\n where: { userName: channelData.channelName.substring(1) }\n });\n }).then(function (user) {\n if (!user) {\n logger.debug('no user found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n return user.comparePassword(userPassword);\n }).then(function (isMatch) {\n if (!isMatch) {\n logger.debug('incorrect password');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n logger.debug('...password was a match...');\n resolve(channelData);\n }).catch(function (error) {\n reject(error);\n });\n });\n }\n};\n\n/***/ }),\n/* 75 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(5),\n resolveUri = _require.resolveUri;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\n/*\n\n route to run a resolve request on the daemon\n\n*/\n\nvar claimResolve = function claimResolve(_ref, res) {\n var headers = _ref.headers,\n ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n resolveUri(params.name + '#' + params.claimId).then(function (resolvedUri) {\n res.status(200).json(resolvedUri);\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimResolve;\n\n/***/ }),\n/* 76 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to get a short claim id from long claim Id\n\n*/\n\nvar claimShortId = function claimShortId(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name).then(function (shortId) {\n res.status(200).json({ success: true, data: shortId });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimShortId;\n\n/***/ }),\n/* 77 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(5),\n getClaimList = _require.getClaimList;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\n/*\n\n route to get list of claims\n\n*/\n\nvar claimList = function claimList(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n getClaimList(params.name).then(function (claimsList) {\n res.status(200).json(claimsList);\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimList;\n\n/***/ }),\n/* 78 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to see if asset is available locally\n\n*/\n\nvar fileAvailability = function fileAvailability(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n var name = params.name;\n var claimId = params.claimId;\n db.File.findOne({\n where: {\n name: name,\n claimId: claimId\n }\n }).then(function (result) {\n if (result) {\n return res.status(200).json({ success: true, data: true });\n }\n res.status(200).json({ success: true, data: false });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = fileAvailability;\n\n/***/ }),\n/* 79 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar multipart = __webpack_require__(80);\n\nvar _require = __webpack_require__(3),\n uploadDirectory = _require.publishing.uploadDirectory;\n\nvar multipartMiddleware = multipart({ uploadDir: uploadDirectory });\n\nmodule.exports = multipartMiddleware;\n\n/***/ }),\n/* 80 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"connect-multiparty\");\n\n/***/ }),\n/* 81 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRequest = __webpack_require__(82);\nvar handleEmbedRequest = __webpack_require__(83);\nvar redirect = __webpack_require__(84);\n\nmodule.exports = function (app) {\n app.get('/', handlePageRequest);\n app.get('/login', handlePageRequest);\n app.get('/about', handlePageRequest);\n app.get('/trending', redirect('/popular'));\n app.get('/popular', handlePageRequest);\n app.get('/new', handlePageRequest);\n app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)\n};\n\n/***/ }),\n/* 82 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRender = __webpack_require__(14);\n\nvar sendReactApp = function sendReactApp(req, res) {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n/***/ }),\n/* 83 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(3),\n host = _require.details.host;\n\nvar sendEmbedPage = function sendEmbedPage(_ref, res) {\n var params = _ref.params;\n\n var claimId = params.claimId;\n var name = params.name;\n // get and render the content\n res.status(200).render('embed', { layout: 'embed', host: host, claimId: claimId, name: name });\n};\n\nmodule.exports = sendEmbedPage;\n\n/***/ }),\n/* 84 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar redirect = function redirect(route) {\n return function (req, res) {\n res.status(301).redirect(route);\n };\n};\n\nmodule.exports = redirect;\n\n/***/ }),\n/* 85 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar serveAssetByClaim = __webpack_require__(86);\nvar serveAssetByIdentifierAndClaim = __webpack_require__(89);\n\nmodule.exports = function (app, db) {\n app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);\n app.get('/:claim', serveAssetByClaim);\n};\n\n/***/ }),\n/* 86 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(4),\n sendGAServeEvent = _require.sendGAServeEvent;\n\nvar _require2 = __webpack_require__(23),\n determineResponseType = _require2.determineResponseType,\n logRequestData = _require2.logRequestData,\n getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;\n\nvar lbryUri = __webpack_require__(24);\nvar handleShowRender = __webpack_require__(25);\nvar SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name only\n\n*/\n\nvar serverAssetByClaim = function serverAssetByClaim(req, res) {\n var headers = req.headers,\n ip = req.ip,\n originalUrl = req.originalUrl,\n params = req.params;\n // decide if this is a show request\n\n var hasFileExtension = void 0;\n try {\n var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);\n\n hasFileExtension = _lbryUri$parseModifie.hasFileExtension;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n var responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n var claimName = void 0;\n try {\n var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);\n\n claimName = _lbryUri$parseClaim.claimName;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, null, null);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByClaim;\n\n/***/ }),\n/* 87 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"redux-saga\");\n\n/***/ }),\n/* 88 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"redux-saga/effects\");\n\n/***/ }),\n/* 89 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar _require = __webpack_require__(4),\n sendGAServeEvent = _require.sendGAServeEvent;\n\nvar _require2 = __webpack_require__(23),\n determineResponseType = _require2.determineResponseType,\n flipClaimNameAndIdForBackwardsCompatibility = _require2.flipClaimNameAndIdForBackwardsCompatibility,\n logRequestData = _require2.logRequestData,\n getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;\n\nvar lbryUri = __webpack_require__(24);\nvar handleShowRender = __webpack_require__(25);\n\nvar SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name and an identifier\n\n*/\n\nvar serverAssetByIdentifierAndClaim = function serverAssetByIdentifierAndClaim(req, res) {\n var headers = req.headers,\n ip = req.ip,\n originalUrl = req.originalUrl,\n params = req.params;\n // decide if this is a show request\n\n var hasFileExtension = void 0;\n try {\n var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);\n\n hasFileExtension = _lbryUri$parseModifie.hasFileExtension;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n var responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n var claimName = void 0;\n try {\n var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);\n\n claimName = _lbryUri$parseClaim.claimName;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n // parse the identifier\n var isChannel = void 0,\n channelName = void 0,\n channelClaimId = void 0,\n claimId = void 0;\n try {\n var _lbryUri$parseIdentif = lbryUri.parseIdentifier(params.identifier);\n\n isChannel = _lbryUri$parseIdentif.isChannel;\n channelName = _lbryUri$parseIdentif.channelName;\n channelClaimId = _lbryUri$parseIdentif.channelClaimId;\n claimId = _lbryUri$parseIdentif.claimId;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n if (!isChannel) {\n var _flipClaimNameAndIdFo = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);\n\n var _flipClaimNameAndIdFo2 = _slicedToArray(_flipClaimNameAndIdFo, 2);\n\n claimId = _flipClaimNameAndIdFo2[0];\n claimName = _flipClaimNameAndIdFo2[1];\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, channelName, claimId);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByIdentifierAndClaim;\n\n/***/ }),\n/* 90 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRequest = __webpack_require__(91);\n\nmodule.exports = function (app) {\n app.get('*', handlePageRequest);\n};\n\n/***/ }),\n/* 91 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRender = __webpack_require__(14);\n\nvar sendReactApp = function sendReactApp(req, res) {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// index.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 26);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 997e9b26fb4c0319bb2a","module.exports = require(\"winston\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"winston\"\n// module id = 0\n// module chunks = 0","const logger = require('winston');\n\nmodule.exports = {\n handleErrorResponse: function (originalUrl, ip, error, res) {\n logger.error(`Error on ${originalUrl}`, module.exports.useObjectPropertiesIfNoKeys(error));\n const [status, message] = module.exports.returnErrorMessageAndStatus(error);\n res\n .status(status)\n .json(module.exports.createErrorResponsePayload(status, message));\n },\n returnErrorMessageAndStatus: function (error) {\n let status, message;\n // check for daemon being turned off\n if (error.code === 'ECONNREFUSED') {\n status = 503;\n message = 'Connection refused. The daemon may not be running.';\n // fallback for everything else\n } else {\n status = 400;\n if (error.message) {\n message = error.message;\n } else {\n message = error;\n };\n };\n return [status, message];\n },\n useObjectPropertiesIfNoKeys: function (err) {\n if (Object.keys(err).length === 0) {\n let newErrorObject = {};\n Object.getOwnPropertyNames(err).forEach((key) => {\n newErrorObject[key] = err[key];\n });\n return newErrorObject;\n }\n return err;\n },\n createErrorResponsePayload (status, message) {\n return {\n status,\n success: false,\n message,\n };\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/errorHandlers.js","const Certificate = require('models/certificate.js');\nconst Channel = require('models/channel.js');\nconst Claim = require('models/claim.js');\nconst File = require('models/file.js');\nconst Request = require('models/request.js');\nconst User = require('models/user.js');\n\nconst Sequelize = require('sequelize');\nconst logger = require('winston');\n\nconst {database, username, password} = require('mysqlConfig.js');\n\n// set sequelize options\nconst sequelize = new Sequelize(database, username, password, {\n host : 'localhost',\n dialect : 'mysql',\n dialectOptions: {decimalNumbers: true},\n logging : false,\n pool : {\n max : 5,\n min : 0,\n idle : 10000,\n acquire: 10000,\n },\n});\n\n// establish mysql connection\nsequelize\n .authenticate()\n .then(() => {\n logger.info('Sequelize has established mysql connection successfully.');\n })\n .catch(err => {\n logger.error('Sequelize was unable to connect to the database:', err);\n });\n\n// manually add each model to the db object (note: make this dynamic)\nconst db = {};\ndb['Certificate'] = sequelize.import('Certificate', Certificate);\ndb['Channel'] = sequelize.import('Channel', Channel);\ndb['Claim'] = sequelize.import('Claim', Claim);\ndb['File'] = sequelize.import('File', File);\ndb['Request'] = sequelize.import('Request', Request);\ndb['User'] = sequelize.import('User', User);\n\n// run model.association for each model in the db object that has an association\nlogger.info('associating db models...');\nObject.keys(db).forEach(modelName => {\n if (db[modelName].associate) {\n logger.info('Associating model:', modelName);\n db[modelName].associate(db);\n }\n});\n\n// add sequelize/Sequelize to db\ndb.sequelize = sequelize;\ndb.Sequelize = Sequelize;\n// add an 'upsert' method to the db object\ndb.upsert = (Model, values, condition, tableName) => {\n return Model\n .findOne({\n where: condition,\n })\n .then(obj => {\n if (obj) { // update\n logger.debug(`updating record in db.${tableName}`);\n return obj.update(values);\n } else { // insert\n logger.debug(`creating record in db.${tableName}`);\n return Model.create(values);\n }\n })\n .catch(function (error) {\n logger.error(`${tableName}.upsert error`, error);\n throw error;\n });\n};\n\nmodule.exports = db;\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/index.js","function SiteConfig () {\n this.analytics = {\n googleId: 'default',\n };\n this.assetDefaults = {\n description: 'An asset published on Spee.ch',\n thumbnail : 'https://spee.ch/assets/img/video_thumb_default.png',\n title : 'Spee.ch',\n };\n this.auth = {\n sessionKey: 'default',\n };\n this.customComponents = {\n components: {},\n containers: {},\n pages : {},\n };\n this.details = {\n description: 'Open-source, decentralized image and video sharing.',\n host : 'default',\n port : 3000,\n title : 'Spee.ch',\n twitter : '@spee_ch',\n };\n this.publishing = {\n additionalClaimAddresses: [],\n disabled : false,\n disabledMessage : 'Please check back soon.',\n primaryClaimAddress : 'default',\n thumbnailChannel : 'default',\n thumbnailChannelId : 'default',\n uploadDirectory : '/home/lbry/Uploads',\n };\n this.routes = {};\n this.update = (config) => {\n if (!config) {\n return console.log('No site config received.');\n }\n const { analytics, assetDefaults, auth, customComponents, details, publishing, routes } = config;\n console.log('Configuring site details...');\n this.analytics = analytics;\n this.assetDefaults = assetDefaults;\n this.auth = auth;\n this.details = details;\n this.publishing = publishing;\n this.customComponents = customComponents;\n this.routes = routes;\n };\n};\n\nmodule.exports = new SiteConfig();\n\n\n\n// WEBPACK FOOTER //\n// ./config/siteConfig.js","const logger = require('winston');\nconst ua = require('universal-analytics');\nconst { analytics : { googleId }, details: { title } } = require('../../config/siteConfig.js');\n\nfunction createServeEventParams (headers, ip, originalUrl) {\n return {\n eventCategory : 'client requests',\n eventAction : 'serve request',\n eventLabel : originalUrl,\n ipOverride : ip,\n userAgentOverride: headers['user-agent'],\n };\n};\n\nfunction createPublishTimingEventParams (category, variable, label, startTime, endTime) {\n const duration = endTime - startTime;\n return {\n userTimingCategory : category,\n userTimingVariableName: variable,\n userTimingTime : duration,\n userTimingLabel : label,\n };\n};\n\nfunction sendGoogleAnalyticsEvent (ip, params) {\n const visitorId = ip.replace(/\\./g, '-');\n const visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.event(params, (err) => {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n });\n};\n\nfunction sendGoogleAnalyticsTiming (visitorId, params) {\n const visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.timing(params, (err) => {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n logger.debug(`Timing event successfully sent to google analytics`);\n });\n};\n\nmodule.exports = {\n sendGAServeEvent (headers, ip, originalUrl) {\n const params = createServeEventParams(headers, ip, originalUrl);\n sendGoogleAnalyticsEvent(ip, params);\n },\n sendGATimingEvent (category, variable, label, startTime, endTime) {\n const params = createPublishTimingEventParams(category, variable, label, startTime, endTime);\n sendGoogleAnalyticsTiming(title, params);\n },\n chooseGaLbrynetPublishLabel ({ channel_name: channelName, channel_id: channelId }) {\n return (channelName || channelId ? 'PUBLISH_IN_CHANNEL_CLAIM' : 'PUBLISH_ANONYMOUS_CLAIM');\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/googleAnalytics.js","const axios = require('axios');\nconst logger = require('winston');\nconst { api: { apiHost, apiPort } } = require('../../config/lbryConfig.js');\nconst lbryApiUri = 'http://' + apiHost + ':' + apiPort;\nconst { chooseGaLbrynetPublishLabel, sendGATimingEvent } = require('./googleAnalytics.js');\n\nconst handleLbrynetResponse = ({ data }, resolve, reject) => {\n logger.debug('lbry api data:', data);\n if (data.result) {\n // check for an error\n if (data.result.error) {\n logger.debug('Lbrynet api error:', data.result.error);\n reject(new Error(data.result.error));\n return;\n };\n resolve(data.result);\n return;\n }\n // fallback in case it just timed out\n reject(JSON.stringify(data));\n};\n\nmodule.exports = {\n publishClaim (publishParams) {\n logger.debug(`lbryApi >> Publishing claim to \"${publishParams.name}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'publish',\n params: publishParams,\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getClaim (uri) {\n logger.debug(`lbryApi >> Getting Claim for \"${uri}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'get',\n params: { uri, timeout: 20 },\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'getClaim', 'GET', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getClaimList (claimName) {\n logger.debug(`lbryApi >> Getting claim_list for \"${claimName}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'claim_list',\n params: { name: claimName },\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'getClaimList', 'CLAIM_LIST', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n resolveUri (uri) {\n logger.debug(`lbryApi >> Resolving URI for \"${uri}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'resolve',\n params: { uri },\n })\n .then(({ data }) => {\n sendGATimingEvent('lbrynet', 'resolveUri', 'RESOLVE', gaStartTime, Date.now());\n if (data.result[uri].error) { // check for errors\n reject(data.result[uri].error);\n } else { // if no errors, resolve\n resolve(data.result[uri]);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getDownloadDirectory () {\n logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...');\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'settings_get',\n })\n .then(({ data }) => {\n sendGATimingEvent('lbrynet', 'getDownloadDirectory', 'SETTINGS_GET', gaStartTime, Date.now());\n if (data.result) {\n resolve(data.result.download_directory);\n } else {\n return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.');\n }\n })\n .catch(error => {\n logger.error('Lbrynet Error:', error);\n resolve('/home/lbry/Downloads/');\n });\n });\n },\n createChannel (name) {\n logger.debug(`lbryApi >> Creating channel for ${name}...`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'channel_new',\n params: {\n channel_name: name,\n amount : 0.1,\n },\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'createChannel', 'CHANNEL_NEW', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/lbryApi.js","const db = require('models');\nconst logger = require('winston');\nconst { returnPaginatedChannelClaims } = require('helpers/channelPagination.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\nconst NO_CLAIM = 'NO_CLAIM';\nconst NO_FILE = 'NO_FILE';\n\nmodule.exports = {\n getClaimId (channelName, channelClaimId, name, claimId) {\n if (channelName) {\n return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);\n } else {\n return module.exports.getClaimIdByClaim(name, claimId);\n }\n },\n getClaimIdByClaim (claimName, claimId) {\n logger.debug(`getClaimIdByClaim(${claimName}, ${claimId})`);\n return new Promise((resolve, reject) => {\n db.Claim.getLongClaimId(claimName, claimId)\n .then(longClaimId => {\n if (!longClaimId) {\n resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getClaimIdByChannel (channelName, channelClaimId, claimName) {\n logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`);\n return new Promise((resolve, reject) => {\n db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id\n .then(longChannelId => {\n if (!longChannelId) {\n return [null, null];\n }\n return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id\n })\n .then(([longChannelId, longClaimId]) => {\n if (!longChannelId) {\n return resolve(NO_CHANNEL);\n }\n if (!longClaimId) {\n return resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getChannelData (channelName, channelClaimId, page) {\n return new Promise((resolve, reject) => {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId)\n .then(longChannelClaimId => {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]);\n })\n .then(([longChannelClaimId, shortChannelClaimId]) => {\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. return all the channel information\n resolve({\n channelName,\n longChannelClaimId,\n shortChannelClaimId,\n });\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getChannelClaims (channelName, channelClaimId, page) {\n return new Promise((resolve, reject) => {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId)\n .then(longChannelClaimId => {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]);\n })\n .then(([longChannelClaimId, channelClaimsArray]) => {\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. format the data for the view, including pagination\n let paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page);\n // 4. return all the channel information and contents\n resolve(paginatedChannelViewData);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getLocalFileRecord (claimId, name) {\n return db.File.findOne({where: {claimId, name}})\n .then(file => {\n if (!file) {\n return NO_FILE;\n }\n return file.dataValues;\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/controllers/serveController.js","const passport = require('passport');\nconst localLoginStrategy = require('./local-login.js');\nconst localSignupStrategy = require('./local-signup.js');\nconst { serializeSpeechUser, deserializeSpeechUser } = require('helpers/authHelpers.js');\n\npassport.deserializeUser(deserializeSpeechUser);\npassport.serializeUser(serializeSpeechUser);\npassport.use('local-login', localLoginStrategy);\npassport.use('local-signup', localSignupStrategy);\n\nmodule.exports = passport;\n\n\n\n// WEBPACK FOOTER //\n// ./server/speechPassport/index.js","const logger = require('winston');\nconst db = require('models');\nconst lbryApi = require('helpers/lbryApi.js');\nconst publishHelpers = require('helpers/publishHelpers.js');\nconst { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('siteConfig.js');\nconst Sequelize = require('sequelize');\nconst Op = Sequelize.Op;\n\nmodule.exports = {\n publish (publishParams, fileName, fileType) {\n return new Promise((resolve, reject) => {\n let publishResults, certificateId, channelName;\n // publish the file\n return lbryApi.publishClaim(publishParams)\n .then(tx => {\n logger.info(`Successfully published ${publishParams.name} ${fileName}`, tx);\n publishResults = tx;\n // get the channel information\n if (publishParams.channel_name) {\n logger.debug(`this claim was published in channel: ${publishParams.channel_name}`);\n return db.Channel.findOne({\n where: {\n channelName: publishParams.channel_name,\n },\n });\n } else {\n logger.debug('this claim was not published in a channel');\n return null;\n }\n })\n .then(channel => {\n // set channel information\n certificateId = null;\n channelName = null;\n if (channel) {\n certificateId = channel.channelClaimId;\n channelName = channel.channelName;\n }\n logger.debug(`certificateId: ${certificateId}`);\n })\n .then(() => {\n // create the File record\n const fileRecord = {\n name : publishParams.name,\n claimId : publishResults.claim_id,\n title : publishParams.metadata.title,\n description: publishParams.metadata.description,\n address : publishParams.claim_address,\n outpoint : `${publishResults.txid}:${publishResults.nout}`,\n height : 0,\n fileName,\n filePath : publishParams.file_path,\n fileType,\n nsfw : publishParams.metadata.nsfw,\n };\n // create the Claim record\n const claimRecord = {\n name : publishParams.name,\n claimId : publishResults.claim_id,\n title : publishParams.metadata.title,\n description: publishParams.metadata.description,\n address : publishParams.claim_address,\n thumbnail : publishParams.metadata.thumbnail,\n outpoint : `${publishResults.txid}:${publishResults.nout}`,\n height : 0,\n contentType: fileType,\n nsfw : publishParams.metadata.nsfw,\n amount : publishParams.bid,\n certificateId,\n channelName,\n };\n // upsert criteria\n const upsertCriteria = {\n name : publishParams.name,\n claimId: publishResults.claim_id,\n };\n // upsert the records\n return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]);\n })\n .then(([file, claim]) => {\n logger.debug('File and Claim records successfully created');\n return Promise.all([file.setClaim(claim), claim.setFile(file)]);\n })\n .then(() => {\n logger.debug('File and Claim records successfully associated');\n resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim;\n })\n .catch(error => {\n logger.error('PUBLISH ERROR', error);\n publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file\n reject(error);\n });\n });\n },\n claimNameIsAvailable (name) {\n const claimAddresses = additionalClaimAddresses || [];\n claimAddresses.push(primaryClaimAddress);\n // find any records where the name is used\n return db.Claim\n .findAll({\n attributes: ['address'],\n where : {\n name,\n address: {\n [Op.or]: claimAddresses,\n },\n },\n })\n .then(result => {\n if (result.length >= 1) {\n throw new Error('That claim is already in use');\n };\n return name;\n })\n .catch(error => {\n throw error;\n });\n },\n checkChannelAvailability (name) {\n return db.Channel\n .findAll({\n where: { channelName: name },\n })\n .then(result => {\n if (result.length >= 1) {\n throw new Error('That channel has already been claimed');\n }\n return name;\n })\n .catch(error => {\n throw error;\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/controllers/publishController.js","const logger = require('winston');\nconst fs = require('fs');\n\nconst { details, publishing } = require('../../config/siteConfig.js');\n\nmodule.exports = {\n parsePublishApiRequestBody ({name, nsfw, license, title, description, thumbnail}) {\n // validate name\n if (!name) {\n throw new Error('no name field found in request');\n }\n const invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name);\n if (invalidNameCharacters) {\n throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and \"-\"');\n }\n // optional parameters\n nsfw = (nsfw === 'true');\n license = license || null;\n title = title || null;\n description = description || null;\n thumbnail = thumbnail || null;\n // return results\n return {\n name,\n nsfw,\n license,\n title,\n description,\n thumbnail,\n };\n },\n parsePublishApiRequestFiles ({file, thumbnail}) {\n // make sure a file was provided\n if (!file) {\n throw new Error('no file with key of [file] found in request');\n }\n if (!file.path) {\n throw new Error('no file path found');\n }\n if (!file.type) {\n throw new Error('no file type found');\n }\n if (!file.size) {\n throw new Error('no file type found');\n }\n // validate the file name\n if (/'/.test(file.name)) {\n throw new Error('apostrophes are not allowed in the file name');\n }\n // validate the file\n module.exports.validateFileTypeAndSize(file);\n // return results\n return {\n fileName : file.name,\n filePath : file.path,\n fileType : file.type,\n thumbnailFileName: (thumbnail ? thumbnail.name : null),\n thumbnailFilePath: (thumbnail ? thumbnail.path : null),\n thumbnailFileType: (thumbnail ? thumbnail.type : null),\n };\n },\n validateFileTypeAndSize (file) {\n // check file type and size\n switch (file.type) {\n case 'image/jpeg':\n case 'image/jpg':\n case 'image/png':\n if (file.size > 10000000) {\n logger.debug('publish > file validation > .jpeg/.jpg/.png was too big');\n throw new Error('Sorry, images are limited to 10 megabytes.');\n }\n break;\n case 'image/gif':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .gif was too big');\n throw new Error('Sorry, .gifs are limited to 50 megabytes.');\n }\n break;\n case 'video/mp4':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .mp4 was too big');\n throw new Error('Sorry, videos are limited to 50 megabytes.');\n }\n break;\n default:\n logger.debug('publish > file validation > unrecognized file type');\n throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');\n }\n return file;\n },\n createBasicPublishParams (filePath, name, title, description, license, nsfw, thumbnail) {\n logger.debug(`Creating Publish Parameters`);\n // provide defaults for title\n if (title === null || title.trim() === '') {\n title = name;\n }\n // provide default for description\n if (description === null || description.trim() === '') {\n description = '';\n }\n // provide default for license\n if (license === null || license.trim() === '') {\n license = ' '; // default to empty string\n }\n // create the publish params\n const publishParams = {\n name,\n file_path: filePath,\n bid : 0.01,\n metadata : {\n description,\n title,\n author : details.title,\n language: 'en',\n license,\n nsfw,\n },\n claim_address: publishing.primaryClaimAddress,\n };\n // add thumbnail to channel if video\n if (thumbnail) {\n publishParams['metadata']['thumbnail'] = thumbnail;\n }\n return publishParams;\n },\n createThumbnailPublishParams (thumbnailFilePath, claimName, license, nsfw) {\n if (!thumbnailFilePath) {\n return;\n }\n logger.debug(`Creating Thumbnail Publish Parameters`);\n // create the publish params\n return {\n name : `${claimName}-thumb`,\n file_path: thumbnailFilePath,\n bid : 0.01,\n metadata : {\n title : `${claimName} thumbnail`,\n description: `a thumbnail for ${claimName}`,\n author : details.title,\n language : 'en',\n license,\n nsfw,\n },\n claim_address: publishing.primaryClaimAddress,\n channel_name : publishing.thumbnailChannel,\n channel_id : publishing.thumbnailChannelId,\n };\n },\n deleteTemporaryFile (filePath) {\n fs.unlink(filePath, err => {\n if (err) {\n logger.error(`error deleting temporary file ${filePath}`);\n throw err;\n }\n logger.debug(`successfully deleted ${filePath}`);\n });\n },\n addGetResultsToFileData (fileInfo, getResult) {\n fileInfo.fileName = getResult.file_name;\n fileInfo.filePath = getResult.download_path;\n return fileInfo;\n },\n createFileData ({ name, claimId, outpoint, height, address, nsfw, contentType }) {\n return {\n name,\n claimId,\n outpoint,\n height,\n address,\n fileName: '',\n filePath: '',\n fileType: contentType,\n nsfw,\n };\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/publishHelpers.js","const logger = require('winston');\n\nfunction mysql () {\n this.database = 'default';\n this.username = 'default';\n this.password = 'default';\n this.update = (config) => {\n if (!config) {\n return logger.warn('No MySQL config received.');\n }\n // configure credentials\n logger.info('configuring mysql...');\n const { database, username, password } = config;\n this.database = database;\n this.username = username;\n this.password = password;\n };\n};\n\nmodule.exports = new mysql();\n\n\n\n// WEBPACK FOOTER //\n// ./config/mysqlConfig.js","module.exports = require(\"passport-local\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"passport-local\"\n// module id = 11\n// module chunks = 0","module.exports = {\n returnShortId: function (claimsArray, longId) {\n let claimIndex;\n let shortId = longId.substring(0, 1); // default short id is the first letter\n let shortIdLength = 0;\n // find the index of this claim id\n claimIndex = claimsArray.findIndex(element => {\n return element.claimId === longId;\n });\n if (claimIndex < 0) {\n throw new Error('claim id not found in claims list');\n }\n // get an array of all claims with lower height\n let possibleMatches = claimsArray.slice(0, claimIndex);\n // remove certificates with the same prefixes until none are left.\n while (possibleMatches.length > 0) {\n shortIdLength += 1;\n shortId = longId.substring(0, shortIdLength);\n possibleMatches = possibleMatches.filter(element => {\n return (element.claimId && (element.claimId.substring(0, shortIdLength) === shortId));\n });\n }\n return shortId;\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/sequelizeHelpers.js","module.exports = require(\"sequelize\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"sequelize\"\n// module id = 13\n// module chunks = 0","import React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport { createStore } from 'redux';\nimport { Provider } from 'react-redux';\nimport { StaticRouter } from 'react-router-dom';\nimport { Reducers, GAListener, App } from 'spee.ch-components';\nimport renderFullPage from './renderFullPage.js';\nimport Helmet from 'react-helmet';\n\nmodule.exports = (req, res) => {\n let context = {};\n\n // create a new Redux store instance\n const store = createStore(Reducers);\n\n // render component to a string\n const html = renderToString(\n \n \n \n \n \n \n \n );\n\n // get head tags from helmet\n const helmet = Helmet.renderStatic();\n\n // check for a redirect\n if (context.url) {\n // Somewhere a `` was rendered\n return res.redirect(301, context.url);\n } else {\n // we're good, send the response\n }\n\n // get the initial state from our Redux store\n const preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send(renderFullPage(helmet, html, preloadedState));\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/handlePageRender.jsx","module.exports = require(\"react\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react\"\n// module id = 15\n// module chunks = 0","module.exports = require(\"react-dom/server\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-dom/server\"\n// module id = 16\n// module chunks = 0","module.exports = require(\"redux\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"redux\"\n// module id = 17\n// module chunks = 0","module.exports = require(\"react-redux\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-redux\"\n// module id = 18\n// module chunks = 0","module.exports = require(\"react-router-dom\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-router-dom\"\n// module id = 19\n// module chunks = 0","module.exports = require(\"spee.ch-components\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"spee.ch-components\"\n// module id = 20\n// module chunks = 0","module.exports = (helmet, html, preloadedState) => {\n // take the html and preloadedState and return the full page\n return `\n \n \n \n \n \n \n \n ${helmet.title.toString()}\n ${helmet.meta.toString()}\n ${helmet.link.toString()}\n \n \n \n \n \n \n \n \n
\n
${html}
\n
\n \n \n \n \n `;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/renderFullPage.js","module.exports = require(\"react-helmet\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-helmet\"\n// module id = 22\n// module chunks = 0","const logger = require('winston');\nconst { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js');\nconst { handleErrorResponse } = require('./errorHandlers.js');\n\nconst SERVE = 'SERVE';\nconst SHOW = 'SHOW';\nconst NO_FILE = 'NO_FILE';\nconst NO_CHANNEL = 'NO_CHANNEL';\nconst NO_CLAIM = 'NO_CLAIM';\n\nfunction clientAcceptsHtml ({accept}) {\n return accept && accept.match(/text\\/html/);\n};\n\nfunction requestIsFromBrowser (headers) {\n return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);\n};\n\nfunction clientWantsAsset ({accept, range}) {\n const imageIsWanted = accept && accept.match(/image\\/.*/) && !accept.match(/text\\/html/) && !accept.match(/text\\/\\*/);\n const videoIsWanted = accept && range;\n return imageIsWanted || videoIsWanted;\n};\n\nfunction isValidClaimId (claimId) {\n return ((claimId.length === 40) && !/[^A-Za-z0-9]/g.test(claimId));\n};\n\nfunction isValidShortId (claimId) {\n return claimId.length === 1; // it should really evaluate the short url itself\n};\n\nfunction isValidShortIdOrClaimId (input) {\n return (isValidClaimId(input) || isValidShortId(input));\n};\n\nfunction serveAssetToClient (claimId, name, res) {\n return getLocalFileRecord(claimId, name)\n .then(fileRecord => {\n // check that a local record was found\n if (fileRecord === NO_FILE) {\n return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`);\n }\n // serve the file\n const {filePath, fileType} = fileRecord;\n logger.verbose(`serving file: ${filePath}`);\n const sendFileOptions = {\n headers: {\n 'X-Content-Type-Options': 'nosniff',\n 'Content-Type' : fileType || 'image/jpeg',\n },\n };\n res.status(200).sendFile(filePath, sendFileOptions);\n })\n .catch(error => {\n throw error;\n });\n};\n\nmodule.exports = {\n getClaimIdAndServeAsset (channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) {\n // get the claim Id and then serve the asset\n getClaimId(channelName, channelClaimId, claimName, claimId)\n .then(fullClaimId => {\n if (fullClaimId === NO_CLAIM) {\n return res.status(404).json({success: false, message: 'no claim id could be found'});\n } else if (fullClaimId === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'no channel id could be found'});\n }\n serveAssetToClient(fullClaimId, claimName, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');\n });\n },\n determineResponseType (hasFileExtension, headers) {\n let responseType;\n if (hasFileExtension) {\n responseType = SERVE; // assume a serve request if file extension is present\n if (clientAcceptsHtml(headers)) { // if the request comes from a browser, change it to a show request\n responseType = SHOW;\n }\n } else {\n responseType = SHOW;\n if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { // this is in case someone embeds a show url\n logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');\n responseType = SERVE;\n }\n }\n return responseType;\n },\n flipClaimNameAndIdForBackwardsCompatibility (identifier, name) {\n // this is a patch for backwards compatability with '/name/claim_id' url format\n if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {\n const tempName = name;\n name = identifier;\n identifier = tempName;\n }\n return [identifier, name];\n },\n logRequestData (responseType, claimName, channelName, claimId) {\n logger.debug('responseType ===', responseType);\n logger.debug('claim name === ', claimName);\n logger.debug('channel name ===', channelName);\n logger.debug('claim id ===', claimId);\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/serveHelpers.js","const logger = require('winston');\n\nmodule.exports = {\n REGEXP_INVALID_CLAIM : /[^A-Za-z0-9-]/g,\n REGEXP_INVALID_CHANNEL: /[^A-Za-z0-9-@]/g,\n REGEXP_ADDRESS : /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/,\n CHANNEL_CHAR : '@',\n parseIdentifier : function (identifier) {\n logger.debug('parsing identifier:', identifier);\n const componentsRegex = new RegExp(\n '([^:$#/]*)' + // value (stops at the first separator or end)\n '([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n const [proto, value, modifierSeperator, modifier] = componentsRegex\n .exec(identifier)\n .map(match => match || null);\n logger.debug(`${proto}, ${value}, ${modifierSeperator}, ${modifier}`);\n\n // Validate and process name\n if (!value) {\n throw new Error(`Check your url. No channel name provided before \"${modifierSeperator}\"`);\n }\n const isChannel = value.startsWith(module.exports.CHANNEL_CHAR);\n const channelName = isChannel ? value : null;\n let claimId;\n if (isChannel) {\n if (!channelName) {\n throw new Error('No channel name after @.');\n }\n const nameBadChars = (channelName).match(module.exports.REGEXP_INVALID_CHANNEL);\n if (nameBadChars) {\n throw new Error(`Invalid characters in channel name: ${nameBadChars.join(', ')}.`);\n }\n } else {\n claimId = value;\n }\n\n // Validate and process modifier\n let channelClaimId;\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error(`No modifier provided after separator \"${modifierSeperator}\"`);\n }\n\n if (modifierSeperator === ':') {\n channelClaimId = modifier;\n } else {\n throw new Error(`The \"${modifierSeperator}\" modifier is not currently supported`);\n }\n }\n return {\n isChannel,\n channelName,\n channelClaimId,\n claimId,\n };\n },\n parseClaim: function (claim) {\n logger.debug('parsing name:', claim);\n const componentsRegex = new RegExp(\n '([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n const [proto, claimName, modifierSeperator, modifier] = componentsRegex\n .exec(claim)\n .map(match => match || null);\n logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);\n\n // Validate and process name\n if (!claimName) {\n throw new Error('No claim name provided before .');\n }\n const nameBadChars = (claimName).match(module.exports.REGEXP_INVALID_CLAIM);\n if (nameBadChars) {\n throw new Error(`Invalid characters in claim name: ${nameBadChars.join(', ')}.`);\n }\n // Validate and process modifier\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error(`No file extension provided after separator ${modifierSeperator}.`);\n }\n if (modifierSeperator !== '.') {\n throw new Error(`The ${modifierSeperator} modifier is not supported in the claim name`);\n }\n }\n // return results\n return {\n claimName,\n };\n },\n parseModifier: function (claim) {\n logger.debug('parsing modifier:', claim);\n const componentsRegex = new RegExp(\n '([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n const [proto, claimName, modifierSeperator, modifier] = componentsRegex\n .exec(claim)\n .map(match => match || null);\n logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);\n // Validate and process modifier\n let hasFileExtension = false;\n if (modifierSeperator) {\n hasFileExtension = true;\n }\n return {\n hasFileExtension,\n };\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/lbryUri.js","import React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport { createStore, applyMiddleware } from 'redux';\nimport { Provider } from 'react-redux';\nimport { StaticRouter } from 'react-router-dom';\nimport renderFullPage from './renderFullPage';\nimport createSagaMiddleware from 'redux-saga';\nimport { call } from 'redux-saga/effects';\nimport { Reducers, GAListener, App, Sagas, Actions } from 'spee.ch-components';\n\nimport Helmet from 'react-helmet';\n\nconst returnSagaWithParams = (saga, params) => {\n return function * () {\n yield call(saga, params);\n };\n};\n\nmodule.exports = (req, res) => {\n let context = {};\n\n // create and apply middleware\n const sagaMiddleware = createSagaMiddleware();\n const middleware = applyMiddleware(sagaMiddleware);\n\n // create a new Redux store instance\n const store = createStore(Reducers, middleware);\n\n // create saga\n const action = Actions.onHandleShowPageUri(req.params);\n const saga = returnSagaWithParams(Sagas.handleShowPageUri, action);\n\n // run the saga middleware\n sagaMiddleware\n .run(saga)\n .done\n .then(() => {\n // render component to a string\n const html = renderToString(\n \n \n \n \n \n \n \n );\n\n // get head tags from helmet\n const helmet = Helmet.renderStatic();\n\n // check for a redirect\n if (context.url) {\n return res.redirect(301, context.url);\n }\n\n // get the initial state from our Redux store\n const preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send(renderFullPage(helmet, html, preloadedState));\n });\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/handleShowRender.jsx","module.exports = require(\"babel-polyfill\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"babel-polyfill\"\n// module id = 27\n// module chunks = 0","module.exports = require(\"whatwg-fetch\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"whatwg-fetch\"\n// module id = 28\n// module chunks = 0","const Server = require('./server');\n\nconst exports = {\n Server,\n};\n\nmodule.exports = exports;\n\n\n\n// WEBPACK FOOTER //\n// ./speech.js","// app dependencies\nconst express = require('express');\nconst bodyParser = require('body-parser');\nconst expressHandlebars = require('express-handlebars');\nconst Handlebars = require('handlebars');\nconst helmet = require('helmet');\nconst cookieSession = require('cookie-session');\nconst http = require('http');\nconst logger = require('winston');\nconst requestLogger = require('middleware/requestLogger.js');\nconst Path = require('path');\nconst loggerConfig = require('loggerConfig.js');\nconst mysqlConfig = require('mysqlConfig.js');\nconst siteConfig = require('siteConfig.js');\nconst slackConfig = require('slackConfig.js');\n\nfunction Server () {\n this.configureLogger = (userConfig) => {\n loggerConfig.update(userConfig);\n };\n this.configureMysql = (userConfig) => {\n mysqlConfig.update(userConfig);\n };\n this.configureSiteDetails = (userConfig) => {\n siteConfig.update(userConfig);\n };\n this.configureSlack = (userConfig) => {\n slackConfig.update(userConfig);\n };\n this.configureClientBundle = () => {\n logger.debug('configure the client here by passing in the bundle and configuring it, or better yet: taking in the components to use dynamically from here.');\n };\n this.configureModels = () => {\n logger.debug('here is where you could add/overwrite the default models')\n };\n this.configureRoutes = () => {\n logger.debug('here is where you could add/overwrite the default routes')\n };\n this.createApp = () => {\n // create an Express application\n const app = express();\n\n // trust the proxy to get ip address for us\n app.enable('trust proxy');\n\n /* add middleware */\n // set HTTP headers to protect against well-known web vulnerabilties\n app.use(helmet());\n // 'express.static' to serve static files from public directory\n if (siteConfig.routes.publicFolder) {\n // take in a different public folder, so it can serve it's own bundle if needed\n const publicFolder = Path.resolve(process.cwd(), siteConfig.routes.publicFolder);\n app.use('/static', express.static(publicFolder));\n logger.info('serving static files from custom path:', publicFolder);\n } else {\n const publicPath = Path.resolve(__dirname, 'public');\n app.use('/static', express.static(publicPath));\n logger.info('serving static files from default path:', publicPath);\n };\n // 'body parser' for parsing application/json\n app.use(bodyParser.json());\n // 'body parser' for parsing application/x-www-form-urlencoded\n app.use(bodyParser.urlencoded({ extended: true }));\n\n // add custom middleware (note: build out to accept dynamically use what is in server/middleware/\n app.use(requestLogger);\n\n // configure passport\n const speechPassport = require('speechPassport');\n // initialize passport\n const sessionKey = siteConfig.auth.sessionKey;\n app.use(cookieSession({\n name : 'session',\n keys : [sessionKey],\n maxAge: 24 * 60 * 60 * 1000, // i.e. 24 hours\n }));\n app.use(speechPassport.initialize());\n app.use(speechPassport.session());\n\n // configure handlebars & register it with express app\n const hbs = expressHandlebars.create({\n defaultLayout: 'embed',\n handlebars : Handlebars,\n });\n app.engine('handlebars', hbs.engine);\n app.set('view engine', 'handlebars');\n\n // set the routes on the app\n require('./routes/auth/')(app);\n require('./routes/api/')(app);\n require('./routes/pages/')(app);\n require('./routes/assets/')(app);\n require('./routes/fallback/')(app);\n\n this.app = app;\n };\n this.initialize = () => {\n this.createApp();\n this.server = http.Server(this.app);\n };\n this.start = () => {\n const db = require('models');\n const PORT = siteConfig.details.port;\n // sync sequelize\n db.sequelize.sync()\n // start the server\n .then(() => {\n this.server.listen(PORT, () => {\n logger.info(`Server is listening on PORT ${PORT}`);\n });\n })\n .catch((error) => {\n logger.error(`Startup Error:`, error);\n });\n };\n};\n\nmodule.exports = Server;\n\n\n\n// WEBPACK FOOTER //\n// ./server/index.js","module.exports = require(\"express\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"express\"\n// module id = 31\n// module chunks = 0","module.exports = require(\"body-parser\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"body-parser\"\n// module id = 32\n// module chunks = 0","module.exports = require(\"express-handlebars\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"express-handlebars\"\n// module id = 33\n// module chunks = 0","module.exports = require(\"handlebars\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"handlebars\"\n// module id = 34\n// module chunks = 0","module.exports = require(\"helmet\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"helmet\"\n// module id = 35\n// module chunks = 0","module.exports = require(\"cookie-session\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"cookie-session\"\n// module id = 36\n// module chunks = 0","module.exports = require(\"http\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"http\"\n// module id = 37\n// module chunks = 0","const logger = require('winston');\n\nconst requestLogger = (req, res, next) => { // custom logging middleware to log all incoming http requests\n logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`);\n next();\n};\n\nmodule.exports = requestLogger;\n\n\n\n// WEBPACK FOOTER //\n// ./server/middleware/requestLogger.js","module.exports = require(\"path\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"path\"\n// module id = 39\n// module chunks = 0","const logger = require('winston');\n\nfunction LoggerConfig () {\n this.logLevel = 'debug';\n this.update = (config) => {\n if (!config) {\n return logger.warn('No logger config received.');\n }\n logger.info('configuring winston logger...');\n // update values with local config params\n const {logLevel} = config;\n this.logLevel = logLevel;\n // configure the winston logger\n logger.configure({\n transports: [\n new (logger.transports.Console)({\n level : this.logLevel,\n timestamp : false,\n colorize : true,\n prettyPrint : true,\n handleExceptions : true,\n humanReadableUnhandledException: true,\n }),\n ],\n });\n // test all the log levels\n logger.info('testing winston log levels...');\n logger.error('Level 0');\n logger.warn('Level 1');\n logger.info('Level 2');\n logger.verbose('Level 3');\n logger.debug('Level 4');\n logger.silly('Level 5');\n };\n};\n\nmodule.exports = new LoggerConfig();\n\n\n\n// WEBPACK FOOTER //\n// ./config/loggerConfig.js","const winstonSlackWebHook = require('winston-slack-webhook').SlackWebHook;\nconst winston = require('winston');\n\nfunction SlackConfig () {\n this.slackWebHook = 'default';\n this.slackErrorChannel = 'default';\n this.slackInfoChannel = 'default';\n this.update = (config) => {\n if (!config) {\n return winston.warn('No slack config received');\n }\n // update variables\n winston.info('configuring slack logger...');\n const {slackWebHook, slackErrorChannel, slackInfoChannel} = config;\n this.slackWebHook = slackWebHook;\n this.slackErrorChannel = slackErrorChannel;\n this.slackInfoChannel = slackInfoChannel;\n // update slack webhook settings\n if (this.slackWebHook) {\n // add a transport for errors to slack\n if (this.slackErrorChannel) {\n winston.add(winstonSlackWebHook, {\n name : 'slack-errors-transport',\n level : 'warn',\n webhookUrl: this.slackWebHook,\n channel : this.slackErrorChannel,\n username : 'spee.ch',\n iconEmoji : ':face_with_head_bandage:',\n });\n };\n if (slackInfoChannel) {\n winston.add(winstonSlackWebHook, {\n name : 'slack-info-transport',\n level : 'info',\n webhookUrl: this.slackWebHook,\n channel : this.slackInfoChannel,\n username : 'spee.ch',\n iconEmoji : ':nerd_face:',\n });\n };\n // send test messages\n winston.info('testing slack logger...');\n winston.error('Slack \"error\" logging is online.');\n winston.info('Slack \"info\" logging is online.');\n } else {\n winston.warn('Slack logging is not enabled because no slackWebHook config var provided.');\n }\n };\n};\n\nmodule.exports = new SlackConfig();\n\n\n\n// WEBPACK FOOTER //\n// ./config/slackConfig.js","module.exports = require(\"winston-slack-webhook\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"winston-slack-webhook\"\n// module id = 42\n// module chunks = 0","module.exports = require(\"passport\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"passport\"\n// module id = 43\n// module chunks = 0","const PassportLocalStrategy = require('passport-local').Strategy;\nconst logger = require('winston');\nconst db = require('models');\n\nconst returnUserAndChannelInfo = (userInstance) => {\n return new Promise((resolve, reject) => {\n let userInfo = {};\n userInfo['id'] = userInstance.id;\n userInfo['userName'] = userInstance.userName;\n userInstance\n .getChannel()\n .then(({channelName, channelClaimId}) => {\n userInfo['channelName'] = channelName;\n userInfo['channelClaimId'] = channelClaimId;\n return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName);\n })\n .then(shortChannelId => {\n userInfo['shortChannelId'] = shortChannelId;\n resolve(userInfo);\n })\n .catch(error => {\n reject(error);\n });\n });\n};\n\nmodule.exports = new PassportLocalStrategy(\n {\n usernameField: 'username',\n passwordField: 'password',\n },\n (username, password, done) => {\n return db.User\n .findOne({\n where: {userName: username},\n })\n .then(user => {\n if (!user) {\n logger.debug('no user found');\n return done(null, false, {message: 'Incorrect username or password'});\n }\n return user.comparePassword(password)\n .then(isMatch => {\n if (!isMatch) {\n logger.debug('incorrect password');\n return done(null, false, {message: 'Incorrect username or password'});\n }\n logger.debug('Password was a match, returning User');\n return returnUserAndChannelInfo(user)\n .then(userInfo => {\n return done(null, userInfo);\n })\n .catch(error => {\n return error;\n });\n })\n .catch(error => {\n return error;\n });\n })\n .catch(error => {\n return done(error);\n });\n },\n);\n\n\n\n// WEBPACK FOOTER //\n// ./server/speechPassport/local-login.js","const logger = require('winston');\nconst { returnShortId } = require('../helpers/sequelizeHelpers.js');\n\nmodule.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {\n const Certificate = sequelize.define(\n 'Certificate',\n {\n address: {\n type : STRING,\n default: null,\n },\n amount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n claimId: {\n type : STRING,\n default: null,\n },\n claimSequence: {\n type : INTEGER,\n default: null,\n },\n decodedClaim: {\n type : BOOLEAN,\n default: null,\n },\n depth: {\n type : INTEGER,\n default: null,\n },\n effectiveAmount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n hasSignature: {\n type : BOOLEAN,\n default: null,\n },\n height: {\n type : INTEGER,\n default: null,\n },\n hex: {\n type : TEXT('long'),\n default: null,\n },\n name: {\n type : STRING,\n default: null,\n },\n nout: {\n type : INTEGER,\n default: null,\n },\n txid: {\n type : STRING,\n default: null,\n },\n validAtHeight: {\n type : INTEGER,\n default: null,\n },\n outpoint: {\n type : STRING,\n default: null,\n },\n valueVersion: {\n type : STRING,\n default: null,\n },\n claimType: {\n type : STRING,\n default: null,\n },\n certificateVersion: {\n type : STRING,\n default: null,\n },\n keyType: {\n type : STRING,\n default: null,\n },\n publicKey: {\n type : TEXT('long'),\n default: null,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Certificate.associate = db => {\n Certificate.belongsTo(db.Channel, {\n foreignKey: {\n allowNull: true,\n },\n });\n };\n\n Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {\n logger.debug(`getShortChannelIdFromLongChannelId ${channelName}:${longChannelId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: {name: channelName},\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n throw new Error('No channel(s) found with that channel name');\n default:\n return resolve(returnShortId(result, longChannelId));\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {\n logger.debug(`getLongChannelIdFromShortChannelId(${channelName}, ${channelClaimId})`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: {\n name : channelName,\n claimId: {\n $like: `${channelClaimId}%`,\n },\n },\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n default: // note results must be sorted\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromChannelName = function (channelName) {\n logger.debug(`getLongChannelIdFromChannelName(${channelName})`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name: channelName },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.validateLongChannelId = function (name, claimId) {\n logger.debug(`validateLongChannelId(${name}, ${claimId})`);\n return new Promise((resolve, reject) => {\n this.findOne({\n where: {name, claimId},\n })\n .then(result => {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelId = function (channelName, channelClaimId) {\n logger.debug(`getLongChannelId(${channelName}, ${channelClaimId})`);\n if (channelClaimId && (channelClaimId.length === 40)) { // if a full channel id is provided\n return this.validateLongChannelId(channelName, channelClaimId);\n } else if (channelClaimId && channelClaimId.length < 40) { // if a short channel id is provided\n return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId);\n } else {\n return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided\n }\n };\n\n return Certificate;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/certificate.js","module.exports = (sequelize, { STRING }) => {\n const Channel = sequelize.define(\n 'Channel',\n {\n channelName: {\n type : STRING,\n allowNull: false,\n },\n channelClaimId: {\n type : STRING,\n allowNull: false,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Channel.associate = db => {\n Channel.belongsTo(db.User);\n Channel.hasOne(db.Certificate);\n };\n\n return Channel;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/channel.js","const logger = require('winston');\nconst { returnShortId } = require('../helpers/sequelizeHelpers.js');\nconst { assetDefaults: { thumbnail: defaultThumbnail }, details: { host } } = require('../../config/siteConfig.js');\n\nfunction determineFileExtensionFromContentType (contentType) {\n switch (contentType) {\n case 'image/jpeg':\n case 'image/jpg':\n return 'jpeg';\n case 'image/png':\n return 'png';\n case 'image/gif':\n return 'gif';\n case 'video/mp4':\n return 'mp4';\n default:\n logger.debug('setting unknown file type as file extension jpeg');\n return 'jpeg';\n }\n};\n\nfunction determineThumbnail (storedThumbnail, defaultThumbnail) {\n if (storedThumbnail === '') {\n return defaultThumbnail;\n }\n return storedThumbnail;\n};\n\nfunction prepareClaimData (claim) {\n // logger.debug('preparing claim data based on resolved data:', claim);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['host'] = host;\n return claim;\n};\n\nmodule.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {\n const Claim = sequelize.define(\n 'Claim',\n {\n address: {\n type : STRING,\n default: null,\n },\n amount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n claimId: {\n type : STRING,\n default: null,\n },\n claimSequence: {\n type : INTEGER,\n default: null,\n },\n decodedClaim: {\n type : BOOLEAN,\n default: null,\n },\n depth: {\n type : INTEGER,\n default: null,\n },\n effectiveAmount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n hasSignature: {\n type : BOOLEAN,\n default: null,\n },\n height: {\n type : INTEGER,\n default: null,\n },\n hex: {\n type : TEXT('long'),\n default: null,\n },\n name: {\n type : STRING,\n default: null,\n },\n nout: {\n type : INTEGER,\n default: null,\n },\n txid: {\n type : STRING,\n default: null,\n },\n validAtHeight: {\n type : INTEGER,\n default: null,\n },\n outpoint: {\n type : STRING,\n default: null,\n },\n claimType: {\n type : STRING,\n default: null,\n },\n certificateId: {\n type : STRING,\n default: null,\n },\n author: {\n type : STRING,\n default: null,\n },\n description: {\n type : TEXT('long'),\n default: null,\n },\n language: {\n type : STRING,\n default: null,\n },\n license: {\n type : STRING,\n default: null,\n },\n licenseUrl: {\n type : STRING,\n default: null,\n },\n nsfw: {\n type : BOOLEAN,\n default: null,\n },\n preview: {\n type : STRING,\n default: null,\n },\n thumbnail: {\n type : STRING,\n default: null,\n },\n title: {\n type : STRING,\n default: null,\n },\n metadataVersion: {\n type : STRING,\n default: null,\n },\n contentType: {\n type : STRING,\n default: null,\n },\n source: {\n type : STRING,\n default: null,\n },\n sourceType: {\n type : STRING,\n default: null,\n },\n sourceVersion: {\n type : STRING,\n default: null,\n },\n streamVersion: {\n type : STRING,\n default: null,\n },\n valueVersion: {\n type : STRING,\n default: null,\n },\n channelName: {\n type : STRING,\n allowNull: true,\n default : null,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Claim.associate = db => {\n Claim.belongsTo(db.File, {\n foreignKey: {\n allowNull: true,\n },\n });\n };\n\n Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {\n logger.debug(`Claim.getShortClaimIdFromLongClaimId for ${claimName}#${claimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name: claimName },\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n throw new Error('No claim(s) found with that claim name');\n default:\n resolve(returnShortId(result, claimId));\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getAllChannelClaims = function (channelClaimId) {\n logger.debug(`Claim.getAllChannelClaims for ${channelClaimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { certificateId: channelClaimId },\n order: [['height', 'ASC']],\n raw : true, // returns an array of only data, not an array of instances\n })\n .then(channelClaimsArray => {\n // logger.debug('channelclaimsarray length:', channelClaimsArray.length);\n switch (channelClaimsArray.length) {\n case 0:\n return resolve(null);\n default:\n channelClaimsArray.forEach(claim => {\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n return claim;\n });\n return resolve(channelClaimsArray);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {\n logger.debug(`finding claim id for claim ${claimName} from channel ${channelClaimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name: claimName, certificateId: channelClaimId },\n order: [['id', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(result[0].claimId);\n default:\n logger.error(`${result.length} records found for \"${claimName}\" in channel \"${channelClaimId}\"`);\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: {\n name,\n claimId: {\n $like: `${shortId}%`,\n }},\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n default: // note results must be sorted\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getTopFreeClaimIdByClaimName = function (name) {\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']], // note: maybe height and effective amount need to switch?\n })\n .then(result => {\n logger.debug('length of result', result.length);\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].dataValues.claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.validateLongClaimId = function (name, claimId) {\n return new Promise((resolve, reject) => {\n this.findOne({\n where: {name, claimId},\n })\n .then(result => {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimId = function (claimName, claimId) {\n logger.debug(`getLongClaimId(${claimName}, ${claimId})`);\n if (claimId && (claimId.length === 40)) { // if a full claim id is provided\n return this.validateLongClaimId(claimName, claimId);\n } else if (claimId && claimId.length < 40) {\n return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided\n } else {\n return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided\n }\n };\n\n Claim.resolveClaim = function (name, claimId) {\n logger.debug(`Claim.resolveClaim: ${name} ${claimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name, claimId },\n })\n .then(claimArray => {\n switch (claimArray.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(prepareClaimData(claimArray[0].dataValues));\n default:\n logger.error(`more than one record matches ${name}#${claimId} in db.Claim`);\n return resolve(prepareClaimData(claimArray[0].dataValues));\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n return Claim;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/claim.js","module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => {\n const File = sequelize.define(\n 'File',\n {\n name: {\n type : STRING,\n allowNull: false,\n },\n claimId: {\n type : STRING,\n allowNull: false,\n },\n address: {\n type : STRING,\n allowNull: false,\n },\n outpoint: {\n type : STRING,\n allowNull: false,\n },\n height: {\n type : INTEGER,\n allowNull: false,\n default : 0,\n },\n fileName: {\n type : STRING,\n allowNull: false,\n },\n filePath: {\n type : STRING,\n allowNull: false,\n },\n fileType: {\n type: STRING,\n },\n nsfw: {\n type : BOOLEAN,\n allowNull : false,\n defaultValue: false,\n },\n trendingEligible: {\n type : BOOLEAN,\n allowNull : false,\n defaultValue: true,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n File.associate = db => {\n File.hasMany(db.Request);\n File.hasOne(db.Claim);\n };\n\n File.getRecentClaims = function () {\n return this.findAll({\n where: { nsfw: false, trendingEligible: true },\n order: [['createdAt', 'DESC']],\n limit: 25,\n });\n };\n\n return File;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/file.js","module.exports = (sequelize, { STRING, BOOLEAN, TEXT }) => {\n const Request = sequelize.define(\n 'Request',\n {\n action: {\n type : STRING,\n allowNull: false,\n },\n url: {\n type : STRING,\n allowNull: false,\n },\n ipAddress: {\n type : STRING,\n allowNull: true,\n },\n result: {\n type : TEXT('long'),\n allowNull: true,\n default : null,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Request.associate = db => {\n Request.belongsTo(db.File, {\n foreignKey: {\n allowNull: true,\n },\n });\n };\n\n return Request;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/request.js","'use strict';\nconst bcrypt = require('bcrypt');\nconst logger = require('winston');\n\nmodule.exports = (sequelize, { STRING }) => {\n const User = sequelize.define(\n 'User',\n {\n userName: {\n type : STRING,\n allowNull: false,\n },\n password: {\n type : STRING,\n allowNull: false,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n User.associate = db => {\n User.hasOne(db.Channel);\n };\n\n User.prototype.comparePassword = function (password) {\n return bcrypt.compare(password, this.password);\n };\n\n User.prototype.changePassword = function (newPassword) {\n return new Promise((resolve, reject) => {\n // generate a salt string to use for hashing\n bcrypt.genSalt((saltError, salt) => {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(newPassword, salt, (hashError, hash) => {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the current password with the new hash\n this\n .update({password: hash})\n .then(() => {\n resolve();\n })\n .catch(error => {\n reject(error);\n });\n });\n });\n });\n };\n\n // pre-save hook method to hash the user's password before the user's info is saved to the db.\n User.hook('beforeCreate', (user, options) => {\n logger.debug('User.beforeCreate hook...');\n return new Promise((resolve, reject) => {\n // generate a salt string to use for hashing\n bcrypt.genSalt((saltError, salt) => {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(user.password, salt, (hashError, hash) => {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the password string with the hash password value\n user.password = hash;\n resolve();\n });\n });\n });\n });\n\n return User;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/user.js","module.exports = require(\"bcrypt\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"bcrypt\"\n// module id = 51\n// module chunks = 0","const PassportLocalStrategy = require('passport-local').Strategy;\nconst lbryApi = require('../helpers/lbryApi.js');\nconst logger = require('winston');\nconst db = require('models');\n\nmodule.exports = new PassportLocalStrategy(\n {\n usernameField: 'username',\n passwordField: 'password',\n },\n (username, password, done) => {\n logger.verbose(`new channel signup request. user: ${username} pass: ${password} .`);\n let userInfo = {};\n // server-side validaton of inputs (username, password)\n\n // create the channel and retrieve the metadata\n return lbryApi.createChannel(`@${username}`)\n .then(tx => {\n // create user record\n const userData = {\n userName: username,\n password: password,\n };\n logger.verbose('userData >', userData);\n // create user record\n const channelData = {\n channelName : `@${username}`,\n channelClaimId: tx.claim_id,\n };\n logger.verbose('channelData >', channelData);\n // create certificate record\n const certificateData = {\n claimId: tx.claim_id,\n name : `@${username}`,\n // address,\n };\n logger.verbose('certificateData >', certificateData);\n // save user and certificate to db\n return Promise.all([db.User.create(userData), db.Channel.create(channelData), db.Certificate.create(certificateData)]);\n })\n .then(([newUser, newChannel, newCertificate]) => {\n logger.verbose('user and certificate successfully created');\n // store the relevant newUser info to be passed back for req.User\n userInfo['id'] = newUser.id;\n userInfo['userName'] = newUser.userName;\n userInfo['channelName'] = newChannel.channelName;\n userInfo['channelClaimId'] = newChannel.channelClaimId;\n // associate the instances\n return Promise.all([newCertificate.setChannel(newChannel), newChannel.setUser(newUser)]);\n })\n .then(() => {\n logger.verbose('user and certificate successfully associated');\n return db.Certificate.getShortChannelIdFromLongChannelId(userInfo.channelClaimId, userInfo.channelName);\n })\n .then(shortChannelId => {\n userInfo['shortChannelId'] = shortChannelId;\n return done(null, userInfo);\n })\n .catch(error => {\n logger.error('signup error', error);\n return done(error);\n });\n }\n);\n\n\n\n// WEBPACK FOOTER //\n// ./server/speechPassport/local-signup.js","module.exports = require(\"axios\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"axios\"\n// module id = 53\n// module chunks = 0","const lbryConfig = {\n api: {\n apiHost: 'localhost',\n apiPort: '5279',\n },\n};\n\nmodule.exports = lbryConfig;\n\n\n\n// WEBPACK FOOTER //\n// ./config/lbryConfig.js","module.exports = require(\"universal-analytics\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"universal-analytics\"\n// module id = 55\n// module chunks = 0","module.exports = {\n serializeSpeechUser (user, done) { // returns user data to be serialized into session\n console.log('serializing user');\n done(null, user);\n },\n deserializeSpeechUser (user, done) { // deserializes session and populates additional info to req.user\n console.log('deserializing user');\n done(null, user);\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/authHelpers.js","const speechPassport = require('speechPassport');\nconst handleSignupRequest = require('./signup');\nconst handleLoginRequest = require('./login');\nconst handleLogoutRequest = require('./logout');\nconst handleUserRequest = require('./user');\n\nmodule.exports = (app) => {\n app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest);\n app.post('/login', handleLoginRequest);\n app.get('/logout', handleLogoutRequest);\n app.get('/user', handleUserRequest);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/index.js","const signup = (req, res) => {\n res.status(200).json({\n success : true,\n channelName : req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId,\n });\n};\n\nmodule.exports = signup;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/signup.js","const speechPassport = require('speechPassport');\n\nconst login = (req, res, next) => {\n speechPassport.authenticate('local-login', (err, user, info) => {\n if (err) {\n return next(err);\n }\n if (!user) {\n return res.status(400).json({\n success: false,\n message: info.message,\n });\n }\n req.logIn(user, (err) => {\n if (err) {\n return next(err);\n }\n return res.status(200).json({\n success : true,\n channelName : req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId,\n });\n });\n })(req, res, next);\n};\n\nmodule.exports = login;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/login.js","const logout = (req, res) => {\n req.logout();\n res.status(200).json({success: true, message: 'you successfully logged out'});\n};\n\nmodule.exports = logout;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/logout.js","const user = (req, res) => {\n if (req.user) {\n res.status(200).json({success: true, data: req.user});\n } else {\n res.status(401).json({success: false, message: 'user is not logged in'});\n }\n};\n\nmodule.exports = user;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/user.js","const channelAvailability = require('./channelAvailability');\nconst channelClaims = require('./channelClaims');\nconst channelData = require('./channelData');\nconst channelShortId = require('./channelShortId');\nconst claimAvailability = require('./claimAvailability');\nconst claimData = require('./claimData');\nconst claimGet = require('./claimGet');\nconst claimLongId = require('./claimLongId');\nconst claimPublish = require('./claimPublish');\nconst claimResolve = require('./claimResolve');\nconst claimShortId = require('./claimShortId');\nconst claimList = require('./claimList');\nconst fileAvailability = require('./fileAvailability');\n\nconst multipartMiddleware = require('helpers/multipartMiddleware');\n\nmodule.exports = (app) => {\n // channel routes\n app.get('/api/channel/availability/:name', channelAvailability);\n app.get('/api/channel/short-id/:longId/:name', channelShortId);\n app.get('/api/channel/data/:channelName/:channelClaimId', channelData);\n app.get('/api/channel/claims/:channelName/:channelClaimId/:page', channelClaims);\n // claim routes\n app.get('/api/claim/list/:name', claimList);\n app.get('/api/claim/get/:name/:claimId', claimGet);\n app.get('/api/claim/availability/:name', claimAvailability);\n app.get('/api/claim/resolve/:name/:claimId', claimResolve);\n app.post('/api/claim/publish', multipartMiddleware, claimPublish);\n app.get('/api/claim/short-id/:longId/:name', claimShortId);\n app.post('/api/claim/long-id', claimLongId);\n app.get('/api/claim/data/:claimName/:claimId', claimData);\n // file routes\n app.get('/api/file/availability/:name/:claimId', fileAvailability);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/index.js","const { checkChannelAvailability } = require('controllers/publishController.js');\nconst { sendGATimingEvent } = require('helpers/googleAnalytics.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to check whether site has published to a channel\n\n*/\n\nconst channelAvailability = ({ ip, originalUrl, params: { name } }, res) => {\n const gaStartTime = Date.now();\n checkChannelAvailability(name)\n .then(availableName => {\n res.status(200).json(availableName);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelAvailability;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelAvailability.js","module.exports = require(\"fs\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"fs\"\n// module id = 64\n// module chunks = 0","const { getChannelClaims } = require('controllers/serveController.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get all claims for channel\n\n*/\n\nconst channelClaims = ({ ip, originalUrl, body, params }, res) => {\n const channelName = params.channelName;\n let channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n const page = params.page;\n getChannelClaims(channelName, channelClaimId, page)\n .then(data => {\n if (data === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'No matching channel was found'});\n }\n res.status(200).json({success: true, data});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelClaims;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelClaims.js","const CLAIMS_PER_PAGE = 12;\n\nmodule.exports = {\n returnPaginatedChannelClaims (channelName, longChannelClaimId, claims, page) {\n const totalPages = module.exports.determineTotalPages(claims);\n const paginationPage = module.exports.getPageFromQuery(page);\n const viewData = {\n channelName : channelName,\n longChannelClaimId: longChannelClaimId,\n claims : module.exports.extractPageFromClaims(claims, paginationPage),\n previousPage : module.exports.determinePreviousPage(paginationPage),\n currentPage : paginationPage,\n nextPage : module.exports.determineNextPage(totalPages, paginationPage),\n totalPages : totalPages,\n totalResults : module.exports.determineTotalClaims(claims),\n };\n return viewData;\n },\n getPageFromQuery (page) {\n if (page) {\n return parseInt(page);\n }\n return 1;\n },\n extractPageFromClaims (claims, pageNumber) {\n if (!claims) {\n return []; // if no claims, return this default\n }\n // logger.debug('claims is array?', Array.isArray(claims));\n // logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber));\n const claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE;\n const claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE;\n const pageOfClaims = claims.slice(claimStartIndex, claimEndIndex);\n return pageOfClaims;\n },\n determineTotalPages (claims) {\n if (!claims) {\n return 0;\n } else {\n const totalClaims = claims.length;\n if (totalClaims < CLAIMS_PER_PAGE) {\n return 1;\n }\n const fullPages = Math.floor(totalClaims / CLAIMS_PER_PAGE);\n const remainder = totalClaims % CLAIMS_PER_PAGE;\n if (remainder === 0) {\n return fullPages;\n }\n return fullPages + 1;\n }\n },\n determinePreviousPage (currentPage) {\n if (currentPage === 1) {\n return null;\n }\n return currentPage - 1;\n },\n determineNextPage (totalPages, currentPage) {\n if (currentPage === totalPages) {\n return null;\n }\n return currentPage + 1;\n },\n determineTotalClaims (claims) {\n if (!claims) {\n return 0;\n }\n return claims.length;\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/channelPagination.js","const { getChannelData } = require('controllers/serveController.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get data for a channel\n\n*/\n\nconst channelData = ({ ip, originalUrl, body, params }, res) => {\n const channelName = params.channelName;\n let channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n getChannelData(channelName, channelClaimId, 0)\n .then(data => {\n if (data === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'No matching channel was found'});\n }\n res.status(200).json({success: true, data});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelData;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelData.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\nroute to get a short channel id from long channel Id\n\n*/\n\nconst channelShortIdRoute = ({ ip, originalUrl, params }, res) => {\n db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name)\n .then(shortId => {\n res.status(200).json(shortId);\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelShortIdRoute;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelShortId.js","const { claimNameIsAvailable } = require('controllers/publishController.js');\nconst { sendGATimingEvent } = require('helpers/googleAnalytics.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to check whether this site published to a claim\n\n*/\n\nconst claimAvailability = ({ ip, originalUrl, params: { name } }, res) => {\n const gaStartTime = Date.now();\n claimNameIsAvailable(name)\n .then(result => {\n res.status(200).json(result);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimAvailability;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimAvailability.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to return data for a claim\n\n*/\n\nconst claimData = ({ ip, originalUrl, body, params }, res) => {\n const claimName = params.claimName;\n let claimId = params.claimId;\n if (claimId === 'none') claimId = null;\n db.Claim.resolveClaim(claimName, claimId)\n .then(claimInfo => {\n if (!claimInfo) {\n return res.status(404).json({success: false, message: 'No claim could be found'});\n }\n res.status(200).json({success: true, data: claimInfo});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimData;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimData.js","const { getClaim } = require('helpers/lbryApi.js');\nconst { addGetResultsToFileData, createFileData } = require('../../helpers/publishHelpers.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to get a claim\n\n*/\n\nconst claimGet = ({ ip, originalUrl, params }, res) => {\n const name = params.name;\n const claimId = params.claimId;\n // resolve the claim\n db.Claim.resolveClaim(name, claimId)\n .then(resolveResult => {\n // make sure a claim actually exists at that uri\n if (!resolveResult) {\n throw new Error('No matching uri found in Claim table');\n }\n let fileData = createFileData(resolveResult);\n // get the claim\n return Promise.all([fileData, getClaim(`${name}#${claimId}`)]);\n })\n .then(([ fileData, getResult ]) => {\n fileData = addGetResultsToFileData(fileData, getResult);\n return Promise.all([db.upsert(db.File, fileData, {name, claimId}, 'File'), getResult]);\n })\n .then(([ fileRecord, {message, completed} ]) => {\n res.status(200).json({ success: true, message, completed });\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimGet;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimGet.js","const { getClaimId } = require('controllers/serveController.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\nconst NO_CLAIM = 'NO_CLAIM';\n\n/*\n\n route to get a long claim id\n\n*/\n\nconst claimLongId = ({ ip, originalUrl, body, params }, res) => {\n const channelName = body.channelName;\n const channelClaimId = body.channelClaimId;\n const claimName = body.claimName;\n const claimId = body.claimId;\n getClaimId(channelName, channelClaimId, claimName, claimId)\n .then(result => {\n if (result === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'No matching channel could be found'});\n }\n if (result === NO_CLAIM) {\n return res.status(404).json({success: false, message: 'No matching claim id could be found'});\n }\n res.status(200).json({success: true, data: result});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimLongId;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimLongId.js","const { createBasicPublishParams, createThumbnailPublishParams, parsePublishApiRequestBody, parsePublishApiRequestFiles } = require('helpers/publishHelpers.js');\nconst { claimNameIsAvailable, publish } = require('controllers/publishController.js');\nconst { authenticateUser } = require('auth/authentication.js');\nconst { sendGATimingEvent } = require('helpers/googleAnalytics.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst { details: { host } } = require('siteConfig.js');\n\n/*\n\n route to publish a claim through the daemon\n\n*/\n\nconst claimPublish = ({ body, files, headers, ip, originalUrl, user }, res) => {\n // define variables\n let channelName, channelId, channelPassword, description, fileName, filePath, fileType, gaStartTime, license, name, nsfw, thumbnail, thumbnailFileName, thumbnailFilePath, thumbnailFileType, title;\n // record the start time of the request\n gaStartTime = Date.now();\n // validate the body and files of the request\n try {\n // validateApiPublishRequest(body, files);\n ({name, nsfw, license, title, description, thumbnail} = parsePublishApiRequestBody(body));\n ({fileName, filePath, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files));\n ({channelName, channelId, channelPassword} = body);\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n // check channel authorization\n Promise\n .all([\n authenticateUser(channelName, channelId, channelPassword, user),\n claimNameIsAvailable(name),\n createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail),\n createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw),\n ])\n .then(([{channelName, channelClaimId}, validatedClaimName, publishParams, thumbnailPublishParams]) => {\n // add channel details to the publish params\n if (channelName && channelClaimId) {\n publishParams['channel_name'] = channelName;\n publishParams['channel_id'] = channelClaimId;\n }\n // publish the thumbnail\n if (thumbnailPublishParams) {\n publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);\n }\n // publish the asset\n return publish(publishParams, fileName, fileType);\n })\n .then(result => {\n res.status(200).json({\n success: true,\n message: 'publish completed successfully',\n data : {\n name,\n claimId: result.claim_id,\n url : `${host}/${result.claim_id}/${name}`,\n lbryTx : result,\n },\n });\n // record the publish end time and send to google analytics\n sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimPublish;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimPublish.js","const db = require('models');\nconst logger = require('winston');\n\nmodule.exports = {\n authenticateUser (channelName, channelId, channelPassword, user) {\n // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided\n if (!channelName && !channelId) {\n return {\n channelName : null,\n channelClaimId: null,\n };\n }\n // case: channelName or channel Id are provided with user token\n if (user) {\n if (channelName && channelName !== user.channelName) {\n throw new Error('the provided channel name does not match user credentials');\n }\n if (channelId && channelId !== user.channelClaimId) {\n throw new Error('the provided channel id does not match user credentials');\n }\n return {\n channelName : user.channelName,\n channelClaimId: user.channelClaimId,\n };\n }\n // case: channelName or channel Id are provided with password instead of user token\n if (!channelPassword) throw new Error('no channel password provided');\n return module.exports.authenticateChannelCredentials(channelName, channelId, channelPassword);\n },\n authenticateChannelCredentials (channelName, channelId, userPassword) {\n return new Promise((resolve, reject) => {\n // hoisted variables\n let channelData;\n // build the params for finding the channel\n let channelFindParams = {};\n if (channelName) channelFindParams['channelName'] = channelName;\n if (channelId) channelFindParams['channelClaimId'] = channelId;\n // find the channel\n db.Channel\n .findOne({\n where: channelFindParams,\n })\n .then(channel => {\n if (!channel) {\n logger.debug('no channel found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n channelData = channel.get();\n logger.debug('channel data:', channelData);\n return db.User.findOne({\n where: { userName: channelData.channelName.substring(1) },\n });\n })\n .then(user => {\n if (!user) {\n logger.debug('no user found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n return user.comparePassword(userPassword);\n })\n .then(isMatch => {\n if (!isMatch) {\n logger.debug('incorrect password');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n logger.debug('...password was a match...');\n resolve(channelData);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/auth/authentication.js","const { resolveUri } = require('helpers/lbryApi.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to run a resolve request on the daemon\n\n*/\n\nconst claimResolve = ({ headers, ip, originalUrl, params }, res) => {\n resolveUri(`${params.name}#${params.claimId}`)\n .then(resolvedUri => {\n res.status(200).json(resolvedUri);\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimResolve;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimResolve.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to get a short claim id from long claim Id\n\n*/\n\nconst claimShortId = ({ ip, originalUrl, body, params }, res) => {\n db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)\n .then(shortId => {\n res.status(200).json({success: true, data: shortId});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimShortId;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimShortId.js","const { getClaimList } = require('helpers/lbryApi.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to get list of claims\n\n*/\n\nconst claimList = ({ ip, originalUrl, params }, res) => {\n getClaimList(params.name)\n .then(claimsList => {\n res.status(200).json(claimsList);\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimList;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimList.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to see if asset is available locally\n\n*/\n\nconst fileAvailability = ({ ip, originalUrl, params }, res) => {\n const name = params.name;\n const claimId = params.claimId;\n db.File\n .findOne({\n where: {\n name,\n claimId,\n },\n })\n .then(result => {\n if (result) {\n return res.status(200).json({success: true, data: true});\n }\n res.status(200).json({success: true, data: false});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = fileAvailability;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/fileAvailability.js","const multipart = require('connect-multiparty');\r\nconst { publishing: { uploadDirectory } } = require('siteConfig.js');\r\nconst multipartMiddleware = multipart({uploadDir: uploadDirectory});\r\n\r\nmodule.exports = multipartMiddleware;\r\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/multipartMiddleware.js","module.exports = require(\"connect-multiparty\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"connect-multiparty\"\n// module id = 80\n// module chunks = 0","const handlePageRequest = require('./sendReactApp');\nconst handleEmbedRequest = require('./sendEmbedPage');\nconst redirect = require('./redirect');\n\nmodule.exports = (app) => {\n app.get('/', handlePageRequest);\n app.get('/login', handlePageRequest);\n app.get('/about', handlePageRequest);\n app.get('/trending', redirect('/popular'));\n app.get('/popular', handlePageRequest);\n app.get('/new', handlePageRequest);\n app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/index.js","const handlePageRender = require('helpers/handlePageRender.jsx');\n\nconst sendReactApp = (req, res) => {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/sendReactApp.js","const { details: { host } } = require('siteConfig.js');\n\nconst sendEmbedPage = ({ params }, res) => {\n const claimId = params.claimId;\n const name = params.name;\n // get and render the content\n res.status(200).render('embed', { layout: 'embed', host, claimId, name });\n};\n\nmodule.exports = sendEmbedPage;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/sendEmbedPage.js","const redirect = (route) => {\n return (req, res) => {\n res.status(301).redirect(route);\n };\n};\n\nmodule.exports = redirect;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/redirect.js","const serveAssetByClaim = require('./serveAssetByClaim');\nconst serveAssetByIdentifierAndClaim = require('./serveAssetByIdentifierAndClaim');\n\nmodule.exports = (app, db) => {\n app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);\n app.get('/:claim', serveAssetByClaim);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/assets/index.js","const { sendGAServeEvent } = require('helpers/googleAnalytics');\nconst { determineResponseType, logRequestData, getClaimIdAndServeAsset } = require('helpers/serveHelpers.js');\nconst lbryUri = require('helpers/lbryUri.js');\nconst handleShowRender = require('helpers/handleShowRender.jsx');\nconst SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name only\n\n*/\n\nconst serverAssetByClaim = (req, res) => {\n const { headers, ip, originalUrl, params } = req;\n // decide if this is a show request\n let hasFileExtension;\n try {\n ({ hasFileExtension } = lbryUri.parseModifier(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n let responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n let claimName;\n try {\n ({claimName} = lbryUri.parseClaim(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, null, null);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByClaim;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/assets/serveAssetByClaim.js","module.exports = require(\"redux-saga\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"redux-saga\"\n// module id = 87\n// module chunks = 0","module.exports = require(\"redux-saga/effects\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"redux-saga/effects\"\n// module id = 88\n// module chunks = 0","const { sendGAServeEvent } = require('helpers/googleAnalytics');\nconst {\n determineResponseType,\n flipClaimNameAndIdForBackwardsCompatibility,\n logRequestData,\n getClaimIdAndServeAsset,\n} = require('helpers/serveHelpers.js');\nconst lbryUri = require('helpers/lbryUri.js');\nconst handleShowRender = require('helpers/handleShowRender.jsx');\n\nconst SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name and an identifier\n\n*/\n\nconst serverAssetByIdentifierAndClaim = (req, res) => {\n const { headers, ip, originalUrl, params } = req;\n // decide if this is a show request\n let hasFileExtension;\n try {\n ({ hasFileExtension } = lbryUri.parseModifier(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n let responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n let claimName;\n try {\n ({ claimName } = lbryUri.parseClaim(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n // parse the identifier\n let isChannel, channelName, channelClaimId, claimId;\n try {\n ({ isChannel, channelName, channelClaimId, claimId } = lbryUri.parseIdentifier(params.identifier));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n if (!isChannel) {\n [claimId, claimName] = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, channelName, claimId);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByIdentifierAndClaim;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/assets/serveAssetByIdentifierAndClaim.js","const handlePageRequest = require('./sendReactApp');\r\n\r\nmodule.exports = (app) => {\r\n app.get('*', handlePageRequest);\r\n};\r\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/fallback/index.js","const handlePageRender = require('helpers/handlePageRender.jsx');\n\nconst sendReactApp = (req, res) => {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/fallback/sendReactApp.js"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///index.js","webpack:///webpack/bootstrap 82ebf2ca30129849e4ef","webpack:///external \"winston\"","webpack:///./server/helpers/errorHandlers.js","webpack:///./server/models/index.js","webpack:///./config/siteConfig.js","webpack:///./server/helpers/googleAnalytics.js","webpack:///./server/helpers/lbryApi.js","webpack:///./server/controllers/serveController.js","webpack:///./server/speechPassport/index.js","webpack:///./server/controllers/publishController.js","webpack:///./server/helpers/publishHelpers.js","webpack:///./config/mysqlConfig.js","webpack:///external \"passport-local\"","webpack:///./server/helpers/sequelizeHelpers.js","webpack:///external \"sequelize\"","webpack:///./server/helpers/handlePageRender.jsx","webpack:///external \"react\"","webpack:///external \"react-dom/server\"","webpack:///external \"redux\"","webpack:///external \"react-redux\"","webpack:///external \"react-router-dom\"","webpack:///external \"spee.ch-components\"","webpack:///./server/helpers/renderFullPage.js","webpack:///external \"react-helmet\"","webpack:///./server/helpers/serveHelpers.js","webpack:///./server/helpers/lbryUri.js","webpack:///./server/helpers/handleShowRender.jsx","webpack:///external \"babel-polyfill\"","webpack:///external \"whatwg-fetch\"","webpack:///./speech.js","webpack:///./server/index.js","webpack:///external \"express\"","webpack:///external \"body-parser\"","webpack:///external \"express-handlebars\"","webpack:///external \"handlebars\"","webpack:///external \"helmet\"","webpack:///external \"cookie-session\"","webpack:///external \"http\"","webpack:///./server/middleware/requestLogger.js","webpack:///external \"path\"","webpack:///./config/loggerConfig.js","webpack:///./config/slackConfig.js","webpack:///external \"winston-slack-webhook\"","webpack:///external \"passport\"","webpack:///./server/speechPassport/local-login.js","webpack:///./server/models/certificate.js","webpack:///./server/models/channel.js","webpack:///./server/models/claim.js","webpack:///./server/models/file.js","webpack:///./server/models/request.js","webpack:///./server/models/user.js","webpack:///external \"bcrypt\"","webpack:///./server/speechPassport/local-signup.js","webpack:///external \"axios\"","webpack:///./config/lbryConfig.js","webpack:///external \"universal-analytics\"","webpack:///./server/helpers/authHelpers.js","webpack:///./server/routes/auth/index.js","webpack:///./server/routes/auth/signup.js","webpack:///./server/routes/auth/login.js","webpack:///./server/routes/auth/logout.js","webpack:///./server/routes/auth/user.js","webpack:///./server/routes/api/index.js","webpack:///./server/routes/api/channelAvailability.js","webpack:///external \"fs\"","webpack:///./server/routes/api/channelClaims.js","webpack:///./server/helpers/channelPagination.js","webpack:///./server/routes/api/channelData.js","webpack:///./server/routes/api/channelShortId.js","webpack:///./server/routes/api/claimAvailability.js","webpack:///./server/routes/api/claimData.js","webpack:///./server/routes/api/claimGet.js","webpack:///./server/routes/api/claimLongId.js","webpack:///./server/routes/api/claimPublish.js","webpack:///./server/auth/authentication.js","webpack:///./server/routes/api/claimResolve.js","webpack:///./server/routes/api/claimShortId.js","webpack:///./server/routes/api/claimList.js","webpack:///./server/routes/api/fileAvailability.js","webpack:///./server/helpers/multipartMiddleware.js","webpack:///external \"connect-multiparty\"","webpack:///./server/routes/pages/index.js","webpack:///./server/routes/pages/sendReactApp.js","webpack:///./server/routes/pages/sendEmbedPage.js","webpack:///./server/routes/pages/redirect.js","webpack:///./server/routes/assets/index.js","webpack:///./server/routes/assets/serveAssetByClaim.js","webpack:///external \"redux-saga\"","webpack:///external \"redux-saga/effects\"","webpack:///./server/routes/assets/serveAssetByIdentifierAndClaim.js","webpack:///./server/routes/fallback/index.js","webpack:///./server/routes/fallback/sendReactApp.js"],"names":["module","exports","modules","__webpack_require__","moduleId","installedModules","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","require","_slicedToArray","sliceIterator","arr","_arr","_n","_d","_e","undefined","_s","_i","Symbol","iterator","next","done","push","value","length","err","Array","isArray","TypeError","logger","handleErrorResponse","originalUrl","ip","error","res","useObjectPropertiesIfNoKeys","_module$exports$retur","returnErrorMessageAndStatus","_module$exports$retur2","status","message","json","createErrorResponsePayload","code","keys","newErrorObject","getOwnPropertyNames","forEach","key","success","Certificate","Channel","Claim","File","Request","User","Sequelize","_require","database","username","password","sequelize","host","dialect","dialectOptions","decimalNumbers","logging","pool","max","min","idle","acquire","authenticate","then","info","catch","db","import","modelName","associate","upsert","Model","values","condition","tableName","findOne","where","obj","debug","update","create","SiteConfig","_this","this","analytics","googleId","assetDefaults","description","thumbnail","title","auth","sessionKey","customComponents","components","containers","pages","details","port","twitter","publishing","additionalClaimAddresses","disabled","disabledMessage","primaryClaimAddress","thumbnailChannel","thumbnailChannelId","uploadDirectory","routes","config","console","log","createServeEventParams","headers","eventCategory","eventAction","eventLabel","ipOverride","userAgentOverride","createPublishTimingEventParams","category","variable","label","startTime","endTime","userTimingCategory","userTimingVariableName","userTimingTime","userTimingLabel","sendGoogleAnalyticsEvent","params","visitorId","replace","ua","strictCidFormat","https","event","sendGoogleAnalyticsTiming","timing","sendGAServeEvent","sendGATimingEvent","chooseGaLbrynetPublishLabel","_ref","channelName","channel_name","channelId","channel_id","axios","_require$api","api","apiHost","apiPort","lbryApiUri","_require2","handleLbrynetResponse","resolve","reject","data","result","Error","JSON","stringify","publishClaim","publishParams","gaStartTime","Date","now","Promise","post","method","response","getClaim","uri","timeout","getClaimList","claimName","resolveUri","_ref2","getDownloadDirectory","_ref3","download_directory","createChannel","amount","returnPaginatedChannelClaims","getClaimId","channelClaimId","claimId","getClaimIdByChannel","getClaimIdByClaim","getLongClaimId","longClaimId","getLongChannelId","longChannelId","all","getClaimIdByLongChannelId","getChannelData","page","longChannelClaimId","getShortChannelIdFromLongChannelId","_ref4","shortChannelClaimId","getChannelClaims","getAllChannelClaims","_ref5","_ref6","channelClaimsArray","paginatedChannelViewData","getLocalFileRecord","file","dataValues","passport","localLoginStrategy","localSignupStrategy","serializeSpeechUser","deserializeSpeechUser","deserializeUser","serializeUser","use","_defineProperty","writable","lbryApi","publishHelpers","_require$publishing","Op","publish","fileName","fileType","publishResults","certificateId","tx","channel","fileRecord","claim_id","metadata","address","claim_address","outpoint","txid","nout","height","filePath","file_path","nsfw","claimRecord","contentType","bid","upsertCriteria","claim","setClaim","setFile","deleteTemporaryFile","claimNameIsAvailable","claimAddresses","findAll","attributes","or","checkChannelAvailability","fs","parsePublishApiRequestBody","license","exec","parsePublishApiRequestFiles","path","type","size","test","validateFileTypeAndSize","thumbnailFileName","thumbnailFilePath","thumbnailFileType","createBasicPublishParams","trim","author","language","createThumbnailPublishParams","unlink","addGetResultsToFileData","fileInfo","getResult","file_name","download_path","createFileData","mysql","warn","returnShortId","claimsArray","longId","claimIndex","shortId","substring","shortIdLength","findIndex","element","possibleMatches","slice","filter","_interopRequireDefault","default","_react","_react2","_server","_redux","_reactRedux","_reactRouterDom","_spee","_renderFullPage","_renderFullPage2","_reactHelmet","_reactHelmet2","siteConfig","req","context","customizedReducers","Reducers","store","createStore","html","renderToString","createElement","Provider","StaticRouter","location","url","GAListener","App","helmet","renderStatic","redirect","preloadedState","getState","send","toString","meta","link","clientAcceptsHtml","accept","match","requestIsFromBrowser","clientWantsAsset","range","imageIsWanted","videoIsWanted","isValidClaimId","isValidShortId","isValidShortIdOrClaimId","input","serveAssetToClient","NO_FILE","verbose","sendFileOptions","X-Content-Type-Options","Content-Type","sendFile","getClaimIdAndServeAsset","fullClaimId","determineResponseType","hasFileExtension","responseType","flipClaimNameAndIdForBackwardsCompatibility","identifier","tempName","logRequestData","REGEXP_INVALID_CLAIM","REGEXP_INVALID_CHANNEL","REGEXP_ADDRESS","CHANNEL_CHAR","parseIdentifier","componentsRegex","RegExp","_componentsRegex$exec","map","_componentsRegex$exec2","proto","modifierSeperator","modifier","isChannel","startsWith","nameBadChars","join","parseClaim","_componentsRegex$exec3","_componentsRegex$exec4","parseModifier","_componentsRegex$exec5","_componentsRegex$exec6","_reduxSaga","_reduxSaga2","_effects","returnSagaWithParams","saga","regeneratorRuntime","mark","_callee","wrap","_context","prev","stop","sagaMiddleware","middleware","applyMiddleware","action","Actions","onHandleShowPageUri","Sagas","handleShowPageUri","run","Server","configureLogger","userConfig","loggerConfig","configureMysql","mysqlConfig","configureSiteDetails","configureSlack","slackConfig","configureClientBundle","configureModels","configureRoutes","createApp","app","express","enable","publicFolder","Path","process","cwd","static","publicPath","__dirname","bodyParser","urlencoded","extended","requestLogger","speechPassport","cookieSession","maxAge","initialize","session","hbs","expressHandlebars","defaultLayout","handlebars","Handlebars","engine","set","server","http","start","PORT","sync","listen","LoggerConfig","logLevel","configure","transports","Console","level","timestamp","colorize","prettyPrint","handleExceptions","humanReadableUnhandledException","silly","SlackConfig","slackWebHook","slackErrorChannel","slackInfoChannel","winston","add","winstonSlackWebHook","webhookUrl","iconEmoji","SlackWebHook","PassportLocalStrategy","Strategy","returnUserAndChannelInfo","userInstance","userInfo","id","userName","getChannel","shortChannelId","usernameField","passwordField","user","comparePassword","isMatch","STRING","BOOLEAN","INTEGER","TEXT","DECIMAL","define","claimSequence","decodedClaim","depth","effectiveAmount","hasSignature","hex","validAtHeight","valueVersion","claimType","certificateVersion","keyType","publicKey","freezeTableName","belongsTo","foreignKey","allowNull","order","getLongChannelIdFromShortChannelId","_this2","$like","getLongChannelIdFromChannelName","_this3","validateLongChannelId","_this4","hasOne","determineFileExtensionFromContentType","determineThumbnail","storedThumbnail","defaultThumbnail","prepareClaimData","licenseUrl","preview","metadataVersion","source","sourceType","sourceVersion","streamVersion","getShortClaimIdFromLongClaimId","raw","getLongClaimIdFromShortClaimId","getTopFreeClaimIdByClaimName","_this5","validateLongClaimId","_this6","resolveClaim","_this7","claimArray","defaultValue","trendingEligible","hasMany","getRecentClaims","limit","ipAddress","bcrypt","compare","changePassword","newPassword","genSalt","saltError","salt","hash","hashError","hook","options","userData","channelData","certificateData","newUser","newChannel","newCertificate","setChannel","setUser","lbryConfig","handleSignupRequest","handleLoginRequest","handleLogoutRequest","handleUserRequest","signup","login","logIn","logout","channelAvailability","channelClaims","channelShortId","claimAvailability","claimData","claimGet","claimLongId","claimPublish","claimResolve","claimShortId","claimList","fileAvailability","multipartMiddleware","_require3","availableName","body","claims","totalPages","determineTotalPages","paginationPage","getPageFromQuery","extractPageFromClaims","previousPage","determinePreviousPage","currentPage","nextPage","determineNextPage","totalResults","determineTotalClaims","parseInt","pageNumber","claimStartIndex","claimEndIndex","totalClaims","fullPages","Math","floor","channelShortIdRoute","claimInfo","resolveResult","fileData","_ref5$","completed","authenticateUser","_require4","_require5","_require6","files","channelPassword","_parsePublishApiReque","_parsePublishApiReque2","_ref3$","thumbnailPublishParams","lbryTx","authenticateChannelCredentials","userPassword","channelFindParams","resolvedUri","claimsList","multipart","uploadDir","handlePageRequest","handleEmbedRequest","handlePageRender","sendReactApp","sendEmbedPage","render","layout","route","serveAssetByClaim","serveAssetByIdentifierAndClaim","lbryUri","handleShowRender","serverAssetByClaim","serverAssetByIdentifierAndClaim","_lbryUri$parseIdentif","_flipClaimNameAndIdFo","_flipClaimNameAndIdFo2"],"mappings":"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","file":"index.js","sourcesContent":["module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"/\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 26);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"winston\");\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar logger = __webpack_require__(0);\n\nmodule.exports = {\n handleErrorResponse: function handleErrorResponse(originalUrl, ip, error, res) {\n logger.error('Error on ' + originalUrl, module.exports.useObjectPropertiesIfNoKeys(error));\n\n var _module$exports$retur = module.exports.returnErrorMessageAndStatus(error),\n _module$exports$retur2 = _slicedToArray(_module$exports$retur, 2),\n status = _module$exports$retur2[0],\n message = _module$exports$retur2[1];\n\n res.status(status).json(module.exports.createErrorResponsePayload(status, message));\n },\n returnErrorMessageAndStatus: function returnErrorMessageAndStatus(error) {\n var status = void 0,\n message = void 0;\n // check for daemon being turned off\n if (error.code === 'ECONNREFUSED') {\n status = 503;\n message = 'Connection refused. The daemon may not be running.';\n // fallback for everything else\n } else {\n status = 400;\n if (error.message) {\n message = error.message;\n } else {\n message = error;\n };\n };\n return [status, message];\n },\n useObjectPropertiesIfNoKeys: function useObjectPropertiesIfNoKeys(err) {\n if (Object.keys(err).length === 0) {\n var newErrorObject = {};\n Object.getOwnPropertyNames(err).forEach(function (key) {\n newErrorObject[key] = err[key];\n });\n return newErrorObject;\n }\n return err;\n },\n createErrorResponsePayload: function createErrorResponsePayload(status, message) {\n return {\n status: status,\n success: false,\n message: message\n };\n }\n};\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar Certificate = __webpack_require__(45);\nvar Channel = __webpack_require__(46);\nvar Claim = __webpack_require__(47);\nvar File = __webpack_require__(48);\nvar Request = __webpack_require__(49);\nvar User = __webpack_require__(50);\n\nvar Sequelize = __webpack_require__(13);\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(10),\n database = _require.database,\n username = _require.username,\n password = _require.password;\n\n// set sequelize options\n\n\nvar sequelize = new Sequelize(database, username, password, {\n host: 'localhost',\n dialect: 'mysql',\n dialectOptions: { decimalNumbers: true },\n logging: false,\n pool: {\n max: 5,\n min: 0,\n idle: 10000,\n acquire: 10000\n }\n});\n\n// establish mysql connection\nsequelize.authenticate().then(function () {\n logger.info('Sequelize has established mysql connection successfully.');\n}).catch(function (err) {\n logger.error('Sequelize was unable to connect to the database:', err);\n});\n\n// manually add each model to the db object (note: make this dynamic)\nvar db = {};\ndb['Certificate'] = sequelize.import('Certificate', Certificate);\ndb['Channel'] = sequelize.import('Channel', Channel);\ndb['Claim'] = sequelize.import('Claim', Claim);\ndb['File'] = sequelize.import('File', File);\ndb['Request'] = sequelize.import('Request', Request);\ndb['User'] = sequelize.import('User', User);\n\n// run model.association for each model in the db object that has an association\nlogger.info('associating db models...');\nObject.keys(db).forEach(function (modelName) {\n if (db[modelName].associate) {\n logger.info('Associating model:', modelName);\n db[modelName].associate(db);\n }\n});\n\n// add sequelize/Sequelize to db\ndb.sequelize = sequelize;\ndb.Sequelize = Sequelize;\n// add an 'upsert' method to the db object\ndb.upsert = function (Model, values, condition, tableName) {\n return Model.findOne({\n where: condition\n }).then(function (obj) {\n if (obj) {\n // update\n logger.debug('updating record in db.' + tableName);\n return obj.update(values);\n } else {\n // insert\n logger.debug('creating record in db.' + tableName);\n return Model.create(values);\n }\n }).catch(function (error) {\n logger.error(tableName + '.upsert error', error);\n throw error;\n });\n};\n\nmodule.exports = db;\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nfunction SiteConfig() {\n var _this = this;\n\n this.analytics = {\n googleId: 'default'\n };\n this.assetDefaults = {\n description: 'An asset published on Spee.ch',\n thumbnail: 'https://spee.ch/assets/img/video_thumb_default.png',\n title: 'Spee.ch'\n };\n this.auth = {\n sessionKey: 'default'\n };\n this.customComponents = {\n components: {},\n containers: {},\n pages: {}\n };\n this.details = {\n description: 'Open-source, decentralized image and video sharing.',\n host: 'default',\n port: 3000,\n title: 'Spee.ch',\n twitter: '@spee_ch'\n };\n this.publishing = {\n additionalClaimAddresses: [],\n disabled: false,\n disabledMessage: 'Please check back soon.',\n primaryClaimAddress: 'default',\n thumbnailChannel: 'default',\n thumbnailChannelId: 'default',\n uploadDirectory: '/home/lbry/Uploads'\n };\n this.routes = {};\n this.update = function (config) {\n if (!config) {\n return console.log('No site config received.');\n }\n var analytics = config.analytics,\n assetDefaults = config.assetDefaults,\n auth = config.auth,\n customComponents = config.customComponents,\n details = config.details,\n publishing = config.publishing,\n routes = config.routes;\n\n console.log('Configuring site details...');\n _this.analytics = analytics;\n _this.assetDefaults = assetDefaults;\n _this.auth = auth;\n _this.details = details;\n _this.publishing = publishing;\n _this.customComponents = customComponents;\n _this.routes = routes;\n };\n};\n\nmodule.exports = new SiteConfig();\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\nvar ua = __webpack_require__(55);\n\nvar _require = __webpack_require__(3),\n googleId = _require.analytics.googleId,\n title = _require.details.title;\n\nfunction createServeEventParams(headers, ip, originalUrl) {\n return {\n eventCategory: 'client requests',\n eventAction: 'serve request',\n eventLabel: originalUrl,\n ipOverride: ip,\n userAgentOverride: headers['user-agent']\n };\n};\n\nfunction createPublishTimingEventParams(category, variable, label, startTime, endTime) {\n var duration = endTime - startTime;\n return {\n userTimingCategory: category,\n userTimingVariableName: variable,\n userTimingTime: duration,\n userTimingLabel: label\n };\n};\n\nfunction sendGoogleAnalyticsEvent(ip, params) {\n var visitorId = ip.replace(/\\./g, '-');\n var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.event(params, function (err) {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n });\n};\n\nfunction sendGoogleAnalyticsTiming(visitorId, params) {\n var visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.timing(params, function (err) {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n logger.debug('Timing event successfully sent to google analytics');\n });\n};\n\nmodule.exports = {\n sendGAServeEvent: function sendGAServeEvent(headers, ip, originalUrl) {\n var params = createServeEventParams(headers, ip, originalUrl);\n sendGoogleAnalyticsEvent(ip, params);\n },\n sendGATimingEvent: function sendGATimingEvent(category, variable, label, startTime, endTime) {\n var params = createPublishTimingEventParams(category, variable, label, startTime, endTime);\n sendGoogleAnalyticsTiming(title, params);\n },\n chooseGaLbrynetPublishLabel: function chooseGaLbrynetPublishLabel(_ref) {\n var channelName = _ref.channel_name,\n channelId = _ref.channel_id;\n\n return channelName || channelId ? 'PUBLISH_IN_CHANNEL_CLAIM' : 'PUBLISH_ANONYMOUS_CLAIM';\n }\n};\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar axios = __webpack_require__(53);\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(54),\n _require$api = _require.api,\n apiHost = _require$api.apiHost,\n apiPort = _require$api.apiPort;\n\nvar lbryApiUri = 'http://' + apiHost + ':' + apiPort;\n\nvar _require2 = __webpack_require__(4),\n chooseGaLbrynetPublishLabel = _require2.chooseGaLbrynetPublishLabel,\n sendGATimingEvent = _require2.sendGATimingEvent;\n\nvar handleLbrynetResponse = function handleLbrynetResponse(_ref, resolve, reject) {\n var data = _ref.data;\n\n logger.debug('lbry api data:', data);\n if (data.result) {\n // check for an error\n if (data.result.error) {\n logger.debug('Lbrynet api error:', data.result.error);\n reject(new Error(data.result.error));\n return;\n };\n resolve(data.result);\n return;\n }\n // fallback in case it just timed out\n reject(JSON.stringify(data));\n};\n\nmodule.exports = {\n publishClaim: function publishClaim(publishParams) {\n logger.debug('lbryApi >> Publishing claim to \"' + publishParams.name + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'publish',\n params: publishParams\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getClaim: function getClaim(uri) {\n logger.debug('lbryApi >> Getting Claim for \"' + uri + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'get',\n params: { uri: uri, timeout: 20 }\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'getClaim', 'GET', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getClaimList: function getClaimList(claimName) {\n logger.debug('lbryApi >> Getting claim_list for \"' + claimName + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'claim_list',\n params: { name: claimName }\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'getClaimList', 'CLAIM_LIST', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n resolveUri: function resolveUri(uri) {\n logger.debug('lbryApi >> Resolving URI for \"' + uri + '\"');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'resolve',\n params: { uri: uri }\n }).then(function (_ref2) {\n var data = _ref2.data;\n\n sendGATimingEvent('lbrynet', 'resolveUri', 'RESOLVE', gaStartTime, Date.now());\n if (data.result[uri].error) {\n // check for errors\n reject(data.result[uri].error);\n } else {\n // if no errors, resolve\n resolve(data.result[uri]);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getDownloadDirectory: function getDownloadDirectory() {\n logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'settings_get'\n }).then(function (_ref3) {\n var data = _ref3.data;\n\n sendGATimingEvent('lbrynet', 'getDownloadDirectory', 'SETTINGS_GET', gaStartTime, Date.now());\n if (data.result) {\n resolve(data.result.download_directory);\n } else {\n return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.');\n }\n }).catch(function (error) {\n logger.error('Lbrynet Error:', error);\n resolve('/home/lbry/Downloads/');\n });\n });\n },\n createChannel: function createChannel(name) {\n logger.debug('lbryApi >> Creating channel for ' + name + '...');\n var gaStartTime = Date.now();\n return new Promise(function (resolve, reject) {\n axios.post(lbryApiUri, {\n method: 'channel_new',\n params: {\n channel_name: name,\n amount: 0.1\n }\n }).then(function (response) {\n sendGATimingEvent('lbrynet', 'createChannel', 'CHANNEL_NEW', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n }).catch(function (error) {\n reject(error);\n });\n });\n }\n};\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar db = __webpack_require__(2);\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(66),\n returnPaginatedChannelClaims = _require.returnPaginatedChannelClaims;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\nvar NO_CLAIM = 'NO_CLAIM';\nvar NO_FILE = 'NO_FILE';\n\nmodule.exports = {\n getClaimId: function getClaimId(channelName, channelClaimId, name, claimId) {\n if (channelName) {\n return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);\n } else {\n return module.exports.getClaimIdByClaim(name, claimId);\n }\n },\n getClaimIdByClaim: function getClaimIdByClaim(claimName, claimId) {\n logger.debug('getClaimIdByClaim(' + claimName + ', ' + claimId + ')');\n return new Promise(function (resolve, reject) {\n db.Claim.getLongClaimId(claimName, claimId).then(function (longClaimId) {\n if (!longClaimId) {\n resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getClaimIdByChannel: function getClaimIdByChannel(channelName, channelClaimId, claimName) {\n logger.debug('getClaimIdByChannel(' + channelName + ', ' + channelClaimId + ', ' + claimName + ')');\n return new Promise(function (resolve, reject) {\n db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id\n .then(function (longChannelId) {\n if (!longChannelId) {\n return [null, null];\n }\n return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id\n }).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n longChannelId = _ref2[0],\n longClaimId = _ref2[1];\n\n if (!longChannelId) {\n return resolve(NO_CHANNEL);\n }\n if (!longClaimId) {\n return resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getChannelData: function getChannelData(channelName, channelClaimId, page) {\n return new Promise(function (resolve, reject) {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (longChannelClaimId) {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]);\n }).then(function (_ref3) {\n var _ref4 = _slicedToArray(_ref3, 2),\n longChannelClaimId = _ref4[0],\n shortChannelClaimId = _ref4[1];\n\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. return all the channel information\n resolve({\n channelName: channelName,\n longChannelClaimId: longChannelClaimId,\n shortChannelClaimId: shortChannelClaimId\n });\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getChannelClaims: function getChannelClaims(channelName, channelClaimId, page) {\n return new Promise(function (resolve, reject) {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId).then(function (longChannelClaimId) {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]);\n }).then(function (_ref5) {\n var _ref6 = _slicedToArray(_ref5, 2),\n longChannelClaimId = _ref6[0],\n channelClaimsArray = _ref6[1];\n\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. format the data for the view, including pagination\n var paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page);\n // 4. return all the channel information and contents\n resolve(paginatedChannelViewData);\n }).catch(function (error) {\n reject(error);\n });\n });\n },\n getLocalFileRecord: function getLocalFileRecord(claimId, name) {\n return db.File.findOne({ where: { claimId: claimId, name: name } }).then(function (file) {\n if (!file) {\n return NO_FILE;\n }\n return file.dataValues;\n });\n }\n};\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar passport = __webpack_require__(43);\nvar localLoginStrategy = __webpack_require__(44);\nvar localSignupStrategy = __webpack_require__(52);\n\nvar _require = __webpack_require__(56),\n serializeSpeechUser = _require.serializeSpeechUser,\n deserializeSpeechUser = _require.deserializeSpeechUser;\n\npassport.deserializeUser(deserializeSpeechUser);\npassport.serializeUser(serializeSpeechUser);\npassport.use('local-login', localLoginStrategy);\npassport.use('local-signup', localSignupStrategy);\n\nmodule.exports = passport;\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nfunction _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; }\n\nvar logger = __webpack_require__(0);\nvar db = __webpack_require__(2);\nvar lbryApi = __webpack_require__(5);\nvar publishHelpers = __webpack_require__(9);\n\nvar _require = __webpack_require__(3),\n _require$publishing = _require.publishing,\n primaryClaimAddress = _require$publishing.primaryClaimAddress,\n additionalClaimAddresses = _require$publishing.additionalClaimAddresses;\n\nvar Sequelize = __webpack_require__(13);\nvar Op = Sequelize.Op;\n\nmodule.exports = {\n publish: function publish(publishParams, fileName, fileType) {\n return new Promise(function (resolve, reject) {\n var publishResults = void 0,\n certificateId = void 0,\n channelName = void 0;\n // publish the file\n return lbryApi.publishClaim(publishParams).then(function (tx) {\n logger.info('Successfully published ' + publishParams.name + ' ' + fileName, tx);\n publishResults = tx;\n // get the channel information\n if (publishParams.channel_name) {\n logger.debug('this claim was published in channel: ' + publishParams.channel_name);\n return db.Channel.findOne({\n where: {\n channelName: publishParams.channel_name\n }\n });\n } else {\n logger.debug('this claim was not published in a channel');\n return null;\n }\n }).then(function (channel) {\n // set channel information\n certificateId = null;\n channelName = null;\n if (channel) {\n certificateId = channel.channelClaimId;\n channelName = channel.channelName;\n }\n logger.debug('certificateId: ' + certificateId);\n }).then(function () {\n // create the File record\n var fileRecord = {\n name: publishParams.name,\n claimId: publishResults.claim_id,\n title: publishParams.metadata.title,\n description: publishParams.metadata.description,\n address: publishParams.claim_address,\n outpoint: publishResults.txid + ':' + publishResults.nout,\n height: 0,\n fileName: fileName,\n filePath: publishParams.file_path,\n fileType: fileType,\n nsfw: publishParams.metadata.nsfw\n };\n // create the Claim record\n var claimRecord = {\n name: publishParams.name,\n claimId: publishResults.claim_id,\n title: publishParams.metadata.title,\n description: publishParams.metadata.description,\n address: publishParams.claim_address,\n thumbnail: publishParams.metadata.thumbnail,\n outpoint: publishResults.txid + ':' + publishResults.nout,\n height: 0,\n contentType: fileType,\n nsfw: publishParams.metadata.nsfw,\n amount: publishParams.bid,\n certificateId: certificateId,\n channelName: channelName\n };\n // upsert criteria\n var upsertCriteria = {\n name: publishParams.name,\n claimId: publishResults.claim_id\n };\n // upsert the records\n return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]);\n }).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n file = _ref2[0],\n claim = _ref2[1];\n\n logger.debug('File and Claim records successfully created');\n return Promise.all([file.setClaim(claim), claim.setFile(file)]);\n }).then(function () {\n logger.debug('File and Claim records successfully associated');\n resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim;\n }).catch(function (error) {\n logger.error('PUBLISH ERROR', error);\n publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file\n reject(error);\n });\n });\n },\n claimNameIsAvailable: function claimNameIsAvailable(name) {\n var claimAddresses = additionalClaimAddresses || [];\n claimAddresses.push(primaryClaimAddress);\n // find any records where the name is used\n return db.Claim.findAll({\n attributes: ['address'],\n where: {\n name: name,\n address: _defineProperty({}, Op.or, claimAddresses)\n }\n }).then(function (result) {\n if (result.length >= 1) {\n throw new Error('That claim is already in use');\n };\n return name;\n }).catch(function (error) {\n throw error;\n });\n },\n checkChannelAvailability: function checkChannelAvailability(name) {\n return db.Channel.findAll({\n where: { channelName: name }\n }).then(function (result) {\n if (result.length >= 1) {\n throw new Error('That channel has already been claimed');\n }\n return name;\n }).catch(function (error) {\n throw error;\n });\n }\n};\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\nvar fs = __webpack_require__(64);\n\nvar _require = __webpack_require__(3),\n details = _require.details,\n publishing = _require.publishing;\n\nmodule.exports = {\n parsePublishApiRequestBody: function parsePublishApiRequestBody(_ref) {\n var name = _ref.name,\n nsfw = _ref.nsfw,\n license = _ref.license,\n title = _ref.title,\n description = _ref.description,\n thumbnail = _ref.thumbnail;\n\n // validate name\n if (!name) {\n throw new Error('no name field found in request');\n }\n var invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name);\n if (invalidNameCharacters) {\n throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and \"-\"');\n }\n // optional parameters\n nsfw = nsfw === 'true';\n license = license || null;\n title = title || null;\n description = description || null;\n thumbnail = thumbnail || null;\n // return results\n return {\n name: name,\n nsfw: nsfw,\n license: license,\n title: title,\n description: description,\n thumbnail: thumbnail\n };\n },\n parsePublishApiRequestFiles: function parsePublishApiRequestFiles(_ref2) {\n var file = _ref2.file,\n thumbnail = _ref2.thumbnail;\n\n // make sure a file was provided\n if (!file) {\n throw new Error('no file with key of [file] found in request');\n }\n if (!file.path) {\n throw new Error('no file path found');\n }\n if (!file.type) {\n throw new Error('no file type found');\n }\n if (!file.size) {\n throw new Error('no file type found');\n }\n // validate the file name\n if (/'/.test(file.name)) {\n throw new Error('apostrophes are not allowed in the file name');\n }\n // validate the file\n module.exports.validateFileTypeAndSize(file);\n // return results\n return {\n fileName: file.name,\n filePath: file.path,\n fileType: file.type,\n thumbnailFileName: thumbnail ? thumbnail.name : null,\n thumbnailFilePath: thumbnail ? thumbnail.path : null,\n thumbnailFileType: thumbnail ? thumbnail.type : null\n };\n },\n validateFileTypeAndSize: function validateFileTypeAndSize(file) {\n // check file type and size\n switch (file.type) {\n case 'image/jpeg':\n case 'image/jpg':\n case 'image/png':\n if (file.size > 10000000) {\n logger.debug('publish > file validation > .jpeg/.jpg/.png was too big');\n throw new Error('Sorry, images are limited to 10 megabytes.');\n }\n break;\n case 'image/gif':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .gif was too big');\n throw new Error('Sorry, .gifs are limited to 50 megabytes.');\n }\n break;\n case 'video/mp4':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .mp4 was too big');\n throw new Error('Sorry, videos are limited to 50 megabytes.');\n }\n break;\n default:\n logger.debug('publish > file validation > unrecognized file type');\n throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');\n }\n return file;\n },\n createBasicPublishParams: function createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail) {\n logger.debug('Creating Publish Parameters');\n // provide defaults for title\n if (title === null || title.trim() === '') {\n title = name;\n }\n // provide default for description\n if (description === null || description.trim() === '') {\n description = '';\n }\n // provide default for license\n if (license === null || license.trim() === '') {\n license = ' '; // default to empty string\n }\n // create the publish params\n var publishParams = {\n name: name,\n file_path: filePath,\n bid: 0.01,\n metadata: {\n description: description,\n title: title,\n author: details.title,\n language: 'en',\n license: license,\n nsfw: nsfw\n },\n claim_address: publishing.primaryClaimAddress\n };\n // add thumbnail to channel if video\n if (thumbnail) {\n publishParams['metadata']['thumbnail'] = thumbnail;\n }\n return publishParams;\n },\n createThumbnailPublishParams: function createThumbnailPublishParams(thumbnailFilePath, claimName, license, nsfw) {\n if (!thumbnailFilePath) {\n return;\n }\n logger.debug('Creating Thumbnail Publish Parameters');\n // create the publish params\n return {\n name: claimName + '-thumb',\n file_path: thumbnailFilePath,\n bid: 0.01,\n metadata: {\n title: claimName + ' thumbnail',\n description: 'a thumbnail for ' + claimName,\n author: details.title,\n language: 'en',\n license: license,\n nsfw: nsfw\n },\n claim_address: publishing.primaryClaimAddress,\n channel_name: publishing.thumbnailChannel,\n channel_id: publishing.thumbnailChannelId\n };\n },\n deleteTemporaryFile: function deleteTemporaryFile(filePath) {\n fs.unlink(filePath, function (err) {\n if (err) {\n logger.error('error deleting temporary file ' + filePath);\n throw err;\n }\n logger.debug('successfully deleted ' + filePath);\n });\n },\n addGetResultsToFileData: function addGetResultsToFileData(fileInfo, getResult) {\n fileInfo.fileName = getResult.file_name;\n fileInfo.filePath = getResult.download_path;\n return fileInfo;\n },\n createFileData: function createFileData(_ref3) {\n var name = _ref3.name,\n claimId = _ref3.claimId,\n outpoint = _ref3.outpoint,\n height = _ref3.height,\n address = _ref3.address,\n nsfw = _ref3.nsfw,\n contentType = _ref3.contentType;\n\n return {\n name: name,\n claimId: claimId,\n outpoint: outpoint,\n height: height,\n address: address,\n fileName: '',\n filePath: '',\n fileType: contentType,\n nsfw: nsfw\n };\n }\n};\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nfunction mysql() {\n var _this = this;\n\n this.database = 'default';\n this.username = 'default';\n this.password = 'default';\n this.update = function (config) {\n if (!config) {\n return logger.warn('No MySQL config received.');\n }\n // configure credentials\n logger.info('configuring mysql...');\n var database = config.database,\n username = config.username,\n password = config.password;\n\n _this.database = database;\n _this.username = username;\n _this.password = password;\n };\n};\n\nmodule.exports = new mysql();\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"passport-local\");\n\n/***/ }),\n/* 12 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = {\n returnShortId: function returnShortId(claimsArray, longId) {\n var claimIndex = void 0;\n var shortId = longId.substring(0, 1); // default short id is the first letter\n var shortIdLength = 0;\n // find the index of this claim id\n claimIndex = claimsArray.findIndex(function (element) {\n return element.claimId === longId;\n });\n if (claimIndex < 0) {\n throw new Error('claim id not found in claims list');\n }\n // get an array of all claims with lower height\n var possibleMatches = claimsArray.slice(0, claimIndex);\n // remove certificates with the same prefixes until none are left.\n while (possibleMatches.length > 0) {\n shortIdLength += 1;\n shortId = longId.substring(0, shortIdLength);\n possibleMatches = possibleMatches.filter(function (element) {\n return element.claimId && element.claimId.substring(0, shortIdLength) === shortId;\n });\n }\n return shortId;\n }\n};\n\n/***/ }),\n/* 13 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"sequelize\");\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _react = __webpack_require__(15);\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _server = __webpack_require__(16);\n\nvar _redux = __webpack_require__(17);\n\nvar _reactRedux = __webpack_require__(18);\n\nvar _reactRouterDom = __webpack_require__(19);\n\nvar _spee = __webpack_require__(20);\n\nvar _renderFullPage = __webpack_require__(21);\n\nvar _renderFullPage2 = _interopRequireDefault(_renderFullPage);\n\nvar _reactHelmet = __webpack_require__(22);\n\nvar _reactHelmet2 = _interopRequireDefault(_reactHelmet);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar siteConfig = __webpack_require__(3);\n\nmodule.exports = function (req, res) {\n var context = {};\n\n // customize the reducer by passing in intial state configs\n var customizedReducers = (0, _spee.Reducers)(siteConfig);\n\n // create a new Redux store instance\n var store = (0, _redux.createStore)(customizedReducers);\n\n // render component to a string\n var html = (0, _server.renderToString)(_react2.default.createElement(\n _reactRedux.Provider,\n { store: store },\n _react2.default.createElement(\n _reactRouterDom.StaticRouter,\n { location: req.url, context: context },\n _react2.default.createElement(\n _spee.GAListener,\n null,\n _react2.default.createElement(_spee.App, null)\n )\n )\n ));\n\n // get head tags from helmet\n var helmet = _reactHelmet2.default.renderStatic();\n\n // check for a redirect\n if (context.url) {\n // Somewhere a `` was rendered\n return res.redirect(301, context.url);\n } else {}\n // we're good, send the response\n\n\n // get the initial state from our Redux store\n var preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));\n\n console.log('hello from spee.ch handlePageRender.jsx');\n};\n\n/***/ }),\n/* 15 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react\");\n\n/***/ }),\n/* 16 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-dom/server\");\n\n/***/ }),\n/* 17 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"redux\");\n\n/***/ }),\n/* 18 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-redux\");\n\n/***/ }),\n/* 19 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-router-dom\");\n\n/***/ }),\n/* 20 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"spee.ch-components\");\n\n/***/ }),\n/* 21 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (helmet, html, preloadedState) {\n // take the html and preloadedState and return the full page\n return '\\n \\n \\n \\n \\n \\n \\n \\n ' + helmet.title.toString() + '\\n ' + helmet.meta.toString() + '\\n ' + helmet.link.toString() + '\\n \\n \\n \\n \\n \\n \\n \\n \\n
\\n
' + html + '
\\n
\\n \\n \\n \\n \\n ';\n};\n\n/***/ }),\n/* 22 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"react-helmet\");\n\n/***/ }),\n/* 23 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(6),\n getClaimId = _require.getClaimId,\n getLocalFileRecord = _require.getLocalFileRecord;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar SERVE = 'SERVE';\nvar SHOW = 'SHOW';\nvar NO_FILE = 'NO_FILE';\nvar NO_CHANNEL = 'NO_CHANNEL';\nvar NO_CLAIM = 'NO_CLAIM';\n\nfunction clientAcceptsHtml(_ref) {\n var accept = _ref.accept;\n\n return accept && accept.match(/text\\/html/);\n};\n\nfunction requestIsFromBrowser(headers) {\n return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);\n};\n\nfunction clientWantsAsset(_ref2) {\n var accept = _ref2.accept,\n range = _ref2.range;\n\n var imageIsWanted = accept && accept.match(/image\\/.*/) && !accept.match(/text\\/html/) && !accept.match(/text\\/\\*/);\n var videoIsWanted = accept && range;\n return imageIsWanted || videoIsWanted;\n};\n\nfunction isValidClaimId(claimId) {\n return claimId.length === 40 && !/[^A-Za-z0-9]/g.test(claimId);\n};\n\nfunction isValidShortId(claimId) {\n return claimId.length === 1; // it should really evaluate the short url itself\n};\n\nfunction isValidShortIdOrClaimId(input) {\n return isValidClaimId(input) || isValidShortId(input);\n};\n\nfunction serveAssetToClient(claimId, name, res) {\n return getLocalFileRecord(claimId, name).then(function (fileRecord) {\n // check that a local record was found\n if (fileRecord === NO_FILE) {\n return res.status(307).redirect('/api/claim/get/' + name + '/' + claimId);\n }\n // serve the file\n var filePath = fileRecord.filePath,\n fileType = fileRecord.fileType;\n\n logger.verbose('serving file: ' + filePath);\n var sendFileOptions = {\n headers: {\n 'X-Content-Type-Options': 'nosniff',\n 'Content-Type': fileType || 'image/jpeg'\n }\n };\n res.status(200).sendFile(filePath, sendFileOptions);\n }).catch(function (error) {\n throw error;\n });\n};\n\nmodule.exports = {\n getClaimIdAndServeAsset: function getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) {\n // get the claim Id and then serve the asset\n getClaimId(channelName, channelClaimId, claimName, claimId).then(function (fullClaimId) {\n if (fullClaimId === NO_CLAIM) {\n return res.status(404).json({ success: false, message: 'no claim id could be found' });\n } else if (fullClaimId === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'no channel id could be found' });\n }\n serveAssetToClient(fullClaimId, claimName, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');\n });\n },\n determineResponseType: function determineResponseType(hasFileExtension, headers) {\n var responseType = void 0;\n if (hasFileExtension) {\n responseType = SERVE; // assume a serve request if file extension is present\n if (clientAcceptsHtml(headers)) {\n // if the request comes from a browser, change it to a show request\n responseType = SHOW;\n }\n } else {\n responseType = SHOW;\n if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) {\n // this is in case someone embeds a show url\n logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');\n responseType = SERVE;\n }\n }\n return responseType;\n },\n flipClaimNameAndIdForBackwardsCompatibility: function flipClaimNameAndIdForBackwardsCompatibility(identifier, name) {\n // this is a patch for backwards compatability with '/name/claim_id' url format\n if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {\n var tempName = name;\n name = identifier;\n identifier = tempName;\n }\n return [identifier, name];\n },\n logRequestData: function logRequestData(responseType, claimName, channelName, claimId) {\n logger.debug('responseType ===', responseType);\n logger.debug('claim name === ', claimName);\n logger.debug('channel name ===', channelName);\n logger.debug('claim id ===', claimId);\n }\n};\n\n/***/ }),\n/* 24 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar logger = __webpack_require__(0);\n\nmodule.exports = {\n REGEXP_INVALID_CLAIM: /[^A-Za-z0-9-]/g,\n REGEXP_INVALID_CHANNEL: /[^A-Za-z0-9-@]/g,\n REGEXP_ADDRESS: /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/,\n CHANNEL_CHAR: '@',\n parseIdentifier: function parseIdentifier(identifier) {\n logger.debug('parsing identifier:', identifier);\n var componentsRegex = new RegExp('([^:$#/]*)' + // value (stops at the first separator or end)\n '([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n\n var _componentsRegex$exec = componentsRegex.exec(identifier).map(function (match) {\n return match || null;\n }),\n _componentsRegex$exec2 = _slicedToArray(_componentsRegex$exec, 4),\n proto = _componentsRegex$exec2[0],\n value = _componentsRegex$exec2[1],\n modifierSeperator = _componentsRegex$exec2[2],\n modifier = _componentsRegex$exec2[3];\n\n logger.debug(proto + ', ' + value + ', ' + modifierSeperator + ', ' + modifier);\n\n // Validate and process name\n if (!value) {\n throw new Error('Check your url. No channel name provided before \"' + modifierSeperator + '\"');\n }\n var isChannel = value.startsWith(module.exports.CHANNEL_CHAR);\n var channelName = isChannel ? value : null;\n var claimId = void 0;\n if (isChannel) {\n if (!channelName) {\n throw new Error('No channel name after @.');\n }\n var nameBadChars = channelName.match(module.exports.REGEXP_INVALID_CHANNEL);\n if (nameBadChars) {\n throw new Error('Invalid characters in channel name: ' + nameBadChars.join(', ') + '.');\n }\n } else {\n claimId = value;\n }\n\n // Validate and process modifier\n var channelClaimId = void 0;\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error('No modifier provided after separator \"' + modifierSeperator + '\"');\n }\n\n if (modifierSeperator === ':') {\n channelClaimId = modifier;\n } else {\n throw new Error('The \"' + modifierSeperator + '\" modifier is not currently supported');\n }\n }\n return {\n isChannel: isChannel,\n channelName: channelName,\n channelClaimId: channelClaimId,\n claimId: claimId\n };\n },\n parseClaim: function parseClaim(claim) {\n logger.debug('parsing name:', claim);\n var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n\n var _componentsRegex$exec3 = componentsRegex.exec(claim).map(function (match) {\n return match || null;\n }),\n _componentsRegex$exec4 = _slicedToArray(_componentsRegex$exec3, 4),\n proto = _componentsRegex$exec4[0],\n claimName = _componentsRegex$exec4[1],\n modifierSeperator = _componentsRegex$exec4[2],\n modifier = _componentsRegex$exec4[3];\n\n logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);\n\n // Validate and process name\n if (!claimName) {\n throw new Error('No claim name provided before .');\n }\n var nameBadChars = claimName.match(module.exports.REGEXP_INVALID_CLAIM);\n if (nameBadChars) {\n throw new Error('Invalid characters in claim name: ' + nameBadChars.join(', ') + '.');\n }\n // Validate and process modifier\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error('No file extension provided after separator ' + modifierSeperator + '.');\n }\n if (modifierSeperator !== '.') {\n throw new Error('The ' + modifierSeperator + ' modifier is not supported in the claim name');\n }\n }\n // return results\n return {\n claimName: claimName\n };\n },\n parseModifier: function parseModifier(claim) {\n logger.debug('parsing modifier:', claim);\n var componentsRegex = new RegExp('([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n\n var _componentsRegex$exec5 = componentsRegex.exec(claim).map(function (match) {\n return match || null;\n }),\n _componentsRegex$exec6 = _slicedToArray(_componentsRegex$exec5, 4),\n proto = _componentsRegex$exec6[0],\n claimName = _componentsRegex$exec6[1],\n modifierSeperator = _componentsRegex$exec6[2],\n modifier = _componentsRegex$exec6[3];\n\n logger.debug(proto + ', ' + claimName + ', ' + modifierSeperator + ', ' + modifier);\n // Validate and process modifier\n var hasFileExtension = false;\n if (modifierSeperator) {\n hasFileExtension = true;\n }\n return {\n hasFileExtension: hasFileExtension\n };\n }\n};\n\n/***/ }),\n/* 25 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _react = __webpack_require__(15);\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _server = __webpack_require__(16);\n\nvar _redux = __webpack_require__(17);\n\nvar _reactRedux = __webpack_require__(18);\n\nvar _reactRouterDom = __webpack_require__(19);\n\nvar _renderFullPage = __webpack_require__(21);\n\nvar _renderFullPage2 = _interopRequireDefault(_renderFullPage);\n\nvar _reduxSaga = __webpack_require__(87);\n\nvar _reduxSaga2 = _interopRequireDefault(_reduxSaga);\n\nvar _effects = __webpack_require__(88);\n\nvar _spee = __webpack_require__(20);\n\nvar _reactHelmet = __webpack_require__(22);\n\nvar _reactHelmet2 = _interopRequireDefault(_reactHelmet);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n// configure the reducers by passing initial state configs\nvar siteConfig = __webpack_require__(3);\nvar customizedReducers = (0, _spee.Reducers)(siteConfig);\n\nvar returnSagaWithParams = function returnSagaWithParams(saga, params) {\n return (/*#__PURE__*/regeneratorRuntime.mark(function _callee() {\n return regeneratorRuntime.wrap(function _callee$(_context) {\n while (1) {\n switch (_context.prev = _context.next) {\n case 0:\n _context.next = 2;\n return (0, _effects.call)(saga, params);\n\n case 2:\n case 'end':\n return _context.stop();\n }\n }\n }, _callee, this);\n })\n );\n};\n\nmodule.exports = function (req, res) {\n var context = {};\n\n // create and apply middleware\n var sagaMiddleware = (0, _reduxSaga2.default)();\n var middleware = (0, _redux.applyMiddleware)(sagaMiddleware);\n\n // create a new Redux store instance\n var store = (0, _redux.createStore)(customizedReducers, middleware);\n\n // create saga\n var action = _spee.Actions.onHandleShowPageUri(req.params);\n var saga = returnSagaWithParams(_spee.Sagas.handleShowPageUri, action);\n\n // run the saga middleware\n sagaMiddleware.run(saga).done.then(function () {\n // render component to a string\n var html = (0, _server.renderToString)(_react2.default.createElement(\n _reactRedux.Provider,\n { store: store },\n _react2.default.createElement(\n _reactRouterDom.StaticRouter,\n { location: req.url, context: context },\n _react2.default.createElement(\n _spee.GAListener,\n null,\n _react2.default.createElement(_spee.App, null)\n )\n )\n ));\n\n // get head tags from helmet\n var helmet = _reactHelmet2.default.renderStatic();\n\n // check for a redirect\n if (context.url) {\n return res.redirect(301, context.url);\n }\n\n // get the initial state from our Redux store\n var preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send((0, _renderFullPage2.default)(helmet, html, preloadedState));\n });\n\n console.log('hello from spee.ch handleShowRender.jsx');\n};\n\n/***/ }),\n/* 26 */\n/***/ (function(module, exports, __webpack_require__) {\n\n__webpack_require__(27);\n__webpack_require__(28);\nmodule.exports = __webpack_require__(29);\n\n\n/***/ }),\n/* 27 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"babel-polyfill\");\n\n/***/ }),\n/* 28 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"whatwg-fetch\");\n\n/***/ }),\n/* 29 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar Server = __webpack_require__(30);\n\nvar _exports = {\n Server: Server\n};\n\nmodule.exports = _exports;\n\n/***/ }),\n/* 30 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n// app dependencies\nvar express = __webpack_require__(31);\nvar bodyParser = __webpack_require__(32);\nvar expressHandlebars = __webpack_require__(33);\nvar Handlebars = __webpack_require__(34);\nvar helmet = __webpack_require__(35);\nvar cookieSession = __webpack_require__(36);\nvar http = __webpack_require__(37);\nvar logger = __webpack_require__(0);\nvar requestLogger = __webpack_require__(38);\nvar Path = __webpack_require__(39);\nvar loggerConfig = __webpack_require__(40);\nvar mysqlConfig = __webpack_require__(10);\nvar siteConfig = __webpack_require__(3);\nvar slackConfig = __webpack_require__(41);\n\nfunction Server() {\n var _this = this;\n\n this.configureLogger = function (userConfig) {\n loggerConfig.update(userConfig);\n };\n this.configureMysql = function (userConfig) {\n mysqlConfig.update(userConfig);\n };\n this.configureSiteDetails = function (userConfig) {\n siteConfig.update(userConfig);\n };\n this.configureSlack = function (userConfig) {\n slackConfig.update(userConfig);\n };\n this.configureClientBundle = function () {\n logger.debug('configure the client here by passing in the bundle and configuring it, or better yet: taking in the components to use dynamically from here.');\n };\n this.configureModels = function () {\n logger.debug('here is where you could add/overwrite the default models');\n };\n this.configureRoutes = function () {\n logger.debug('here is where you could add/overwrite the default routes');\n };\n this.createApp = function () {\n // create an Express application\n var app = express();\n\n // trust the proxy to get ip address for us\n app.enable('trust proxy');\n\n /* add middleware */\n // set HTTP headers to protect against well-known web vulnerabilties\n app.use(helmet());\n // 'express.static' to serve static files from public directory\n if (siteConfig.routes.publicFolder) {\n // take in a different public folder, so it can serve it's own bundle if needed\n var publicFolder = Path.resolve(process.cwd(), siteConfig.routes.publicFolder);\n app.use('/static', express.static(publicFolder));\n logger.info('serving static files from custom path:', publicFolder);\n } else {\n var publicPath = Path.resolve(__dirname, 'public');\n app.use('/static', express.static(publicPath));\n logger.info('serving static files from default path:', publicPath);\n };\n // 'body parser' for parsing application/json\n app.use(bodyParser.json());\n // 'body parser' for parsing application/x-www-form-urlencoded\n app.use(bodyParser.urlencoded({ extended: true }));\n\n // add custom middleware (note: build out to accept dynamically use what is in server/middleware/\n app.use(requestLogger);\n\n // configure passport\n var speechPassport = __webpack_require__(7);\n // initialize passport\n var sessionKey = siteConfig.auth.sessionKey;\n app.use(cookieSession({\n name: 'session',\n keys: [sessionKey],\n maxAge: 24 * 60 * 60 * 1000 // i.e. 24 hours\n }));\n app.use(speechPassport.initialize());\n app.use(speechPassport.session());\n\n // configure handlebars & register it with express app\n var hbs = expressHandlebars.create({\n defaultLayout: 'embed',\n handlebars: Handlebars\n });\n app.engine('handlebars', hbs.engine);\n app.set('view engine', 'handlebars');\n\n // set the routes on the app\n __webpack_require__(57)(app);\n __webpack_require__(62)(app);\n __webpack_require__(81)(app);\n __webpack_require__(85)(app);\n __webpack_require__(90)(app);\n\n _this.app = app;\n };\n this.initialize = function () {\n _this.createApp();\n _this.server = http.Server(_this.app);\n };\n this.start = function () {\n var db = __webpack_require__(2);\n var PORT = siteConfig.details.port;\n // sync sequelize\n db.sequelize.sync()\n // start the server\n .then(function () {\n _this.server.listen(PORT, function () {\n logger.info('Server is listening on PORT ' + PORT);\n });\n }).catch(function (error) {\n logger.error('Startup Error:', error);\n });\n };\n};\n\nmodule.exports = Server;\n\n/***/ }),\n/* 31 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"express\");\n\n/***/ }),\n/* 32 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"body-parser\");\n\n/***/ }),\n/* 33 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"express-handlebars\");\n\n/***/ }),\n/* 34 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"handlebars\");\n\n/***/ }),\n/* 35 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"helmet\");\n\n/***/ }),\n/* 36 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"cookie-session\");\n\n/***/ }),\n/* 37 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"http\");\n\n/***/ }),\n/* 38 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar requestLogger = function requestLogger(req, res, next) {\n // custom logging middleware to log all incoming http requests\n logger.verbose('Request on ' + req.originalUrl + ' from ' + req.ip);\n next();\n};\n\nmodule.exports = requestLogger;\n\n/***/ }),\n/* 39 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"path\");\n\n/***/ }),\n/* 40 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nfunction LoggerConfig() {\n var _this = this;\n\n this.logLevel = 'debug';\n this.update = function (config) {\n if (!config) {\n return logger.warn('No logger config received.');\n }\n logger.info('configuring winston logger...');\n // update values with local config params\n var logLevel = config.logLevel;\n\n _this.logLevel = logLevel;\n // configure the winston logger\n logger.configure({\n transports: [new logger.transports.Console({\n level: _this.logLevel,\n timestamp: false,\n colorize: true,\n prettyPrint: true,\n handleExceptions: true,\n humanReadableUnhandledException: true\n })]\n });\n // test all the log levels\n logger.info('testing winston log levels...');\n logger.error('Level 0');\n logger.warn('Level 1');\n logger.info('Level 2');\n logger.verbose('Level 3');\n logger.debug('Level 4');\n logger.silly('Level 5');\n };\n};\n\nmodule.exports = new LoggerConfig();\n\n/***/ }),\n/* 41 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar winstonSlackWebHook = __webpack_require__(42).SlackWebHook;\nvar winston = __webpack_require__(0);\n\nfunction SlackConfig() {\n var _this = this;\n\n this.slackWebHook = 'default';\n this.slackErrorChannel = 'default';\n this.slackInfoChannel = 'default';\n this.update = function (config) {\n if (!config) {\n return winston.warn('No slack config received');\n }\n // update variables\n winston.info('configuring slack logger...');\n var slackWebHook = config.slackWebHook,\n slackErrorChannel = config.slackErrorChannel,\n slackInfoChannel = config.slackInfoChannel;\n\n _this.slackWebHook = slackWebHook;\n _this.slackErrorChannel = slackErrorChannel;\n _this.slackInfoChannel = slackInfoChannel;\n // update slack webhook settings\n if (_this.slackWebHook) {\n // add a transport for errors to slack\n if (_this.slackErrorChannel) {\n winston.add(winstonSlackWebHook, {\n name: 'slack-errors-transport',\n level: 'warn',\n webhookUrl: _this.slackWebHook,\n channel: _this.slackErrorChannel,\n username: 'spee.ch',\n iconEmoji: ':face_with_head_bandage:'\n });\n };\n if (slackInfoChannel) {\n winston.add(winstonSlackWebHook, {\n name: 'slack-info-transport',\n level: 'info',\n webhookUrl: _this.slackWebHook,\n channel: _this.slackInfoChannel,\n username: 'spee.ch',\n iconEmoji: ':nerd_face:'\n });\n };\n // send test messages\n winston.info('testing slack logger...');\n winston.error('Slack \"error\" logging is online.');\n winston.info('Slack \"info\" logging is online.');\n } else {\n winston.warn('Slack logging is not enabled because no slackWebHook config var provided.');\n }\n };\n};\n\nmodule.exports = new SlackConfig();\n\n/***/ }),\n/* 42 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"winston-slack-webhook\");\n\n/***/ }),\n/* 43 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"passport\");\n\n/***/ }),\n/* 44 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar PassportLocalStrategy = __webpack_require__(11).Strategy;\nvar logger = __webpack_require__(0);\nvar db = __webpack_require__(2);\n\nvar returnUserAndChannelInfo = function returnUserAndChannelInfo(userInstance) {\n return new Promise(function (resolve, reject) {\n var userInfo = {};\n userInfo['id'] = userInstance.id;\n userInfo['userName'] = userInstance.userName;\n userInstance.getChannel().then(function (_ref) {\n var channelName = _ref.channelName,\n channelClaimId = _ref.channelClaimId;\n\n userInfo['channelName'] = channelName;\n userInfo['channelClaimId'] = channelClaimId;\n return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName);\n }).then(function (shortChannelId) {\n userInfo['shortChannelId'] = shortChannelId;\n resolve(userInfo);\n }).catch(function (error) {\n reject(error);\n });\n });\n};\n\nmodule.exports = new PassportLocalStrategy({\n usernameField: 'username',\n passwordField: 'password'\n}, function (username, password, done) {\n return db.User.findOne({\n where: { userName: username }\n }).then(function (user) {\n if (!user) {\n logger.debug('no user found');\n return done(null, false, { message: 'Incorrect username or password' });\n }\n return user.comparePassword(password).then(function (isMatch) {\n if (!isMatch) {\n logger.debug('incorrect password');\n return done(null, false, { message: 'Incorrect username or password' });\n }\n logger.debug('Password was a match, returning User');\n return returnUserAndChannelInfo(user).then(function (userInfo) {\n return done(null, userInfo);\n }).catch(function (error) {\n return error;\n });\n }).catch(function (error) {\n return error;\n });\n }).catch(function (error) {\n return done(error);\n });\n});\n\n/***/ }),\n/* 45 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(12),\n returnShortId = _require.returnShortId;\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n INTEGER = _ref.INTEGER,\n TEXT = _ref.TEXT,\n DECIMAL = _ref.DECIMAL;\n\n var Certificate = sequelize.define('Certificate', {\n address: {\n type: STRING,\n default: null\n },\n amount: {\n type: DECIMAL(19, 8),\n default: null\n },\n claimId: {\n type: STRING,\n default: null\n },\n claimSequence: {\n type: INTEGER,\n default: null\n },\n decodedClaim: {\n type: BOOLEAN,\n default: null\n },\n depth: {\n type: INTEGER,\n default: null\n },\n effectiveAmount: {\n type: DECIMAL(19, 8),\n default: null\n },\n hasSignature: {\n type: BOOLEAN,\n default: null\n },\n height: {\n type: INTEGER,\n default: null\n },\n hex: {\n type: TEXT('long'),\n default: null\n },\n name: {\n type: STRING,\n default: null\n },\n nout: {\n type: INTEGER,\n default: null\n },\n txid: {\n type: STRING,\n default: null\n },\n validAtHeight: {\n type: INTEGER,\n default: null\n },\n outpoint: {\n type: STRING,\n default: null\n },\n valueVersion: {\n type: STRING,\n default: null\n },\n claimType: {\n type: STRING,\n default: null\n },\n certificateVersion: {\n type: STRING,\n default: null\n },\n keyType: {\n type: STRING,\n default: null\n },\n publicKey: {\n type: TEXT('long'),\n default: null\n }\n }, {\n freezeTableName: true\n });\n\n Certificate.associate = function (db) {\n Certificate.belongsTo(db.Channel, {\n foreignKey: {\n allowNull: true\n }\n });\n };\n\n Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {\n var _this = this;\n\n logger.debug('getShortChannelIdFromLongChannelId ' + channelName + ':' + longChannelId);\n return new Promise(function (resolve, reject) {\n _this.findAll({\n where: { name: channelName },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n throw new Error('No channel(s) found with that channel name');\n default:\n return resolve(returnShortId(result, longChannelId));\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {\n var _this2 = this;\n\n logger.debug('getLongChannelIdFromShortChannelId(' + channelName + ', ' + channelClaimId + ')');\n return new Promise(function (resolve, reject) {\n _this2.findAll({\n where: {\n name: channelName,\n claimId: {\n $like: channelClaimId + '%'\n }\n },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n // note results must be sorted\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromChannelName = function (channelName) {\n var _this3 = this;\n\n logger.debug('getLongChannelIdFromChannelName(' + channelName + ')');\n return new Promise(function (resolve, reject) {\n _this3.findAll({\n where: { name: channelName },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.validateLongChannelId = function (name, claimId) {\n var _this4 = this;\n\n logger.debug('validateLongChannelId(' + name + ', ' + claimId + ')');\n return new Promise(function (resolve, reject) {\n _this4.findOne({\n where: { name: name, claimId: claimId }\n }).then(function (result) {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelId = function (channelName, channelClaimId) {\n logger.debug('getLongChannelId(' + channelName + ', ' + channelClaimId + ')');\n if (channelClaimId && channelClaimId.length === 40) {\n // if a full channel id is provided\n return this.validateLongChannelId(channelName, channelClaimId);\n } else if (channelClaimId && channelClaimId.length < 40) {\n // if a short channel id is provided\n return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId);\n } else {\n return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided\n }\n };\n\n return Certificate;\n};\n\n/***/ }),\n/* 46 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING;\n\n var Channel = sequelize.define('Channel', {\n channelName: {\n type: STRING,\n allowNull: false\n },\n channelClaimId: {\n type: STRING,\n allowNull: false\n }\n }, {\n freezeTableName: true\n });\n\n Channel.associate = function (db) {\n Channel.belongsTo(db.User);\n Channel.hasOne(db.Certificate);\n };\n\n return Channel;\n};\n\n/***/ }),\n/* 47 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logger = __webpack_require__(0);\n\nvar _require = __webpack_require__(12),\n returnShortId = _require.returnShortId;\n\nvar _require2 = __webpack_require__(3),\n defaultThumbnail = _require2.assetDefaults.thumbnail,\n host = _require2.details.host;\n\nfunction determineFileExtensionFromContentType(contentType) {\n switch (contentType) {\n case 'image/jpeg':\n case 'image/jpg':\n return 'jpeg';\n case 'image/png':\n return 'png';\n case 'image/gif':\n return 'gif';\n case 'video/mp4':\n return 'mp4';\n default:\n logger.debug('setting unknown file type as file extension jpeg');\n return 'jpeg';\n }\n};\n\nfunction determineThumbnail(storedThumbnail, defaultThumbnail) {\n if (storedThumbnail === '') {\n return defaultThumbnail;\n }\n return storedThumbnail;\n};\n\nfunction prepareClaimData(claim) {\n // logger.debug('preparing claim data based on resolved data:', claim);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['host'] = host;\n return claim;\n};\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n INTEGER = _ref.INTEGER,\n TEXT = _ref.TEXT,\n DECIMAL = _ref.DECIMAL;\n\n var Claim = sequelize.define('Claim', {\n address: {\n type: STRING,\n default: null\n },\n amount: {\n type: DECIMAL(19, 8),\n default: null\n },\n claimId: {\n type: STRING,\n default: null\n },\n claimSequence: {\n type: INTEGER,\n default: null\n },\n decodedClaim: {\n type: BOOLEAN,\n default: null\n },\n depth: {\n type: INTEGER,\n default: null\n },\n effectiveAmount: {\n type: DECIMAL(19, 8),\n default: null\n },\n hasSignature: {\n type: BOOLEAN,\n default: null\n },\n height: {\n type: INTEGER,\n default: null\n },\n hex: {\n type: TEXT('long'),\n default: null\n },\n name: {\n type: STRING,\n default: null\n },\n nout: {\n type: INTEGER,\n default: null\n },\n txid: {\n type: STRING,\n default: null\n },\n validAtHeight: {\n type: INTEGER,\n default: null\n },\n outpoint: {\n type: STRING,\n default: null\n },\n claimType: {\n type: STRING,\n default: null\n },\n certificateId: {\n type: STRING,\n default: null\n },\n author: {\n type: STRING,\n default: null\n },\n description: {\n type: TEXT('long'),\n default: null\n },\n language: {\n type: STRING,\n default: null\n },\n license: {\n type: STRING,\n default: null\n },\n licenseUrl: {\n type: STRING,\n default: null\n },\n nsfw: {\n type: BOOLEAN,\n default: null\n },\n preview: {\n type: STRING,\n default: null\n },\n thumbnail: {\n type: STRING,\n default: null\n },\n title: {\n type: STRING,\n default: null\n },\n metadataVersion: {\n type: STRING,\n default: null\n },\n contentType: {\n type: STRING,\n default: null\n },\n source: {\n type: STRING,\n default: null\n },\n sourceType: {\n type: STRING,\n default: null\n },\n sourceVersion: {\n type: STRING,\n default: null\n },\n streamVersion: {\n type: STRING,\n default: null\n },\n valueVersion: {\n type: STRING,\n default: null\n },\n channelName: {\n type: STRING,\n allowNull: true,\n default: null\n }\n }, {\n freezeTableName: true\n });\n\n Claim.associate = function (db) {\n Claim.belongsTo(db.File, {\n foreignKey: {\n allowNull: true\n }\n });\n };\n\n Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {\n var _this = this;\n\n logger.debug('Claim.getShortClaimIdFromLongClaimId for ' + claimName + '#' + claimId);\n return new Promise(function (resolve, reject) {\n _this.findAll({\n where: { name: claimName },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n throw new Error('No claim(s) found with that claim name');\n default:\n resolve(returnShortId(result, claimId));\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getAllChannelClaims = function (channelClaimId) {\n var _this2 = this;\n\n logger.debug('Claim.getAllChannelClaims for ' + channelClaimId);\n return new Promise(function (resolve, reject) {\n _this2.findAll({\n where: { certificateId: channelClaimId },\n order: [['height', 'ASC']],\n raw: true // returns an array of only data, not an array of instances\n }).then(function (channelClaimsArray) {\n // logger.debug('channelclaimsarray length:', channelClaimsArray.length);\n switch (channelClaimsArray.length) {\n case 0:\n return resolve(null);\n default:\n channelClaimsArray.forEach(function (claim) {\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n return claim;\n });\n return resolve(channelClaimsArray);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {\n var _this3 = this;\n\n logger.debug('finding claim id for claim ' + claimName + ' from channel ' + channelClaimId);\n return new Promise(function (resolve, reject) {\n _this3.findAll({\n where: { name: claimName, certificateId: channelClaimId },\n order: [['id', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(result[0].claimId);\n default:\n logger.error(result.length + ' records found for \"' + claimName + '\" in channel \"' + channelClaimId + '\"');\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {\n var _this4 = this;\n\n return new Promise(function (resolve, reject) {\n _this4.findAll({\n where: {\n name: name,\n claimId: {\n $like: shortId + '%'\n } },\n order: [['height', 'ASC']]\n }).then(function (result) {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n // note results must be sorted\n return resolve(result[0].claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getTopFreeClaimIdByClaimName = function (name) {\n var _this5 = this;\n\n return new Promise(function (resolve, reject) {\n _this5.findAll({\n where: { name: name },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']] // note: maybe height and effective amount need to switch?\n }).then(function (result) {\n logger.debug('length of result', result.length);\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].dataValues.claimId);\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.validateLongClaimId = function (name, claimId) {\n var _this6 = this;\n\n return new Promise(function (resolve, reject) {\n _this6.findOne({\n where: { name: name, claimId: claimId }\n }).then(function (result) {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimId = function (claimName, claimId) {\n logger.debug('getLongClaimId(' + claimName + ', ' + claimId + ')');\n if (claimId && claimId.length === 40) {\n // if a full claim id is provided\n return this.validateLongClaimId(claimName, claimId);\n } else if (claimId && claimId.length < 40) {\n return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided\n } else {\n return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided\n }\n };\n\n Claim.resolveClaim = function (name, claimId) {\n var _this7 = this;\n\n logger.debug('Claim.resolveClaim: ' + name + ' ' + claimId);\n return new Promise(function (resolve, reject) {\n _this7.findAll({\n where: { name: name, claimId: claimId }\n }).then(function (claimArray) {\n switch (claimArray.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(prepareClaimData(claimArray[0].dataValues));\n default:\n logger.error('more than one record matches ' + name + '#' + claimId + ' in db.Claim');\n return resolve(prepareClaimData(claimArray[0].dataValues));\n }\n }).catch(function (error) {\n reject(error);\n });\n });\n };\n\n return Claim;\n};\n\n/***/ }),\n/* 48 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n INTEGER = _ref.INTEGER;\n\n var File = sequelize.define('File', {\n name: {\n type: STRING,\n allowNull: false\n },\n claimId: {\n type: STRING,\n allowNull: false\n },\n address: {\n type: STRING,\n allowNull: false\n },\n outpoint: {\n type: STRING,\n allowNull: false\n },\n height: {\n type: INTEGER,\n allowNull: false,\n default: 0\n },\n fileName: {\n type: STRING,\n allowNull: false\n },\n filePath: {\n type: STRING,\n allowNull: false\n },\n fileType: {\n type: STRING\n },\n nsfw: {\n type: BOOLEAN,\n allowNull: false,\n defaultValue: false\n },\n trendingEligible: {\n type: BOOLEAN,\n allowNull: false,\n defaultValue: true\n }\n }, {\n freezeTableName: true\n });\n\n File.associate = function (db) {\n File.hasMany(db.Request);\n File.hasOne(db.Claim);\n };\n\n File.getRecentClaims = function () {\n return this.findAll({\n where: { nsfw: false, trendingEligible: true },\n order: [['createdAt', 'DESC']],\n limit: 25\n });\n };\n\n return File;\n};\n\n/***/ }),\n/* 49 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING,\n BOOLEAN = _ref.BOOLEAN,\n TEXT = _ref.TEXT;\n\n var Request = sequelize.define('Request', {\n action: {\n type: STRING,\n allowNull: false\n },\n url: {\n type: STRING,\n allowNull: false\n },\n ipAddress: {\n type: STRING,\n allowNull: true\n },\n result: {\n type: TEXT('long'),\n allowNull: true,\n default: null\n }\n }, {\n freezeTableName: true\n });\n\n Request.associate = function (db) {\n Request.belongsTo(db.File, {\n foreignKey: {\n allowNull: true\n }\n });\n };\n\n return Request;\n};\n\n/***/ }),\n/* 50 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar bcrypt = __webpack_require__(51);\nvar logger = __webpack_require__(0);\n\nmodule.exports = function (sequelize, _ref) {\n var STRING = _ref.STRING;\n\n var User = sequelize.define('User', {\n userName: {\n type: STRING,\n allowNull: false\n },\n password: {\n type: STRING,\n allowNull: false\n }\n }, {\n freezeTableName: true\n });\n\n User.associate = function (db) {\n User.hasOne(db.Channel);\n };\n\n User.prototype.comparePassword = function (password) {\n return bcrypt.compare(password, this.password);\n };\n\n User.prototype.changePassword = function (newPassword) {\n var _this = this;\n\n return new Promise(function (resolve, reject) {\n // generate a salt string to use for hashing\n bcrypt.genSalt(function (saltError, salt) {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(newPassword, salt, function (hashError, hash) {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the current password with the new hash\n _this.update({ password: hash }).then(function () {\n resolve();\n }).catch(function (error) {\n reject(error);\n });\n });\n });\n });\n };\n\n // pre-save hook method to hash the user's password before the user's info is saved to the db.\n User.hook('beforeCreate', function (user, options) {\n logger.debug('User.beforeCreate hook...');\n return new Promise(function (resolve, reject) {\n // generate a salt string to use for hashing\n bcrypt.genSalt(function (saltError, salt) {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(user.password, salt, function (hashError, hash) {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the password string with the hash password value\n user.password = hash;\n resolve();\n });\n });\n });\n });\n\n return User;\n};\n\n/***/ }),\n/* 51 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"bcrypt\");\n\n/***/ }),\n/* 52 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar PassportLocalStrategy = __webpack_require__(11).Strategy;\nvar lbryApi = __webpack_require__(5);\nvar logger = __webpack_require__(0);\nvar db = __webpack_require__(2);\n\nmodule.exports = new PassportLocalStrategy({\n usernameField: 'username',\n passwordField: 'password'\n}, function (username, password, done) {\n logger.verbose('new channel signup request. user: ' + username + ' pass: ' + password + ' .');\n var userInfo = {};\n // server-side validaton of inputs (username, password)\n\n // create the channel and retrieve the metadata\n return lbryApi.createChannel('@' + username).then(function (tx) {\n // create user record\n var userData = {\n userName: username,\n password: password\n };\n logger.verbose('userData >', userData);\n // create user record\n var channelData = {\n channelName: '@' + username,\n channelClaimId: tx.claim_id\n };\n logger.verbose('channelData >', channelData);\n // create certificate record\n var certificateData = {\n claimId: tx.claim_id,\n name: '@' + username\n // address,\n };\n logger.verbose('certificateData >', certificateData);\n // save user and certificate to db\n return Promise.all([db.User.create(userData), db.Channel.create(channelData), db.Certificate.create(certificateData)]);\n }).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 3),\n newUser = _ref2[0],\n newChannel = _ref2[1],\n newCertificate = _ref2[2];\n\n logger.verbose('user and certificate successfully created');\n // store the relevant newUser info to be passed back for req.User\n userInfo['id'] = newUser.id;\n userInfo['userName'] = newUser.userName;\n userInfo['channelName'] = newChannel.channelName;\n userInfo['channelClaimId'] = newChannel.channelClaimId;\n // associate the instances\n return Promise.all([newCertificate.setChannel(newChannel), newChannel.setUser(newUser)]);\n }).then(function () {\n logger.verbose('user and certificate successfully associated');\n return db.Certificate.getShortChannelIdFromLongChannelId(userInfo.channelClaimId, userInfo.channelName);\n }).then(function (shortChannelId) {\n userInfo['shortChannelId'] = shortChannelId;\n return done(null, userInfo);\n }).catch(function (error) {\n logger.error('signup error', error);\n return done(error);\n });\n});\n\n/***/ }),\n/* 53 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"axios\");\n\n/***/ }),\n/* 54 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar lbryConfig = {\n api: {\n apiHost: 'localhost',\n apiPort: '5279'\n }\n};\n\nmodule.exports = lbryConfig;\n\n/***/ }),\n/* 55 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"universal-analytics\");\n\n/***/ }),\n/* 56 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nmodule.exports = {\n serializeSpeechUser: function serializeSpeechUser(user, done) {\n // returns user data to be serialized into session\n console.log('serializing user');\n done(null, user);\n },\n deserializeSpeechUser: function deserializeSpeechUser(user, done) {\n // deserializes session and populates additional info to req.user\n console.log('deserializing user');\n done(null, user);\n }\n};\n\n/***/ }),\n/* 57 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar speechPassport = __webpack_require__(7);\nvar handleSignupRequest = __webpack_require__(58);\nvar handleLoginRequest = __webpack_require__(59);\nvar handleLogoutRequest = __webpack_require__(60);\nvar handleUserRequest = __webpack_require__(61);\n\nmodule.exports = function (app) {\n app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest);\n app.post('/login', handleLoginRequest);\n app.get('/logout', handleLogoutRequest);\n app.get('/user', handleUserRequest);\n};\n\n/***/ }),\n/* 58 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar signup = function signup(req, res) {\n res.status(200).json({\n success: true,\n channelName: req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId\n });\n};\n\nmodule.exports = signup;\n\n/***/ }),\n/* 59 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar speechPassport = __webpack_require__(7);\n\nvar login = function login(req, res, next) {\n speechPassport.authenticate('local-login', function (err, user, info) {\n if (err) {\n return next(err);\n }\n if (!user) {\n return res.status(400).json({\n success: false,\n message: info.message\n });\n }\n req.logIn(user, function (err) {\n if (err) {\n return next(err);\n }\n return res.status(200).json({\n success: true,\n channelName: req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId\n });\n });\n })(req, res, next);\n};\n\nmodule.exports = login;\n\n/***/ }),\n/* 60 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar logout = function logout(req, res) {\n req.logout();\n res.status(200).json({ success: true, message: 'you successfully logged out' });\n};\n\nmodule.exports = logout;\n\n/***/ }),\n/* 61 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar user = function user(req, res) {\n if (req.user) {\n res.status(200).json({ success: true, data: req.user });\n } else {\n res.status(401).json({ success: false, message: 'user is not logged in' });\n }\n};\n\nmodule.exports = user;\n\n/***/ }),\n/* 62 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar channelAvailability = __webpack_require__(63);\nvar channelClaims = __webpack_require__(65);\nvar channelData = __webpack_require__(67);\nvar channelShortId = __webpack_require__(68);\nvar claimAvailability = __webpack_require__(69);\nvar claimData = __webpack_require__(70);\nvar claimGet = __webpack_require__(71);\nvar claimLongId = __webpack_require__(72);\nvar claimPublish = __webpack_require__(73);\nvar claimResolve = __webpack_require__(75);\nvar claimShortId = __webpack_require__(76);\nvar claimList = __webpack_require__(77);\nvar fileAvailability = __webpack_require__(78);\n\nvar multipartMiddleware = __webpack_require__(79);\n\nmodule.exports = function (app) {\n // channel routes\n app.get('/api/channel/availability/:name', channelAvailability);\n app.get('/api/channel/short-id/:longId/:name', channelShortId);\n app.get('/api/channel/data/:channelName/:channelClaimId', channelData);\n app.get('/api/channel/claims/:channelName/:channelClaimId/:page', channelClaims);\n // claim routes\n app.get('/api/claim/list/:name', claimList);\n app.get('/api/claim/get/:name/:claimId', claimGet);\n app.get('/api/claim/availability/:name', claimAvailability);\n app.get('/api/claim/resolve/:name/:claimId', claimResolve);\n app.post('/api/claim/publish', multipartMiddleware, claimPublish);\n app.get('/api/claim/short-id/:longId/:name', claimShortId);\n app.post('/api/claim/long-id', claimLongId);\n app.get('/api/claim/data/:claimName/:claimId', claimData);\n // file routes\n app.get('/api/file/availability/:name/:claimId', fileAvailability);\n};\n\n/***/ }),\n/* 63 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(8),\n checkChannelAvailability = _require.checkChannelAvailability;\n\nvar _require2 = __webpack_require__(4),\n sendGATimingEvent = _require2.sendGATimingEvent;\n\nvar _require3 = __webpack_require__(1),\n handleErrorResponse = _require3.handleErrorResponse;\n\n/*\n\n route to check whether site has published to a channel\n\n*/\n\nvar channelAvailability = function channelAvailability(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n name = _ref.params.name;\n\n var gaStartTime = Date.now();\n checkChannelAvailability(name).then(function (availableName) {\n res.status(200).json(availableName);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelAvailability;\n\n/***/ }),\n/* 64 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"fs\");\n\n/***/ }),\n/* 65 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(6),\n getChannelClaims = _require.getChannelClaims;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get all claims for channel\n\n*/\n\nvar channelClaims = function channelClaims(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var channelName = params.channelName;\n var channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n var page = params.page;\n getChannelClaims(channelName, channelClaimId, page).then(function (data) {\n if (data === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'No matching channel was found' });\n }\n res.status(200).json({ success: true, data: data });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelClaims;\n\n/***/ }),\n/* 66 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar CLAIMS_PER_PAGE = 12;\n\nmodule.exports = {\n returnPaginatedChannelClaims: function returnPaginatedChannelClaims(channelName, longChannelClaimId, claims, page) {\n var totalPages = module.exports.determineTotalPages(claims);\n var paginationPage = module.exports.getPageFromQuery(page);\n var viewData = {\n channelName: channelName,\n longChannelClaimId: longChannelClaimId,\n claims: module.exports.extractPageFromClaims(claims, paginationPage),\n previousPage: module.exports.determinePreviousPage(paginationPage),\n currentPage: paginationPage,\n nextPage: module.exports.determineNextPage(totalPages, paginationPage),\n totalPages: totalPages,\n totalResults: module.exports.determineTotalClaims(claims)\n };\n return viewData;\n },\n getPageFromQuery: function getPageFromQuery(page) {\n if (page) {\n return parseInt(page);\n }\n return 1;\n },\n extractPageFromClaims: function extractPageFromClaims(claims, pageNumber) {\n if (!claims) {\n return []; // if no claims, return this default\n }\n // logger.debug('claims is array?', Array.isArray(claims));\n // logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber));\n var claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE;\n var claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE;\n var pageOfClaims = claims.slice(claimStartIndex, claimEndIndex);\n return pageOfClaims;\n },\n determineTotalPages: function determineTotalPages(claims) {\n if (!claims) {\n return 0;\n } else {\n var totalClaims = claims.length;\n if (totalClaims < CLAIMS_PER_PAGE) {\n return 1;\n }\n var fullPages = Math.floor(totalClaims / CLAIMS_PER_PAGE);\n var remainder = totalClaims % CLAIMS_PER_PAGE;\n if (remainder === 0) {\n return fullPages;\n }\n return fullPages + 1;\n }\n },\n determinePreviousPage: function determinePreviousPage(currentPage) {\n if (currentPage === 1) {\n return null;\n }\n return currentPage - 1;\n },\n determineNextPage: function determineNextPage(totalPages, currentPage) {\n if (currentPage === totalPages) {\n return null;\n }\n return currentPage + 1;\n },\n determineTotalClaims: function determineTotalClaims(claims) {\n if (!claims) {\n return 0;\n }\n return claims.length;\n }\n};\n\n/***/ }),\n/* 67 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(6),\n getChannelData = _require.getChannelData;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get data for a channel\n\n*/\n\nvar channelData = function channelData(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var channelName = params.channelName;\n var channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n getChannelData(channelName, channelClaimId, 0).then(function (data) {\n if (data === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'No matching channel was found' });\n }\n res.status(200).json({ success: true, data: data });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelData;\n\n/***/ }),\n/* 68 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\nroute to get a short channel id from long channel Id\n\n*/\n\nvar channelShortIdRoute = function channelShortIdRoute(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name).then(function (shortId) {\n res.status(200).json(shortId);\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelShortIdRoute;\n\n/***/ }),\n/* 69 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(8),\n claimNameIsAvailable = _require.claimNameIsAvailable;\n\nvar _require2 = __webpack_require__(4),\n sendGATimingEvent = _require2.sendGATimingEvent;\n\nvar _require3 = __webpack_require__(1),\n handleErrorResponse = _require3.handleErrorResponse;\n\n/*\n\n route to check whether this site published to a claim\n\n*/\n\nvar claimAvailability = function claimAvailability(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n name = _ref.params.name;\n\n var gaStartTime = Date.now();\n claimNameIsAvailable(name).then(function (result) {\n res.status(200).json(result);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimAvailability;\n\n/***/ }),\n/* 70 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to return data for a claim\n\n*/\n\nvar claimData = function claimData(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var claimName = params.claimName;\n var claimId = params.claimId;\n if (claimId === 'none') claimId = null;\n db.Claim.resolveClaim(claimName, claimId).then(function (claimInfo) {\n if (!claimInfo) {\n return res.status(404).json({ success: false, message: 'No claim could be found' });\n }\n res.status(200).json({ success: true, data: claimInfo });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimData;\n\n/***/ }),\n/* 71 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar _require = __webpack_require__(5),\n getClaim = _require.getClaim;\n\nvar _require2 = __webpack_require__(9),\n addGetResultsToFileData = _require2.addGetResultsToFileData,\n createFileData = _require2.createFileData;\n\nvar _require3 = __webpack_require__(1),\n handleErrorResponse = _require3.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to get a claim\n\n*/\n\nvar claimGet = function claimGet(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n var name = params.name;\n var claimId = params.claimId;\n // resolve the claim\n db.Claim.resolveClaim(name, claimId).then(function (resolveResult) {\n // make sure a claim actually exists at that uri\n if (!resolveResult) {\n throw new Error('No matching uri found in Claim table');\n }\n var fileData = createFileData(resolveResult);\n // get the claim\n return Promise.all([fileData, getClaim(name + '#' + claimId)]);\n }).then(function (_ref2) {\n var _ref3 = _slicedToArray(_ref2, 2),\n fileData = _ref3[0],\n getResult = _ref3[1];\n\n fileData = addGetResultsToFileData(fileData, getResult);\n return Promise.all([db.upsert(db.File, fileData, { name: name, claimId: claimId }, 'File'), getResult]);\n }).then(function (_ref4) {\n var _ref5 = _slicedToArray(_ref4, 2),\n fileRecord = _ref5[0],\n _ref5$ = _ref5[1],\n message = _ref5$.message,\n completed = _ref5$.completed;\n\n res.status(200).json({ success: true, message: message, completed: completed });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimGet;\n\n/***/ }),\n/* 72 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(6),\n getClaimId = _require.getClaimId;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\nvar NO_CHANNEL = 'NO_CHANNEL';\nvar NO_CLAIM = 'NO_CLAIM';\n\n/*\n\n route to get a long claim id\n\n*/\n\nvar claimLongId = function claimLongId(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n var channelName = body.channelName;\n var channelClaimId = body.channelClaimId;\n var claimName = body.claimName;\n var claimId = body.claimId;\n getClaimId(channelName, channelClaimId, claimName, claimId).then(function (result) {\n if (result === NO_CHANNEL) {\n return res.status(404).json({ success: false, message: 'No matching channel could be found' });\n }\n if (result === NO_CLAIM) {\n return res.status(404).json({ success: false, message: 'No matching claim id could be found' });\n }\n res.status(200).json({ success: true, data: result });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimLongId;\n\n/***/ }),\n/* 73 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar _require = __webpack_require__(9),\n createBasicPublishParams = _require.createBasicPublishParams,\n createThumbnailPublishParams = _require.createThumbnailPublishParams,\n parsePublishApiRequestBody = _require.parsePublishApiRequestBody,\n parsePublishApiRequestFiles = _require.parsePublishApiRequestFiles;\n\nvar _require2 = __webpack_require__(8),\n claimNameIsAvailable = _require2.claimNameIsAvailable,\n publish = _require2.publish;\n\nvar _require3 = __webpack_require__(74),\n authenticateUser = _require3.authenticateUser;\n\nvar _require4 = __webpack_require__(4),\n sendGATimingEvent = _require4.sendGATimingEvent;\n\nvar _require5 = __webpack_require__(1),\n handleErrorResponse = _require5.handleErrorResponse;\n\nvar _require6 = __webpack_require__(3),\n host = _require6.details.host;\n\n/*\n\n route to publish a claim through the daemon\n\n*/\n\nvar claimPublish = function claimPublish(_ref, res) {\n var body = _ref.body,\n files = _ref.files,\n headers = _ref.headers,\n ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n user = _ref.user;\n\n // define variables\n var channelName = void 0,\n channelId = void 0,\n channelPassword = void 0,\n description = void 0,\n fileName = void 0,\n filePath = void 0,\n fileType = void 0,\n gaStartTime = void 0,\n license = void 0,\n name = void 0,\n nsfw = void 0,\n thumbnail = void 0,\n thumbnailFileName = void 0,\n thumbnailFilePath = void 0,\n thumbnailFileType = void 0,\n title = void 0;\n // record the start time of the request\n gaStartTime = Date.now();\n // validate the body and files of the request\n try {\n var _parsePublishApiReque = parsePublishApiRequestBody(body);\n // validateApiPublishRequest(body, files);\n\n\n name = _parsePublishApiReque.name;\n nsfw = _parsePublishApiReque.nsfw;\n license = _parsePublishApiReque.license;\n title = _parsePublishApiReque.title;\n description = _parsePublishApiReque.description;\n thumbnail = _parsePublishApiReque.thumbnail;\n\n var _parsePublishApiReque2 = parsePublishApiRequestFiles(files);\n\n fileName = _parsePublishApiReque2.fileName;\n filePath = _parsePublishApiReque2.filePath;\n fileType = _parsePublishApiReque2.fileType;\n thumbnailFileName = _parsePublishApiReque2.thumbnailFileName;\n thumbnailFilePath = _parsePublishApiReque2.thumbnailFilePath;\n thumbnailFileType = _parsePublishApiReque2.thumbnailFileType;\n channelName = body.channelName;\n channelId = body.channelId;\n channelPassword = body.channelPassword;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n // check channel authorization\n 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) {\n var _ref3 = _slicedToArray(_ref2, 4),\n _ref3$ = _ref3[0],\n channelName = _ref3$.channelName,\n channelClaimId = _ref3$.channelClaimId,\n validatedClaimName = _ref3[1],\n publishParams = _ref3[2],\n thumbnailPublishParams = _ref3[3];\n\n // add channel details to the publish params\n if (channelName && channelClaimId) {\n publishParams['channel_name'] = channelName;\n publishParams['channel_id'] = channelClaimId;\n }\n // publish the thumbnail\n if (thumbnailPublishParams) {\n publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);\n }\n // publish the asset\n return publish(publishParams, fileName, fileType);\n }).then(function (result) {\n res.status(200).json({\n success: true,\n message: 'publish completed successfully',\n data: {\n name: name,\n claimId: result.claim_id,\n url: host + '/' + result.claim_id + '/' + name,\n lbryTx: result\n }\n });\n // record the publish end time and send to google analytics\n sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimPublish;\n\n/***/ }),\n/* 74 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar db = __webpack_require__(2);\nvar logger = __webpack_require__(0);\n\nmodule.exports = {\n authenticateUser: function authenticateUser(channelName, channelId, channelPassword, user) {\n // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided\n if (!channelName && !channelId) {\n return {\n channelName: null,\n channelClaimId: null\n };\n }\n // case: channelName or channel Id are provided with user token\n if (user) {\n if (channelName && channelName !== user.channelName) {\n throw new Error('the provided channel name does not match user credentials');\n }\n if (channelId && channelId !== user.channelClaimId) {\n throw new Error('the provided channel id does not match user credentials');\n }\n return {\n channelName: user.channelName,\n channelClaimId: user.channelClaimId\n };\n }\n // case: channelName or channel Id are provided with password instead of user token\n if (!channelPassword) throw new Error('no channel password provided');\n return module.exports.authenticateChannelCredentials(channelName, channelId, channelPassword);\n },\n authenticateChannelCredentials: function authenticateChannelCredentials(channelName, channelId, userPassword) {\n return new Promise(function (resolve, reject) {\n // hoisted variables\n var channelData = void 0;\n // build the params for finding the channel\n var channelFindParams = {};\n if (channelName) channelFindParams['channelName'] = channelName;\n if (channelId) channelFindParams['channelClaimId'] = channelId;\n // find the channel\n db.Channel.findOne({\n where: channelFindParams\n }).then(function (channel) {\n if (!channel) {\n logger.debug('no channel found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n channelData = channel.get();\n logger.debug('channel data:', channelData);\n return db.User.findOne({\n where: { userName: channelData.channelName.substring(1) }\n });\n }).then(function (user) {\n if (!user) {\n logger.debug('no user found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n return user.comparePassword(userPassword);\n }).then(function (isMatch) {\n if (!isMatch) {\n logger.debug('incorrect password');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n logger.debug('...password was a match...');\n resolve(channelData);\n }).catch(function (error) {\n reject(error);\n });\n });\n }\n};\n\n/***/ }),\n/* 75 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(5),\n resolveUri = _require.resolveUri;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\n/*\n\n route to run a resolve request on the daemon\n\n*/\n\nvar claimResolve = function claimResolve(_ref, res) {\n var headers = _ref.headers,\n ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n resolveUri(params.name + '#' + params.claimId).then(function (resolvedUri) {\n res.status(200).json(resolvedUri);\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimResolve;\n\n/***/ }),\n/* 76 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to get a short claim id from long claim Id\n\n*/\n\nvar claimShortId = function claimShortId(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n body = _ref.body,\n params = _ref.params;\n\n db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name).then(function (shortId) {\n res.status(200).json({ success: true, data: shortId });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimShortId;\n\n/***/ }),\n/* 77 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(5),\n getClaimList = _require.getClaimList;\n\nvar _require2 = __webpack_require__(1),\n handleErrorResponse = _require2.handleErrorResponse;\n\n/*\n\n route to get list of claims\n\n*/\n\nvar claimList = function claimList(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n getClaimList(params.name).then(function (claimsList) {\n res.status(200).json(claimsList);\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimList;\n\n/***/ }),\n/* 78 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(1),\n handleErrorResponse = _require.handleErrorResponse;\n\nvar db = __webpack_require__(2);\n\n/*\n\n route to see if asset is available locally\n\n*/\n\nvar fileAvailability = function fileAvailability(_ref, res) {\n var ip = _ref.ip,\n originalUrl = _ref.originalUrl,\n params = _ref.params;\n\n var name = params.name;\n var claimId = params.claimId;\n db.File.findOne({\n where: {\n name: name,\n claimId: claimId\n }\n }).then(function (result) {\n if (result) {\n return res.status(200).json({ success: true, data: true });\n }\n res.status(200).json({ success: true, data: false });\n }).catch(function (error) {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = fileAvailability;\n\n/***/ }),\n/* 79 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar multipart = __webpack_require__(80);\n\nvar _require = __webpack_require__(3),\n uploadDirectory = _require.publishing.uploadDirectory;\n\nvar multipartMiddleware = multipart({ uploadDir: uploadDirectory });\n\nmodule.exports = multipartMiddleware;\n\n/***/ }),\n/* 80 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"connect-multiparty\");\n\n/***/ }),\n/* 81 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRequest = __webpack_require__(82);\nvar handleEmbedRequest = __webpack_require__(83);\nvar redirect = __webpack_require__(84);\n\nmodule.exports = function (app) {\n app.get('/', handlePageRequest);\n app.get('/login', handlePageRequest);\n app.get('/about', handlePageRequest);\n app.get('/trending', redirect('/popular'));\n app.get('/popular', handlePageRequest);\n app.get('/new', handlePageRequest);\n app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)\n};\n\n/***/ }),\n/* 82 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRender = __webpack_require__(14);\n\nvar sendReactApp = function sendReactApp(req, res) {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n/***/ }),\n/* 83 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(3),\n host = _require.details.host;\n\nvar sendEmbedPage = function sendEmbedPage(_ref, res) {\n var params = _ref.params;\n\n var claimId = params.claimId;\n var name = params.name;\n // get and render the content\n res.status(200).render('embed', { layout: 'embed', host: host, claimId: claimId, name: name });\n};\n\nmodule.exports = sendEmbedPage;\n\n/***/ }),\n/* 84 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar redirect = function redirect(route) {\n return function (req, res) {\n res.status(301).redirect(route);\n };\n};\n\nmodule.exports = redirect;\n\n/***/ }),\n/* 85 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar serveAssetByClaim = __webpack_require__(86);\nvar serveAssetByIdentifierAndClaim = __webpack_require__(89);\n\nmodule.exports = function (app, db) {\n app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);\n app.get('/:claim', serveAssetByClaim);\n};\n\n/***/ }),\n/* 86 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _require = __webpack_require__(4),\n sendGAServeEvent = _require.sendGAServeEvent;\n\nvar _require2 = __webpack_require__(23),\n determineResponseType = _require2.determineResponseType,\n logRequestData = _require2.logRequestData,\n getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;\n\nvar lbryUri = __webpack_require__(24);\nvar handleShowRender = __webpack_require__(25);\nvar SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name only\n\n*/\n\nvar serverAssetByClaim = function serverAssetByClaim(req, res) {\n var headers = req.headers,\n ip = req.ip,\n originalUrl = req.originalUrl,\n params = req.params;\n // decide if this is a show request\n\n var hasFileExtension = void 0;\n try {\n var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);\n\n hasFileExtension = _lbryUri$parseModifie.hasFileExtension;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n var responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n var claimName = void 0;\n try {\n var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);\n\n claimName = _lbryUri$parseClaim.claimName;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, null, null);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByClaim;\n\n/***/ }),\n/* 87 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"redux-saga\");\n\n/***/ }),\n/* 88 */\n/***/ (function(module, exports) {\n\nmodule.exports = require(\"redux-saga/effects\");\n\n/***/ }),\n/* 89 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _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\"); } }; }();\n\nvar _require = __webpack_require__(4),\n sendGAServeEvent = _require.sendGAServeEvent;\n\nvar _require2 = __webpack_require__(23),\n determineResponseType = _require2.determineResponseType,\n flipClaimNameAndIdForBackwardsCompatibility = _require2.flipClaimNameAndIdForBackwardsCompatibility,\n logRequestData = _require2.logRequestData,\n getClaimIdAndServeAsset = _require2.getClaimIdAndServeAsset;\n\nvar lbryUri = __webpack_require__(24);\nvar handleShowRender = __webpack_require__(25);\n\nvar SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name and an identifier\n\n*/\n\nvar serverAssetByIdentifierAndClaim = function serverAssetByIdentifierAndClaim(req, res) {\n var headers = req.headers,\n ip = req.ip,\n originalUrl = req.originalUrl,\n params = req.params;\n // decide if this is a show request\n\n var hasFileExtension = void 0;\n try {\n var _lbryUri$parseModifie = lbryUri.parseModifier(params.claim);\n\n hasFileExtension = _lbryUri$parseModifie.hasFileExtension;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n var responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n var claimName = void 0;\n try {\n var _lbryUri$parseClaim = lbryUri.parseClaim(params.claim);\n\n claimName = _lbryUri$parseClaim.claimName;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n // parse the identifier\n var isChannel = void 0,\n channelName = void 0,\n channelClaimId = void 0,\n claimId = void 0;\n try {\n var _lbryUri$parseIdentif = lbryUri.parseIdentifier(params.identifier);\n\n isChannel = _lbryUri$parseIdentif.isChannel;\n channelName = _lbryUri$parseIdentif.channelName;\n channelClaimId = _lbryUri$parseIdentif.channelClaimId;\n claimId = _lbryUri$parseIdentif.claimId;\n } catch (error) {\n return res.status(400).json({ success: false, message: error.message });\n }\n if (!isChannel) {\n var _flipClaimNameAndIdFo = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);\n\n var _flipClaimNameAndIdFo2 = _slicedToArray(_flipClaimNameAndIdFo, 2);\n\n claimId = _flipClaimNameAndIdFo2[0];\n claimName = _flipClaimNameAndIdFo2[1];\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, channelName, claimId);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByIdentifierAndClaim;\n\n/***/ }),\n/* 90 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRequest = __webpack_require__(91);\n\nmodule.exports = function (app) {\n app.get('*', handlePageRequest);\n};\n\n/***/ }),\n/* 91 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar handlePageRender = __webpack_require__(14);\n\nvar sendReactApp = function sendReactApp(req, res) {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// index.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 26);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 82ebf2ca30129849e4ef","module.exports = require(\"winston\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"winston\"\n// module id = 0\n// module chunks = 0","const logger = require('winston');\n\nmodule.exports = {\n handleErrorResponse: function (originalUrl, ip, error, res) {\n logger.error(`Error on ${originalUrl}`, module.exports.useObjectPropertiesIfNoKeys(error));\n const [status, message] = module.exports.returnErrorMessageAndStatus(error);\n res\n .status(status)\n .json(module.exports.createErrorResponsePayload(status, message));\n },\n returnErrorMessageAndStatus: function (error) {\n let status, message;\n // check for daemon being turned off\n if (error.code === 'ECONNREFUSED') {\n status = 503;\n message = 'Connection refused. The daemon may not be running.';\n // fallback for everything else\n } else {\n status = 400;\n if (error.message) {\n message = error.message;\n } else {\n message = error;\n };\n };\n return [status, message];\n },\n useObjectPropertiesIfNoKeys: function (err) {\n if (Object.keys(err).length === 0) {\n let newErrorObject = {};\n Object.getOwnPropertyNames(err).forEach((key) => {\n newErrorObject[key] = err[key];\n });\n return newErrorObject;\n }\n return err;\n },\n createErrorResponsePayload (status, message) {\n return {\n status,\n success: false,\n message,\n };\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/errorHandlers.js","const Certificate = require('models/certificate.js');\nconst Channel = require('models/channel.js');\nconst Claim = require('models/claim.js');\nconst File = require('models/file.js');\nconst Request = require('models/request.js');\nconst User = require('models/user.js');\n\nconst Sequelize = require('sequelize');\nconst logger = require('winston');\n\nconst {database, username, password} = require('mysqlConfig.js');\n\n// set sequelize options\nconst sequelize = new Sequelize(database, username, password, {\n host : 'localhost',\n dialect : 'mysql',\n dialectOptions: {decimalNumbers: true},\n logging : false,\n pool : {\n max : 5,\n min : 0,\n idle : 10000,\n acquire: 10000,\n },\n});\n\n// establish mysql connection\nsequelize\n .authenticate()\n .then(() => {\n logger.info('Sequelize has established mysql connection successfully.');\n })\n .catch(err => {\n logger.error('Sequelize was unable to connect to the database:', err);\n });\n\n// manually add each model to the db object (note: make this dynamic)\nconst db = {};\ndb['Certificate'] = sequelize.import('Certificate', Certificate);\ndb['Channel'] = sequelize.import('Channel', Channel);\ndb['Claim'] = sequelize.import('Claim', Claim);\ndb['File'] = sequelize.import('File', File);\ndb['Request'] = sequelize.import('Request', Request);\ndb['User'] = sequelize.import('User', User);\n\n// run model.association for each model in the db object that has an association\nlogger.info('associating db models...');\nObject.keys(db).forEach(modelName => {\n if (db[modelName].associate) {\n logger.info('Associating model:', modelName);\n db[modelName].associate(db);\n }\n});\n\n// add sequelize/Sequelize to db\ndb.sequelize = sequelize;\ndb.Sequelize = Sequelize;\n// add an 'upsert' method to the db object\ndb.upsert = (Model, values, condition, tableName) => {\n return Model\n .findOne({\n where: condition,\n })\n .then(obj => {\n if (obj) { // update\n logger.debug(`updating record in db.${tableName}`);\n return obj.update(values);\n } else { // insert\n logger.debug(`creating record in db.${tableName}`);\n return Model.create(values);\n }\n })\n .catch(function (error) {\n logger.error(`${tableName}.upsert error`, error);\n throw error;\n });\n};\n\nmodule.exports = db;\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/index.js","function SiteConfig () {\n this.analytics = {\n googleId: 'default',\n };\n this.assetDefaults = {\n description: 'An asset published on Spee.ch',\n thumbnail : 'https://spee.ch/assets/img/video_thumb_default.png',\n title : 'Spee.ch',\n };\n this.auth = {\n sessionKey: 'default',\n };\n this.customComponents = {\n components: {},\n containers: {},\n pages : {},\n };\n this.details = {\n description: 'Open-source, decentralized image and video sharing.',\n host : 'default',\n port : 3000,\n title : 'Spee.ch',\n twitter : '@spee_ch',\n };\n this.publishing = {\n additionalClaimAddresses: [],\n disabled : false,\n disabledMessage : 'Please check back soon.',\n primaryClaimAddress : 'default',\n thumbnailChannel : 'default',\n thumbnailChannelId : 'default',\n uploadDirectory : '/home/lbry/Uploads',\n };\n this.routes = {};\n this.update = (config) => {\n if (!config) {\n return console.log('No site config received.');\n }\n const { analytics, assetDefaults, auth, customComponents, details, publishing, routes } = config;\n console.log('Configuring site details...');\n this.analytics = analytics;\n this.assetDefaults = assetDefaults;\n this.auth = auth;\n this.details = details;\n this.publishing = publishing;\n this.customComponents = customComponents;\n this.routes = routes;\n };\n};\n\nmodule.exports = new SiteConfig();\n\n\n\n// WEBPACK FOOTER //\n// ./config/siteConfig.js","const logger = require('winston');\nconst ua = require('universal-analytics');\nconst { analytics : { googleId }, details: { title } } = require('../../config/siteConfig.js');\n\nfunction createServeEventParams (headers, ip, originalUrl) {\n return {\n eventCategory : 'client requests',\n eventAction : 'serve request',\n eventLabel : originalUrl,\n ipOverride : ip,\n userAgentOverride: headers['user-agent'],\n };\n};\n\nfunction createPublishTimingEventParams (category, variable, label, startTime, endTime) {\n const duration = endTime - startTime;\n return {\n userTimingCategory : category,\n userTimingVariableName: variable,\n userTimingTime : duration,\n userTimingLabel : label,\n };\n};\n\nfunction sendGoogleAnalyticsEvent (ip, params) {\n const visitorId = ip.replace(/\\./g, '-');\n const visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.event(params, (err) => {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n });\n};\n\nfunction sendGoogleAnalyticsTiming (visitorId, params) {\n const visitor = ua(googleId, visitorId, { strictCidFormat: false, https: true });\n visitor.timing(params, (err) => {\n if (err) {\n logger.error('Google Analytics Event Error >>', err);\n }\n logger.debug(`Timing event successfully sent to google analytics`);\n });\n};\n\nmodule.exports = {\n sendGAServeEvent (headers, ip, originalUrl) {\n const params = createServeEventParams(headers, ip, originalUrl);\n sendGoogleAnalyticsEvent(ip, params);\n },\n sendGATimingEvent (category, variable, label, startTime, endTime) {\n const params = createPublishTimingEventParams(category, variable, label, startTime, endTime);\n sendGoogleAnalyticsTiming(title, params);\n },\n chooseGaLbrynetPublishLabel ({ channel_name: channelName, channel_id: channelId }) {\n return (channelName || channelId ? 'PUBLISH_IN_CHANNEL_CLAIM' : 'PUBLISH_ANONYMOUS_CLAIM');\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/googleAnalytics.js","const axios = require('axios');\nconst logger = require('winston');\nconst { api: { apiHost, apiPort } } = require('../../config/lbryConfig.js');\nconst lbryApiUri = 'http://' + apiHost + ':' + apiPort;\nconst { chooseGaLbrynetPublishLabel, sendGATimingEvent } = require('./googleAnalytics.js');\n\nconst handleLbrynetResponse = ({ data }, resolve, reject) => {\n logger.debug('lbry api data:', data);\n if (data.result) {\n // check for an error\n if (data.result.error) {\n logger.debug('Lbrynet api error:', data.result.error);\n reject(new Error(data.result.error));\n return;\n };\n resolve(data.result);\n return;\n }\n // fallback in case it just timed out\n reject(JSON.stringify(data));\n};\n\nmodule.exports = {\n publishClaim (publishParams) {\n logger.debug(`lbryApi >> Publishing claim to \"${publishParams.name}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'publish',\n params: publishParams,\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'publish', chooseGaLbrynetPublishLabel(publishParams), gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getClaim (uri) {\n logger.debug(`lbryApi >> Getting Claim for \"${uri}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'get',\n params: { uri, timeout: 20 },\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'getClaim', 'GET', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getClaimList (claimName) {\n logger.debug(`lbryApi >> Getting claim_list for \"${claimName}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'claim_list',\n params: { name: claimName },\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'getClaimList', 'CLAIM_LIST', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n resolveUri (uri) {\n logger.debug(`lbryApi >> Resolving URI for \"${uri}\"`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'resolve',\n params: { uri },\n })\n .then(({ data }) => {\n sendGATimingEvent('lbrynet', 'resolveUri', 'RESOLVE', gaStartTime, Date.now());\n if (data.result[uri].error) { // check for errors\n reject(data.result[uri].error);\n } else { // if no errors, resolve\n resolve(data.result[uri]);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getDownloadDirectory () {\n logger.debug('lbryApi >> Retrieving the download directory path from lbry daemon...');\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'settings_get',\n })\n .then(({ data }) => {\n sendGATimingEvent('lbrynet', 'getDownloadDirectory', 'SETTINGS_GET', gaStartTime, Date.now());\n if (data.result) {\n resolve(data.result.download_directory);\n } else {\n return new Error('Successfully connected to lbry daemon, but unable to retrieve the download directory.');\n }\n })\n .catch(error => {\n logger.error('Lbrynet Error:', error);\n resolve('/home/lbry/Downloads/');\n });\n });\n },\n createChannel (name) {\n logger.debug(`lbryApi >> Creating channel for ${name}...`);\n const gaStartTime = Date.now();\n return new Promise((resolve, reject) => {\n axios\n .post(lbryApiUri, {\n method: 'channel_new',\n params: {\n channel_name: name,\n amount : 0.1,\n },\n })\n .then(response => {\n sendGATimingEvent('lbrynet', 'createChannel', 'CHANNEL_NEW', gaStartTime, Date.now());\n handleLbrynetResponse(response, resolve, reject);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/lbryApi.js","const db = require('models');\nconst logger = require('winston');\nconst { returnPaginatedChannelClaims } = require('helpers/channelPagination.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\nconst NO_CLAIM = 'NO_CLAIM';\nconst NO_FILE = 'NO_FILE';\n\nmodule.exports = {\n getClaimId (channelName, channelClaimId, name, claimId) {\n if (channelName) {\n return module.exports.getClaimIdByChannel(channelName, channelClaimId, name);\n } else {\n return module.exports.getClaimIdByClaim(name, claimId);\n }\n },\n getClaimIdByClaim (claimName, claimId) {\n logger.debug(`getClaimIdByClaim(${claimName}, ${claimId})`);\n return new Promise((resolve, reject) => {\n db.Claim.getLongClaimId(claimName, claimId)\n .then(longClaimId => {\n if (!longClaimId) {\n resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getClaimIdByChannel (channelName, channelClaimId, claimName) {\n logger.debug(`getClaimIdByChannel(${channelName}, ${channelClaimId}, ${claimName})`);\n return new Promise((resolve, reject) => {\n db.Certificate.getLongChannelId(channelName, channelClaimId) // 1. get the long channel id\n .then(longChannelId => {\n if (!longChannelId) {\n return [null, null];\n }\n return Promise.all([longChannelId, db.Claim.getClaimIdByLongChannelId(longChannelId, claimName)]); // 2. get the long claim id\n })\n .then(([longChannelId, longClaimId]) => {\n if (!longChannelId) {\n return resolve(NO_CHANNEL);\n }\n if (!longClaimId) {\n return resolve(NO_CLAIM);\n }\n resolve(longClaimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getChannelData (channelName, channelClaimId, page) {\n return new Promise((resolve, reject) => {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId)\n .then(longChannelClaimId => {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Certificate.getShortChannelIdFromLongChannelId(longChannelClaimId, channelName)]);\n })\n .then(([longChannelClaimId, shortChannelClaimId]) => {\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. return all the channel information\n resolve({\n channelName,\n longChannelClaimId,\n shortChannelClaimId,\n });\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getChannelClaims (channelName, channelClaimId, page) {\n return new Promise((resolve, reject) => {\n // 1. get the long channel Id (make sure channel exists)\n db.Certificate.getLongChannelId(channelName, channelClaimId)\n .then(longChannelClaimId => {\n if (!longChannelClaimId) {\n return [null, null, null];\n }\n // 2. get the short ID and all claims for that channel\n return Promise.all([longChannelClaimId, db.Claim.getAllChannelClaims(longChannelClaimId)]);\n })\n .then(([longChannelClaimId, channelClaimsArray]) => {\n if (!longChannelClaimId) {\n return resolve(NO_CHANNEL);\n }\n // 3. format the data for the view, including pagination\n let paginatedChannelViewData = returnPaginatedChannelClaims(channelName, longChannelClaimId, channelClaimsArray, page);\n // 4. return all the channel information and contents\n resolve(paginatedChannelViewData);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n getLocalFileRecord (claimId, name) {\n return db.File.findOne({where: {claimId, name}})\n .then(file => {\n if (!file) {\n return NO_FILE;\n }\n return file.dataValues;\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/controllers/serveController.js","const passport = require('passport');\nconst localLoginStrategy = require('./local-login.js');\nconst localSignupStrategy = require('./local-signup.js');\nconst { serializeSpeechUser, deserializeSpeechUser } = require('helpers/authHelpers.js');\n\npassport.deserializeUser(deserializeSpeechUser);\npassport.serializeUser(serializeSpeechUser);\npassport.use('local-login', localLoginStrategy);\npassport.use('local-signup', localSignupStrategy);\n\nmodule.exports = passport;\n\n\n\n// WEBPACK FOOTER //\n// ./server/speechPassport/index.js","const logger = require('winston');\nconst db = require('models');\nconst lbryApi = require('helpers/lbryApi.js');\nconst publishHelpers = require('helpers/publishHelpers.js');\nconst { publishing: { primaryClaimAddress, additionalClaimAddresses } } = require('siteConfig.js');\nconst Sequelize = require('sequelize');\nconst Op = Sequelize.Op;\n\nmodule.exports = {\n publish (publishParams, fileName, fileType) {\n return new Promise((resolve, reject) => {\n let publishResults, certificateId, channelName;\n // publish the file\n return lbryApi.publishClaim(publishParams)\n .then(tx => {\n logger.info(`Successfully published ${publishParams.name} ${fileName}`, tx);\n publishResults = tx;\n // get the channel information\n if (publishParams.channel_name) {\n logger.debug(`this claim was published in channel: ${publishParams.channel_name}`);\n return db.Channel.findOne({\n where: {\n channelName: publishParams.channel_name,\n },\n });\n } else {\n logger.debug('this claim was not published in a channel');\n return null;\n }\n })\n .then(channel => {\n // set channel information\n certificateId = null;\n channelName = null;\n if (channel) {\n certificateId = channel.channelClaimId;\n channelName = channel.channelName;\n }\n logger.debug(`certificateId: ${certificateId}`);\n })\n .then(() => {\n // create the File record\n const fileRecord = {\n name : publishParams.name,\n claimId : publishResults.claim_id,\n title : publishParams.metadata.title,\n description: publishParams.metadata.description,\n address : publishParams.claim_address,\n outpoint : `${publishResults.txid}:${publishResults.nout}`,\n height : 0,\n fileName,\n filePath : publishParams.file_path,\n fileType,\n nsfw : publishParams.metadata.nsfw,\n };\n // create the Claim record\n const claimRecord = {\n name : publishParams.name,\n claimId : publishResults.claim_id,\n title : publishParams.metadata.title,\n description: publishParams.metadata.description,\n address : publishParams.claim_address,\n thumbnail : publishParams.metadata.thumbnail,\n outpoint : `${publishResults.txid}:${publishResults.nout}`,\n height : 0,\n contentType: fileType,\n nsfw : publishParams.metadata.nsfw,\n amount : publishParams.bid,\n certificateId,\n channelName,\n };\n // upsert criteria\n const upsertCriteria = {\n name : publishParams.name,\n claimId: publishResults.claim_id,\n };\n // upsert the records\n return Promise.all([db.upsert(db.File, fileRecord, upsertCriteria, 'File'), db.upsert(db.Claim, claimRecord, upsertCriteria, 'Claim')]);\n })\n .then(([file, claim]) => {\n logger.debug('File and Claim records successfully created');\n return Promise.all([file.setClaim(claim), claim.setFile(file)]);\n })\n .then(() => {\n logger.debug('File and Claim records successfully associated');\n resolve(publishResults); // resolve the promise with the result from lbryApi.publishClaim;\n })\n .catch(error => {\n logger.error('PUBLISH ERROR', error);\n publishHelpers.deleteTemporaryFile(publishParams.file_path); // delete the local file\n reject(error);\n });\n });\n },\n claimNameIsAvailable (name) {\n const claimAddresses = additionalClaimAddresses || [];\n claimAddresses.push(primaryClaimAddress);\n // find any records where the name is used\n return db.Claim\n .findAll({\n attributes: ['address'],\n where : {\n name,\n address: {\n [Op.or]: claimAddresses,\n },\n },\n })\n .then(result => {\n if (result.length >= 1) {\n throw new Error('That claim is already in use');\n };\n return name;\n })\n .catch(error => {\n throw error;\n });\n },\n checkChannelAvailability (name) {\n return db.Channel\n .findAll({\n where: { channelName: name },\n })\n .then(result => {\n if (result.length >= 1) {\n throw new Error('That channel has already been claimed');\n }\n return name;\n })\n .catch(error => {\n throw error;\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/controllers/publishController.js","const logger = require('winston');\nconst fs = require('fs');\n\nconst { details, publishing } = require('../../config/siteConfig.js');\n\nmodule.exports = {\n parsePublishApiRequestBody ({name, nsfw, license, title, description, thumbnail}) {\n // validate name\n if (!name) {\n throw new Error('no name field found in request');\n }\n const invalidNameCharacters = /[^A-Za-z0-9,-]/.exec(name);\n if (invalidNameCharacters) {\n throw new Error('The claim name you provided is not allowed. Only the following characters are allowed: A-Z, a-z, 0-9, and \"-\"');\n }\n // optional parameters\n nsfw = (nsfw === 'true');\n license = license || null;\n title = title || null;\n description = description || null;\n thumbnail = thumbnail || null;\n // return results\n return {\n name,\n nsfw,\n license,\n title,\n description,\n thumbnail,\n };\n },\n parsePublishApiRequestFiles ({file, thumbnail}) {\n // make sure a file was provided\n if (!file) {\n throw new Error('no file with key of [file] found in request');\n }\n if (!file.path) {\n throw new Error('no file path found');\n }\n if (!file.type) {\n throw new Error('no file type found');\n }\n if (!file.size) {\n throw new Error('no file type found');\n }\n // validate the file name\n if (/'/.test(file.name)) {\n throw new Error('apostrophes are not allowed in the file name');\n }\n // validate the file\n module.exports.validateFileTypeAndSize(file);\n // return results\n return {\n fileName : file.name,\n filePath : file.path,\n fileType : file.type,\n thumbnailFileName: (thumbnail ? thumbnail.name : null),\n thumbnailFilePath: (thumbnail ? thumbnail.path : null),\n thumbnailFileType: (thumbnail ? thumbnail.type : null),\n };\n },\n validateFileTypeAndSize (file) {\n // check file type and size\n switch (file.type) {\n case 'image/jpeg':\n case 'image/jpg':\n case 'image/png':\n if (file.size > 10000000) {\n logger.debug('publish > file validation > .jpeg/.jpg/.png was too big');\n throw new Error('Sorry, images are limited to 10 megabytes.');\n }\n break;\n case 'image/gif':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .gif was too big');\n throw new Error('Sorry, .gifs are limited to 50 megabytes.');\n }\n break;\n case 'video/mp4':\n if (file.size > 50000000) {\n logger.debug('publish > file validation > .mp4 was too big');\n throw new Error('Sorry, videos are limited to 50 megabytes.');\n }\n break;\n default:\n logger.debug('publish > file validation > unrecognized file type');\n throw new Error('The ' + file.type + ' content type is not supported. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.');\n }\n return file;\n },\n createBasicPublishParams (filePath, name, title, description, license, nsfw, thumbnail) {\n logger.debug(`Creating Publish Parameters`);\n // provide defaults for title\n if (title === null || title.trim() === '') {\n title = name;\n }\n // provide default for description\n if (description === null || description.trim() === '') {\n description = '';\n }\n // provide default for license\n if (license === null || license.trim() === '') {\n license = ' '; // default to empty string\n }\n // create the publish params\n const publishParams = {\n name,\n file_path: filePath,\n bid : 0.01,\n metadata : {\n description,\n title,\n author : details.title,\n language: 'en',\n license,\n nsfw,\n },\n claim_address: publishing.primaryClaimAddress,\n };\n // add thumbnail to channel if video\n if (thumbnail) {\n publishParams['metadata']['thumbnail'] = thumbnail;\n }\n return publishParams;\n },\n createThumbnailPublishParams (thumbnailFilePath, claimName, license, nsfw) {\n if (!thumbnailFilePath) {\n return;\n }\n logger.debug(`Creating Thumbnail Publish Parameters`);\n // create the publish params\n return {\n name : `${claimName}-thumb`,\n file_path: thumbnailFilePath,\n bid : 0.01,\n metadata : {\n title : `${claimName} thumbnail`,\n description: `a thumbnail for ${claimName}`,\n author : details.title,\n language : 'en',\n license,\n nsfw,\n },\n claim_address: publishing.primaryClaimAddress,\n channel_name : publishing.thumbnailChannel,\n channel_id : publishing.thumbnailChannelId,\n };\n },\n deleteTemporaryFile (filePath) {\n fs.unlink(filePath, err => {\n if (err) {\n logger.error(`error deleting temporary file ${filePath}`);\n throw err;\n }\n logger.debug(`successfully deleted ${filePath}`);\n });\n },\n addGetResultsToFileData (fileInfo, getResult) {\n fileInfo.fileName = getResult.file_name;\n fileInfo.filePath = getResult.download_path;\n return fileInfo;\n },\n createFileData ({ name, claimId, outpoint, height, address, nsfw, contentType }) {\n return {\n name,\n claimId,\n outpoint,\n height,\n address,\n fileName: '',\n filePath: '',\n fileType: contentType,\n nsfw,\n };\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/publishHelpers.js","const logger = require('winston');\n\nfunction mysql () {\n this.database = 'default';\n this.username = 'default';\n this.password = 'default';\n this.update = (config) => {\n if (!config) {\n return logger.warn('No MySQL config received.');\n }\n // configure credentials\n logger.info('configuring mysql...');\n const { database, username, password } = config;\n this.database = database;\n this.username = username;\n this.password = password;\n };\n};\n\nmodule.exports = new mysql();\n\n\n\n// WEBPACK FOOTER //\n// ./config/mysqlConfig.js","module.exports = require(\"passport-local\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"passport-local\"\n// module id = 11\n// module chunks = 0","module.exports = {\n returnShortId: function (claimsArray, longId) {\n let claimIndex;\n let shortId = longId.substring(0, 1); // default short id is the first letter\n let shortIdLength = 0;\n // find the index of this claim id\n claimIndex = claimsArray.findIndex(element => {\n return element.claimId === longId;\n });\n if (claimIndex < 0) {\n throw new Error('claim id not found in claims list');\n }\n // get an array of all claims with lower height\n let possibleMatches = claimsArray.slice(0, claimIndex);\n // remove certificates with the same prefixes until none are left.\n while (possibleMatches.length > 0) {\n shortIdLength += 1;\n shortId = longId.substring(0, shortIdLength);\n possibleMatches = possibleMatches.filter(element => {\n return (element.claimId && (element.claimId.substring(0, shortIdLength) === shortId));\n });\n }\n return shortId;\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/sequelizeHelpers.js","module.exports = require(\"sequelize\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"sequelize\"\n// module id = 13\n// module chunks = 0","import React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport { createStore } from 'redux';\nimport { Provider } from 'react-redux';\nimport { StaticRouter } from 'react-router-dom';\nimport { Reducers, GAListener, App } from 'spee.ch-components';\nimport renderFullPage from './renderFullPage.js';\nimport Helmet from 'react-helmet';\n\nconst siteConfig = require('siteConfig.js');\n\nmodule.exports = (req, res) => {\n let context = {};\n\n // customize the reducer by passing in intial state configs\n const customizedReducers = Reducers(siteConfig);\n\n // create a new Redux store instance\n const store = createStore(customizedReducers);\n\n // render component to a string\n const html = renderToString(\n \n \n \n \n \n \n \n );\n\n // get head tags from helmet\n const helmet = Helmet.renderStatic();\n\n // check for a redirect\n if (context.url) {\n // Somewhere a `` was rendered\n return res.redirect(301, context.url);\n } else {\n // we're good, send the response\n }\n\n // get the initial state from our Redux store\n const preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send(renderFullPage(helmet, html, preloadedState));\n\n console.log('hello from spee.ch handlePageRender.jsx');\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/handlePageRender.jsx","module.exports = require(\"react\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react\"\n// module id = 15\n// module chunks = 0","module.exports = require(\"react-dom/server\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-dom/server\"\n// module id = 16\n// module chunks = 0","module.exports = require(\"redux\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"redux\"\n// module id = 17\n// module chunks = 0","module.exports = require(\"react-redux\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-redux\"\n// module id = 18\n// module chunks = 0","module.exports = require(\"react-router-dom\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-router-dom\"\n// module id = 19\n// module chunks = 0","module.exports = require(\"spee.ch-components\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"spee.ch-components\"\n// module id = 20\n// module chunks = 0","module.exports = (helmet, html, preloadedState) => {\n // take the html and preloadedState and return the full page\n return `\n \n \n \n \n \n \n \n ${helmet.title.toString()}\n ${helmet.meta.toString()}\n ${helmet.link.toString()}\n \n \n \n \n \n \n \n \n
\n
${html}
\n
\n \n \n \n \n `;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/renderFullPage.js","module.exports = require(\"react-helmet\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"react-helmet\"\n// module id = 22\n// module chunks = 0","const logger = require('winston');\nconst { getClaimId, getLocalFileRecord } = require('../controllers/serveController.js');\nconst { handleErrorResponse } = require('./errorHandlers.js');\n\nconst SERVE = 'SERVE';\nconst SHOW = 'SHOW';\nconst NO_FILE = 'NO_FILE';\nconst NO_CHANNEL = 'NO_CHANNEL';\nconst NO_CLAIM = 'NO_CLAIM';\n\nfunction clientAcceptsHtml ({accept}) {\n return accept && accept.match(/text\\/html/);\n};\n\nfunction requestIsFromBrowser (headers) {\n return headers['user-agent'] && headers['user-agent'].match(/Mozilla/);\n};\n\nfunction clientWantsAsset ({accept, range}) {\n const imageIsWanted = accept && accept.match(/image\\/.*/) && !accept.match(/text\\/html/) && !accept.match(/text\\/\\*/);\n const videoIsWanted = accept && range;\n return imageIsWanted || videoIsWanted;\n};\n\nfunction isValidClaimId (claimId) {\n return ((claimId.length === 40) && !/[^A-Za-z0-9]/g.test(claimId));\n};\n\nfunction isValidShortId (claimId) {\n return claimId.length === 1; // it should really evaluate the short url itself\n};\n\nfunction isValidShortIdOrClaimId (input) {\n return (isValidClaimId(input) || isValidShortId(input));\n};\n\nfunction serveAssetToClient (claimId, name, res) {\n return getLocalFileRecord(claimId, name)\n .then(fileRecord => {\n // check that a local record was found\n if (fileRecord === NO_FILE) {\n return res.status(307).redirect(`/api/claim/get/${name}/${claimId}`);\n }\n // serve the file\n const {filePath, fileType} = fileRecord;\n logger.verbose(`serving file: ${filePath}`);\n const sendFileOptions = {\n headers: {\n 'X-Content-Type-Options': 'nosniff',\n 'Content-Type' : fileType || 'image/jpeg',\n },\n };\n res.status(200).sendFile(filePath, sendFileOptions);\n })\n .catch(error => {\n throw error;\n });\n};\n\nmodule.exports = {\n getClaimIdAndServeAsset (channelName, channelClaimId, claimName, claimId, originalUrl, ip, res) {\n // get the claim Id and then serve the asset\n getClaimId(channelName, channelClaimId, claimName, claimId)\n .then(fullClaimId => {\n if (fullClaimId === NO_CLAIM) {\n return res.status(404).json({success: false, message: 'no claim id could be found'});\n } else if (fullClaimId === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'no channel id could be found'});\n }\n serveAssetToClient(fullClaimId, claimName, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'success');\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n // postToStats(responseType, originalUrl, ip, claimName, fullClaimId, 'fail');\n });\n },\n determineResponseType (hasFileExtension, headers) {\n let responseType;\n if (hasFileExtension) {\n responseType = SERVE; // assume a serve request if file extension is present\n if (clientAcceptsHtml(headers)) { // if the request comes from a browser, change it to a show request\n responseType = SHOW;\n }\n } else {\n responseType = SHOW;\n if (clientWantsAsset(headers) && requestIsFromBrowser(headers)) { // this is in case someone embeds a show url\n logger.debug('Show request came from browser but wants an image/video. Changing response to serve...');\n responseType = SERVE;\n }\n }\n return responseType;\n },\n flipClaimNameAndIdForBackwardsCompatibility (identifier, name) {\n // this is a patch for backwards compatability with '/name/claim_id' url format\n if (isValidShortIdOrClaimId(name) && !isValidShortIdOrClaimId(identifier)) {\n const tempName = name;\n name = identifier;\n identifier = tempName;\n }\n return [identifier, name];\n },\n logRequestData (responseType, claimName, channelName, claimId) {\n logger.debug('responseType ===', responseType);\n logger.debug('claim name === ', claimName);\n logger.debug('channel name ===', channelName);\n logger.debug('claim id ===', claimId);\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/serveHelpers.js","const logger = require('winston');\n\nmodule.exports = {\n REGEXP_INVALID_CLAIM : /[^A-Za-z0-9-]/g,\n REGEXP_INVALID_CHANNEL: /[^A-Za-z0-9-@]/g,\n REGEXP_ADDRESS : /^b(?=[^0OIl]{32,33})[0-9A-Za-z]{32,33}$/,\n CHANNEL_CHAR : '@',\n parseIdentifier : function (identifier) {\n logger.debug('parsing identifier:', identifier);\n const componentsRegex = new RegExp(\n '([^:$#/]*)' + // value (stops at the first separator or end)\n '([:$#]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n const [proto, value, modifierSeperator, modifier] = componentsRegex\n .exec(identifier)\n .map(match => match || null);\n logger.debug(`${proto}, ${value}, ${modifierSeperator}, ${modifier}`);\n\n // Validate and process name\n if (!value) {\n throw new Error(`Check your url. No channel name provided before \"${modifierSeperator}\"`);\n }\n const isChannel = value.startsWith(module.exports.CHANNEL_CHAR);\n const channelName = isChannel ? value : null;\n let claimId;\n if (isChannel) {\n if (!channelName) {\n throw new Error('No channel name after @.');\n }\n const nameBadChars = (channelName).match(module.exports.REGEXP_INVALID_CHANNEL);\n if (nameBadChars) {\n throw new Error(`Invalid characters in channel name: ${nameBadChars.join(', ')}.`);\n }\n } else {\n claimId = value;\n }\n\n // Validate and process modifier\n let channelClaimId;\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error(`No modifier provided after separator \"${modifierSeperator}\"`);\n }\n\n if (modifierSeperator === ':') {\n channelClaimId = modifier;\n } else {\n throw new Error(`The \"${modifierSeperator}\" modifier is not currently supported`);\n }\n }\n return {\n isChannel,\n channelName,\n channelClaimId,\n claimId,\n };\n },\n parseClaim: function (claim) {\n logger.debug('parsing name:', claim);\n const componentsRegex = new RegExp(\n '([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n const [proto, claimName, modifierSeperator, modifier] = componentsRegex\n .exec(claim)\n .map(match => match || null);\n logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);\n\n // Validate and process name\n if (!claimName) {\n throw new Error('No claim name provided before .');\n }\n const nameBadChars = (claimName).match(module.exports.REGEXP_INVALID_CLAIM);\n if (nameBadChars) {\n throw new Error(`Invalid characters in claim name: ${nameBadChars.join(', ')}.`);\n }\n // Validate and process modifier\n if (modifierSeperator) {\n if (!modifier) {\n throw new Error(`No file extension provided after separator ${modifierSeperator}.`);\n }\n if (modifierSeperator !== '.') {\n throw new Error(`The ${modifierSeperator} modifier is not supported in the claim name`);\n }\n }\n // return results\n return {\n claimName,\n };\n },\n parseModifier: function (claim) {\n logger.debug('parsing modifier:', claim);\n const componentsRegex = new RegExp(\n '([^:$#/.]*)' + // name (stops at the first modifier)\n '([:$#.]?)([^/]*)' // modifier separator, modifier (stops at the first path separator or end)\n );\n const [proto, claimName, modifierSeperator, modifier] = componentsRegex\n .exec(claim)\n .map(match => match || null);\n logger.debug(`${proto}, ${claimName}, ${modifierSeperator}, ${modifier}`);\n // Validate and process modifier\n let hasFileExtension = false;\n if (modifierSeperator) {\n hasFileExtension = true;\n }\n return {\n hasFileExtension,\n };\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/lbryUri.js","import React from 'react';\nimport { renderToString } from 'react-dom/server';\nimport { createStore, applyMiddleware } from 'redux';\nimport { Provider } from 'react-redux';\nimport { StaticRouter } from 'react-router-dom';\nimport renderFullPage from './renderFullPage';\nimport createSagaMiddleware from 'redux-saga';\nimport { call } from 'redux-saga/effects';\nimport { Reducers, GAListener, App, Sagas, Actions } from 'spee.ch-components';\n\nimport Helmet from 'react-helmet';\n\n// configure the reducers by passing initial state configs\nconst siteConfig = require('siteConfig.js');\nconst customizedReducers = Reducers(siteConfig);\n\nconst returnSagaWithParams = (saga, params) => {\n return function * () {\n yield call(saga, params);\n };\n};\n\nmodule.exports = (req, res) => {\n let context = {};\n\n // create and apply middleware\n const sagaMiddleware = createSagaMiddleware();\n const middleware = applyMiddleware(sagaMiddleware);\n\n // create a new Redux store instance\n const store = createStore(customizedReducers, middleware);\n\n // create saga\n const action = Actions.onHandleShowPageUri(req.params);\n const saga = returnSagaWithParams(Sagas.handleShowPageUri, action);\n\n // run the saga middleware\n sagaMiddleware\n .run(saga)\n .done\n .then(() => {\n // render component to a string\n const html = renderToString(\n \n \n \n \n \n \n \n );\n\n // get head tags from helmet\n const helmet = Helmet.renderStatic();\n\n // check for a redirect\n if (context.url) {\n return res.redirect(301, context.url);\n }\n\n // get the initial state from our Redux store\n const preloadedState = store.getState();\n\n // send the rendered page back to the client\n res.send(renderFullPage(helmet, html, preloadedState));\n });\n\n console.log('hello from spee.ch handleShowRender.jsx');\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/handleShowRender.jsx","module.exports = require(\"babel-polyfill\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"babel-polyfill\"\n// module id = 27\n// module chunks = 0","module.exports = require(\"whatwg-fetch\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"whatwg-fetch\"\n// module id = 28\n// module chunks = 0","const Server = require('./server');\n\nconst exports = {\n Server,\n};\n\nmodule.exports = exports;\n\n\n\n// WEBPACK FOOTER //\n// ./speech.js","// app dependencies\nconst express = require('express');\nconst bodyParser = require('body-parser');\nconst expressHandlebars = require('express-handlebars');\nconst Handlebars = require('handlebars');\nconst helmet = require('helmet');\nconst cookieSession = require('cookie-session');\nconst http = require('http');\nconst logger = require('winston');\nconst requestLogger = require('middleware/requestLogger.js');\nconst Path = require('path');\nconst loggerConfig = require('loggerConfig.js');\nconst mysqlConfig = require('mysqlConfig.js');\nconst siteConfig = require('siteConfig.js');\nconst slackConfig = require('slackConfig.js');\n\nfunction Server () {\n this.configureLogger = (userConfig) => {\n loggerConfig.update(userConfig);\n };\n this.configureMysql = (userConfig) => {\n mysqlConfig.update(userConfig);\n };\n this.configureSiteDetails = (userConfig) => {\n siteConfig.update(userConfig);\n };\n this.configureSlack = (userConfig) => {\n slackConfig.update(userConfig);\n };\n this.configureClientBundle = () => {\n logger.debug('configure the client here by passing in the bundle and configuring it, or better yet: taking in the components to use dynamically from here.');\n };\n this.configureModels = () => {\n logger.debug('here is where you could add/overwrite the default models')\n };\n this.configureRoutes = () => {\n logger.debug('here is where you could add/overwrite the default routes')\n };\n this.createApp = () => {\n // create an Express application\n const app = express();\n\n // trust the proxy to get ip address for us\n app.enable('trust proxy');\n\n /* add middleware */\n // set HTTP headers to protect against well-known web vulnerabilties\n app.use(helmet());\n // 'express.static' to serve static files from public directory\n if (siteConfig.routes.publicFolder) {\n // take in a different public folder, so it can serve it's own bundle if needed\n const publicFolder = Path.resolve(process.cwd(), siteConfig.routes.publicFolder);\n app.use('/static', express.static(publicFolder));\n logger.info('serving static files from custom path:', publicFolder);\n } else {\n const publicPath = Path.resolve(__dirname, 'public');\n app.use('/static', express.static(publicPath));\n logger.info('serving static files from default path:', publicPath);\n };\n // 'body parser' for parsing application/json\n app.use(bodyParser.json());\n // 'body parser' for parsing application/x-www-form-urlencoded\n app.use(bodyParser.urlencoded({ extended: true }));\n\n // add custom middleware (note: build out to accept dynamically use what is in server/middleware/\n app.use(requestLogger);\n\n // configure passport\n const speechPassport = require('speechPassport');\n // initialize passport\n const sessionKey = siteConfig.auth.sessionKey;\n app.use(cookieSession({\n name : 'session',\n keys : [sessionKey],\n maxAge: 24 * 60 * 60 * 1000, // i.e. 24 hours\n }));\n app.use(speechPassport.initialize());\n app.use(speechPassport.session());\n\n // configure handlebars & register it with express app\n const hbs = expressHandlebars.create({\n defaultLayout: 'embed',\n handlebars : Handlebars,\n });\n app.engine('handlebars', hbs.engine);\n app.set('view engine', 'handlebars');\n\n // set the routes on the app\n require('./routes/auth/')(app);\n require('./routes/api/')(app);\n require('./routes/pages/')(app);\n require('./routes/assets/')(app);\n require('./routes/fallback/')(app);\n\n this.app = app;\n };\n this.initialize = () => {\n this.createApp();\n this.server = http.Server(this.app);\n };\n this.start = () => {\n const db = require('models');\n const PORT = siteConfig.details.port;\n // sync sequelize\n db.sequelize.sync()\n // start the server\n .then(() => {\n this.server.listen(PORT, () => {\n logger.info(`Server is listening on PORT ${PORT}`);\n });\n })\n .catch((error) => {\n logger.error(`Startup Error:`, error);\n });\n };\n};\n\nmodule.exports = Server;\n\n\n\n// WEBPACK FOOTER //\n// ./server/index.js","module.exports = require(\"express\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"express\"\n// module id = 31\n// module chunks = 0","module.exports = require(\"body-parser\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"body-parser\"\n// module id = 32\n// module chunks = 0","module.exports = require(\"express-handlebars\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"express-handlebars\"\n// module id = 33\n// module chunks = 0","module.exports = require(\"handlebars\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"handlebars\"\n// module id = 34\n// module chunks = 0","module.exports = require(\"helmet\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"helmet\"\n// module id = 35\n// module chunks = 0","module.exports = require(\"cookie-session\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"cookie-session\"\n// module id = 36\n// module chunks = 0","module.exports = require(\"http\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"http\"\n// module id = 37\n// module chunks = 0","const logger = require('winston');\n\nconst requestLogger = (req, res, next) => { // custom logging middleware to log all incoming http requests\n logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`);\n next();\n};\n\nmodule.exports = requestLogger;\n\n\n\n// WEBPACK FOOTER //\n// ./server/middleware/requestLogger.js","module.exports = require(\"path\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"path\"\n// module id = 39\n// module chunks = 0","const logger = require('winston');\n\nfunction LoggerConfig () {\n this.logLevel = 'debug';\n this.update = (config) => {\n if (!config) {\n return logger.warn('No logger config received.');\n }\n logger.info('configuring winston logger...');\n // update values with local config params\n const {logLevel} = config;\n this.logLevel = logLevel;\n // configure the winston logger\n logger.configure({\n transports: [\n new (logger.transports.Console)({\n level : this.logLevel,\n timestamp : false,\n colorize : true,\n prettyPrint : true,\n handleExceptions : true,\n humanReadableUnhandledException: true,\n }),\n ],\n });\n // test all the log levels\n logger.info('testing winston log levels...');\n logger.error('Level 0');\n logger.warn('Level 1');\n logger.info('Level 2');\n logger.verbose('Level 3');\n logger.debug('Level 4');\n logger.silly('Level 5');\n };\n};\n\nmodule.exports = new LoggerConfig();\n\n\n\n// WEBPACK FOOTER //\n// ./config/loggerConfig.js","const winstonSlackWebHook = require('winston-slack-webhook').SlackWebHook;\nconst winston = require('winston');\n\nfunction SlackConfig () {\n this.slackWebHook = 'default';\n this.slackErrorChannel = 'default';\n this.slackInfoChannel = 'default';\n this.update = (config) => {\n if (!config) {\n return winston.warn('No slack config received');\n }\n // update variables\n winston.info('configuring slack logger...');\n const {slackWebHook, slackErrorChannel, slackInfoChannel} = config;\n this.slackWebHook = slackWebHook;\n this.slackErrorChannel = slackErrorChannel;\n this.slackInfoChannel = slackInfoChannel;\n // update slack webhook settings\n if (this.slackWebHook) {\n // add a transport for errors to slack\n if (this.slackErrorChannel) {\n winston.add(winstonSlackWebHook, {\n name : 'slack-errors-transport',\n level : 'warn',\n webhookUrl: this.slackWebHook,\n channel : this.slackErrorChannel,\n username : 'spee.ch',\n iconEmoji : ':face_with_head_bandage:',\n });\n };\n if (slackInfoChannel) {\n winston.add(winstonSlackWebHook, {\n name : 'slack-info-transport',\n level : 'info',\n webhookUrl: this.slackWebHook,\n channel : this.slackInfoChannel,\n username : 'spee.ch',\n iconEmoji : ':nerd_face:',\n });\n };\n // send test messages\n winston.info('testing slack logger...');\n winston.error('Slack \"error\" logging is online.');\n winston.info('Slack \"info\" logging is online.');\n } else {\n winston.warn('Slack logging is not enabled because no slackWebHook config var provided.');\n }\n };\n};\n\nmodule.exports = new SlackConfig();\n\n\n\n// WEBPACK FOOTER //\n// ./config/slackConfig.js","module.exports = require(\"winston-slack-webhook\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"winston-slack-webhook\"\n// module id = 42\n// module chunks = 0","module.exports = require(\"passport\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"passport\"\n// module id = 43\n// module chunks = 0","const PassportLocalStrategy = require('passport-local').Strategy;\nconst logger = require('winston');\nconst db = require('models');\n\nconst returnUserAndChannelInfo = (userInstance) => {\n return new Promise((resolve, reject) => {\n let userInfo = {};\n userInfo['id'] = userInstance.id;\n userInfo['userName'] = userInstance.userName;\n userInstance\n .getChannel()\n .then(({channelName, channelClaimId}) => {\n userInfo['channelName'] = channelName;\n userInfo['channelClaimId'] = channelClaimId;\n return db.Certificate.getShortChannelIdFromLongChannelId(channelClaimId, channelName);\n })\n .then(shortChannelId => {\n userInfo['shortChannelId'] = shortChannelId;\n resolve(userInfo);\n })\n .catch(error => {\n reject(error);\n });\n });\n};\n\nmodule.exports = new PassportLocalStrategy(\n {\n usernameField: 'username',\n passwordField: 'password',\n },\n (username, password, done) => {\n return db.User\n .findOne({\n where: {userName: username},\n })\n .then(user => {\n if (!user) {\n logger.debug('no user found');\n return done(null, false, {message: 'Incorrect username or password'});\n }\n return user.comparePassword(password)\n .then(isMatch => {\n if (!isMatch) {\n logger.debug('incorrect password');\n return done(null, false, {message: 'Incorrect username or password'});\n }\n logger.debug('Password was a match, returning User');\n return returnUserAndChannelInfo(user)\n .then(userInfo => {\n return done(null, userInfo);\n })\n .catch(error => {\n return error;\n });\n })\n .catch(error => {\n return error;\n });\n })\n .catch(error => {\n return done(error);\n });\n },\n);\n\n\n\n// WEBPACK FOOTER //\n// ./server/speechPassport/local-login.js","const logger = require('winston');\nconst { returnShortId } = require('../helpers/sequelizeHelpers.js');\n\nmodule.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {\n const Certificate = sequelize.define(\n 'Certificate',\n {\n address: {\n type : STRING,\n default: null,\n },\n amount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n claimId: {\n type : STRING,\n default: null,\n },\n claimSequence: {\n type : INTEGER,\n default: null,\n },\n decodedClaim: {\n type : BOOLEAN,\n default: null,\n },\n depth: {\n type : INTEGER,\n default: null,\n },\n effectiveAmount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n hasSignature: {\n type : BOOLEAN,\n default: null,\n },\n height: {\n type : INTEGER,\n default: null,\n },\n hex: {\n type : TEXT('long'),\n default: null,\n },\n name: {\n type : STRING,\n default: null,\n },\n nout: {\n type : INTEGER,\n default: null,\n },\n txid: {\n type : STRING,\n default: null,\n },\n validAtHeight: {\n type : INTEGER,\n default: null,\n },\n outpoint: {\n type : STRING,\n default: null,\n },\n valueVersion: {\n type : STRING,\n default: null,\n },\n claimType: {\n type : STRING,\n default: null,\n },\n certificateVersion: {\n type : STRING,\n default: null,\n },\n keyType: {\n type : STRING,\n default: null,\n },\n publicKey: {\n type : TEXT('long'),\n default: null,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Certificate.associate = db => {\n Certificate.belongsTo(db.Channel, {\n foreignKey: {\n allowNull: true,\n },\n });\n };\n\n Certificate.getShortChannelIdFromLongChannelId = function (longChannelId, channelName) {\n logger.debug(`getShortChannelIdFromLongChannelId ${channelName}:${longChannelId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: {name: channelName},\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n throw new Error('No channel(s) found with that channel name');\n default:\n return resolve(returnShortId(result, longChannelId));\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromShortChannelId = function (channelName, channelClaimId) {\n logger.debug(`getLongChannelIdFromShortChannelId(${channelName}, ${channelClaimId})`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: {\n name : channelName,\n claimId: {\n $like: `${channelClaimId}%`,\n },\n },\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n default: // note results must be sorted\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelIdFromChannelName = function (channelName) {\n logger.debug(`getLongChannelIdFromChannelName(${channelName})`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name: channelName },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.validateLongChannelId = function (name, claimId) {\n logger.debug(`validateLongChannelId(${name}, ${claimId})`);\n return new Promise((resolve, reject) => {\n this.findOne({\n where: {name, claimId},\n })\n .then(result => {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Certificate.getLongChannelId = function (channelName, channelClaimId) {\n logger.debug(`getLongChannelId(${channelName}, ${channelClaimId})`);\n if (channelClaimId && (channelClaimId.length === 40)) { // if a full channel id is provided\n return this.validateLongChannelId(channelName, channelClaimId);\n } else if (channelClaimId && channelClaimId.length < 40) { // if a short channel id is provided\n return this.getLongChannelIdFromShortChannelId(channelName, channelClaimId);\n } else {\n return this.getLongChannelIdFromChannelName(channelName); // if no channel id provided\n }\n };\n\n return Certificate;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/certificate.js","module.exports = (sequelize, { STRING }) => {\n const Channel = sequelize.define(\n 'Channel',\n {\n channelName: {\n type : STRING,\n allowNull: false,\n },\n channelClaimId: {\n type : STRING,\n allowNull: false,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Channel.associate = db => {\n Channel.belongsTo(db.User);\n Channel.hasOne(db.Certificate);\n };\n\n return Channel;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/channel.js","const logger = require('winston');\nconst { returnShortId } = require('../helpers/sequelizeHelpers.js');\nconst { assetDefaults: { thumbnail: defaultThumbnail }, details: { host } } = require('../../config/siteConfig.js');\n\nfunction determineFileExtensionFromContentType (contentType) {\n switch (contentType) {\n case 'image/jpeg':\n case 'image/jpg':\n return 'jpeg';\n case 'image/png':\n return 'png';\n case 'image/gif':\n return 'gif';\n case 'video/mp4':\n return 'mp4';\n default:\n logger.debug('setting unknown file type as file extension jpeg');\n return 'jpeg';\n }\n};\n\nfunction determineThumbnail (storedThumbnail, defaultThumbnail) {\n if (storedThumbnail === '') {\n return defaultThumbnail;\n }\n return storedThumbnail;\n};\n\nfunction prepareClaimData (claim) {\n // logger.debug('preparing claim data based on resolved data:', claim);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['host'] = host;\n return claim;\n};\n\nmodule.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {\n const Claim = sequelize.define(\n 'Claim',\n {\n address: {\n type : STRING,\n default: null,\n },\n amount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n claimId: {\n type : STRING,\n default: null,\n },\n claimSequence: {\n type : INTEGER,\n default: null,\n },\n decodedClaim: {\n type : BOOLEAN,\n default: null,\n },\n depth: {\n type : INTEGER,\n default: null,\n },\n effectiveAmount: {\n type : DECIMAL(19, 8),\n default: null,\n },\n hasSignature: {\n type : BOOLEAN,\n default: null,\n },\n height: {\n type : INTEGER,\n default: null,\n },\n hex: {\n type : TEXT('long'),\n default: null,\n },\n name: {\n type : STRING,\n default: null,\n },\n nout: {\n type : INTEGER,\n default: null,\n },\n txid: {\n type : STRING,\n default: null,\n },\n validAtHeight: {\n type : INTEGER,\n default: null,\n },\n outpoint: {\n type : STRING,\n default: null,\n },\n claimType: {\n type : STRING,\n default: null,\n },\n certificateId: {\n type : STRING,\n default: null,\n },\n author: {\n type : STRING,\n default: null,\n },\n description: {\n type : TEXT('long'),\n default: null,\n },\n language: {\n type : STRING,\n default: null,\n },\n license: {\n type : STRING,\n default: null,\n },\n licenseUrl: {\n type : STRING,\n default: null,\n },\n nsfw: {\n type : BOOLEAN,\n default: null,\n },\n preview: {\n type : STRING,\n default: null,\n },\n thumbnail: {\n type : STRING,\n default: null,\n },\n title: {\n type : STRING,\n default: null,\n },\n metadataVersion: {\n type : STRING,\n default: null,\n },\n contentType: {\n type : STRING,\n default: null,\n },\n source: {\n type : STRING,\n default: null,\n },\n sourceType: {\n type : STRING,\n default: null,\n },\n sourceVersion: {\n type : STRING,\n default: null,\n },\n streamVersion: {\n type : STRING,\n default: null,\n },\n valueVersion: {\n type : STRING,\n default: null,\n },\n channelName: {\n type : STRING,\n allowNull: true,\n default : null,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Claim.associate = db => {\n Claim.belongsTo(db.File, {\n foreignKey: {\n allowNull: true,\n },\n });\n };\n\n Claim.getShortClaimIdFromLongClaimId = function (claimId, claimName) {\n logger.debug(`Claim.getShortClaimIdFromLongClaimId for ${claimName}#${claimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name: claimName },\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n throw new Error('No claim(s) found with that claim name');\n default:\n resolve(returnShortId(result, claimId));\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getAllChannelClaims = function (channelClaimId) {\n logger.debug(`Claim.getAllChannelClaims for ${channelClaimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { certificateId: channelClaimId },\n order: [['height', 'ASC']],\n raw : true, // returns an array of only data, not an array of instances\n })\n .then(channelClaimsArray => {\n // logger.debug('channelclaimsarray length:', channelClaimsArray.length);\n switch (channelClaimsArray.length) {\n case 0:\n return resolve(null);\n default:\n channelClaimsArray.forEach(claim => {\n claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);\n claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);\n return claim;\n });\n return resolve(channelClaimsArray);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getClaimIdByLongChannelId = function (channelClaimId, claimName) {\n logger.debug(`finding claim id for claim ${claimName} from channel ${channelClaimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name: claimName, certificateId: channelClaimId },\n order: [['id', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(result[0].claimId);\n default:\n logger.error(`${result.length} records found for \"${claimName}\" in channel \"${channelClaimId}\"`);\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimIdFromShortClaimId = function (name, shortId) {\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: {\n name,\n claimId: {\n $like: `${shortId}%`,\n }},\n order: [['height', 'ASC']],\n })\n .then(result => {\n switch (result.length) {\n case 0:\n return resolve(null);\n default: // note results must be sorted\n return resolve(result[0].claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getTopFreeClaimIdByClaimName = function (name) {\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name },\n order: [['effectiveAmount', 'DESC'], ['height', 'ASC']], // note: maybe height and effective amount need to switch?\n })\n .then(result => {\n logger.debug('length of result', result.length);\n switch (result.length) {\n case 0:\n return resolve(null);\n default:\n return resolve(result[0].dataValues.claimId);\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.validateLongClaimId = function (name, claimId) {\n return new Promise((resolve, reject) => {\n this.findOne({\n where: {name, claimId},\n })\n .then(result => {\n if (!result) {\n return resolve(null);\n };\n resolve(claimId);\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n Claim.getLongClaimId = function (claimName, claimId) {\n logger.debug(`getLongClaimId(${claimName}, ${claimId})`);\n if (claimId && (claimId.length === 40)) { // if a full claim id is provided\n return this.validateLongClaimId(claimName, claimId);\n } else if (claimId && claimId.length < 40) {\n return this.getLongClaimIdFromShortClaimId(claimName, claimId); // if a short claim id is provided\n } else {\n return this.getTopFreeClaimIdByClaimName(claimName); // if no claim id is provided\n }\n };\n\n Claim.resolveClaim = function (name, claimId) {\n logger.debug(`Claim.resolveClaim: ${name} ${claimId}`);\n return new Promise((resolve, reject) => {\n this\n .findAll({\n where: { name, claimId },\n })\n .then(claimArray => {\n switch (claimArray.length) {\n case 0:\n return resolve(null);\n case 1:\n return resolve(prepareClaimData(claimArray[0].dataValues));\n default:\n logger.error(`more than one record matches ${name}#${claimId} in db.Claim`);\n return resolve(prepareClaimData(claimArray[0].dataValues));\n }\n })\n .catch(error => {\n reject(error);\n });\n });\n };\n\n return Claim;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/claim.js","module.exports = (sequelize, { STRING, BOOLEAN, INTEGER }) => {\n const File = sequelize.define(\n 'File',\n {\n name: {\n type : STRING,\n allowNull: false,\n },\n claimId: {\n type : STRING,\n allowNull: false,\n },\n address: {\n type : STRING,\n allowNull: false,\n },\n outpoint: {\n type : STRING,\n allowNull: false,\n },\n height: {\n type : INTEGER,\n allowNull: false,\n default : 0,\n },\n fileName: {\n type : STRING,\n allowNull: false,\n },\n filePath: {\n type : STRING,\n allowNull: false,\n },\n fileType: {\n type: STRING,\n },\n nsfw: {\n type : BOOLEAN,\n allowNull : false,\n defaultValue: false,\n },\n trendingEligible: {\n type : BOOLEAN,\n allowNull : false,\n defaultValue: true,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n File.associate = db => {\n File.hasMany(db.Request);\n File.hasOne(db.Claim);\n };\n\n File.getRecentClaims = function () {\n return this.findAll({\n where: { nsfw: false, trendingEligible: true },\n order: [['createdAt', 'DESC']],\n limit: 25,\n });\n };\n\n return File;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/file.js","module.exports = (sequelize, { STRING, BOOLEAN, TEXT }) => {\n const Request = sequelize.define(\n 'Request',\n {\n action: {\n type : STRING,\n allowNull: false,\n },\n url: {\n type : STRING,\n allowNull: false,\n },\n ipAddress: {\n type : STRING,\n allowNull: true,\n },\n result: {\n type : TEXT('long'),\n allowNull: true,\n default : null,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n Request.associate = db => {\n Request.belongsTo(db.File, {\n foreignKey: {\n allowNull: true,\n },\n });\n };\n\n return Request;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/request.js","'use strict';\nconst bcrypt = require('bcrypt');\nconst logger = require('winston');\n\nmodule.exports = (sequelize, { STRING }) => {\n const User = sequelize.define(\n 'User',\n {\n userName: {\n type : STRING,\n allowNull: false,\n },\n password: {\n type : STRING,\n allowNull: false,\n },\n },\n {\n freezeTableName: true,\n }\n );\n\n User.associate = db => {\n User.hasOne(db.Channel);\n };\n\n User.prototype.comparePassword = function (password) {\n return bcrypt.compare(password, this.password);\n };\n\n User.prototype.changePassword = function (newPassword) {\n return new Promise((resolve, reject) => {\n // generate a salt string to use for hashing\n bcrypt.genSalt((saltError, salt) => {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(newPassword, salt, (hashError, hash) => {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the current password with the new hash\n this\n .update({password: hash})\n .then(() => {\n resolve();\n })\n .catch(error => {\n reject(error);\n });\n });\n });\n });\n };\n\n // pre-save hook method to hash the user's password before the user's info is saved to the db.\n User.hook('beforeCreate', (user, options) => {\n logger.debug('User.beforeCreate hook...');\n return new Promise((resolve, reject) => {\n // generate a salt string to use for hashing\n bcrypt.genSalt((saltError, salt) => {\n if (saltError) {\n logger.error('salt error', saltError);\n reject(saltError);\n return;\n }\n // generate a hashed version of the user's password\n bcrypt.hash(user.password, salt, (hashError, hash) => {\n // if there is an error with the hash generation return the error\n if (hashError) {\n logger.error('hash error', hashError);\n reject(hashError);\n return;\n }\n // replace the password string with the hash password value\n user.password = hash;\n resolve();\n });\n });\n });\n });\n\n return User;\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/models/user.js","module.exports = require(\"bcrypt\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"bcrypt\"\n// module id = 51\n// module chunks = 0","const PassportLocalStrategy = require('passport-local').Strategy;\nconst lbryApi = require('../helpers/lbryApi.js');\nconst logger = require('winston');\nconst db = require('models');\n\nmodule.exports = new PassportLocalStrategy(\n {\n usernameField: 'username',\n passwordField: 'password',\n },\n (username, password, done) => {\n logger.verbose(`new channel signup request. user: ${username} pass: ${password} .`);\n let userInfo = {};\n // server-side validaton of inputs (username, password)\n\n // create the channel and retrieve the metadata\n return lbryApi.createChannel(`@${username}`)\n .then(tx => {\n // create user record\n const userData = {\n userName: username,\n password: password,\n };\n logger.verbose('userData >', userData);\n // create user record\n const channelData = {\n channelName : `@${username}`,\n channelClaimId: tx.claim_id,\n };\n logger.verbose('channelData >', channelData);\n // create certificate record\n const certificateData = {\n claimId: tx.claim_id,\n name : `@${username}`,\n // address,\n };\n logger.verbose('certificateData >', certificateData);\n // save user and certificate to db\n return Promise.all([db.User.create(userData), db.Channel.create(channelData), db.Certificate.create(certificateData)]);\n })\n .then(([newUser, newChannel, newCertificate]) => {\n logger.verbose('user and certificate successfully created');\n // store the relevant newUser info to be passed back for req.User\n userInfo['id'] = newUser.id;\n userInfo['userName'] = newUser.userName;\n userInfo['channelName'] = newChannel.channelName;\n userInfo['channelClaimId'] = newChannel.channelClaimId;\n // associate the instances\n return Promise.all([newCertificate.setChannel(newChannel), newChannel.setUser(newUser)]);\n })\n .then(() => {\n logger.verbose('user and certificate successfully associated');\n return db.Certificate.getShortChannelIdFromLongChannelId(userInfo.channelClaimId, userInfo.channelName);\n })\n .then(shortChannelId => {\n userInfo['shortChannelId'] = shortChannelId;\n return done(null, userInfo);\n })\n .catch(error => {\n logger.error('signup error', error);\n return done(error);\n });\n }\n);\n\n\n\n// WEBPACK FOOTER //\n// ./server/speechPassport/local-signup.js","module.exports = require(\"axios\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"axios\"\n// module id = 53\n// module chunks = 0","const lbryConfig = {\n api: {\n apiHost: 'localhost',\n apiPort: '5279',\n },\n};\n\nmodule.exports = lbryConfig;\n\n\n\n// WEBPACK FOOTER //\n// ./config/lbryConfig.js","module.exports = require(\"universal-analytics\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"universal-analytics\"\n// module id = 55\n// module chunks = 0","module.exports = {\n serializeSpeechUser (user, done) { // returns user data to be serialized into session\n console.log('serializing user');\n done(null, user);\n },\n deserializeSpeechUser (user, done) { // deserializes session and populates additional info to req.user\n console.log('deserializing user');\n done(null, user);\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/authHelpers.js","const speechPassport = require('speechPassport');\nconst handleSignupRequest = require('./signup');\nconst handleLoginRequest = require('./login');\nconst handleLogoutRequest = require('./logout');\nconst handleUserRequest = require('./user');\n\nmodule.exports = (app) => {\n app.post('/signup', speechPassport.authenticate('local-signup'), handleSignupRequest);\n app.post('/login', handleLoginRequest);\n app.get('/logout', handleLogoutRequest);\n app.get('/user', handleUserRequest);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/index.js","const signup = (req, res) => {\n res.status(200).json({\n success : true,\n channelName : req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId,\n });\n};\n\nmodule.exports = signup;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/signup.js","const speechPassport = require('speechPassport');\n\nconst login = (req, res, next) => {\n speechPassport.authenticate('local-login', (err, user, info) => {\n if (err) {\n return next(err);\n }\n if (!user) {\n return res.status(400).json({\n success: false,\n message: info.message,\n });\n }\n req.logIn(user, (err) => {\n if (err) {\n return next(err);\n }\n return res.status(200).json({\n success : true,\n channelName : req.user.channelName,\n channelClaimId: req.user.channelClaimId,\n shortChannelId: req.user.shortChannelId,\n });\n });\n })(req, res, next);\n};\n\nmodule.exports = login;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/login.js","const logout = (req, res) => {\n req.logout();\n res.status(200).json({success: true, message: 'you successfully logged out'});\n};\n\nmodule.exports = logout;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/logout.js","const user = (req, res) => {\n if (req.user) {\n res.status(200).json({success: true, data: req.user});\n } else {\n res.status(401).json({success: false, message: 'user is not logged in'});\n }\n};\n\nmodule.exports = user;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/auth/user.js","const channelAvailability = require('./channelAvailability');\nconst channelClaims = require('./channelClaims');\nconst channelData = require('./channelData');\nconst channelShortId = require('./channelShortId');\nconst claimAvailability = require('./claimAvailability');\nconst claimData = require('./claimData');\nconst claimGet = require('./claimGet');\nconst claimLongId = require('./claimLongId');\nconst claimPublish = require('./claimPublish');\nconst claimResolve = require('./claimResolve');\nconst claimShortId = require('./claimShortId');\nconst claimList = require('./claimList');\nconst fileAvailability = require('./fileAvailability');\n\nconst multipartMiddleware = require('helpers/multipartMiddleware');\n\nmodule.exports = (app) => {\n // channel routes\n app.get('/api/channel/availability/:name', channelAvailability);\n app.get('/api/channel/short-id/:longId/:name', channelShortId);\n app.get('/api/channel/data/:channelName/:channelClaimId', channelData);\n app.get('/api/channel/claims/:channelName/:channelClaimId/:page', channelClaims);\n // claim routes\n app.get('/api/claim/list/:name', claimList);\n app.get('/api/claim/get/:name/:claimId', claimGet);\n app.get('/api/claim/availability/:name', claimAvailability);\n app.get('/api/claim/resolve/:name/:claimId', claimResolve);\n app.post('/api/claim/publish', multipartMiddleware, claimPublish);\n app.get('/api/claim/short-id/:longId/:name', claimShortId);\n app.post('/api/claim/long-id', claimLongId);\n app.get('/api/claim/data/:claimName/:claimId', claimData);\n // file routes\n app.get('/api/file/availability/:name/:claimId', fileAvailability);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/index.js","const { checkChannelAvailability } = require('controllers/publishController.js');\nconst { sendGATimingEvent } = require('helpers/googleAnalytics.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to check whether site has published to a channel\n\n*/\n\nconst channelAvailability = ({ ip, originalUrl, params: { name } }, res) => {\n const gaStartTime = Date.now();\n checkChannelAvailability(name)\n .then(availableName => {\n res.status(200).json(availableName);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelAvailability;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelAvailability.js","module.exports = require(\"fs\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"fs\"\n// module id = 64\n// module chunks = 0","const { getChannelClaims } = require('controllers/serveController.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get all claims for channel\n\n*/\n\nconst channelClaims = ({ ip, originalUrl, body, params }, res) => {\n const channelName = params.channelName;\n let channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n const page = params.page;\n getChannelClaims(channelName, channelClaimId, page)\n .then(data => {\n if (data === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'No matching channel was found'});\n }\n res.status(200).json({success: true, data});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelClaims;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelClaims.js","const CLAIMS_PER_PAGE = 12;\n\nmodule.exports = {\n returnPaginatedChannelClaims (channelName, longChannelClaimId, claims, page) {\n const totalPages = module.exports.determineTotalPages(claims);\n const paginationPage = module.exports.getPageFromQuery(page);\n const viewData = {\n channelName : channelName,\n longChannelClaimId: longChannelClaimId,\n claims : module.exports.extractPageFromClaims(claims, paginationPage),\n previousPage : module.exports.determinePreviousPage(paginationPage),\n currentPage : paginationPage,\n nextPage : module.exports.determineNextPage(totalPages, paginationPage),\n totalPages : totalPages,\n totalResults : module.exports.determineTotalClaims(claims),\n };\n return viewData;\n },\n getPageFromQuery (page) {\n if (page) {\n return parseInt(page);\n }\n return 1;\n },\n extractPageFromClaims (claims, pageNumber) {\n if (!claims) {\n return []; // if no claims, return this default\n }\n // logger.debug('claims is array?', Array.isArray(claims));\n // logger.debug(`pageNumber ${pageNumber} is number?`, Number.isInteger(pageNumber));\n const claimStartIndex = (pageNumber - 1) * CLAIMS_PER_PAGE;\n const claimEndIndex = claimStartIndex + CLAIMS_PER_PAGE;\n const pageOfClaims = claims.slice(claimStartIndex, claimEndIndex);\n return pageOfClaims;\n },\n determineTotalPages (claims) {\n if (!claims) {\n return 0;\n } else {\n const totalClaims = claims.length;\n if (totalClaims < CLAIMS_PER_PAGE) {\n return 1;\n }\n const fullPages = Math.floor(totalClaims / CLAIMS_PER_PAGE);\n const remainder = totalClaims % CLAIMS_PER_PAGE;\n if (remainder === 0) {\n return fullPages;\n }\n return fullPages + 1;\n }\n },\n determinePreviousPage (currentPage) {\n if (currentPage === 1) {\n return null;\n }\n return currentPage - 1;\n },\n determineNextPage (totalPages, currentPage) {\n if (currentPage === totalPages) {\n return null;\n }\n return currentPage + 1;\n },\n determineTotalClaims (claims) {\n if (!claims) {\n return 0;\n }\n return claims.length;\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/channelPagination.js","const { getChannelData } = require('controllers/serveController.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\n\n/*\n\n route to get data for a channel\n\n*/\n\nconst channelData = ({ ip, originalUrl, body, params }, res) => {\n const channelName = params.channelName;\n let channelClaimId = params.channelClaimId;\n if (channelClaimId === 'none') channelClaimId = null;\n getChannelData(channelName, channelClaimId, 0)\n .then(data => {\n if (data === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'No matching channel was found'});\n }\n res.status(200).json({success: true, data});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelData;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelData.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\nroute to get a short channel id from long channel Id\n\n*/\n\nconst channelShortIdRoute = ({ ip, originalUrl, params }, res) => {\n db.Certificate.getShortChannelIdFromLongChannelId(params.longId, params.name)\n .then(shortId => {\n res.status(200).json(shortId);\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = channelShortIdRoute;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/channelShortId.js","const { claimNameIsAvailable } = require('controllers/publishController.js');\nconst { sendGATimingEvent } = require('helpers/googleAnalytics.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to check whether this site published to a claim\n\n*/\n\nconst claimAvailability = ({ ip, originalUrl, params: { name } }, res) => {\n const gaStartTime = Date.now();\n claimNameIsAvailable(name)\n .then(result => {\n res.status(200).json(result);\n sendGATimingEvent('end-to-end', 'claim name availability', name, gaStartTime, Date.now());\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimAvailability;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimAvailability.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to return data for a claim\n\n*/\n\nconst claimData = ({ ip, originalUrl, body, params }, res) => {\n const claimName = params.claimName;\n let claimId = params.claimId;\n if (claimId === 'none') claimId = null;\n db.Claim.resolveClaim(claimName, claimId)\n .then(claimInfo => {\n if (!claimInfo) {\n return res.status(404).json({success: false, message: 'No claim could be found'});\n }\n res.status(200).json({success: true, data: claimInfo});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimData;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimData.js","const { getClaim } = require('helpers/lbryApi.js');\nconst { addGetResultsToFileData, createFileData } = require('../../helpers/publishHelpers.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to get a claim\n\n*/\n\nconst claimGet = ({ ip, originalUrl, params }, res) => {\n const name = params.name;\n const claimId = params.claimId;\n // resolve the claim\n db.Claim.resolveClaim(name, claimId)\n .then(resolveResult => {\n // make sure a claim actually exists at that uri\n if (!resolveResult) {\n throw new Error('No matching uri found in Claim table');\n }\n let fileData = createFileData(resolveResult);\n // get the claim\n return Promise.all([fileData, getClaim(`${name}#${claimId}`)]);\n })\n .then(([ fileData, getResult ]) => {\n fileData = addGetResultsToFileData(fileData, getResult);\n return Promise.all([db.upsert(db.File, fileData, {name, claimId}, 'File'), getResult]);\n })\n .then(([ fileRecord, {message, completed} ]) => {\n res.status(200).json({ success: true, message, completed });\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimGet;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimGet.js","const { getClaimId } = require('controllers/serveController.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\nconst NO_CHANNEL = 'NO_CHANNEL';\nconst NO_CLAIM = 'NO_CLAIM';\n\n/*\n\n route to get a long claim id\n\n*/\n\nconst claimLongId = ({ ip, originalUrl, body, params }, res) => {\n const channelName = body.channelName;\n const channelClaimId = body.channelClaimId;\n const claimName = body.claimName;\n const claimId = body.claimId;\n getClaimId(channelName, channelClaimId, claimName, claimId)\n .then(result => {\n if (result === NO_CHANNEL) {\n return res.status(404).json({success: false, message: 'No matching channel could be found'});\n }\n if (result === NO_CLAIM) {\n return res.status(404).json({success: false, message: 'No matching claim id could be found'});\n }\n res.status(200).json({success: true, data: result});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimLongId;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimLongId.js","const { createBasicPublishParams, createThumbnailPublishParams, parsePublishApiRequestBody, parsePublishApiRequestFiles } = require('helpers/publishHelpers.js');\nconst { claimNameIsAvailable, publish } = require('controllers/publishController.js');\nconst { authenticateUser } = require('auth/authentication.js');\nconst { sendGATimingEvent } = require('helpers/googleAnalytics.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst { details: { host } } = require('siteConfig.js');\n\n/*\n\n route to publish a claim through the daemon\n\n*/\n\nconst claimPublish = ({ body, files, headers, ip, originalUrl, user }, res) => {\n // define variables\n let channelName, channelId, channelPassword, description, fileName, filePath, fileType, gaStartTime, license, name, nsfw, thumbnail, thumbnailFileName, thumbnailFilePath, thumbnailFileType, title;\n // record the start time of the request\n gaStartTime = Date.now();\n // validate the body and files of the request\n try {\n // validateApiPublishRequest(body, files);\n ({name, nsfw, license, title, description, thumbnail} = parsePublishApiRequestBody(body));\n ({fileName, filePath, fileType, thumbnailFileName, thumbnailFilePath, thumbnailFileType} = parsePublishApiRequestFiles(files));\n ({channelName, channelId, channelPassword} = body);\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n // check channel authorization\n Promise\n .all([\n authenticateUser(channelName, channelId, channelPassword, user),\n claimNameIsAvailable(name),\n createBasicPublishParams(filePath, name, title, description, license, nsfw, thumbnail),\n createThumbnailPublishParams(thumbnailFilePath, name, license, nsfw),\n ])\n .then(([{channelName, channelClaimId}, validatedClaimName, publishParams, thumbnailPublishParams]) => {\n // add channel details to the publish params\n if (channelName && channelClaimId) {\n publishParams['channel_name'] = channelName;\n publishParams['channel_id'] = channelClaimId;\n }\n // publish the thumbnail\n if (thumbnailPublishParams) {\n publish(thumbnailPublishParams, thumbnailFileName, thumbnailFileType);\n }\n // publish the asset\n return publish(publishParams, fileName, fileType);\n })\n .then(result => {\n res.status(200).json({\n success: true,\n message: 'publish completed successfully',\n data : {\n name,\n claimId: result.claim_id,\n url : `${host}/${result.claim_id}/${name}`,\n lbryTx : result,\n },\n });\n // record the publish end time and send to google analytics\n sendGATimingEvent('end-to-end', 'publish', fileType, gaStartTime, Date.now());\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimPublish;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimPublish.js","const db = require('models');\nconst logger = require('winston');\n\nmodule.exports = {\n authenticateUser (channelName, channelId, channelPassword, user) {\n // case: no channelName or channel Id are provided (anonymous), regardless of whether user token is provided\n if (!channelName && !channelId) {\n return {\n channelName : null,\n channelClaimId: null,\n };\n }\n // case: channelName or channel Id are provided with user token\n if (user) {\n if (channelName && channelName !== user.channelName) {\n throw new Error('the provided channel name does not match user credentials');\n }\n if (channelId && channelId !== user.channelClaimId) {\n throw new Error('the provided channel id does not match user credentials');\n }\n return {\n channelName : user.channelName,\n channelClaimId: user.channelClaimId,\n };\n }\n // case: channelName or channel Id are provided with password instead of user token\n if (!channelPassword) throw new Error('no channel password provided');\n return module.exports.authenticateChannelCredentials(channelName, channelId, channelPassword);\n },\n authenticateChannelCredentials (channelName, channelId, userPassword) {\n return new Promise((resolve, reject) => {\n // hoisted variables\n let channelData;\n // build the params for finding the channel\n let channelFindParams = {};\n if (channelName) channelFindParams['channelName'] = channelName;\n if (channelId) channelFindParams['channelClaimId'] = channelId;\n // find the channel\n db.Channel\n .findOne({\n where: channelFindParams,\n })\n .then(channel => {\n if (!channel) {\n logger.debug('no channel found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n channelData = channel.get();\n logger.debug('channel data:', channelData);\n return db.User.findOne({\n where: { userName: channelData.channelName.substring(1) },\n });\n })\n .then(user => {\n if (!user) {\n logger.debug('no user found');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n return user.comparePassword(userPassword);\n })\n .then(isMatch => {\n if (!isMatch) {\n logger.debug('incorrect password');\n throw new Error('Authentication failed, you do not have access to that channel');\n }\n logger.debug('...password was a match...');\n resolve(channelData);\n })\n .catch(error => {\n reject(error);\n });\n });\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/auth/authentication.js","const { resolveUri } = require('helpers/lbryApi.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to run a resolve request on the daemon\n\n*/\n\nconst claimResolve = ({ headers, ip, originalUrl, params }, res) => {\n resolveUri(`${params.name}#${params.claimId}`)\n .then(resolvedUri => {\n res.status(200).json(resolvedUri);\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimResolve;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimResolve.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to get a short claim id from long claim Id\n\n*/\n\nconst claimShortId = ({ ip, originalUrl, body, params }, res) => {\n db.Claim.getShortClaimIdFromLongClaimId(params.longId, params.name)\n .then(shortId => {\n res.status(200).json({success: true, data: shortId});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimShortId;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimShortId.js","const { getClaimList } = require('helpers/lbryApi.js');\nconst { handleErrorResponse } = require('helpers/errorHandlers.js');\n\n/*\n\n route to get list of claims\n\n*/\n\nconst claimList = ({ ip, originalUrl, params }, res) => {\n getClaimList(params.name)\n .then(claimsList => {\n res.status(200).json(claimsList);\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = claimList;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/claimList.js","const { handleErrorResponse } = require('helpers/errorHandlers.js');\nconst db = require('models');\n\n/*\n\n route to see if asset is available locally\n\n*/\n\nconst fileAvailability = ({ ip, originalUrl, params }, res) => {\n const name = params.name;\n const claimId = params.claimId;\n db.File\n .findOne({\n where: {\n name,\n claimId,\n },\n })\n .then(result => {\n if (result) {\n return res.status(200).json({success: true, data: true});\n }\n res.status(200).json({success: true, data: false});\n })\n .catch(error => {\n handleErrorResponse(originalUrl, ip, error, res);\n });\n};\n\nmodule.exports = fileAvailability;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/api/fileAvailability.js","const multipart = require('connect-multiparty');\r\nconst { publishing: { uploadDirectory } } = require('siteConfig.js');\r\nconst multipartMiddleware = multipart({uploadDir: uploadDirectory});\r\n\r\nmodule.exports = multipartMiddleware;\r\n\n\n\n// WEBPACK FOOTER //\n// ./server/helpers/multipartMiddleware.js","module.exports = require(\"connect-multiparty\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"connect-multiparty\"\n// module id = 80\n// module chunks = 0","const handlePageRequest = require('./sendReactApp');\nconst handleEmbedRequest = require('./sendEmbedPage');\nconst redirect = require('./redirect');\n\nmodule.exports = (app) => {\n app.get('/', handlePageRequest);\n app.get('/login', handlePageRequest);\n app.get('/about', handlePageRequest);\n app.get('/trending', redirect('/popular'));\n app.get('/popular', handlePageRequest);\n app.get('/new', handlePageRequest);\n app.get('/embed/:claimId/:name', handleEmbedRequest); // route to send embedable video player (for twitter)\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/index.js","const handlePageRender = require('helpers/handlePageRender.jsx');\n\nconst sendReactApp = (req, res) => {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/sendReactApp.js","const { details: { host } } = require('siteConfig.js');\n\nconst sendEmbedPage = ({ params }, res) => {\n const claimId = params.claimId;\n const name = params.name;\n // get and render the content\n res.status(200).render('embed', { layout: 'embed', host, claimId, name });\n};\n\nmodule.exports = sendEmbedPage;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/sendEmbedPage.js","const redirect = (route) => {\n return (req, res) => {\n res.status(301).redirect(route);\n };\n};\n\nmodule.exports = redirect;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/pages/redirect.js","const serveAssetByClaim = require('./serveAssetByClaim');\nconst serveAssetByIdentifierAndClaim = require('./serveAssetByIdentifierAndClaim');\n\nmodule.exports = (app, db) => {\n app.get('/:identifier/:claim', serveAssetByIdentifierAndClaim);\n app.get('/:claim', serveAssetByClaim);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/assets/index.js","const { sendGAServeEvent } = require('helpers/googleAnalytics');\nconst { determineResponseType, logRequestData, getClaimIdAndServeAsset } = require('helpers/serveHelpers.js');\nconst lbryUri = require('helpers/lbryUri.js');\nconst handleShowRender = require('helpers/handleShowRender.jsx');\nconst SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name only\n\n*/\n\nconst serverAssetByClaim = (req, res) => {\n const { headers, ip, originalUrl, params } = req;\n // decide if this is a show request\n let hasFileExtension;\n try {\n ({ hasFileExtension } = lbryUri.parseModifier(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n let responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n let claimName;\n try {\n ({claimName} = lbryUri.parseClaim(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, null, null);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(null, null, claimName, null, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByClaim;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/assets/serveAssetByClaim.js","module.exports = require(\"redux-saga\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"redux-saga\"\n// module id = 87\n// module chunks = 0","module.exports = require(\"redux-saga/effects\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"redux-saga/effects\"\n// module id = 88\n// module chunks = 0","const { sendGAServeEvent } = require('helpers/googleAnalytics');\nconst {\n determineResponseType,\n flipClaimNameAndIdForBackwardsCompatibility,\n logRequestData,\n getClaimIdAndServeAsset,\n} = require('helpers/serveHelpers.js');\nconst lbryUri = require('helpers/lbryUri.js');\nconst handleShowRender = require('helpers/handleShowRender.jsx');\n\nconst SERVE = 'SERVE';\n\n/*\n\n route to serve an asset or the react app via the claim name and an identifier\n\n*/\n\nconst serverAssetByIdentifierAndClaim = (req, res) => {\n const { headers, ip, originalUrl, params } = req;\n // decide if this is a show request\n let hasFileExtension;\n try {\n ({ hasFileExtension } = lbryUri.parseModifier(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n let responseType = determineResponseType(hasFileExtension, headers);\n if (responseType !== SERVE) {\n return handleShowRender(req, res);\n }\n // handle serve request\n // send google analytics\n sendGAServeEvent(headers, ip, originalUrl);\n // parse the claim\n let claimName;\n try {\n ({ claimName } = lbryUri.parseClaim(params.claim));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n // parse the identifier\n let isChannel, channelName, channelClaimId, claimId;\n try {\n ({ isChannel, channelName, channelClaimId, claimId } = lbryUri.parseIdentifier(params.identifier));\n } catch (error) {\n return res.status(400).json({success: false, message: error.message});\n }\n if (!isChannel) {\n [claimId, claimName] = flipClaimNameAndIdForBackwardsCompatibility(claimId, claimName);\n }\n // log the request data for debugging\n logRequestData(responseType, claimName, channelName, claimId);\n // get the claim Id and then serve the asset\n getClaimIdAndServeAsset(channelName, channelClaimId, claimName, claimId, originalUrl, ip, res);\n};\n\nmodule.exports = serverAssetByIdentifierAndClaim;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/assets/serveAssetByIdentifierAndClaim.js","const handlePageRequest = require('./sendReactApp');\r\n\r\nmodule.exports = (app) => {\r\n app.get('*', handlePageRequest);\r\n};\r\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/fallback/index.js","const handlePageRender = require('helpers/handlePageRender.jsx');\n\nconst sendReactApp = (req, res) => {\n handlePageRender(req, res);\n};\n\nmodule.exports = sendReactApp;\n\n\n\n// WEBPACK FOOTER //\n// ./server/routes/fallback/sendReactApp.js"],"sourceRoot":""} \ No newline at end of file diff --git a/server/helpers/handlePageRender.jsx b/server/helpers/handlePageRender.jsx index e0cca3dc..ce9844bd 100644 --- a/server/helpers/handlePageRender.jsx +++ b/server/helpers/handlePageRender.jsx @@ -7,11 +7,16 @@ import { Reducers, GAListener, App } from 'spee.ch-components'; import renderFullPage from './renderFullPage.js'; import Helmet from 'react-helmet'; +const siteConfig = require('siteConfig.js'); + module.exports = (req, res) => { let context = {}; + // customize the reducer by passing in intial state configs + const customizedReducers = Reducers(siteConfig); + // create a new Redux store instance - const store = createStore(Reducers); + const store = createStore(customizedReducers); // render component to a string const html = renderToString( @@ -40,4 +45,6 @@ module.exports = (req, res) => { // send the rendered page back to the client res.send(renderFullPage(helmet, html, preloadedState)); + + console.log('hello from spee.ch handlePageRender.jsx'); }; diff --git a/server/helpers/handleShowRender.jsx b/server/helpers/handleShowRender.jsx index dfef14b1..5b6aa272 100644 --- a/server/helpers/handleShowRender.jsx +++ b/server/helpers/handleShowRender.jsx @@ -10,6 +10,10 @@ import { Reducers, GAListener, App, Sagas, Actions } from 'spee.ch-components'; import Helmet from 'react-helmet'; +// configure the reducers by passing initial state configs +const siteConfig = require('siteConfig.js'); +const customizedReducers = Reducers(siteConfig); + const returnSagaWithParams = (saga, params) => { return function * () { yield call(saga, params); @@ -24,7 +28,7 @@ module.exports = (req, res) => { const middleware = applyMiddleware(sagaMiddleware); // create a new Redux store instance - const store = createStore(Reducers, middleware); + const store = createStore(customizedReducers, middleware); // create saga const action = Actions.onHandleShowPageUri(req.params); @@ -60,4 +64,6 @@ module.exports = (req, res) => { // send the rendered page back to the client res.send(renderFullPage(helmet, html, preloadedState)); }); + + console.log('hello from spee.ch handleShowRender.jsx'); };