mirror of
https://github.com/chuot/rdio-scanner.git
synced 2026-08-13 08:33:00 -06:00
Version 6.1.7
This commit is contained in:
parent
0534693937
commit
1eebbc1154
|
|
@ -49,6 +49,14 @@ _v6.1.6_
|
|||
|
||||
- Fix webapp not reporting the correct version.
|
||||
|
||||
_v6.1.7_
|
||||
|
||||
- More concurrency mutexes to resolve SQL_BUSY errors.
|
||||
- Better internal management of dirwatches.
|
||||
- Fix SDRTrunk files not being ingested (discussion #108).
|
||||
- Fix Trunk Recorder talkgroup_tag assign to the wrong property (issue #115).
|
||||
- Improved the way the talkgroup label and name are autopopulated. If Trunk Recorder sends a talkgroup_tag with an empty value or with a single `-`, it will not overwrite the talkgroup label.
|
||||
|
||||
## Version 6.0
|
||||
|
||||
- Backend server rewritten in Go for better performance and ease of installation.
|
||||
|
|
|
|||
16
COMPILING.md
16
COMPILING.md
|
|
@ -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.6.zip
|
||||
rdio-scanner-darwin-arm64-v6.1.6.zip
|
||||
rdio-scanner-freebsd-amd64-v6.1.6.zip
|
||||
rdio-scanner-linux-386-v6.1.6.zip
|
||||
rdio-scanner-linux-amd64-v6.1.6.zip
|
||||
rdio-scanner-linux-arm64-v6.1.6.zip
|
||||
rdio-scanner-linux-arm-v6.1.6.zip
|
||||
rdio-scanner-windows-amd64-v6.1.6.zip
|
||||
rdio-scanner-darwin-amd64-v6.1.7.zip
|
||||
rdio-scanner-darwin-arm64-v6.1.7.zip
|
||||
rdio-scanner-freebsd-amd64-v6.1.7.zip
|
||||
rdio-scanner-linux-386-v6.1.7.zip
|
||||
rdio-scanner-linux-amd64-v6.1.7.zip
|
||||
rdio-scanner-linux-arm64-v6.1.7.zip
|
||||
rdio-scanner-linux-arm-v6.1.7.zip
|
||||
rdio-scanner-windows-amd64-v6.1.7.zip
|
||||
|
||||
**Happy Rdio scanning !**
|
||||
4
Makefile
4
Makefile
|
|
@ -16,8 +16,8 @@
|
|||
################################################################################
|
||||
|
||||
app := rdio-scanner
|
||||
date := 2022/01/24
|
||||
ver := 6.1.6
|
||||
date := 2022/01/27
|
||||
ver := 6.1.7
|
||||
|
||||
client := $(wildcard client/*.json client/*.ts)
|
||||
server := $(wildcard server/*.go)
|
||||
|
|
|
|||
2205
client/package-lock.json
generated
2205
client/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -25,7 +25,6 @@
|
|||
"@typescript-eslint/parser": "^5.10.0",
|
||||
"ajv-keywords": "^5.1.0",
|
||||
"eslint": "^8.7.0",
|
||||
"npm-check-updates": "^12.2.1",
|
||||
"ts-node": "~10.4.0",
|
||||
"typescript": "~4.4.4"
|
||||
},
|
||||
|
|
@ -39,5 +38,5 @@
|
|||
"build": "ng build --base-href ./ --configuration production",
|
||||
"start": "ng serve"
|
||||
},
|
||||
"version": "6.1.6"
|
||||
"version": "6.1.7"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ export class RdioScannerMainComponent implements OnDestroy, OnInit {
|
|||
|
||||
this.callFrequency = typeof this.call.frequency === 'number'
|
||||
? this.formatFrequency(this.call.frequency)
|
||||
: this.call.audioName?.replace(/\..+$/, '') || '';
|
||||
: '';
|
||||
|
||||
this.callSpike = '';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.6.zip
|
||||
Archive: /Users/rdio/Downloads/rdio-scanner-darwin-arm64-v6.1.6.zip
|
||||
> ~/Downloads/rdio-scanner-darwin-arm64-v6.1.7.zip
|
||||
Archive: /Users/rdio/Downloads/rdio-scanner-darwin-arm64-v6.1.7.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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 08:38:06 server started
|
||||
2022/01/24 08:38:06 main interface at http://macos.local:3000
|
||||
2022/01/24 08:38:06 admin interface at http://macos.local:3000/admin
|
||||
2022/01/27 08:38:06 server started
|
||||
2022/01/27 08:38:06 main interface at http://macos.local:3000
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 08:48:03 server started
|
||||
2022/01/24 08:48:03 main interface at http://macos.local
|
||||
2022/01/24 08:48:03 admin interface at http://macos.local/admin
|
||||
2022/01/27 08:48:03 server started
|
||||
2022/01/27 08:48:03 main interface at http://macos.local
|
||||
2022/01/27 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/24 08:49:16 generating ssl certificate files
|
||||
2022/01/24 08:49:17 ssl files created
|
||||
2022/01/27 08:49:16 generating ssl certificate files
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 08:50:58 server started
|
||||
2022/01/24 08:50:58 main interface at http://macos.local
|
||||
2022/01/24 08:50:58 main interface at https://macos.local
|
||||
2022/01/24 08:50:58 admin interface at https://macos.local/admin
|
||||
2022/01/27 08:50:58 server started
|
||||
2022/01/27 08:50:58 main interface at http://macos.local
|
||||
2022/01/27 08:50:58 main interface at https://macos.local
|
||||
2022/01/27 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/24 08:52:24 rdio-scanner.ini file created
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 08:54:08 server started
|
||||
2022/01/24 08:54:08 main interface at http://macos.local
|
||||
2022/01/24 08:54:08 main interface at https://macos.local
|
||||
2022/01/24 08:54:08 admin interface at https://macos.local/admin
|
||||
2022/01/27 08:54:08 server started
|
||||
2022/01/27 08:54:08 main interface at http://macos.local
|
||||
2022/01/27 08:54:08 main interface at https://macos.local
|
||||
2022/01/27 08:54:08 admin interface at https://macos.local/admin
|
||||
|
||||
## Install Rdio Scanner as a service
|
||||
|
||||
|
|
|
|||
|
|
@ -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.6.zip
|
||||
Archive: ../rdio-scanner-freebsd-amd64-v6.1.6.zip
|
||||
> ~/rdio-scanner-freebsd-amd64-v6.1.7.zip
|
||||
Archive: ../rdio-scanner-freebsd-amd64-v6.1.7.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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 08:16:36 server started
|
||||
2022/01/24 08:16:36 main interface at http://pc-freebsd:3000
|
||||
2022/01/24 08:16:36 admin interface at http://pc-freebsd:3000/admin
|
||||
2022/01/27 08:16:36 server started
|
||||
2022/01/27 08:16:36 main interface at http://pc-freebsd:3000
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 08:19:38 server started
|
||||
2022/01/24 08:19:38 main interface at http://pc-freebsd
|
||||
2022/01/24 08:19:38 admin interface at http://pc-freebsd/admin
|
||||
2022/01/27 08:19:38 server started
|
||||
2022/01/27 08:19:38 main interface at http://pc-freebsd
|
||||
2022/01/27 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/24 10:32:17 generating ssl certificate files
|
||||
2022/01/24 10:32:19 ssl files created
|
||||
2022/01/27 10:32:17 generating ssl certificate files
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 10:34:29 server started
|
||||
2022/01/24 10:34:29 main interface at http://pc-freebsd
|
||||
2022/01/24 10:34:29 main interface at https://pc-freebsd
|
||||
2022/01/24 10:34:29 admin interface at https://pc-freebsd/admin
|
||||
2022/01/27 10:34:29 server started
|
||||
2022/01/27 10:34:29 main interface at http://pc-freebsd
|
||||
2022/01/27 10:34:29 main interface at https://pc-freebsd
|
||||
2022/01/27 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/24 10:37:00 rdio-scanner.ini file created
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 10:38:28 server started
|
||||
2022/01/24 10:38:29 main interface at http://pc-freebsd
|
||||
2022/01/24 10:38:29 main interface at https://pc-freebsd
|
||||
2022/01/24 10:38:29 admin interface at https://pc-freebsd/admin
|
||||
2022/01/27 10:38:28 server started
|
||||
2022/01/27 10:38:29 main interface at http://pc-freebsd
|
||||
2022/01/27 10:38:29 main interface at https://pc-freebsd
|
||||
2022/01/27 10:38:29 admin interface at https://pc-freebsd/admin
|
||||
|
||||
## Install Rdio Scanner as a service
|
||||
|
||||
|
|
|
|||
|
|
@ -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.6.zip
|
||||
Archive: /home/rdio/Downloads/rdio-scanner-linux-amd64-v6.1.6.zip
|
||||
> ~/Downloads/rdio-scanner-linux-amd64-v6.1.7.zip
|
||||
Archive: /home/rdio/Downloads/rdio-scanner-linux-amd64-v6.1.7.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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 09:11:48 server started
|
||||
2022/01/24 09:11:48 main interface at http://pc-linux:3000
|
||||
2022/01/24 09:11:48 admin interface at http://pc-linux:3000/admin
|
||||
2022/01/27 09:11:48 server started
|
||||
2022/01/27 09:11:48 main interface at http://pc-linux:3000
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 09:14:00 server started
|
||||
2022/01/24 09:14:00 main interface at http://pc-linux
|
||||
2022/01/24 09:14:00 admin interface at http://pc-linux/admin
|
||||
2022/01/27 09:14:00 server started
|
||||
2022/01/27 09:14:00 main interface at http://pc-linux
|
||||
2022/01/27 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/24 09:15:03 generating ssl certificate files
|
||||
2022/01/24 09:15:05 ssl files created
|
||||
2022/01/27 09:15:03 generating ssl certificate files
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 09:16:47 server started
|
||||
2022/01/24 09:16:47 main interface at http://pc-linux
|
||||
2022/01/24 09:16:47 main interface at https://pc-linux
|
||||
2022/01/24 09:16:47 admin interface at https://pc-linux/admin
|
||||
2022/01/27 09:16:47 server started
|
||||
2022/01/27 09:16:47 main interface at http://pc-linux
|
||||
2022/01/27 09:16:47 main interface at https://pc-linux
|
||||
2022/01/27 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/24 09:19:29 rdio-scanner.ini file created
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 09:20:40 server started
|
||||
2022/01/24 09:20:40 main interface at http://pc-linux
|
||||
2022/01/24 09:20:40 main interface at https://pc-linux
|
||||
2022/01/24 09:20:40 admin interface at https://pc-linux/admin
|
||||
2022/01/27 09:20:40 server started
|
||||
2022/01/27 09:20:40 main interface at http://pc-linux
|
||||
2022/01/27 09:20:40 main interface at https://pc-linux
|
||||
2022/01/27 09:20:40 admin interface at https://pc-linux/admin
|
||||
|
||||
## Install Rdio Scanner as a service
|
||||
|
||||
|
|
|
|||
|
|
@ -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.6.zip
|
||||
..\downloads\rdio-scanner-windows-amd64-v6.1.7.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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 13:48:48 server started
|
||||
2022/01/24 13:48:48 main interface at http://pc-windows:3000
|
||||
2022/01/24 13:48:48 admin interface at http://pc-windows:3000/admin
|
||||
2022/01/27 13:48:48 server started
|
||||
2022/01/27 13:48:48 main interface at http://pc-windows:3000
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 10:53:31 server started
|
||||
2022/01/24 10:53:31 main interface at http://pc-windows
|
||||
2022/01/24 10:53:31 admin interface at http://pc-windows/admin
|
||||
2022/01/27 10:53:31 server started
|
||||
2022/01/27 10:53:31 main interface at http://pc-windows
|
||||
2022/01/27 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/24 10:58:51 generating ssl certificate files
|
||||
2022/01/24 10:58:54 ssl files created
|
||||
2022/01/27 10:58:51 generating ssl certificate files
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 11:05:43 server started
|
||||
2022/01/24 11:05:43 main interface at http://pc-windows
|
||||
2022/01/24 11:05:43 main interface at https://pc-windows
|
||||
2022/01/24 11:05:43 admin interface at https://pc-windows/admin
|
||||
2022/01/27 11:05:43 server started
|
||||
2022/01/27 11:05:43 main interface at http://pc-windows
|
||||
2022/01/27 11:05:43 main interface at https://pc-windows
|
||||
2022/01/27 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/24 11:08:28 rdio-scanner.ini file created
|
||||
2022/01/27 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.6
|
||||
Rdio Scanner v6.1.7
|
||||
----------------------------------
|
||||
2022/01/24 11:11:28 server started
|
||||
2022/01/24 11:11:28 main interface at http://pc-windows
|
||||
2022/01/24 11:11:28 main interface at https://pc-windows
|
||||
2022/01/24 11:11:28 admin interface at https://pc-windows/admin
|
||||
2022/01/27 11:11:28 server started
|
||||
2022/01/27 11:11:28 main interface at http://pc-windows
|
||||
2022/01/27 11:11:28 main interface at https://pc-windows
|
||||
2022/01/27 11:11:28 admin interface at https://pc-windows/admin
|
||||
|
||||
\pagebreak{}
|
||||
|
||||
|
|
|
|||
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "rdio-scanner",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
1
package.json
Normal file
1
package.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -127,13 +127,13 @@ func (access *Access) HasExpired() bool {
|
|||
|
||||
type Accesses struct {
|
||||
List []*Access
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewAccesses() *Accesses {
|
||||
return &Accesses{
|
||||
List: []*Access{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,8 +154,8 @@ func (accesses *Accesses) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (accesses *Accesses) GetAccess(code string) (access *Access, ok bool) {
|
||||
accesses.mutex.RLock()
|
||||
defer accesses.mutex.RUnlock()
|
||||
accesses.mutex.Lock()
|
||||
defer accesses.mutex.Unlock()
|
||||
|
||||
for _, access := range accesses.List {
|
||||
if access.Code == code {
|
||||
|
|
@ -167,8 +167,8 @@ func (accesses *Accesses) GetAccess(code string) (access *Access, ok bool) {
|
|||
}
|
||||
|
||||
func (accesses *Accesses) IsRestricted() bool {
|
||||
accesses.mutex.RLock()
|
||||
defer accesses.mutex.RUnlock()
|
||||
accesses.mutex.Lock()
|
||||
defer accesses.mutex.Unlock()
|
||||
|
||||
return len(accesses.List) > 0
|
||||
}
|
||||
|
|
@ -185,8 +185,8 @@ func (accesses *Accesses) Read(db *Database) error {
|
|||
t time.Time
|
||||
)
|
||||
|
||||
accesses.mutex.RLock()
|
||||
defer accesses.mutex.RUnlock()
|
||||
accesses.mutex.Lock()
|
||||
defer accesses.mutex.Unlock()
|
||||
|
||||
accesses.List = []*Access{}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
|
|
@ -47,6 +48,7 @@ type Admin struct {
|
|||
Register chan *websocket.Conn
|
||||
Tokens []string
|
||||
Unregister chan *websocket.Conn
|
||||
mutex sync.Mutex
|
||||
running bool
|
||||
}
|
||||
|
||||
|
|
@ -68,6 +70,7 @@ func NewAdmin(controller *Controller) *Admin {
|
|||
Register: make(chan *websocket.Conn, 100),
|
||||
Tokens: []string{},
|
||||
Unregister: make(chan *websocket.Conn, 100),
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -145,6 +148,11 @@ func (admin *Admin) ConfigHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}()
|
||||
|
||||
} else {
|
||||
admin.Controller.Calls.mutex.Lock()
|
||||
admin.mutex.Lock()
|
||||
defer admin.mutex.Unlock()
|
||||
defer admin.Controller.Calls.mutex.Unlock()
|
||||
|
||||
logError := func(err error) {
|
||||
admin.Controller.Logs.LogEvent(admin.Controller.Database, LogLevelError, fmt.Sprintf("admin.confighandler.put: %s", err.Error()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,13 +110,13 @@ func (apikey *Apikey) HasAccess(call *Call) bool {
|
|||
|
||||
type Apikeys struct {
|
||||
List []*Apikey
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewApikeys() *Apikeys {
|
||||
return &Apikeys{
|
||||
List: []*Apikey{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -137,8 +137,8 @@ func (apikeys *Apikeys) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (apikeys *Apikeys) GetApikey(key string) (apikey *Apikey, ok bool) {
|
||||
apikeys.mutex.RLock()
|
||||
defer apikeys.mutex.RUnlock()
|
||||
apikeys.mutex.Lock()
|
||||
defer apikeys.mutex.Unlock()
|
||||
|
||||
for _, apikey := range apikeys.List {
|
||||
if apikey.Key == key && !apikey.Disabled {
|
||||
|
|
@ -157,8 +157,8 @@ func (apikeys *Apikeys) Read(db *Database) error {
|
|||
systems string
|
||||
)
|
||||
|
||||
apikeys.mutex.RLock()
|
||||
defer apikeys.mutex.RUnlock()
|
||||
apikeys.mutex.Lock()
|
||||
defer apikeys.mutex.Unlock()
|
||||
|
||||
apikeys.List = []*Apikey{}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,20 +106,20 @@ func (call *Call) ToJson() (string, error) {
|
|||
}
|
||||
|
||||
type Calls struct {
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewCalls() *Calls {
|
||||
return &Calls{
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (calls *Calls) CheckDuplicate(call *Call, msTimeFrame uint, db *Database) bool {
|
||||
var count uint
|
||||
|
||||
calls.mutex.RLock()
|
||||
defer calls.mutex.RUnlock()
|
||||
calls.mutex.Lock()
|
||||
defer calls.mutex.Unlock()
|
||||
|
||||
d := time.Duration(msTimeFrame) * time.Millisecond
|
||||
from := call.DateTime.Add(-d).Format(db.DateTimeFormat)
|
||||
|
|
@ -142,8 +142,8 @@ func (calls *Calls) GetCall(id uint, db *Database) (*Call, error) {
|
|||
t time.Time
|
||||
)
|
||||
|
||||
calls.mutex.RLock()
|
||||
defer calls.mutex.RUnlock()
|
||||
calls.mutex.Lock()
|
||||
defer calls.mutex.Unlock()
|
||||
|
||||
call := Call{}
|
||||
|
||||
|
|
@ -209,8 +209,8 @@ func (calls *Calls) Search(searchOptions *CallsSearchOptions, client *Client) (*
|
|||
where string = "true"
|
||||
)
|
||||
|
||||
calls.mutex.RLock()
|
||||
defer calls.mutex.RUnlock()
|
||||
calls.mutex.Lock()
|
||||
defer calls.mutex.Unlock()
|
||||
|
||||
db := client.Controller.Database
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ func (config *Config) GetPath(p string) string {
|
|||
if path.IsAbs(p) {
|
||||
return p
|
||||
}
|
||||
return path.Join(config.BaseDir, p)
|
||||
return filepath.Join(config.BaseDir, p)
|
||||
}
|
||||
|
||||
func (config *Config) GetSslCaCertFilePath() string {
|
||||
|
|
|
|||
|
|
@ -81,10 +81,6 @@ func NewController(config *Config) *Controller {
|
|||
return controller
|
||||
}
|
||||
|
||||
func (controller *Controller) CheckDuplicate(call *Call) bool {
|
||||
return controller.Calls.CheckDuplicate(call, controller.Options.DuplicateDetectionTimeFrame, controller.Database)
|
||||
}
|
||||
|
||||
func (controller *Controller) ConvertAudio(call *Call) {
|
||||
var (
|
||||
args = []string{"-i", "-"}
|
||||
|
|
@ -295,7 +291,6 @@ func (controller *Controller) IngestCall(call *Call) {
|
|||
GroupId: groupId,
|
||||
Id: call.Talkgroup,
|
||||
Label: fmt.Sprintf("%d", call.Talkgroup),
|
||||
Name: fmt.Sprintf("Talkgroup %d", call.Talkgroup),
|
||||
TagId: tagId,
|
||||
}
|
||||
|
||||
|
|
@ -316,6 +311,11 @@ func (controller *Controller) IngestCall(call *Call) {
|
|||
populated = true
|
||||
talkgroup.Name = v
|
||||
}
|
||||
default:
|
||||
if len(talkgroup.Name) == 0 {
|
||||
populated = true
|
||||
talkgroup.Name = talkgroup.Label
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,7 +350,7 @@ func (controller *Controller) IngestCall(call *Call) {
|
|||
}
|
||||
|
||||
if !controller.Options.DisableDuplicateDetection {
|
||||
if controller.CheckDuplicate(call) {
|
||||
if controller.Calls.CheckDuplicate(call, controller.Options.DuplicateDetectionTimeFrame, controller.Database) {
|
||||
logCall(call, LogLevelWarn, "duplicate call rejected")
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,9 +61,10 @@ func NewDatabase(config *Config) *Database {
|
|||
log.Fatalf("unknown database type %s\n", config.DbType)
|
||||
}
|
||||
|
||||
database.Sql.SetConnMaxIdleTime(time.Second * 5)
|
||||
database.Sql.SetConnMaxLifetime(0)
|
||||
database.Sql.SetMaxIdleConns(10)
|
||||
database.Sql.SetMaxOpenConns(10)
|
||||
database.Sql.SetMaxIdleConns(64)
|
||||
database.Sql.SetMaxOpenConns(64)
|
||||
|
||||
if err = database.migrate(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ var defaults Defaults = Defaults{
|
|||
"Air",
|
||||
"EMS",
|
||||
"Fire",
|
||||
"Interop",
|
||||
"Law",
|
||||
},
|
||||
keypadBeeps: "uniden",
|
||||
|
|
@ -102,15 +103,13 @@ var defaults Defaults = Defaults{
|
|||
},
|
||||
systems: []System{},
|
||||
tags: []string{
|
||||
"Air Apron",
|
||||
"Air Ground",
|
||||
"Air Traffic",
|
||||
"EMS Dispatch ",
|
||||
"EMS Operations ",
|
||||
"Air Traffic Control",
|
||||
"Emergency ",
|
||||
"Fire Dispatch",
|
||||
"Fire Tac",
|
||||
"Fire Talk",
|
||||
"Law Dispatch",
|
||||
"Law Talk",
|
||||
"Interop",
|
||||
"Security",
|
||||
"Service",
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"mime"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
|
@ -57,6 +58,7 @@ type Dirwatch struct {
|
|||
UsePolling bool `json:"usePolling"`
|
||||
controller *Controller
|
||||
dirs map[string]bool
|
||||
pending map[string]*time.Timer
|
||||
running bool
|
||||
watcher *fsnotify.Watcher
|
||||
}
|
||||
|
|
@ -465,7 +467,11 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
|
|||
|
||||
newTimer := func(eventName string) *time.Timer {
|
||||
return time.AfterFunc(2*time.Second, func() {
|
||||
dirwatch.Ingest(eventName)
|
||||
if dirwatch.running {
|
||||
if _, err := os.Stat(eventName); err == nil {
|
||||
dirwatch.Ingest(eventName)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -475,6 +481,7 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
|
|||
if dirwatch.watcher == nil {
|
||||
break
|
||||
}
|
||||
|
||||
if event, ok := <-dirwatch.watcher.Events; ok {
|
||||
switch event.Op {
|
||||
case fsnotify.Create:
|
||||
|
|
@ -482,11 +489,16 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
|
|||
case uint:
|
||||
time.Sleep(time.Duration(v) * time.Millisecond)
|
||||
}
|
||||
|
||||
if dirwatch.isDir(event.Name) {
|
||||
if err := dirwatch.walkDir(event.Name); err != nil {
|
||||
logError(err)
|
||||
}
|
||||
|
||||
} else {
|
||||
if pending[event.Name] != nil {
|
||||
pending[event.Name].Stop()
|
||||
}
|
||||
pending[event.Name] = newTimer(event.Name)
|
||||
}
|
||||
|
||||
|
|
@ -501,16 +513,28 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
|
|||
|
||||
case fsnotify.Write:
|
||||
if pending[event.Name] != nil {
|
||||
pending[event.Name].Stop()
|
||||
if pending[event.Name] != nil {
|
||||
pending[event.Name].Stop()
|
||||
}
|
||||
pending[event.Name] = newTimer(event.Name)
|
||||
}
|
||||
}
|
||||
|
||||
} else if dirwatch.running {
|
||||
dirwatch.watcher.Close()
|
||||
dirwatch.watcher, _ = fsnotify.NewWatcher()
|
||||
if dirwatch.watcher != nil {
|
||||
dirwatch.watcher.Close()
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
if dirwatch.watcher, err = fsnotify.NewWatcher(); err != nil {
|
||||
controller.Logs.LogEvent(
|
||||
controller.Database,
|
||||
LogLevelError,
|
||||
fmt.Sprintf("dirwatch.watcher.restart: %s", err.Error()),
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
dirwatch.Stop()
|
||||
break
|
||||
|
|
@ -521,10 +545,12 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
|
|||
go watcher()
|
||||
|
||||
go func() {
|
||||
time.Sleep(2 * time.Second)
|
||||
if err := fs.WalkDir(os.DirFS(dirwatch.Directory), ".", func(p string, d fs.DirEntry, err error) error {
|
||||
if !dirwatch.running {
|
||||
return nil
|
||||
}
|
||||
|
||||
fs.WalkDir(os.DirFS(dirwatch.Directory), ".", func(p string, d fs.DirEntry, err error) error {
|
||||
fp := path.Join(dirwatch.Directory, p)
|
||||
fp := filepath.Join(dirwatch.Directory, p)
|
||||
|
||||
if dirwatch.isDir(fp) {
|
||||
dirwatch.dirs[fp] = true
|
||||
|
|
@ -533,31 +559,42 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
|
|||
} else if dirwatch.DeleteAfter {
|
||||
dirwatch.Ingest(fp)
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
}); err != nil {
|
||||
controller.Logs.LogEvent(
|
||||
controller.Database,
|
||||
LogLevelError,
|
||||
fmt.Sprintf("dirwatch.walkdir: %s", err.Error()),
|
||||
)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dirwatch *Dirwatch) Stop() {
|
||||
dirwatch.running = false
|
||||
|
||||
for k := range dirwatch.pending {
|
||||
dirwatch.pending[k].Stop()
|
||||
}
|
||||
|
||||
if dirwatch.watcher != nil {
|
||||
dirwatch.watcher.Close()
|
||||
dirwatch.watcher = nil
|
||||
}
|
||||
|
||||
dirwatch.running = false
|
||||
}
|
||||
|
||||
type Dirwatches struct {
|
||||
List []*Dirwatch
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewDirwatches() *Dirwatches {
|
||||
return &Dirwatches{
|
||||
List: []*Dirwatch{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -594,8 +631,8 @@ func (dirwatches *Dirwatches) Read(db *Database) error {
|
|||
talkgroupId sql.NullFloat64
|
||||
)
|
||||
|
||||
dirwatches.mutex.RLock()
|
||||
defer dirwatches.mutex.RUnlock()
|
||||
dirwatches.mutex.Lock()
|
||||
defer dirwatches.mutex.Unlock()
|
||||
|
||||
dirwatches.Stop()
|
||||
|
||||
|
|
@ -610,7 +647,7 @@ func (dirwatches *Dirwatches) Read(db *Database) error {
|
|||
}
|
||||
|
||||
for rows.Next() {
|
||||
dirwatch := &Dirwatch{}
|
||||
dirwatch := &Dirwatch{pending: map[string]*time.Timer{}}
|
||||
|
||||
if err = rows.Scan(&id, &delay, &dirwatch.DeleteAfter, &dirwatch.Directory, &dirwatch.Disabled, &extension, &frequency, &mask, &order, &systemId, &talkgroupId, &kind, &dirwatch.UsePolling); err != nil {
|
||||
break
|
||||
|
|
@ -770,7 +807,7 @@ func (dirwatch *Dirwatch) walkDir(d string) error {
|
|||
dfs := os.DirFS(d)
|
||||
|
||||
return fs.WalkDir(dfs, ".", func(p string, de fs.DirEntry, err error) error {
|
||||
fp := path.Join(d, p)
|
||||
fp := filepath.Join(d, p)
|
||||
if dirwatch.isDir(fp) {
|
||||
if !dirwatch.dirs[fp] {
|
||||
dirwatch.dirs[fp] = true
|
||||
|
|
|
|||
|
|
@ -350,13 +350,13 @@ func (downstream *Downstream) Send(call *Call) error {
|
|||
|
||||
type Downstreams struct {
|
||||
List []*Downstream
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewDownstreams() *Downstreams {
|
||||
return &Downstreams{
|
||||
List: []*Downstream{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -384,8 +384,8 @@ func (downstreams *Downstreams) Read(db *Database) error {
|
|||
rows *sql.Rows
|
||||
)
|
||||
|
||||
downstreams.mutex.RLock()
|
||||
defer downstreams.mutex.RUnlock()
|
||||
downstreams.mutex.Lock()
|
||||
defer downstreams.mutex.Unlock()
|
||||
|
||||
downstreams.List = []*Downstream{}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ require (
|
|||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.35.22 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.11 // indirect
|
||||
modernc.org/libc v1.14.4 // indirect
|
||||
modernc.org/ccgo/v3 v3.15.13 // indirect
|
||||
modernc.org/libc v1.14.5 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.0.5 // indirect
|
||||
modernc.org/opt v0.1.1 // indirect
|
||||
|
|
|
|||
|
|
@ -152,10 +152,12 @@ modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6
|
|||
modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
|
||||
modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0=
|
||||
modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8=
|
||||
modernc.org/ccgo/v3 v3.15.11 h1:rBUQkkX3u/Sh1ipCDCCwGnaPIjaErgtR23S5mHzuJH4=
|
||||
modernc.org/ccgo/v3 v3.15.11/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
|
||||
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA=
|
||||
modernc.org/ccgo/v3 v3.15.12/go.mod h1:VFePOWoCd8uDGRJpq/zfJ29D0EVzMSyID8LCMWYbX6I=
|
||||
modernc.org/ccgo/v3 v3.15.13 h1:hqlCzNJTXLrhS70y1PqWckrF9x1btSQRC7JFuQcBg5c=
|
||||
modernc.org/ccgo/v3 v3.15.13/go.mod h1:QHtvdpeODlXjdK3tsbpyK+7U9JV4PQsrPGIbtmc0KfY=
|
||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/ccorpus v1.11.4 h1:YOmQBBzE8GC/puUx76D5j/gJYIZQsydrh6VMJVfXF0M=
|
||||
modernc.org/ccorpus v1.11.4/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w=
|
||||
|
|
@ -201,8 +203,8 @@ modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
|
|||
modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk=
|
||||
modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34=
|
||||
modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
|
||||
modernc.org/libc v1.14.4 h1:Sw2GDhSQbQF75VKC6RSd5//QH2gj9TgBzjLNZTW6m00=
|
||||
modernc.org/libc v1.14.4/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ=
|
||||
modernc.org/libc v1.14.5 h1:DAHvwGoVRDZs5iJXnX9RJrgXSsorupCWmJ2ac964Owk=
|
||||
modernc.org/libc v1.14.5/go.mod h1:2PJHINagVxO4QW/5OQdRrvMYo+bm5ClpUFfyXCYl9ak=
|
||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
|
|
|
|||
|
|
@ -42,13 +42,13 @@ func (group *Group) FromMap(m map[string]interface{}) {
|
|||
|
||||
type Groups struct {
|
||||
List []*Group
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewGroups() *Groups {
|
||||
return &Groups{
|
||||
List: []*Group{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +69,8 @@ func (groups *Groups) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (groups *Groups) GetGroup(f interface{}) (group *Group, ok bool) {
|
||||
groups.mutex.RLock()
|
||||
defer groups.mutex.RUnlock()
|
||||
groups.mutex.Lock()
|
||||
defer groups.mutex.Unlock()
|
||||
|
||||
switch v := f.(type) {
|
||||
case uint:
|
||||
|
|
@ -165,8 +165,8 @@ func (groups *Groups) Read(db *Database) error {
|
|||
rows *sql.Rows
|
||||
)
|
||||
|
||||
groups.mutex.RLock()
|
||||
defer groups.mutex.RUnlock()
|
||||
groups.mutex.Lock()
|
||||
defer groups.mutex.Unlock()
|
||||
|
||||
groups.List = []*Group{}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ import (
|
|||
|
||||
type Livefeed struct {
|
||||
Matrix map[uint]map[uint]bool
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewLivefeed() *Livefeed {
|
||||
return &Livefeed{
|
||||
Matrix: map[uint]map[uint]bool{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,8 +66,8 @@ func (livefeed *Livefeed) FromMap(f interface{}) {
|
|||
}
|
||||
|
||||
func (livefeed *Livefeed) IsAllOff() bool {
|
||||
livefeed.mutex.RLock()
|
||||
defer livefeed.mutex.RUnlock()
|
||||
livefeed.mutex.Lock()
|
||||
defer livefeed.mutex.Unlock()
|
||||
|
||||
for _, sys := range livefeed.Matrix {
|
||||
for _, tg := range sys {
|
||||
|
|
@ -81,8 +81,8 @@ func (livefeed *Livefeed) IsAllOff() bool {
|
|||
}
|
||||
|
||||
func (livefeed *Livefeed) IsEnabled(call *Call) bool {
|
||||
livefeed.mutex.RLock()
|
||||
defer livefeed.mutex.RUnlock()
|
||||
livefeed.mutex.Lock()
|
||||
defer livefeed.mutex.Unlock()
|
||||
|
||||
if call != nil {
|
||||
if livefeed.Matrix[call.System][call.Talkgroup] {
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ type Log struct {
|
|||
}
|
||||
|
||||
type Logs struct {
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewLogs() *Logs {
|
||||
return &Logs{
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,8 +94,8 @@ func (logs *Logs) Search(searchOptions *LogsSearchOptions, db *Database) (*LogsS
|
|||
where string = "true"
|
||||
)
|
||||
|
||||
logs.mutex.RLock()
|
||||
defer logs.mutex.RUnlock()
|
||||
logs.mutex.Lock()
|
||||
defer logs.mutex.Unlock()
|
||||
|
||||
formatError := func(err error) error {
|
||||
return fmt.Errorf("newLogResults: %v", err)
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@ type Options struct {
|
|||
TagsToggle bool `json:"tagsToggle"`
|
||||
adminPassword string
|
||||
adminPasswordNeedChange bool
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
secret string
|
||||
}
|
||||
|
||||
func NewOptions() *Options {
|
||||
return &Options{
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,8 +129,8 @@ func (options *Options) Read(db *Database) error {
|
|||
f interface{}
|
||||
)
|
||||
|
||||
options.mutex.RLock()
|
||||
defer options.mutex.RUnlock()
|
||||
options.mutex.Lock()
|
||||
defer options.mutex.Unlock()
|
||||
|
||||
defaultPassword, _ = bcrypt.GenerateFromPassword([]byte(defaults.adminPassword), bcrypt.DefaultCost)
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func ParseSdrTrunkMeta(call *Call, controller *Controller) error {
|
|||
|
||||
s = regexp.MustCompile(`^([0-9]+)$`).FindStringSubmatch(m.Artist())
|
||||
if len(s) == 2 {
|
||||
if i, err = strconv.Atoi(s[1]); err == nil {
|
||||
if i, err = strconv.Atoi(s[1]); err != nil {
|
||||
return err
|
||||
}
|
||||
if i > 0 {
|
||||
|
|
@ -271,22 +271,22 @@ func ParseMultipartContent(call *Call, p *multipart.Part, b []byte) {
|
|||
}
|
||||
|
||||
case "talkgroupGroup":
|
||||
if s := string(b); len(s) > 1 {
|
||||
if s := string(b); len(s) > 0 && s != "-" {
|
||||
call.talkgroupGroup = s
|
||||
}
|
||||
|
||||
case "talkgroupLabel":
|
||||
if s := string(b); len(s) > 1 {
|
||||
if s := string(b); len(s) > 0 && s != "-" {
|
||||
call.talkgroupLabel = s
|
||||
}
|
||||
|
||||
case "talkgroupName":
|
||||
if s := string(b); len(s) > 1 {
|
||||
if s := string(b); len(s) > 0 && s != "-" {
|
||||
call.talkgroupName = s
|
||||
}
|
||||
|
||||
case "talkgroupTag":
|
||||
if s := string(b); len(s) > 1 {
|
||||
if s := string(b); len(s) > 0 && s != "-" {
|
||||
call.talkgroupTag = s
|
||||
}
|
||||
}
|
||||
|
|
@ -425,9 +425,9 @@ func ParseTrunkRecorderMeta(call *Call, b []byte) error {
|
|||
|
||||
switch v := m["talkgroup_tag"].(type) {
|
||||
case string:
|
||||
call.talkgroupTag = v
|
||||
call.talkgroupLabel = v
|
||||
call.talkgroupName = v
|
||||
if len(v) > 0 && v != "-" {
|
||||
call.talkgroupLabel = v
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -95,13 +95,13 @@ type SystemMap map[string]interface{}
|
|||
|
||||
type Systems struct {
|
||||
List []*System
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewSystems() *Systems {
|
||||
return &Systems{
|
||||
List: []*System{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -122,8 +122,8 @@ func (systems *Systems) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (systems *Systems) GetNewSystemId() uint {
|
||||
systems.mutex.RLock()
|
||||
defer systems.mutex.RUnlock()
|
||||
systems.mutex.Lock()
|
||||
defer systems.mutex.Unlock()
|
||||
|
||||
NextId:
|
||||
for i := uint(1); i < 65535; i++ {
|
||||
|
|
@ -138,8 +138,8 @@ NextId:
|
|||
}
|
||||
|
||||
func (systems *Systems) GetSystem(f interface{}) (system *System, ok bool) {
|
||||
systems.mutex.RLock()
|
||||
defer systems.mutex.RUnlock()
|
||||
systems.mutex.Lock()
|
||||
defer systems.mutex.Unlock()
|
||||
|
||||
switch v := f.(type) {
|
||||
case uint:
|
||||
|
|
@ -319,8 +319,8 @@ func (systems *Systems) Read(db *Database) error {
|
|||
rows *sql.Rows
|
||||
)
|
||||
|
||||
systems.mutex.RLock()
|
||||
defer systems.mutex.RUnlock()
|
||||
systems.mutex.Lock()
|
||||
defer systems.mutex.Unlock()
|
||||
|
||||
systems.List = []*System{}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,13 +42,13 @@ func (tag *Tag) FromMap(m map[string]interface{}) {
|
|||
|
||||
type Tags struct {
|
||||
List []*Tag
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewTags() *Tags {
|
||||
return &Tags{
|
||||
List: []*Tag{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +69,8 @@ func (tags *Tags) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (tags *Tags) GetTag(f interface{}) (tag *Tag, ok bool) {
|
||||
tags.mutex.RLock()
|
||||
defer tags.mutex.RUnlock()
|
||||
tags.mutex.Lock()
|
||||
defer tags.mutex.Unlock()
|
||||
|
||||
switch v := f.(type) {
|
||||
case uint:
|
||||
|
|
@ -165,8 +165,8 @@ func (tags *Tags) Read(db *Database) error {
|
|||
rows *sql.Rows
|
||||
)
|
||||
|
||||
tags.mutex.RLock()
|
||||
defer tags.mutex.RUnlock()
|
||||
tags.mutex.Lock()
|
||||
defer tags.mutex.Unlock()
|
||||
|
||||
tags.List = []*Tag{}
|
||||
|
||||
|
|
@ -93,13 +93,13 @@ type TalkgroupMap map[string]interface{}
|
|||
|
||||
type Talkgroups struct {
|
||||
List []*Talkgroup
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewTalkgroups() *Talkgroups {
|
||||
return &Talkgroups{
|
||||
List: []*Talkgroup{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -120,8 +120,8 @@ func (talkgroups *Talkgroups) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (talkgroups *Talkgroups) GetTalkgroup(f interface{}) (system *Talkgroup, ok bool) {
|
||||
talkgroups.mutex.RLock()
|
||||
defer talkgroups.mutex.RUnlock()
|
||||
talkgroups.mutex.Lock()
|
||||
defer talkgroups.mutex.Unlock()
|
||||
|
||||
switch v := f.(type) {
|
||||
case uint:
|
||||
|
|
@ -149,8 +149,8 @@ func (talkgroups *Talkgroups) Read(db *Database, systemId uint) error {
|
|||
rows *sql.Rows
|
||||
)
|
||||
|
||||
talkgroups.mutex.RLock()
|
||||
defer talkgroups.mutex.RUnlock()
|
||||
talkgroups.mutex.Lock()
|
||||
defer talkgroups.mutex.Unlock()
|
||||
|
||||
talkgroups.List = []*Talkgroup{}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ func (unit *Unit) FromMap(m map[string]interface{}) {
|
|||
|
||||
type Units struct {
|
||||
List []*Unit
|
||||
mutex sync.RWMutex
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func NewUnits() *Units {
|
||||
return &Units{
|
||||
List: []*Unit{},
|
||||
mutex: sync.RWMutex{},
|
||||
mutex: sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +88,9 @@ func (units *Units) FromMap(f []interface{}) {
|
|||
}
|
||||
|
||||
func (u *Units) Merge(units *Units) {
|
||||
units.mutex.Lock()
|
||||
defer units.mutex.Unlock()
|
||||
|
||||
for _, v := range units.List {
|
||||
u.Add(v.Id, v.Label)
|
||||
}
|
||||
|
|
@ -99,8 +102,8 @@ func (units *Units) Read(db *Database, systemId uint) error {
|
|||
rows *sql.Rows
|
||||
)
|
||||
|
||||
units.mutex.RLock()
|
||||
defer units.mutex.RUnlock()
|
||||
units.mutex.Lock()
|
||||
defer units.mutex.Unlock()
|
||||
|
||||
units.List = []*Unit{}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@
|
|||
|
||||
package main
|
||||
|
||||
const Version = "6.1.6"
|
||||
const Version = "6.1.7"
|
||||
|
|
|
|||
Loading…
Reference in a new issue