Version 5.0.0

This commit is contained in:
Chrystian Huot 2021-01-08 12:06:14 -05:00
parent 627fab3bcb
commit 61db573873
18 changed files with 754 additions and 610 deletions

View file

@ -1,3 +1,10 @@
# Version 5.0
- Add rdioScanner.options.autoPopulate which by default is true. The configuration file will now be automatically populated from new received calls with unknown system/talkgroup.
- Add rdioScanner.options.sortTalkgroupswhich by default is false. Sort talkgroups based on their ID.
- Remove default rdioScanner.systems for new installation, since now we have autoPopulate.
- Node modules update.
# Version 4.9
- Add basic duplicate call detection and rejection.

257
client/package-lock.json generated
View file

@ -1,29 +1,29 @@
{
"name": "rdio-scanner-client",
"version": "4.9.2",
"version": "5.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@angular-devkit/architect": {
"version": "0.1100.5",
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1100.5.tgz",
"integrity": "sha512-yOYfucNouc1doTbcGbCNMXGMSc36+j97XpdNoeGyzFQ7GwezLAro0a9gxc5PdOxndfelkND7J1JuOjxdW5O17A==",
"version": "0.1100.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1100.6.tgz",
"integrity": "sha512-4O+cg3AimI2bNAxxdu5NrqSf4Oa8r8xL0+G2Ycd3jLoFv0h0ecJiNKEG5F6IpTprb4aexZD6pcxBJCqQ8MmzWQ==",
"dev": true,
"requires": {
"@angular-devkit/core": "11.0.5",
"@angular-devkit/core": "11.0.6",
"rxjs": "6.6.3"
}
},
"@angular-devkit/build-angular": {
"version": "0.1100.5",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1100.5.tgz",
"integrity": "sha512-lJYsnBImBAqUAIVC2qGY64UaC2uWOPZEpSWjYUxkRZA/c4IVCJj3M12CgONBjtcKYzFVXc1eojhrScukGIJJcg==",
"version": "0.1100.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.1100.6.tgz",
"integrity": "sha512-HcqsWiSIUxExGg3HRQScLOmF+ckVkCKolfpPcNOCCpBYxH/i8n4wDGLBP5Rtxky+0Qz+3nnAaFIpNb9p9aUmbg==",
"dev": true,
"requires": {
"@angular-devkit/architect": "0.1100.5",
"@angular-devkit/build-optimizer": "0.1100.5",
"@angular-devkit/build-webpack": "0.1100.5",
"@angular-devkit/core": "11.0.5",
"@angular-devkit/architect": "0.1100.6",
"@angular-devkit/build-optimizer": "0.1100.6",
"@angular-devkit/build-webpack": "0.1100.6",
"@angular-devkit/core": "11.0.6",
"@babel/core": "7.12.3",
"@babel/generator": "7.12.1",
"@babel/plugin-transform-runtime": "7.12.1",
@ -31,7 +31,7 @@
"@babel/runtime": "7.12.1",
"@babel/template": "7.10.4",
"@jsdevtools/coverage-istanbul-loader": "3.0.5",
"@ngtools/webpack": "11.0.5",
"@ngtools/webpack": "11.0.6",
"ansi-colors": "4.1.1",
"autoprefixer": "9.8.6",
"babel-loader": "8.1.0",
@ -92,9 +92,9 @@
}
},
"@angular-devkit/build-optimizer": {
"version": "0.1100.5",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.5.tgz",
"integrity": "sha512-aKITFuiydR681eS1z84EIdOtqdxP/V5xGZuF3xjGmg5Ddwv36PweAHaCVJEB4btHSWH6uxMvW2hLXg2RTWbRNg==",
"version": "0.1100.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1100.6.tgz",
"integrity": "sha512-Qkq7n6510N+nXmfZqpqpI0I6Td+b+06RRNmS7KftSNJntU1z5QYh4FggwlthZ5P0QUT92cnBQsnT8OgYqGnwbg==",
"dev": true,
"requires": {
"loader-utils": "2.0.0",
@ -113,20 +113,20 @@
}
},
"@angular-devkit/build-webpack": {
"version": "0.1100.5",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1100.5.tgz",
"integrity": "sha512-oD5t2oCfyiCyyeZckrqBnQco94zIMkRnRGzy3lFDH7KMiL0DG9l7x3nxn9H0YunYWr55LsGWwXGoR7l03Kl+jw==",
"version": "0.1100.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1100.6.tgz",
"integrity": "sha512-kK0FlpYJHP25o1yzIGHQqIvO5kp+p6V5OwGpD2GGRZLlJqd3WdjY5DxnyZoX3/IofO6KsTnmm76fzTRqc62z/Q==",
"dev": true,
"requires": {
"@angular-devkit/architect": "0.1100.5",
"@angular-devkit/core": "11.0.5",
"@angular-devkit/architect": "0.1100.6",
"@angular-devkit/core": "11.0.6",
"rxjs": "6.6.3"
}
},
"@angular-devkit/core": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.5.tgz",
"integrity": "sha512-hwV8fjF8JNPJkiVWw8MNzeIfDo01aD/OAOlC4L5rQnVHn+i2EiU3brSDmFqyeHPPV3h/QjuBkS3tkN7gSnVWaQ==",
"version": "11.0.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-11.0.6.tgz",
"integrity": "sha512-nhvU5hH01r9qcexAqvIFU233treWWeW3ncs9UFYjD9Hys9sDSvqC3+bvGvl9vCG5FsyY7oDsjaVAipyUc+SFAg==",
"dev": true,
"requires": {
"ajv": "6.12.6",
@ -137,20 +137,20 @@
}
},
"@angular-devkit/schematics": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-11.0.5.tgz",
"integrity": "sha512-0NKGC8Nf/4vvDpWKB7bwxIazvNnNHnZBX6XlyBXNl+fW8tpTef3PNMJMSErTz9LFnuv61vsKbc36u/Ek2YChWg==",
"version": "11.0.6",
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-11.0.6.tgz",
"integrity": "sha512-hCyu/SSSiC6dKl/NxdWctknIrBqKR6pRe7DMArWowrZX6P9oi36LpKEFnKutE8+tXjsOqQj8XMBq9L64sXZWqg==",
"dev": true,
"requires": {
"@angular-devkit/core": "11.0.5",
"@angular-devkit/core": "11.0.6",
"ora": "5.1.0",
"rxjs": "6.6.3"
}
},
"@angular/animations": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-11.0.5.tgz",
"integrity": "sha512-ghE/xDTYuEWkKNZtioH9JBrSlux0MLHzWoE7tNP+XMaplt80lCm979vWsEBO3/xpQLRmRlGPul6RacCAoeqogg==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-11.0.7.tgz",
"integrity": "sha512-P3cluDGIsaj7vqvqIGW7xFCIXWa1lJDsHsmY3Fexk+ZVCncokftp5ZUANb2+DwOD3BPgd/WjBdXVjwzFQFsoVA==",
"requires": {
"tslib": "^2.0.0"
}
@ -165,16 +165,16 @@
}
},
"@angular/cli": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-11.0.5.tgz",
"integrity": "sha512-k4j/2z7qkuigJ1shH0McW1wW63clhrbrg98FK4/KWhU/sce5AgVjuHDQFycAclTwHesf7Vs6Gzt7zGlqUmeKIg==",
"version": "11.0.6",
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-11.0.6.tgz",
"integrity": "sha512-bwrXXyU23HjUlFl0CNCU+XMGa/enooqpMLcTAA15StVpKFHyaA4c57il/aqu+1IuB+zR6rGDzhAABuvRcHd+mQ==",
"dev": true,
"requires": {
"@angular-devkit/architect": "0.1100.5",
"@angular-devkit/core": "11.0.5",
"@angular-devkit/schematics": "11.0.5",
"@schematics/angular": "11.0.5",
"@schematics/update": "0.1100.5",
"@angular-devkit/architect": "0.1100.6",
"@angular-devkit/core": "11.0.6",
"@angular-devkit/schematics": "11.0.6",
"@schematics/angular": "11.0.6",
"@schematics/update": "0.1100.6",
"@yarnpkg/lockfile": "1.1.0",
"ansi-colors": "4.1.1",
"debug": "4.2.0",
@ -220,25 +220,25 @@
}
},
"@angular/common": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-11.0.5.tgz",
"integrity": "sha512-aoXdTkoni65LWhrPKNsAiOnO70XFaTaisO+K8ZYMpciMTTAxHx3hFCF9sj4a+Bo3M1a5UDjpsFDYMeGgJOkmFA==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/common/-/common-11.0.7.tgz",
"integrity": "sha512-9VuT9qrSP7Q91Wp276DDieCIZiTBrpLNoJzK/RygQShTymCVPg4Dsl3tQUKaHBPx9MexeqRG/HjN02DVpeqtsA==",
"requires": {
"tslib": "^2.0.0"
}
},
"@angular/compiler": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-11.0.5.tgz",
"integrity": "sha512-japxEn07P9z9FnW8ii+M5DIfgRAGNxl6QNQWKBkNo5ytN6iCAB7pVbJI0vn1AUT9TByV3+xDW/FNuoSuzsnX3w==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-11.0.7.tgz",
"integrity": "sha512-U+aGn6lP3iB184D2Z+OSK5vCwNtxtsF59T7nNJBMCCwcN7Qc5tfDBbSj1GI11XrIiuuoOxXbAp9BKS0dAyNCWw==",
"requires": {
"tslib": "^2.0.0"
}
},
"@angular/compiler-cli": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-11.0.5.tgz",
"integrity": "sha512-1EbnDdK2Em9xpnbLCjw+9w2F0I6gl5AS6QAn03ztYX9ZooNzCeC6sT8qghzrNTFTV89nyIoAqyMtgcLS6udVkg==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-11.0.7.tgz",
"integrity": "sha512-04agqIPmw1exMeZjJmRzeYFgTEXYJ7gKD8TZipsGlu99uU/NQJIsetpzR7/bhPAKDH6YO0p/uavxV0nRpSTIQw==",
"dev": true,
"requires": {
"@babel/core": "^7.8.6",
@ -346,17 +346,17 @@
}
},
"@angular/core": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-11.0.5.tgz",
"integrity": "sha512-XAXWQi7R3ucZXQwx9QK5jSKJeQyRJ53u2dQDpr7R5stzeCy1a5hrNOkZLg9zOTTPcth/6+FrOrRZP9SMdxtw3w==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/core/-/core-11.0.7.tgz",
"integrity": "sha512-Kj5uRZoK5+xfMTjkP3tw8oIF5hKTnoF9Bwh5m9GUKqg1wHVKOJcT5JBIEMc8qPyiFgALREA01reIzQdGMjX36A==",
"requires": {
"tslib": "^2.0.0"
}
},
"@angular/forms": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-11.0.5.tgz",
"integrity": "sha512-2zB1IuqYNJrjh7Og9J8f/AtjX3NHc3VVbt0rPw35ghqIU3aQLpOichdQ1y5QvMWic1UzZ7SjWXDU7RpKbm4iUA==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-11.0.7.tgz",
"integrity": "sha512-+3A+SciMyHTdUwkKUz4XzC1DSYexQEbFLe0PKQIFSFOROmbssjnWJv7yO2HbzCpGa7oGKPYNlE5twYWyLxpvFg==",
"requires": {
"tslib": "^2.0.0"
}
@ -370,25 +370,25 @@
}
},
"@angular/platform-browser": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-11.0.5.tgz",
"integrity": "sha512-173JZHF3QS78hEscBxFZ/kX8KLjdaDhfAYi4Sh8daIKNUcDcyhqEy7wpAjWmCwdspL1QUtWKCrhZqrEVNGTpvA==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-11.0.7.tgz",
"integrity": "sha512-W8Wt8jMUjcbpqGtqrNWAj0p7CLdjOxgVlbrgBXTbaoqdchvXH85YzGr7ohA3MuE61H90OcVK9OhfYQk5o6joSg==",
"requires": {
"tslib": "^2.0.0"
}
},
"@angular/platform-browser-dynamic": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.5.tgz",
"integrity": "sha512-MFjpQcqkHOu8iTUMKVG6vfuOHwrRlgPBvkNucEbtXhTTYNlsw2mprxfUODYEu26EBUAh+FGttu8ZjclUGw4bVg==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.0.7.tgz",
"integrity": "sha512-pUXCum1Z2DZV/34WR4Vfmkc5nWxbmVdwAA9pXbAarwAYqHIqOzX8rpRaHsuHBAR+SK+VH+xjproeLgsVfV8FSA==",
"requires": {
"tslib": "^2.0.0"
}
},
"@angular/service-worker": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-11.0.5.tgz",
"integrity": "sha512-5H3wJD9vQzhJqNes5N9fKmJp7ftv7UlqJZHewbwfZKd3xta7+mHXGFelMIdzsvb0WGkqPrW1mUgL0sIQ9DYKOg==",
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-11.0.7.tgz",
"integrity": "sha512-b8OaHvWqz2roaeo+f77ZA9n+OJkuDQzRNyXIs9GaUYc+nEwhXuXzHnjM9f48clvhPXAeQApgf9c121beiEbRig==",
"requires": {
"tslib": "^2.0.0"
}
@ -1514,39 +1514,39 @@
}
},
"@ngtools/webpack": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.0.5.tgz",
"integrity": "sha512-hM0LdOSlC6c7ij+BvIpAFbe7dpJhL+A51L5v6YbMA6aM0Sb/y+HpE2u34AHEQvute7cLe4EyOyvJ9jSinVAJhQ==",
"version": "11.0.6",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-11.0.6.tgz",
"integrity": "sha512-vf5YNEpXWRa0fKC/BRq5sVVj2WnEqW8jn14YQRHwVt5ppUeyu8IKUF69p6W1MwZMgMqMaw/vPQ8LI5cFbyf3uw==",
"dev": true,
"requires": {
"@angular-devkit/core": "11.0.5",
"@angular-devkit/core": "11.0.6",
"enhanced-resolve": "5.3.1",
"webpack-sources": "2.0.1"
}
},
"@nodelib/fs.scandir": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
"integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==",
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
"integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==",
"dev": true,
"requires": {
"@nodelib/fs.stat": "2.0.3",
"@nodelib/fs.stat": "2.0.4",
"run-parallel": "^1.1.9"
}
},
"@nodelib/fs.stat": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz",
"integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==",
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz",
"integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==",
"dev": true
},
"@nodelib/fs.walk": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz",
"integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==",
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz",
"integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==",
"dev": true,
"requires": {
"@nodelib/fs.scandir": "2.1.3",
"@nodelib/fs.scandir": "2.1.4",
"fastq": "^1.6.0"
}
},
@ -1568,24 +1568,24 @@
}
},
"@schematics/angular": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-11.0.5.tgz",
"integrity": "sha512-7p2wweoJYhim8YUy3ih1SrPGqRsa6+aEFbYgo9v4zt7b3tOva8SvkbC2alayK74fclzQ7umqa6xAwvWhy8ORvg==",
"version": "11.0.6",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-11.0.6.tgz",
"integrity": "sha512-XUcpOrlcp55PBHrgpIVx69lnhDY6ro35BSRmqNmjXik56qcOkfvdki8vvyW9EsWvu9/sfBSsVDdparlbVois7w==",
"dev": true,
"requires": {
"@angular-devkit/core": "11.0.5",
"@angular-devkit/schematics": "11.0.5",
"@angular-devkit/core": "11.0.6",
"@angular-devkit/schematics": "11.0.6",
"jsonc-parser": "2.3.1"
}
},
"@schematics/update": {
"version": "0.1100.5",
"resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1100.5.tgz",
"integrity": "sha512-BYtKKuiWsrlc4FMW3bRyl4tm6lWNMTi8oql/mtkSgH7V5eMmaLDJtM+zDl+qyC/KHPxbHTfoHDapfv1tITSWjA==",
"version": "0.1100.6",
"resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.1100.6.tgz",
"integrity": "sha512-+B8n+k+zZ3VYOhjNBsLqzjp8O9ZdUWgdpf9L8XAA7mh/oPwufXpExyEc66uAS07imvUMmjz6i8E2eNWV/IjBJg==",
"dev": true,
"requires": {
"@angular-devkit/core": "11.0.5",
"@angular-devkit/schematics": "11.0.5",
"@angular-devkit/core": "11.0.6",
"@angular-devkit/schematics": "11.0.6",
"@yarnpkg/lockfile": "1.1.0",
"ini": "1.3.6",
"npm-package-arg": "^8.0.0",
@ -2566,16 +2566,16 @@
}
},
"browserslist": {
"version": "4.16.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz",
"integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==",
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz",
"integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001165",
"caniuse-lite": "^1.0.30001173",
"colorette": "^1.2.1",
"electron-to-chromium": "^1.3.621",
"electron-to-chromium": "^1.3.634",
"escalade": "^3.1.1",
"node-releases": "^1.1.67"
"node-releases": "^1.1.69"
}
},
"buffer": {
@ -2734,9 +2734,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001170",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz",
"integrity": "sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==",
"version": "1.0.30001173",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001173.tgz",
"integrity": "sha512-R3aqmjrICdGCTAnSXtNyvWYMK3YtV5jwudbq0T7nN9k4kmE4CBuwPqyJ+KBzepSTh0huivV2gLbSMEzTTmfeYw==",
"dev": true
},
"canonical-path": {
@ -2769,19 +2769,28 @@
"dev": true
},
"chokidar": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
"integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.0.tgz",
"integrity": "sha512-JgQM9JS92ZbFR4P90EvmzNpSGhpPBGBSj10PILeDyYFwp4h2/D9OM03wsJ4zW1fEp4ka2DGrnUeD7FuvQ2aZ2Q==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
},
"dependencies": {
"fsevents": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
"integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
"dev": true,
"optional": true
}
}
},
"chownr": {
@ -3307,12 +3316,12 @@
"dev": true
},
"core-js-compat": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.1.tgz",
"integrity": "sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ==",
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.2.tgz",
"integrity": "sha512-LO8uL9lOIyRRrQmZxHZFl1RV+ZbcsAkFWTktn5SmH40WgLtSNYN4m4W2v9ONT147PxBY/XrRhrWq8TlvObyUjQ==",
"dev": true,
"requires": {
"browserslist": "^4.15.0",
"browserslist": "^4.16.0",
"semver": "7.0.0"
},
"dependencies": {
@ -4049,9 +4058,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.3.633",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz",
"integrity": "sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==",
"version": "1.3.634",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.634.tgz",
"integrity": "sha512-QPrWNYeE/A0xRvl/QP3E0nkaEvYUvH3gM04ZWYtIa6QlSpEetRlRI1xvQ7hiMIySHHEV+mwDSX8Kj4YZY6ZQAw==",
"dev": true
},
"elliptic": {
@ -5007,9 +5016,9 @@
"dev": true
},
"globby": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz",
"integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==",
"version": "11.0.2",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
"integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
"dev": true,
"requires": {
"array-union": "^2.1.0",
@ -6622,18 +6631,18 @@
"dev": true
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
"integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
"dev": true
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"version": "2.1.28",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
"integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
"dev": true,
"requires": {
"mime-db": "1.44.0"
"mime-db": "1.45.0"
}
},
"mimic-fn": {
@ -6963,9 +6972,9 @@
}
},
"node-releases": {
"version": "1.1.67",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz",
"integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==",
"version": "1.1.69",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz",
"integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==",
"dev": true
},
"normalize-package-data": {
@ -10331,9 +10340,9 @@
"dev": true
},
"tar": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz",
"integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
"integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
"dev": true,
"requires": {
"chownr": "^2.0.0",

View file

@ -1,24 +1,24 @@
{
"author": "Chrystian Huot <chrystian.huot@saubeo.solutions>",
"dependencies": {
"@angular/animations": "^11.0.5",
"@angular/animations": "^11.0.7",
"@angular/cdk": "^11.0.3",
"@angular/common": "~11.0.5",
"@angular/compiler": "~11.0.5",
"@angular/core": "~11.0.5",
"@angular/forms": "~11.0.5",
"@angular/common": "~11.0.7",
"@angular/compiler": "~11.0.7",
"@angular/core": "~11.0.7",
"@angular/forms": "~11.0.7",
"@angular/material": "^11.0.3",
"@angular/platform-browser": "~11.0.5",
"@angular/platform-browser-dynamic": "~11.0.5",
"@angular/service-worker": "~11.0.5",
"@angular/platform-browser": "~11.0.7",
"@angular/platform-browser-dynamic": "~11.0.7",
"@angular/service-worker": "~11.0.7",
"rxjs": "~6.6.3",
"tslib": "^2.1.0",
"zone.js": "~0.11.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1100.5",
"@angular/cli": "^11.0.5",
"@angular/compiler-cli": "~11.0.5",
"@angular-devkit/build-angular": "~0.1100.6",
"@angular/cli": "^11.0.6",
"@angular/compiler-cli": "~11.0.7",
"@types/node": "~14.14.20",
"codelyzer": "^6.0.1",
"ts-node": "~9.1.1",
@ -32,5 +32,5 @@
"build": "ng build --base-href ./ --prod",
"start": "ng serve"
},
"version": "4.9.2"
"version": "5.0.0"
}

View file

@ -880,11 +880,11 @@ export class AppRdioScannerService implements OnDestroy {
this.groups = Object.keys(this.config.groups || []).map((label) => {
const allOff = Object.keys(this.config.groups[label]).map((sys) => +sys)
.every((sys: number) => this.config.groups[label] && this.config.groups[label][sys]
.every((tg) => !this.livefeedMap[sys][tg]));
.every((tg) => this.livefeedMap[sys] && !this.livefeedMap[sys][tg]));
const allOn = Object.keys(this.config.groups[label]).map((sys) => +sys)
.every((sys: number) => this.config.groups[label] && this.config.groups[label][sys]
.every((tg) => this.livefeedMap[sys][tg]));
.every((tg) => this.livefeedMap[sys] && this.livefeedMap[sys][tg]));
const status = allOff ? RdioScannerGroupStatus.Off : allOn ? RdioScannerGroupStatus.On : RdioScannerGroupStatus.Partial;
@ -955,10 +955,6 @@ export class AppRdioScannerService implements OnDestroy {
if (Array.isArray(this.config?.systems)) {
call.systemData = this.config.systems.find((system) => system.id === call.system);
if (!call.systemData) {
console.log(call.system, call.systemData);
}
if (Array.isArray(call.systemData?.talkgroups)) {
call.talkgroupData = call.systemData?.talkgroups.find((talkgroup) => talkgroup.id === call.talkgroup);
}

View file

@ -1,4 +1,4 @@
<fieldset class="fieldset">
<fieldset *ngIf="groups?.length && (groups?.length || 0) >= 2" class="fieldset">
<div>
<button *ngFor="let group of groups" class="rdio-button" [ngClass]="group.status"
(click)="toggleGroup(group.label)">

View file

@ -55,6 +55,11 @@ This file is at the heart of [Rdio Scanner](https://github.com/chuot/rdio-scanne
// (object) Options definitions
"options": {
// (boolean) Allows the automatic creation of systems/talkgroups not configured
// in the configuration file.
// Default value is true milliseconds
"autoPopulate": true,
// (number) Delay in milliseconds before turning off the screen backlight when inactive
// Default value is 5000 milliseconds
"dimmerDelay": 5000,
@ -76,6 +81,10 @@ This file is at the heart of [Rdio Scanner](https://github.com/chuot/rdio-scanne
// Default value is 7
// Specifying a value of 0 will disable this feature
"pruneDays": 7,
// (boolean) Sort talkgroups by their id
// Default value is false
"sortTalkgroups": false
}
// (object[]) Systems definitions
@ -348,7 +357,7 @@ Default value is an empty array `[]` .
- Ingest audio files from **SDRTrunk**
> Note that **System name** on SDRTrunk **must match** the **system.label** in your configuration.
> Note that **System name** on SDRTrunk **must match** the **system.label** in your configuration. If no match is found and if the `autoPopulate` option is enabled, then a new system will be created with the frequency of the control channel frequency as the system.id. It is therefore preferable to preconfigure the system with the correct system.id and system.label.
```json
"dirWatch": [
@ -608,7 +617,7 @@ Setting `options.keypadBeeps` to `2` set the keypadBeeps to Whistler style. It i
## Systems - rdioScanner.systems
The heart of [Rdio Scanner](https://github.com/chuot/rdio-scanner) where all your systems and talkgroups are defined. Audio files to unknown systems / talkgroups will not be ingested.
The heart of [Rdio Scanner](https://github.com/chuot/rdio-scanner) where all your systems and talkgroups are defined. Audio files to unknown systems / talkgroups will not be ingested unless `rdioScanner.options.autoPopulate` is true.
**Definitions of the rdioScanner.systems object**

View file

@ -0,0 +1,333 @@
{
"nodejs": {
"env": "production",
"host": "0.0.0.0",
"port": 3000,
"sslCA": null,
"sslCert": null,
"sslKey": null
},
"rdioScanner": {
"access": null,
"apiKeys": "d2079382-07df-4aa9-8940-8fb9e4ef5f2e",
"dirWatch": [],
"downstreams": [],
"options": {
"autoPopulate": true,
"dimmerDelay": 5000,
"disableAudioConversion": false,
"disableKeyboardShortcuts": false,
"keypadBeeps": 1,
"pruneDays": 7,
"sortTalkgroups": false
},
"systems": [
{
"id": 11,
"label": "RSP25MTL1",
"talkgroups": [
{
"group": "FIRE DISPATCH",
"id": 54241,
"label": "TDB A1",
"name": "MRC TDB Fire Alpha 1",
"tag": "Fire Dispatch"
},
{
"group": "FIRE TAC",
"id": 54242,
"label": "TDB B1",
"name": "MRC TDB Fire Bravo 1",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54243,
"label": "TDB B2",
"name": "MRC TDB Fire Bravo 2",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54248,
"label": "TDB B3",
"name": "MRC TDB Fire Bravo 3",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54251,
"label": "TDB B4",
"name": "MRC TDB Fire Bravo 4",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54261,
"label": "TDB B5",
"name": "MRC TDB Fire Bravo 5",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54244,
"label": "TDB B6",
"name": "MRC TDB Fire Bravo 6",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54129,
"label": "TDB B7",
"name": "MRC TDB Fire Bravo 7",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 54125,
"label": "TDB B8",
"name": "MRC TDB Fire Bravo 8",
"tag": "Fire Tac"
}
],
"units": [
{
"id": 4424001,
"label": "CAUCA"
}
]
},
{
"id": 21,
"label": "SERAM",
"talkgroups": [
{
"group": "FIRE DISPATCH",
"id": 60040,
"label": "GENERAL",
"name": "SERAM General",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 60041,
"label": "REPART",
"name": "SERAM Repartition",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50001,
"label": "SG 1",
"name": "SERAM Regroupement 1",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50002,
"label": "SG 2",
"name": "SERAM Regroupement 2",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50003,
"label": "SG 3",
"name": "SERAM Regroupement 3",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50004,
"label": "SG 4",
"name": "SERAM Regroupement 4",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50005,
"label": "SG 5",
"name": "SERAM Regroupement 5",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50006,
"label": "SG 6",
"name": "SERAM Regroupement 6",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50007,
"label": "SG 7",
"name": "SERAM Regroupement 7",
"tag": "Fire Dispatch"
},
{
"group": "FIRE DISPATCH",
"id": 50008,
"label": "SG 8",
"name": "SERAM Regroupement 8",
"tag": "Fire Dispatch"
},
{
"group": "FIRE TAC",
"id": 60051,
"label": "CMD 3",
"name": "SERAM Commandement 3",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60052,
"label": "CMD 4",
"name": "SERAM Commandement 4",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60053,
"label": "CMD 5",
"name": "SERAM Commandement 5",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60054,
"label": "CMD 6",
"name": "SERAM Commandement 6",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60055,
"label": "CMD 7",
"name": "SERAM Commandement 7",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60056,
"label": "CMD 8",
"name": "SERAM Commandement 8",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60059,
"label": "CMD 11",
"name": "SERAM Commandement 11",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60091,
"label": "CMD 12",
"name": "SERAM Commandement 12",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60092,
"label": "CMD 13",
"name": "SERAM Commandement 13",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60057,
"label": "CMD 14",
"name": "SERAM Commandement 14",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60061,
"label": "OPS 3",
"name": "SERAM Operations 3",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60062,
"label": "OPS 4",
"name": "SERAM Operations 4",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60063,
"label": "OPS 5",
"name": "SERAM Operations 5",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60064,
"label": "OPS 6",
"name": "SERAM Operations 6",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60065,
"label": "OPS 7",
"name": "SERAM Operations 7",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60066,
"label": "OPS 8",
"name": "SERAM Operations 8",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60069,
"label": "OPS 11",
"name": "SERAM Operations 11",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60093,
"label": "OPS 12",
"name": "SERAM Operations 12",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60094,
"label": "OPS 13",
"name": "SERAM Operations 13",
"tag": "Fire Tac"
},
{
"group": "FIRE TAC",
"id": 60067,
"label": "OPS 14",
"name": "SERAM Operations 14",
"tag": "Fire Tac"
}
],
"units": [
{
"id": 702099,
"label": "DISPATCH"
}
]
}
]
},
"sequelize": {
"database": null,
"dialect": "sqlite",
"host": null,
"password": null,
"port": null,
"storage": "database.sqlite",
"username": null
}
}

View file

@ -45,9 +45,7 @@ $ ls -l ~/.rdio-scanner
# 3. Configure Rdio Scanner
The `config.json` is preloaded with 2 systems, which you probably don't want. They just serve as an example and can be replaced with new ones as desired.
> Read the documentation [docs/config.md](./config.md) for an explanation of all configurable parameters.
Read the documentation [docs/config.md](./config.md) for an explanation of all configurable parameters.
If your [Rdio Scanner](https://github.com/chuot/rdio-scanner) is already running, be sure to restart it every time you make changes to the `config.json` file.

View file

@ -66,9 +66,7 @@ $ DEBUG=true node run init
# 3. Configure Rdio Scanner
The `server/config.json` is preloaded with 2 systems, which you probably don't want. They just serve as an example and can be replaced with new ones as desired.
> Read the documentation [docs/config.md](./config.md) for an explanation of all configurable parameters.
Read the documentation [docs/config.md](./config.md) for an explanation of all configurable parameters.
If your [Rdio Scanner](https://github.com/chuot/rdio-scanner) is already running, be sure to restart it every time you make changes to the `server/config.json` file.

View file

@ -6,9 +6,9 @@
"private": true,
"scripts": {
"build": "docker build --tag chuot/rdio-scanner:latest .",
"buildx": "docker buildx build --cache-from type=local,src=dist --cache-to type=local,dest=dist --platform linux/amd64,linux/arm64/v8,linux/arm/v7,linux/arm/v6,linux/ppc64le,linux/s390x --push --tag docker.io/chuot/rdio-scanner:latest .",
"buildx": "docker buildx build --cache-from type=local,src=dist --cache-to type=local,dest=dist --platform linux/amd64,linux/arm64/v8,linux/arm/v7,linux/arm/v6,linux/ppc64le,linux/s390x --push --tag ${REGISTRY:-docker.io}/chuot/rdio-scanner:latest .",
"start": "node run",
"update": "node update"
},
"version": "4.9.2"
"version": "5.0.0"
}

View file

@ -90,9 +90,7 @@ class App {
config.sequelize.port = config.sequelize.port || process.env.DB_PORT || null;
if (config.sequelize.dialect === 'sqlite') {
config.sequelize.storage = config.sequelize.storage
? path.resolve(__dirname, config.sequelize.storage)
: path.resolve(process.env.APP_DATA || process.env.DB_STORAGE || __dirname, 'database.sqlite');
config.sequelize.storage = config.sequelize.storage ? config.sequelize.storage : 'database.sqlite';
} else {
config.sequelize.storage = null;
@ -184,7 +182,12 @@ class App {
this.httpServer = http.createServer(this.router);
}
this.sequelize = new Sequelize(Object.assign({}, { logging: false, }, this.config.sequelize));
this.sequelize = new Sequelize(Object.assign({}, {
logging: false,
storage: this.config.sequelize.storage
? path.resolve(process.env.APP_DATA || process.env.DB_STORAGE || __dirname, this.config.sequelize.storage)
: '',
}, this.config.sequelize));
this.rdioScanner = new RdioScanner(this);

View file

@ -29,6 +29,8 @@ const uuid = require('uuid');
const defaults = require('./defaults');
const WebSocket = require('./websocket');
const maxAuthenticationTries = 3;
const wsCommand = {
@ -49,6 +51,8 @@ class Controller extends EventEmitter {
this.setMaxListeners(0);
this.app = ctx.app;
this.config = parseConfig(ctx.config);
this.groups = {};
@ -57,6 +61,61 @@ class Controller extends EventEmitter {
this.tags = {};
this.websocket = null;
this.ffmpeg = !spawnSync('ffmpeg', ['-version']).error;
if (!this.ffmpeg) {
console.warn('ffmpeg is missing, no audio conversion possible.');
}
if (this.config.options.pruneDays > 0) {
this.pruneInterval = setInterval(() => {
const now = new Date();
this.models.call.destroy({
where: {
dateTime: {
[Op.lt]: new Date(now.getFullYear(), now.getMonth(), now.getDate() - this.config.options.pruneDays),
},
},
});
}, 15 * 60 * 1000);
}
this.buildGroupsAndTags();
}
authenticate(token) {
const parse = (doc) => {
if (!this.isAccessRestricted) {
return true;
} else if (Array.isArray(doc)) {
return doc.map((acc) => parse(acc)).some((acc) => acc);
} else if (doc !== null && typeof doc === 'object') {
return doc.code === token;
} else {
return doc === token;
}
}
return parse(this.config.access);
}
broadcastConfig() {
if (this.websocket) {
this.websocket.getSockets().forEach(async (socket) => {
socket.scope = this.getScope(socket.token);
socket.send(JSON.stringify([wsCommand.config, this.getConfig(socket.scope)]));
})
}
}
buildGroupsAndTags() {
this.config.systems.forEach((system) => {
system.talkgroups.forEach((talkgroup) => {
if (!this.groups[talkgroup.group]) {
@ -84,45 +143,6 @@ class Controller extends EventEmitter {
}
})
});
this.ffmpeg = !spawnSync('ffmpeg', ['-version']).error;
if (!this.ffmpeg) {
console.warn('ffmpeg is missing, no audio conversion possible.');
}
if (this.config.options.pruneDays > 0) {
this.pruneInterval = setInterval(() => {
const now = new Date();
this.models.call.destroy({
where: {
dateTime: {
[Op.lt]: new Date(now.getFullYear(), now.getMonth(), now.getDate() - this.config.options.pruneDays),
},
},
});
}, 15 * 60 * 1000);
}
}
authenticate(token) {
const parse = (doc) => {
if (!this.isAccessRestricted) {
return true;
} else if (Array.isArray(doc)) {
return doc.map((acc) => parse(acc)).some((acc) => acc);
} else if (doc !== null && typeof doc === 'object') {
return doc.code === token;
} else {
return doc === token;
}
}
return parse(this.config.access);
}
convertCallAudio(call = {}) {
@ -294,15 +314,15 @@ class Controller extends EventEmitter {
return { count, dateStart, dateStop, options, results };
}
async getConfig(scope) {
getConfig(scope) {
return Object.assign({}, this.getOptions(), {
groups: this.getGroups(scope),
systems: await this.getSystems(scope),
systems: this.getSystems(scope),
tags: this.getTags(scope),
});
}
getGroups(scope = {}) {
getGroups(scope) {
if (scope !== null && typeof scope === 'object') {
return Object.keys(this.groups).reduce((groups, group) => {
Object.keys(this.groups[group]).forEach((system) => {
@ -425,27 +445,18 @@ class Controller extends EventEmitter {
}, {});
}
async getSystems(scope = {}) {
getSystems(scope) {
if (scope !== null && typeof scope === 'object') {
const systems = await this.models.system.findAll({
where: {
id: {
[Op.in]: Object.keys(scope),
},
},
});
const sysIds = Object.keys(scope).map((id) => +id);
return systems.map((system) => (system.talkgroups = system.talkgroups
.filter((tg) => scope[system.id].includes(tg.id))) && system);
return this.config.systems.filter((sys) => sysIds.includes(sys.id));
} else {
const systems = await this.models.system.findAll();
return systems;
return this.config.systems;
}
}
getTags(scope = {}) {
getTags(scope) {
if (scope !== null && typeof scope === 'object') {
return Object.keys(this.tags).reduce((tags, tag) => {
Object.keys(this.tags[tag]).forEach((system) => {
@ -472,10 +483,12 @@ class Controller extends EventEmitter {
}
}
async importCall(call = {}) {
const system = this.config.systems.find((sys) => sys.id === call.system);
async importCall(call = {}, meta) {
meta = meta !== null && typeof meta === 'object' ? meta : {};
const talkgroup = Array.isArray(system && system.talkgroups) ? system.talkgroups.find((tg) => {
let system = this.config.systems.find((sys) => sys.id === call.system);
let talkgroup = Array.isArray(system && system.talkgroups) ? system.talkgroups.find((tg) => {
if (tg.id === call.talkgroup) {
return true;
@ -489,6 +502,51 @@ class Controller extends EventEmitter {
}
}) : null;
if (this.config.options.autoPopulate) {
let populated = false;
if (!system && call.system) {
populated = true;
system = {
id: call.system,
label: meta.systemLabel || `System ${call.system}`,
talkgroups: [],
units: [],
};
this.config.systems.push(system);
this.config.systems.sort((a, b) => a.id - b.id);
}
if (!talkgroup && call.talkgroup) {
populated = true;
talkgroup = {
group: 'Unknown',
id: call.talkgroup,
label: `${call.talkgroup}`,
name: `Talkgroup ${call.talkgroup}`,
tag: 'untagged'
};
system.talkgroups.push(talkgroup);
if (this.config.options.sortTalkgroups) {
system.talkgroups.sort((a, b) => a.id - b.id);
}
this.buildGroupsAndTags();
}
if (populated) {
this.app.config.persist();
this.broadcastConfig();
}
}
if (!system || !talkgroup) {
console.log(`NewCall: system=${call.system || 'unknown'} talkgroup=${call.talkgroup || 'unknown'} `
+ `file=${call.audioName} No matching system/talkgroup`);
@ -596,7 +654,7 @@ class Controller extends EventEmitter {
socket.send(JSON.stringify(response));
} else if (message[0] === wsCommand.config) {
socket.send(JSON.stringify([wsCommand.config, await this.getConfig(socket.scope)]));
socket.send(JSON.stringify([wsCommand.config, this.getConfig(socket.scope)]));
} else if (message[0] === wsCommand.listCall) {
socket.send(JSON.stringify([wsCommand.listCall, await this.getCalls(message[1], socket.scope)]));
@ -656,7 +714,7 @@ class Controller extends EventEmitter {
socket.send(JSON.stringify([wsCommand.livefeedMap, returnStatus]));
} else if (message[0] === wsCommand.pin) {
const token = Buffer.from(message[1], 'base64').toString();
socket.token = Buffer.from(message[1], 'base64').toString();
if (typeof socket.authCount !== 'number') {
socket.authCount = 1;
@ -669,22 +727,22 @@ class Controller extends EventEmitter {
socket.send(JSON.stringify([wsCommand.pin]));
} else {
socket.isAuthenticated = this.authenticate(token);
socket.isAuthenticated = this.authenticate(socket.token);
if (socket.isAuthenticated) {
socket.authCount = 0;
} else if (socket.authCount === maxAuthenticationTries) {
console.log(`Authentication: token=${token} Locked`);
console.log(`Authentication: token=${socket.token} Locked`);
} else {
console.log(`Authentication: token=${token} Failed`);
console.log(`Authentication: token=${socket.token} Failed`);
}
socket.scope = this.getScope(token);
socket.scope = this.getScope(socket.token);
if (socket.isAuthenticated) {
socket.send(JSON.stringify([wsCommand.config, await this.getConfig(socket.scope)]));
socket.send(JSON.stringify([wsCommand.config, this.getConfig(socket.scope)]));
} else {
socket.send(JSON.stringify([wsCommand.pin]));
@ -694,17 +752,30 @@ class Controller extends EventEmitter {
}
}
validateApiKey(apiKey, system, talkgroup) {
const scope = this.getScope(apiKey, this.config.apiKeys);
registerWebSocket(websocket) {
if (websocket instanceof WebSocket) {
this.websocket = websocket;
}
}
return Array.isArray(scope[system]) && (
scope[system].includes(talkgroup) ||
this.config.systems.some((sys) => {
return sys.id === system && sys.talkgroups.some((tg) => {
return Array.isArray(tg.patches) && tg.patches.includes(talkgroup);
validateApiKey(apiKey, system, talkgroup) {
if (typeof apiKey === 'string' && apiKey === this.config.apiKeys) {
return true;
} else if (Array.isArray(this.config.apiKeys) && this.config.apiKeys.includes(apiKey)) {
return true;
} else {
const scope = this.getScope(apiKey, this.config.apiKeys);
return Array.isArray(scope[system]) && (
scope[system].includes(talkgroup) || this.config.systems.some((sys) => {
return sys.id === system && sys.talkgroups.some((tg) => {
return Array.isArray(tg.patches) && tg.patches.includes(talkgroup);
})
})
})
);
);
}
}
}
@ -729,6 +800,8 @@ function parseConfig(config) {
delete config.allowDownload;
}
config.options.autoPopulate = typeof config.options.autoPopulate === 'boolean' ? config.options.autoPopulate : true;
config.options.dimmerDelay = typeof config.options.dimmerDelay === 'number' && config.options.dimmerDelay > 0
? config.options.dimmerDelay : 5000;
@ -824,6 +897,8 @@ function parseConfig(config) {
delete config.pruneDays;
}
config.options.sortTalkgroups = typeof config.options.sortTalkgroups === 'boolean' ? config.options.sortTalkgroups : false;
if (config.options.useDimmer !== undefined) {
delete config.options.useDimmer;
}

View file

@ -104,301 +104,7 @@ const defaults = {
],
},
},
systems: [{
id: 11,
label: 'RSP25MTL1',
talkgroups: [
{
id: 54241,
label: 'TDB A1',
name: 'MRC TDB Fire Alpha 1',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 54242,
label: 'TDB B1',
name: 'MRC TDB Fire Bravo 1',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54243,
label: 'TDB B2',
name: 'MRC TDB Fire Bravo 2',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54248,
label: 'TDB B3',
name: 'MRC TDB Fire Bravo 3',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54251,
label: 'TDB B4',
name: 'MRC TDB Fire Bravo 4',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54261,
label: 'TDB B5',
name: 'MRC TDB Fire Bravo 5',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54244,
label: 'TDB B6',
name: 'MRC TDB Fire Bravo 6',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54129,
label: 'TDB B7',
name: 'MRC TDB Fire Bravo 7',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 54125,
label: 'TDB B8',
name: 'MRC TDB Fire Bravo 8',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
],
units: [
{
id: 4424001,
label: 'CAUCA',
},
],
},
{
id: 21,
label: 'SERAM',
talkgroups: [
{
id: 60040,
label: 'GENERAL',
name: 'SERAM General',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 60041,
label: 'REPART',
name: 'SERAM Repartition',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50001,
label: 'SG 1',
name: 'SERAM Regroupement 1',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50002,
label: 'SG 2',
name: 'SERAM Regroupement 2',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50003,
label: 'SG 3',
name: 'SERAM Regroupement 3',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50004,
label: 'SG 4',
name: 'SERAM Regroupement 4',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50005,
label: 'SG 5',
name: 'SERAM Regroupement 5',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50006,
label: 'SG 6',
name: 'SERAM Regroupement 6',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50007,
label: 'SG 7',
name: 'SERAM Regroupement 7',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 50008,
label: 'SG 8',
name: 'SERAM Regroupement 8',
tag: 'Fire Dispatch',
group: 'FIRE DISPATCH',
},
{
id: 60051,
label: 'CMD 3',
name: 'SERAM Commandement 3',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60052,
label: 'CMD 4',
name: 'SERAM Commandement 4',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60053,
label: 'CMD 5',
name: 'SERAM Commandement 5',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60054,
label: 'CMD 6',
name: 'SERAM Commandement 6',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60055,
label: 'CMD 7',
name: 'SERAM Commandement 7',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60056,
label: 'CMD 8',
name: 'SERAM Commandement 8',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60059,
label: 'CMD 11',
name: 'SERAM Commandement 11',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60091,
label: 'CMD 12',
name: 'SERAM Commandement 12',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60092,
label: 'CMD 13',
name: 'SERAM Commandement 13',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60057,
label: 'CMD 14',
name: 'SERAM Commandement 14',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60061,
label: 'OPS 3',
name: 'SERAM Operations 3',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60062,
label: 'OPS 4',
name: 'SERAM Operations 4',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60063,
label: 'OPS 5',
name: 'SERAM Operations 5',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60064,
label: 'OPS 6',
name: 'SERAM Operations 6',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60065,
label: 'OPS 7',
name: 'SERAM Operations 7',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60066,
label: 'OPS 8',
name: 'SERAM Operations 8',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60069,
label: 'OPS 11',
name: 'SERAM Operations 11',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60093,
label: 'OPS 12',
name: 'SERAM Operations 12',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60094,
label: 'OPS 13',
name: 'SERAM Operations 13',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
{
id: 60067,
label: 'OPS 14',
name: 'SERAM Operations 14',
tag: 'Fire Tac',
group: 'FIRE TAC',
},
],
units: [{
id: 702099,
label: 'DISPATCH',
}],
}],
systems: [],
};
module.exports = defaults;

View file

@ -173,7 +173,7 @@ class DirWatch {
}, dirWatch.delay);
watcher.on('raw', (_, filename, details) => {
filename = details.watchedPath.indexOf(filename) === -1
filename = details.watchedPath.indexOf(filename) === -1
? path.join(details.watchedPath, filename)
: details.watchedPath;
@ -235,10 +235,17 @@ class DirWatch {
call.talkgroup = this.parseRegex(dirWatch.talkgroup, filename);
}
await this.controller.importCall(call);
try {
await this.controller.importCall(call);
if (dirWatch.deleteAfter) {
this.unlink(filename);
if (dirWatch.deleteAfter) {
this.unlink(filename);
}
} catch (error) {
console.error(`DirWatch: Error importing file ${file.base}, ${error.message}`);
return;
}
}
}
@ -304,13 +311,7 @@ class DirWatch {
const sys = this.controller.config.systems.find((system) => system.label === tags.TIT1);
if (!sys) {
console.error(`DirWatch: Unable to find system label ${tags.TIT1} for file ${filename}`);
return;
}
const system = sys.id;
const system = sys ? sys.id : frequency;
const source = parseInt(tags.artist, 10) || null;
@ -333,8 +334,10 @@ class DirWatch {
talkgroup,
};
const meta = { systemLabel: tags.TIT1 };
try {
await this.controller.importCall(call);
await this.controller.importCall(call, meta);
if (dirWatch.deleteAfter) {
this.unlink(filename);

View file

@ -75,6 +75,8 @@ class RdioScanner extends EventEmitter {
app.config.rdioScanner = {};
}
this.app = app;
this.config = app.config.rdioScanner;
this.models = new Models(this);

View file

@ -25,6 +25,7 @@ const WS = require('ws');
class WebSocket {
constructor(ctx = {}) {
this.controller = ctx.controller;
this.controller.registerWebSocket(this);
this.httpServer = ctx.httpServer;
@ -74,6 +75,10 @@ class WebSocket {
});
}
getSockets() {
return this.wss.clients;
}
logClientsCount() {
console.log(`WebSocket: Listeners count is ${this.wss.clients.size}`);
}

134
server/package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "rdio-scanner-server",
"version": "4.9.2",
"version": "5.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -562,9 +562,9 @@
"optional": true
},
"aws4": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
"integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"optional": true
},
"balanced-match": {
@ -650,16 +650,16 @@
}
},
"browserslist": {
"version": "4.16.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.0.tgz",
"integrity": "sha512-/j6k8R0p3nxOC6kx5JGAxsnhc9ixaWJfYc+TNTzxg6+ARaESAvQGV7h0uNOB4t+pLQJZWzcrMxXOxjgsCj3dqQ==",
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz",
"integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001165",
"caniuse-lite": "^1.0.30001173",
"colorette": "^1.2.1",
"electron-to-chromium": "^1.3.621",
"electron-to-chromium": "^1.3.634",
"escalade": "^3.1.1",
"node-releases": "^1.1.67"
"node-releases": "^1.1.69"
}
},
"buffer-from": {
@ -727,9 +727,9 @@
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"caniuse-lite": {
"version": "1.0.30001171",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001171.tgz",
"integrity": "sha512-5Alrh8TTYPG9IH4UkRqEBZoEToWRLvPbSQokvzSz0lii8/FOWKG4keO1HoYfPWs8IF/NH/dyNPg1cmJGvV3Zlg==",
"version": "1.0.30001173",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001173.tgz",
"integrity": "sha512-R3aqmjrICdGCTAnSXtNyvWYMK3YtV5jwudbq0T7nN9k4kmE4CBuwPqyJ+KBzepSTh0huivV2gLbSMEzTTmfeYw==",
"dev": true
},
"caseless": {
@ -1102,9 +1102,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.3.633",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz",
"integrity": "sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==",
"version": "1.3.634",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.634.tgz",
"integrity": "sha512-QPrWNYeE/A0xRvl/QP3E0nkaEvYUvH3gM04ZWYtIa6QlSpEetRlRI1xvQ7hiMIySHHEV+mwDSX8Kj4YZY6ZQAw==",
"dev": true
},
"emoji-regex": {
@ -1738,11 +1738,11 @@
"dev": true
},
"global-dirs": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz",
"integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz",
"integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==",
"requires": {
"ini": "^1.3.5"
"ini": "1.3.7"
}
},
"globals": {
@ -1981,9 +1981,9 @@
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz",
"integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ=="
},
"interpret": {
"version": "2.2.0",
@ -2228,9 +2228,9 @@
}
},
"loader-runner": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.1.0.tgz",
"integrity": "sha512-oR4lB4WvwFoC70ocraKhn5nkKSs23t57h9udUgw8o0iH8hMXeEoRuUgfcvgUwAJ1ZpRqBvcou4N2SMvM1DwMrA==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz",
"integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==",
"dev": true
},
"locate-path": {
@ -2501,9 +2501,9 @@
"dev": true
},
"needle": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz",
"integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz",
"integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==",
"requires": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
@ -2511,17 +2511,17 @@
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.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.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
@ -2537,9 +2537,9 @@
"dev": true
},
"node-addon-api": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz",
"integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA=="
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz",
"integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw=="
},
"node-gyp": {
"version": "3.8.0",
@ -2621,15 +2621,15 @@
}
},
"node-releases": {
"version": "1.1.67",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz",
"integrity": "sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==",
"version": "1.1.69",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.69.tgz",
"integrity": "sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==",
"dev": true
},
"nodemon": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz",
"integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==",
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz",
"integrity": "sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA==",
"requires": {
"chokidar": "^3.2.2",
"debug": "^3.2.6",
@ -2644,17 +2644,17 @@
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.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.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}
}
},
@ -3054,9 +3054,9 @@
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"pupa": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.0.tgz",
"integrity": "sha512-Pj8EhJzFiPwnf4dEXpuUWwH8M/Yl4vpl4cN2RX1i3R77DWvbY5ZPKni7CCKkOYxz+XKt2fieemsV+WTZbIlYzg==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz",
"integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==",
"requires": {
"escape-goat": "^2.0.0"
}
@ -3137,9 +3137,9 @@
"dev": true
},
"registry-auth-token": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz",
"integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz",
"integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==",
"requires": {
"rc": "^1.2.8"
}
@ -3541,11 +3541,11 @@
"dev": true
},
"sqlite3": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz",
"integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.1.tgz",
"integrity": "sha512-kh2lTIcYNfmVcvhVJihsYuPj9U0xzBbh6bmqILO2hkryWSC9RRhzYmkIDtJkJ+d8Kg4wZRJ0T1reyHUEspICfg==",
"requires": {
"node-addon-api": "2.0.0",
"node-addon-api": "^3.0.0",
"node-gyp": "3.x",
"node-pre-gyp": "^0.11.0"
}
@ -3699,9 +3699,9 @@
}
},
"term-size": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz",
"integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw=="
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz",
"integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg=="
},
"terser": {
"version": "5.5.1",
@ -3958,9 +3958,9 @@
}
},
"webpack": {
"version": "5.11.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.11.1.tgz",
"integrity": "sha512-tNUIdAmYJv+nupRs/U/gqmADm6fgrf5xE+rSlSsf2PgsGO7j2WG7ccU6AWNlOJlHFl+HnmXlBmHIkiLf+XA9mQ==",
"version": "5.12.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.12.1.tgz",
"integrity": "sha512-Bh6hPzUvTLuGZg33xsZLEtAkaEJf9ux29WwGj4IeAGUCy7RE8zhqe4aHN4UqA8yHmHzvhORFH2p9ohB6h6R3yg==",
"dev": true,
"requires": {
"@types/eslint-scope": "^3.7.0",
@ -3978,7 +3978,7 @@
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.4",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^4.1.0",
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"pkg-dir": "^5.0.0",

View file

@ -11,17 +11,17 @@
"mime-types": "^2.1.28",
"multer": "^1.4.2",
"mysql2": "^2.2.5",
"nodemon": "^2.0.6",
"nodemon": "^2.0.7",
"pg": "^8.5.1",
"sequelize": "^6.3.5",
"sqlite3": "^5.0.0",
"sqlite3": "^5.0.1",
"umzug": "^2.3.0",
"uuid": "^8.3.2",
"ws": "^7.4.2"
},
"devDependencies": {
"eslint": "^7.17.0",
"webpack": "^5.11.1",
"webpack": "^5.12.1",
"webpack-cli": "^4.3.1",
"webpack-node-externals": "^2.5.2"
},
@ -39,5 +39,5 @@
"build": "webpack",
"start": "nodemon"
},
"version": "4.9.2"
"version": "5.0.0"
}