Version 6.1.3

This commit is contained in:
Chrystian Huot 2022-01-11 14:24:04 -05:00
parent 7b527b1b00
commit 2a6f721f4f
29 changed files with 829 additions and 753 deletions

View file

@ -21,6 +21,14 @@ _v6.1.2_
- Dirwatch type trunk-recorder now deletes json files without audio (when deleteAfter is set).
- Add a new `docs/update-from-v5.md` document.
_v6.1.3_
- Fix concurrent config write when autopopulate is enabled (issue #77).
- Fix API in regards to audio filename and audio type (issue #78).
- Fix some calls not playing on the native app (issue #87).
- Fix migration error on mysql database (issue #88).
- Fix admin password not read from mysql.
## Version 6.0
- Backend server rewritten in Go for better performance and ease of installation.

View file

@ -24,13 +24,13 @@ Clone the official repository on your computer and start the build process.
When finished, you will find the precompiled versions for various platforms in the `dist` folder.
rdio-scanner-darwin-amd64-v6.1.2.zip
rdio-scanner-darwin-arm64-v6.1.2.zip
rdio-scanner-freebsd-amd64-v6.1.2.zip
rdio-scanner-linux-386-v6.1.2.zip
rdio-scanner-linux-amd64-v6.1.2.zip
rdio-scanner-linux-arm64-v6.1.2.zip
rdio-scanner-linux-arm-v6.1.2.zip
rdio-scanner-windows-amd64-v6.1.2.zip
rdio-scanner-darwin-amd64-v6.1.3.zip
rdio-scanner-darwin-arm64-v6.1.3.zip
rdio-scanner-freebsd-amd64-v6.1.3.zip
rdio-scanner-linux-386-v6.1.3.zip
rdio-scanner-linux-amd64-v6.1.3.zip
rdio-scanner-linux-arm64-v6.1.3.zip
rdio-scanner-linux-arm-v6.1.3.zip
rdio-scanner-windows-amd64-v6.1.3.zip
**Happy Rdio scanning !**

View file

@ -16,8 +16,8 @@
################################################################################
app := rdio-scanner
date := 2022/01/05
ver := 6.1.2
date := 2022/01/11
ver := 6.1.3
client := $(wildcard client/*.json client/*.ts)
server := $(wildcard server/*.go)
@ -39,7 +39,7 @@ clean:
container: webapp linux-amd64
@podman build --platform linux/amd64,linux/arm,linux/arm64 --manifest rdio-scanner:latest .
@podman manifest push --format v2s2 localhost/rdio-scanner:latest docker://docker.io/chuot/rdio-scanner:latest
@podman manifest push --format v2s2 --rm localhost/rdio-scanner:latest docker://docker.io/chuot/rdio-scanner:latest
dist: darwin freebsd linux windows

491
client/package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "rdio-scanner",
"version": "6.1.0",
"version": "6.1.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "rdio-scanner",
"version": "6.1.0",
"version": "6.1.3",
"license": "LICENSE",
"dependencies": {
"@angular/animations": "^13.1.1",
@ -25,12 +25,12 @@
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.1.2",
"@angular-devkit/build-angular": "^13.1.2",
"@angular/cli": "^13.1.2",
"@angular/compiler-cli": "~13.1.1",
"@types/node": "~17.0.7",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
"@types/node": "~17.0.8",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"ajv-keywords": "^5.1.0",
"eslint": "^8.6.0",
"npm-check-updates": "^12.1.0",
@ -612,9 +612,9 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.16.4",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz",
"integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz",
"integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@ -987,14 +987,14 @@
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.7.tgz",
"integrity": "sha512-C3o117GnP/j/N2OWo+oepeWbFEKRfNaay+F1Eo5Mj3A1SRjyx+qaFhm23nlipub7Cjv2azdUUiDH+VlpdwUFRg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz",
"integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-wrap-function": "^7.16.7",
"@babel/types": "^7.16.7"
"@babel/helper-wrap-function": "^7.16.8",
"@babel/types": "^7.16.8"
},
"engines": {
"node": ">=6.9.0"
@ -1083,15 +1083,15 @@
}
},
"node_modules/@babel/helper-wrap-function": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.7.tgz",
"integrity": "sha512-7a9sABeVwcunnztZZ7WTgSw6jVYLzM1wua0Z4HIXm9S3/HC96WKQTkFgGEaj5W06SHHihPJ6Le6HzS5cGOQMNw==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz",
"integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==",
"dev": true,
"dependencies": {
"@babel/helper-function-name": "^7.16.7",
"@babel/template": "^7.16.7",
"@babel/traverse": "^7.16.7",
"@babel/types": "^7.16.7"
"@babel/traverse": "^7.16.8",
"@babel/types": "^7.16.8"
},
"engines": {
"node": ">=6.9.0"
@ -1154,9 +1154,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz",
"integrity": "sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
"integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@ -1887,9 +1887,9 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.7.tgz",
"integrity": "sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
"integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
"dev": true,
"dependencies": {
"@babel/helper-module-transforms": "^7.16.7",
@ -1940,9 +1940,9 @@
}
},
"node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.7.tgz",
"integrity": "sha512-kFy35VwmwIQwCjwrAQhl3+c/kr292i4KdLPKp5lPH03Ltc51qnFlIADoyPxc/6Naz3ok3WdYKg+KK6AH+D4utg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz",
"integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==",
"dev": true,
"dependencies": {
"@babel/helper-create-regexp-features-plugin": "^7.16.7"
@ -2321,19 +2321,19 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz",
"integrity": "sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.8.tgz",
"integrity": "sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.7",
"@babel/generator": "^7.16.8",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-hoist-variables": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
"@babel/parser": "^7.16.7",
"@babel/types": "^7.16.7",
"@babel/parser": "^7.16.8",
"@babel/types": "^7.16.8",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@ -2342,12 +2342,12 @@
}
},
"node_modules/@babel/traverse/node_modules/@babel/generator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz",
"integrity": "sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
"integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
"dev": true,
"dependencies": {
"@babel/types": "^7.16.7",
"@babel/types": "^7.16.8",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
},
@ -2365,9 +2365,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz",
"integrity": "sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
"integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.16.7",
@ -2763,9 +2763,9 @@
"dev": true
},
"node_modules/@types/eslint": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.1.tgz",
"integrity": "sha512-UP9rzNn/XyGwb5RQ2fok+DzcIRIYwc16qTXse5+Smsy8MOIccCChT15KAwnsgQx4PzJkaMq4myFyZ4CL5TjhIQ==",
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.2.tgz",
"integrity": "sha512-nQxgB8/Sg+QKhnV8e0WzPpxjIGT3tuJDDzybkDi8ItE/IgTlHo07U0shaIjzhcvQxlq9SDRE42lsJ23uvEgJ2A==",
"dev": true,
"dependencies": {
"@types/estree": "*",
@ -2773,9 +2773,9 @@
}
},
"node_modules/@types/eslint-scope": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.2.tgz",
"integrity": "sha512-TzgYCWoPiTeRg6RQYgtuW7iODtVoKu3RVL72k3WohqhjfaOLK5Mg2T4Tg1o2bSfu0vPkoI48wdQFv5b/Xe04wQ==",
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==",
"dev": true,
"dependencies": {
"@types/eslint": "*",
@ -2804,9 +2804,9 @@
"dev": true
},
"node_modules/@types/node": {
"version": "17.0.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.7.tgz",
"integrity": "sha512-1QUk+WAUD4t8iR+Oj+UgI8oJa6yyxaB8a8pHaC8uqM6RrS1qbL7bf3Pwl5rHv0psm2CuDErgho6v5N+G+5fwtQ==",
"version": "17.0.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
"integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==",
"dev": true
},
"node_modules/@types/parse-json": {
@ -2822,14 +2822,14 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz",
"integrity": "sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.1.tgz",
"integrity": "sha512-Xv9tkFlyD4MQGpJgTo6wqDqGvHIRmRgah/2Sjz1PUnJTawjHWIwBivUE9x0QtU2WVii9baYgavo/bHjrZJkqTw==",
"dev": true,
"dependencies": {
"@typescript-eslint/experimental-utils": "5.9.0",
"@typescript-eslint/scope-manager": "5.9.0",
"@typescript-eslint/type-utils": "5.9.0",
"@typescript-eslint/experimental-utils": "5.9.1",
"@typescript-eslint/scope-manager": "5.9.1",
"@typescript-eslint/type-utils": "5.9.1",
"debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8",
@ -2876,15 +2876,15 @@
}
},
"node_modules/@typescript-eslint/experimental-utils": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz",
"integrity": "sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.1.tgz",
"integrity": "sha512-cb1Njyss0mLL9kLXgS/eEY53SZQ9sT519wpX3i+U457l2UXRDuo87hgKfgRazmu9/tQb0x2sr3Y0yrU+Zz0y+w==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.9.0",
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/typescript-estree": "5.9.0",
"@typescript-eslint/scope-manager": "5.9.1",
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/typescript-estree": "5.9.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
@ -2900,14 +2900,14 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz",
"integrity": "sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.1.tgz",
"integrity": "sha512-PLYO0AmwD6s6n0ZQB5kqPgfvh73p0+VqopQQLuNfi7Lm0EpfKyDalchpVwkE+81k5HeiRrTV/9w1aNHzjD7C4g==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.9.0",
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/typescript-estree": "5.9.0",
"@typescript-eslint/scope-manager": "5.9.1",
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/typescript-estree": "5.9.1",
"debug": "^4.3.2"
},
"engines": {
@ -2927,13 +2927,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz",
"integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.1.tgz",
"integrity": "sha512-8BwvWkho3B/UOtzRyW07ffJXPaLSUKFBjpq8aqsRvu6HdEuzCY57+ffT7QoV4QXJXWSU1+7g3wE4AlgImmQ9pQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/visitor-keys": "5.9.0"
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/visitor-keys": "5.9.1"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -2944,12 +2944,12 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz",
"integrity": "sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.1.tgz",
"integrity": "sha512-tRSpdBnPRssjlUh35rE9ug5HrUvaB9ntREy7gPXXKwmIx61TNN7+l5YKgi1hMKxo5NvqZCfYhA5FvyuJG6X6vg==",
"dev": true,
"dependencies": {
"@typescript-eslint/experimental-utils": "5.9.0",
"@typescript-eslint/experimental-utils": "5.9.1",
"debug": "^4.3.2",
"tsutils": "^3.21.0"
},
@ -2991,9 +2991,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz",
"integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.1.tgz",
"integrity": "sha512-SsWegWudWpkZCwwYcKoDwuAjoZXnM1y2EbEerTHho19Hmm+bQ56QG4L4jrtCu0bI5STaRTvRTZmjprWlTw/5NQ==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@ -3004,13 +3004,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz",
"integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.1.tgz",
"integrity": "sha512-gL1sP6A/KG0HwrahVXI9fZyeVTxEYV//6PmcOn1tD0rw8VhUWYeZeuWHwwhnewnvEMcHjhnJLOBhA9rK4vmb8A==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/visitor-keys": "5.9.0",
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/visitor-keys": "5.9.1",
"debug": "^4.3.2",
"globby": "^11.0.4",
"is-glob": "^4.0.3",
@ -3052,12 +3052,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz",
"integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.1.tgz",
"integrity": "sha512-Xh37pNz9e9ryW4TVdwiFzmr4hloty8cFj8GTWMXh3Z8swGwyQWeCcNgF0hm6t09iZd6eiZmIf4zHedQVP6TVtg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/types": "5.9.1",
"eslint-visitor-keys": "^3.0.0"
},
"engines": {
@ -4169,9 +4169,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001296",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz",
"integrity": "sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q==",
"version": "1.0.30001298",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001298.tgz",
"integrity": "sha512-AcKqikjMLlvghZL/vfTHorlQsLDhGRalYf1+GmWCf5SCMziSGjRYQW/JEksj14NaYHIR6KIhrFAy0HV5C25UzQ==",
"dev": true,
"funding": {
"type": "opencollective",
@ -5435,9 +5435,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.4.34",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.34.tgz",
"integrity": "sha512-B7g6Y9No9XMYk1VNrQ8KAmSEo1Iltrz/5EjOGxl1DffQAb3z/XbpHRCfYKwV8D+CPXm4Q7Xg1sceSt9osNwRIA==",
"version": "1.4.40",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.40.tgz",
"integrity": "sha512-j+eVIyQGt2EU5xPWUblhpp5P5z5xyAdRgzogBgfe2F5JGV17gr9pfzWBua6DlPL00LavbOjxubWkWkbVQe9Wlw==",
"dev": true
},
"node_modules/emoji-regex": {
@ -6420,9 +6420,9 @@
"dev": true
},
"node_modules/fast-glob": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
"integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
"version": "3.2.10",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.10.tgz",
"integrity": "sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@ -6432,7 +6432,7 @@
"micromatch": "^4.0.4"
},
"engines": {
"node": ">=8"
"node": ">=8.6.0"
}
},
"node_modules/fast-json-stable-stringify": {
@ -6609,9 +6609,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.14.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
"dev": true,
"funding": [
{
@ -6853,16 +6853,16 @@
}
},
"node_modules/globby": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
"integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.1.1",
"ignore": "^5.1.4",
"merge2": "^1.3.0",
"fast-glob": "^3.2.9",
"ignore": "^5.2.0",
"merge2": "^1.4.1",
"slash": "^3.0.0"
},
"engines": {
@ -6895,9 +6895,9 @@
}
},
"node_modules/graceful-fs": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
"dev": true
},
"node_modules/handle-thing": {
@ -6987,9 +6987,9 @@
"dev": true
},
"node_modules/hosted-git-info": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz",
"integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
"integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@ -7479,9 +7479,9 @@
}
},
"node_modules/is-core-module": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
"integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
@ -7779,9 +7779,9 @@
}
},
"node_modules/jest-worker": {
"version": "27.4.5",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz",
"integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==",
"version": "27.4.6",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.6.tgz",
"integrity": "sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw==",
"dev": true,
"dependencies": {
"@types/node": "*",
@ -8716,9 +8716,9 @@
"dev": true
},
"node_modules/nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"version": "3.1.31",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.31.tgz",
"integrity": "sha512-ZivnJm0o9bb13p2Ot5CpgC2rQdzB9Uxm/mFZweqm5eMViqOJe3PV6LU2E30SiLgheesmcPrjquqraoolONSA0A==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
@ -12227,9 +12227,9 @@
"dev": true
},
"node_modules/selfsigned": {
"version": "1.10.11",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
"integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
"version": "1.10.14",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz",
"integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==",
"dev": true,
"dependencies": {
"node-forge": "^0.10.0"
@ -12585,6 +12585,7 @@
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz",
"integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==",
"deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
"dev": true,
"dependencies": {
"atob": "^2.1.2",
@ -14401,9 +14402,9 @@
}
},
"@babel/compat-data": {
"version": "7.16.4",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz",
"integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz",
"integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==",
"dev": true
},
"@babel/core": {
@ -14695,14 +14696,14 @@
"dev": true
},
"@babel/helper-remap-async-to-generator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.7.tgz",
"integrity": "sha512-C3o117GnP/j/N2OWo+oepeWbFEKRfNaay+F1Eo5Mj3A1SRjyx+qaFhm23nlipub7Cjv2azdUUiDH+VlpdwUFRg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz",
"integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-wrap-function": "^7.16.7",
"@babel/types": "^7.16.7"
"@babel/helper-wrap-function": "^7.16.8",
"@babel/types": "^7.16.8"
},
"dependencies": {
"@babel/helper-annotate-as-pure": {
@ -14769,15 +14770,15 @@
"dev": true
},
"@babel/helper-wrap-function": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.7.tgz",
"integrity": "sha512-7a9sABeVwcunnztZZ7WTgSw6jVYLzM1wua0Z4HIXm9S3/HC96WKQTkFgGEaj5W06SHHihPJ6Le6HzS5cGOQMNw==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz",
"integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==",
"dev": true,
"requires": {
"@babel/helper-function-name": "^7.16.7",
"@babel/template": "^7.16.7",
"@babel/traverse": "^7.16.7",
"@babel/types": "^7.16.7"
"@babel/traverse": "^7.16.8",
"@babel/types": "^7.16.8"
},
"dependencies": {
"@babel/template": {
@ -14829,9 +14830,9 @@
}
},
"@babel/parser": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz",
"integrity": "sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz",
"integrity": "sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw==",
"dev": true
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@ -15311,9 +15312,9 @@
}
},
"@babel/plugin-transform-modules-commonjs": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.7.tgz",
"integrity": "sha512-h2RP2kE7He1ZWKyAlanMZrAbdv+Acw1pA8dQZhE025WJZE2z0xzFADAinXA9fxd5bn7JnM+SdOGcndGx1ARs9w==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
"integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.16.7",
@ -15346,9 +15347,9 @@
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.7.tgz",
"integrity": "sha512-kFy35VwmwIQwCjwrAQhl3+c/kr292i4KdLPKp5lPH03Ltc51qnFlIADoyPxc/6Naz3ok3WdYKg+KK6AH+D4utg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz",
"integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==",
"dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.16.7"
@ -15620,30 +15621,30 @@
}
},
"@babel/traverse": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz",
"integrity": "sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.8.tgz",
"integrity": "sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.7",
"@babel/generator": "^7.16.8",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-hoist-variables": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
"@babel/parser": "^7.16.7",
"@babel/types": "^7.16.7",
"@babel/parser": "^7.16.8",
"@babel/types": "^7.16.8",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
"dependencies": {
"@babel/generator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz",
"integrity": "sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
"integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7",
"@babel/types": "^7.16.8",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
@ -15657,9 +15658,9 @@
}
},
"@babel/types": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz",
"integrity": "sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg==",
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
"integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.16.7",
@ -15970,9 +15971,9 @@
"dev": true
},
"@types/eslint": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.1.tgz",
"integrity": "sha512-UP9rzNn/XyGwb5RQ2fok+DzcIRIYwc16qTXse5+Smsy8MOIccCChT15KAwnsgQx4PzJkaMq4myFyZ4CL5TjhIQ==",
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.2.tgz",
"integrity": "sha512-nQxgB8/Sg+QKhnV8e0WzPpxjIGT3tuJDDzybkDi8ItE/IgTlHo07U0shaIjzhcvQxlq9SDRE42lsJ23uvEgJ2A==",
"dev": true,
"requires": {
"@types/estree": "*",
@ -15980,9 +15981,9 @@
}
},
"@types/eslint-scope": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.2.tgz",
"integrity": "sha512-TzgYCWoPiTeRg6RQYgtuW7iODtVoKu3RVL72k3WohqhjfaOLK5Mg2T4Tg1o2bSfu0vPkoI48wdQFv5b/Xe04wQ==",
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==",
"dev": true,
"requires": {
"@types/eslint": "*",
@ -16011,9 +16012,9 @@
"dev": true
},
"@types/node": {
"version": "17.0.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.7.tgz",
"integrity": "sha512-1QUk+WAUD4t8iR+Oj+UgI8oJa6yyxaB8a8pHaC8uqM6RrS1qbL7bf3Pwl5rHv0psm2CuDErgho6v5N+G+5fwtQ==",
"version": "17.0.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.8.tgz",
"integrity": "sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==",
"dev": true
},
"@types/parse-json": {
@ -16029,14 +16030,14 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz",
"integrity": "sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.1.tgz",
"integrity": "sha512-Xv9tkFlyD4MQGpJgTo6wqDqGvHIRmRgah/2Sjz1PUnJTawjHWIwBivUE9x0QtU2WVii9baYgavo/bHjrZJkqTw==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "5.9.0",
"@typescript-eslint/scope-manager": "5.9.0",
"@typescript-eslint/type-utils": "5.9.0",
"@typescript-eslint/experimental-utils": "5.9.1",
"@typescript-eslint/scope-manager": "5.9.1",
"@typescript-eslint/type-utils": "5.9.1",
"debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8",
@ -16063,48 +16064,48 @@
}
},
"@typescript-eslint/experimental-utils": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz",
"integrity": "sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.1.tgz",
"integrity": "sha512-cb1Njyss0mLL9kLXgS/eEY53SZQ9sT519wpX3i+U457l2UXRDuo87hgKfgRazmu9/tQb0x2sr3Y0yrU+Zz0y+w==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
"@typescript-eslint/scope-manager": "5.9.0",
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/typescript-estree": "5.9.0",
"@typescript-eslint/scope-manager": "5.9.1",
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/typescript-estree": "5.9.1",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
}
},
"@typescript-eslint/parser": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz",
"integrity": "sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.1.tgz",
"integrity": "sha512-PLYO0AmwD6s6n0ZQB5kqPgfvh73p0+VqopQQLuNfi7Lm0EpfKyDalchpVwkE+81k5HeiRrTV/9w1aNHzjD7C4g==",
"dev": true,
"requires": {
"@typescript-eslint/scope-manager": "5.9.0",
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/typescript-estree": "5.9.0",
"@typescript-eslint/scope-manager": "5.9.1",
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/typescript-estree": "5.9.1",
"debug": "^4.3.2"
}
},
"@typescript-eslint/scope-manager": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz",
"integrity": "sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.1.tgz",
"integrity": "sha512-8BwvWkho3B/UOtzRyW07ffJXPaLSUKFBjpq8aqsRvu6HdEuzCY57+ffT7QoV4QXJXWSU1+7g3wE4AlgImmQ9pQ==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/visitor-keys": "5.9.0"
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/visitor-keys": "5.9.1"
}
},
"@typescript-eslint/type-utils": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz",
"integrity": "sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.1.tgz",
"integrity": "sha512-tRSpdBnPRssjlUh35rE9ug5HrUvaB9ntREy7gPXXKwmIx61TNN7+l5YKgi1hMKxo5NvqZCfYhA5FvyuJG6X6vg==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "5.9.0",
"@typescript-eslint/experimental-utils": "5.9.1",
"debug": "^4.3.2",
"tsutils": "^3.21.0"
},
@ -16127,19 +16128,19 @@
}
},
"@typescript-eslint/types": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz",
"integrity": "sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.1.tgz",
"integrity": "sha512-SsWegWudWpkZCwwYcKoDwuAjoZXnM1y2EbEerTHho19Hmm+bQ56QG4L4jrtCu0bI5STaRTvRTZmjprWlTw/5NQ==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz",
"integrity": "sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.1.tgz",
"integrity": "sha512-gL1sP6A/KG0HwrahVXI9fZyeVTxEYV//6PmcOn1tD0rw8VhUWYeZeuWHwwhnewnvEMcHjhnJLOBhA9rK4vmb8A==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/visitor-keys": "5.9.0",
"@typescript-eslint/types": "5.9.1",
"@typescript-eslint/visitor-keys": "5.9.1",
"debug": "^4.3.2",
"globby": "^11.0.4",
"is-glob": "^4.0.3",
@ -16165,12 +16166,12 @@
}
},
"@typescript-eslint/visitor-keys": {
"version": "5.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz",
"integrity": "sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==",
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.1.tgz",
"integrity": "sha512-Xh37pNz9e9ryW4TVdwiFzmr4hloty8cFj8GTWMXh3Z8swGwyQWeCcNgF0hm6t09iZd6eiZmIf4zHedQVP6TVtg==",
"dev": true,
"requires": {
"@typescript-eslint/types": "5.9.0",
"@typescript-eslint/types": "5.9.1",
"eslint-visitor-keys": "^3.0.0"
}
},
@ -17043,9 +17044,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001296",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz",
"integrity": "sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q==",
"version": "1.0.30001298",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001298.tgz",
"integrity": "sha512-AcKqikjMLlvghZL/vfTHorlQsLDhGRalYf1+GmWCf5SCMziSGjRYQW/JEksj14NaYHIR6KIhrFAy0HV5C25UzQ==",
"dev": true
},
"canonical-path": {
@ -17994,9 +17995,9 @@
"dev": true
},
"electron-to-chromium": {
"version": "1.4.34",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.34.tgz",
"integrity": "sha512-B7g6Y9No9XMYk1VNrQ8KAmSEo1Iltrz/5EjOGxl1DffQAb3z/XbpHRCfYKwV8D+CPXm4Q7Xg1sceSt9osNwRIA==",
"version": "1.4.40",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.40.tgz",
"integrity": "sha512-j+eVIyQGt2EU5xPWUblhpp5P5z5xyAdRgzogBgfe2F5JGV17gr9pfzWBua6DlPL00LavbOjxubWkWkbVQe9Wlw==",
"dev": true
},
"emoji-regex": {
@ -18697,9 +18698,9 @@
"dev": true
},
"fast-glob": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
"integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
"version": "3.2.10",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.10.tgz",
"integrity": "sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A==",
"dev": true,
"requires": {
"@nodelib/fs.stat": "^2.0.2",
@ -18854,9 +18855,9 @@
"dev": true
},
"follow-redirects": {
"version": "1.14.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
"dev": true
},
"forwarded": {
@ -19023,16 +19024,16 @@
"dev": true
},
"globby": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
"integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"requires": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.1.1",
"ignore": "^5.1.4",
"merge2": "^1.3.0",
"fast-glob": "^3.2.9",
"ignore": "^5.2.0",
"merge2": "^1.4.1",
"slash": "^3.0.0"
}
},
@ -19056,9 +19057,9 @@
}
},
"graceful-fs": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
"dev": true
},
"handle-thing": {
@ -19127,9 +19128,9 @@
"dev": true
},
"hosted-git-info": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz",
"integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
"integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
@ -19510,9 +19511,9 @@
}
},
"is-core-module": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
"integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"dev": true,
"requires": {
"has": "^1.0.3"
@ -19716,9 +19717,9 @@
}
},
"jest-worker": {
"version": "27.4.5",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz",
"integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==",
"version": "27.4.6",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.6.tgz",
"integrity": "sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw==",
"dev": true,
"requires": {
"@types/node": "*",
@ -20430,9 +20431,9 @@
"dev": true
},
"nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"version": "3.1.31",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.31.tgz",
"integrity": "sha512-ZivnJm0o9bb13p2Ot5CpgC2rQdzB9Uxm/mFZweqm5eMViqOJe3PV6LU2E30SiLgheesmcPrjquqraoolONSA0A==",
"dev": true
},
"natural-compare": {
@ -23071,9 +23072,9 @@
"dev": true
},
"selfsigned": {
"version": "1.10.11",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
"integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
"version": "1.10.14",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz",
"integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==",
"dev": true,
"requires": {
"node-forge": "^0.10.0"

View file

@ -17,12 +17,12 @@
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.1.2",
"@angular-devkit/build-angular": "^13.1.2",
"@angular/cli": "^13.1.2",
"@angular/compiler-cli": "~13.1.1",
"@types/node": "~17.0.7",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
"@types/node": "~17.0.8",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"ajv-keywords": "^5.1.0",
"eslint": "^8.6.0",
"npm-check-updates": "^12.1.0",
@ -39,5 +39,5 @@
"build": "ng build --base-href ./ --configuration production",
"start": "ng serve"
},
"version": "6.1.2"
"version": "6.1.3"
}

View file

@ -17,42 +17,45 @@
* ****************************************************************************
*/
import { Injectable } from '@angular/core';
import { ApplicationRef, Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { SwUpdate } from '@angular/service-worker';
import { SwUpdate, VersionEvent } from '@angular/service-worker';
import { AppUpdateComponent } from './update.component';
import { concat, interval } from 'rxjs';
import { first } from 'rxjs/operators';
@Injectable()
export class AppUpdateService {
private prompted: boolean = false;
constructor(
private matDialog: MatDialog,
private swUpdate: SwUpdate,
private ngAppRef: ApplicationRef,
private ngSwUpdate: SwUpdate,
) {
if (swUpdate.isEnabled) {
swUpdate.versionUpdates.subscribe(() => this.prompt());
setInterval(() => swUpdate.checkForUpdate(), 60 * 60 * 1000);
}
}
prompt(): void {
if (this.prompted) {
if (!ngSwUpdate.isEnabled) {
return;
}
this.prompted = true
concat(
this.ngAppRef.isStable.pipe(first((stable) => stable === true)),
interval(10 * 60 * 1000),
).subscribe(() => this.ngSwUpdate.checkForUpdate());
this.ngSwUpdate.versionUpdates.subscribe((event: VersionEvent) => {
if (event.type === 'VERSION_READY') {
this.prompt();
}
});
}
prompt(): void {
this.matDialog.open(AppUpdateComponent).afterClosed().subscribe((doUpdate) => {
if (doUpdate) {
if (this.swUpdate.isEnabled) {
this.swUpdate.activateUpdate().then(() => document.location.reload());
if (this.ngSwUpdate.isEnabled) {
this.ngSwUpdate.activateUpdate().then(() => document.location.reload());
} else {
document.location.reload();
}
}
this.prompted = false;
});
}
}

View file

@ -16,4 +16,8 @@ A: No problem, just drop us a line at **[rdio-scanner@saubeo.solutions](mailto:r
A: First, don't use the update.js script, it won't work since the server portion of version 6 as been completely rewritten in GO. Simply unzip the archive that contains the Rdio Scanner executable and its PDF document to a new folder, then copy the database.sqlite from version 5 to the new folder that contains version 6 and make sure to rename it to _rdio-scanner.db_.
**Q: The web app keeps displaying a dialog telling me that a new version is available**
A: Force a refresh of the web application from the browser (usually with ctrl-shift-r) to resolve the issue. Alternatively, you can click on the icon just to the left of the URL address and select website settings, then clear all website data.
\pagebreak{}

View file

@ -42,8 +42,8 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@macos ~ % mkdir rdio-scanner
rdio@macos ~ % cd rdio-scanner
rdio@macos rdio-scanner % unzip \
> ~/Downloads/rdio-scanner-darwin-arm64-v6.1.2.zip
Archive: /Users/rdio/Downloads/rdio-scanner-darwin-arm64-v6.1.2.zip
> ~/Downloads/rdio-scanner-darwin-arm64-v6.1.3.zip
Archive: /Users/rdio/Downloads/rdio-scanner-darwin-arm64-v6.1.3.zip
inflating: rdio-scanner
inflating: rdio-scanner.pdf
@ -51,11 +51,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@macos rdio-scanner % ./rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 08:38:06 server started
2022/01/05 08:38:06 main interface at http://macos.local:3000
2022/01/05 08:38:06 admin interface at http://macos.local:3000/admin
2022/01/11 08:38:06 server started
2022/01/11 08:38:06 main interface at http://macos.local:3000
2022/01/11 08:38:06 admin interface at http://macos.local:3000/admin
4. Access the administrative dashboard to finalize the configuration.
@ -77,11 +77,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
rdio@macos rdio-scanner % ./rdio-scanner --listen :80
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 08:48:03 server started
2022/01/05 08:48:03 main interface at http://macos.local
2022/01/05 08:48:03 admin interface at http://macos.local/admin
2022/01/11 08:48:03 server started
2022/01/11 08:48:03 main interface at http://macos.local
2022/01/11 08:48:03 admin interface at http://macos.local/admin
## Listening with SSL with self-signed certificates
@ -90,8 +90,8 @@ It is advised to share your [Rdio Scanner](https://github.com/chuot/rdio-scanner
We can create such self-signed certificates by running [Rdio Scanner](https://github.com/chuot/rdio-scanner) with the **-ssl_create** argument.
rdio@macos rdio-scanner % ./rdio-scanner -ssl_create
2022/01/05 08:49:16 generating ssl certificate files
2022/01/05 08:49:17 ssl files created
2022/01/11 08:49:16 generating ssl certificate files
2022/01/11 08:49:17 ssl files created
This has generated these files in the same folder as your [Rdio Scanner](https://github.com/chuot/rdio-scanner) executable.
@ -108,12 +108,12 @@ Now we use the self-signed server certificate to run our instance.
> -ssl_key_file server.key \
> -ssl_listen :443
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 08:50:58 server started
2022/01/05 08:50:58 main interface at http://macos.local
2022/01/05 08:50:58 main interface at https://macos.local
2022/01/05 08:50:58 admin interface at https://macos.local/admin
2022/01/11 08:50:58 server started
2022/01/11 08:50:58 main interface at http://macos.local
2022/01/11 08:50:58 main interface at https://macos.local
2022/01/11 08:50:58 admin interface at https://macos.local/admin
## Save your advanced configuration to a config file
@ -125,7 +125,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
> -ssl_key_file server.key \
> -ssl_listen :443 \
> -config_save
2022/01/05 08:52:24 rdio-scanner.ini file created
2022/01/11 08:52:24 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -140,12 +140,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
rdio@macos rdio-scanner % ./rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 08:54:08 server started
2022/01/05 08:54:08 main interface at http://macos.local
2022/01/05 08:54:08 main interface at https://macos.local
2022/01/05 08:54:08 admin interface at https://macos.local/admin
2022/01/11 08:54:08 server started
2022/01/11 08:54:08 main interface at http://macos.local
2022/01/11 08:54:08 main interface at https://macos.local
2022/01/11 08:54:08 admin interface at https://macos.local/admin
## Install Rdio Scanner as a service

View file

@ -42,8 +42,8 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@pc-freebsd:~ $ mkdir rdio-scanner
rdio@pc-freebsd:~ $ cd rdio-scanner
rdio@pc-freebsd:~/rdio-scanner $ unzip \
> ~/rdio-scanner-freebsd-amd64-v6.1.2.zip
Archive: ../rdio-scanner-freebsd-amd64-v6.1.2.zip
> ~/rdio-scanner-freebsd-amd64-v6.1.3.zip
Archive: ../rdio-scanner-freebsd-amd64-v6.1.3.zip
extracting: rdio-scanner
extracting: rdio-scanner.pdf
@ -51,11 +51,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
rdio@pc-freebsd:~/rdio-scanner $ ./rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 08:16:36 server started
2022/01/05 08:16:36 main interface at http://pc-freebsd:3000
2022/01/05 08:16:36 admin interface at http://pc-freebsd:3000/admin
2022/01/11 08:16:36 server started
2022/01/11 08:16:36 main interface at http://pc-freebsd:3000
2022/01/11 08:16:36 admin interface at http://pc-freebsd:3000/admin
4. Access the administrative dashboard to finalize the configuration.
@ -81,11 +81,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
Password:
root@pc-freebsd:/home/rdio/rdio-scanner # ./rdio-scanner -listen :80
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 08:19:38 server started
2022/01/05 08:19:38 main interface at http://pc-freebsd
2022/01/05 08:19:38 admin interface at http://pc-freebsd/admin
2022/01/11 08:19:38 server started
2022/01/11 08:19:38 main interface at http://pc-freebsd
2022/01/11 08:19:38 admin interface at http://pc-freebsd/admin
## Listening with SSL with self-signed certificates
@ -94,8 +94,8 @@ It is advised to share your [Rdio Scanner](https://github.com/chuot/rdio-scanner
We can create such self-signed certificates by running [Rdio Scanner](https://github.com/chuot/rdio-scanner) with the **-ssl_create** argument.
rdio@pc-freebsd:~/rdio-scanner $ ./rdio-scanner -ssl_create
2022/01/05 10:32:17 generating ssl certificate files
2022/01/05 10:32:19 ssl files created
2022/01/11 10:32:17 generating ssl certificate files
2022/01/11 10:32:19 ssl files created
This has generated these files in the same folder as your [Rdio Scanner](https://github.com/chuot/rdio-scanner) executable.
@ -114,12 +114,12 @@ Now we use the self-signed server certificate to run our instance.
> -ssl_key_file server.key \
> -ssl_listen :443
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 10:34:29 server started
2022/01/05 10:34:29 main interface at http://pc-freebsd
2022/01/05 10:34:29 main interface at https://pc-freebsd
2022/01/05 10:34:29 admin interface at https://pc-freebsd/admin
2022/01/11 10:34:29 server started
2022/01/11 10:34:29 main interface at http://pc-freebsd
2022/01/11 10:34:29 main interface at https://pc-freebsd
2022/01/11 10:34:29 admin interface at https://pc-freebsd/admin
## Save your advanced configuration to a config file
@ -131,7 +131,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
> -ssl_key_file server.key \
> -ssl_listen :443 \
> -config_save
2022/01/05 10:37:00 rdio-scanner.ini file created
2022/01/11 10:37:00 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -148,12 +148,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
Password:
root@pc-freebsd:/home/rdio/rdio-scanner # ./rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 10:38:28 server started
2022/01/05 10:38:29 main interface at http://pc-freebsd
2022/01/05 10:38:29 main interface at https://pc-freebsd
2022/01/05 10:38:29 admin interface at https://pc-freebsd/admin
2022/01/11 10:38:28 server started
2022/01/11 10:38:29 main interface at http://pc-freebsd
2022/01/11 10:38:29 main interface at https://pc-freebsd
2022/01/11 10:38:29 admin interface at https://pc-freebsd/admin
## Install Rdio Scanner as a service

View file

@ -42,8 +42,8 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
[rdio@pc-linux ~]$ mkdir rdio-scanner
[rdio@pc-linux ~]$ cd rdio-scanner
[rdio@pc-linux rdio-scanner]$ unzip \
> ~/Downloads/rdio-scanner-linux-amd64-v6.1.2.zip
Archive: /home/rdio/Downloads/rdio-scanner-linux-amd64-v6.1.2.zip
> ~/Downloads/rdio-scanner-linux-amd64-v6.1.3.zip
Archive: /home/rdio/Downloads/rdio-scanner-linux-amd64-v6.1.3.zip
inflating: rdio-scanner
inflating: rdio-scanner.pdf
@ -51,11 +51,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
[rdio@pc-linux rdio-scanner]$ ./rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 09:11:48 server started
2022/01/05 09:11:48 main interface at http://pc-linux:3000
2022/01/05 09:11:48 admin interface at http://pc-linux:3000/admin
2022/01/11 09:11:48 server started
2022/01/11 09:11:48 main interface at http://pc-linux:3000
2022/01/11 09:11:48 admin interface at http://pc-linux:3000/admin
4. Access the administrative dashboard to finalize the configuration.
@ -78,11 +78,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
[rdio@pc-linux rdio-scanner]$ sudo ./rdio-scanner -listen :80
[sudo] password for rdio:
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 09:14:00 server started
2022/01/05 09:14:00 main interface at http://pc-linux
2022/01/05 09:14:00 admin interface at http://pc-linux/admin
2022/01/11 09:14:00 server started
2022/01/11 09:14:00 main interface at http://pc-linux
2022/01/11 09:14:00 admin interface at http://pc-linux/admin
## Listening with SSL with self-signed certificates
@ -91,8 +91,8 @@ It is advised to share your [Rdio Scanner](https://github.com/chuot/rdio-scanner
We can create such self-signed certificates by running [Rdio Scanner](https://github.com/chuot/rdio-scanner) with the **-ssl_create** argument.
[rdio@pc-linux rdio-scanner]$ ./rdio-scanner -ssl_create
2022/01/05 09:15:03 generating ssl certificate files
2022/01/05 09:15:05 ssl files created
2022/01/11 09:15:03 generating ssl certificate files
2022/01/11 09:15:05 ssl files created
This has generated these files in the same folder as your [Rdio Scanner](https://github.com/chuot/rdio-scanner) executable.
@ -110,12 +110,12 @@ Now we use the self-signed server certificate to run our instance.
> -ssl_listen :443
[sudo] password for rdio:
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 09:16:47 server started
2022/01/05 09:16:47 main interface at http://pc-linux
2022/01/05 09:16:47 main interface at https://pc-linux
2022/01/05 09:16:47 admin interface at https://pc-linux/admin
2022/01/11 09:16:47 server started
2022/01/11 09:16:47 main interface at http://pc-linux
2022/01/11 09:16:47 main interface at https://pc-linux
2022/01/11 09:16:47 admin interface at https://pc-linux/admin
## Save your advanced configuration to a config file
@ -127,7 +127,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
> -ssl_key_file server.key \
> -ssl_listen :443 \
> -config_save
2022/01/05 09:19:29 rdio-scanner.ini file created
2022/01/11 09:19:29 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -143,12 +143,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
[rdio@pc-linux rdio-scanner]$ sudo ./rdio-scanner
[sudo] Mot de passe de rdio :
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 09:20:40 server started
2022/01/05 09:20:40 main interface at http://pc-linux
2022/01/05 09:20:40 main interface at https://pc-linux
2022/01/05 09:20:40 admin interface at https://pc-linux/admin
2022/01/11 09:20:40 server started
2022/01/11 09:20:40 main interface at http://pc-linux
2022/01/11 09:20:40 main interface at https://pc-linux
2022/01/11 09:20:40 admin interface at https://pc-linux/admin
## Install Rdio Scanner as a service

View file

@ -44,7 +44,7 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
C:\Users\rdio> cd rdio-scanner
C:\Users\rdio\rdio-scanner> tar -xvf ^
..\downloads\rdio-scanner-windows-amd64-v6.1.2.zip
..\downloads\rdio-scanner-windows-amd64-v6.1.3.zip
x rdio-scanner.exe
x rdio-scanner.pdf
@ -52,11 +52,11 @@ ALWAYS DOWNLOAD THE LATEST VERSION OF [RDIO SCANNER](https://github.com/chuot/rd
C:\Users\rdio\rdio-scanner>rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 13:48:48 server started
2022/01/05 13:48:48 main interface at http://pc-windows:3000
2022/01/05 13:48:48 admin interface at http://pc-windows:3000/admin
2022/01/11 13:48:48 server started
2022/01/11 13:48:48 main interface at http://pc-windows:3000
2022/01/11 13:48:48 admin interface at http://pc-windows:3000/admin
4. Access the administrative dashboard to finalize the configuration.
@ -78,11 +78,11 @@ Here we want our [Rdio Scanner](https://guthub.com/chuot/rdio-scanner) instance
C:\Users\rdio\rdio-scanner>rdio-scanner -listen :80
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 10:53:31 server started
2022/01/05 10:53:31 main interface at http://pc-windows
2022/01/05 10:53:31 admin interface at http://pc-windows/admin
2022/01/11 10:53:31 server started
2022/01/11 10:53:31 main interface at http://pc-windows
2022/01/11 10:53:31 admin interface at http://pc-windows/admin
## Listening with SSL with self-signed certificates
@ -91,8 +91,8 @@ It is advised to share your [Rdio Scanner](https://github.com/chuot/rdio-scanner
We can create such self-signed certificates by running [Rdio Scanner](https://github.com/chuot/rdio-scanner) with the **-ssl_create** argument.
C:\Users\rdio\rdio-scanner>rdio-scanner -ssl_create
2022/01/05 10:58:51 generating ssl certificate files
2022/01/05 10:58:54 ssl files created
2022/01/11 10:58:51 generating ssl certificate files
2022/01/11 10:58:54 ssl files created
This has generated these files in the same folder as your [Rdio Scanner](https://github.com/chuot/rdio-scanner) executable.
@ -109,12 +109,12 @@ Now we use the self-signed server certificate to run our instance.
-ssl_key_file server.key ^
-ssl_listen :443
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 11:05:43 server started
2022/01/05 11:05:43 main interface at http://pc-windows
2022/01/05 11:05:43 main interface at https://pc-windows
2022/01/05 11:05:43 admin interface at https://pc-windows/admin
2022/01/11 11:05:43 server started
2022/01/11 11:05:43 main interface at http://pc-windows
2022/01/11 11:05:43 main interface at https://pc-windows
2022/01/11 11:05:43 admin interface at https://pc-windows/admin
## Save your advanced configuration to a config file
@ -126,7 +126,7 @@ You don't want to have to type everytime a long list of arguments. No problem, y
-ssl_key_file server.key ^
-ssl_listen :443 ^
-config_save
2022/01/05 11:08:28 rdio-scanner.ini file created
2022/01/11 11:08:28 rdio-scanner.ini file created
All of your parameters passed as arguments to [Rdio Scanner](https://github.com/chuot/rdio-scanner) have been saved to an INI file which has the same arguments/values list.
@ -141,12 +141,12 @@ Then simply run [Rdio Scanner](https://github.com/chuot/rdio-scanner) without an
C:\Users\rdio\rdio-scanner>rdio-scanner
Rdio Scanner v6.1.2
Rdio Scanner v6.1.3
----------------------------------
2022/01/05 11:11:28 server started
2022/01/05 11:11:28 main interface at http://pc-windows
2022/01/05 11:11:28 main interface at https://pc-windows
2022/01/05 11:11:28 admin interface at https://pc-windows/admin
2022/01/11 11:11:28 server started
2022/01/11 11:11:28 main interface at http://pc-windows
2022/01/11 11:11:28 main interface at https://pc-windows
2022/01/11 11:11:28 admin interface at https://pc-windows/admin
\pagebreak{}

View file

@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"strings"
"sync"
"time"
)
@ -124,7 +125,10 @@ func (access *Access) HasExpired() bool {
return false
}
type Accesses []Access
type Accesses struct {
List []*Access
mutex sync.Mutex
}
func (accesses *Accesses) FromMap(f []interface{}) {
*accesses = Accesses{}
@ -132,24 +136,24 @@ func (accesses *Accesses) FromMap(f []interface{}) {
for _, r := range f {
switch m := r.(type) {
case map[string]interface{}:
access := Access{}
access := &Access{}
access.FromMap(m)
*accesses = append(*accesses, access)
accesses.List = append(accesses.List, access)
}
}
}
func (accesses *Accesses) GetAccess(code string) (access *Access, ok bool) {
for _, access := range *accesses {
for _, access := range accesses.List {
if access.Code == code {
return &access, true
return access, true
}
}
return nil, false
}
func (accesses *Accesses) IsRestricted() bool {
return len(*accesses) > 0
return len(accesses.List) > 0
}
func (accesses *Accesses) Read(db *Database) error {
@ -164,7 +168,7 @@ func (accesses *Accesses) Read(db *Database) error {
t time.Time
)
*accesses = Accesses{}
accesses.List = []*Access{}
formatError := func(err error) error {
return fmt.Errorf("accesses.read: %v", err)
@ -175,7 +179,8 @@ func (accesses *Accesses) Read(db *Database) error {
}
for rows.Next() {
access := Access{}
access := &Access{}
if err = rows.Scan(&id, &access.Code, &expiration, &access.Ident, &limit, &order, &systems); err != nil {
break
}
@ -206,7 +211,7 @@ func (accesses *Accesses) Read(db *Database) error {
access.Systems = []interface{}{}
}
*accesses = append(*accesses, access)
accesses.List = append(accesses.List, access)
}
rows.Close()
@ -227,11 +232,13 @@ func (accesses *Accesses) Write(db *Database) error {
systems interface{}
)
accesses.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("accesses.write: %v", err)
}
for _, access := range *accesses {
for _, access := range accesses.List {
switch access.Systems {
case "*":
systems = `"*"`
@ -265,7 +272,7 @@ func (accesses *Accesses) Write(db *Database) error {
var id uint
rows.Scan(&id)
remove := true
for _, access := range *accesses {
for _, access := range accesses.List {
if access.Id == nil || access.Id == id {
remove = false
break
@ -294,5 +301,7 @@ func (accesses *Accesses) Write(db *Database) error {
}
}
accesses.mutex.Unlock()
return nil
}

View file

@ -81,30 +81,36 @@ func (admin *Admin) BroadcastConfig() {
}
func (admin *Admin) ChangePassword(currentPassword string, newPassword string) error {
if len(currentPassword) > 0 {
if err := bcrypt.CompareHashAndPassword([]byte(admin.Controller.Options.adminPassword), []byte(currentPassword)); err == nil {
var hash []byte
if hash, err = bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost); err != nil {
return err
}
var (
err error
hash []byte
)
admin.Controller.Options.adminPassword = string(hash)
admin.Controller.Options.adminPasswordNeedChange = newPassword == defaults.adminPassword
if err := admin.Controller.Options.Write(admin.Controller.Database); err != nil {
return err
}
if err := admin.Controller.Options.Read(admin.Controller.Database); err != nil {
return err
}
LogEvent(admin.Controller.Database, LogLevelInfo, "admin password changed.")
} else {
return err
}
if len(newPassword) == 0 {
return errors.New("newPassword is empty")
}
if err = bcrypt.CompareHashAndPassword([]byte(admin.Controller.Options.adminPassword), []byte(currentPassword)); err != nil {
return err
}
if hash, err = bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost); err != nil {
return err
}
admin.Controller.Options.adminPassword = string(hash)
admin.Controller.Options.adminPasswordNeedChange = newPassword == defaults.adminPassword
if err := admin.Controller.Options.Write(admin.Controller.Database); err != nil {
return err
}
if err := admin.Controller.Options.Read(admin.Controller.Database); err != nil {
return err
}
LogEvent(admin.Controller.Database, LogLevelInfo, "admin password changed.")
return nil
}
@ -287,7 +293,7 @@ func (admin *Admin) GetAuthorization(r *http.Request) string {
func (admin *Admin) GetConfig() map[string]interface{} {
systems := []map[string]interface{}{}
for _, system := range *admin.Controller.Systems {
for _, system := range admin.Controller.Systems.List {
systems = append(systems, map[string]interface{}{
"_id": system.RowId,
"autoPopulate": system.AutoPopulate,
@ -302,14 +308,14 @@ func (admin *Admin) GetConfig() map[string]interface{} {
}
return map[string]interface{}{
"access": *admin.Controller.Accesses,
"apiKeys": *admin.Controller.Apikeys,
"dirWatch": *admin.Controller.Dirwatches,
"downstreams": *admin.Controller.Downstreams,
"groups": *admin.Controller.Groups,
"options": *admin.Controller.Options,
"access": admin.Controller.Accesses.List,
"apiKeys": admin.Controller.Apikeys.List,
"dirWatch": admin.Controller.Dirwatches.List,
"downstreams": admin.Controller.Downstreams.List,
"groups": admin.Controller.Groups.List,
"options": admin.Controller.Options,
"systems": systems,
"tags": *admin.Controller.Tags,
"tags": admin.Controller.Tags.List,
}
}

View file

@ -16,16 +16,12 @@
package main
import (
"encoding/json"
"fmt"
"io"
"mime"
"mime/multipart"
"net/http"
"regexp"
"strconv"
"strings"
"time"
)
const (
@ -45,23 +41,8 @@ func (api *Api) CallUploadHandler(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodPost:
var (
audio []byte
audioName string
audioType string
dateTime time.Time
frequencies = []map[string]interface{}{}
frequency interface{}
key string
patches = []uint{}
source interface{}
sources = []map[string]interface{}{}
system uint
systemLabel interface{}
talkgroup uint
talkgroupGroup interface{}
talkgroupLabel interface{}
talkgroupTag interface{}
units interface{}
call = NewCall()
key string
)
mediaType, params, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
@ -93,182 +74,15 @@ func (api *Api) CallUploadHandler(w http.ResponseWriter, r *http.Request) {
}
switch p.FormName() {
case "audio":
audio = b
audioName = p.FileName()
audioType = p.Header.Get("Content-Type")
case "audioName":
audioName = string(b)
case "audioType":
audioType = string(b)
case "dateTime":
if regexp.MustCompile(`^[0-9]+$`).Match(b) {
if i, err := strconv.Atoi(string(b)); err == nil {
dateTime = time.Unix(int64(i), 0).UTC()
}
} else {
dateTime, _ = time.Parse(time.RFC3339, string(b))
dateTime = dateTime.UTC()
}
case "frequencies":
var f interface{}
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
case []interface{}:
for _, f := range v {
freq := map[string]interface{}{}
switch v := f.(type) {
case map[string]interface{}:
switch v := v["errorCount"].(type) {
case float64:
freq["errorCount"] = uint(v)
}
switch v := v["freq"].(type) {
case float64:
freq["freq"] = uint(v)
}
switch v := v["len"].(type) {
case float64:
freq["len"] = uint(v)
}
switch v := v["pos"].(type) {
case float64:
freq["pos"] = uint(v)
}
switch v := v["spikeCount"].(type) {
case float64:
freq["spikeCount"] = uint(v)
}
}
frequencies = append(frequencies, freq)
}
}
}
case "frequency":
if i, err := strconv.Atoi(string(b)); err == nil {
frequency = uint(i)
}
case "key":
key = string(b)
case "patches", "patched_talkgroups":
var f interface{}
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
case []interface{}:
for _, patch := range v {
switch v := patch.(type) {
case float64:
if v > 0 {
patches = append(patches, uint(v))
}
}
}
}
}
case "source":
if i, err := strconv.Atoi(string(b)); err == nil {
source = int(i)
}
case "sources":
var f interface{}
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
case []interface{}:
for _, f := range v {
src := map[string]interface{}{}
switch v := f.(type) {
case map[string]interface{}:
switch v := v["pos"].(type) {
case float64:
src["pos"] = uint(v)
}
switch s := v["src"].(type) {
case float64:
if s > 0 {
src["src"] = uint(s)
switch t := v["tag"].(type) {
case string:
var u Units
switch v := units.(type) {
case Units:
u = v
default:
u = Units{}
}
u.Add(int(s), t)
units = u
}
}
}
}
sources = append(sources, src)
}
}
}
case "system", "systemId":
if i, err := strconv.Atoi(string(b)); err == nil {
system = uint(i)
}
case "systemLabel":
systemLabel = string(b)
case "talkgroup", "talkgroupId":
if i, err := strconv.Atoi(string(b)); err == nil {
talkgroup = uint(i)
}
case "talkgroupGroup":
if s := string(b); len(s) > 1 {
talkgroupGroup = s
}
case "talkgroupLabel":
if s := string(b); len(s) > 1 {
talkgroupLabel = s
}
case "talkgroupTag":
if s := string(b); len(s) > 1 {
talkgroupTag = s
}
default:
ParseMultipartContent(call, p, b)
}
}
call := &Call{
Audio: audio,
AudioName: audioName,
AudioType: audioType,
DateTime: dateTime,
Frequencies: frequencies,
Frequency: frequency,
Patches: patches,
Source: source,
Sources: sources,
System: system,
Talkgroup: talkgroup,
systemLabel: systemLabel,
talkgroupGroup: talkgroupGroup,
talkgroupLabel: talkgroupLabel,
talkgroupTag: talkgroupTag,
units: units,
}
if call.IsValid() {
api.HandleCall(key, call, w)
} else {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte("Incomplete call data"))
@ -306,12 +120,8 @@ func (api *Api) TrunkRecorderCallUploadHandler(w http.ResponseWriter, r *http.Re
switch r.Method {
case http.MethodPost:
var (
audio []byte
audioName string
audioType string
key string
meta []byte
system uint
call = NewCall()
key string
)
mediaType, params, err := mime.ParseMediaType(r.Header.Get("Content-Type"))
@ -343,35 +153,33 @@ func (api *Api) TrunkRecorderCallUploadHandler(w http.ResponseWriter, r *http.Re
}
switch p.FormName() {
case "audio":
audio = b
audioName = p.FileName()
audioType = p.Header.Get("Content-Type")
case "key":
key = string(b)
case "meta":
meta = b
case "system":
if i, err := strconv.Atoi(string(b)); err == nil {
system = uint(i)
if err := ParseTrunkRecorderMeta(call, b); err != nil {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte("Invalid call data"))
return
}
}
}
call := &Call{
Audio: audio,
AudioName: audioName,
AudioType: audioType,
System: system,
}
mr = multipart.NewReader(r.Body, params["boundary"])
if err := ParseTrunkRecorderMeta(call, meta); err != nil {
w.WriteHeader(http.StatusExpectationFailed)
w.Write([]byte("Invalid call data"))
return
for {
p, err := mr.NextPart()
if err == io.EOF {
break
} else if err != nil {
continue
}
b, err := io.ReadAll(p)
if err != nil {
continue
}
ParseMultipartContent(call, p, b)
}
if call.IsValid() {

View file

@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"strings"
"sync"
"github.com/google/uuid"
)
@ -107,25 +108,28 @@ func (apikey *Apikey) HasAccess(call *Call) bool {
return false
}
type Apikeys []Apikey
type Apikeys struct {
List []*Apikey
mutex sync.Mutex
}
func (apikeys *Apikeys) FromMap(f []interface{}) {
*apikeys = Apikeys{}
apikeys.List = []*Apikey{}
for _, r := range f {
switch m := r.(type) {
case map[string]interface{}:
apikey := Apikey{}
apikey := &Apikey{}
apikey.FromMap(m)
*apikeys = append(*apikeys, apikey)
apikeys.List = append(apikeys.List, apikey)
}
}
}
func (apikeys *Apikeys) GetApikey(key string) (apikey *Apikey, ok bool) {
for _, apikey := range *apikeys {
for _, apikey := range apikeys.List {
if apikey.Key == key {
return &apikey, true
return apikey, true
}
}
return nil, false
@ -140,7 +144,7 @@ func (apikeys *Apikeys) Read(db *Database) error {
systems string
)
*apikeys = Apikeys{}
apikeys.List = []*Apikey{}
formatError := func(err error) error {
return fmt.Errorf("apikeys.read: %v", err)
@ -151,7 +155,8 @@ func (apikeys *Apikeys) Read(db *Database) error {
}
for rows.Next() {
apikey := Apikey{}
apikey := &Apikey{}
if err = rows.Scan(&id, &apikey.Disabled, &apikey.Ident, &apikey.Key, &order, &systems); err != nil {
break
}
@ -176,7 +181,7 @@ func (apikeys *Apikeys) Read(db *Database) error {
apikey.Systems = []interface{}{}
}
*apikeys = append(*apikeys, apikey)
apikeys.List = append(apikeys.List, apikey)
}
rows.Close()
@ -197,11 +202,13 @@ func (apikeys *Apikeys) Write(db *Database) error {
systems interface{}
)
apikeys.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("apikeys.write %v", err)
}
for _, apikey := range *apikeys {
for _, apikey := range apikeys.List {
switch apikey.Systems {
case "*":
systems = `"*"`
@ -235,7 +242,7 @@ func (apikeys *Apikeys) Write(db *Database) error {
var id uint
rows.Scan(&id)
remove := true
for _, apikey := range *apikeys {
for _, apikey := range apikeys.List {
if apikey.Id == nil || apikey.Id == id {
remove = false
break
@ -264,5 +271,7 @@ func (apikeys *Apikeys) Write(db *Database) error {
}
}
apikeys.mutex.Unlock()
return nil
}

View file

@ -43,6 +43,14 @@ type Call struct {
units interface{}
}
func NewCall() *Call {
return &Call{
Frequencies: []map[string]interface{}{},
Patches: []uint{},
Sources: []map[string]interface{}{},
}
}
func (call *Call) IsValid() bool {
if len(call.Audio) <= 44 {
return false

View file

@ -219,7 +219,7 @@ func (controller *Controller) IngestCall(call *Call) {
system.Label = fmt.Sprintf("System %v", call.System)
}
*controller.Systems = append(*controller.Systems, system)
controller.Systems.List = append(controller.Systems.List, system)
}
if system != nil && talkgroup == nil && (controller.Options.AutoPopulate || system.AutoPopulate) {
@ -242,7 +242,7 @@ func (controller *Controller) IngestCall(call *Call) {
if group, ok = controller.Groups.GetGroup(groupLabel); !ok {
group = &Group{Label: groupLabel}
*controller.Groups = append(*controller.Groups, *group)
controller.Groups.List = append(controller.Groups.List, group)
if err = controller.Groups.Write(controller.Database); err != nil {
logError(err)
@ -271,7 +271,7 @@ func (controller *Controller) IngestCall(call *Call) {
if tag, ok = controller.Tags.GetTag(tagLabel); !ok {
tag = &Tag{Label: tagLabel}
*controller.Tags = append(*controller.Tags, *tag)
controller.Tags.List = append(controller.Tags.List, tag)
if err = controller.Tags.Write(controller.Database); err != nil {
logError(err)
@ -508,8 +508,8 @@ func (controller *Controller) ProcessMessageCommandPin(client *Client, message *
switch v := client.Access.Limit.(type) {
case uint:
count := uint(0)
for _, acc := range *controller.Accesses {
if acc == *client.Access {
for _, acc := range controller.Accesses.List {
if acc == client.Access {
count++
}
}

View file

@ -206,7 +206,7 @@ func (db *Database) migration20191028144433(verbose bool) error {
}
} else {
queries = []string{
"create table `rdioScannerSystems` (`id` integer primary key auto_increment, `createdAt` datetime not null, `updatedAt` datetime not null, `name` varchar(255) not null, `system` integer not null, `talkgroups` json not null default '[]')",
"create table `rdioScannerSystems` (`id` integer primary key auto_increment, `createdAt` datetime not null, `updatedAt` datetime not null, `name` varchar(255) not null, `system` integer not null, `talkgroups` json not null)",
"create unique index `rdio_scanner_systems_system` on `rdioScannerSystems` (`system`)",
}
}
@ -261,7 +261,7 @@ func (db *Database) migration20191220093214(verbose bool) error {
queries = []string{
"alter table `rdioScannerCalls` add column `audioName` varchar(255)",
"alter table `rdioScannerCalls` add column `audioType` varchar(255)",
"alter table `rdioScannerSystems` add column `aliases` json not null default '[]'",
"alter table `rdioScannerSystems` add column `aliases` json not null",
}
}
return db.migrateWithSchema("20191220093214-new-v3-tables", queries, verbose)
@ -297,7 +297,7 @@ func (db *Database) migration20200428132918(verbose bool) error {
} else {
queries = []string{
"drop table `rdioScannerSystems`",
"create table `rdioScannerCalls2` (`id` integer primary key auto_increment, `audio` longblob not null, `audioName` varchar(255), `audioType` varchar(255), `dateTime` datetime not null, `frequencies` json not null default '[]', `frequency` integer, `source` integer, `sources` json not null default '[]', `system` integer not null, `talkgroup` integer not null)",
"create table `rdioScannerCalls2` (`id` integer primary key auto_increment, `audio` longblob not null, `audioName` varchar(255), `audioType` varchar(255), `dateTime` datetime not null, `frequencies` json not null, `frequency` integer, `source` integer, `sources` json not null, `system` integer not null, `talkgroup` integer not null)",
"insert into `rdioScannerCalls2` select `id`, `audio`, `audioName`, `audioType`, `startTime`, `freqList`, `freq`, null, `srcList`, `system`, `talkgroup` from `rdioScannerCalls`",
"drop table `rdioScannerCalls`",
"alter table `rdioScannerCalls2` rename to `rdioScannerCalls`",

View file

@ -29,6 +29,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/fsnotify/fsnotify"
@ -161,16 +162,16 @@ func (dirwatch *Dirwatch) ingestDefault(p string) error {
}
if strings.EqualFold(path.Ext(p), ext) {
call := Call{
AudioName: path.Base(p),
AudioType: mime.TypeByExtension(path.Ext(p)),
}
call := NewCall()
call.AudioName = path.Base(p)
call.AudioType = mime.TypeByExtension(path.Ext(p))
if call.Audio, err = os.ReadFile(p); err != nil {
return err
}
dirwatch.parseMask(&call)
dirwatch.parseMask(call)
switch v := dirwatch.SystemId.(type) {
case uint:
@ -183,7 +184,7 @@ func (dirwatch *Dirwatch) ingestDefault(p string) error {
}
if call.IsValid() {
dirwatch.controller.Ingest <- &call
dirwatch.controller.Ingest <- call
if dirwatch.DeleteAfter {
if err = os.Remove(p); err != nil {
@ -217,23 +218,23 @@ func (dirwatch *Dirwatch) ingestSdrTrunk(p string) error {
return nil
}
call := Call{
AudioName: path.Base(p),
AudioType: mime.TypeByExtension(path.Ext(p)),
}
call := NewCall()
call.AudioName = path.Base(p)
call.AudioType = mime.TypeByExtension(path.Ext(p))
if call.Audio, err = os.ReadFile(p); err != nil {
fmt.Println("err1")
return err
}
if err = ParseSdrTrunkMeta(&call, dirwatch.controller); err != nil {
if err = ParseSdrTrunkMeta(call, dirwatch.controller); err != nil {
fmt.Println("err2")
return err
}
if call.IsValid() {
dirwatch.controller.Ingest <- &call
dirwatch.controller.Ingest <- call
if dirwatch.DeleteAfter {
if err = os.Remove(p); err != nil {
@ -272,10 +273,10 @@ func (dirwatch *Dirwatch) ingestTrunkRecorder(p string) error {
audioName := base + ext
call := Call{
AudioName: path.Base(audioName),
AudioType: mime.TypeByExtension(path.Ext(audioName)),
}
call := NewCall()
call.AudioName = path.Base(audioName)
call.AudioType = mime.TypeByExtension(path.Ext(audioName))
switch v := dirwatch.SystemId.(type) {
case uint:
@ -290,12 +291,12 @@ func (dirwatch *Dirwatch) ingestTrunkRecorder(p string) error {
return err
}
if err = ParseTrunkRecorderMeta(&call, b); err != nil {
if err = ParseTrunkRecorderMeta(call, b); err != nil {
return err
}
if call.IsValid() {
dirwatch.controller.Ingest <- &call
dirwatch.controller.Ingest <- call
}
if dirwatch.DeleteAfter {
@ -428,7 +429,10 @@ func (dirwatch *Dirwatch) parseMask(call *Call) {
switch v := metaval["unit"].(type) {
case string:
if i, err := strconv.Atoi(v); err == nil {
call.Sources = map[string]interface{}{"pos": 0, "src": uint(i)}
switch sources := call.Sources.(type) {
case []map[string]interface{}:
call.Sources = append(sources, map[string]interface{}{"pos": 0, "src": uint(i)})
}
}
}
}
@ -530,19 +534,22 @@ func (dirwatch *Dirwatch) Stop() {
}
}
type Dirwatches []Dirwatch
type Dirwatches struct {
List []*Dirwatch
mutex sync.Mutex
}
func (dirwatches *Dirwatches) FromMap(f []interface{}) {
dirwatches.Stop()
*dirwatches = Dirwatches{}
dirwatches.List = []*Dirwatch{}
for _, f := range f {
switch v := f.(type) {
case map[string]interface{}:
dirwatch := Dirwatch{}
dirwatch := &Dirwatch{}
dirwatch.FromMap(v)
*dirwatches = append(*dirwatches, dirwatch)
dirwatches.List = append(dirwatches.List, dirwatch)
}
}
}
@ -575,7 +582,7 @@ func (dirwatches *Dirwatches) Read(db *Database) error {
}
for rows.Next() {
dirwatch := Dirwatch{}
dirwatch := &Dirwatch{}
if err = rows.Scan(&id, &delay, &dirwatch.DeleteAfter, &dirwatch.Directory, &dirwatch.Disabled, &extension, &frequency, &mask, &order, &systemId, &talkgroupId, &kind, &dirwatch.UsePolling); err != nil {
break
@ -617,7 +624,7 @@ func (dirwatches *Dirwatches) Read(db *Database) error {
dirwatch.Kind = kind.String
}
*dirwatches = append(*dirwatches, dirwatch)
dirwatches.List = append(dirwatches.List, dirwatch)
}
rows.Close()
@ -630,8 +637,8 @@ func (dirwatches *Dirwatches) Read(db *Database) error {
}
func (dirwatches *Dirwatches) Start(controller *Controller) {
for i := range *dirwatches {
if err := (*dirwatches)[i].Start(controller); err != nil {
for i := range dirwatches.List {
if err := dirwatches.List[i].Start(controller); err != nil {
LogEvent(
controller.Database,
LogLevelError,
@ -642,8 +649,8 @@ func (dirwatches *Dirwatches) Start(controller *Controller) {
}
func (dirwatches *Dirwatches) Stop() {
for i := range *dirwatches {
(*dirwatches)[i].Stop()
for i := range dirwatches.List {
dirwatches.List[i].Stop()
}
}
@ -655,11 +662,13 @@ func (dirwatches *Dirwatches) Write(db *Database) error {
rowIds = []uint{}
)
dirwatches.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("dirwatches.write: %v", err)
}
for _, dirwatch := range *dirwatches {
for _, dirwatch := range dirwatches.List {
if err = db.Sql.QueryRow("select count(*) from `rdioScannerDirWatches` where `_id` = ?", dirwatch.Id).Scan(&count); err != nil {
break
}
@ -686,7 +695,7 @@ func (dirwatches *Dirwatches) Write(db *Database) error {
var rowId uint
rows.Scan(&rowId)
remove := true
for _, dirwatch := range *dirwatches {
for _, dirwatch := range dirwatches.List {
if dirwatch.Id == nil || dirwatch.Id == rowId {
remove = false
break
@ -715,6 +724,8 @@ func (dirwatches *Dirwatches) Write(db *Database) error {
}
}
dirwatches.mutex.Unlock()
return nil
}

View file

@ -25,6 +25,7 @@ import (
"net/url"
"path"
"strings"
"sync"
"time"
"github.com/google/uuid"
@ -321,7 +322,10 @@ func (downstream *Downstream) Send(call *Call) error {
return nil
}
type Downstreams []Downstream
type Downstreams struct {
List []*Downstream
mutex sync.Mutex
}
func (downstreams *Downstreams) FromMap(f []interface{}) {
*downstreams = Downstreams{}
@ -329,9 +333,9 @@ func (downstreams *Downstreams) FromMap(f []interface{}) {
for _, r := range f {
switch m := r.(type) {
case map[string]interface{}:
downstream := Downstream{}
downstream := &Downstream{}
downstream.FromMap(m)
*downstreams = append(*downstreams, downstream)
downstreams.List = append(downstreams.List, downstream)
}
}
}
@ -344,7 +348,7 @@ func (downstreams *Downstreams) Read(db *Database) error {
rows *sql.Rows
)
*downstreams = Downstreams{}
downstreams.List = []*Downstream{}
formatError := func(err error) error {
return fmt.Errorf("downstreams.read: %v", err)
@ -355,7 +359,7 @@ func (downstreams *Downstreams) Read(db *Database) error {
}
for rows.Next() {
downstream := Downstream{}
downstream := &Downstream{}
if err = rows.Scan(&id, &downstream.Apikey, &downstream.Disabled, &order, &downstream.Systems, &downstream.Url); err != nil {
break
@ -382,7 +386,7 @@ func (downstreams *Downstreams) Read(db *Database) error {
continue
}
*downstreams = append(*downstreams, downstream)
downstreams.List = append(downstreams.List, downstream)
}
rows.Close()
@ -395,7 +399,7 @@ func (downstreams *Downstreams) Read(db *Database) error {
}
func (downstreams *Downstreams) Send(controller *Controller, call *Call) {
for _, downstream := range *downstreams {
for _, downstream := range downstreams.List {
logEvent := func(logLevel string, message string) {
LogEvent(
controller.Database,
@ -423,11 +427,13 @@ func (downstreams *Downstreams) Write(db *Database) error {
systems interface{}
)
downstreams.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("downstreams.write: %v", err)
}
for _, downstream := range *downstreams {
for _, downstream := range downstreams.List {
switch downstream.Systems {
case "*":
systems = `"*"`
@ -461,7 +467,7 @@ func (downstreams *Downstreams) Write(db *Database) error {
var rowId uint
rows.Scan(&rowId)
remove := true
for _, downstream := range *downstreams {
for _, downstream := range downstreams.List {
if downstream.Id == nil || downstream.Id == rowId {
remove = false
break
@ -490,5 +496,7 @@ func (downstreams *Downstreams) Write(db *Database) error {
}
}
downstreams.mutex.Unlock()
return nil
}

View file

@ -9,10 +9,10 @@ require (
github.com/golang-jwt/jwt/v4 v4.2.0
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.4.2
github.com/kardianos/service v1.2.0
github.com/kardianos/service v1.2.1
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
gopkg.in/ini.v1 v1.66.2
modernc.org/sqlite v1.14.3
modernc.org/sqlite v1.14.4
)
require (
@ -21,8 +21,8 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/stretchr/testify v1.7.0 // indirect
golang.org/x/mod v0.5.1 // indirect
golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 // indirect
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.8 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect

View file

@ -16,15 +16,15 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g=
github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/kardianos/service v1.2.1 h1:AYndMsehS+ywIS6RB9KOlcXzteWUzxgMgBymJD7+BYk=
github.com/kardianos/service v1.2.1/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
@ -47,8 +47,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98 h1:+6WJMRLHlD7X7frgp7TUZ36RnQzSf9wVVTNakEp+nqY=
golang.org/x/net v0.0.0-20220105145211-5b0dc2dfae98/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03 h1:0FB83qp0AzVJm+0wcIlauAjJ+tNdh7jLuacRYCIVv7s=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -65,8 +65,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -142,10 +142,8 @@ modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY=
modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w=
modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU=
modernc.org/ccgo/v3 v3.12.88/go.mod h1:0MFzUHIuSIthpVZyMWiFYMwjiFnhrN5MkvBrUwON+ZM=
modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko=
modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA=
modernc.org/ccgo/v3 v3.12.95/go.mod h1:ZcLyvtocXYi8uF+9Ebm3G8EF8HNY5hGomBqthDp4eC8=
modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4=
modernc.org/ccgo/v3 v3.14.0 h1:Zr1Ny9+7r5yAiXpBdgp8XiXqkNA4ARrRphHGHVXeAp0=
modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q=
@ -188,11 +186,8 @@ modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI=
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE=
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY=
modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ=
modernc.org/libc v1.11.90/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c=
modernc.org/libc v1.11.99/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI=
modernc.org/libc v1.11.104/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ=
modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
modernc.org/libc v1.13.2 h1:GCFjY9bmwDZ/TJC4OZOUWaNgxIxwb104C/QZrqpcVEA=
@ -207,13 +202,13 @@ modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14=
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM=
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.14.3 h1:psrTwgpEujgWEP3FNdsC9yNh5tSeA77U0GeWhHH4XmQ=
modernc.org/sqlite v1.14.3/go.mod h1:xMpicS1i2MJ4C8+Ap0vYBqTwYfpFvdnPE6brbFOtV2Y=
modernc.org/sqlite v1.14.4 h1:F3DRiVZKnCLqIQ0LhEGqBLnw9LcdADciCwCIHQ8bD5g=
modernc.org/sqlite v1.14.4/go.mod h1:LWtcO8JtBrt29KKmTqNNXDjAn36vHa/3nHvOYoVIAjc=
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.9.2 h1:YA87dFLOsR2KqMka371a2Xgr+YsyUwo7OmHVSv/kztw=
modernc.org/tcl v1.9.2/go.mod h1:aw7OnlIoiuJgu1gwbTZtrKnGpDqH9wyH++jZcxdqNsg=
modernc.org/tcl v1.10.0 h1:vux2MNFhSXYqD8Kq4Uc9RjWcgv2c7Atx3da3VpLPPEw=
modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s=
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.2.20 h1:DyboxM1sJR2NB803j2StnbnL6jcQXz273OhHDGu8dGk=
modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo=
modernc.org/z v1.2.21 h1:UO0ptLQLHM2eNistCE6ofm1fMKKXk0n0IkrQly3z5HA=
modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc=

View file

@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"strings"
"sync"
)
type Group struct {
@ -39,17 +40,20 @@ func (group *Group) FromMap(m map[string]interface{}) {
}
}
type Groups []Group
type Groups struct {
List []*Group
mutex sync.Mutex
}
func (groups *Groups) FromMap(f []interface{}) {
*groups = Groups{}
groups.List = []*Group{}
for _, r := range f {
switch m := r.(type) {
case map[string]interface{}:
group := Group{}
group := &Group{}
group.FromMap(m)
*groups = append(*groups, group)
groups.List = append(groups.List, group)
}
}
}
@ -57,15 +61,15 @@ func (groups *Groups) FromMap(f []interface{}) {
func (groups *Groups) GetGroup(f interface{}) (group *Group, ok bool) {
switch v := f.(type) {
case uint:
for _, group := range *groups {
for _, group := range groups.List {
if group.Id == v {
return &group, true
return group, true
}
}
case string:
for _, group := range *groups {
for _, group := range groups.List {
if group.Label == v {
return &group, true
return group, true
}
}
}
@ -147,7 +151,7 @@ func (groups *Groups) Read(db *Database) error {
rows *sql.Rows
)
*groups = Groups{}
groups.List = []*Group{}
formatError := func(err error) error {
return fmt.Errorf("groups.read: %v", err)
@ -158,7 +162,7 @@ func (groups *Groups) Read(db *Database) error {
}
for rows.Next() {
group := Group{}
group := &Group{}
if err = rows.Scan(&id, &group.Label); err != nil {
break
@ -172,7 +176,7 @@ func (groups *Groups) Read(db *Database) error {
continue
}
*groups = append(*groups, group)
groups.List = append(groups.List, group)
}
rows.Close()
@ -192,11 +196,13 @@ func (groups *Groups) Write(db *Database) error {
rowIds = []uint{}
)
groups.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("groups.write %v", err)
}
for _, group := range *groups {
for _, group := range groups.List {
if err = db.Sql.QueryRow("select count(*) from `rdioScannerGroups` where `_id` = ?", group.Id).Scan(&count); err != nil {
break
}
@ -223,7 +229,7 @@ func (groups *Groups) Write(db *Database) error {
var rowId uint
rows.Scan(&rowId)
remove := true
for _, group := range *groups {
for _, group := range groups.List {
if group.Id == nil || group.Id == rowId {
remove = false
break
@ -251,6 +257,9 @@ func (groups *Groups) Write(db *Database) error {
}
}
}
groups.mutex.Unlock()
return nil
}

View file

@ -68,7 +68,9 @@ sys:
}
func (livefeedMap *LivefeedMap) IsEnabled(call *Call) bool {
if (*livefeedMap)[call.System][call.Talkgroup] {
if livefeedMap == nil {
return false
} else if (*livefeedMap)[call.System][call.Talkgroup] {
return true
} else {
switch v := call.Patches.(type) {

View file

@ -19,6 +19,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"sync"
"golang.org/x/crypto/bcrypt"
)
@ -36,6 +37,7 @@ type Options struct {
TagsToggle bool `json:"tagsToggle"`
adminPassword string
adminPasswordNeedChange bool
mutex sync.Mutex
secret string
}
@ -136,6 +138,11 @@ func (options *Options) Read(db *Database) error {
err = db.Sql.QueryRow("select `val` from `rdioScannerConfigs` where `key` = 'adminPassword'").Scan(&f)
if err == nil {
switch v := f.(type) {
case []uint8:
var f string
if err = json.Unmarshal(v, &f); err == nil {
options.adminPassword = f
}
case string:
var f string
if err = json.Unmarshal([]byte(v), &f); err == nil {
@ -147,6 +154,11 @@ func (options *Options) Read(db *Database) error {
err = db.Sql.QueryRow("select `val` from `rdioScannerConfigs` where `key` = 'adminPasswordNeedChange'").Scan(&f)
if err == nil {
switch v := f.(type) {
case []uint8:
var f bool
if err = json.Unmarshal(v, &f); err == nil {
options.adminPasswordNeedChange = f
}
case string:
var f bool
if err = json.Unmarshal([]byte(v), &f); err == nil {
@ -238,6 +250,8 @@ func (options *Options) Write(db *Database) error {
res sql.Result
)
options.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("options.write: %v", err)
}
@ -289,5 +303,7 @@ func (options *Options) Write(db *Database) error {
db.Sql.Exec("insert into `rdioScannerConfigs` (`key`, `val`) values (?, ?)", "options", string(b))
}
options.mutex.Unlock()
return nil
}

View file

@ -18,6 +18,9 @@ package main
import (
"bytes"
"encoding/json"
"mime"
"mime/multipart"
"path"
"regexp"
"strconv"
"strings"
@ -111,6 +114,166 @@ func ParseSdrTrunkMeta(call *Call, controller *Controller) error {
return nil
}
func ParseMultipartContent(call *Call, p *multipart.Part, b []byte) {
switch p.FormName() {
case "audio":
call.Audio = b
call.AudioName = p.FileName()
case "audioName":
call.AudioName = string(b)
call.AudioType = mime.TypeByExtension(path.Ext(string(b)))
case "dateTime":
if regexp.MustCompile(`^[0-9]+$`).Match(b) {
if i, err := strconv.Atoi(string(b)); err == nil {
call.DateTime = time.Unix(int64(i), 0).UTC()
}
} else {
call.DateTime, _ = time.Parse(time.RFC3339, string(b))
call.DateTime = call.DateTime.UTC()
}
case "frequencies":
var f interface{}
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
case []interface{}:
var frequencies = []map[string]interface{}{}
for _, f := range v {
freq := map[string]interface{}{}
switch v := f.(type) {
case map[string]interface{}:
switch v := v["errorCount"].(type) {
case float64:
freq["errorCount"] = uint(v)
}
switch v := v["freq"].(type) {
case float64:
freq["freq"] = uint(v)
}
switch v := v["len"].(type) {
case float64:
freq["len"] = uint(v)
}
switch v := v["pos"].(type) {
case float64:
freq["pos"] = uint(v)
}
switch v := v["spikeCount"].(type) {
case float64:
freq["spikeCount"] = uint(v)
}
}
frequencies = append(frequencies, freq)
}
call.Frequencies = frequencies
}
}
case "frequency":
if i, err := strconv.Atoi(string(b)); err == nil {
call.Frequency = uint(i)
}
case "patches", "patched_talkgroups":
var (
f interface{}
patches = []uint{}
)
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
case []interface{}:
for _, patch := range v {
switch v := patch.(type) {
case float64:
if v > 0 {
patches = append(patches, uint(v))
}
}
}
}
call.Patches = patches
}
case "source":
if i, err := strconv.Atoi(string(b)); err == nil {
call.Source = int(i)
}
case "sources":
var (
f interface{}
units interface{}
)
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
case []interface{}:
var sources = []map[string]interface{}{}
for _, f := range v {
src := map[string]interface{}{}
switch v := f.(type) {
case map[string]interface{}:
switch v := v["pos"].(type) {
case float64:
src["pos"] = uint(v)
}
switch s := v["src"].(type) {
case float64:
if s > 0 {
src["src"] = uint(s)
switch t := v["tag"].(type) {
case string:
var u Units
switch v := units.(type) {
case Units:
u = v
default:
u = Units{}
}
u.Add(int(s), t)
units = u
}
}
}
}
sources = append(sources, src)
}
call.Sources = sources
call.units = units
}
}
case "system", "systemId":
if i, err := strconv.Atoi(string(b)); err == nil {
call.System = uint(i)
}
case "systemLabel":
call.systemLabel = string(b)
case "talkgroup", "talkgroupId":
if i, err := strconv.Atoi(string(b)); err == nil {
call.Talkgroup = uint(i)
}
case "talkgroupGroup":
if s := string(b); len(s) > 1 {
call.talkgroupGroup = s
}
case "talkgroupLabel":
if s := string(b); len(s) > 1 {
call.talkgroupLabel = s
}
case "talkgroupTag":
if s := string(b); len(s) > 1 {
call.talkgroupTag = s
}
}
}
func ParseTrunkRecorderMeta(call *Call, b []byte) error {
m := map[string]interface{}{}

View file

@ -22,6 +22,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
)
type System struct {
@ -85,17 +86,20 @@ func (system *System) FromMap(m map[string]interface{}) {
type SystemMap map[string]interface{}
type Systems []*System
type Systems struct {
List []*System
mutex sync.Mutex
}
func (systems *Systems) FromMap(f []interface{}) {
*systems = Systems{}
systems.List = []*System{}
for _, r := range f {
switch m := r.(type) {
case map[string]interface{}:
system := &System{}
system.FromMap(m)
*systems = append(*systems, system)
systems.List = append(systems.List, system)
}
}
}
@ -103,7 +107,7 @@ func (systems *Systems) FromMap(f []interface{}) {
func (systems *Systems) GetNewSystemId() uint {
NextId:
for i := uint(1); i < 65535; i++ {
for _, s := range *systems {
for _, s := range systems.List {
if s.Id == i {
continue NextId
}
@ -116,13 +120,13 @@ NextId:
func (systems *Systems) GetSystem(f interface{}) (system *System, ok bool) {
switch v := f.(type) {
case uint:
for _, system := range *systems {
for _, system := range systems.List {
if system.Id == v {
return system, true
}
}
case string:
for _, system := range *systems {
for _, system := range systems.List {
if system.Label == v {
return system, true
}
@ -133,21 +137,21 @@ func (systems *Systems) GetSystem(f interface{}) (system *System, ok bool) {
func (systems *Systems) GetScopedSystems(client *Client, groups *Groups, tags *Tags, sortTalkgroups bool) *SystemsMap {
var (
rawSystems = Systems{}
rawSystems = []*System{}
systemsMap = SystemsMap{}
)
if client.Access == nil {
rawSystems = append(rawSystems, *systems...)
rawSystems = append(rawSystems, systems.List...)
} else {
switch v := client.Access.Systems.(type) {
case nil:
rawSystems = append(rawSystems, *systems...)
rawSystems = append(rawSystems, systems.List...)
case string:
if v == "*" {
rawSystems = append(rawSystems, *systems...)
rawSystems = append(rawSystems, systems.List...)
}
case []interface{}:
@ -338,7 +342,7 @@ func (systems *Systems) Read(db *Database) error {
return err
}
*systems = append(*systems, system)
systems.List = append(systems.List, system)
}
rows.Close()
@ -347,8 +351,8 @@ func (systems *Systems) Read(db *Database) error {
return formatError(err)
}
sort.Slice(*systems, func(i int, j int) bool {
return (*systems)[i].Order < (*systems)[j].Order
sort.Slice(systems.List, func(i int, j int) bool {
return systems.List[i].Order < systems.List[j].Order
})
return nil
@ -364,11 +368,13 @@ func (systems *Systems) Write(db *Database) error {
systemIds = []uint{}
)
systems.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("systems.write: %v", err)
}
for _, system := range *systems {
for _, system := range systems.List {
if len(system.Blacklists) > 0 {
blacklists = strings.Join([]string{"[", system.Blacklists.String(), "]"}, "")
} else {
@ -410,7 +416,7 @@ func (systems *Systems) Write(db *Database) error {
var systemId uint
rows.Scan(&rowId, &systemId)
remove := true
for _, system := range *systems {
for _, system := range systems.List {
if system.RowId == nil || system.RowId == rowId {
remove = false
break
@ -456,6 +462,8 @@ func (systems *Systems) Write(db *Database) error {
}
}
systems.mutex.Unlock()
return nil
}

View file

@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"strings"
"sync"
)
type Tag struct {
@ -39,17 +40,20 @@ func (tag *Tag) FromMap(m map[string]interface{}) {
}
}
type Tags []Tag
type Tags struct {
List []*Tag
mutex sync.Mutex
}
func (tags *Tags) FromMap(f []interface{}) {
*tags = Tags{}
tags.List = []*Tag{}
for _, r := range f {
switch m := r.(type) {
case map[string]interface{}:
tag := Tag{}
tag := &Tag{}
tag.FromMap(m)
*tags = append(*tags, tag)
tags.List = append(tags.List, tag)
}
}
}
@ -57,15 +61,15 @@ func (tags *Tags) FromMap(f []interface{}) {
func (tags *Tags) GetTag(f interface{}) (tag *Tag, ok bool) {
switch v := f.(type) {
case uint:
for _, tag := range *tags {
for _, tag := range tags.List {
if tag.Id == v {
return &tag, true
return tag, true
}
}
case string:
for _, tag := range *tags {
for _, tag := range tags.List {
if tag.Label == v {
return &tag, true
return tag, true
}
}
}
@ -147,7 +151,7 @@ func (tags *Tags) Read(db *Database) error {
rows *sql.Rows
)
*tags = Tags{}
tags.List = []*Tag{}
formatError := func(err error) error {
return fmt.Errorf("tags read: %v", err)
@ -158,7 +162,7 @@ func (tags *Tags) Read(db *Database) error {
}
for rows.Next() {
tag := Tag{}
tag := &Tag{}
if err = rows.Scan(&id, &tag.Label); err != nil {
break
@ -168,7 +172,7 @@ func (tags *Tags) Read(db *Database) error {
tag.Id = uint(id.Float64)
}
*tags = append(*tags, tag)
tags.List = append(tags.List, tag)
}
rows.Close()
@ -188,11 +192,13 @@ func (tags *Tags) Write(db *Database) error {
rowIds = []uint{}
)
tags.mutex.Lock()
formatError := func(err error) error {
return fmt.Errorf("tags write %v", err)
}
for _, tag := range *tags {
for _, tag := range tags.List {
if err = db.Sql.QueryRow("select count(*) from `rdioScannerTags` where `_id` = ?", tag.Id).Scan(&count); err != nil {
break
}
@ -218,7 +224,7 @@ func (tags *Tags) Write(db *Database) error {
var rowId uint
rows.Scan(&rowId)
remove := true
for _, tag := range *tags {
for _, tag := range tags.List {
if tag.Id == nil || tag.Id == rowId {
remove = false
break
@ -247,6 +253,8 @@ func (tags *Tags) Write(db *Database) error {
}
}
tags.mutex.Unlock()
return nil
}

View file

@ -15,4 +15,4 @@
package main
const Version = "6.1.2"
const Version = "6.1.3"