From c9b6798c168d83b9910231e4753f877b3a8ca048 Mon Sep 17 00:00:00 2001 From: Grzegorz Date: Sat, 15 Jan 2022 11:16:50 +0100 Subject: [PATCH] bump 2.0.13 --- CHANGELOG.md | 15 +- README.md | 22 +- config.schema.json | 2 +- index.js | 132 ++++++------ package-lock.json | 464 +++++++++++----------------------------- package.json | 4 +- src/packet/message.js | 13 +- src/packet/simple.js | 2 +- src/packet/structure.js | 10 +- src/smartglass.js | 65 +++--- 10 files changed, 260 insertions(+), 469 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6452559..27259a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### NOTE!!! ## After update to 2.x.x the plugin settings (xboxLiveId) need to be updated. +## [2.0.13] - (15.01.2022) + +### Added +- Network Troubleshooter as defaul input + +### Changed +- removed manual authorization method +- code cleanup +- redme update + +### Fixed +- services calculation count + ## [2.0.12] - (09.01.2022) ### Changed - code cleanup @@ -33,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.0.3] - 2021-12-28 ### Added -- Selectable display type of buttons in Home app +- Selectable display type of buttons in HomeKit app ## [2.0.2] - 2021-12-28 ### Changed diff --git a/README.md b/README.md index b763ca5..74a2429 100644 --- a/README.md +++ b/README.md @@ -28,25 +28,25 @@ Homebridge plugin for Microsoft game Consoles. Tested with Xbox One X/S and Xbox * For versions 1.4.0 and above the minimum required version of Homebridge is v1.3.x. ## Know Issues -* If used with Hoobs, there is a possible configuration incompatibilty. +* Console connected to WLAN network some times lose its connection to the network and the *Power ON* command may not work. ## Troubleshooting * If for some reason the device is not displayed in HomeKit app try this procedure: * Go to `./homebridge/persist`. * Remove `AccessoryInfo.xxx` file which contain Your device data: `{"displayName":"Xbox"}`. * Next remove `IdentifierCashe.xxx` file with same name as `AccessoryInfo.xxx`. - * Restart Homebridge and try add it to the Home app again. + * Restart Homebridge and try add it to the HomeKit app again. ## Features and How To Use Them * Power ON/OFF short press tile in HomeKit app. * Reboot Console with additional button, rquired `webApiControl` enabled. -* RC/Media/Pad control is possible with the RC app on iPhone/iPad or with additional buttons. -* Speaker control is possible using hardware buttons on iPhone/iPad `Speaker Service`. -* Legacy Volume/Mute control is possible throught extra `lightbulbs`/`fans` or with additional buttons. +* RC/Media control is possible after you go to the RC app on iPhone/iPad. +* Speaker control is possible after you go to RC app on iPhone/iPad `Speaker Service`. +* Legacy Volume and Mute control is possible throught extra `lightbulb`/`fan` (slider). * Apps, Inputs, Games can be switched if `webApiControl` is enabled and console is authorized. +* Siri can be used for all functions, some times need create legacy buttons/switches/sensors. +* Automations can be used for all functions, some times need create legacy buttons/switches/sensors. * Record Game DVR with additional button. -* Siri can be used to control all functions, some functions require create buttons. -* Home automations and shortcuts can be used for all functions.

Accessory tile in the HomeKit app @@ -65,13 +65,13 @@ Homebridge plugin for Microsoft game Consoles. Tested with Xbox One X/S and Xbox * First of all please use built in Authorization Manager. * Start new authorization need remove old token first, to clear token use Authorization Manager GUI. * Make sure Your web browser do not block pop-up window, if Yes allow pop-up window for this app. -* If for some reason you cannot use Authorization Manager, please use Authorization Manual Mode. +* If for some reason you cannot use Authorization Manager, please use Authorization Manual Mode (removed ab v2.1.x).

Authentication Manager

