diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b12bd55
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+node_modules
+*.asar
diff --git a/README.md b/README.md
index f76b972..101b037 100644
--- a/README.md
+++ b/README.md
@@ -4,15 +4,17 @@
## Goals
- **Hotpluggable** - just swap the asar file, nothing else needed
- **Lightweight** - it should be at least as fast or lightweight, hopefully more
-- **No Tracking** - no crash reporting, etc
+- **No Tracking** - no crash reporting, error tracking, etc
- **Minimal** - generally only doing what is needed (see: implementation)
## Implementation
Below is a list in order of priority, marked as complete when finished:
-- [ ] Stub everything
-- [ ] Bootstrapping
-- [ ] Splash screen
+- [X] Bootstrapping
+- [X] Splash screen
+- [X] Error handling
+- [ ] A bunch of specific minor fixes / features
+ - [ ] Handle hardware acceleration
- [ ] Auto start
-- [ ] Updating
- - [ ] Updater v1
- - [ ] Updater v2
\ No newline at end of file
+- [ ] First run
+- [ ] Self-write updater code (currently mostly copied)
+- [ ] Self-write some small parts of internals
\ No newline at end of file
diff --git a/src/Constants.js b/src/Constants.js
new file mode 100644
index 0000000..2f0f862
--- /dev/null
+++ b/src/Constants.js
@@ -0,0 +1,34 @@
+// Bootstrap consts, heavily copied as don't want to mess with it
+const { releaseChannel } = require('./utils/buildInfo');
+
+const { getSettings } = require('./appSettings');
+
+const settings = getSettings();
+
+function capitalizeFirstLetter(s) {
+ return s.charAt(0).toUpperCase() + s.slice(1);
+}
+
+const appNameSuffix = releaseChannel === 'stable' ? '' : capitalizeFirstLetter(releaseChannel);
+const APP_COMPANY = 'Discord Inc';
+const APP_DESCRIPTION = 'Discord - https://discord.com';
+const APP_NAME = 'Discord' + appNameSuffix;
+const APP_NAME_FOR_HUMANS = 'Discord' + (appNameSuffix !== '' ? ' ' + appNameSuffix : '');
+const APP_ID_BASE = 'com.squirrel';
+const APP_ID = `${APP_ID_BASE}.${APP_NAME}.${APP_NAME}`;
+const APP_PROTOCOL = 'Discord';
+const API_ENDPOINT = settings.get('API_ENDPOINT') || 'https://discord.com/api';
+const UPDATE_ENDPOINT = settings.get('UPDATE_ENDPOINT') || API_ENDPOINT;
+const NEW_UPDATE_ENDPOINT = settings.get('NEW_UPDATE_ENDPOINT') || 'https://discord.com/api/updates/';
+
+module.exports = {
+ APP_COMPANY,
+ APP_DESCRIPTION,
+ APP_NAME,
+ APP_NAME_FOR_HUMANS,
+ APP_ID,
+ APP_PROTOCOL,
+ API_ENDPOINT,
+ NEW_UPDATE_ENDPOINT,
+ UPDATE_ENDPOINT
+};
\ No newline at end of file
diff --git a/src/GPUSettings.js b/src/GPUSettings.js
new file mode 100644
index 0000000..6012783
--- /dev/null
+++ b/src/GPUSettings.js
@@ -0,0 +1,6 @@
+// Idk why Discord has to use this
+exports.replace = (GPUSettings) => {
+ for (const name of Object.keys(GPUSettings)) {
+ exports[name] = GPUSettings[name];
+ }
+};
\ No newline at end of file
diff --git a/src/appSettings.js b/src/appSettings.js
new file mode 100644
index 0000000..509014a
--- /dev/null
+++ b/src/appSettings.js
@@ -0,0 +1,7 @@
+const Settings = require('./utils/Settings');
+const paths = require('./paths');
+
+const settings = new Settings(paths.getUserData());
+
+exports.getSettings = () => settings;
+exports.init = () => {}; // Stub as we setup on require
\ No newline at end of file
diff --git a/src/autoStart/index.js b/src/autoStart/index.js
new file mode 100644
index 0000000..5ad5088
--- /dev/null
+++ b/src/autoStart/index.js
@@ -0,0 +1,6 @@
+// Stub for now at least
+
+exports.install = (callback) => { callback(); };
+exports.update = (callback) => { callback(); };
+exports.uninstall = (callback) => { callback(); };
+exports.isInstalled = (callback) => { callback(true); }; // Stub to true or false?
\ No newline at end of file
diff --git a/src/bootstrap.js b/src/bootstrap.js
new file mode 100644
index 0000000..50c9940
--- /dev/null
+++ b/src/bootstrap.js
@@ -0,0 +1,63 @@
+const { join } = require('path');
+const NodeModule = require('module');
+const { app } = require('electron');
+
+const log = require('./utils/log');
+const requireNative = require('./utils/requireNative');
+const paths = require('./paths');
+const buildInfo = require('./utils/buildInfo');
+
+// Just required for startup
+const appSettings = require('./appSettings');
+const GPUSettings = require('./GPUSettings');
+const crashReporterSetup = require('./crashReporterSetup');
+const splashScreen = require('./splash/splashScreen');
+const Constants = require('./Constants');
+const autoStart = require('./autoStart');
+
+const updater = require('./updater/updater');
+const moduleUpdater = require('./updater/moduleUpdater');
+const appUpdater = require('./updater/appUpdater');
+
+let desktopCore;
+const startCore = () => {
+ desktopCore = requireNative('discord_desktop_core');
+ log('Bootstrap', 'Required desktop_core:', desktopCore);
+
+ desktopCore.startup({
+ paths,
+ splashScreen,
+ moduleUpdater,
+ autoStart,
+ buildInfo,
+ appSettings,
+ Constants,
+ GPUSettings,
+ updater,
+ crashReporterSetup
+ });
+};
+
+const startUpdate = () => {
+ appUpdater.update(false, () => {
+ startCore();
+ }, () => {
+ desktopCore.setMainWindowVisible(true);
+ });
+};
+
+module.exports = () => {
+ // Paths logging
+ log('Paths', `Init! Returns:
+getUserData: ${paths.getUserData()}
+getUserDataVersioned: ${paths.getUserDataVersioned()}
+getResources: ${paths.getResources()}
+getModuleDataPath: ${paths.getModuleDataPath()}
+getInstallPath: ${paths.getInstallPath()}`);
+
+ if (app.isReady()) {
+ startUpdate();
+ } else {
+ app.once('ready', startUpdate);
+ }
+};
\ No newline at end of file
diff --git a/src/crashReporterSetup.js b/src/crashReporterSetup.js
new file mode 100644
index 0000000..119c733
--- /dev/null
+++ b/src/crashReporterSetup.js
@@ -0,0 +1,5 @@
+// Much crash reporting, such wow
+exports.init = () => {};
+exports.isInitialized = () => true;
+
+exports.metadata = {};
\ No newline at end of file
diff --git a/src/errorHandler.js b/src/errorHandler.js
new file mode 100644
index 0000000..b19f545
--- /dev/null
+++ b/src/errorHandler.js
@@ -0,0 +1,40 @@
+const { app } = require("electron");
+
+const log = require('./utils/log');
+
+exports.init = () => {
+ /* process.on('uncaughtException', error => {
+ const stack = error.stack ? error.stack : String(error);
+ const message = `Uncaught exception:\n ${stack}`;
+ console.warn(message);
+
+ if (!isErrorSafeToSuppress(error)) {
+ _electron.dialog.showErrorBox('A JavaScript error occurred in the main process', message);
+ }
+ }); */
+};
+
+
+exports.fatal = (err) => {
+ const options = {
+ type: 'error',
+ message: 'A fatal Javascript error occured',
+ detail: err && err.stack ? err.stack : String(err)
+ };
+
+ const callback = _ => app.quit();
+
+ const electronMajor = parseInt(process.versions.electron.split('.')[0]);
+
+ if (electronMajor >= 6) {
+ _electron.dialog.showMessageBox(null, options).then(callback);
+ } else {
+ _electron.dialog.showMessageBox(options, callback);
+ }
+
+ log('ErrorHandler', 'Fatal:', err);
+};
+
+exports.handled = (err) => {
+ log('ErrorHandler', 'Handled:', err);
+};
\ No newline at end of file
diff --git a/src/firstRun/index.js b/src/firstRun/index.js
new file mode 100644
index 0000000..e51a75c
--- /dev/null
+++ b/src/firstRun/index.js
@@ -0,0 +1,3 @@
+// Stub for now at least
+
+exports.update = (callback) => { callback(); };
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..3505e7d
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,7 @@
+const log = require('./utils/log');
+
+log('', 'Initing...');
+
+const bootstrap = require('./bootstrap');
+
+bootstrap(); // Start bootstrap
\ No newline at end of file
diff --git a/src/ipcMain.js b/src/ipcMain.js
new file mode 100644
index 0000000..a8a663e
--- /dev/null
+++ b/src/ipcMain.js
@@ -0,0 +1,5 @@
+// Discord's wrapper around ipcMain
+const { ipcMain } = require('electron');
+
+exports.on = (event, callback) => ipcMain.on('DISCORD_' + event, callback);
+exports.removeListener = (event, callback) => ipcMain.removeListener('DISCORD_' + event, callback);
\ No newline at end of file
diff --git a/src/package-lock.json b/src/package-lock.json
new file mode 100644
index 0000000..43c94eb
--- /dev/null
+++ b/src/package-lock.json
@@ -0,0 +1,873 @@
+{
+ "name": "openasar",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "openasar",
+ "dependencies": {
+ "mkdirp": "^0.5.1",
+ "request": "2.88.0",
+ "yauzl": "^2.10.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "node_modules/aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "node_modules/dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "dependencies": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "node_modules/extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "engines": [
+ "node >=0.6.0"
+ ]
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "deprecated": "this library is no longer supported",
+ "dependencies": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.8",
+ "npm": ">=1.3.7"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "node_modules/jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "node_modules/json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "node_modules/jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "dependencies": {
+ "mime-db": "1.51.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "dependencies": {
+ "minimist": "^1.2.5"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "node_modules/psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
+ },
+ "node_modules/punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "node_modules/qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "dependencies": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/uri-js/node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ }
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
+ },
+ "aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
+ },
+ "har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "requires": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
+ },
+ "json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
+ },
+ "jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ }
+ },
+ "mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
+ },
+ "mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "requires": {
+ "mime-db": "1.51.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "mkdirp": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
+ "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
+ },
+ "psl": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "sshpk": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
+ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "requires": {
+ "punycode": "^2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
+ }
+ }
+ },
+ "uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
+ "requires": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ }
+ }
+}
diff --git a/src/package.json b/src/package.json
index c8d0056..7810b7f 100644
--- a/src/package.json
+++ b/src/package.json
@@ -1,9 +1,12 @@
{
"name": "openasar",
- "description": "Discord Client for Desktop - Bootstrapper",
+ "description": "Open-source alternative of Discord desktop's app.asar",
"main": "index.js",
"dependencies": {
+ "mkdirp": "^0.5.1",
+ "request": "2.88.0",
+ "yauzl": "^2.10.0"
}
}
\ No newline at end of file
diff --git a/src/paths.js b/src/paths.js
new file mode 100644
index 0000000..bdae911
--- /dev/null
+++ b/src/paths.js
@@ -0,0 +1,25 @@
+const { join, dirname, basename } = require('path');
+const { app } = require('electron');
+
+const log = require('./utils/log');
+const buildInfo = require('./utils/buildInfo');
+
+
+const appDir = 'discord' + (buildInfo.releaseChannel === 'stable' ? '' : buildInfo.releaseChannel); // Clean channel naming up later to util?
+const userData = join(app.getPath('appData'), appDir);
+const userDataVersioned = join(userData, buildInfo.version);
+
+const exeDir = dirname(app.getPath('exe'));
+const installPath = /^app-[0-9]+\.[0-9]+\.[0-9]+/.test(basename(exeDir)) ? join(exeDir, '..') : null;
+
+const moduleData = buildInfo.newUpdater ? join(userData, 'module_data') : join(userDataVersioned, 'modules');
+
+
+exports.getUserData = () => userData;
+exports.getUserDataVersioned = () => userDataVersioned;
+
+exports.getResources = () => process.resourcesPath; // Discord uses path and require.main.filename here because ??
+exports.getModuleDataPath = () => moduleData;
+exports.getInstallPath = () => installPath;
+
+exports.init = () => {}; // Stub as we setup on require
\ No newline at end of file
diff --git a/src/splash/index.html b/src/splash/index.html
new file mode 100644
index 0000000..9066141
--- /dev/null
+++ b/src/splash/index.html
@@ -0,0 +1,89 @@
+
openasar go brr
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/splash/preload.js b/src/splash/preload.js
new file mode 100644
index 0000000..a475675
--- /dev/null
+++ b/src/splash/preload.js
@@ -0,0 +1,36 @@
+"use strict";
+
+const {
+ app,
+ contextBridge,
+ ipcRenderer
+} = require('electron');
+
+const {
+ saferShellOpenExternal
+} = require('../utils/securityUtils');
+
+contextBridge.exposeInMainWorld('DiscordSplash', {
+ getReleaseChannel: () => {
+ const buildInfo = require('../utils/buildInfo');
+
+ return buildInfo.releaseChannel;
+ },
+ signalReady: () => {
+ ipcRenderer.send('DISCORD_SPLASH_SCREEN_READY');
+ },
+ onStateUpdate: callback => {
+ ipcRenderer.on('DISCORD_SPLASH_UPDATE_STATE', (_, state) => {
+ callback(state);
+ });
+ },
+ onQuoteUpdate: callback => {
+ ipcRenderer.on('DISCORD_SPLASH_SCREEN_QUOTE', (_, quote) => {
+ callback(quote);
+ });
+ },
+ openUrl: saferShellOpenExternal,
+ quitDiscord: () => {
+ ipcRenderer.send('DISCORD_SPLASH_SCREEN_QUIT');
+ }
+});
\ No newline at end of file
diff --git a/src/splash/splashScreen.js b/src/splash/splashScreen.js
new file mode 100644
index 0000000..b647cba
--- /dev/null
+++ b/src/splash/splashScreen.js
@@ -0,0 +1,486 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.initSplash = initSplash;
+exports.focusWindow = focusWindow;
+exports.pageReady = pageReady;
+exports.events = exports.APP_SHOULD_SHOW = exports.APP_SHOULD_LAUNCH = void 0;
+
+var _electron = require("electron");
+
+var _events = require("events");
+
+var _fs = _interopRequireDefault(require("fs"));
+
+var _path = _interopRequireDefault(require("path"));
+
+var _url = _interopRequireDefault(require("url"));
+
+var _Backoff = _interopRequireDefault(require("../utils/Backoff"));
+
+var moduleUpdater = _interopRequireWildcard(require("../updater/moduleUpdater"));
+
+var paths = _interopRequireWildcard(require("../paths"));
+
+var _securityUtils = require("../utils/securityUtils");
+
+var _updater = require("../updater/updater");
+
+var _ipcMain = _interopRequireDefault(require("../ipcMain"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+const UPDATE_TIMEOUT_WAIT = 10000;
+const RETRY_CAP_SECONDS = 60; // citron note: atom seems to add about 50px height to the frame on mac but not windows
+// TODO: see if we can eliminate fudge by using useContentSize BrowserWindow option
+
+const LOADING_WINDOW_WIDTH = 300;
+const LOADING_WINDOW_HEIGHT = process.platform === 'darwin' ? 300 : 350; // TODO: addModulesListener events should use Module's constants
+
+const CHECKING_FOR_UPDATES = 'checking-for-updates';
+const UPDATE_CHECK_FINISHED = 'update-check-finished';
+const UPDATE_FAILURE = 'update-failure';
+const LAUNCHING = 'launching';
+const DOWNLOADING_MODULE = 'downloading-module';
+const DOWNLOADING_UPDATES = 'downloading-updates';
+const DOWNLOADING_MODULES_FINISHED = 'downloading-modules-finished';
+const DOWNLOADING_MODULE_PROGRESS = 'downloading-module-progress';
+const DOWNLOADED_MODULE = 'downloaded-module';
+const NO_PENDING_UPDATES = 'no-pending-updates';
+const INSTALLING_MODULE = 'installing-module';
+const INSTALLING_UPDATES = 'installing-updates';
+const INSTALLED_MODULE = 'installed-module';
+const INSTALLING_MODULE_PROGRESS = 'installing-module-progress';
+const INSTALLING_MODULES_FINISHED = 'installing-modules-finished';
+const UPDATE_MANUALLY = 'update-manually';
+const APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH';
+exports.APP_SHOULD_LAUNCH = APP_SHOULD_LAUNCH;
+const APP_SHOULD_SHOW = 'APP_SHOULD_SHOW';
+exports.APP_SHOULD_SHOW = APP_SHOULD_SHOW;
+const events = new _events.EventEmitter();
+exports.events = events;
+
+function webContentsSend(win, event, ...args) {
+ if (win != null && win.webContents != null) {
+ win.webContents.send(`DISCORD_${event}`, ...args);
+ }
+}
+
+let splashWindow;
+let modulesListeners;
+let updateTimeout;
+let updateAttempt;
+let splashState;
+let launchedMainWindow;
+let quoteCachePath;
+let restartRequired = false;
+let newUpdater;
+const updateBackoff = new _Backoff.default(1000, 30000); // TODO(eiz): some of this logic should probably not live in the splash.
+//
+// Disabled because Rust interop stuff is going on in here.
+
+/* eslint-disable camelcase */
+
+class TaskProgress {
+ constructor() {
+ this.inProgress = new Map();
+ this.finished = new Set();
+ this.allTasks = new Set();
+ }
+
+ recordProgress(progress, task) {
+ this.allTasks.add(task.package_sha256);
+
+ if (progress.state !== _updater.TASK_STATE_WAITING) {
+ this.inProgress.set(task.package_sha256, progress.percent);
+
+ if (progress.state === _updater.TASK_STATE_COMPLETE) {
+ this.finished.add(task.package_sha256);
+ }
+ }
+ }
+
+ updateSplashState(newState) {
+ if (this.inProgress.size > 0 && this.inProgress.size > this.finished.size) {
+ let totalPercent = 0;
+
+ for (const item of this.inProgress.values()) {
+ totalPercent += item;
+ }
+
+ totalPercent /= this.allTasks.size;
+ splashState = {
+ current: this.finished.size + 1,
+ total: this.allTasks.size,
+ progress: totalPercent
+ };
+ updateSplashState(newState);
+ return true;
+ }
+
+ return false;
+ }
+
+}
+
+async function updateUntilCurrent() {
+ const retryOptions = {
+ skip_host_delta: false,
+ skip_module_delta: {}
+ };
+
+ while (true) {
+ updateSplashState(CHECKING_FOR_UPDATES);
+
+ try {
+ let installedAnything = false;
+ const downloads = new TaskProgress();
+ const installs = new TaskProgress();
+ await newUpdater.updateToLatestWithOptions(retryOptions, progress => {
+ const task = progress.task;
+ const downloadTask = task.HostDownload || task.ModuleDownload;
+ const installTask = task.HostInstall || task.ModuleInstall;
+ installedAnything = true;
+
+ if (downloadTask != null) {
+ downloads.recordProgress(progress, downloadTask);
+ }
+
+ if (installTask != null) {
+ installs.recordProgress(progress, installTask);
+
+ if (progress.state.Failed != null) {
+ if (task.HostInstall != null) {
+ retryOptions.skip_host_delta = true;
+ } else if (task.ModuleInstall != null) {
+ retryOptions.skip_module_delta[installTask.version.module.name] = true;
+ }
+ }
+ }
+
+ if (!downloads.updateSplashState(DOWNLOADING_UPDATES)) {
+ installs.updateSplashState(INSTALLING_UPDATES);
+ }
+ });
+
+ if (!installedAnything) {
+ await newUpdater.startCurrentVersion();
+ newUpdater.setRunningInBackground();
+ newUpdater.collectGarbage();
+ launchMainWindow();
+ updateBackoff.succeed();
+ updateSplashState(LAUNCHING);
+ return;
+ }
+ } catch (e) {
+ console.error('Update failed', e);
+ await new Promise(resolve => {
+ const delayMs = updateBackoff.fail(resolve);
+ splashState.seconds = Math.round(delayMs / 1000);
+ updateSplashState(UPDATE_FAILURE);
+ });
+ }
+ }
+}
+/* eslint-enable camelcase */
+
+
+function initOldUpdater() {
+ modulesListeners = {};
+ addModulesListener(CHECKING_FOR_UPDATES, () => {
+ startUpdateTimeout();
+ updateSplashState(CHECKING_FOR_UPDATES);
+ });
+ addModulesListener(UPDATE_CHECK_FINISHED, ({
+ succeeded,
+ updateCount,
+ manualRequired
+ }) => {
+ stopUpdateTimeout();
+
+ if (!succeeded) {
+ scheduleUpdateCheck();
+ updateSplashState(UPDATE_FAILURE);
+ } else if (updateCount === 0) {
+ moduleUpdater.setInBackground();
+ launchMainWindow();
+ updateSplashState(LAUNCHING);
+ }
+ });
+ addModulesListener(DOWNLOADING_MODULE, ({
+ name,
+ current,
+ total
+ }) => {
+ stopUpdateTimeout();
+ splashState = {
+ current,
+ total
+ };
+ updateSplashState(DOWNLOADING_UPDATES);
+ });
+ addModulesListener(DOWNLOADING_MODULE_PROGRESS, ({
+ name,
+ progress
+ }) => {
+ splashState.progress = progress;
+ updateSplashState(DOWNLOADING_UPDATES);
+ });
+ addModulesListener(DOWNLOADED_MODULE, ({
+ name,
+ current,
+ total,
+ succeeded
+ }) => {
+ delete splashState.progress;
+
+ if (name === 'host') {
+ restartRequired = true;
+ }
+ });
+ addModulesListener(DOWNLOADING_MODULES_FINISHED, ({
+ succeeded,
+ failed
+ }) => {
+ if (failed > 0) {
+ scheduleUpdateCheck();
+ updateSplashState(UPDATE_FAILURE);
+ } else {
+ process.nextTick(() => {
+ if (restartRequired) {
+ moduleUpdater.quitAndInstallUpdates();
+ } else {
+ moduleUpdater.installPendingUpdates();
+ }
+ });
+ }
+ });
+ addModulesListener(NO_PENDING_UPDATES, () => moduleUpdater.checkForUpdates());
+ addModulesListener(INSTALLING_MODULE, ({
+ name,
+ current,
+ total
+ }) => {
+ splashState = {
+ current,
+ total
+ };
+ updateSplashState(INSTALLING_UPDATES);
+ });
+ addModulesListener(INSTALLED_MODULE, ({
+ name,
+ current,
+ total,
+ succeeded
+ }) => delete splashState.progress);
+ addModulesListener(INSTALLING_MODULE_PROGRESS, ({
+ name,
+ progress
+ }) => {
+ splashState.progress = progress;
+ updateSplashState(INSTALLING_UPDATES);
+ });
+ addModulesListener(INSTALLING_MODULES_FINISHED, ({
+ succeeded,
+ failed
+ }) => moduleUpdater.checkForUpdates());
+ addModulesListener(UPDATE_MANUALLY, ({
+ newVersion
+ }) => {
+ splashState.newVersion = newVersion;
+ updateSplashState(UPDATE_MANUALLY);
+ });
+}
+
+function initSplash(startMinimized = false) {
+ splashState = {};
+ launchedMainWindow = false;
+ updateAttempt = 0;
+ newUpdater = (0, _updater.getUpdater)();
+
+ if (newUpdater == null) {
+ initOldUpdater();
+ }
+
+ launchSplashWindow(startMinimized);
+ quoteCachePath = _path.default.join(paths.getUserData(), 'quotes.json');
+
+ _ipcMain.default.on('UPDATED_QUOTES', (_event, quotes) => cacheLatestQuotes(quotes));
+}
+
+function destroySplash() {
+ stopUpdateTimeout();
+
+ if (splashWindow) {
+ splashWindow.setSkipTaskbar(true); // defer the window hiding for a short moment so it gets covered by the main window
+
+ const _nukeWindow = () => {
+ if (splashWindow != null) {
+ splashWindow.hide();
+ splashWindow.close();
+ splashWindow = null;
+ }
+ };
+
+ setTimeout(_nukeWindow, 100);
+ }
+}
+
+function addModulesListener(event, listener) {
+ if (newUpdater != null) return;
+ modulesListeners[event] = listener;
+ moduleUpdater.events.addListener(event, listener);
+}
+
+function removeModulesListeners() {
+ if (newUpdater != null) return;
+
+ for (const event of Object.keys(modulesListeners)) {
+ moduleUpdater.events.removeListener(event, modulesListeners[event]);
+ }
+}
+
+function startUpdateTimeout() {
+ if (!updateTimeout) {
+ updateTimeout = setTimeout(() => scheduleUpdateCheck(), UPDATE_TIMEOUT_WAIT);
+ }
+}
+
+function stopUpdateTimeout() {
+ if (updateTimeout) {
+ clearTimeout(updateTimeout);
+ updateTimeout = null;
+ }
+}
+
+function updateSplashState(event) {
+ if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) {
+ webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', {
+ status: event,
+ ...splashState
+ });
+ }
+}
+
+function launchSplashWindow(startMinimized) {
+ const windowConfig = {
+ width: LOADING_WINDOW_WIDTH,
+ height: LOADING_WINDOW_HEIGHT,
+ transparent: false,
+ frame: false,
+ resizable: false,
+ center: true,
+ show: false,
+ webPreferences: {
+ nodeIntegration: false,
+ enableRemoteModule: false,
+ contextIsolation: true,
+ preload: _path.default.join(__dirname, 'preload.js')
+ }
+ };
+ splashWindow = new _electron.BrowserWindow(windowConfig); // prevent users from dropping links to navigate in splash window
+
+ splashWindow.webContents.on('will-navigate', e => e.preventDefault());
+ splashWindow.webContents.on('new-window', (e, windowURL) => {
+ e.preventDefault();
+ (0, _securityUtils.saferShellOpenExternal)(windowURL); // exit, but delay half a second because openExternal is about to fire
+ // some events to things that are freed by app.quit.
+
+ setTimeout(_electron.app.quit, 500);
+ });
+
+ if (process.platform !== 'darwin') {
+ // citron note: this causes a crash on quit while the window is open on osx
+ splashWindow.on('closed', () => {
+ splashWindow = null;
+
+ if (!launchedMainWindow) {
+ // user has closed this window before we launched the app, so let's quit
+ _electron.app.quit();
+ }
+ });
+ }
+
+ _ipcMain.default.on('SPLASH_SCREEN_READY', () => {
+ const cachedQuote = chooseCachedQuote();
+
+ if (cachedQuote) {
+ webContentsSend(splashWindow, 'SPLASH_SCREEN_QUOTE', cachedQuote);
+ }
+
+ if (splashWindow && !startMinimized) {
+ splashWindow.show();
+ }
+
+ if (newUpdater != null) {
+ updateUntilCurrent();
+ } else {
+ moduleUpdater.installPendingUpdates();
+ }
+ });
+
+ _ipcMain.default.on('SPLASH_SCREEN_QUIT', () => {
+ _electron.app.quit();
+ });
+
+ const splashUrl = _url.default.format({
+ protocol: 'file',
+ slashes: true,
+ pathname: _path.default.join(__dirname, 'index.html')
+ });
+
+ splashWindow.loadURL(splashUrl);
+}
+
+function launchMainWindow() {
+ removeModulesListeners();
+
+ if (!launchedMainWindow && splashWindow != null) {
+ launchedMainWindow = true;
+ events.emit(APP_SHOULD_LAUNCH);
+ }
+}
+
+function scheduleUpdateCheck() {
+ // TODO: can we use backoff here?
+ updateAttempt += 1;
+ const retryInSeconds = Math.min(updateAttempt * 10, RETRY_CAP_SECONDS);
+ splashState.seconds = retryInSeconds;
+ setTimeout(() => moduleUpdater.checkForUpdates(), retryInSeconds * 1000);
+}
+
+function focusWindow() {
+ if (splashWindow != null) {
+ splashWindow.focus();
+ }
+}
+
+function pageReady() {
+ destroySplash();
+ process.nextTick(() => events.emit(APP_SHOULD_SHOW));
+}
+
+function cacheLatestQuotes(quotes) {
+ _fs.default.writeFile(quoteCachePath, JSON.stringify(quotes), e => {
+ if (e) {
+ console.warn('Failed updating quote cache with error: ', e);
+ }
+ });
+}
+
+function chooseCachedQuote() {
+ let cachedQuote = null;
+
+ try {
+ const cachedQuotes = JSON.parse(_fs.default.readFileSync(quoteCachePath));
+ cachedQuote = cachedQuotes[Math.floor(Math.random() * cachedQuotes.length)];
+ } catch (_err) {}
+
+ return cachedQuote;
+}
\ No newline at end of file
diff --git a/src/splash/splashScreen.js.self b/src/splash/splashScreen.js.self
new file mode 100644
index 0000000..d76e875
--- /dev/null
+++ b/src/splash/splashScreen.js.self
@@ -0,0 +1,95 @@
+const { BrowserWindow, app } = require('electron');
+
+const { format } = require('url');
+const { join } = require('path');
+
+const ipcMain = require('../ipcMain');
+
+
+const LOADING_WINDOW_WIDTH = 300;
+const LOADING_WINDOW_HEIGHT = process.platform === 'darwin' ? 300 : 350; // TODO: addModulesListener events should use Module's constants
+
+let window;
+
+const APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH';
+exports.APP_SHOULD_LAUNCH = APP_SHOULD_LAUNCH;
+const APP_SHOULD_SHOW = 'APP_SHOULD_SHOW';
+exports.APP_SHOULD_SHOW = APP_SHOULD_SHOW;
+const events = new (require('events')).EventEmitter();
+
+exports.events = events;
+
+exports.initSplash = (startMinimized = false) => { // Make splash window
+ const windowConfig = {
+ width: LOADING_WINDOW_WIDTH,
+ height: LOADING_WINDOW_HEIGHT,
+ transparent: false,
+ frame: false,
+ resizable: false,
+ center: true,
+ show: false,
+ webPreferences: {
+ nodeIntegration: false,
+ enableRemoteModule: false,
+ contextIsolation: true,
+ preload: join(__dirname, 'preload.js')
+ }
+ };
+
+ window = new BrowserWindow(windowConfig);
+
+ window.on('closed', () => { // Quit app on splash screen close
+ app.quit();
+ window = null;
+ });
+
+
+ // IPC "handlers"
+ ipcMain.on('SPLASH_SCREEN_READY', () => {
+ if (!startMinimized && window) window.show();
+
+ // Update and stuff
+
+ events.emit(APP_SHOULD_LAUNCH);
+ });
+
+ if (!startMinimized && window) window.show();
+
+ // Update and stuff
+
+ events.emit(APP_SHOULD_LAUNCH);
+
+ ipcMain.on('SPLASH_SCREEN_QUIT', () => {
+ app.quit();
+ });
+
+ const splashUrl = format({
+ protocol: 'file',
+ slashes: true,
+ pathname: join(__dirname, 'index.html')
+ });
+
+ window.loadURL(splashUrl);
+};
+
+exports.focusWindow = () => { // Focus splash window
+ if (window) window.focus();
+};
+
+const killWindow = () => {
+ if (!window) return;
+
+ window.setSkipTaskbar(true);
+
+ setTimeout(() => {
+ window.hide();
+ window.close();
+ window = null;
+ }, 100);
+};
+
+exports.pageReady = () => { // Kill splash window, emit
+ killWindow();
+
+ process.nextTick(() => events.emit(APP_SHOULD_SHOW));
+};
\ No newline at end of file
diff --git a/src/splash/web/a934ab008c7f6a2274ec441f6be0696a.woff b/src/splash/web/a934ab008c7f6a2274ec441f6be0696a.woff
new file mode 100644
index 0000000..98aa239
Binary files /dev/null and b/src/splash/web/a934ab008c7f6a2274ec441f6be0696a.woff differ
diff --git a/src/splash/web/abddffb32a4a35627c3857a06c751424.png b/src/splash/web/abddffb32a4a35627c3857a06c751424.png
new file mode 100644
index 0000000..909b729
Binary files /dev/null and b/src/splash/web/abddffb32a4a35627c3857a06c751424.png differ
diff --git a/src/splash/web/d153359b5d87601d2b9c708b7ae2db02.woff b/src/splash/web/d153359b5d87601d2b9c708b7ae2db02.woff
new file mode 100644
index 0000000..2a2f65a
Binary files /dev/null and b/src/splash/web/d153359b5d87601d2b9c708b7ae2db02.woff differ
diff --git a/src/splash/web/index.html b/src/splash/web/index.html
new file mode 100644
index 0000000..5dec1de
--- /dev/null
+++ b/src/splash/web/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+ Discord Updater
+
+
+
+
+
+
diff --git a/src/splash/web/index.js b/src/splash/web/index.js
new file mode 100644
index 0000000..9ea6c28
--- /dev/null
+++ b/src/splash/web/index.js
@@ -0,0 +1,41 @@
+!function(e){var t={};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}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return 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,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=27)}([function(e,t,n){e.exports=n(25)()},function(e,t,n){"use strict";e.exports=n(18)},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}}(),e.exports=n(19)},function(e,t,n){var r;
+/*!
+ Copyright (c) 2018 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/classnames
+*/!function(){"use strict";var n={}.hasOwnProperty;function a(){for(var e=[],t=0;t=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}(this.props,[]);return function(e){c.forEach((function(t){return delete e[t]}))}(a),a.className=this.props.inputClassName,a.id=this.state.inputId,a.style=n,l.default.createElement("div",{className:this.props.className,style:t},this.renderStyles(),l.default.createElement("input",r({},a,{ref:this.inputRef})),l.default.createElement("div",{ref:this.sizerRef,style:s},e),this.props.placeholder?l.default.createElement("div",{ref:this.placeHolderSizerRef,style:s},this.props.placeholder):null)}}]),t}(o.Component);h.propTypes={className:i.default.string,defaultValue:i.default.any,extraWidth:i.default.oneOfType([i.default.number,i.default.string]),id:i.default.string,injectStyles:i.default.bool,inputClassName:i.default.string,inputRef:i.default.func,inputStyle:i.default.object,minWidth:i.default.oneOfType([i.default.number,i.default.string]),onAutosize:i.default.func,onChange:i.default.func,placeholder:i.default.string,placeholderIsMinWidth:i.default.bool,style:i.default.object,value:i.default.any},h.defaultProps={minWidth:1,injectStyles:!0},t.default=h},function(e,t,n){var r=n(10);"string"==typeof r&&(r=[[e.i,r,""]]);var a={hmr:!0,transform:void 0};n(16)(r,a);r.locals&&(e.exports=r.locals)},function(e,t,n){var r=n(11);(t=e.exports=n(6)(!1)).i(n(12),""),t.push([e.i,"@font-face {\n font-family: Whitney;\n font-style: normal;\n font-weight: 400;\n src: url("+r(n(13))+") format('woff');\n}\n@font-face {\n font-family: Whitney;\n font-style: medium;\n font-weight: 600;\n src: url("+r(n(14))+') format(\'woff\');\n}\n* {\n box-sizing: border-box;\n -webkit-user-select: none;\n cursor: default;\n}\nbody,\nhtml {\n -webkit-app-region: drag;\n padding: 0;\n margin: 0;\n overflow: hidden;\n width: 300px;\n height: 300px;\n}\n#splash {\n -webkit-app-region: drag;\n background: #282b30;\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 3000;\n transform: translateZ(0);\n padding-bottom: 10px;\n}\n#splash .splash-inner {\n text-align: center;\n}\n#splash .splash-inner img,\n#splash .splash-inner video {\n size: 200px;\n}\n#splash .splash-inner video {\n visibility: hidden;\n}\n#splash .splash-inner video.loaded {\n visibility: visible;\n}\n#splash .splash-inner .splash-text {\n position: relative;\n top: -30px;\n}\n#splash .splash-inner .splash-text > span {\n color: #8a8e94;\n font-size: 12px;\n font-family: Whitney, "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;\n font-weight: 600;\n text-transform: uppercase;\n display: block;\n}\n#splash .splash-inner .splash-text > span.splash-status {\n color: #fff;\n font-weight: 400;\n font-style: italic;\n font-size: 16px;\n}\n#splash .splash-inner-dl .dice-image {\n position: absolute;\n left: 77px;\n top: 45px;\n width: 146px;\n height: 100px;\n background: url('+r(n(15))+') center center no-repeat;\n background-size: 146px 100px;\n}\n#splash .splash-inner-dl .dl-update-message {\n font-family: Whitney, "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;\n font-style: medium;\n font-size: 18px;\n color: #fff;\n padding-left: 20px;\n padding-right: 20px;\n top: 169px;\n left: 0;\n margin: 0;\n position: absolute;\n text-align: center;\n}\n#splash .splash-inner-dl .dl-version-message {\n font-family: Whitney, "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;\n font-style: medium;\n font-size: 12px;\n color: #8a8e94;\n text-transform: uppercase;\n position: absolute;\n width: 100%;\n bottom: 12px;\n left: 0;\n margin: 0;\n text-align: center;\n}\n#splash .splash-inner-dl .dl-select-frame {\n -webkit-app-region: no-drag;\n font-family: Whitney, "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;\n overflow: hidden;\n position: absolute;\n width: 100%;\n height: 130px;\n top: 220px;\n left: 0;\n margin: 0;\n}\n#splash .splash-inner-dl .dl-select-frame .Select {\n position: absolute;\n left: 0;\n top: 0;\n width: 165px;\n height: 44px;\n margin-left: 20px;\n margin-right: 10px;\n color: #fff;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-control {\n border: 1px solid;\n border-color: rgba(255,255,255,0.3);\n border-radius: 3px;\n background: #282b30;\n height: 44px;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-menu-outer {\n background: #282b30;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-menu {\n max-height: 80px;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-option {\n color: #8a8e94;\n line-height: 15px;\n padding: 5px 10px;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-option.is-focused {\n color: #fff;\n background-color: #4e59e0;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-value {\n color: #fff;\n bottom: 0;\n align-items: center;\n display: flex;\n}\n#splash .splash-inner-dl .dl-select-frame .Select-input {\n outline: none;\n}\n#splash .splash-inner-dl .dl-select-frame .dl-button {\n position: absolute;\n left: 195px;\n top: 0;\n width: 85px;\n height: 44px;\n background-color: #5865f2;\n color: #fff;\n font-size: 14px;\n font-weight: 600;\n border-radius: 3px;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n#splash .splash-inner-dl .dl-select-frame .dl-button:hover {\n background-color: #4e59e0;\n}\n.progress {\n display: flex;\n justify-content: center;\n margin-top: 10px;\n}\n.progress .progress-bar {\n height: 8px;\n border-radius: 4px;\n width: 180px;\n background-color: rgba(255,255,255,0.1);\n}\n.progress .progress-bar .complete {\n border-radius: 4px;\n box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.1), inset 0px 1px 0px 0px rgba(255,255,255,0.1);\n height: 100%;\n background-color: #737f8d;\n}\n.progress-placeholder {\n margin-top: 10px;\n height: 8px;\n}\n',""])},function(e,t){e.exports=function(e){return"string"!=typeof e?e:(/^['"].*['"]$/.test(e)&&(e=e.slice(1,-1)),/["'() \t\n]/.test(e)?'"'+e.replace(/"/g,'\\"').replace(/\n/g,"\\n")+'"':e)}},function(e,t,n){(e.exports=n(6)(!1)).push([e.i,"/**\n * React Select\n * ============\n * Created by Jed Watson and Joss Mackison for KeystoneJS, http://www.keystonejs.com/\n * https://twitter.com/jedwatson https://twitter.com/jossmackison https://twitter.com/keystonejs\n * MIT License: https://github.com/keystonejs/react-select\n*/\n.Select {\n position: relative;\n}\n.Select,\n.Select div,\n.Select input,\n.Select span {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n.Select.is-disabled > .Select-control {\n background-color: #f6f6f6;\n}\n.Select.is-disabled .Select-arrow-zone {\n cursor: default;\n pointer-events: none;\n}\n.Select-control {\n background-color: #fff;\n border-color: #d9d9d9 #ccc #b3b3b3;\n border-radius: 4px;\n border: 1px solid #ccc;\n color: #333;\n cursor: default;\n display: table;\n height: 36px;\n outline: none;\n overflow: hidden;\n position: relative;\n width: 100%;\n}\n.Select-control:hover {\n box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);\n}\n.is-searchable.is-open > .Select-control {\n cursor: text;\n}\n.is-open > .Select-control {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n background: #fff;\n border-color: #b3b3b3 #ccc #d9d9d9;\n}\n.is-open > .Select-control > .Select-arrow {\n border-color: transparent transparent #999;\n border-width: 0 5px 5px;\n}\n.is-searchable.is-focused:not(.is-open) > .Select-control {\n cursor: text;\n}\n.is-focused:not(.is-open) > .Select-control {\n border-color: #08c #0099e6 #0099e6;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 5px -1px rgba(0, 136, 204, 0.5);\n}\n.Select-placeholder {\n bottom: 0;\n color: #aaa;\n left: 0;\n line-height: 34px;\n padding-left: 10px;\n padding-right: 10px;\n position: absolute;\n right: 0;\n top: 0;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.has-value > .Select-control > .Select-placeholder {\n color: #333;\n}\n.Select-value {\n color: #aaa;\n left: 0;\n padding: 8px 52px 8px 10px;\n position: absolute;\n right: -15px;\n top: 0;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.has-value > .Select-control > .Select-value {\n color: #333;\n}\n.Select-input {\n height: 34px;\n padding-left: 10px;\n padding-right: 10px;\n vertical-align: middle;\n}\n.Select-input > input {\n background: none transparent;\n border: 0 none;\n box-shadow: none;\n cursor: default;\n display: inline-block;\n font-family: inherit;\n font-size: inherit;\n height: 34px;\n margin: 0;\n outline: none;\n padding: 0;\n -webkit-appearance: none;\n}\n.is-focused .Select-input > input {\n cursor: text;\n}\n.Select-control:not(.is-searchable) > .Select-input {\n outline: none;\n}\n.Select-loading-zone {\n cursor: pointer;\n display: table-cell;\n position: relative;\n text-align: center;\n vertical-align: middle;\n width: 16px;\n}\n.Select-loading {\n -webkit-animation: Select-animation-spin 400ms infinite linear;\n -o-animation: Select-animation-spin 400ms infinite linear;\n animation: Select-animation-spin 400ms infinite linear;\n width: 16px;\n height: 16px;\n box-sizing: border-box;\n border-radius: 50%;\n border: 2px solid #ccc;\n border-right-color: #333;\n display: inline-block;\n position: relative;\n vertical-align: middle;\n}\n.Select-clear-zone {\n -webkit-animation: Select-animation-fadeIn 200ms;\n -o-animation: Select-animation-fadeIn 200ms;\n animation: Select-animation-fadeIn 200ms;\n color: #999;\n cursor: pointer;\n display: table-cell;\n position: relative;\n text-align: center;\n vertical-align: middle;\n width: 17px;\n}\n.Select-clear-zone:hover {\n color: #d0021b;\n}\n.Select-clear {\n display: inline-block;\n font-size: 18px;\n line-height: 1;\n}\n.Select--multi .Select-clear-zone {\n width: 17px;\n}\n.Select-arrow-zone {\n cursor: pointer;\n display: table-cell;\n position: relative;\n text-align: center;\n vertical-align: middle;\n width: 25px;\n padding-right: 5px;\n}\n.Select-arrow {\n border-color: #999 transparent transparent;\n border-style: solid;\n border-width: 5px 5px 2.5px;\n display: inline-block;\n height: 0;\n width: 0;\n}\n.is-open .Select-arrow,\n.Select-arrow-zone:hover > .Select-arrow {\n border-top-color: #666;\n}\n@-webkit-keyframes Select-animation-fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n@keyframes Select-animation-fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.Select-menu-outer {\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n background-color: #fff;\n border: 1px solid #ccc;\n border-top-color: #e6e6e6;\n box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);\n box-sizing: border-box;\n margin-top: -1px;\n max-height: 200px;\n position: absolute;\n top: 100%;\n width: 100%;\n z-index: 1000;\n -webkit-overflow-scrolling: touch;\n}\n.Select-menu {\n max-height: 198px;\n overflow-y: auto;\n}\n.Select-option {\n box-sizing: border-box;\n color: #666666;\n cursor: pointer;\n display: block;\n padding: 8px 10px;\n}\n.Select-option:last-child {\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.Select-option.is-focused {\n background-color: #f2f9fc;\n color: #333;\n}\n.Select-option.is-disabled {\n color: #cccccc;\n cursor: not-allowed;\n}\n.Select-noresults,\n.Select-search-prompt,\n.Select-searching {\n box-sizing: border-box;\n color: #999999;\n cursor: default;\n display: block;\n padding: 8px 10px;\n}\n.Select--multi .Select-input {\n vertical-align: middle;\n margin-left: 10px;\n padding: 0;\n}\n.Select--multi.has-value .Select-input {\n margin-left: 5px;\n}\n.Select-item {\n background-color: #f2f9fc;\n border-radius: 2px;\n border: 1px solid #c9e6f2;\n color: #08c;\n display: inline-block;\n font-size: 0.9em;\n margin-left: 5px;\n margin-top: 5px;\n vertical-align: top;\n}\n.Select-item-icon,\n.Select-item-label {\n display: inline-block;\n vertical-align: middle;\n}\n.Select-item-label {\n border-bottom-right-radius: 2px;\n border-top-right-radius: 2px;\n cursor: default;\n padding: 2px 5px;\n}\n.Select-item-label .Select-item-label__a {\n color: #08c;\n cursor: pointer;\n}\n.Select-item-icon {\n cursor: pointer;\n border-bottom-left-radius: 2px;\n border-top-left-radius: 2px;\n border-right: 1px solid #c9e6f2;\n padding: 1px 5px 3px;\n}\n.Select-item-icon:hover,\n.Select-item-icon:focus {\n background-color: #ddeff7;\n color: #0077b3;\n}\n.Select-item-icon:active {\n background-color: #c9e6f2;\n}\n.Select--multi.is-disabled .Select-item {\n background-color: #f2f2f2;\n border: 1px solid #d9d9d9;\n color: #888;\n}\n.Select--multi.is-disabled .Select-item-icon {\n cursor: not-allowed;\n border-right: 1px solid #d9d9d9;\n}\n.Select--multi.is-disabled .Select-item-icon:hover,\n.Select--multi.is-disabled .Select-item-icon:focus,\n.Select--multi.is-disabled .Select-item-icon:active {\n background-color: #f2f2f2;\n}\n@keyframes Select-animation-spin {\n to {\n transform: rotate(1turn);\n }\n}\n@-webkit-keyframes Select-animation-spin {\n to {\n -webkit-transform: rotate(1turn);\n }\n}\n",""])},function(e,t,n){e.exports=n.p+"d153359b5d87601d2b9c708b7ae2db02.woff"},function(e,t,n){e.exports=n.p+"a934ab008c7f6a2274ec441f6be0696a.woff"},function(e,t,n){e.exports=n.p+"abddffb32a4a35627c3857a06c751424.png"},function(e,t,n){var r,a,o={},l=(r=function(){return window&&document&&document.all&&!window.atob},function(){return void 0===a&&(a=r.apply(this,arguments)),a}),i=function(e){var t={};return function(n){if(void 0===t[n]){var r=e.call(this,n);if(r instanceof window.HTMLIFrameElement)try{r=r.contentDocument.head}catch(e){r=null}t[n]=r}return t[n]}}((function(e){return document.querySelector(e)})),u=null,s=0,c=[],f=n(17);function p(e,t){for(var n=0;n=0&&c.splice(t,1)}function v(e){var t=document.createElement("style");return e.attrs.type="text/css",g(t,e.attrs),h(e,t),t}function g(e,t){Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])}))}function y(e,t){var n,r,a,o;if(t.transform&&e.css){if(!(o=t.transform(e.css)))return function(){};e.css=o}if(t.singleton){var l=s++;n=u||(u=v(t)),r=w.bind(null,n,l,!1),a=w.bind(null,n,l,!0)}else e.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(e){var t=document.createElement("link");return e.attrs.type="text/css",e.attrs.rel="stylesheet",g(t,e.attrs),h(e,t),t}(t),r=S.bind(null,n,t),a=function(){m(n),n.href&&URL.revokeObjectURL(n.href)}):(n=v(t),r=k.bind(null,n),a=function(){m(n)});return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else a()}}e.exports=function(e,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||(t.singleton=l()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var n=d(e,t);return p(n,t),function(e){for(var r=[],a=0;at}return!1}(t,n,a,r)&&(n=null),r||null===a?function(e){return!!d.call(m,e)||!d.call(h,e)&&(p.test(e)?m[e]=!0:(h[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):a.mustUseProperty?e[a.propertyName]=null===n?3!==a.type&&"":n:(t=a.attributeName,r=a.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(a=a.type)||4===a&&!0===n?"":""+n,r?e.setAttributeNS(r,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(y,b);g[t]=new v(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(y,b);g[t]=new v(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(y,b);g[t]=new v(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){g[e]=new v(e,1,!1,e.toLowerCase(),null,!1,!1)})),g.xlinkHref=new v("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){g[e]=new v(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=r.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,k=60103,S=60106,x=60107,C=60108,_=60114,O=60109,F=60110,D=60112,P=60113,N=60120,A=60115,T=60116,M=60121,R=60128,I=60129,L=60130,z=60131;if("function"==typeof Symbol&&Symbol.for){var V=Symbol.for;k=V("react.element"),S=V("react.portal"),x=V("react.fragment"),C=V("react.strict_mode"),_=V("react.profiler"),O=V("react.provider"),F=V("react.context"),D=V("react.forward_ref"),P=V("react.suspense"),N=V("react.suspense_list"),A=V("react.memo"),T=V("react.lazy"),M=V("react.block"),V("react.scope"),R=V("react.opaque.id"),I=V("react.debug_trace_mode"),L=V("react.offscreen"),z=V("react.legacy_hidden")}var j,B="function"==typeof Symbol&&Symbol.iterator;function U(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=B&&e[B]||e["@@iterator"])?e:null}function W(e){if(void 0===j)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);j=t&&t[1]||""}return"\n"+j+e}var $=!1;function K(e,t){if(!e||$)return"";$=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(e){var r=e}Reflect.construct(e,[],t)}else{try{t.call()}catch(e){r=e}e.call(t.prototype)}else{try{throw Error()}catch(e){r=e}e()}}catch(e){if(e&&r&&"string"==typeof e.stack){for(var a=e.stack.split("\n"),o=r.stack.split("\n"),l=a.length-1,i=o.length-1;1<=l&&0<=i&&a[l]!==o[i];)i--;for(;1<=l&&0<=i;l--,i--)if(a[l]!==o[i]){if(1!==l||1!==i)do{if(l--,0>--i||a[l]!==o[i])return"\n"+a[l].replace(" at new "," at ")}while(1<=l&&0<=i);break}}}finally{$=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?W(e):""}function H(e){switch(e.tag){case 5:return W(e.type);case 16:return W("Lazy");case 13:return W("Suspense");case 19:return W("SuspenseList");case 0:case 2:case 15:return e=K(e.type,!1);case 11:return e=K(e.type.render,!1);case 22:return e=K(e.type._render,!1);case 1:return e=K(e.type,!0);default:return""}}function q(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case x:return"Fragment";case S:return"Portal";case _:return"Profiler";case C:return"StrictMode";case P:return"Suspense";case N:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case F:return(e.displayName||"Context")+".Consumer";case O:return(e._context.displayName||"Context")+".Provider";case D:var t=e.render;return t=t.displayName||t.name||"",e.displayName||(""!==t?"ForwardRef("+t+")":"ForwardRef");case A:return q(e.type);case M:return q(e._render);case T:t=e._payload,e=e._init;try{return q(e(t))}catch(e){}}return null}function Q(e){switch(typeof e){case"boolean":case"number":case"object":case"string":case"undefined":return e;default:return""}}function Y(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function G(e){e._valueTracker||(e._valueTracker=function(e){var t=Y(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var a=n.get,o=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return a.call(this)},set:function(e){r=""+e,o.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(e){r=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function X(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=Y(e)?e.checked?"true":"false":e.value),(e=r)!==n&&(t.setValue(e),!0)}function J(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Z(e,t){var n=t.checked;return a({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function ee(e,t){var n=null==t.defaultValue?"":t.defaultValue,r=null!=t.checked?t.checked:t.defaultChecked;n=Q(null!=t.value?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function te(e,t){null!=(t=t.checked)&&E(e,"checked",t,!1)}function ne(e,t){te(e,t);var n=Q(t.value),r=t.type;if(null!=n)"number"===r?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===r||"reset"===r)return void e.removeAttribute("value");t.hasOwnProperty("value")?ae(e,t.type,n):t.hasOwnProperty("defaultValue")&&ae(e,t.type,Q(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function re(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!("submit"!==r&&"reset"!==r||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ae(e,t,n){"number"===t&&J(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}function oe(e,t){return e=a({children:void 0},t),(t=function(e){var t="";return r.Children.forEach(e,(function(e){null!=e&&(t+=e)})),t}(t.children))&&(e.children=t),e}function le(e,t,n,r){if(e=e.options,t){t={};for(var a=0;a=n.length))throw Error(l(93));n=n[0]}t=n}null==t&&(t=""),n=t}e._wrapperState={initialValue:Q(n)}}function se(e,t){var n=Q(t.value),r=Q(t.defaultValue);null!=n&&((n=""+n)!==e.value&&(e.value=n),null==t.defaultValue&&e.defaultValue!==n&&(e.defaultValue=n)),null!=r&&(e.defaultValue=""+r)}function ce(e){var t=e.textContent;t===e._wrapperState.initialValue&&""!==t&&null!==t&&(e.value=t)}var fe="http://www.w3.org/1999/xhtml",pe="http://www.w3.org/2000/svg";function de(e){switch(e){case"svg":return"http://www.w3.org/2000/svg";case"math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function he(e,t){return null==e||"http://www.w3.org/1999/xhtml"===e?de(t):"http://www.w3.org/2000/svg"===e&&"foreignObject"===t?"http://www.w3.org/1999/xhtml":e}var me,ve=function(e){return"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(t,n,r,a){MSApp.execUnsafeLocalFunction((function(){return e(t,n)}))}:e}((function(e,t){if(e.namespaceURI!==pe||"innerHTML"in e)e.innerHTML=t;else{for((me=me||document.createElement("div")).innerHTML="",t=me.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}}));function ge(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var ye={animationIterationCount:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},be=["Webkit","ms","Moz","O"];function Ee(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||ye.hasOwnProperty(e)&&ye[e]?(""+t).trim():t+"px"}function we(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var r=0===n.indexOf("--"),a=Ee(n,t[n],r);"float"===n&&(n="cssFloat"),r?e.setProperty(n,a):e[n]=a}}Object.keys(ye).forEach((function(e){be.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),ye[t]=ye[e]}))}));var ke=a({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Se(e,t){if(t){if(ke[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(l(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(l(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(l(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(l(62))}}function xe(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}function Ce(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var _e=null,Oe=null,Fe=null;function De(e){if(e=Jr(e)){if("function"!=typeof _e)throw Error(l(280));var t=e.stateNode;t&&(t=ea(t),_e(e.stateNode,e.type,t))}}function Pe(e){Oe?Fe?Fe.push(e):Fe=[e]:Oe=e}function Ne(){if(Oe){var e=Oe,t=Fe;if(Fe=Oe=null,De(e),t)for(e=0;e(r=31-qt(r))?0:1<n;n++)t.push(e);return t}function Ht(e,t,n){e.pendingLanes|=t;var r=t-1;e.suspendedLanes&=r,e.pingedLanes&=r,(e=e.eventTimes)[t=31-qt(t)]=n}var qt=Math.clz32?Math.clz32:function(e){return 0===e?32:31-(Qt(e)/Yt|0)|0},Qt=Math.log,Yt=Math.LN2;var Gt=o.unstable_UserBlockingPriority,Xt=o.unstable_runWithPriority,Jt=!0;function Zt(e,t,n,r){Ie||Me();var a=tn,o=Ie;Ie=!0;try{Te(a,e,t,n,r)}finally{(Ie=o)||ze()}}function en(e,t,n,r){Xt(Gt,tn.bind(null,e,t,n,r))}function tn(e,t,n,r){var a;if(Jt)if((a=0==(4&t))&&0=zn),Bn=String.fromCharCode(32),Un=!1;function Wn(e,t){switch(e){case"keyup":return-1!==In.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function $n(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var Kn=!1;var Hn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function qn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Hn[e.type]:"textarea"===t}function Qn(e,t,n,r){Pe(r),0<(t=Ir(t,"onChange")).length&&(n=new vn("onChange","change",null,n,r),e.push({event:n,listeners:t}))}var Yn=null,Gn=null;function Xn(e){Fr(e,0)}function Jn(e){if(X(Zr(e)))return e}function Zn(e,t){if("change"===e)return t}var er=!1;if(f){var tr;if(f){var nr="oninput"in document;if(!nr){var rr=document.createElement("div");rr.setAttribute("oninput","return;"),nr="function"==typeof rr.oninput}tr=nr}else tr=!1;er=tr&&(!document.documentMode||9=t)return{node:r,offset:t-e};e=n}e:{for(;r;){if(r.nextSibling){r=r.nextSibling;break e}r=r.parentNode}r=void 0}r=dr(r)}}function mr(){for(var e=window,t=J();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(e){n=!1}if(!n)break;t=J((e=t.contentWindow).document)}return t}function vr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}var gr=f&&"documentMode"in document&&11>=document.documentMode,yr=null,br=null,Er=null,wr=!1;function kr(e,t,n){var r=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;wr||null==yr||yr!==J(r)||("selectionStart"in(r=yr)&&vr(r)?r={start:r.selectionStart,end:r.selectionEnd}:r={anchorNode:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset},Er&&pr(Er,r)||(Er=r,0<(r=Ir(br,"onSelect")).length&&(t=new vn("onSelect","select",null,t,n),e.push({event:t,listeners:r}),t.target=yr)))}Lt("cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focusin focus focusout blur input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange".split(" "),0),Lt("drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel".split(" "),1),Lt(It,2);for(var Sr="change selectionchange textInput compositionstart compositionend compositionupdate".split(" "),xr=0;xrra||(e.current=na[ra],na[ra]=null,ra--)}function la(e,t){ra++,na[ra]=e.current,e.current=t}var ia={},ua=aa(ia),sa=aa(!1),ca=ia;function fa(e,t){var n=e.type.contextTypes;if(!n)return ia;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var a,o={};for(a in n)o[a]=t[a];return r&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function pa(e){return null!=(e=e.childContextTypes)}function da(){oa(sa),oa(ua)}function ha(e,t,n){if(ua.current!==ia)throw Error(l(168));la(ua,t),la(sa,n)}function ma(e,t,n){var r=e.stateNode;if(e=t.childContextTypes,"function"!=typeof r.getChildContext)return n;for(var o in r=r.getChildContext())if(!(o in e))throw Error(l(108,q(t)||"Unknown",o));return a({},n,r)}function va(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||ia,ca=ua.current,la(ua,e),la(sa,sa.current),!0}function ga(e,t,n){var r=e.stateNode;if(!r)throw Error(l(169));n?(e=ma(e,t,ca),r.__reactInternalMemoizedMergedChildContext=e,oa(sa),oa(ua),la(ua,e)):oa(sa),la(sa,n)}var ya=null,ba=null,Ea=o.unstable_runWithPriority,wa=o.unstable_scheduleCallback,ka=o.unstable_cancelCallback,Sa=o.unstable_shouldYield,xa=o.unstable_requestPaint,Ca=o.unstable_now,_a=o.unstable_getCurrentPriorityLevel,Oa=o.unstable_ImmediatePriority,Fa=o.unstable_UserBlockingPriority,Da=o.unstable_NormalPriority,Pa=o.unstable_LowPriority,Na=o.unstable_IdlePriority,Aa={},Ta=void 0!==xa?xa:function(){},Ma=null,Ra=null,Ia=!1,La=Ca(),za=1e4>La?Ca:function(){return Ca()-La};function Va(){switch(_a()){case Oa:return 99;case Fa:return 98;case Da:return 97;case Pa:return 96;case Na:return 95;default:throw Error(l(332))}}function ja(e){switch(e){case 99:return Oa;case 98:return Fa;case 97:return Da;case 96:return Pa;case 95:return Na;default:throw Error(l(332))}}function Ba(e,t){return e=ja(e),Ea(e,t)}function Ua(e,t,n){return e=ja(e),wa(e,t,n)}function Wa(){if(null!==Ra){var e=Ra;Ra=null,ka(e)}$a()}function $a(){if(!Ia&&null!==Ma){Ia=!0;var e=0;try{var t=Ma;Ba(99,(function(){for(;em?(v=f,f=null):v=f.sibling;var g=d(a,f,i[m],u);if(null===g){null===f&&(f=v);break}e&&f&&null===g.alternate&&t(a,f),l=o(g,l,m),null===c?s=g:c.sibling=g,c=g,f=v}if(m===i.length)return n(a,f),s;if(null===f){for(;mv?(g=m,m=null):g=m.sibling;var b=d(a,m,y.value,s);if(null===b){null===m&&(m=g);break}e&&m&&null===b.alternate&&t(a,m),i=o(b,i,v),null===f?c=b:f.sibling=b,f=b,m=g}if(y.done)return n(a,m),c;if(null===m){for(;!y.done;v++,y=u.next())null!==(y=p(a,y.value,s))&&(i=o(y,i,v),null===f?c=y:f.sibling=y,f=y);return c}for(m=r(a,m);!y.done;v++,y=u.next())null!==(y=h(m,a,v,y.value,s))&&(e&&null!==y.alternate&&m.delete(null===y.key?v:y.key),i=o(y,i,v),null===f?c=y:f.sibling=y,f=y);return e&&m.forEach((function(e){return t(a,e)})),c}return function e(r,o,u,s){var c="object"==typeof u&&null!==u&&u.type===x&&null===u.key;c&&(u=u.props.children);var f="object"==typeof u&&null!==u;if(f)switch(u.$$typeof){case k:e:{for(f=u.key,c=o;null!==c;){if(c.key===f){switch(c.tag){case 7:if(u.type===x){n(r,c.sibling),(o=a(c,u.props.children)).return=r,r=o;break e}break;case 22:if((f=u.type).$$typeof===T&&(f=wo(f)),f.$$typeof===M&&f._render===c.type._render){n(r,c.sibling),(o=a(c,u.props)).type=f,o.return=r,r=o;break e}default:if(c.elementType===u.type){n(r,c.sibling),(o=a(c,u.props)).ref=bo(r,c,u),o.return=r,r=o;break e}}n(r,c);break}t(r,c),c=c.sibling}u.type===x?((o=Gu(u.props.children,r.mode,s,u.key)).return=r,r=o):((s=Yu(u.type,u.key,u.props,null,r.mode,s)).ref=bo(r,o,u),s.return=r,r=s)}return i(r);case S:e:{for(c=u.key;null!==o;){if(o.key===c){if(4===o.tag&&o.stateNode.containerInfo===u.containerInfo&&o.stateNode.implementation===u.implementation){n(r,o.sibling),(o=a(o,u.children||[])).return=r,r=o;break e}n(r,o);break}t(r,o),o=o.sibling}(o=Zu(u,r.mode,s)).return=r,r=o}return i(r);case T:return e(r,o,(c=u._init)(u._payload),s)}if("string"==typeof u||"number"==typeof u)return u=""+u,null!==o&&6===o.tag?(n(r,o.sibling),(o=a(o,u)).return=r,r=o):(n(r,o),(o=Ju(u,r.mode,s)).return=r,r=o),i(r);if(yo(u))return m(r,o,u,s);if(U(u))return v(r,o,u,s);if(f&&Eo(r,u),void 0===u&&!c)switch(r.tag){case 1:case 22:case 0:case 11:case 15:throw Error(l(152,q(r.type)||"Component"))}return n(r,o)}}var So=ko(!0),xo=ko(!1),Co={},_o=aa(Co),Oo=aa(Co),Fo=aa(Co);function Do(e){if(e===Co)throw Error(l(174));return e}function Po(e,t){switch(la(Fo,t),la(Oo,e),la(_o,Co),e=t.nodeType){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:he(null,"");break;default:t=he(t=(e=8===e?t.parentNode:t).namespaceURI||null,e=e.tagName)}oa(_o),la(_o,t)}function No(){oa(_o),oa(Oo),oa(Fo)}function Ao(e){Do(Fo.current);var t=Do(_o.current),n=he(t,e.type);t!==n&&(la(Oo,e),la(_o,n))}function To(e){Oo.current===e&&(oa(_o),oa(Oo))}var Mo=aa(0);function Ro(e){for(var t=e;null!==t;){if(13===t.tag){var n=t.memoizedState;if(null!==n&&(null===(n=n.dehydrated)||"$?"===n.data||"$!"===n.data))return t}else if(19===t.tag&&void 0!==t.memoizedProps.revealOrder){if(0!=(64&t.flags))return t}else if(null!==t.child){t.child.return=t,t=t.child;continue}if(t===e)break;for(;null===t.sibling;){if(null===t.return||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var Io=null,Lo=null,zo=!1;function Vo(e,t){var n=Hu(5,null,null,0);n.elementType="DELETED",n.type="DELETED",n.stateNode=t,n.return=e,n.flags=8,null!==e.lastEffect?(e.lastEffect.nextEffect=n,e.lastEffect=n):e.firstEffect=e.lastEffect=n}function jo(e,t){switch(e.tag){case 5:var n=e.type;return null!==(t=1!==t.nodeType||n.toLowerCase()!==t.nodeName.toLowerCase()?null:t)&&(e.stateNode=t,!0);case 6:return null!==(t=""===e.pendingProps||3!==t.nodeType?null:t)&&(e.stateNode=t,!0);case 13:return null!==(t=8!==t.nodeType?null:t)&&(e.memoizedState={dehydrated:t,retryLane:1073741824},(n=Hu(18,null,null,0)).stateNode=t,n.return=e,e.child=n,!0);default:return!1}}function Bo(e){if(zo){var t=Lo;if(t){var n=t;if(!jo(e,t)){if(!(t=Qr(n.nextSibling))||!jo(e,t))return e.flags=-1025&e.flags|2,zo=!1,void(Io=e);Vo(Io,n)}Io=e,Lo=Qr(t.firstChild)}else e.flags=-1025&e.flags|2,zo=!1,Io=e}}function Uo(e){for(e=e.return;null!==e&&5!==e.tag&&3!==e.tag&&13!==e.tag;)e=e.return;Io=e}function Wo(e){if(e!==Io)return!1;if(!zo)return Uo(e),zo=!0,!1;var t=e.type;if(5!==e.tag||"head"!==t&&"body"!==t&&!Wr(t,e.memoizedProps))for(t=Lo;t;)Vo(e,t),t=Qr(t.nextSibling);if(Uo(e),13===e.tag){if(!(e=null!==(e=e.memoizedState)?e.dehydrated:null))throw Error(l(317));e:{for(e=e.nextSibling,t=0;e;){if(8===e.nodeType){var n=e.data;if("/$"===n){if(0===t){Lo=Qr(e.nextSibling);break e}t--}else"$"!==n&&"$!"!==n&&"$?"!==n||t++}e=e.nextSibling}Lo=null}}else Lo=Io?Qr(e.stateNode.nextSibling):null;return!0}function $o(){Lo=Io=null,zo=!1}var Ko=[];function Ho(){for(var e=0;eo))throw Error(l(301));o+=1,Jo=Xo=null,t.updateQueue=null,qo.current=Al,e=n(r,a)}while(el)}if(qo.current=Dl,t=null!==Xo&&null!==Xo.next,Yo=0,Jo=Xo=Go=null,Zo=!1,t)throw Error(l(300));return e}function al(e,t,n){t.updateQueue=e.updateQueue,t.flags&=-517,e.lanes&=~n}function ol(){var e={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};return null===Jo?Go.memoizedState=Jo=e:Jo=Jo.next=e,Jo}function ll(){if(null===Xo){var e=Go.alternate;e=null!==e?e.memoizedState:null}else e=Xo.next;var t=null===Jo?Go.memoizedState:Jo.next;if(null!==t)Jo=t,Xo=e;else{if(null===e)throw Error(l(310));e={memoizedState:(Xo=e).memoizedState,baseState:Xo.baseState,baseQueue:Xo.baseQueue,queue:Xo.queue,next:null},null===Jo?Go.memoizedState=Jo=e:Jo=Jo.next=e}return Jo}function il(e,t){return"function"==typeof t?t(e):t}function ul(e){var t=ll(),n=t.queue;if(null===n)throw Error(l(311));n.lastRenderedReducer=e;var r=Xo,a=r.baseQueue,o=n.pending;if(null!==o){if(null!==a){var i=a.next;a.next=o.next,o.next=i}r.baseQueue=a=o,n.pending=null}if(null!==a){a=a.next,r=r.baseState;var u=i=o=null,s=a;do{var c=s.lane;if((Yo&c)===c)null!==u&&(u=u.next={lane:0,action:s.action,eagerReducer:s.eagerReducer,eagerState:s.eagerState,next:null}),r=s.eagerReducer===e?s.eagerState:e(r,s.action);else{var f={lane:c,action:s.action,eagerReducer:s.eagerReducer,eagerState:s.eagerState,next:null};null===u?(i=u=f,o=r):u=u.next=f,Go.lanes|=c,Vi|=c}s=s.next}while(null!==s&&s!==a);null===u?o=r:u.next=i,cr(r,t.memoizedState)||(Ml=!0),t.memoizedState=r,t.baseState=o,t.baseQueue=u,n.lastRenderedState=r}return[t.memoizedState,n.dispatch]}function sl(e){var t=ll(),n=t.queue;if(null===n)throw Error(l(311));n.lastRenderedReducer=e;var r=n.dispatch,a=n.pending,o=t.memoizedState;if(null!==a){n.pending=null;var i=a=a.next;do{o=e(o,i.action),i=i.next}while(i!==a);cr(o,t.memoizedState)||(Ml=!0),t.memoizedState=o,null===t.baseQueue&&(t.baseState=o),n.lastRenderedState=o}return[o,r]}function cl(e,t,n){var r=t._getVersion;r=r(t._source);var a=t._workInProgressVersionPrimary;if(null!==a?e=a===r:(e=e.mutableReadLanes,(e=(Yo&e)===e)&&(t._workInProgressVersionPrimary=r,Ko.push(t))),e)return n(t._source);throw Ko.push(t),Error(l(350))}function fl(e,t,n,r){var a=Ni;if(null===a)throw Error(l(349));var o=t._getVersion,i=o(t._source),u=qo.current,s=u.useState((function(){return cl(a,t,n)})),c=s[1],f=s[0];s=Jo;var p=e.memoizedState,d=p.refs,h=d.getSnapshot,m=p.source;p=p.subscribe;var v=Go;return e.memoizedState={refs:d,source:t,subscribe:r},u.useEffect((function(){d.getSnapshot=n,d.setSnapshot=c;var e=o(t._source);if(!cr(i,e)){e=n(t._source),cr(f,e)||(c(e),e=fu(v),a.mutableReadLanes|=e&a.pendingLanes),e=a.mutableReadLanes,a.entangledLanes|=e;for(var r=a.entanglements,l=e;0n?98:n,(function(){e(!0)})),Ba(97<\/script>",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=s.createElement(n,{is:r.is}):(e=s.createElement(n),"select"===n&&(s=e,r.multiple?s.multiple=!0:r.size&&(s.size=r.size))):e=s.createElementNS(e,n),e.__reactFiber$=t,e.__reactProps$=r,Hl(e,t),t.stateNode=e,s=xe(n,r),n){case"dialog":Dr("cancel",e),Dr("close",e),o=r;break;case"iframe":case"object":case"embed":Dr("load",e),o=r;break;case"video":case"audio":for(o=0;o$i&&(t.flags|=64,i=!0,li(r,!1),t.lanes=33554432)}else{if(!i)if(null!==(e=Ro(s))){if(t.flags|=64,i=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),li(r,!0),null===r.tail&&"hidden"===r.tailMode&&!s.alternate&&!zo)return null!==(t=t.lastEffect=r.lastEffect)&&(t.nextEffect=null),null}else 2*za()-r.renderingStartTime>$i&&1073741824!==n&&(t.flags|=64,i=!0,li(r,!1),t.lanes=33554432);r.isBackwards?(s.sibling=t.child,t.child=s):(null!==(n=r.last)?n.sibling=s:t.child=s,r.last=s)}return null!==r.tail?(n=r.tail,r.rendering=n,r.tail=n.sibling,r.lastEffect=t.lastEffect,r.renderingStartTime=za(),n.sibling=null,t=Mo.current,la(Mo,i?1&t|2:1&t),n):null;case 22:return null;case 23:case 24:return ku(),null!==e&&null!==e.memoizedState!=(null!==t.memoizedState)&&"unstable-defer-without-hiding"!==r.mode&&(t.flags|=4),null}throw Error(l(156,t.tag))}function ui(e){switch(e.tag){case 1:pa(e.type)&&da();var t=e.flags;return 4096&t?(e.flags=-4097&t|64,e):null;case 3:if(No(),oa(sa),oa(ua),Ho(),0!=(64&(t=e.flags)))throw Error(l(285));return e.flags=-4097&t|64,e;case 5:return To(e),null;case 13:if(oa(Mo),null!==(t=e.memoizedState)&&null!==t.dehydrated){if(null===e.alternate)throw Error(l(340));$o()}return 4096&(t=e.flags)?(e.flags=-4097&t|64,e):null;case 19:return oa(Mo),null;case 4:return No(),null;case 10:return Ja(e),null;case 23:case 24:return ku(),null;default:return null}}function si(e,t){try{var n="",r=t;do{n+=H(r),r=r.return}while(r);var a=n}catch(e){a="\nError generating stack: "+e.message+"\n"+e.stack}return{value:e,source:t,stack:a}}function ci(e,t){try{console.error(t.value)}catch(e){setTimeout((function(){throw e}))}}Hl=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},ql=function(e,t,n,r){var o=e.memoizedProps;if(o!==r){e=t.stateNode,Do(_o.current);var l,i=null;switch(n){case"input":o=Z(e,o),r=Z(e,r),i=[];break;case"option":o=oe(e,o),r=oe(e,r),i=[];break;case"select":o=a({},o,{value:void 0}),r=a({},r,{value:void 0}),i=[];break;case"textarea":o=ie(e,o),r=ie(e,r),i=[];break;default:"function"!=typeof o.onClick&&"function"==typeof r.onClick&&(e.onclick=Vr)}for(f in Se(n,r),n=null,o)if(!r.hasOwnProperty(f)&&o.hasOwnProperty(f)&&null!=o[f])if("style"===f){var s=o[f];for(l in s)s.hasOwnProperty(l)&&(n||(n={}),n[l]="")}else"dangerouslySetInnerHTML"!==f&&"children"!==f&&"suppressContentEditableWarning"!==f&&"suppressHydrationWarning"!==f&&"autoFocus"!==f&&(u.hasOwnProperty(f)?i||(i=[]):(i=i||[]).push(f,null));for(f in r){var c=r[f];if(s=null!=o?o[f]:void 0,r.hasOwnProperty(f)&&c!==s&&(null!=c||null!=s))if("style"===f)if(s){for(l in s)!s.hasOwnProperty(l)||c&&c.hasOwnProperty(l)||(n||(n={}),n[l]="");for(l in c)c.hasOwnProperty(l)&&s[l]!==c[l]&&(n||(n={}),n[l]=c[l])}else n||(i||(i=[]),i.push(f,n)),n=c;else"dangerouslySetInnerHTML"===f?(c=c?c.__html:void 0,s=s?s.__html:void 0,null!=c&&s!==c&&(i=i||[]).push(f,c)):"children"===f?"string"!=typeof c&&"number"!=typeof c||(i=i||[]).push(f,""+c):"suppressContentEditableWarning"!==f&&"suppressHydrationWarning"!==f&&(u.hasOwnProperty(f)?(null!=c&&"onScroll"===f&&Dr("scroll",e),i||s===c||(i=[])):"object"==typeof c&&null!==c&&c.$$typeof===R?c.toString():(i=i||[]).push(f,c))}n&&(i=i||[]).push("style",n);var f=i;(t.updateQueue=f)&&(t.flags|=4)}},Ql=function(e,t,n,r){n!==r&&(t.flags|=4)};var fi="function"==typeof WeakMap?WeakMap:Map;function pi(e,t,n){(n=oo(-1,n)).tag=3,n.payload={element:null};var r=t.value;return n.callback=function(){Qi||(Qi=!0,Yi=r),ci(0,t)},n}function di(e,t,n){(n=oo(-1,n)).tag=3;var r=e.type.getDerivedStateFromError;if("function"==typeof r){var a=t.value;n.payload=function(){return ci(0,t),r(a)}}var o=e.stateNode;return null!==o&&"function"==typeof o.componentDidCatch&&(n.callback=function(){"function"!=typeof r&&(null===Gi?Gi=new Set([this]):Gi.add(this),ci(0,t));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}var hi="function"==typeof WeakSet?WeakSet:Set;function mi(e){var t=e.ref;if(null!==t)if("function"==typeof t)try{t(null)}catch(t){ju(e,t)}else t.current=null}function vi(e,t){switch(t.tag){case 0:case 11:case 15:case 22:return;case 1:if(256&t.flags&&null!==e){var n=e.memoizedProps,r=e.memoizedState;t=(e=t.stateNode).getSnapshotBeforeUpdate(t.elementType===t.type?n:Ha(t.type,n),r),e.__reactInternalSnapshotBeforeUpdate=t}return;case 3:return void(256&t.flags&&qr(t.stateNode.containerInfo));case 5:case 6:case 4:case 17:return}throw Error(l(163))}function gi(e,t,n){switch(n.tag){case 0:case 11:case 15:case 22:if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{if(3==(3&e.tag)){var r=e.create;e.destroy=r()}e=e.next}while(e!==t)}if(null!==(t=null!==(t=n.updateQueue)?t.lastEffect:null)){e=t=t.next;do{var a=e;r=a.next,0!=(4&(a=a.tag))&&0!=(1&a)&&(Lu(n,e),Iu(n,e)),e=r}while(e!==t)}return;case 1:return e=n.stateNode,4&n.flags&&(null===t?e.componentDidMount():(r=n.elementType===n.type?t.memoizedProps:Ha(n.type,t.memoizedProps),e.componentDidUpdate(r,t.memoizedState,e.__reactInternalSnapshotBeforeUpdate))),void(null!==(t=n.updateQueue)&&so(n,t,e));case 3:if(null!==(t=n.updateQueue)){if(e=null,null!==n.child)switch(n.child.tag){case 5:e=n.child.stateNode;break;case 1:e=n.child.stateNode}so(n,t,e)}return;case 5:return e=n.stateNode,void(null===t&&4&n.flags&&Ur(n.type,n.memoizedProps)&&e.focus());case 6:case 4:case 12:return;case 13:return void(null===n.memoizedState&&(n=n.alternate,null!==n&&(n=n.memoizedState,null!==n&&(n=n.dehydrated,null!==n&&xt(n)))));case 19:case 17:case 20:case 21:case 23:case 24:return}throw Error(l(163))}function yi(e,t){for(var n=e;;){if(5===n.tag){var r=n.stateNode;if(t)"function"==typeof(r=r.style).setProperty?r.setProperty("display","none","important"):r.display="none";else{r=n.stateNode;var a=n.memoizedProps.style;a=null!=a&&a.hasOwnProperty("display")?a.display:null,r.style.display=Ee("display",a)}}else if(6===n.tag)n.stateNode.nodeValue=t?"":n.memoizedProps;else if((23!==n.tag&&24!==n.tag||null===n.memoizedState||n===e)&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===e)break;for(;null===n.sibling;){if(null===n.return||n.return===e)return;n=n.return}n.sibling.return=n.return,n=n.sibling}}function bi(e,t){if(ba&&"function"==typeof ba.onCommitFiberUnmount)try{ba.onCommitFiberUnmount(ya,t)}catch(e){}switch(t.tag){case 0:case 11:case 14:case 15:case 22:if(null!==(e=t.updateQueue)&&null!==(e=e.lastEffect)){var n=e=e.next;do{var r=n,a=r.destroy;if(r=r.tag,void 0!==a)if(0!=(4&r))Lu(t,n);else{r=t;try{a()}catch(e){ju(r,e)}}n=n.next}while(n!==e)}break;case 1:if(mi(t),"function"==typeof(e=t.stateNode).componentWillUnmount)try{e.props=t.memoizedProps,e.state=t.memoizedState,e.componentWillUnmount()}catch(e){ju(t,e)}break;case 5:mi(t),t.stateNode.__reactFiber$=null,t.stateNode.__reactProps$=null,t.stateNode.__reactContainer$=null,t.stateNode.__reactEvents$=null,t.stateNode.__reactListeners$=null,t.stateNode.__reactHandles$=null;break;case 6:t.stateNode.__reactFiber$=null,t.stateNode.__reactProps$=null,t.stateNode.__reactContainer$=null,t.stateNode.__reactEvents$=null,t.stateNode.__reactListeners$=null,t.stateNode.__reactHandles$=null;break;case 4:Si(e,t)}t.stateNode=null,null!=t.alternate&&(t.alternate.stateNode=null)}function Ei(e){e.alternate=null,e.child=null,e.dependencies=null,e.firstEffect=null,e.lastEffect=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.return=null,e.updateQueue=null}function wi(e){return 5===e.tag||3===e.tag||4===e.tag}function ki(e){e:{for(var t=e.return;null!==t;){if(wi(t))break e;t=t.return}throw Error(l(160))}var n=t;switch(t=n.stateNode,n.tag){case 5:var r=!1;break;case 3:case 4:t=t.containerInfo,r=!0;break;default:throw Error(l(161))}16&n.flags&&(ge(t,""),n.flags&=-17);e:t:for(n=e;;){for(;null===n.sibling;){if(null===n.return||wi(n.return)){n=null;break e}n=n.return}for(n.sibling.return=n.return,n=n.sibling;5!==n.tag&&6!==n.tag&&18!==n.tag;){if(2&n.flags)continue t;if(null===n.child||4===n.tag)continue t;n.child.return=n,n=n.child}if(!(2&n.flags)){n=n.stateNode;break e}}r?function e(t,n,r){var a=t.tag,o=5===a||6===a;if(o)t=o?t.stateNode:t.stateNode.instance,n?8===r.nodeType?r.parentNode.insertBefore(t,n):r.insertBefore(t,n):(8===r.nodeType?(n=r.parentNode).insertBefore(t,r):(n=r).appendChild(t),null!==(r=r._reactRootContainer)&&void 0!==r||null!==n.onclick||(n.onclick=Vr));else if(4!==a&&null!==(t=t.child))for(e(t,n,r),t=t.sibling;null!==t;)e(t,n,r),t=t.sibling}(e,n,t):function e(t,n,r){var a=t.tag,o=5===a||6===a;if(o)t=o?t.stateNode:t.stateNode.instance,n?r.insertBefore(t,n):r.appendChild(t);else if(4!==a&&null!==(t=t.child))for(e(t,n,r),t=t.sibling;null!==t;)e(t,n,r),t=t.sibling}(e,n,t)}function Si(e,t){for(var n,r,a=t,o=!1;;){if(!o){o=a.return;e:for(;;){if(null===o)throw Error(l(160));switch(n=o.stateNode,o.tag){case 5:r=!1;break e;case 3:case 4:n=n.containerInfo,r=!0;break e}o=o.return}o=!0}if(5===a.tag||6===a.tag){var i=a.stateNode;e:for(var u=e,s=a,c=s;;)if(bi(u,c),null!==c.child&&4!==c.tag)c.child.return=c,c=c.child;else{if(c===s)break e;for(;null===c.sibling;){if(null===c.return||c.return===s)break e;c=c.return}c.sibling.return=c.return,c=c.sibling}r?8===(u=n).nodeType?u.parentNode.removeChild(i):u.removeChild(i):n.removeChild(i)}else if(18===a.tag)r?(i=n,u=a.stateNode,8===i.nodeType?Hr(i.parentNode,u):1===i.nodeType&&Hr(i,u),xt(i)):Hr(n,a.stateNode);else if(4===a.tag){if(null!==a.child){n=a.stateNode.containerInfo,r=!0,a.child.return=a,a=a.child;continue}}else if(bi(e,a),null!==a.child){a.child.return=a,a=a.child;continue}if(a===t)break;for(;null===a.sibling;){if(null===a.return||a.return===t)return;4===(a=a.return).tag&&(o=!1)}a.sibling.return=a.return,a=a.sibling}}function xi(e,t){switch(t.tag){case 0:case 11:case 14:case 15:case 22:var n=t.updateQueue;if(null!==(n=null!==n?n.lastEffect:null)){var r=n=n.next;do{3==(3&r.tag)&&(e=r.destroy,r.destroy=void 0,void 0!==e&&e()),r=r.next}while(r!==n)}return;case 1:return;case 5:if(null!=(n=t.stateNode)){r=t.memoizedProps;var a=null!==e?e.memoizedProps:r;e=t.type;var o=t.updateQueue;if(t.updateQueue=null,null!==o){for(n.__reactProps$=r,"input"===e&&"radio"===r.type&&null!=r.name&&te(n,r),xe(e,a),t=xe(e,r),a=0;aa&&(a=i),n&=~o}if(n=a,10<(n=(120>(n=za()-n)?120:480>n?480:1080>n?1080:1920>n?1920:3e3>n?3e3:4320>n?4320:1960*Oi(n/1960))-n)){e.timeoutHandle=$r(Au.bind(null,e),n);break}Au(e);break;case 5:Au(e);break;default:throw Error(l(329))}}return hu(e,za()),e.callbackNode===t?mu.bind(null,e):null}function vu(e,t){for(t&=~Bi,t&=~ji,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0 component higher in the tree to provide a loading indicator or placeholder to display.")}5!==Ii&&(Ii=2),u=si(u,i),p=l;do{switch(p.tag){case 3:o=u,p.flags|=4096,t&=-t,p.lanes|=t,io(p,pi(0,o,t));break e;case 1:o=u;var w=p.type,k=p.stateNode;if(0==(64&p.flags)&&("function"==typeof w.getDerivedStateFromError||null!==k&&"function"==typeof k.componentDidCatch&&(null===Gi||!Gi.has(k)))){p.flags|=4096,t&=-t,p.lanes|=t,io(p,di(p,o,t));break e}}p=p.return}while(null!==p)}Nu(n)}catch(e){t=e,Ai===n&&null!==n&&(Ai=n=n.return);continue}break}}function Cu(){var e=Fi.current;return Fi.current=Dl,null===e?Dl:e}function _u(){0!==Ii&&3!==Ii||(Ii=4),null===Ni||0==(134217727&Vi)&&0==(134217727&ji)||vu(Ni,Ti)}function Ou(e,t){var n=Pi;Pi|=16;var r=Cu();for(Ni===e&&Ti===t||Su(e,t);;)try{Fu();break}catch(t){xu(e,t)}if(Xa(),Pi=n,Fi.current=r,null!==Ai)throw Error(l(261));return Ni=null,Ti=0,Ii}function Fu(){for(;null!==Ai;)Pu(Ai)}function Du(){for(;null!==Ai&&!Sa();)Pu(Ai)}function Pu(e){var t=Hi(e.alternate,e,Mi);e.memoizedProps=e.pendingProps,null===t?Nu(e):Ai=t,Di.current=null}function Nu(e){var t=e;do{var n=t.alternate;if(e=t.return,0==(2048&t.flags)){if(null!==(n=ii(n,t,Mi)))return void(Ai=n);if(24!==(n=t).tag&&23!==n.tag||null===n.memoizedState||0!=(1073741824&Mi)||0==(4&n.mode)){for(var r=0,a=n.child;null!==a;)r|=a.lanes|a.childLanes,a=a.sibling;n.childLanes=r}null!==e&&0==(2048&e.flags)&&(null===e.firstEffect&&(e.firstEffect=t.firstEffect),null!==t.lastEffect&&(null!==e.lastEffect&&(e.lastEffect.nextEffect=t.firstEffect),e.lastEffect=t.lastEffect),1i&&(u=i,i=k,k=u),u=hr(b,k),o=hr(b,i),u&&o&&(1!==w.rangeCount||w.anchorNode!==u.node||w.anchorOffset!==u.offset||w.focusNode!==o.node||w.focusOffset!==o.offset)&&((E=E.createRange()).setStart(u.node,u.offset),w.removeAllRanges(),k>i?(w.addRange(E),w.extend(o.node,o.offset)):(E.setEnd(o.node,o.offset),w.addRange(E))))),E=[];for(w=b;w=w.parentNode;)1===w.nodeType&&E.push({element:w,left:w.scrollLeft,top:w.scrollTop});for("function"==typeof b.focus&&b.focus(),b=0;bza()-Wi?Su(e,0):Bi|=n),hu(e,t)}function Uu(e,t){0===t&&(0==(2&(t=e.mode))?t=1:0==(4&t)?t=99===Va()?1:2:(0===lu&&(lu=zi),0===(t=$t(62914560&~lu))&&(t=4194304)));var n=cu();null!==(e=du(e,t))&&(Ht(e,t,n),hu(e,n))}function Wu(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),Uu(e,n)}function $u(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,a=e.memoizedState;null!==a&&(n=a.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(l(314))}null!==r&&r.delete(t),Uu(e,n)}function Ku(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.flags=0,this.lastEffect=this.firstEffect=this.nextEffect=null,this.childLanes=this.lanes=0,this.alternate=null}function Hu(e,t,n,r){return new Ku(e,t,n,r)}function qu(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Qu(e,t){var n=e.alternate;return null===n?((n=Hu(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.nextEffect=null,n.firstEffect=null,n.lastEffect=null),n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Yu(e,t,n,r,a,o){var i=2;if(r=e,"function"==typeof e)qu(e)&&(i=1);else if("string"==typeof e)i=5;else e:switch(e){case x:return Gu(n.children,a,o,t);case I:i=8,a|=16;break;case C:i=8,a|=1;break;case _:return(e=Hu(12,n,t,8|a)).elementType=_,e.type=_,e.lanes=o,e;case P:return(e=Hu(13,n,t,a)).type=P,e.elementType=P,e.lanes=o,e;case N:return(e=Hu(19,n,t,a)).elementType=N,e.lanes=o,e;case L:return Xu(n,a,o,t);case z:return(e=Hu(24,n,t,a)).elementType=z,e.lanes=o,e;default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case O:i=10;break e;case F:i=9;break e;case D:i=11;break e;case A:i=14;break e;case T:i=16,r=null;break e;case M:i=22;break e}throw Error(l(130,null==e?e:typeof e,""))}return(t=Hu(i,n,t,a)).elementType=e,t.type=r,t.lanes=o,t}function Gu(e,t,n,r){return(e=Hu(7,e,r,t)).lanes=n,e}function Xu(e,t,n,r){return(e=Hu(23,e,r,t)).elementType=L,e.lanes=n,e}function Ju(e,t,n){return(e=Hu(6,e,null,t)).lanes=n,e}function Zu(e,t,n){return(t=Hu(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function es(e,t,n){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.pendingContext=this.context=null,this.hydrate=n,this.callbackNode=null,this.callbackPriority=0,this.eventTimes=Kt(0),this.expirationTimes=Kt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Kt(0),this.mutableSourceEagerHydrationData=null}function ts(e,t,n){var r=3=E},l=function(){},t.unstable_forceFrameRate=function(e){0>e||125>>1,a=e[r];if(!(void 0!==a&&0<_(a,t)))break e;e[r]=t,e[n]=a,n=r}}function x(e){return void 0===(e=e[0])?null:e}function C(e){var t=e[0];if(void 0!==t){var n=e.pop();if(n!==t){e[0]=n;e:for(var r=0,a=e.length;r_(l,n))void 0!==u&&0>_(u,l)?(e[r]=u,e[i]=n,r=i):(e[r]=l,e[o]=n,r=o);else{if(!(void 0!==u&&0>_(u,n)))break e;e[r]=u,e[i]=n,r=i}}}return t}return null}function _(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],F=[],D=1,P=null,N=3,A=!1,T=!1,M=!1;function R(e){for(var t=x(F);null!==t;){if(null===t.callback)C(F);else{if(!(t.startTime<=e))break;C(F),t.sortIndex=t.expirationTime,S(O,t)}t=x(F)}}function I(e){if(M=!1,R(e),!T)if(null!==x(O))T=!0,r(L);else{var t=x(F);null!==t&&a(I,t.startTime-e)}}function L(e,n){T=!1,M&&(M=!1,o()),A=!0;var r=N;try{for(R(n),P=x(O);null!==P&&(!(P.expirationTime>n)||e&&!t.unstable_shouldYield());){var l=P.callback;if("function"==typeof l){P.callback=null,N=P.priorityLevel;var i=l(P.expirationTime<=n);n=t.unstable_now(),"function"==typeof i?P.callback=i:P===x(O)&&C(O),R(n)}else C(O);P=x(O)}if(null!==P)var u=!0;else{var s=x(F);null!==s&&a(I,s.startTime-n),u=!1}return u}finally{P=null,N=r,A=!1}}var z=l;t.unstable_IdlePriority=5,t.unstable_ImmediatePriority=1,t.unstable_LowPriority=4,t.unstable_NormalPriority=3,t.unstable_Profiling=null,t.unstable_UserBlockingPriority=2,t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_continueExecution=function(){T||A||(T=!0,r(L))},t.unstable_getCurrentPriorityLevel=function(){return N},t.unstable_getFirstCallbackNode=function(){return x(O)},t.unstable_next=function(e){switch(N){case 1:case 2:case 3:var t=3;break;default:t=N}var n=N;N=t;try{return e()}finally{N=n}},t.unstable_pauseExecution=function(){},t.unstable_requestPaint=z,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=N;N=e;try{return t()}finally{N=n}},t.unstable_scheduleCallback=function(e,n,l){var i=t.unstable_now();switch("object"==typeof l&&null!==l?l="number"==typeof(l=l.delay)&&0i?(e.sortIndex=l,S(F,e),null===x(O)&&e===x(F)&&(M?o():M=!0,a(I,l-i))):(e.sortIndex=u,S(O,e),T||A||(T=!0,r(L))),e},t.unstable_wrapCallback=function(e){var t=N;return function(){var n=N;N=t;try{return e.apply(this,arguments)}finally{N=n}}}},function(e,t,n){"use strict";var r=n(4),a=n(23),o=n(24);e.exports=function(e,t,n){var l=[],i={mixins:"DEFINE_MANY",statics:"DEFINE_MANY",propTypes:"DEFINE_MANY",contextTypes:"DEFINE_MANY",childContextTypes:"DEFINE_MANY",getDefaultProps:"DEFINE_MANY_MERGED",getInitialState:"DEFINE_MANY_MERGED",getChildContext:"DEFINE_MANY_MERGED",render:"DEFINE_ONCE",componentWillMount:"DEFINE_MANY",componentDidMount:"DEFINE_MANY",componentWillReceiveProps:"DEFINE_MANY",shouldComponentUpdate:"DEFINE_ONCE",componentWillUpdate:"DEFINE_MANY",componentDidUpdate:"DEFINE_MANY",componentWillUnmount:"DEFINE_MANY",UNSAFE_componentWillMount:"DEFINE_MANY",UNSAFE_componentWillReceiveProps:"DEFINE_MANY",UNSAFE_componentWillUpdate:"DEFINE_MANY",updateComponent:"OVERRIDE_BASE"},u={getDerivedStateFromProps:"DEFINE_MANY_MERGED"},s={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n-1)return!1;if(r.filterOption)return r.filterOption.call(void 0,e,t);if(!t)return!0;var a=e[r.valueKey],o=e[r.labelKey],l=y(a),i=y(o);if(!l&&!i)return!1;var u=l?String(a):null,s=i?String(o):null;return r.ignoreAccents&&(u&&"label"!==r.matchProp&&(u=g(u)),s&&"value"!==r.matchProp&&(s=g(s))),r.ignoreCase&&(u&&"label"!==r.matchProp&&(u=u.toLowerCase()),s&&"value"!==r.matchProp&&(s=s.toLowerCase())),"start"===r.matchPos?u&&"label"!==r.matchProp&&u.substr(0,t.length)===t||s&&"value"!==r.matchProp&&s.substr(0,t.length)===t:u&&"label"!==r.matchProp&&u.indexOf(t)>=0||s&&"value"!==r.matchProp&&s.indexOf(t)>=0}))},E=function(e){var t=e.focusedOption,n=e.focusOption,r=e.inputValue,o=e.instancePrefix,l=e.onFocus,i=e.onOptionRef,u=e.onSelect,s=e.optionClassName,c=e.optionComponent,f=e.optionRenderer,d=e.options,h=e.removeValue,m=e.selectValue,v=e.valueArray,g=e.valueKey,y=c;return d.map((function(e,c){var d=v&&v.some((function(t){return t[g]===e[g]})),b=e===t,E=p()(s,{"Select-option":!0,"is-selected":d,"is-focused":b,"is-disabled":e.disabled});return a.a.createElement(y,{className:E,focusOption:n,inputValue:r,instancePrefix:o,isDisabled:e.disabled,isFocused:b,isSelected:d,key:"option-"+c+"-"+e[g],onFocus:l,onSelect:u,option:e,optionIndex:c,ref:function(e){i(e,b)},removeValue:h,selectValue:m},f(e,c,r))}))};E.propTypes={focusOption:h.a.func,focusedOption:h.a.object,inputValue:h.a.string,instancePrefix:h.a.string,onFocus:h.a.func,onOptionRef:h.a.func,onSelect:h.a.func,optionClassName:h.a.string,optionComponent:h.a.func,optionRenderer:h.a.func,options:h.a.array,removeValue:h.a.func,selectValue:h.a.func,valueArray:h.a.array,valueKey:h.a.string};var w=function(e){e.preventDefault(),e.stopPropagation(),"A"===e.target.tagName&&"href"in e.target&&(e.target.target?window.open(e.target.href,e.target.target):window.location.href=e.target.href)},k="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},S=(function(){function e(e){this.value=e}function t(t){var n,r;function a(n,r){try{var l=t[n](r),i=l.value;i instanceof e?Promise.resolve(i.value).then((function(e){a("next",e)}),(function(e){a("throw",e)})):o(l.done?"return":"normal",l.value)}catch(e){o("throw",e)}}function o(e,t){switch(e){case"return":n.resolve({value:t,done:!0});break;case"throw":n.reject(t);break;default:n.resolve({value:t,done:!1})}(n=n.next)?a(n.key,n.arg):r=null}this._invoke=function(e,t){return new Promise((function(o,l){var i={key:e,arg:t,resolve:o,reject:l,next:null};r?r=r.next=i:(n=r=i,a(e,t))}))},"function"!=typeof t.return&&(this.return=void 0)}"function"==typeof Symbol&&Symbol.asyncIterator&&(t.prototype[Symbol.asyncIterator]=function(){return this}),t.prototype.next=function(e){return this._invoke("next",e)},t.prototype.throw=function(e){return this._invoke("throw",e)},t.prototype.return=function(e){return this._invoke("return",e)}}(),function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}),x=function(){function e(e,t){for(var n=0;n=0||Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n},D=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},P=function(e){function t(e){S(this,t);var n=D(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.handleMouseDown=n.handleMouseDown.bind(n),n.handleMouseEnter=n.handleMouseEnter.bind(n),n.handleMouseMove=n.handleMouseMove.bind(n),n.handleTouchStart=n.handleTouchStart.bind(n),n.handleTouchEnd=n.handleTouchEnd.bind(n),n.handleTouchMove=n.handleTouchMove.bind(n),n.onFocus=n.onFocus.bind(n),n}return O(t,e),x(t,[{key:"handleMouseDown",value:function(e){e.preventDefault(),e.stopPropagation(),this.props.onSelect(this.props.option,e)}},{key:"handleMouseEnter",value:function(e){this.onFocus(e)}},{key:"handleMouseMove",value:function(e){this.onFocus(e)}},{key:"handleTouchEnd",value:function(e){this.dragging||this.handleMouseDown(e)}},{key:"handleTouchMove",value:function(){this.dragging=!0}},{key:"handleTouchStart",value:function(){this.dragging=!1}},{key:"onFocus",value:function(e){this.props.isFocused||this.props.onFocus(this.props.option,e)}},{key:"render",value:function(){var e=this.props,t=e.option,n=e.instancePrefix,r=e.optionIndex,o=p()(this.props.className,t.className);return t.disabled?a.a.createElement("div",{className:o,onMouseDown:w,onClick:w},this.props.children):a.a.createElement("div",{className:o,style:t.style,role:"option","aria-label":t.label,onMouseDown:this.handleMouseDown,onMouseEnter:this.handleMouseEnter,onMouseMove:this.handleMouseMove,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove,onTouchEnd:this.handleTouchEnd,id:n+"-option-"+r,title:t.title},this.props.children)}}]),t}(a.a.Component);P.propTypes={children:h.a.node,className:h.a.string,instancePrefix:h.a.string.isRequired,isDisabled:h.a.bool,isFocused:h.a.bool,isSelected:h.a.bool,onFocus:h.a.func,onSelect:h.a.func,onUnfocus:h.a.func,option:h.a.object.isRequired,optionIndex:h.a.number};var N=function(e){function t(e){S(this,t);var n=D(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return n.handleMouseDown=n.handleMouseDown.bind(n),n.onRemove=n.onRemove.bind(n),n.handleTouchEndRemove=n.handleTouchEndRemove.bind(n),n.handleTouchMove=n.handleTouchMove.bind(n),n.handleTouchStart=n.handleTouchStart.bind(n),n}return O(t,e),x(t,[{key:"handleMouseDown",value:function(e){if("mousedown"!==e.type||0===e.button)return this.props.onClick?(e.stopPropagation(),void this.props.onClick(this.props.value,e)):void(this.props.value.href&&e.stopPropagation())}},{key:"onRemove",value:function(e){e.preventDefault(),e.stopPropagation(),this.props.onRemove(this.props.value)}},{key:"handleTouchEndRemove",value:function(e){this.dragging||this.onRemove(e)}},{key:"handleTouchMove",value:function(){this.dragging=!0}},{key:"handleTouchStart",value:function(){this.dragging=!1}},{key:"renderRemoveIcon",value:function(){if(!this.props.disabled&&this.props.onRemove)return a.a.createElement("span",{className:"Select-value-icon","aria-hidden":"true",onMouseDown:this.onRemove,onTouchEnd:this.handleTouchEndRemove,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove},"×")}},{key:"renderLabel",value:function(){return this.props.onClick||this.props.value.href?a.a.createElement("a",{className:"Select-value-label",href:this.props.value.href,target:this.props.value.target,onMouseDown:this.handleMouseDown,onTouchEnd:this.handleMouseDown},this.props.children):a.a.createElement("span",{className:"Select-value-label",role:"option","aria-selected":"true",id:this.props.id},this.props.children)}},{key:"render",value:function(){return a.a.createElement("div",{className:p()("Select-value",this.props.value.disabled?"Select-value-disabled":"",this.props.value.className),style:this.props.value.style,title:this.props.value.title},this.renderRemoveIcon(),this.renderLabel())}}]),t}(a.a.Component);N.propTypes={children:h.a.node,disabled:h.a.bool,id:h.a.string,onClick:h.a.func,onRemove:h.a.func,value:h.a.object.isRequired};
+/*!
+ Copyright (c) 2018 Jed Watson.
+ Licensed under the MIT License (MIT), see
+ http://jedwatson.github.io/react-select
+*/
+var A=function(e){return"string"==typeof e?e:null!==e&&JSON.stringify(e)||""},T=h.a.oneOfType([h.a.string,h.a.node]),M=h.a.oneOfType([h.a.string,h.a.number]),R=1,I=function(e,t){var n=void 0===e?"undefined":k(e);if("string"!==n&&"number"!==n&&"boolean"!==n)return e;var r=t.options,a=t.valueKey;if(r)for(var o=0;oi||lp.bottom?c.scrollTop=s.offsetTop+s.clientHeight-c.offsetHeight:f.topt.offsetHeight&&t.scrollHeight-t.offsetHeight-t.scrollTop<=0&&this.props.onMenuScrollToBottom()}}},{key:"getOptionLabel",value:function(e){return e[this.props.labelKey]}},{key:"getValueArray",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,n="object"===(void 0===t?"undefined":k(t))?t:this.props;if(n.multi){if("string"==typeof e&&(e=e.split(n.delimiter)),!Array.isArray(e)){if(null==e)return[];e=[e]}return e.map((function(e){return I(e,n)})).filter((function(e){return e}))}var r=I(e,n);return r?[r]:[]}},{key:"setValue",value:function(e){var t=this;if(this.props.autoBlur&&this.blurInput(),this.props.required){var n=L(e,this.props.multi);this.setState({required:n})}this.props.simpleValue&&e&&(e=this.props.multi?e.map((function(e){return e[t.props.valueKey]})).join(this.props.delimiter):e[this.props.valueKey]),this.props.onChange&&this.props.onChange(e)}},{key:"selectValue",value:function(e){var t=this;this.props.closeOnSelect&&(this.hasScrolledToOption=!1);var n=this.props.onSelectResetsInput?"":this.state.inputValue;this.props.multi?this.setState({focusedIndex:null,inputValue:this.handleInputValueChange(n),isOpen:!this.props.closeOnSelect},(function(){t.getValueArray(t.props.value).some((function(n){return n[t.props.valueKey]===e[t.props.valueKey]}))?t.removeValue(e):t.addValue(e)})):this.setState({inputValue:this.handleInputValueChange(n),isOpen:!this.props.closeOnSelect,isPseudoFocused:this.state.isFocused},(function(){t.setValue(e)}))}},{key:"addValue",value:function(e){var t=this.getValueArray(this.props.value),n=this._visibleOptions.filter((function(e){return!e.disabled})),r=n.indexOf(e);this.setValue(t.concat(e)),this.props.closeOnSelect&&(n.length-1===r?this.focusOption(n[r-1]):n.length>r&&this.focusOption(n[r+1]))}},{key:"popValue",value:function(){var e=this.getValueArray(this.props.value);e.length&&!1!==e[e.length-1].clearableValue&&this.setValue(this.props.multi?e.slice(0,e.length-1):null)}},{key:"removeValue",value:function(e){var t=this,n=this.getValueArray(this.props.value);this.setValue(n.filter((function(n){return n[t.props.valueKey]!==e[t.props.valueKey]}))),this.focus()}},{key:"clearValue",value:function(e){e&&"mousedown"===e.type&&0!==e.button||(e.preventDefault(),this.setValue(this.getResetValue()),this.setState({inputValue:this.handleInputValueChange(""),isOpen:!1},this.focus),this._focusAfterClear=!0)}},{key:"getResetValue",value:function(){return void 0!==this.props.resetValue?this.props.resetValue:this.props.multi?[]:null}},{key:"focusOption",value:function(e){this.setState({focusedOption:e})}},{key:"focusNextOption",value:function(){this.focusAdjacentOption("next")}},{key:"focusPreviousOption",value:function(){this.focusAdjacentOption("previous")}},{key:"focusPageUpOption",value:function(){this.focusAdjacentOption("page_up")}},{key:"focusPageDownOption",value:function(){this.focusAdjacentOption("page_down")}},{key:"focusStartOption",value:function(){this.focusAdjacentOption("start")}},{key:"focusEndOption",value:function(){this.focusAdjacentOption("end")}},{key:"focusAdjacentOption",value:function(e){var t=this._visibleOptions.map((function(e,t){return{option:e,index:t}})).filter((function(e){return!e.option.disabled}));if(this._scrollToFocusedOptionOnUpdate=!0,!this.state.isOpen){var n={focusedOption:this._focusedOption||(t.length?t["next"===e?0:t.length-1].option:null),isOpen:!0};return this.props.onSelectResetsInput&&(n.inputValue=""),void this.setState(n)}if(t.length){for(var r=-1,a=0;a0?r-=1:r=t.length-1;else if("start"===e)r=0;else if("end"===e)r=t.length-1;else if("page_up"===e){var o=r-this.props.pageSize;r=o<0?0:o}else if("page_down"===e){var l=r+this.props.pageSize;r=l>t.length-1?t.length-1:l}-1===r&&(r=0),this.setState({focusedIndex:t[r].index,focusedOption:t[r].option})}}},{key:"getFocusedOption",value:function(){return this._focusedOption}},{key:"selectFocusedOption",value:function(){if(this._focusedOption)return this.selectValue(this._focusedOption)}},{key:"renderLoading",value:function(){if(this.props.isLoading)return a.a.createElement("span",{className:"Select-loading-zone","aria-hidden":"true"},a.a.createElement("span",{className:"Select-loading"}))}},{key:"renderValue",value:function(e,t){var n=this,r=this.props.valueRenderer||this.getOptionLabel,o=this.props.valueComponent;if(!e.length)return function(e,t,n){var r=e.inputValue,a=e.isPseudoFocused,o=e.isFocused,l=t.onSelectResetsInput;return!r||!l&&!n&&!a&&!o}(this.state,this.props,t)?a.a.createElement("div",{className:"Select-placeholder"},this.props.placeholder):null;var l,i,u,s,c,f,p=this.props.onValueClick?this.handleValueClick:null;return this.props.multi?e.map((function(t,l){return a.a.createElement(o,{disabled:n.props.disabled||!1===t.clearableValue,id:n._instancePrefix+"-value-"+l,instancePrefix:n._instancePrefix,key:"value-"+l+"-"+t[n.props.valueKey],onClick:p,onRemove:n.removeValue,placeholder:n.props.placeholder,value:t,values:e},r(t,l),a.a.createElement("span",{className:"Select-aria-only"}," "))})):(l=this.state,i=this.props,u=l.inputValue,s=l.isPseudoFocused,c=l.isFocused,f=i.onSelectResetsInput,u&&(f||!c&&s||c&&!s)?void 0:(t&&(p=null),a.a.createElement(o,{disabled:this.props.disabled,id:this._instancePrefix+"-value-item",instancePrefix:this._instancePrefix,onClick:p,placeholder:this.props.placeholder,value:e[0]},r(e[0]))))}},{key:"renderInput",value:function(e,t){var n,r=this,o=p()("Select-input",this.props.inputProps.className),l=this.state.isOpen,i=p()((C(n={},this._instancePrefix+"-list",l),C(n,this._instancePrefix+"-backspace-remove-message",this.props.multi&&!this.props.disabled&&this.state.isFocused&&!this.state.inputValue),n)),u=this.state.inputValue;!u||this.props.onSelectResetsInput||this.state.isFocused||(u="");var s=_({},this.props.inputProps,{"aria-activedescendant":l?this._instancePrefix+"-option-"+t:this._instancePrefix+"-value","aria-describedby":this.props["aria-describedby"],"aria-expanded":""+l,"aria-haspopup":""+l,"aria-label":this.props["aria-label"],"aria-labelledby":this.props["aria-labelledby"],"aria-owns":i,onBlur:this.handleInputBlur,onChange:this.handleInputChange,onFocus:this.handleInputFocus,ref:function(e){return r.input=e},role:"combobox",required:this.state.required,tabIndex:this.props.tabIndex,value:u});if(this.props.inputRenderer)return this.props.inputRenderer(s);if(this.props.disabled||!this.props.searchable){var f=F(this.props.inputProps,[]),d=p()(C({},this._instancePrefix+"-list",l));return a.a.createElement("div",_({},f,{"aria-expanded":l,"aria-owns":d,"aria-activedescendant":l?this._instancePrefix+"-option-"+t:this._instancePrefix+"-value","aria-disabled":""+this.props.disabled,"aria-label":this.props["aria-label"],"aria-labelledby":this.props["aria-labelledby"],className:o,onBlur:this.handleInputBlur,onFocus:this.handleInputFocus,ref:function(e){return r.input=e},role:"combobox",style:{border:0,width:1,display:"inline-block"},tabIndex:this.props.tabIndex||0}))}return this.props.autosize?a.a.createElement(c.a,_({id:this.props.id},s,{className:o,minWidth:"5"})):a.a.createElement("div",{className:o,key:"input-wrap",style:{display:"inline-block"}},a.a.createElement("input",_({id:this.props.id},s)))}},{key:"renderClear",value:function(){var e=this.getValueArray(this.props.value);if(this.props.clearable&&e.length&&!this.props.disabled&&!this.props.isLoading){var t=this.props.multi?this.props.clearAllText:this.props.clearValueText,n=this.props.clearRenderer();return a.a.createElement("span",{"aria-label":t,className:"Select-clear-zone",onMouseDown:this.clearValue,onTouchEnd:this.handleTouchEndClearValue,onTouchMove:this.handleTouchMove,onTouchStart:this.handleTouchStart,title:t},n)}}},{key:"renderArrow",value:function(){if(this.props.arrowRenderer){var e=this.handleMouseDownOnArrow,t=this.state.isOpen,n=this.props.arrowRenderer({onMouseDown:e,isOpen:t});return n?a.a.createElement("span",{className:"Select-arrow-zone",onMouseDown:e},n):null}}},{key:"filterOptions",value:function(e){var t=this.state.inputValue,n=this.props.options||[];if(this.props.filterOptions){var r="function"==typeof this.props.filterOptions?this.props.filterOptions:b;return r(n,t,e,{filterOption:this.props.filterOption,ignoreAccents:this.props.ignoreAccents,ignoreCase:this.props.ignoreCase,labelKey:this.props.labelKey,matchPos:this.props.matchPos,matchProp:this.props.matchProp,trimFilter:this.props.trimFilter,valueKey:this.props.valueKey})}return n}},{key:"onOptionRef",value:function(e,t){t&&(this.focused=e)}},{key:"renderMenu",value:function(e,t,n){return e&&e.length?this.props.menuRenderer({focusedOption:n,focusOption:this.focusOption,inputValue:this.state.inputValue,instancePrefix:this._instancePrefix,labelKey:this.props.labelKey,onFocus:this.focusOption,onOptionRef:this.onOptionRef,onSelect:this.selectValue,optionClassName:this.props.optionClassName,optionComponent:this.props.optionComponent,optionRenderer:this.props.optionRenderer||this.getOptionLabel,options:e,removeValue:this.removeValue,selectValue:this.selectValue,valueArray:t,valueKey:this.props.valueKey}):this.props.noResultsText?a.a.createElement("div",{className:"Select-noresults"},this.props.noResultsText):null}},{key:"renderHiddenField",value:function(e){var t=this;if(this.props.name){if(this.props.joinValues){var n=e.map((function(e){return A(e[t.props.valueKey])})).join(this.props.delimiter);return a.a.createElement("input",{disabled:this.props.disabled,name:this.props.name,ref:function(e){return t.value=e},type:"hidden",value:n})}return e.map((function(e,n){return a.a.createElement("input",{disabled:t.props.disabled,key:"hidden."+n,name:t.props.name,ref:"value"+n,type:"hidden",value:A(e[t.props.valueKey])})}))}}},{key:"getFocusableOptionIndex",value:function(e){var t=this._visibleOptions;if(!t.length)return null;var n=this.props.valueKey,r=this.state.focusedOption||e;if(r&&!r.disabled){var a=-1;if(t.some((function(e,t){var o=e[n]===r[n];return o&&(a=t),o})),-1!==a)return a}for(var o=0;oa.a.createElement("div",{className:"progress"},a.a.createElement("div",{className:"progress-bar"},a.a.createElement("div",{className:"complete",style:{width:e+"%"}})));const ee=[{value:"deb",label:"Ubuntu (deb)"},{value:"tar.gz",label:"Linux (tar.gz)"},{value:"nope",label:"I'll figure it out"}],te=`https://discord.com/api/download/${DiscordSplash.getReleaseChannel()}?platform=linux&format=`;var ne=u()({displayName:"Splash",setInterval(e,t){this.clearInterval(),this._interval=window.setInterval(t,e)},clearInterval(){this._interval&&(window.clearInterval(this._interval),this._interval=null)},componentWillUnmount(){this.clearInterval()},getInitialState:()=>({quote:J[Math.floor(Math.random()*J.length)],videoLoaded:!1,status:"checking-for-updates",update:{},selectedDownload:"deb"}),componentDidMount(){l.a.findDOMNode(this.refs.video).addEventListener("loadeddata",this.handleVideoLoaded),this.setInterval(1e3,this.updateCountdownSeconds),DiscordSplash.onStateUpdate(e=>{this.setState({update:e})}),DiscordSplash.onQuoteUpdate(e=>{this.setState({quote:e})}),DiscordSplash.signalReady()},updateCountdownSeconds(){if(this.state.update.seconds>0){const e=this.state.update;e.seconds-=1,this.setState({update:e})}},handleVideoLoaded(){this.setState({videoLoaded:!0})},handleDownloadChanged(e){this.setState({selectedDownload:e.value})},handleDownload(){if("nope"!==this.state.selectedDownload){const e=te+this.state.selectedDownload;DiscordSplash.openUrl(e,{activate:!0})}DiscordSplash.quitDiscord()},render(){let e,t=a.a.createElement("div",{className:"progress-placeholder"}," ");switch(this.state.update.status){case"installing-updates":e=a.a.createElement("span",null,"Installing Update ",this.state.update.current," of ",this.state.update.total),"number"==typeof this.state.update.progress&&(t=a.a.createElement(Z,{percent:this.state.update.progress}));break;case"downloading-updates":e=a.a.createElement("span",null,"Downloading Update ",this.state.update.current," of ",this.state.update.total),"number"==typeof this.state.update.progress&&(t=a.a.createElement(Z,{percent:this.state.update.progress}));break;case"update-failure":e=a.a.createElement("span",null,"Update Failed — Retrying in ",this.state.update.seconds," sec");break;case"launching":e=a.a.createElement("span",null,"Starting…");break;case"update-manually":const n="nope"!=this.state.selectedDownload?"Download":"Okay";return a.a.createElement("div",{id:"splash"},a.a.createElement("div",{className:"splash-inner-dl"},a.a.createElement("div",{className:"dice-image"}),a.a.createElement("div",{className:"dl-update-message"},"Must be your lucky day, there’s a new update!"),a.a.createElement("div",{className:"dl-select-frame"},a.a.createElement(X,{value:this.state.selectedDownload,autosize:!1,clearable:!1,searchable:!1,options:ee,disabled:!1,onChange:this.handleDownloadChanged}),a.a.createElement("div",{className:"dl-button",onClick:this.handleDownload},n)),a.a.createElement("div",{className:"dl-version-message"},"Version ",this.state.update.newVersion," available")));case"checking-for-updates":default:e=a.a.createElement("span",null,"Checking For Updates")}return a.a.createElement("div",{id:"splash"},a.a.createElement("div",{className:"splash-inner"},a.a.createElement("video",{autoPlay:!0,width:200,height:200,loop:!0,ref:"video",className:this.state.videoLoaded?"loaded":void 0},a.a.createElement("source",{src:"../videos/connecting.webm",type:"video/webm"})),a.a.createElement("div",{className:"splash-text"},a.a.createElement("span",{className:"splash-status"},e),t)))}});l.a.render(a.a.createElement(ne,null),document.getElementById("splash-mount"))}]);
\ No newline at end of file
diff --git a/src/splash/web/variables.json b/src/splash/web/variables.json
new file mode 100644
index 0000000..db7882a
--- /dev/null
+++ b/src/splash/web/variables.json
@@ -0,0 +1,6 @@
+{
+ "width": "300px",
+ "height": "300px",
+ "inDuration": 700,
+ "outDuration": 333
+}
diff --git a/src/updater/appUpdater.js b/src/updater/appUpdater.js
new file mode 100644
index 0000000..211af4b
--- /dev/null
+++ b/src/updater/appUpdater.js
@@ -0,0 +1,73 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.update = update;
+exports.focusSplash = focusSplash;
+
+var _fs = _interopRequireDefault(require("fs"));
+
+var _path = _interopRequireDefault(require("path"));
+
+var moduleUpdater = _interopRequireWildcard(require("./moduleUpdater"));
+
+var paths = _interopRequireWildcard(require("../paths"));
+
+var _updater = require("./updater");
+
+var _appSettings = require("../appSettings");
+
+var autoStart = _interopRequireWildcard(require("../autoStart"));
+
+var _buildInfo = _interopRequireDefault(require("../utils/buildInfo"));
+
+var _errorHandler = require("../errorHandler");
+
+var firstRun = _interopRequireWildcard(require("../firstRun"));
+
+var splashScreen = _interopRequireWildcard(require("../splash/splashScreen"));
+
+var _Constants = require("../Constants");
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// settings
+const USE_PINNED_UPDATE_MANIFEST = 'USE_PINNED_UPDATE_MANIFEST';
+
+function update(startMinimized, doneCallback, showCallback) {
+ const settings = (0, _appSettings.getSettings)();
+
+ if ((0, _updater.tryInitUpdater)(_buildInfo.default, _Constants.NEW_UPDATE_ENDPOINT)) {
+ const updater = (0, _updater.getUpdater)();
+ const usePinnedUpdateManifest = settings.get(USE_PINNED_UPDATE_MANIFEST);
+ updater.on('host-updated', () => {
+ autoStart.update(() => {});
+ });
+ updater.on('unhandled-exception', _errorHandler.fatal);
+ updater.on(_updater.INCONSISTENT_INSTALLER_STATE_ERROR, _errorHandler.fatal);
+ updater.on('update-error', _errorHandler.handled);
+
+ if (usePinnedUpdateManifest) {
+ const manifestPath = _path.default.join(paths.getUserData(), 'pinned_update.json');
+
+ updater.setPinnedManifestSync(JSON.parse(_fs.default.readFileSync(manifestPath)));
+ }
+
+ firstRun.performFirstRunTasks(updater);
+ } else {
+ moduleUpdater.init(_Constants.UPDATE_ENDPOINT, settings, _buildInfo.default);
+ }
+
+ splashScreen.initSplash(startMinimized);
+ splashScreen.events.once(splashScreen.APP_SHOULD_LAUNCH, doneCallback);
+ splashScreen.events.once(splashScreen.APP_SHOULD_SHOW, showCallback);
+}
+
+function focusSplash() {
+ splashScreen.focusWindow();
+}
\ No newline at end of file
diff --git a/src/updater/hostUpdater.js b/src/updater/hostUpdater.js
new file mode 100644
index 0000000..833df98
--- /dev/null
+++ b/src/updater/hostUpdater.js
@@ -0,0 +1,199 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var _electron = require("electron");
+
+var _events = require("events");
+
+var _request = _interopRequireDefault(require("./request"));
+
+var squirrelUpdate = _interopRequireWildcard(require("./squirrelUpdate"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function versionParse(verString) {
+ return verString.split('.').map(i => parseInt(i));
+}
+
+function versionNewer(verA, verB) {
+ let i = 0;
+
+ while (true) {
+ const a = verA[i];
+ const b = verB[i];
+ i++;
+
+ if (a === undefined) {
+ return false;
+ } else {
+ if (b === undefined || a > b) {
+ return true;
+ }
+
+ if (a < b) {
+ return false;
+ }
+ }
+ }
+}
+
+class AutoUpdaterWin32 extends _events.EventEmitter {
+ constructor() {
+ super();
+ this.updateUrl = null;
+ this.updateVersion = null;
+ }
+
+ setFeedURL(updateUrl) {
+ this.updateUrl = updateUrl;
+ }
+
+ quitAndInstall() {
+ if (squirrelUpdate.updateExistsSync()) {
+ squirrelUpdate.restart(_electron.app, this.updateVersion || _electron.app.getVersion());
+ } else {
+ require('auto-updater').quitAndInstall();
+ }
+ }
+
+ downloadAndInstallUpdate(callback) {
+ squirrelUpdate.spawnUpdateInstall(this.updateUrl, progress => {
+ this.emit('update-progress', progress);
+ }).catch(err => callback(err)).then(() => callback());
+ }
+
+ checkForUpdates() {
+ if (this.updateUrl == null) {
+ throw new Error('Update URL is not set');
+ }
+
+ this.emit('checking-for-update');
+
+ if (!squirrelUpdate.updateExistsSync()) {
+ this.emit('update-not-available');
+ return;
+ }
+
+ squirrelUpdate.spawnUpdate(['--check', this.updateUrl], (error, stdout) => {
+ if (error != null) {
+ this.emit('error', error);
+ return;
+ }
+
+ try {
+ // Last line of the output is JSON details about the releases
+ const json = stdout.trim().split('\n').pop();
+ const releasesFound = JSON.parse(json).releasesToApply;
+
+ if (releasesFound == null || releasesFound.length == 0) {
+ this.emit('update-not-available');
+ return;
+ }
+
+ const update = releasesFound.pop();
+ this.emit('update-available');
+ this.downloadAndInstallUpdate(error => {
+ if (error != null) {
+ this.emit('error', error);
+ return;
+ }
+
+ this.updateVersion = update.version;
+ this.emit('update-downloaded', {}, update.release, update.version, new Date(), this.updateUrl, this.quitAndInstall.bind(this));
+ });
+ } catch (error) {
+ error.stdout = stdout;
+ this.emit('error', error);
+ }
+ });
+ }
+
+} // todo
+
+
+class AutoUpdaterLinux extends _events.EventEmitter {
+ constructor() {
+ super();
+ this.updateUrl = null;
+ }
+
+ setFeedURL(url) {
+ this.updateUrl = url;
+ }
+
+ quitAndInstall() {
+ // Just restart. The splash screen will hit the update manually state and
+ // prompt the user to download the new package.
+ _electron.app.relaunch();
+
+ _electron.app.quit();
+ }
+
+ async checkForUpdates() {
+ const currVersion = versionParse(_electron.app.getVersion());
+ this.emit('checking-for-update');
+
+ try {
+ const response = await _request.default.get(this.updateUrl);
+
+ if (response.statusCode === 204) {
+ // you are up to date
+ this.emit('update-not-available');
+ return;
+ }
+
+ let latestVerStr = '';
+ let latestVersion = [];
+
+ try {
+ const latestMetadata = JSON.parse(response.body);
+ latestVerStr = latestMetadata.name;
+ latestVersion = versionParse(latestVerStr);
+ } catch (_) {}
+
+ if (versionNewer(latestVersion, currVersion)) {
+ console.log('[Updates] You are out of date!'); // you need to update
+
+ this.emit('update-manually', latestVerStr);
+ } else {
+ console.log('[Updates] You are living in the future!');
+ this.emit('update-not-available');
+ }
+ } catch (err) {
+ console.error('[Updates] Error fetching ' + this.updateUrl + ': ' + err.message);
+ this.emit('error', err);
+ }
+ }
+
+}
+
+let autoUpdater; // TODO
+// events: checking-for-update, update-available, update-not-available, update-manually, update-downloaded, error
+// also, checkForUpdates, setFeedURL, quitAndInstall
+// also, see electron.autoUpdater, and its API
+
+switch (process.platform) {
+ case 'darwin':
+ autoUpdater = require('electron').autoUpdater;
+ break;
+
+ case 'win32':
+ autoUpdater = new AutoUpdaterWin32();
+ break;
+
+ case 'linux':
+ autoUpdater = new AutoUpdaterLinux();
+ break;
+}
+
+var _default = autoUpdater;
+exports.default = _default;
+module.exports = exports.default;
\ No newline at end of file
diff --git a/src/updater/moduleUpdater.js b/src/updater/moduleUpdater.js
new file mode 100644
index 0000000..0bc8236
--- /dev/null
+++ b/src/updater/moduleUpdater.js
@@ -0,0 +1,967 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.initPathsOnly = initPathsOnly;
+exports.init = init;
+exports.checkForUpdates = checkForUpdates;
+exports.setInBackground = setInBackground;
+exports.quitAndInstallUpdates = quitAndInstallUpdates;
+exports.isInstalled = isInstalled;
+exports.getInstalled = getInstalled;
+exports.install = install;
+exports.installPendingUpdates = installPendingUpdates;
+exports.supportsEventObjects = exports.events = exports.NO_PENDING_UPDATES = exports.INSTALLING_MODULE_PROGRESS = exports.INSTALLING_MODULE = exports.INSTALLING_MODULES_FINISHED = exports.DOWNLOADED_MODULE = exports.UPDATE_MANUALLY = exports.DOWNLOADING_MODULES_FINISHED = exports.DOWNLOADING_MODULE_PROGRESS = exports.DOWNLOADING_MODULE = exports.UPDATE_CHECK_FINISHED = exports.INSTALLED_MODULE = exports.CHECKING_FOR_UPDATES = void 0;
+
+var _fs = _interopRequireDefault(require("fs"));
+
+var _path = _interopRequireDefault(require("path"));
+
+var _module = _interopRequireDefault(require("module"));
+
+var _events = require("events");
+
+var _mkdirp = _interopRequireDefault(require("mkdirp"));
+
+var _process = require("process");
+
+var _yauzl = _interopRequireDefault(require("yauzl"));
+
+var _Backoff = _interopRequireDefault(require("../utils/Backoff"));
+
+var paths = _interopRequireWildcard(require("../paths"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// Manages additional module installation and management.
+// We add the module folder path to require() lookup paths here.
+// undocumented node API
+const originalFs = require('original-fs'); // events
+
+
+const CHECKING_FOR_UPDATES = 'checking-for-updates';
+exports.CHECKING_FOR_UPDATES = CHECKING_FOR_UPDATES;
+const INSTALLED_MODULE = 'installed-module';
+exports.INSTALLED_MODULE = INSTALLED_MODULE;
+const UPDATE_CHECK_FINISHED = 'update-check-finished';
+exports.UPDATE_CHECK_FINISHED = UPDATE_CHECK_FINISHED;
+const DOWNLOADING_MODULE = 'downloading-module';
+exports.DOWNLOADING_MODULE = DOWNLOADING_MODULE;
+const DOWNLOADING_MODULE_PROGRESS = 'downloading-module-progress';
+exports.DOWNLOADING_MODULE_PROGRESS = DOWNLOADING_MODULE_PROGRESS;
+const DOWNLOADING_MODULES_FINISHED = 'downloading-modules-finished';
+exports.DOWNLOADING_MODULES_FINISHED = DOWNLOADING_MODULES_FINISHED;
+const UPDATE_MANUALLY = 'update-manually';
+exports.UPDATE_MANUALLY = UPDATE_MANUALLY;
+const DOWNLOADED_MODULE = 'downloaded-module';
+exports.DOWNLOADED_MODULE = DOWNLOADED_MODULE;
+const INSTALLING_MODULES_FINISHED = 'installing-modules-finished';
+exports.INSTALLING_MODULES_FINISHED = INSTALLING_MODULES_FINISHED;
+const INSTALLING_MODULE = 'installing-module';
+exports.INSTALLING_MODULE = INSTALLING_MODULE;
+const INSTALLING_MODULE_PROGRESS = 'installing-module-progress';
+exports.INSTALLING_MODULE_PROGRESS = INSTALLING_MODULE_PROGRESS;
+const NO_PENDING_UPDATES = 'no-pending-updates'; // settings
+
+exports.NO_PENDING_UPDATES = NO_PENDING_UPDATES;
+const ALWAYS_ALLOW_UPDATES = 'ALWAYS_ALLOW_UPDATES';
+const SKIP_HOST_UPDATE = 'SKIP_HOST_UPDATE';
+const SKIP_MODULE_UPDATE = 'SKIP_MODULE_UPDATE';
+const ALWAYS_BOOTSTRAP_MODULES = 'ALWAYS_BOOTSTRAP_MODULES';
+const USE_LOCAL_MODULE_VERSIONS = 'USE_LOCAL_MODULE_VERSIONS';
+
+class Events extends _events.EventEmitter {
+ constructor() {
+ super();
+ this.history = [];
+ }
+
+ append(evt) {
+ evt.now = String(_process.hrtime.bigint());
+
+ if (this._eventIsInteresting(evt)) {
+ this.history.push(evt);
+ }
+
+ process.nextTick(() => this.emit(evt.type, evt));
+ }
+
+ _eventIsInteresting(evt) {
+ return evt.type !== DOWNLOADING_MODULE_PROGRESS && evt.type !== INSTALLING_MODULE_PROGRESS;
+ }
+
+}
+
+class LogStream {
+ constructor(logPath) {
+ try {
+ this.logStream = _fs.default.createWriteStream(logPath, {
+ flags: 'a'
+ });
+ } catch (e) {
+ console.error(`Failed to create ${logPath}: ${String(e)}`);
+ }
+ }
+
+ log(message) {
+ message = `[Modules] ${message}`;
+ console.log(message);
+
+ if (this.logStream) {
+ this.logStream.write(message);
+ this.logStream.write('\r\n');
+ }
+ }
+
+ end() {
+ if (this.logStream) {
+ this.logStream.end();
+ this.logStream = null;
+ }
+ }
+
+}
+
+const request = require('./request');
+
+const REQUEST_TIMEOUT = 15000;
+const backoff = new _Backoff.default(1000, 20000);
+const events = new Events();
+exports.events = events;
+const supportsEventObjects = true;
+exports.supportsEventObjects = supportsEventObjects;
+let logger;
+let locallyInstalledModules;
+let moduleInstallPath;
+let installedModulesFilePath;
+let moduleDownloadPath;
+let bootstrapping;
+let hostUpdater;
+let hostUpdateAvailable;
+let skipHostUpdate;
+let skipModuleUpdate;
+let checkingForUpdates;
+let remoteBaseURL;
+let remoteQuery;
+let settings;
+let remoteModuleVersions;
+let installedModules;
+let download;
+let unzip;
+let newInstallInProgress;
+let localModuleVersionsFilePath;
+let updatable;
+let bootstrapManifestFilePath;
+let runningInBackground = false;
+
+function initPathsOnly(_buildInfo) {
+ if (locallyInstalledModules || moduleInstallPath) {
+ return;
+ } // If we have `localModulesRoot` in our buildInfo file, we do not fetch modules
+ // from remote, and rely on our locally bundled ones.
+ // Typically used for development mode, or private builds.
+
+
+ locallyInstalledModules = _buildInfo.localModulesRoot != null;
+
+ if (locallyInstalledModules) {
+ if (_module.default.globalPaths.indexOf(_buildInfo.localModulesRoot) === -1) {
+ _module.default.globalPaths.push(_buildInfo.localModulesRoot);
+ }
+ } else {
+ moduleInstallPath = _path.default.join(paths.getUserDataVersioned(), 'modules');
+
+ if (_module.default.globalPaths.indexOf(moduleInstallPath) === -1) {
+ _module.default.globalPaths.push(moduleInstallPath);
+ }
+ }
+}
+
+function init(_endpoint, _settings, _buildInfo) {
+ const endpoint = _endpoint;
+ settings = _settings;
+ const buildInfo = _buildInfo;
+ updatable = buildInfo.version != '0.0.0' && !buildInfo.debug || settings.get(ALWAYS_ALLOW_UPDATES);
+ initPathsOnly(buildInfo);
+ logger = new LogStream(_path.default.join(paths.getUserData(), 'modules.log'));
+ bootstrapping = false;
+ hostUpdateAvailable = false;
+ checkingForUpdates = false;
+ skipHostUpdate = settings.get(SKIP_HOST_UPDATE) || !updatable;
+ skipModuleUpdate = settings.get(SKIP_MODULE_UPDATE) || locallyInstalledModules || !updatable;
+ localModuleVersionsFilePath = _path.default.join(paths.getUserData(), 'local_module_versions.json');
+ bootstrapManifestFilePath = _path.default.join(paths.getResources(), 'bootstrap', 'manifest.json');
+ installedModules = {};
+ remoteModuleVersions = {};
+ newInstallInProgress = {};
+ download = {
+ // currently downloading
+ active: false,
+ // {name, version}
+ queue: [],
+ // current queue index being downloaded
+ next: 0,
+ // download failure count
+ failures: 0
+ };
+ unzip = {
+ // currently unzipping
+ active: false,
+ // {name, version, zipfile}
+ queue: [],
+ // current queue index being unzipped
+ next: 0,
+ // unzip failure count
+ failures: 0
+ };
+ logger.log(`Modules initializing`);
+ logger.log(`Distribution: ${locallyInstalledModules ? 'local' : 'remote'}`);
+ logger.log(`Host updates: ${skipHostUpdate ? 'disabled' : 'enabled'}`);
+ logger.log(`Module updates: ${skipModuleUpdate ? 'disabled' : 'enabled'}`);
+
+ if (!locallyInstalledModules) {
+ installedModulesFilePath = _path.default.join(moduleInstallPath, 'installed.json');
+ moduleDownloadPath = _path.default.join(moduleInstallPath, 'pending');
+
+ _mkdirp.default.sync(moduleDownloadPath);
+
+ logger.log(`Module install path: ${moduleInstallPath}`);
+ logger.log(`Module installed file path: ${installedModulesFilePath}`);
+ logger.log(`Module download path: ${moduleDownloadPath}`);
+ let failedLoadingInstalledModules = false;
+
+ try {
+ installedModules = JSON.parse(_fs.default.readFileSync(installedModulesFilePath));
+ } catch (err) {
+ failedLoadingInstalledModules = true;
+ }
+
+ cleanDownloadedModules(installedModules);
+ bootstrapping = failedLoadingInstalledModules || settings.get(ALWAYS_BOOTSTRAP_MODULES);
+ }
+
+ hostUpdater = require('./hostUpdater'); // TODO: hostUpdater constants
+
+ hostUpdater.on('checking-for-update', () => events.append({
+ type: CHECKING_FOR_UPDATES
+ }));
+ hostUpdater.on('update-available', () => hostOnUpdateAvailable());
+ hostUpdater.on('update-progress', progress => hostOnUpdateProgress(progress));
+ hostUpdater.on('update-not-available', () => hostOnUpdateNotAvailable());
+ hostUpdater.on('update-manually', newVersion => hostOnUpdateManually(newVersion));
+ hostUpdater.on('update-downloaded', () => hostOnUpdateDownloaded());
+ hostUpdater.on('error', err => hostOnError(err));
+ const setFeedURL = hostUpdater.setFeedURL.bind(hostUpdater);
+ remoteBaseURL = `${endpoint}/modules/${buildInfo.releaseChannel}`; // eslint-disable-next-line camelcase
+
+ remoteQuery = {
+ host_version: buildInfo.version
+ };
+
+ switch (process.platform) {
+ case 'darwin':
+ setFeedURL(`${endpoint}/updates/${buildInfo.releaseChannel}?platform=osx&version=${buildInfo.version}`);
+ remoteQuery.platform = 'osx';
+ break;
+
+ case 'win32':
+ // Squirrel for Windows can't handle query params
+ // https://github.com/Squirrel/Squirrel.Windows/issues/132
+ setFeedURL(`${endpoint}/updates/${buildInfo.releaseChannel}`);
+ remoteQuery.platform = 'win';
+ break;
+
+ case 'linux':
+ setFeedURL(`${endpoint}/updates/${buildInfo.releaseChannel}?platform=linux&version=${buildInfo.version}`);
+ remoteQuery.platform = 'linux';
+ break;
+ }
+}
+
+function cleanDownloadedModules(installedModules) {
+ try {
+ const entries = _fs.default.readdirSync(moduleDownloadPath) || [];
+ entries.forEach(entry => {
+ const entryPath = _path.default.join(moduleDownloadPath, entry);
+
+ let isStale = true;
+
+ for (const moduleName of Object.keys(installedModules)) {
+ if (entryPath === installedModules[moduleName].updateZipfile) {
+ isStale = false;
+ break;
+ }
+ }
+
+ if (isStale) {
+ _fs.default.unlinkSync(_path.default.join(moduleDownloadPath, entry));
+ }
+ });
+ } catch (err) {
+ logger.log('Could not clean downloaded modules');
+ logger.log(err.stack);
+ }
+}
+
+function hostOnUpdateAvailable() {
+ logger.log(`Host update is available.`);
+ hostUpdateAvailable = true;
+ events.append({
+ type: UPDATE_CHECK_FINISHED,
+ succeeded: true,
+ updateCount: 1,
+ manualRequired: false
+ });
+ events.append({
+ type: DOWNLOADING_MODULE,
+ name: 'host',
+ current: 1,
+ total: 1,
+ foreground: !runningInBackground
+ });
+}
+
+function hostOnUpdateProgress(progress) {
+ logger.log(`Host update progress: ${progress}%`);
+ events.append({
+ type: DOWNLOADING_MODULE_PROGRESS,
+ name: 'host',
+ progress: progress
+ });
+}
+
+function hostOnUpdateNotAvailable() {
+ logger.log(`Host is up to date.`);
+
+ if (!skipModuleUpdate) {
+ checkForModuleUpdates();
+ } else {
+ events.append({
+ type: UPDATE_CHECK_FINISHED,
+ succeeded: true,
+ updateCount: 0,
+ manualRequired: false
+ });
+ }
+}
+
+function hostOnUpdateManually(newVersion) {
+ logger.log(`Host update is available. Manual update required!`);
+ hostUpdateAvailable = true;
+ checkingForUpdates = false;
+ events.append({
+ type: UPDATE_MANUALLY,
+ newVersion: newVersion
+ });
+ events.append({
+ type: UPDATE_CHECK_FINISHED,
+ succeeded: true,
+ updateCount: 1,
+ manualRequired: true
+ });
+}
+
+function hostOnUpdateDownloaded() {
+ logger.log(`Host update downloaded.`);
+ checkingForUpdates = false;
+ events.append({
+ type: DOWNLOADED_MODULE,
+ name: 'host',
+ current: 1,
+ total: 1,
+ succeeded: true
+ });
+ events.append({
+ type: DOWNLOADING_MODULES_FINISHED,
+ succeeded: 1,
+ failed: 0
+ });
+}
+
+function hostOnError(err) {
+ logger.log(`Host update failed: ${err}`); // [adill] osx unsigned builds will fire this code signing error inside setFeedURL and
+ // if we don't do anything about it hostUpdater.checkForUpdates() will never respond.
+
+ if (err && String(err).indexOf('Could not get code signature for running application') !== -1) {
+ console.warn('Skipping host updates due to code signing failure.');
+ skipHostUpdate = true;
+ }
+
+ checkingForUpdates = false;
+
+ if (!hostUpdateAvailable) {
+ events.append({
+ type: UPDATE_CHECK_FINISHED,
+ succeeded: false,
+ updateCount: 0,
+ manualRequired: false
+ });
+ } else {
+ events.append({
+ type: DOWNLOADED_MODULE,
+ name: 'host',
+ current: 1,
+ total: 1,
+ succeeded: false
+ });
+ events.append({
+ type: DOWNLOADING_MODULES_FINISHED,
+ succeeded: 0,
+ failed: 1
+ });
+ }
+}
+
+function checkForUpdates() {
+ if (checkingForUpdates) return;
+ checkingForUpdates = true;
+ hostUpdateAvailable = false;
+
+ if (skipHostUpdate) {
+ events.append({
+ type: CHECKING_FOR_UPDATES
+ });
+ hostOnUpdateNotAvailable();
+ } else {
+ logger.log('Checking for host updates.');
+ hostUpdater.checkForUpdates();
+ }
+} // Indicates that the initial update process is complete and that future updates
+// are background updates. This merely affects the content of the events sent to
+// the app so that analytics can correctly attribute module download/installs
+// depending on whether they were ui-blocking or not.
+
+
+function setInBackground() {
+ runningInBackground = true;
+}
+
+function getRemoteModuleName(name) {
+ if (process.platform === 'win32' && process.arch === 'x64') {
+ return `${name}.x64`;
+ }
+
+ return name;
+}
+
+async function checkForModuleUpdates() {
+ const query = { ...remoteQuery,
+ _: Math.floor(Date.now() / 1000 / 60 / 5)
+ };
+ const url = `${remoteBaseURL}/versions.json`;
+ logger.log(`Checking for module updates at ${url}`);
+ let response;
+
+ try {
+ response = await request.get({
+ url,
+ qs: query,
+ timeout: REQUEST_TIMEOUT
+ });
+ checkingForUpdates = false;
+ } catch (err) {
+ checkingForUpdates = false;
+ logger.log(`Failed fetching module versions: ${String(err)}`);
+ events.append({
+ type: UPDATE_CHECK_FINISHED,
+ succeeded: false,
+ updateCount: 0,
+ manualRequired: false
+ });
+ return;
+ }
+
+ remoteModuleVersions = JSON.parse(response.body);
+
+ if (settings.get(USE_LOCAL_MODULE_VERSIONS)) {
+ try {
+ remoteModuleVersions = JSON.parse(_fs.default.readFileSync(localModuleVersionsFilePath));
+ console.log('Using local module versions: ', remoteModuleVersions);
+ } catch (err) {
+ console.warn('Failed to parse local module versions: ', err);
+ }
+ }
+
+ const updatesToDownload = [];
+
+ for (const moduleName of Object.keys(installedModules)) {
+ const installedModule = installedModules[moduleName];
+ const installed = installedModule.installedVersion;
+
+ if (installed === null) {
+ continue;
+ }
+
+ const update = installedModule.updateVersion || 0;
+ const remote = remoteModuleVersions[getRemoteModuleName(moduleName)] || 0;
+
+ if (installed !== remote && update !== remote) {
+ logger.log(`Module update available: ${moduleName}@${remote} [installed: ${installed}]`);
+ updatesToDownload.push({
+ name: moduleName,
+ version: remote
+ });
+ }
+ }
+
+ events.append({
+ type: UPDATE_CHECK_FINISHED,
+ succeeded: true,
+ updateCount: updatesToDownload.length,
+ manualRequired: false
+ });
+
+ if (updatesToDownload.length === 0) {
+ logger.log(`No module updates available.`);
+ } else {
+ updatesToDownload.forEach(e => addModuleToDownloadQueue(e.name, e.version));
+ }
+}
+
+function addModuleToDownloadQueue(name, version, authToken) {
+ download.queue.push({
+ name,
+ version,
+ authToken
+ });
+ process.nextTick(() => processDownloadQueue());
+}
+
+async function processDownloadQueue() {
+ if (download.active) return;
+ if (download.queue.length === 0) return;
+ download.active = true;
+ const queuedModule = download.queue[download.next];
+ download.next += 1;
+ events.append({
+ type: DOWNLOADING_MODULE,
+ name: queuedModule.name,
+ current: download.next,
+ total: download.queue.length,
+ foreground: !runningInBackground
+ });
+ let progress = 0;
+ let receivedBytes = 0;
+ const url = `${remoteBaseURL}/${encodeURIComponent(getRemoteModuleName(queuedModule.name))}/${encodeURIComponent(queuedModule.version)}`;
+ logger.log(`Fetching ${queuedModule.name}@${queuedModule.version} from ${url}`);
+ const headers = {};
+
+ if (queuedModule.authToken) {
+ headers['Authorization'] = queuedModule.authToken;
+ }
+
+ const moduleZipPath = _path.default.join(moduleDownloadPath, `${queuedModule.name}-${queuedModule.version}.zip`);
+
+ const stream = _fs.default.createWriteStream(moduleZipPath);
+
+ stream.on('progress', ({
+ receivedBytes: newReceivedBytes,
+ totalBytes
+ }) => {
+ receivedBytes = newReceivedBytes;
+ const newProgress = Math.min(Math.floor(100 * (receivedBytes / totalBytes)), 100);
+
+ if (progress !== newProgress) {
+ progress = newProgress;
+ logger.log(`Streaming ${queuedModule.name}@${queuedModule.version} to ${moduleZipPath}: ${progress}%`);
+ events.append({
+ type: DOWNLOADING_MODULE_PROGRESS,
+ name: queuedModule.name,
+ progress: progress
+ });
+ }
+ });
+ logger.log(`Streaming ${queuedModule.name}@${queuedModule.version} to ${moduleZipPath}`);
+
+ try {
+ const response = await request.get({
+ url,
+ qs: remoteQuery,
+ headers,
+ timeout: REQUEST_TIMEOUT,
+ stream
+ });
+ finishModuleDownload(queuedModule.name, queuedModule.version, moduleZipPath, receivedBytes, response.statusCode === 200);
+ } catch (err) {
+ logger.log(`Failed fetching module ${queuedModule.name}@${queuedModule.version}: ${String(err)}`);
+ finishModuleDownload(queuedModule.name, queuedModule.version, null, receivedBytes, false);
+ }
+}
+
+function commitInstalledModules() {
+ const data = JSON.stringify(installedModules, null, 2);
+
+ _fs.default.writeFileSync(installedModulesFilePath, data);
+}
+
+function finishModuleDownload(name, version, zipfile, receivedBytes, succeeded) {
+ if (!installedModules[name]) {
+ installedModules[name] = {};
+ }
+
+ if (succeeded) {
+ installedModules[name].updateVersion = version;
+ installedModules[name].updateZipfile = zipfile;
+ commitInstalledModules();
+ } else {
+ download.failures += 1;
+ }
+
+ events.append({
+ type: DOWNLOADED_MODULE,
+ name: name,
+ current: download.next,
+ total: download.queue.length,
+ succeeded: succeeded,
+ receivedBytes: receivedBytes
+ });
+
+ if (download.next >= download.queue.length) {
+ const successes = download.queue.length - download.failures;
+ logger.log(`Finished module downloads. [success: ${successes}] [failure: ${download.failures}]`);
+ events.append({
+ type: DOWNLOADING_MODULES_FINISHED,
+ succeeded: successes,
+ failed: download.failures
+ });
+ download.queue = [];
+ download.next = 0;
+ download.failures = 0;
+ download.active = false;
+ } else {
+ const continueDownloads = () => {
+ download.active = false;
+ processDownloadQueue();
+ };
+
+ if (succeeded) {
+ backoff.succeed();
+ process.nextTick(continueDownloads);
+ } else {
+ logger.log(`Waiting ${Math.floor(backoff.current)}ms before next download.`);
+ backoff.fail(continueDownloads);
+ }
+ }
+
+ if (newInstallInProgress[name]) {
+ addModuleToUnzipQueue(name, version, zipfile);
+ }
+}
+
+function addModuleToUnzipQueue(name, version, zipfile) {
+ unzip.queue.push({
+ name,
+ version,
+ zipfile
+ });
+ process.nextTick(() => processUnzipQueue());
+}
+
+function processUnzipQueue() {
+ if (unzip.active) return;
+ if (unzip.queue.length === 0) return;
+ unzip.active = true;
+ const queuedModule = unzip.queue[unzip.next];
+ const installedModule = installedModules[queuedModule.name];
+ const installedVersion = installedModule != null ? installedModule.installedVersion : null;
+ unzip.next += 1;
+ events.append({
+ type: INSTALLING_MODULE,
+ name: queuedModule.name,
+ current: unzip.next,
+ total: unzip.queue.length,
+ foreground: !runningInBackground,
+ oldVersion: installedVersion,
+ newVersion: queuedModule.version
+ });
+ let hasErrored = false;
+
+ const onError = (error, zipfile) => {
+ if (hasErrored) return;
+ hasErrored = true;
+ logger.log(`Failed installing ${queuedModule.name}@${queuedModule.version}: ${String(error)}`);
+ succeeded = false;
+
+ if (zipfile) {
+ zipfile.close();
+ }
+
+ finishModuleUnzip(queuedModule, succeeded);
+ };
+
+ let succeeded = true;
+
+ const extractRoot = _path.default.join(moduleInstallPath, queuedModule.name);
+
+ logger.log(`Installing ${queuedModule.name}@${queuedModule.version} from ${queuedModule.zipfile}`);
+
+ const processZipfile = (err, zipfile) => {
+ if (err) {
+ onError(err, null);
+ return;
+ }
+
+ const totalEntries = zipfile.entryCount;
+ let processedEntries = 0;
+ zipfile.on('entry', entry => {
+ processedEntries += 1;
+ const percent = Math.min(Math.floor(processedEntries / totalEntries * 100), 100);
+ events.append({
+ type: INSTALLING_MODULE_PROGRESS,
+ name: queuedModule.name,
+ progress: percent
+ }); // skip directories
+
+ if (/\/$/.test(entry.fileName)) {
+ zipfile.readEntry();
+ return;
+ }
+
+ zipfile.openReadStream(entry, (err, stream) => {
+ if (err) {
+ onError(err, zipfile);
+ return;
+ }
+
+ stream.on('error', e => onError(e, zipfile));
+ (0, _mkdirp.default)(_path.default.join(extractRoot, _path.default.dirname(entry.fileName)), err => {
+ if (err) {
+ onError(err, zipfile);
+ return;
+ } // [adill] createWriteStream via original-fs is broken in Electron 4.0.0-beta.6 with .asar files
+ // so we unzip to a temporary filename and rename it afterwards
+
+
+ const tempFileName = _path.default.join(extractRoot, entry.fileName + '.tmp');
+
+ const finalFileName = _path.default.join(extractRoot, entry.fileName);
+
+ const writeStream = originalFs.createWriteStream(tempFileName);
+ writeStream.on('error', e => {
+ stream.destroy();
+
+ try {
+ originalFs.unlinkSync(tempFileName);
+ } catch (err) {}
+
+ onError(e, zipfile);
+ });
+ writeStream.on('finish', () => {
+ try {
+ originalFs.unlinkSync(finalFileName);
+ } catch (err) {}
+
+ try {
+ originalFs.renameSync(tempFileName, finalFileName);
+ } catch (err) {
+ onError(err, zipfile);
+ return;
+ }
+
+ zipfile.readEntry();
+ });
+ stream.pipe(writeStream);
+ });
+ });
+ });
+ zipfile.on('error', err => {
+ onError(err, zipfile);
+ });
+ zipfile.on('end', () => {
+ if (!succeeded) return;
+ installedModules[queuedModule.name].installedVersion = queuedModule.version;
+ finishModuleUnzip(queuedModule, succeeded);
+ });
+ zipfile.readEntry();
+ };
+
+ try {
+ _yauzl.default.open(queuedModule.zipfile, {
+ lazyEntries: true,
+ autoClose: true
+ }, processZipfile);
+ } catch (err) {
+ onError(err, null);
+ }
+}
+
+function finishModuleUnzip(unzippedModule, succeeded) {
+ delete newInstallInProgress[unzippedModule.name];
+ delete installedModules[unzippedModule.name].updateZipfile;
+ delete installedModules[unzippedModule.name].updateVersion;
+ commitInstalledModules();
+
+ if (!succeeded) {
+ unzip.failures += 1;
+ }
+
+ events.append({
+ type: INSTALLED_MODULE,
+ name: unzippedModule.name,
+ current: unzip.next,
+ total: unzip.queue.length,
+ succeeded: succeeded
+ });
+
+ if (unzip.next >= unzip.queue.length) {
+ const successes = unzip.queue.length - unzip.failures;
+ bootstrapping = false;
+ logger.log(`Finished module installations. [success: ${successes}] [failure: ${unzip.failures}]`);
+ unzip.queue = [];
+ unzip.next = 0;
+ unzip.failures = 0;
+ unzip.active = false;
+ events.append({
+ type: INSTALLING_MODULES_FINISHED,
+ succeeded: successes,
+ failed: unzip.failures
+ });
+ return;
+ }
+
+ process.nextTick(() => {
+ unzip.active = false;
+ processUnzipQueue();
+ });
+}
+
+function quitAndInstallUpdates() {
+ logger.log(`Relaunching to install ${hostUpdateAvailable ? 'host' : 'module'} updates...`);
+
+ if (hostUpdateAvailable) {
+ hostUpdater.quitAndInstall();
+ } else {
+ relaunch();
+ }
+}
+
+function relaunch() {
+ logger.end();
+
+ const {
+ app
+ } = require('electron');
+
+ app.relaunch();
+ app.quit();
+}
+
+function isInstalled(name, version) {
+ const metadata = installedModules[name];
+ if (locallyInstalledModules) return true;
+
+ if (metadata && metadata.installedVersion > 0) {
+ if (!version) return true;
+ if (metadata.installedVersion === version) return true;
+ }
+
+ return false;
+}
+
+function getInstalled() {
+ return { ...installedModules
+ };
+}
+
+function install(name, defer, options) {
+ let {
+ version,
+ authToken
+ } = options || {};
+
+ if (isInstalled(name, version)) {
+ if (!defer) {
+ events.append({
+ type: INSTALLED_MODULE,
+ name: name,
+ current: 1,
+ total: 1,
+ succeeded: true
+ });
+ }
+
+ return;
+ }
+
+ if (newInstallInProgress[name]) return;
+
+ if (!updatable) {
+ logger.log(`Not updatable; ignoring request to install ${name}...`);
+ return;
+ }
+
+ if (defer) {
+ if (version) {
+ throw new Error(`Cannot defer install for a specific version module (${name}, ${version})`);
+ }
+
+ logger.log(`Deferred install for ${name}...`);
+ installedModules[name] = {
+ installedVersion: 0
+ };
+ commitInstalledModules();
+ } else {
+ logger.log(`Starting to install ${name}...`);
+
+ if (!version) {
+ version = remoteModuleVersions[name] || 0;
+ }
+
+ newInstallInProgress[name] = version;
+ addModuleToDownloadQueue(name, version, authToken);
+ }
+}
+
+function installPendingUpdates() {
+ const updatesToInstall = [];
+
+ if (bootstrapping) {
+ let modules = {};
+
+ try {
+ modules = JSON.parse(_fs.default.readFileSync(bootstrapManifestFilePath));
+ } catch (err) {}
+
+ for (const moduleName of Object.keys(modules)) {
+ installedModules[moduleName] = {
+ installedVersion: 0
+ };
+
+ const zipfile = _path.default.join(paths.getResources(), 'bootstrap', `${moduleName}.zip`);
+
+ updatesToInstall.push({
+ moduleName,
+ update: modules[moduleName],
+ zipfile
+ });
+ }
+ }
+
+ for (const moduleName of Object.keys(installedModules)) {
+ const update = installedModules[moduleName].updateVersion || 0;
+ const zipfile = installedModules[moduleName].updateZipfile;
+
+ if (update > 0 && zipfile != null) {
+ updatesToInstall.push({
+ moduleName,
+ update,
+ zipfile
+ });
+ }
+ }
+
+ if (updatesToInstall.length > 0) {
+ logger.log(`${bootstrapping ? 'Bootstrapping' : 'Installing updates'}...`);
+ updatesToInstall.forEach(e => addModuleToUnzipQueue(e.moduleName, e.update, e.zipfile));
+ } else {
+ logger.log('No updates to install');
+ events.append({
+ type: NO_PENDING_UPDATES
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/updater/request.js b/src/updater/request.js
new file mode 100644
index 0000000..c5a7c71
--- /dev/null
+++ b/src/updater/request.js
@@ -0,0 +1,186 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.default = void 0;
+
+var _electron = require("electron");
+
+var _querystring = _interopRequireDefault(require("querystring"));
+
+var _request = _interopRequireDefault(require("request"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+const DEFAULT_REQUEST_TIMEOUT = 30000;
+
+function makeHTTPResponse({
+ method,
+ url,
+ headers,
+ statusCode,
+ statusMessage
+}, body) {
+ return {
+ method,
+ url,
+ headers,
+ statusCode,
+ statusMessage,
+ body
+ };
+}
+
+function makeHTTPStatusError(response) {
+ const err = new Error(`HTTP Error: Status Code ${response.statusCode}`);
+ err.response = response;
+ return err;
+}
+
+function handleHTTPResponse(resolve, reject, response, stream) {
+ const totalBytes = parseInt(response.headers['content-length'] || 1, 10);
+ let receivedBytes = 0;
+ const chunks = []; // don't stream response if it's a failure
+
+ if (response.statusCode >= 300) {
+ stream = null;
+ }
+
+ response.on('data', chunk => {
+ if (stream != null) {
+ receivedBytes += chunk.length;
+ stream.write(chunk);
+ stream.emit('progress', {
+ totalBytes,
+ receivedBytes
+ });
+ return;
+ }
+
+ chunks.push(chunk);
+ });
+ response.on('end', () => {
+ if (stream != null) {
+ stream.on('finish', () => resolve(makeHTTPResponse(response, null)));
+ stream.end();
+ return;
+ }
+
+ const res = makeHTTPResponse(response, Buffer.concat(chunks));
+
+ if (res.statusCode >= 300) {
+ reject(makeHTTPStatusError(res));
+ return;
+ }
+
+ resolve(res);
+ });
+}
+
+function nodeRequest({
+ method,
+ url,
+ headers,
+ qs,
+ timeout,
+ body,
+ stream
+}) {
+ return new Promise((resolve, reject) => {
+ const req = (0, _request.default)({
+ method,
+ url,
+ qs,
+ headers,
+ followAllRedirects: true,
+ encoding: null,
+ timeout: timeout != null ? timeout : DEFAULT_REQUEST_TIMEOUT,
+ body
+ });
+ req.on('response', response => handleHTTPResponse(resolve, reject, response, stream));
+ req.on('error', err => reject(err));
+ });
+}
+
+async function electronRequest({
+ method,
+ url,
+ headers,
+ qs,
+ timeout,
+ body,
+ stream
+}) {
+ await _electron.app.whenReady();
+
+ const {
+ net,
+ session
+ } = require('electron');
+
+ const req = net.request({
+ method,
+ url: `${url}${qs != null ? `?${_querystring.default.stringify(qs)}` : ''}`,
+ redirect: 'follow',
+ session: session.defaultSession
+ });
+
+ if (headers != null) {
+ for (const headerKey of Object.keys(headers)) {
+ req.setHeader(headerKey, headers[headerKey]);
+ }
+ }
+
+ if (body != null) {
+ req.write(body, 'utf-8');
+ }
+
+ return new Promise((resolve, reject) => {
+ const reqTimeout = setTimeout(() => {
+ req.abort();
+ reject(new Error(`network timeout: ${url}`));
+ }, timeout != null ? timeout : DEFAULT_REQUEST_TIMEOUT);
+ req.on('login', (authInfo, callback) => callback());
+ req.on('response', response => {
+ clearTimeout(reqTimeout);
+ handleHTTPResponse(resolve, reject, response, stream);
+ });
+ req.on('error', err => {
+ clearTimeout(reqTimeout);
+ reject(err);
+ });
+ req.end();
+ });
+}
+
+async function requestWithMethod(method, options) {
+ if (typeof options === 'string') {
+ options = {
+ url: options
+ };
+ }
+
+ options = { ...options,
+ method
+ };
+
+ try {
+ return await electronRequest(options);
+ } catch (err) {
+ console.log(`Error downloading with electron net: ${err.message}`);
+ console.log('Falling back to node net library..');
+ }
+
+ return nodeRequest(options);
+} // only supports get for now, since retrying is non-idempotent and
+// we'd want to grovel the errors to make sure it's safe to retry
+
+
+for (const method of ['get']) {
+ requestWithMethod[method] = requestWithMethod.bind(null, method.toUpperCase());
+}
+
+var _default = requestWithMethod;
+exports.default = _default;
+module.exports = exports.default;
\ No newline at end of file
diff --git a/src/updater/squirrelUpdate.js b/src/updater/squirrelUpdate.js
new file mode 100644
index 0000000..7460c87
--- /dev/null
+++ b/src/updater/squirrelUpdate.js
@@ -0,0 +1,218 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.spawnUpdateInstall = spawnUpdateInstall;
+exports.spawnUpdate = spawnUpdate;
+exports.installProtocol = installProtocol;
+exports.handleStartupEvent = handleStartupEvent;
+exports.updateExistsSync = updateExistsSync;
+exports.restart = restart;
+
+var _child_process = _interopRequireDefault(require("child_process"));
+
+var _fs = _interopRequireDefault(require("fs"));
+
+var _path = _interopRequireDefault(require("path"));
+
+var autoStart = _interopRequireWildcard(require("../autoStart"));
+
+var windowsUtils = _interopRequireWildcard(require("./windowsUtils"));
+
+function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
+
+function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// citron note: this assumes the execPath is in the format Discord/someVersion/Discord.exe
+const appFolder = _path.default.resolve(process.execPath, '..');
+
+const rootFolder = _path.default.resolve(appFolder, '..');
+
+const exeName = _path.default.basename(process.execPath);
+
+const updateExe = _path.default.join(rootFolder, 'Update.exe'); // Specialized spawn function specifically used for spawning the updater in
+// update mode. Calls back with progress percentages.
+// Returns Promise.
+
+
+function spawnUpdateInstall(updateUrl, progressCallback) {
+ return new Promise((resolve, reject) => {
+ const proc = _child_process.default.spawn(updateExe, ['--update', updateUrl]);
+
+ proc.on('error', reject);
+ proc.on('exit', code => {
+ if (code !== 0) {
+ return reject(new Error(`Update failed with exit code ${code}`));
+ }
+
+ return resolve();
+ });
+ let lastProgress = -1;
+
+ function parseProgress() {
+ const lines = stdout.split(/\r?\n/);
+ if (lines.length === 1) return; // return the last (possibly incomplete) line to stdout for parsing again
+
+ stdout = lines.pop();
+ let currentProgress;
+
+ for (const line of lines) {
+ if (!/^\d\d?$/.test(line)) continue;
+ const progress = Number(line); // make sure that this number is steadily increasing
+
+ if (lastProgress > progress) continue;
+ currentProgress = progress;
+ }
+
+ if (currentProgress == null) return;
+ lastProgress = currentProgress;
+ progressCallback(Math.min(currentProgress, 100));
+ }
+
+ let stdout = '';
+ proc.stdout.on('data', chunk => {
+ stdout += String(chunk);
+ parseProgress();
+ });
+ });
+} // Spawn the Update.exe with the given arguments and invoke the callback when
+// the command completes.
+
+
+function spawnUpdate(args, callback) {
+ windowsUtils.spawn(updateExe, args, callback);
+} // Create a desktop and start menu shortcut by using the command line API
+// provided by Squirrel's Update.exe
+
+
+function createShortcuts(callback, updateOnly) {
+ // move icon out to a more stable location, to keep shortcuts from breaking as much
+ const icoSrc = _path.default.join(appFolder, 'app.ico');
+
+ const icoDest = _path.default.join(rootFolder, 'app.ico');
+
+ let icoForTarget = icoDest;
+
+ try {
+ const ico = _fs.default.readFileSync(icoSrc);
+
+ _fs.default.writeFileSync(icoDest, ico);
+ } catch (e) {
+ // if we can't write there for some reason, just use the source.
+ icoForTarget = icoSrc;
+ }
+
+ const createShortcutArgs = ['--createShortcut', exeName, '--setupIcon', icoForTarget];
+
+ if (updateOnly) {
+ createShortcutArgs.push('--updateOnly');
+ }
+
+ spawnUpdate(createShortcutArgs, callback);
+} // Add a protocol registration for this application.
+
+
+function installProtocol(protocol, callback) {
+ const queue = [['HKCU\\Software\\Classes\\' + protocol, '/ve', '/d', `URL:${protocol} Protocol`], ['HKCU\\Software\\Classes\\' + protocol, '/v', 'URL Protocol'], ['HKCU\\Software\\Classes\\' + protocol + '\\DefaultIcon', '/ve', '/d', '"' + process.execPath + '",-1'], ['HKCU\\Software\\Classes\\' + protocol + '\\shell\\open\\command', '/ve', '/d', `"${process.execPath}" --url -- "%1"`]];
+ windowsUtils.addToRegistry(queue, callback);
+}
+
+function terminate(app) {
+ app.quit();
+ process.exit(0);
+} // Remove the desktop and start menu shortcuts by using the command line API
+// provided by Squirrel's Update.exe
+
+
+function removeShortcuts(callback) {
+ spawnUpdate(['--removeShortcut', exeName], callback);
+} // Update the desktop and start menu shortcuts by using the command line API
+// provided by Squirrel's Update.exe
+
+
+function updateShortcuts(callback) {
+ createShortcuts(callback, true);
+} // Purge the protocol for this applicationstart.
+
+
+function uninstallProtocol(protocol, callback) {
+ windowsUtils.spawnReg(['delete', 'HKCU\\Software\\Classes\\' + protocol, '/f'], callback);
+}
+
+function maybeInstallNewUpdaterSeedDb() {
+ const installerDbSrc = _path.default.join(appFolder, 'installer.db');
+
+ const installerDbDest = _path.default.join(rootFolder, 'installer.db');
+
+ if (_fs.default.existsSync(installerDbSrc)) {
+ _fs.default.renameSync(installerDbSrc, installerDbDest);
+ }
+} // Handle squirrel events denoted by --squirrel-* command line arguments.
+// returns `true` if regular startup should be prevented
+
+
+function handleStartupEvent(protocol, app, squirrelCommand) {
+ switch (squirrelCommand) {
+ case '--squirrel-install':
+ createShortcuts(() => {
+ autoStart.install(() => {
+ installProtocol(protocol, () => {
+ // Squirrel doesn't have a way to include app-level files.
+ // We get around this for new updater hosts, which rely on
+ // a seeded manifest, by bubbling the db up from the versioned-app
+ // directory if it exists.
+ maybeInstallNewUpdaterSeedDb();
+ terminate(app);
+ });
+ });
+ }, false);
+ return true;
+
+ case '--squirrel-updated':
+ updateShortcuts(() => {
+ autoStart.update(() => {
+ installProtocol(protocol, () => {
+ terminate(app);
+ });
+ });
+ });
+ return true;
+
+ case '--squirrel-uninstall':
+ removeShortcuts(() => {
+ autoStart.uninstall(() => {
+ uninstallProtocol(protocol, () => {
+ terminate(app);
+ });
+ });
+ });
+ return true;
+
+ case '--squirrel-obsolete':
+ terminate(app);
+ return true;
+
+ default:
+ return false;
+ }
+} // Are we using Squirrel for updates?
+
+
+function updateExistsSync() {
+ return _fs.default.existsSync(updateExe);
+} // Restart app as the new version
+
+
+function restart(app, newVersion) {
+ app.once('will-quit', () => {
+ const execPath = _path.default.resolve(rootFolder, `app-${newVersion}/${exeName}`);
+
+ _child_process.default.spawn(execPath, [], {
+ detached: true
+ });
+ });
+ app.quit();
+}
\ No newline at end of file
diff --git a/src/updater/updater.js b/src/updater/updater.js
new file mode 100644
index 0000000..1f45bdc
--- /dev/null
+++ b/src/updater/updater.js
@@ -0,0 +1,460 @@
+"use strict";
+
+// Too much Rust integration stuff in here.
+
+/* eslint camelcase: 0 */
+const childProcess = require('child_process');
+
+const {
+ app
+} = require('electron');
+
+const {
+ EventEmitter
+} = require('events');
+
+const NodeModule = require('module');
+
+const path = require('path');
+
+const {
+ hrtime
+} = require('process');
+
+let instance;
+const TASK_STATE_COMPLETE = 'Complete';
+const TASK_STATE_FAILED = 'Failed';
+const TASK_STATE_WAITING = 'Waiting';
+const TASK_STATE_WORKING = 'Working';
+const INCONSISTENT_INSTALLER_STATE_ERROR = 'InconsistentInstallerState'; // The dumb linters are mad at each other.
+// eslint-disable-next-line quotes
+
+const INVALID_UPDATER_ERROR = "Can't send request to updater because the native updater isn't loaded.";
+
+class Updater extends EventEmitter {
+ constructor(options) {
+ super();
+ let nativeUpdaterModule = options.nativeUpdaterModule;
+
+ if (nativeUpdaterModule == null) {
+ try {
+ // eslint-disable-next-line import/no-unresolved
+ nativeUpdaterModule = require('../../../updater');
+ } catch (e) {
+ if (e.code === 'MODULE_NOT_FOUND') {
+ return;
+ }
+
+ throw e;
+ }
+ }
+
+ this.committedHostVersion = null;
+ this.committedModules = new Set();
+ this.rootPath = options.root_path;
+ this.nextRequestId = 0;
+ this.requests = new Map();
+ this.updateEventHistory = [];
+ this.isRunningInBackground = false;
+ this.currentlyDownloading = {};
+ this.currentlyInstalling = {};
+ this.hasEmittedUnhandledException = false;
+ this.nativeUpdater = new nativeUpdaterModule.Updater({
+ response_handler: this._handleResponse.bind(this),
+ ...options
+ });
+ }
+
+ get valid() {
+ return this.nativeUpdater != null;
+ }
+
+ _sendRequest(detail, progressCallback = null) {
+ if (!this.valid) {
+ throw new Error(INVALID_UPDATER_ERROR);
+ }
+
+ const requestId = this.nextRequestId++;
+ return new Promise((resolve, reject) => {
+ this.requests.set(requestId, {
+ resolve,
+ reject,
+ progressCallback
+ });
+ this.nativeUpdater.command(JSON.stringify([requestId, detail]));
+ });
+ }
+
+ _sendRequestSync(detail) {
+ if (!this.valid) {
+ throw new Error(INVALID_UPDATER_ERROR);
+ }
+
+ const requestId = this.nextRequestId++;
+ return this.nativeUpdater.command_blocking(JSON.stringify([requestId, detail]));
+ }
+
+ _handleResponse(response) {
+ try {
+ const [id, detail] = JSON.parse(response);
+ const request = this.requests.get(id);
+
+ if (request == null) {
+ console.error('Received response ', detail, ' for a request (', id, ') not in the updater request map.');
+ return;
+ }
+
+ if (detail['Error'] != null) {
+ const {
+ kind,
+ details,
+ severity
+ } = detail['Error'];
+ const e = new Error(`(${kind}) ${details}`);
+
+ if (severity === 'Fatal') {
+ const handled = this.emit(kind, e);
+
+ if (!handled) {
+ throw e;
+ }
+ } else {
+ this.emit('update-error', e);
+ request.reject(e);
+ this.requests.delete(id);
+ }
+ } else if (detail === 'Ok') {
+ request.resolve();
+ this.requests.delete(id);
+ } else if (detail['VersionInfo'] != null) {
+ request.resolve(detail['VersionInfo']);
+ this.requests.delete(id);
+ } else if (detail['ManifestInfo'] != null) {
+ request.resolve(detail['ManifestInfo']);
+ this.requests.delete(id);
+ } else if (detail['TaskProgress'] != null) {
+ const msg = detail['TaskProgress'];
+ const progress = {
+ task: msg[0],
+ state: msg[1],
+ percent: msg[2],
+ bytesProcessed: msg[3]
+ };
+
+ this._recordTaskProgress(progress);
+
+ if (request.progressCallback != null) {
+ request.progressCallback(progress);
+ }
+
+ if (progress.task['HostInstall'] != null && progress.state === TASK_STATE_COMPLETE) {
+ this.emit('host-updated');
+ }
+ } else {
+ console.warn('Unknown updater response', detail);
+ }
+ } catch (e) {
+ console.error('Unhandled exception in updater response handler:', e); // Report the first time this happens, but don't spam.
+
+ if (!this.hasEmittedUnhandledException) {
+ this.hasEmittedUnhandledException = true;
+ this.emit('unhandled-exception', e);
+ }
+ }
+ }
+
+ _handleSyncResponse(response) {
+ const detail = JSON.parse(response);
+
+ if (detail['Error'] != null) {
+ throw new Error(detail['Error']);
+ } else if (detail === 'Ok') {
+ return;
+ } else if (detail['VersionInfo'] != null) {
+ return detail['VersionInfo'];
+ }
+
+ console.warn('Unknown updater response', detail);
+ }
+
+ _getHostPath() {
+ const [major, minor, revision] = this.committedHostVersion;
+ const hostVersionStr = `${major}.${minor}.${revision}`;
+ return path.join(this.rootPath, `app-${hostVersionStr}`);
+ }
+
+ _startCurrentVersionInner(options, versions) {
+ if (this.committedHostVersion == null) {
+ this.committedHostVersion = versions.current_host;
+ }
+
+ const hostPath = this._getHostPath();
+
+ const hostExePath = path.join(hostPath, path.basename(process.execPath));
+
+ if (path.resolve(hostExePath) != path.resolve(process.execPath) && !(options === null || options === void 0 ? void 0 : options.allowObsoleteHost)) {
+ app.once('will-quit', () => {
+ // TODO(eiz): the actual, correct way to do this (win32) is to inherit a
+ // handle to the current process into a new child process which then
+ // waits for that process handle to exit, then runs the new electron.
+ // This requires either implementing a separate updater exe process (big
+ // todo item atm) or likely modifying Electron?
+ //
+ // I intend to do it properly once the new production updater .exe is a
+ // thing.
+ childProcess.spawn(hostExePath, [], {
+ detached: true,
+ stdio: 'inherit'
+ });
+ });
+ console.log(`Restarting from ${path.resolve(process.execPath)} to ${path.resolve(hostExePath)}`);
+ app.quit();
+ return;
+ }
+
+ this._commitModulesInner(versions);
+ }
+
+ _commitModulesInner(versions) {
+ const hostPath = this._getHostPath();
+
+ const modulesPath = path.join(hostPath, 'modules');
+
+ for (const module in versions.current_modules) {
+ const moduleVersion = versions.current_modules[module];
+ const moduleSearchPath = path.join(modulesPath, `${module}-${moduleVersion}`);
+
+ if (!this.committedModules.has(module) && NodeModule.globalPaths.indexOf(moduleSearchPath) === -1) {
+ this.committedModules.add(module);
+ NodeModule.globalPaths.push(moduleSearchPath);
+ }
+ }
+ }
+
+ _recordDownloadProgress(name, progress) {
+ const now = String(hrtime.bigint());
+
+ if (progress.state === TASK_STATE_WORKING && !this.currentlyDownloading[name]) {
+ this.currentlyDownloading[name] = true;
+ this.updateEventHistory.push({
+ type: 'downloading-module',
+ name: name,
+ now: now
+ });
+ } else if (progress.state === TASK_STATE_COMPLETE || progress.state === TASK_STATE_FAILED) {
+ this.currentlyDownloading[name] = false;
+ this.updateEventHistory.push({
+ type: 'downloaded-module',
+ name: name,
+ now: now,
+ succeeded: progress.state === TASK_STATE_COMPLETE,
+ receivedBytes: progress.bytesProcessed
+ });
+ }
+ }
+
+ _recordInstallProgress(name, progress, newVersion, isDelta) {
+ const now = String(hrtime.bigint());
+
+ if (progress.state === TASK_STATE_WORKING && !this.currentlyInstalling[name]) {
+ this.currentlyInstalling[name] = true;
+ this.updateEventHistory.push({
+ type: 'installing-module',
+ name,
+ now,
+ newVersion,
+ foreground: !this.isRunningInBackground
+ });
+ } else if (progress.state === TASK_STATE_COMPLETE || progress.state === TASK_STATE_FAILED) {
+ this.currentlyInstalling[name] = false;
+ this.updateEventHistory.push({
+ type: 'installed-module',
+ name,
+ now,
+ newVersion,
+ succeeded: progress.state === TASK_STATE_COMPLETE,
+ delta: isDelta,
+ foreground: !this.isRunningInBackground
+ });
+ }
+ }
+
+ _recordTaskProgress(progress) {
+ if (progress.task.HostDownload != null) {
+ this._recordDownloadProgress('host', progress);
+ } else if (progress.task.HostInstall != null) {
+ this._recordInstallProgress('host', progress, null, progress.task.HostInstall.from_version != null);
+ } else if (progress.task.ModuleDownload != null) {
+ this._recordDownloadProgress(progress.task.ModuleDownload.version.module.name, progress);
+ } else if (progress.task.ModuleInstall != null) {
+ this._recordInstallProgress(progress.task.ModuleInstall.version.module.name, progress, progress.task.ModuleInstall.version.version, progress.task.ModuleInstall.from_version != null);
+ }
+ }
+
+ queryCurrentVersions() {
+ return this._sendRequest('QueryCurrentVersions');
+ }
+
+ queryCurrentVersionsSync() {
+ return this._handleSyncResponse(this._sendRequestSync('QueryCurrentVersions'));
+ }
+
+ repair(progressCallback) {
+ return this.repairWithOptions(null, progressCallback);
+ }
+
+ repairWithOptions(options, progressCallback) {
+ return this._sendRequest({
+ Repair: {
+ options
+ }
+ }, progressCallback);
+ }
+
+ collectGarbage() {
+ return this._sendRequest('CollectGarbage');
+ }
+
+ setRunningManifest(manifest) {
+ return this._sendRequest({
+ SetManifests: ['Running', manifest]
+ });
+ }
+
+ setPinnedManifestSync(manifest) {
+ return this._handleSyncResponse(this._sendRequestSync({
+ SetManifests: ['Pinned', manifest]
+ }));
+ }
+
+ installModule(name, progressCallback) {
+ return this.installModuleWithOptions(name, null, progressCallback);
+ }
+
+ installModuleWithOptions(name, options, progressCallback) {
+ return this._sendRequest({
+ InstallModule: {
+ name,
+ options
+ }
+ }, progressCallback);
+ }
+
+ updateToLatest(progressCallback) {
+ return this.updateToLatestWithOptions(null, progressCallback);
+ }
+
+ updateToLatestWithOptions(options, progressCallback) {
+ return this._sendRequest({
+ UpdateToLatest: {
+ options
+ }
+ }, progressCallback);
+ } // If the running host is current, adopt the current installed modules and
+ // set up the module search path accordingly. If the running host is not
+ // current, start the new current host and exit this process.
+
+
+ async startCurrentVersion(options) {
+ const versions = await this.queryCurrentVersions();
+ await this.setRunningManifest(versions.last_successful_update);
+
+ this._startCurrentVersionInner(options, versions);
+ }
+
+ startCurrentVersionSync(options) {
+ const versions = this.queryCurrentVersionsSync();
+
+ this._startCurrentVersionInner(options, versions);
+ }
+
+ async commitModules(versions) {
+ if (this.committedHostVersion == null) {
+ throw new Error('Cannot commit modules before host version.');
+ }
+
+ if (versions == null) {
+ versions = await this.queryCurrentVersions();
+ }
+
+ this._commitModulesInner(versions);
+ }
+
+ setRunningInBackground() {
+ this.isRunningInBackground = true;
+ }
+
+ queryAndTruncateHistory() {
+ const history = this.updateEventHistory;
+ this.updateEventHistory = [];
+ return history;
+ }
+
+ getKnownFolder(name) {
+ if (!this.valid) {
+ throw new Error(INVALID_UPDATER_ERROR);
+ }
+
+ return this.nativeUpdater.known_folder(name);
+ }
+
+ createShortcut(options) {
+ if (!this.valid) {
+ throw new Error(INVALID_UPDATER_ERROR);
+ }
+
+ return this.nativeUpdater.create_shortcut(options);
+ }
+
+}
+
+function getUpdaterPlatformName(platform) {
+ switch (platform) {
+ case 'darwin':
+ return 'osx';
+
+ case 'win32':
+ return 'win';
+
+ default:
+ return platform;
+ }
+}
+
+function tryInitUpdater(buildInfo, repositoryUrl) {
+ // We can't require this in module scope because it's not part of the
+ // bootstrapper, which carries a copy of the Updater class.
+ const paths = require('../paths');
+
+ const rootPath = paths.getInstallPath(); // If we're not running from an actual install directory, don't bother trying
+ // to initialize the updater.
+
+ if (rootPath == null) {
+ return false;
+ }
+
+ instance = new Updater({
+ release_channel: buildInfo.releaseChannel,
+ platform: getUpdaterPlatformName(process.platform),
+ repository_url: repositoryUrl,
+ root_path: rootPath
+ });
+ return instance.valid;
+}
+
+function getUpdater() {
+ if (instance != null && instance.valid) {
+ return instance;
+ }
+}
+
+module.exports = {
+ Updater,
+ tryInitUpdater,
+ getUpdater,
+ TASK_STATE_COMPLETE,
+ TASK_STATE_FAILED,
+ TASK_STATE_WAITING,
+ TASK_STATE_WORKING,
+ INCONSISTENT_INSTALLER_STATE_ERROR
+};
\ No newline at end of file
diff --git a/src/updater/windowsUtils.js b/src/updater/windowsUtils.js
new file mode 100644
index 0000000..50a50d0
--- /dev/null
+++ b/src/updater/windowsUtils.js
@@ -0,0 +1,82 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.spawn = spawn;
+exports.spawnReg = spawnReg;
+exports.addToRegistry = addToRegistry;
+
+var _child_process = _interopRequireDefault(require("child_process"));
+
+var _path = _interopRequireDefault(require("path"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+const regExe = process.env.SystemRoot ? _path.default.join(process.env.SystemRoot, 'System32', 'reg.exe') : 'reg.exe'; // Spawn a command and invoke the callback when it completes with an error
+// and the output from standard out.
+
+function spawn(command, args, callback) {
+ let stdout = '';
+ let spawnedProcess;
+
+ try {
+ // TODO: contrary to below, it should not throw any error
+ spawnedProcess = _child_process.default.spawn(command, args);
+ } catch (err) {
+ // Spawn can throw an error
+ process.nextTick(() => {
+ if (callback != null) {
+ callback(err, stdout);
+ }
+ });
+ return;
+ } // TODO: we need to specify the encoding for the data if we're going to concat it as a string
+
+
+ spawnedProcess.stdout.on('data', data => {
+ stdout += data;
+ });
+ let err = null; // TODO: close event might not get called, we should
+ // callback on error https://nodejs.org/api/child_process.html#child_process_event_error
+
+ spawnedProcess.on('error', err => {
+ // TODO: there should always be an error
+ if (err != null) {
+ err = err;
+ }
+ }); // TODO: don't listen to close, but listen to exit instead
+
+ spawnedProcess.on('close', (code, signal) => {
+ if (err === null && code !== 0) {
+ err = new Error('Command failed: ' + (signal || code));
+ }
+
+ if (err != null) {
+ err.code = err.code || code;
+ err.stdout = err.stdout || stdout;
+ }
+
+ if (callback != null) {
+ callback(err, stdout);
+ }
+ });
+} // Spawn reg.exe and callback when it completes
+
+
+function spawnReg(args, callback) {
+ return spawn(regExe, args, callback);
+} // TODO: since we're doing this one by one, we could have a more graceful way of processing the queue
+// rather than mutating the array
+
+
+function addToRegistry(queue, callback) {
+ if (queue.length === 0) {
+ return callback && callback();
+ }
+
+ const args = queue.shift();
+ args.unshift('add');
+ args.push('/f');
+ return spawnReg(args, () => addToRegistry(queue, callback));
+}
\ No newline at end of file
diff --git a/src/utils/Backoff.js b/src/utils/Backoff.js
new file mode 100644
index 0000000..10b673b
--- /dev/null
+++ b/src/utils/Backoff.js
@@ -0,0 +1,94 @@
+class Backoff { // Heavily based on original for compat
+ /**
+ * Create a backoff instance can automatically backoff retries.
+ */
+ constructor(min = 500, max = null, jitter = true) {
+ this.min = min;
+ this.max = max != null ? max : min * 10;
+ this.jitter = jitter;
+ this._current = min;
+ this._timeoutId = null;
+ this._fails = 0;
+ }
+ /**
+ * Return the number of failures.
+ */
+
+
+ get fails() {
+ return this._fails;
+ }
+ /**
+ * Current backoff value in milliseconds.
+ */
+
+
+ get current() {
+ return this._current;
+ }
+ /**
+ * A callback is going to fire.
+ */
+
+
+ get pending() {
+ return this._timeoutId != null;
+ }
+ /**
+ * Clear any pending callbacks and reset the backoff.
+ */
+
+
+ succeed() {
+ this.cancel();
+ this._fails = 0;
+ this._current = this.min;
+ }
+ /**
+ * Increment the backoff and schedule a callback if provided.
+ */
+
+
+ fail(callback) {
+ this._fails += 1;
+ let delay = this._current * 2;
+
+ if (this.jitter) {
+ delay *= Math.random();
+ }
+
+ this._current = Math.min(this._current + delay, this.max);
+
+ if (callback != null) {
+ if (this._timeoutId != null) {
+ throw new Error('callback already pending');
+ }
+
+ this._timeoutId = setTimeout(() => {
+ try {
+ if (callback != null) {
+ callback();
+ }
+ } finally {
+ this._timeoutId = null;
+ }
+ }, this._current);
+ }
+
+ return this._current;
+ }
+ /**
+ * Clear any pending callbacks.
+ */
+
+
+ cancel() {
+ if (this._timeoutId != null) {
+ clearTimeout(this._timeoutId);
+ this._timeoutId = null;
+ }
+ }
+
+}
+
+module.exports = Backoff;
\ No newline at end of file
diff --git a/src/utils/Settings.js b/src/utils/Settings.js
new file mode 100644
index 0000000..f66554f
--- /dev/null
+++ b/src/utils/Settings.js
@@ -0,0 +1,64 @@
+const { readFileSync, statSync, writeFileSync } = require('fs');
+const { join } = require('path');
+
+const log = require('./log');
+
+class Settings { // Heavily based on original for compat, but simplified and tweaked
+ constructor(root) {
+ this.path = join(root, 'settings.json');
+
+ try {
+ this.lastSaved = readFileSync(this.path);
+ this.settings = JSON.parse(this.lastSaved);
+ } catch (e) {
+ this.lastSaved = '';
+ this.settings = {};
+ }
+
+ this.lastModified = this.getLastModified();
+
+ log('AppSettings', 'Loaded settings.json with path', this.path, 'with settings', this.settings, 'and last modified', this.lastModified);
+ }
+
+ getLastModified() {
+ try {
+ return statSync(this.path).mtime.getTime();
+ } catch (e) {
+ return 0;
+ }
+ }
+
+ get(key, defaultValue = false) {
+ return this.settings[key] || defaultValue;
+ }
+
+ set(key, value) {
+ this.settings[key] = value;
+ }
+
+ save() {
+ if (this.lastModified && this.lastModified !== this.getLastModified()) {
+ log('AppSettings', 'Refusing to save settings.json due to last modified date mismatch');
+ return;
+ }
+
+ try {
+ const toSave = JSON.stringify(this.settings, null, 2);
+
+ if (this.lastSaved != toSave) {
+ this.lastSaved = toSave;
+
+ writeFileSync(this.path, toSave);
+
+ this.lastModified = this.getLastModified();
+ }
+
+ log('AppSettings', 'Saved settings.json');
+ } catch (err) {
+ log('AppSettings', 'Failed to save settings.json', err);
+ }
+ }
+
+}
+
+module.exports = Settings;
\ No newline at end of file
diff --git a/src/utils/buildInfo.js b/src/utils/buildInfo.js
new file mode 100644
index 0000000..daef096
--- /dev/null
+++ b/src/utils/buildInfo.js
@@ -0,0 +1,8 @@
+// Discord uses require but we'll use JSON parse for vaguely more security-ish
+const { readFileSync } = require('fs');
+const { join } = require('path');
+
+const buildInfoPath = join(process.resourcesPath, 'build_info.json');
+const buildInfo = JSON.parse(readFileSync(buildInfoPath, 'utf8'));
+
+module.exports = buildInfo;
\ No newline at end of file
diff --git a/src/utils/log.js b/src/utils/log.js
new file mode 100644
index 0000000..f8048ec
--- /dev/null
+++ b/src/utils/log.js
@@ -0,0 +1,3 @@
+const rgb = (r, g, b, text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
+
+module.exports = (area, ...args) => console.log(`[${rgb(88, 101, 242, 'OpenAsar')}${area ? ` > ${area}` : ''}]`, ...args);
\ No newline at end of file
diff --git a/src/utils/requireNative.js b/src/utils/requireNative.js
new file mode 100644
index 0000000..a0ecc86
--- /dev/null
+++ b/src/utils/requireNative.js
@@ -0,0 +1,3 @@
+// From Discord to only require native modules like discord_desktop_core
+module.paths = [];
+module.exports = require;
\ No newline at end of file
diff --git a/src/utils/securityUtils.js b/src/utils/securityUtils.js
new file mode 100644
index 0000000..315b668
--- /dev/null
+++ b/src/utils/securityUtils.js
@@ -0,0 +1,45 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.saferShellOpenExternal = saferShellOpenExternal;
+exports.checkUrlOriginMatches = checkUrlOriginMatches;
+
+var _electron = require("electron");
+
+var _url = _interopRequireDefault(require("url"));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+const BLOCKED_URL_PROTOCOLS = ['file:', 'javascript:', 'vbscript:', 'data:', 'about:', 'chrome:', 'ms-cxh:', 'ms-cxh-full:', 'ms-word:'];
+
+function saferShellOpenExternal(externalUrl) {
+ let parsedUrl;
+
+ try {
+ parsedUrl = _url.default.parse(externalUrl);
+ } catch (_) {
+ return Promise.reject();
+ }
+
+ if (parsedUrl.protocol == null || BLOCKED_URL_PROTOCOLS.includes(parsedUrl.protocol.toLowerCase())) {
+ return Promise.reject();
+ }
+
+ return _electron.shell.openExternal(externalUrl);
+}
+
+function checkUrlOriginMatches(urlA, urlB) {
+ let parsedUrlA;
+ let parsedUrlB;
+
+ try {
+ parsedUrlA = _url.default.parse(urlA);
+ parsedUrlB = _url.default.parse(urlB);
+ } catch (_) {
+ return false;
+ }
+
+ return parsedUrlA.protocol === parsedUrlB.protocol && parsedUrlA.slashes === parsedUrlB.slashes && parsedUrlA.host === parsedUrlB.host;
+}
\ No newline at end of file
diff --git a/src/utils/stub.js b/src/utils/stub.js
new file mode 100644
index 0000000..24bf6a6
--- /dev/null
+++ b/src/utils/stub.js
@@ -0,0 +1,13 @@
+const log = require('./log');
+
+module.exports = (debugName) => {
+ return new Proxy({}, {
+ get(target, prop, receiver) {
+ log('Stub', `${debugName}: Tried getting ${prop}`);
+ },
+
+ set(target, prop, value, receiver) {
+ log('Stub', `${debugName}: Tried setting ${prop}, ${value}`);
+ }
+ });
+};
\ No newline at end of file
diff --git a/test.sh b/test.sh
new file mode 100755
index 0000000..7569c16
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+echo "Packing asar..."
+asar pack src app.asar # Package asar
+# asar list app.asar # List asar for debugging / testing
+
+echo "Copying asar..."
+cp app.asar /opt/discord-canary/resources/app.asar # Overwrite app.asar for Linux Canary
+
+echo "Running discord..."
+echo ""
+
+discord-canary # Run it
\ No newline at end of file