-### Authorization Manual Mode +### Authorization Manual Mode (removed ab v2.1.x) * After enable `webApiControl` option, restart the plugin and go to Homebridge console log. * Follow the instructions in the console log. * Start new authorization need remove old token first, go to *./homebridge/xboxTv/* and remove token file. @@ -111,7 +111,7 @@ Install and use [Homebridge Config UI X](https://github.com/oznu/homebridge-conf | `buttons.name` | Here set *Button Name* which You want expose to the *Homebridge/HomeKit*. | | `buttons.command` | Here select button control mode or command, `Reboot` and `Switch App/Game`- only possible if `webApiControl` enabled. | | `buttons.oneStoreProductId` | Here set *Input oneStoreProductId*, only possible if `webApiControl` enabled.| -| `buttons.displayType` | Here select display type in Home app, possible `Switch`, `Button` - selectable in Home app as Light, Fan, Outlet.| +| `buttons.displayType` | Here select display type in HomeKit app, possible `Switch`, `Button` - selectable in HomeKit app as Light, Fan, Outlet.| | `reference`, `oneStoreProductId` | If web Api enabled then all available in `./homebridge/xboxTv/inputs_xxxxxx` file. | *Example Config: @@ -194,7 +194,7 @@ Each accessory needs to be manually paired. ## Limitations * That maximum Services for 1 accessory is 100. If Services > 100, accessory stop responding. * To solve this problem the plugin counts the number of Services and not allow add more as 100. -* If You have configured more as 100 Services some inputs or buttons will not be available in the Home app. +* If You have configured more as 100 Services some inputs or buttons will not be available in the HomeKit app. * The Services in this accessory are: * Information. * Speaker. diff --git a/config.schema.json b/config.schema.json index 16522ad..8536a33 100644 --- a/config.schema.json +++ b/config.schema.json @@ -527,7 +527,7 @@ ] } ], - "description": "Here select display type in Home app", + "description": "Here select display type in HomeKit app", "required": true } } diff --git a/index.js b/index.js index 320f960..6606630 100644 --- a/index.js +++ b/index.js @@ -81,6 +81,14 @@ const DEFAULT_INPUTS = [{ 'type': 'HOME_SCREEN', 'contentType': 'systemApp' }, + { + 'name': 'Network Troubleshooter', + 'titleId': '1614319806', + 'reference': 'Xbox.NetworkTroubleshooter_8wekyb3d8bbwe!Xbox.NetworkTroubleshooter.Application', + 'oneStoreProductId': 'NetworkTroubleshooter', + 'type': 'HOME_SCREEN', + 'contentType': 'systemApp' + }, { 'name': 'Microsoft Store', 'titleId': '1864271209', @@ -247,13 +255,14 @@ class xboxTvDevice { this.volume = 0; this.muteState = false; this.mediaState = 0; - this.pictureMode = 0; - this.brightness = 0; this.setStartInput = false; this.startInputIdentifier = 0; this.inputIdentifier = 0; + this.pictureMode = 0; + this.brightness = 0; + this.prefDir = path.join(api.user.storagePath(), 'xboxTv'); this.authTokenFile = `${this.prefDir}/authToken_${this.host.split('.').join('')}`; this.devInfoFile = `${this.prefDir}/devInfo_${this.host.split('.').join('')}`; @@ -292,19 +301,18 @@ class xboxTvDevice { clientId: this.clientId, clientSecret: this.clientSecret, userToken: this.userToken, - userHash: this.userHash + uhs: this.userHash }); - this.xboxWebApi._authentication._tokensFile = this.authTokenFile; - const getWebApiToken = this.webApiControl ? this.getWebApiToken() : false; + const checkAuthorizationState = this.webApiControl ? this.getAuthorizationState() : false this.xbox = new Smartglass({ host: this.host, xboxLiveId: this.xboxLiveId, userToken: this.userToken, - userHash: this.userHash + uhs: this.userHash }); - this.xbox.on('connect', (message) => { + this.xbox.on('connected', (message) => { this.powerState = true; if (this.televisionService) { @@ -326,7 +334,7 @@ class xboxTvDevice { .on('message', (message) => { const logInfo = this.disableLogInfo ? false : this.log('Device: %s %s, %s', this.host, this.name, message); }) - .on('devInfo', async (firmwareRevision) => { + .on('deviceInfo', async (firmwareRevision) => { if (!this.disableLogDeviceInfo) { this.log('-------- %s --------', this.name); this.log('Manufacturer: %s', this.manufacturer); @@ -352,7 +360,7 @@ class xboxTvDevice { this.firmwareRevision = firmwareRevision; }) - .on('change', async (decodedMessage, mediaState) => { + .on('stateChanged', async (decodedMessage, mediaState) => { const appsArray = new Array(); const appsCount = decodedMessage.apps.length; for (let i = 0; i < appsCount; i++) { @@ -370,15 +378,19 @@ class xboxTvDevice { //get states const volume = this.volume; const muteState = this.powerState ? this.muteState : true; - - const currentInputIdentifier = this.inputsReference.indexOf(inputReference) >= 0 ? this.inputsReference.indexOf(inputReference) : this.inputsTitleId.indexOf(titleId) >= 0 ? this.inputsTitleId.indexOf(titleId) : this.inputIdentifier; - const inputIdentifier = this.setStartInput ? this.startInputIdentifier : currentInputIdentifier; + const inputIdentifier = this.inputsReference.indexOf(inputReference) >= 0 ? this.inputsReference.indexOf(inputReference) : this.inputsTitleId.indexOf(titleId) >= 0 ? this.inputsTitleId.indexOf(titleId) : this.inputIdentifier; //update characteristics if (this.televisionService) { - const setUpdateCharacteristic = this.setStartInput ? this.televisionService.setCharacteristic(Characteristic.ActiveIdentifier, inputIdentifier) : - this.televisionService.updateCharacteristic(Characteristic.ActiveIdentifier, inputIdentifier); - this.setStartInput = (currentInputIdentifier == inputIdentifier) ? false : true; + this.televisionService + .updateCharacteristic(Characteristic.ActiveIdentifier, inputIdentifier); + + if (this.setStartInput) { + setTimeout(() => { + this.televisionService.setCharacteristic(Characteristic.ActiveIdentifier, this.startInputIdentifier); + this.setStartInput = false; + }, 1200); + } }; if (this.speakerService) { @@ -402,7 +414,7 @@ class xboxTvDevice { this.mediaState = mediaState; this.inputIdentifier = inputIdentifier; }) - .on('disconnect', (message) => { + .on('disconnected', (message) => { this.powerState = false; clearInterval(this.updateWebInstalledApp); @@ -417,41 +429,19 @@ class xboxTvDevice { this.prepareAccessory(); } - async getWebApiToken() { - this.log.debug('Device: %s %s, preparing web api.', this.host, this.name); + getAuthorizationState() { + this.log.debug('Device: %s %s, requesting authorization state.', this.host, this.name); try { - await this.xboxWebApi.isAuthenticated(); + this.xboxWebApi._authentication._tokensFile = this.authTokenFile; + this.xboxWebApi.isAuthenticated(); this.webApiEnabled = true; this.getWebApiInstalledApps(); this.log('Device: %s %s, authorized and Web Api enabled.', this.host, this.name); } catch (error) { - if (this.xboxWebApiToken != undefined) { - const debug = this.enableDebugMode ? this.log('Device: %s %s, trying to authorize with Web Api Token: %s', this.host, this.name, this.xboxWebApiToken) : false; - try { - const authenticationData = await this.xboxWebApi._authentication.getTokenRequest(this.xboxWebApiToken); - const debug = this.enableDebugMode ? this.log('Device: %s %s, get oauth2 Web Api Token: %s', this.host, this.name, authenticationData) : false; - this.xboxWebApi._authentication._tokens.oauth = authenticationData; - this.xboxWebApi._authentication.saveTokens(); - this.webApiEnabled = true; - this.getWebApiInstalledApps(); - this.log('Device: %s %s, Token saved and Web Api enabled.', this.host, this.name); - } catch (error) { - this.log.error('Device: %s %s, Token request error: %s', this.host, this.name, error); - this.webApiEnabled = false; - }; - } else { - const oauth2URI = this.xboxWebApi._authentication.generateAuthorizationUrl(); - this.log('----- Device: %s %s start authorization process -----', this.host, this.name, ); - this.log(`1. Open the URI: ${oauth2URI}`); - this.log('2. Login to Your Xbox Live account and accept permission to allow Homebridge-Smartglass.'); - this.log('3. After you accept permission, copy the part after the (?code=) from the URL of the pop-up.'); - this.log('4. Paste it in to the plugin config, Settings >> Xbox Live and Web Api >> Web Api Token (Not Web Api Client ID).'); - this.log('5. Save and restart the plugin again, then you are done.') - this.log('----------------------------------------------------------------------------------------'); - this.webApiEnabled = false; - } + this.log('Device: %s %s, not authorized, please use Authorization Manager.', this.host, this.name); + this.webApiEnabled = false; }; - } + }; async getWebApiConsolesList() { this.log.debug('Device: %s %s, requesting web api consoles list.', this.host, this.name); @@ -526,8 +516,8 @@ class xboxTvDevice { this.getWebApiUserProfile(); } catch (error) { if (error.status == 401) { - this.getWebApiToken(); - const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, trying to get Installed Apps gave an error, trying to reauthenticate.', this.host, this.name, this.xboxLiveId) : false; + this.getAuthorizationState(); + const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, trying to get Installed Apps gave an error, checking authorization state again.', this.host, this.name, this.xboxLiveId) : false; } else { this.log.error('Device: %s %s, get Consoles List error: %s.', this.host, this.name, error); }; @@ -571,8 +561,8 @@ class xboxTvDevice { this.getWebApiInstalledApps(); } catch (error) { if (error.status == 401) { - this.getWebApiToken(); - const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, trying to get Installed Apps gave an error, trying to reauthenticate.', this.host, this.name, this.xboxLiveId) : false; + this.getAuthorizationState(); + const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, trying to get Installed Apps gave an error, checking authorization state again.', this.host, this.name, this.xboxLiveId) : false; } else { this.log.error('Device: %s %s, get User Profile error: %s.', this.host, this.name, error); }; @@ -630,8 +620,8 @@ class xboxTvDevice { this.getWebApiStorageDevices(); } catch (error) { if (error.status == 401) { - this.getWebApiToken(); - const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, trying to get Installed Apps gave an error, trying to reauthenticate.', this.host, this.name, this.xboxLiveId) : false; + this.getAuthorizationState(); + const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, trying to get Installed Apps gave an error, checking authorization state again.', this.host, this.name, this.xboxLiveId) : false; } else { this.log.error('Device: %s %s, with liveId: %s, get Installed Apps error: %s.', this.host, this.name, this.xboxLiveId, error); }; @@ -675,8 +665,8 @@ class xboxTvDevice { this.getWebApiConsoleStatus(); } catch (error) { if (error.status == 401) { - this.getWebApiToken(); - const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, get Console Status error, trying to reauthenticate.', this.host, this.name, this.xboxLiveId) : false; + this.getAuthorizationState(); + const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, get Console Status error, checking authorization state again.', this.host, this.name, this.xboxLiveId) : false; } else { this.log.error('Device: %s %s, with liveId: %s, get Storage Devices error: %s.', this.host, this.name, this.xboxLiveId, error); }; @@ -710,8 +700,8 @@ class xboxTvDevice { //this.mediaState = playbackState; } catch (error) { if (error.status == 401) { - this.getWebApiToken(); - const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, get Console Status error, trying to reauthenticate.', this.host, this.name, this.xboxLiveId) : false; + this.getAuthorizationState(); + const debug = this.enableDebugMode ? this.log('Device: %s %s, with liveId: %s, get Console Status error, checking authorization state again.', this.host, this.name, this.xboxLiveId) : false; } else { this.log.error('Device: %s %s, with liveId: %s, get Console Status error: %s.', this.host, this.name, this.xboxLiveId, error); }; @@ -783,20 +773,21 @@ class xboxTvDevice { return inputIdentifier; }) .onSet(async (inputIdentifier) => { + const inputName = this.inputsName[inputIdentifier]; + const inputReference = this.inputsReference[inputIdentifier]; + const inputOneStoreProductId = this.inputsOneStoreProductId[inputIdentifier]; + const setDashboard = (inputOneStoreProductId === 'Dashboard' || inputOneStoreProductId === 'Settings' || inputOneStoreProductId === 'SettingsTv' || inputOneStoreProductId === 'Accessory' || inputOneStoreProductId === 'Screensaver' || inputOneStoreProductId === 'NetworkTroubleshooter'); + const setTelevision = (inputOneStoreProductId === 'Television'); + const setApp = ((inputOneStoreProductId != undefined && inputOneStoreProductId != '0') && !setDashboard && !setTelevision); try { - const inputName = this.inputsName[inputIdentifier]; - const inputReference = this.inputsReference[inputIdentifier]; - const inputOneStoreProductId = this.inputsOneStoreProductId[inputIdentifier]; - const setDashboard = (inputOneStoreProductId === 'Dashboard' || inputOneStoreProductId === 'Settings' || inputOneStoreProductId === 'SettingsTv' || inputOneStoreProductId === 'Accessory' || inputOneStoreProductId === 'Screensaver'); - const setTelevision = (inputOneStoreProductId === 'Television'); - const setApp = ((inputOneStoreProductId != undefined && inputOneStoreProductId != '0') && !setDashboard && !setTelevision); const setInput = (this.powerState && this.webApiEnabled) ? setApp ? await this.xboxWebApi.getProvider('smartglass').launchApp(this.xboxLiveId, inputOneStoreProductId) : setDashboard ? await this.xboxWebApi.getProvider('smartglass').launchDashboard(this.xboxLiveId) : setTelevision ? await this.xboxWebApi.getProvider('smartglass').launchOneGuide(this.xboxLiveId) : false : false; const logInfo = this.disableLogInfo ? false : this.log('Device: %s %s, set Input successful, input: %s, reference: %s, product Id: %s', this.host, accessoryName, inputName, inputReference, inputOneStoreProductId); - this.startInputIdentifier = inputIdentifier; - this.setStartInput = this.powerState ? false : this.webApiEnabled ? true : false; + this.inputIdentifier = inputIdentifier; } catch (error) { this.log.error('Device: %s %s, set Input error: %s', this.host, accessoryName, error); }; + this.setStartInput = !this.powerState; + this.startInputIdentifier = inputIdentifier; }); this.televisionService.getCharacteristic(Characteristic.RemoteKey) @@ -1017,7 +1008,7 @@ class xboxTvDevice { } //Prepare inputs services - this.log.debug('prepareInputsService'); + this.log.debug('prepareInputServices'); const savedInputs = ((fs.readFileSync(this.inputsFile)).length > 0) ? JSON.parse(fs.readFileSync(this.inputsFile)) : []; const debug = this.enableDebugMode ? this.log('Device: %s %s, read saved Inputs successful, inpits: %s', this.host, accessoryName, savedInputs) : false; @@ -1119,13 +1110,14 @@ class xboxTvDevice { accessory.addService(inputService); } - //Prepare inputs button services - this.log.debug('prepareInputsButtonService'); + //Prepare buttons services + this.log.debug('prepareButtonServices'); - //check available buttons and possible buttons count (max 93 - inputsCount) + //check available buttons and possible buttons count (max 94) const buttons = this.buttons; const buttonsCount = buttons.length; - const maxButtonsCount = ((inputsCount + buttonsCount) < 93) ? buttonsCount : 93 - inputsCount; + const availableButtonshCount = 94 - maxInputsCount; + const maxButtonsCount = (availableButtonshCount > 0) ? (availableButtonshCount > buttonsCount) ? buttonsCount : availableButtonshCount : 0; for (let i = 0; i < maxButtonsCount; i++) { //get button command @@ -1173,7 +1165,7 @@ class xboxTvDevice { return state; }) .onSet(async (state) => { - const setDashboard = (buttonOneStoreProductId === 'Dashboard' || buttonOneStoreProductId === 'Settings' || buttonOneStoreProductId === 'SettingsTv' || buttonOneStoreProductId === 'Accessory' || buttonOneStoreProductId === 'Screensaver'); + const setDashboard = (buttonOneStoreProductId === 'Dashboard' || buttonOneStoreProductId === 'Settings' || buttonOneStoreProductId === 'SettingsTv' || buttonOneStoreProductId === 'Accessory' || buttonOneStoreProductId === 'Screensaver' || buttonOneStoreProductId === 'NetworkTroubleshooter'); const setTelevision = (buttonOneStoreProductId === 'Television'); const setApp = ((buttonOneStoreProductId != undefined && buttonOneStoreProductId != '0') && !setDashboard && !setTelevision); try { @@ -1192,7 +1184,7 @@ class xboxTvDevice { accessory.addService(buttonService); } - const debug3 = this.enableDebugMode ? this.log('Device: %s %s, publishExternalAccessories.', this.host, accessoryName) : false; + const debug3 = this.enableDebugMode ? this.log('Device: %s %s, publishExternalAccessory.', this.host, accessoryName) : false; this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]); } }; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 35c1875..eaa93ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "homebridge-xbox-tv", - "version": "2.0.10", + "version": "2.0.13", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "2.0.10", + "version": "2.0.13", "license": "MIT", "dependencies": { "@homebridge/plugin-ui-utils": ">=0.0.19", - "elliptic": ">=6.5.4", + "elliptic": "^6.5.4", "hex-to-binary": ">=1.0.1", "jsrsasign": ">=10.5.1", "uuid": ">=8.3.2", @@ -27,14 +27,11 @@ }, "node_modules/@homebridge/plugin-ui-utils": { "version": "0.0.19", - "resolved": "https://registry.npmjs.org/@homebridge/plugin-ui-utils/-/plugin-ui-utils-0.0.19.tgz", - "integrity": "sha512-axFX7lN2Yd7bz/6SlD7dzq5sY/N9+XYuLHPukuiyHQRDtNMRL1uDqJhOx6RVaN2tYDHB75h7YxRQWP7U44Mgzg==", "license": "MIT" }, "node_modules/accepts": { "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.24", "negotiator": "0.6.2" @@ -45,18 +42,15 @@ }, "node_modules/array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "license": "MIT" }, "node_modules/bn.js": { "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "license": "MIT" }, "node_modules/body-parser": { "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "license": "MIT", "dependencies": { "bytes": "3.1.0", "content-type": "~1.0.4", @@ -75,34 +69,29 @@ }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "license": "MIT" }, "node_modules/brorand": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "license": "MIT" }, "node_modules/bytes": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/content-disposition": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "license": "MIT", "dependencies": { "safe-buffer": "5.1.2" }, @@ -112,29 +101,25 @@ }, "node_modules/content-type": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "license": "MIT" }, "node_modules/debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -149,26 +134,24 @@ }, "node_modules/depd": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/destroy": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "license": "MIT" }, "node_modules/ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "license": "MIT" }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -181,29 +164,25 @@ }, "node_modules/encodeurl": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "license": "MIT" }, "node_modules/etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express": { "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "license": "MIT", "dependencies": { "accepts": "~1.3.7", "array-flatten": "1.1.1", @@ -242,21 +221,18 @@ }, "node_modules/express/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/express/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "license": "MIT" }, "node_modules/finalhandler": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -272,37 +248,32 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "license": "MIT" }, "node_modules/forwarded": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/hash.js": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -310,13 +281,11 @@ }, "node_modules/hex-to-binary": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hex-to-binary/-/hex-to-binary-1.0.1.tgz", - "integrity": "sha1-YcevAW/CK86pcE2fLpo46MfbuFQ=" + "license": "MIT" }, "node_modules/hmac-drbg": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "license": "MIT", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -325,8 +294,7 @@ }, "node_modules/http-errors": { "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "license": "MIT", "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -340,13 +308,11 @@ }, "node_modules/http-errors/node_modules/inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "license": "ISC" }, "node_modules/iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -356,21 +322,17 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/jsrsasign": { "version": "10.5.1", - "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.5.1.tgz", - "integrity": "sha512-yW0fq87KNZFw4Pn5ySllXs3ztZAROQZczEheKZTqmiNpCe/Xj9r5NhuAQ7MXTOyEZGJ/+MPHGTsfbgPFaLpwHQ==", "license": "MIT", "funding": { "url": "https://github.com/kjur/jsrsasign#donations" @@ -378,29 +340,25 @@ }, "node_modules/media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "license": "MIT" }, "node_modules/methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -410,16 +368,14 @@ }, "node_modules/mime-db": { "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "license": "MIT", "dependencies": { "mime-db": "1.47.0" }, @@ -429,31 +385,26 @@ }, "node_modules/minimalistic-assert": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "license": "MIT" }, "node_modules/ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/on-finished": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -463,21 +414,18 @@ }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-to-regexp": { "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "license": "MIT" }, "node_modules/proxy-addr": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "license": "MIT", "dependencies": { "forwarded": "~0.1.2", "ipaddr.js": "1.9.1" @@ -488,24 +436,21 @@ }, "node_modules/qs": { "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.6" } }, "node_modules/range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/raw-body": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "license": "MIT", "dependencies": { "bytes": "3.1.0", "http-errors": "1.7.2", @@ -518,18 +463,15 @@ }, "node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "license": "MIT" }, "node_modules/send": { "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "~1.1.2", @@ -551,26 +493,22 @@ }, "node_modules/send/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } }, "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "license": "MIT" }, "node_modules/send/node_modules/ms": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "license": "MIT" }, "node_modules/serve-static": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -583,29 +521,25 @@ }, "node_modules/setprototypeof": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "license": "ISC" }, "node_modules/statuses": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/toidentifier": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "license": "MIT", "engines": { "node": ">=0.6" } }, "node_modules/type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -616,50 +550,42 @@ }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/utils-merge": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/uuid-parse": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", - "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==" + "license": "MIT" }, "node_modules/uuid4": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uuid4/-/uuid4-2.0.2.tgz", - "integrity": "sha512-TzsQS8sN1B2m9WojyNp0X/3JL8J2RScnrAJnooNPL6lq3lA02/XdoWysyUgI6rAif0DzkkWk51N6OggujPy2RA==" + "license": "ISC" }, "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/xbox-webapi": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/xbox-webapi/-/xbox-webapi-1.2.0.tgz", - "integrity": "sha512-KPfrleQdCUd2vzIzAGElIV7sOOB8CgqfSpL/Nb451nDSWENE7J8IT26ZozumN5IR79seqCeuQJ65Z35RUrSjsA==", "license": "MIT", "dependencies": { "debug": "^4.2.0", @@ -670,33 +596,23 @@ }, "dependencies": { "@homebridge/plugin-ui-utils": { - "version": "0.0.19", - "resolved": "https://registry.npmjs.org/@homebridge/plugin-ui-utils/-/plugin-ui-utils-0.0.19.tgz", - "integrity": "sha512-axFX7lN2Yd7bz/6SlD7dzq5sY/N9+XYuLHPukuiyHQRDtNMRL1uDqJhOx6RVaN2tYDHB75h7YxRQWP7U44Mgzg==" + "version": "0.0.19" }, "accepts": { "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "requires": { "mime-types": "~2.1.24", "negotiator": "0.6.2" } }, "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "version": "1.1.1" }, "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.11.9" }, "body-parser": { "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "requires": { "bytes": "3.1.0", "content-type": "~1.0.4", @@ -712,74 +628,50 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.0.0" } } }, "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + "version": "1.1.0" }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.0" }, "content-disposition": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", "requires": { "safe-buffer": "5.1.2" } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.4" }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.4.0" }, "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "version": "1.0.6" }, "debug": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { "ms": "2.1.2" } }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "1.1.2" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.0.4" }, "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "version": "1.1.1" }, "elliptic": { "version": "6.5.4", @@ -796,24 +688,16 @@ } }, "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "version": "1.0.2" }, "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "version": "1.0.3" }, "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "version": "1.8.1" }, "express": { "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", @@ -849,23 +733,17 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.0.0" } } }, "finalhandler": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -878,47 +756,33 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.0.0" } } }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.1.2" }, "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "version": "0.5.2" }, "hash.js": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "hex-to-binary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hex-to-binary/-/hex-to-binary-1.0.1.tgz", - "integrity": "sha1-YcevAW/CK86pcE2fLpo46MfbuFQ=" + "version": "1.0.1" }, "hmac-drbg": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -927,8 +791,6 @@ }, "http-errors": { "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "requires": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -938,129 +800,85 @@ }, "dependencies": { "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.3" } } }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "version": "2.0.4" }, "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "version": "1.9.1" }, "jsrsasign": { - "version": "10.5.1", - "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.5.1.tgz", - "integrity": "sha512-yW0fq87KNZFw4Pn5ySllXs3ztZAROQZczEheKZTqmiNpCe/Xj9r5NhuAQ7MXTOyEZGJ/+MPHGTsfbgPFaLpwHQ==" + "version": "10.5.1" }, "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "version": "0.3.0" }, "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "version": "1.0.1" }, "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "version": "1.1.2" }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "version": "1.6.0" }, "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + "version": "1.47.0" }, "mime-types": { "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "requires": { "mime-db": "1.47.0" } }, "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "version": "1.0.1" }, "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "version": "1.0.1" }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.2" }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.2" }, "on-finished": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "requires": { "ee-first": "1.1.1" } }, "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "version": "1.3.3" }, "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "version": "0.1.7" }, "proxy-addr": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "requires": { "forwarded": "~0.1.2", "ipaddr.js": "1.9.1" } }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.7.0" }, "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "version": "1.2.1" }, "raw-body": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "requires": { "bytes": "3.1.0", "http-errors": "1.7.2", @@ -1069,19 +887,13 @@ } }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.1.2" }, "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "version": "2.1.2" }, "send": { "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -1100,30 +912,22 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" }, "dependencies": { "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.0.0" } } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.1" } } }, "serve-static": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -1132,63 +936,41 @@ } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.1.1" }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "1.5.0" }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.0" }, "type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "requires": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "version": "1.0.0" }, "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "version": "1.0.1" }, "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "version": "8.3.2" }, "uuid-parse": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/uuid-parse/-/uuid-parse-1.1.0.tgz", - "integrity": "sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==" + "version": "1.1.0" }, "uuid4": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uuid4/-/uuid4-2.0.2.tgz", - "integrity": "sha512-TzsQS8sN1B2m9WojyNp0X/3JL8J2RScnrAJnooNPL6lq3lA02/XdoWysyUgI6rAif0DzkkWk51N6OggujPy2RA==" + "version": "2.0.2" }, "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "version": "1.1.2" }, "xbox-webapi": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/xbox-webapi/-/xbox-webapi-1.2.0.tgz", - "integrity": "sha512-KPfrleQdCUd2vzIzAGElIV7sOOB8CgqfSpL/Nb451nDSWENE7J8IT26ZozumN5IR79seqCeuQJ65Z35RUrSjsA==", "requires": { "debug": "^4.2.0", "express": "^4.17.1", diff --git a/package.json b/package.json index ecb57db..2729350 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Xbox TV", "name": "homebridge-xbox-tv", - "version": "2.0.12", + "version": "2.0.13", "description": "Homebridge plugin (https://github.com/homebridge/homebridge) to control Xbox game consoles.", "license": "MIT", "author": "grzegorz914", @@ -34,7 +34,7 @@ }, "dependencies": { "@homebridge/plugin-ui-utils": ">=0.0.19", - "elliptic": ">=6.5.4", + "elliptic": "^6.5.4", "hex-to-binary": ">=1.0.1", "jsrsasign": ">=10.5.1", "uuid": ">=8.3.2", diff --git a/src/packet/message.js b/src/packet/message.js index 736aa25..7139c49 100644 --- a/src/packet/message.js +++ b/src/packet/message.js @@ -114,7 +114,7 @@ class MESSAGE { structure: structure, pack(packetStructure) { packetStructure.writeUInt16(this.value.length); - let arrayStructure = Packet[structure]; + let arrayStructure = Packet[this.structure]; for (let index in this.value) { for (let name in arrayStructure) { arrayStructure[name].value = this.value[index][name] @@ -128,7 +128,7 @@ class MESSAGE { const array = new Array(); for (let i = 0; i < arrayCount; i++) { - const arrayStructure = Packet[structure]; + const arrayStructure = Packet[this.structure]; let item = {}; for (let name in arrayStructure) { @@ -146,10 +146,9 @@ class MESSAGE { value: value, structure: structure, pack(packetStructure) { - packetStructure.writeUInt32(this.value.length); - let arrayStructure = Packet[structure]; + let arrayStructure = Packet[this.structure]; for (let index in this.value) { for (let name in arrayStructure) { arrayStructure[name].value = this.value[index][name] @@ -163,7 +162,7 @@ class MESSAGE { const array = new Array(); for (let i = 0; i < arrayCount; i++) { - const arrayStructure = Packet[structure]; + const arrayStructure = Packet[this.structure]; let item = {}; for (let name in arrayStructure) { @@ -461,14 +460,14 @@ class MESSAGE { }; pack(smartglass) { - let payload = new PacketStructure(); + const payload = new PacketStructure(); for (let name in this.structure) { this.structure[name].pack(payload); }; smartglass.getRequestNum(); - let header = new PacketStructure(); + const header = new PacketStructure(); header.writeBytes(Buffer.from('d00d', 'hex')) header.writeUInt16(payload.toBuffer().length); header.writeUInt32(smartglass.requestNum); diff --git a/src/packet/simple.js b/src/packet/simple.js index 257fc24..745c333 100644 --- a/src/packet/simple.js +++ b/src/packet/simple.js @@ -172,7 +172,7 @@ class SIMPLE { }; pack(smartglass = false) { - let payload = new PacketStructure(); + const payload = new PacketStructure(); let packet = payload.toBuffer(); for (let name in this.structure) { diff --git a/src/packet/structure.js b/src/packet/structure.js index 797bde1..d993f4a 100644 --- a/src/packet/structure.js +++ b/src/packet/structure.js @@ -17,7 +17,7 @@ class STRUCTURE { }; writeSGString(data) { - let lengthBuffer = Buffer.allocUnsafe(2); + const lengthBuffer = Buffer.allocUnsafe(2); lengthBuffer.writeUInt16BE(data.length, 0); const dataBuffer = Buffer.from(data + '\x00'); @@ -55,7 +55,7 @@ class STRUCTURE { }; writeUInt8(data) { - let tempBuffer = Buffer.allocUnsafe(1); + const tempBuffer = Buffer.allocUnsafe(1); tempBuffer.writeUInt8(data, 0); this.add(tempBuffer); return this; @@ -68,7 +68,7 @@ class STRUCTURE { }; writeUInt16(data) { - let tempBuffer = Buffer.allocUnsafe(2); + const tempBuffer = Buffer.allocUnsafe(2); tempBuffer.writeUInt16BE(data, 0); this.add(tempBuffer); return this; @@ -81,7 +81,7 @@ class STRUCTURE { }; writeUInt32(data) { - let tempBuffer = Buffer.allocUnsafe(4); + const tempBuffer = Buffer.allocUnsafe(4); tempBuffer.writeUInt32BE(data, 0); this.add(tempBuffer); return this; @@ -94,7 +94,7 @@ class STRUCTURE { }; writeInt32(data) { - let tempBuffer = Buffer.allocUnsafe(4); + const tempBuffer = Buffer.allocUnsafe(4); tempBuffer.writeInt32BE(data, 0); this.add(tempBuffer); return this; diff --git a/src/smartglass.js b/src/smartglass.js index 01e0c61..ab7e9a8 100644 --- a/src/smartglass.js +++ b/src/smartglass.js @@ -67,7 +67,7 @@ class SMARTGLASS extends EventEmitter { this.host = config.host; this.xboxLiveId = config.xboxLiveId; this.userToken = config.userToken; - this.userHash = config.userHash; + this.userHash = config.uhs; this.crypto = new SGCrypto(); this.isConnected = false; @@ -96,6 +96,7 @@ class SMARTGLASS extends EventEmitter { this.channelTargetId = null; this.channelRequestId = null; + //dgram socket this.socket = new dgram.createSocket('udp4'); this.socket.on('error', (error) => { this.emit('error', `Socket error: ${error}`); @@ -105,7 +106,7 @@ class SMARTGLASS extends EventEmitter { this.emit('debug', `Server reveived message from: ${remote.address}:${remote.port}`); this.messageReceivedTime = (new Date().getTime()) / 1000; message = new Packer(message); - if (!message.structure) { + if (message.structure == false) { return; }; @@ -124,10 +125,10 @@ class SMARTGLASS extends EventEmitter { if (this.response.packetDecoded.flags.needAck == true) { this.emit('debug', 'Packet needs to be acknowledged, send acknowledge.'); - let acknowledge = new Packer('message.acknowledge'); - acknowledge.set('lowWatermark', this.response.packetDecoded.sequenceNumber); + const acknowledge = new Packer('message.acknowledge'); + acknowledge.set('lowWatermark', this.requestNum); acknowledge.structure.structure.processedList.value.push({ - id: this.response.packetDecoded.sequenceNumber + id: this.requestNum }); const message = acknowledge.pack(this); this.sendSocketMessage(message); @@ -145,7 +146,7 @@ class SMARTGLASS extends EventEmitter { this.fragments[jsonMessage.datagramId] = { getValue: () => { - let buffer = Buffer.from(''); + const buffer = Buffer.from(''); for (let partial in this.partials) { buffer = Buffer.concat([ buffer, @@ -157,7 +158,6 @@ class SMARTGLASS extends EventEmitter { }, isValid: () => { const json = this.getValue(); - try { JSON.parse(json.toString()); } catch (error) { @@ -175,7 +175,7 @@ class SMARTGLASS extends EventEmitter { this.response.packetDecoded.protectedPayload.json = this.fragments[jsonMessage.datagramId].getValue().toString(); this.fragments[jsonMessage.datagramId] = undefined; }; - this.function = 'json_fragment'; + this.function = 'jsonFragment'; }; }; this.emit(this.function, this.response); @@ -187,7 +187,7 @@ class SMARTGLASS extends EventEmitter { setInterval(() => { if (!this.isConnected) { - let discoveryPacket = new Packer('simple.discoveryRequest'); + const discoveryPacket = new Packer('simple.discoveryRequest'); const message = discoveryPacket.pack(); this.sendSocketMessage(message); }; @@ -231,7 +231,7 @@ class SMARTGLASS extends EventEmitter { this.crypto.load(Buffer.from(object.publicKey, 'hex'), Buffer.from(object.secret, 'hex')); this.emit('debug', `Loading crypto, public key: ${object.publicKey}, and secret: ${object.secret}`); - let connectRequest = new Packer('simple.connectRequest'); + const connectRequest = new Packer('simple.connectRequest'); connectRequest.set('uuid', uuid4); connectRequest.set('publicKey', this.crypto.getPublicKey()); connectRequest.set('iv', this.crypto.getIv()); @@ -256,10 +256,10 @@ class SMARTGLASS extends EventEmitter { this.participantId = participantId; this.sourceParticipantId = participantId; - if (connectionResult == '0') { + if (connectionResult == 0) { this.emit('debug', 'Connect response received.') - let localJoin = new Packer('message.localJoin'); + const localJoin = new Packer('message.localJoin'); const message = localJoin.pack(this); this.sendSocketMessage(message); @@ -289,14 +289,14 @@ class SMARTGLASS extends EventEmitter { 2: 'Unknown error.', 3: 'No anonymous connections.', 4: 'Device limit exceeded.', - 5: 'Smartglass is disabled on the Xbox console.', + 5: 'Remote connect is disabled on the console.', 6: 'User authentication failed.', 7: 'Sign-in failed.', 8: 'Sign-in timeout.', 9: 'Sign-in required.' }; this.isConnected = false; - this.emit('error', `Connect error: ${errorTable[message.packetDecoded.protectedPayload.connectResult]}`); + this.emit('error', `Connect error: ${errorTable[connectionResult]}`); }; }) .on('channelResponse', (message) => { @@ -321,7 +321,7 @@ class SMARTGLASS extends EventEmitter { const requestIdLength = requestId.length; requestId = (requestId + mediaRequestId++).slice(-requestIdLength); - let mediaCommand = new Packer('message.mediaCommand'); + const mediaCommand = new Packer('message.mediaCommand'); mediaCommand.set('requestId', Buffer.from(requestId, 'hex')); mediaCommand.set('titleId', 0); mediaCommand.set('command', systemMediaCommands[command]); @@ -337,7 +337,7 @@ class SMARTGLASS extends EventEmitter { if (this.channelRequestId == 1) { if (command in systemInputCommands) { const timeStampPress = new Date().getTime(); - let gamepadPress = new Packer('message.gamepad'); + const gamepadPress = new Packer('message.gamepad'); gamepadPress.set('timestamp', Buffer.from(`000${timeStampPress.toString()}`, 'hex')); gamepadPress.set('buttons', systemInputCommands[command]); gamepadPress.setChannel(this.channelTargetId); @@ -347,7 +347,7 @@ class SMARTGLASS extends EventEmitter { setTimeout(() => { const timeStampUnpress = new Date().getTime(); - let gamepadUnpress = new Packer('message.gamepad'); + const gamepadUnpress = new Packer('message.gamepad'); gamepadUnpress.set('timestamp', Buffer.from(`000${timeStampUnpress.toString()}`, 'hex')); gamepadUnpress.set('buttons', systemInputCommands['unpress']); gamepadUnpress.setChannel(this.channelTargetId); @@ -371,7 +371,7 @@ class SMARTGLASS extends EventEmitter { device_id: null } }; - let json = new Packer('message.json'); + const json = new Packer('message.json'); json.set('json', JSON.stringify(jsonRequest)); json.setChannel(this.channelTargetId); const message = json.pack(this); @@ -391,7 +391,7 @@ class SMARTGLASS extends EventEmitter { request: configName, params: null }; - let json = new Packer('message.json'); + const json = new Packer('message.json'); json.set('json', JSON.stringify(jsonRequest)); json.setChannel(this.channelTargetId); const message = json.pack(this); @@ -427,21 +427,24 @@ class SMARTGLASS extends EventEmitter { }; }; }) + .on('jsonFragment', (message) => { + this.emit('debug', `Json fragment: ${message}`); + }) .on('status', (message) => { if (message.packetDecoded.protectedPayload.apps[0] != undefined) { const decodedMessage = message.packetDecoded.protectedPayload; - this.emit('debug', decodedMessage) + this.emit('debug', `Status: ${decodedMessage}`); if (!this.isConnected) { this.isConnected = true; this.discoveredXboxs.splice(0, this.xboxsCount); this.xboxsCount = 0; - this.emit('connect', 'Connected.'); + this.emit('connected', 'Connected.'); const majorVersion = decodedMessage.majorVersion; const minorVersion = decodedMessage.minorVersion; const buildNumber = decodedMessage.buildNumber const firmwareRevision = `${majorVersion}.${minorVersion}.${buildNumber}`; - this.emit('devInfo', firmwareRevision); + this.emit('deviceInfo', firmwareRevision); }; if (this.currentApp != decodedMessage.apps[0].aumId) { @@ -459,7 +462,7 @@ class SMARTGLASS extends EventEmitter { }; this.titleId = appsArray[appsCount - 1].titleId; this.currentApp = appsArray[appsCount - 1].reference; - this.emit('change', decodedMessage, this.mediaState); + this.emit('stateChanged', decodedMessage, this.mediaState); }; }; }); @@ -472,7 +475,7 @@ class SMARTGLASS extends EventEmitter { const bootStartTime = (new Date().getTime()) / 1000; this.boot = setInterval(() => { - let powerOn = new Packer('simple.powerOn'); + const powerOn = new Packer('simple.powerOn'); powerOn.set('liveId', this.xboxLiveId); const message = powerOn.pack(); this.sendSocketMessage(message); @@ -502,7 +505,7 @@ class SMARTGLASS extends EventEmitter { if (this.isConnected) { this.emit('message', 'Send power Off.'); - let powerOff = new Packer('message.powerOff'); + const powerOff = new Packer('message.powerOff'); powerOff.set('liveId', this.xboxLiveId); const message = powerOff.pack(this); this.sendSocketMessage(message); @@ -525,7 +528,7 @@ class SMARTGLASS extends EventEmitter { if (this.isConnected && this.isAuthorized) { this.emit('debug', 'Send record game.'); - let recordGameDvr = new Packer('message.recordGameDvr'); + const recordGameDvr = new Packer('message.recordGameDvr'); recordGameDvr.set('startTimeDelta', -60); recordGameDvr.set('endTimeDelta', 0); const message = recordGameDvr.pack(this); @@ -547,7 +550,7 @@ class SMARTGLASS extends EventEmitter { this.emit('debug', 'Send command.'); if (channelIds[channelName] != this.channelRequestId) { - let channelRequest = new Packer('message.channelRequest'); + const channelRequest = new Packer('message.channelRequest'); channelRequest.set('channelRequestId', channelIds[channelName]); channelRequest.set('titleId', 0); channelRequest.set('service', Buffer.from(channelUuids[channelName], 'hex')); @@ -576,7 +579,9 @@ class SMARTGLASS extends EventEmitter { sendSocketMessage(message) { if (this.socket) { - this.socket.send(message, 0, message.length, 5050, this.host, (error, bytes) => { + const offset = 0; + const messageLength = message.length; + this.socket.send(message, offset, messageLength, 5050, this.host, (error, bytes) => { if (error) { this.emit('error', `Socket send message error: ${error}`); }; @@ -589,7 +594,7 @@ class SMARTGLASS extends EventEmitter { this.emit('debug', 'Disconnecting...'); clearInterval(this.checkConnection); - let disconnect = new Packer('message.disconnect'); + const disconnect = new Packer('message.disconnect'); disconnect.set('reason', 4); disconnect.set('errorCode', 0); const message = disconnect.pack(this); @@ -600,7 +605,7 @@ class SMARTGLASS extends EventEmitter { this.requestNum = 0; this.channelTargetId = null; this.channelRequestId = null; - this.emit('disconnect', 'Disconnected.'); + this.emit('disconnected', 'Disconnected.'); }, 3500); };