diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b66ac2..f959291 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Change log
+## Version 6.5
+
+- Fixed API looping on malformed or invalid multipart content (issue #181, #212).
+- Source code updated to GO 1.18 with `interface{}` replaced by `any`.
+- Removed ingest mutex for performance reasons.
+- Replaced all `path.Base()` by `filepath.Base()` to fix an issue with audio filenames on Windows.
+- New `Branding Label` and `Email Support` options to show on main screen (issue #220).
+- New temporary avoid feature (discussion #218).
+- Fix remote address regexp (issue #225).
+- Add the `ident` to `new listener` log message (discussion #226).
+- New populated talkgroups won't be activated on the client if its group (or tag) is turned off (issue #227).
+- Removed the duplicated webapp section from the PDF document.
+
## Version 6.4
- New `-cmd` command line options to allow advanced administrative tasks.
diff --git a/COMPILING.md b/COMPILING.md
index cd93cc1..1990a15 100644
--- a/COMPILING.md
+++ b/COMPILING.md
@@ -27,13 +27,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.4.5.zip
- rdio-scanner-darwin-arm64-v6.4.5.zip
- rdio-scanner-freebsd-amd64-v6.4.5.zip
- rdio-scanner-linux-386-v6.4.5.zip
- rdio-scanner-linux-amd64-v6.4.5.zip
- rdio-scanner-linux-arm64-v6.4.5.zip
- rdio-scanner-linux-arm-v6.4.5.zip
- rdio-scanner-windows-amd64-v6.4.5.zip
+ rdio-scanner-darwin-amd64-v6.5.0.zip
+ rdio-scanner-darwin-arm64-v6.5.0.zip
+ rdio-scanner-freebsd-amd64-v6.5.0.zip
+ rdio-scanner-linux-386-v6.5.0.zip
+ rdio-scanner-linux-amd64-v6.5.0.zip
+ rdio-scanner-linux-arm64-v6.5.0.zip
+ rdio-scanner-linux-arm-v6.5.0.zip
+ rdio-scanner-windows-amd64-v6.5.0.zip
**Happy Rdio scanning !**
\ No newline at end of file
diff --git a/Makefile b/Makefile
index de67da2..a012022 100644
--- a/Makefile
+++ b/Makefile
@@ -16,14 +16,14 @@
################################################################################
app := rdio-scanner
-date := 2022/06/14
-ver := 6.4.5
+date := 2022/06/27
+ver := 6.5.0
client := $(wildcard client/*.json client/*.ts)
server := $(wildcard server/*.go)
build = @cd server && GOOS=$(1) GOARCH=$(2) go build -o ../dist/$(1)-$(2)/$(3)
-pandoc = @test -d dist/$(1)-$(2) || mkdir -p dist/$(1)-$(2) && pandoc -f markdown -o dist/$(1)-$(2)/$(3) --resource-path docs:docs/platforms $(4) docs/webapp.md docs/webapp.md docs/faq.md CHANGELOG.md
+pandoc = @test -d dist/$(1)-$(2) || mkdir -p dist/$(1)-$(2) && pandoc -f markdown -o dist/$(1)-$(2)/$(3) --resource-path docs:docs/platforms $(4) docs/webapp.md docs/faq.md CHANGELOG.md
zip = @cd dist/$(1)-$(2) && zip -q ../$(app)-$(1)-$(2)-v$(ver).zip * && cd ..
.PHONY: all clean container dist sed
diff --git a/client/package-lock.json b/client/package-lock.json
index 1e476d9..1ae7dfb 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "rdio-scanner",
- "version": "6.4.5",
+ "version": "6.5.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "rdio-scanner",
- "version": "6.4.5",
+ "version": "6.5.0",
"license": "LICENSE",
"dependencies": {
"@angular/animations": "^13.3.10",
diff --git a/client/package.json b/client/package.json
index d0110a1..556c104 100644
--- a/client/package.json
+++ b/client/package.json
@@ -38,5 +38,5 @@
"build": "ng build --base-href ./ --configuration production",
"start": "ng serve"
},
- "version": "6.4.5"
+ "version": "6.5.0"
}
diff --git a/client/src/app/components/rdio-scanner/admin/admin.service.ts b/client/src/app/components/rdio-scanner/admin/admin.service.ts
index 085700d..d7a1e7b 100644
--- a/client/src/app/components/rdio-scanner/admin/admin.service.ts
+++ b/client/src/app/components/rdio-scanner/admin/admin.service.ts
@@ -132,9 +132,11 @@ export interface Options {
afsSystems?: string;
audioConversion?: 0 | 1 | 2 | 3;
autoPopulate?: boolean;
+ branding?: string;
dimmerDelay?: number;
disableDuplicateDetection?: boolean;
duplicateDetectionTimeFrame?: number;
+ email?: string;
keypadBeeps?: string;
maxClients?: number;
playbackGoesLive?: boolean;
@@ -497,9 +499,11 @@ export class RdioScannerAdminService implements OnDestroy {
afsSystems: [options?.afsSystems, this.validateAfsSystems()],
audioConversion: [options?.audioConversion],
autoPopulate: [options?.autoPopulate],
+ branding: [options?.branding],
dimmerDelay: [options?.dimmerDelay, [Validators.required, Validators.min(0)]],
disableDuplicateDetection: [options?.disableDuplicateDetection],
duplicateDetectionTimeFrame: [options?.duplicateDetectionTimeFrame, [Validators.required, Validators.min(0)]],
+ email: [options?.email],
keypadBeeps: [options?.keypadBeeps, Validators.required],
maxClients: [options?.maxClients, [Validators.required, Validators.min(1)]],
playbackGoesLive: [options?.playbackGoesLive],
diff --git a/client/src/app/components/rdio-scanner/admin/config/options/options.component.html b/client/src/app/components/rdio-scanner/admin/config/options/options.component.html
index 6820635..ba44510 100644
--- a/client/src/app/components/rdio-scanner/admin/config/options/options.component.html
+++ b/client/src/app/components/rdio-scanner/admin/config/options/options.component.html
@@ -45,6 +45,16 @@
+ Branding Label
+ A simple line of text displayed above the main screen to help identify the Rdio
+ Scanner instance.
+
Dimmer Delay
@@ -86,6 +96,15 @@
+ Email Support
+ Email address where users can write to to get support.
+
Keypad Beep Style
diff --git a/client/src/app/components/rdio-scanner/common.scss b/client/src/app/components/rdio-scanner/common.scss
index 1deab8a..c42bfed 100644
--- a/client/src/app/components/rdio-scanner/common.scss
+++ b/client/src/app/components/rdio-scanner/common.scss
@@ -1,6 +1,11 @@
.rdio-button,
.rdio-button-mini {
- background: rgb(45, 45, 45);
+ --def: rgb(45, 45, 45);
+ --green: rgb(0, 230, 118);
+ --red: rgb(255, 23, 68);
+ --yellow: rgb(255, 234, 0);
+
+ background: var(--def);
border-style: solid;
border-width: 1px;
border-bottom-color: rgba(0, 0, 0, 0.87);
@@ -41,24 +46,71 @@
right: 4px;
top: 4px;
width: 6px;
+
+ animation: blink 1s linear infinite both;
}
&.off::after {
- background: rgb(255, 23, 68);
- box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset,
- 0 0 3px 1px rgb(255, 23, 68);
+ background: var(--red);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 3px 1px var(--red);
+ }
+
+ &.off.blink::after {
+ animation: blink-off 500ms linear infinite;
+ }
+
+ @keyframes blink-off {
+ 0%, 50% {
+ background: var(--def);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 0px 0px var(--def);
+ }
+
+ 50%, 100% {
+ background: var(--red);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 3px 1px var(--red);
+ }
}
&.on::after {
- background: rgb(0, 230, 118);;
- box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset,
- 0 0 3px 1px rgb(0, 230, 118);;
+ background: var(--green);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 3px 1px var(--green);
+ }
+
+ &.on.blink::after {
+ animation: blink-on 500ms linear infinite;
+ }
+
+ @keyframes blink-on {
+ 0%, 50% {
+ background: var(--def);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 0px 0px var(--def);
+ }
+
+ 50%, 100% {
+ background: var(--def);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 3px 1px var(--green);
+ }
}
&.partial::after {
- background: rgb(255, 234, 0);
- box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset,
- 0 0 3px 1px rgb(255, 234, 0);
+ background: var(--yellow);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 3px 1px var(--yellow);
+ }
+
+ &.partial.blink::after {
+ animation: blink-partial 500ms linear infinite;
+ }
+
+ @keyframes blink-partial {
+ 0%, 50% {
+ background: var(--def);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 0px 0px var(--def);
+ }
+
+ 50%, 100% {
+ background: var(--yellow);
+ box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7) inset, 0 0 3px 1px var(--yellow);
+ }
}
}
diff --git a/client/src/app/components/rdio-scanner/main/main.component.html b/client/src/app/components/rdio-scanner/main/main.component.html
index 90fcfbd..8d9657e 100644
--- a/client/src/app/components/rdio-scanner/main/main.component.html
+++ b/client/src/app/components/rdio-scanner/main/main.component.html
@@ -1,4 +1,5 @@
arguments.", COMMAND_ARG_CODE))
}
- u := map[string]interface{}{
+ u := map[string]any{
"code": command.code,
"ident": command.ident,
"systems": "*",
@@ -392,9 +392,9 @@ func (command *Command) userAdd() {
}
}
if len(s) > 0 {
- systems := []map[string]interface{}{}
+ systems := []map[string]any{}
for _, i := range s {
- systems = append(systems, map[string]interface{}{"id": i, "talkgroups": "*"})
+ systems = append(systems, map[string]any{"id": i, "talkgroups": "*"})
}
u["systems"] = systems
} else {
@@ -419,7 +419,7 @@ func (command *Command) userRemove() {
command.exitWithError(fmt.Sprintf("Missing %s arguments.", COMMAND_ARG_IDENT))
}
- if body, err := command.writeBody(map[string]interface{}{"ident": command.ident}); err == nil {
+ if body, err := command.writeBody(map[string]any{"ident": command.ident}); err == nil {
if res, err := command.submit(http.MethodPost, "/api/admin/user-remove", body, true); err == nil {
if res.StatusCode == http.StatusOK {
fmt.Printf("User %s removed.\n", command.ident)
@@ -432,12 +432,12 @@ func (command *Command) userRemove() {
}
}
-func (c *Command) readBody(body io.ReadCloser) (data interface{}, err error) {
+func (c *Command) readBody(body io.ReadCloser) (data any, err error) {
err = json.NewDecoder(body).Decode(&data)
return data, err
}
-func (c *Command) writeBody(data interface{}) (body io.Reader, err error) {
+func (c *Command) writeBody(data any) (body io.Reader, err error) {
var b []byte
if b, err = json.Marshal(data); err == nil {
body = bytes.NewReader(b)
@@ -464,7 +464,7 @@ func (c *Command) submit(method string, url string, body io.Reader, auth bool) (
return res, err
}
-func (c *Command) exitWithError(err interface{}) {
+func (c *Command) exitWithError(err any) {
fmt.Printf("%v\n", err)
os.Exit(1)
}
diff --git a/server/controller.go b/server/controller.go
index c3dd52c..7c2fd9e 100644
--- a/server/controller.go
+++ b/server/controller.go
@@ -67,10 +67,9 @@ func NewController(config *Config) *Controller {
Systems: NewSystems(),
Tags: NewTags(),
Clients: NewClients(),
- Register: make(chan *Client),
- Unregister: make(chan *Client),
- Ingest: make(chan *Call),
- ingestMutex: sync.Mutex{},
+ Register: make(chan *Client, 4096),
+ Unregister: make(chan *Client, 4096),
+ Ingest: make(chan *Call, 4096),
}
controller.Admin = NewAdmin(controller)
@@ -110,9 +109,6 @@ func (controller *Controller) IngestCall(call *Call) {
talkgroup *Talkgroup
)
- controller.IngestLock()
- defer controller.IngestUnlock()
-
logCall := func(call *Call, level string, message string) {
controller.Logs.LogEvent(level, fmt.Sprintf("newcall: system=%v talkgroup=%v file=%v %v", call.System, call.Talkgroup, call.AudioName, message))
}
@@ -317,21 +313,13 @@ func (controller *Controller) IngestCall(call *Call) {
}
}
-func (controller *Controller) IngestLock() {
- controller.ingestMutex.Lock()
-}
-
-func (controller *Controller) IngestUnlock() {
- controller.ingestMutex.Unlock()
-}
-
func (controller *Controller) LogClientsCount() {
controller.Logs.LogEvent(LogLevelInfo, fmt.Sprintf("listeners count is %v", controller.Clients.Count()))
}
func (controller *Controller) ProcessMessage(client *Client, message *Message) error {
if message.Command == MessageCommandVersion {
- client.Send <- &Message{Command: MessageCommandVersion, Payload: Version}
+ controller.ProcessMessageCommandVersion(client)
} else if controller.Accesses.IsRestricted() && client.Access.Systems == nil && message.Command != MessageCommandPin {
client.Send <- &Message{Command: MessageCommandPin}
@@ -394,7 +382,7 @@ func (controller *Controller) ProcessMessageCommandCall(client *Client, message
func (controller *Controller) ProcessMessageCommandListCall(client *Client, message *Message) error {
switch v := message.Payload.(type) {
- case map[string]interface{}:
+ case map[string]any:
searchOptions := CallsSearchOptions{searchPatchedTalkgroups: controller.Options.SearchPatchedTalkgroups}
searchOptions.fromMap(v)
if searchResults, err := controller.Calls.Search(&searchOptions, client); err == nil {
@@ -467,6 +455,20 @@ func (controller *Controller) ProcessMessageCommandPin(client *Client, message *
return nil
}
+func (controller *Controller) ProcessMessageCommandVersion(client *Client) {
+ p := map[string]string{"version": Version}
+
+ if len(controller.Options.Branding) > 0 {
+ p["branding"] = controller.Options.Branding
+ }
+
+ if len(controller.Options.Email) > 0 {
+ p["email"] = controller.Options.Email
+ }
+
+ client.Send <- &Message{Command: MessageCommandVersion, Payload: p}
+}
+
func (controller *Controller) Start() error {
var err error
diff --git a/server/database.go b/server/database.go
index ed284e4..a4da93d 100644
--- a/server/database.go
+++ b/server/database.go
@@ -76,7 +76,7 @@ func NewDatabase(config *Config) *Database {
return database
}
-func (db *Database) ParseDateTime(f interface{}) (time.Time, error) {
+func (db *Database) ParseDateTime(f any) (time.Time, error) {
switch v := f.(type) {
case []uint8:
return time.Parse(db.DateTimeFormat, string(v))
@@ -377,10 +377,10 @@ func (db *Database) migration20211202094819(verbose bool) error {
func (db *Database) migration20220101070000(verbose bool) error {
var (
err error
- frequency interface{}
+ frequency any
id uint
label string
- led interface{}
+ led any
name string
queries []string
rows *sql.Rows
diff --git a/server/dirwatch.go b/server/dirwatch.go
index d386d20..53febbb 100644
--- a/server/dirwatch.go
+++ b/server/dirwatch.go
@@ -44,25 +44,25 @@ const (
)
type Dirwatch struct {
- Id interface{} `json:"_id"`
- Delay interface{} `json:"delay"`
- DeleteAfter bool `json:"deleteAfter"`
- Directory string `json:"directory"`
- Disabled bool `json:"disabled"`
- Extension interface{} `json:"extension"`
- Frequency interface{} `json:"frequency"`
- Mask interface{} `json:"mask"`
- Order interface{} `json:"order"`
- SystemId interface{} `json:"systemId"`
- TalkgroupId interface{} `json:"talkgroupId"`
- Kind interface{} `json:"type"`
- UsePolling bool `json:"usePolling"`
+ Id any `json:"_id"`
+ Delay any `json:"delay"`
+ DeleteAfter bool `json:"deleteAfter"`
+ Directory string `json:"directory"`
+ Disabled bool `json:"disabled"`
+ Extension any `json:"extension"`
+ Frequency any `json:"frequency"`
+ Mask any `json:"mask"`
+ Order any `json:"order"`
+ SystemId any `json:"systemId"`
+ TalkgroupId any `json:"talkgroupId"`
+ Kind any `json:"type"`
+ UsePolling bool `json:"usePolling"`
controller *Controller
dirs map[string]bool
watcher *fsnotify.Watcher
}
-func (dirwatch *Dirwatch) FromMap(m map[string]interface{}) *Dirwatch {
+func (dirwatch *Dirwatch) FromMap(m map[string]any) *Dirwatch {
switch v := m["_id"].(type) {
case float64:
dirwatch.Id = uint(v)
@@ -164,7 +164,7 @@ func (dirwatch *Dirwatch) ingestDefault(p string) error {
if strings.EqualFold(path.Ext(p), ext) {
call := NewCall()
- call.AudioName = path.Base(p)
+ call.AudioName = filepath.Base(p)
call.AudioType = mime.TypeByExtension(path.Ext(p))
call.Frequency = dirwatch.Frequency
@@ -224,7 +224,7 @@ func (dirwatch *Dirwatch) ingestSdrTrunk(p string) error {
call := NewCall()
- call.AudioName = path.Base(p)
+ call.AudioName = filepath.Base(p)
call.AudioType = mime.TypeByExtension(path.Ext(p))
call.Frequency = dirwatch.Frequency
@@ -280,7 +280,7 @@ func (dirwatch *Dirwatch) ingestTrunkRecorder(p string) error {
call := NewCall()
- call.AudioName = path.Base(audioName)
+ call.AudioName = filepath.Base(audioName)
call.AudioType = mime.TypeByExtension(path.Ext(audioName))
call.Frequency = dirwatch.Frequency
@@ -344,8 +344,8 @@ func (dirwatch *Dirwatch) parseMask(call *Call) {
var (
filename string
mask string
- metapos = [][]interface{}{}
- metaval = map[string]interface{}{}
+ metapos = [][]any{}
+ metaval = map[string]any{}
)
switch v := dirwatch.Mask.(type) {
@@ -364,7 +364,7 @@ func (dirwatch *Dirwatch) parseMask(call *Call) {
for _, v := range meta {
if i := strings.Index(mask, v[1]); i != -1 {
- metapos = append(metapos, []interface{}{v[0], i})
+ metapos = append(metapos, []any{v[0], i})
mask = strings.Replace(mask, v[1], fmt.Sprintf("(%v)", v[2]), 1)
}
}
@@ -513,8 +513,8 @@ func (dirwatch *Dirwatch) parseMask(call *Call) {
case string:
if i, err := strconv.Atoi(v); err == nil {
switch sources := call.Sources.(type) {
- case []map[string]interface{}:
- call.Sources = append(sources, map[string]interface{}{"pos": 0, "src": uint(i)})
+ case []map[string]any:
+ call.Sources = append(sources, map[string]any{"pos": 0, "src": uint(i)})
}
}
}
@@ -549,7 +549,6 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
}
go func() {
- // var timers = map[string]*time.Timer{}
var timers = sync.Map{}
logError := func(err error) {
@@ -567,7 +566,7 @@ func (dirwatch *Dirwatch) Start(controller *Controller) error {
}
defer func() {
- timers.Range(func(k interface{}, t interface{}) bool {
+ timers.Range(func(k any, t any) bool {
switch v := t.(type) {
case *time.Timer:
v.Stop()
@@ -688,7 +687,7 @@ func NewDirwatches() *Dirwatches {
}
}
-func (dirwatches *Dirwatches) FromMap(f []interface{}) *Dirwatches {
+func (dirwatches *Dirwatches) FromMap(f []any) *Dirwatches {
dirwatches.mutex.Lock()
defer dirwatches.mutex.Unlock()
@@ -698,7 +697,7 @@ func (dirwatches *Dirwatches) FromMap(f []interface{}) *Dirwatches {
for _, f := range f {
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
dirwatch := &Dirwatch{}
dirwatch.FromMap(v)
dirwatches.List = append(dirwatches.List, dirwatch)
diff --git a/server/downstream.go b/server/downstream.go
index 58b699c..2700595 100644
--- a/server/downstream.go
+++ b/server/downstream.go
@@ -32,15 +32,15 @@ import (
)
type Downstream struct {
- Id interface{} `json:"_id"`
- Apikey string `json:"apiKey"`
- Disabled bool `json:"disabled"`
- Order interface{} `json:"order"`
- Systems interface{} `json:"systems"`
- Url string `json:"url"`
+ Id any `json:"_id"`
+ Apikey string `json:"apiKey"`
+ Disabled bool `json:"disabled"`
+ Order any `json:"order"`
+ Systems any `json:"systems"`
+ Url string `json:"url"`
}
-func (downstream *Downstream) FromMap(m map[string]interface{}) *Downstream {
+func (downstream *Downstream) FromMap(m map[string]any) *Downstream {
switch v := m["_id"].(type) {
case float64:
downstream.Id = uint(v)
@@ -62,7 +62,7 @@ func (downstream *Downstream) FromMap(m map[string]interface{}) *Downstream {
}
switch v := m["systems"].(type) {
- case []interface{}:
+ case []any:
if b, err := json.Marshal(v); err == nil {
downstream.Systems = string(b)
}
@@ -84,10 +84,10 @@ func (downstream *Downstream) HasAccess(call *Call) bool {
}
switch v := downstream.Systems.(type) {
- case []interface{}:
+ case []any:
for _, f := range v {
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
switch id := v["id"].(type) {
case float64:
if id == float64(call.System) {
@@ -96,7 +96,7 @@ func (downstream *Downstream) HasAccess(call *Call) bool {
if tg == "*" {
return true
}
- case []interface{}:
+ case []any:
for _, f := range tg {
switch tg := f.(type) {
case float64:
@@ -181,7 +181,7 @@ func (downstream *Downstream) Send(call *Call) error {
}
switch v := call.Frequencies.(type) {
- case []map[string]interface{}:
+ case []map[string]any:
if w, err := mw.CreateFormField("frequencies"); err == nil {
if b, err := json.Marshal(v); err == nil {
if _, err = w.Write(b); err != nil {
@@ -241,7 +241,7 @@ func (downstream *Downstream) Send(call *Call) error {
}
switch v := call.Sources.(type) {
- case []map[string]interface{}:
+ case []map[string]any:
if w, err := mw.CreateFormField("sources"); err == nil {
if b, err := json.Marshal(v); err == nil {
if _, err = w.Write(b); err != nil {
@@ -363,7 +363,7 @@ func NewDownstreams() *Downstreams {
}
}
-func (downstreams *Downstreams) FromMap(f []interface{}) *Downstreams {
+func (downstreams *Downstreams) FromMap(f []any) *Downstreams {
downstreams.mutex.Lock()
defer downstreams.mutex.Unlock()
@@ -371,7 +371,7 @@ func (downstreams *Downstreams) FromMap(f []interface{}) *Downstreams {
for _, r := range f {
switch m := r.(type) {
- case map[string]interface{}:
+ case map[string]any:
downstream := &Downstream{}
downstream.FromMap(m)
downstreams.List = append(downstreams.List, downstream)
@@ -423,7 +423,7 @@ func (downstreams *Downstreams) Read(db *Database) error {
}
if err = json.Unmarshal([]byte(systems), &downstream.Systems); err != nil {
- downstream.Systems = []interface{}{}
+ downstream.Systems = []any{}
}
if len(downstream.Url) == 0 {
@@ -464,7 +464,7 @@ func (downstreams *Downstreams) Write(db *Database) error {
err error
rows *sql.Rows
rowIds = []uint{}
- systems interface{}
+ systems any
)
downstreams.mutex.Lock()
diff --git a/server/go.mod b/server/go.mod
index 68adfdc..6278d88 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -1,9 +1,9 @@
module rdio-scanner/server
-go 1.17
+go 1.18
require (
- github.com/dhowden/tag v0.0.0-20220530110423-77907a30b7f1
+ github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086
github.com/fsnotify/fsnotify v1.5.4
github.com/go-sql-driver/mysql v1.6.0
github.com/golang-jwt/jwt/v4 v4.4.1
@@ -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.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
- golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
- golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d // indirect
+ golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect
+ golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.11 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
diff --git a/server/go.sum b/server/go.sum
index c780b72..de78b90 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dhowden/tag v0.0.0-20220530110423-77907a30b7f1 h1:jD1A7flCBuwFb5PvK3B2u/jmUUZ2j3n3puR0F7peZWM=
github.com/dhowden/tag v0.0.0-20220530110423-77907a30b7f1/go.mod h1:SniNVYuaD1jmdEEvi+7ywb1QFR7agjeTdGKyFb0p7Rw=
+github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086 h1:ORubSQoKnncsBnR4zD9CuYFJCPOCuSNEpWEZrDdBXkc=
+github.com/dhowden/tag v0.0.0-20220618230019-adf36e896086/go.mod h1:Z3Lomva4pyMWYezjMAU5QWRh0p1VvO4199OHlFnyKkM=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
@@ -51,6 +53,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 h1:Yqz/iviulwKwAREEeUd3nbBFn0XuyJqkoft2IlrvOhc=
+golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
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=
@@ -69,6 +73,8 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d h1:Zu/JngovGLVi6t2J3nmAf3AoTDwuzw85YZ3b9o4yU7s=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
+golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/server/group.go b/server/group.go
index feca449..f6e0c8b 100644
--- a/server/group.go
+++ b/server/group.go
@@ -24,11 +24,11 @@ import (
)
type Group struct {
- Id interface{} `json:"_id"`
- Label string `json:"label"`
+ Id any `json:"_id"`
+ Label string `json:"label"`
}
-func (group *Group) FromMap(m map[string]interface{}) *Group {
+func (group *Group) FromMap(m map[string]any) *Group {
switch v := m["_id"].(type) {
case float64:
group.Id = uint(v)
@@ -54,7 +54,7 @@ func NewGroups() *Groups {
}
}
-func (groups *Groups) FromMap(f []interface{}) *Groups {
+func (groups *Groups) FromMap(f []any) *Groups {
groups.mutex.Lock()
defer groups.mutex.Unlock()
@@ -62,7 +62,7 @@ func (groups *Groups) FromMap(f []interface{}) *Groups {
for _, r := range f {
switch m := r.(type) {
- case map[string]interface{}:
+ case map[string]any:
group := &Group{}
group.FromMap(m)
groups.List = append(groups.List, group)
@@ -72,7 +72,7 @@ func (groups *Groups) FromMap(f []interface{}) *Groups {
return groups
}
-func (groups *Groups) GetGroup(f interface{}) (group *Group, ok bool) {
+func (groups *Groups) GetGroup(f any) (group *Group, ok bool) {
groups.mutex.Lock()
defer groups.mutex.Unlock()
diff --git a/server/livefeed.go b/server/livefeed.go
index 967051a..90e8415 100644
--- a/server/livefeed.go
+++ b/server/livefeed.go
@@ -32,7 +32,7 @@ func NewLivefeed() *Livefeed {
}
}
-func (livefeed *Livefeed) FromMap(f interface{}) *Livefeed {
+func (livefeed *Livefeed) FromMap(f any) *Livefeed {
livefeed.mutex.Lock()
defer livefeed.mutex.Unlock()
@@ -41,12 +41,12 @@ func (livefeed *Livefeed) FromMap(f interface{}) *Livefeed {
}
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
for s, n := range v {
if sysId, err := strconv.Atoi(s); err == nil {
sysId := uint(sysId)
switch v := n.(type) {
- case map[string]interface{}:
+ case map[string]any:
for t, b := range v {
switch v := b.(type) {
case bool:
diff --git a/server/log.go b/server/log.go
index d3ffc3f..302c8b9 100644
--- a/server/log.go
+++ b/server/log.go
@@ -31,10 +31,10 @@ const (
)
type Log struct {
- Id interface{} `json:"_id"`
- DateTime time.Time `json:"dateTime"`
- Level string `json:"level"`
- Message string `json:"message"`
+ Id any `json:"_id"`
+ DateTime time.Time `json:"dateTime"`
+ Level string `json:"level"`
+ Message string `json:"message"`
}
type Logs struct {
@@ -99,7 +99,7 @@ func (logs *Logs) Search(searchOptions *LogsSearchOptions, db *Database) (*LogsS
)
var (
- dateTime interface{}
+ dateTime any
err error
id sql.NullFloat64
limit uint
@@ -240,14 +240,14 @@ func (logs *Logs) setDatabase(d *Database) {
}
type LogsSearchOptions struct {
- Date interface{} `json:"date,omitempty"`
- Level interface{} `json:"level,omitempty"`
- Limit interface{} `json:"limit,omitempty"`
- Offset interface{} `json:"offset,omitempty"`
- Sort interface{} `json:"sort,omitempty"`
+ Date any `json:"date,omitempty"`
+ Level any `json:"level,omitempty"`
+ Limit any `json:"limit,omitempty"`
+ Offset any `json:"offset,omitempty"`
+ Sort any `json:"sort,omitempty"`
}
-func (searchOptions *LogsSearchOptions) FromMap(m map[string]interface{}) error {
+func (searchOptions *LogsSearchOptions) FromMap(m map[string]any) error {
switch v := m["date"].(type) {
case string:
if t, err := time.Parse(time.RFC3339, v); err == nil {
diff --git a/server/main.go b/server/main.go
index dc8beee..cb95f89 100644
--- a/server/main.go
+++ b/server/main.go
@@ -229,7 +229,7 @@ func main() {
}
func GetRemoteAddr(r *http.Request) string {
- re := regexp.MustCompile(`(\[[^\]]+\]|[^:]+):.*`)
+ re := regexp.MustCompile(`(.+):.*$`)
for _, addr := range strings.Split(r.Header.Get("X-Forwarded-For"), ",") {
if ip := re.ReplaceAllString(addr, "$1"); len(ip) > 0 {
@@ -241,5 +241,5 @@ func GetRemoteAddr(r *http.Request) string {
return ip
}
- return "unknown"
+ return r.RemoteAddr
}
diff --git a/server/message.go b/server/message.go
index e97bb33..3e9eaf3 100644
--- a/server/message.go
+++ b/server/message.go
@@ -35,15 +35,15 @@ const (
)
type Message struct {
- Command interface{}
- Payload interface{}
- Flag interface{}
+ Command any
+ Payload any
+ Flag any
}
func (message *Message) FromJson(b []byte) error {
var (
err error
- f []interface{}
+ f []any
)
if err = json.Unmarshal(b, &f); err != nil {
@@ -68,7 +68,7 @@ func (message *Message) FromJson(b []byte) error {
}
func (message *Message) ToJson() ([]byte, error) {
- str := []interface{}{message.Command}
+ str := []any{message.Command}
if message.Payload != nil && message.Payload != "" {
str = append(str, message.Payload)
diff --git a/server/options.go b/server/options.go
index c570008..7a854e9 100644
--- a/server/options.go
+++ b/server/options.go
@@ -28,9 +28,11 @@ type Options struct {
AfsSystems string `json:"afsSystems"`
AudioConversion uint `json:"audioConversion"`
AutoPopulate bool `json:"autoPopulate"`
+ Branding string `json:"branding"`
DimmerDelay uint `json:"dimmerDelay"`
DisableDuplicateDetection bool `json:"disableDuplicateDetection"`
DuplicateDetectionTimeFrame uint `json:"duplicateDetectionTimeFrame"`
+ Email string `json:"email"`
KeypadBeeps string `json:"keypadBeeps"`
MaxClients uint `json:"maxClients"`
PlaybackGoesLive bool `json:"playbackGoesLive"`
@@ -59,7 +61,7 @@ func NewOptions() *Options {
}
}
-func (options *Options) FromMap(m map[string]interface{}) *Options {
+func (options *Options) FromMap(m map[string]any) *Options {
options.mutex.Lock()
defer options.mutex.Unlock()
@@ -82,6 +84,11 @@ func (options *Options) FromMap(m map[string]interface{}) *Options {
options.AutoPopulate = defaults.options.autoPopulate
}
+ switch v := m["branding"].(type) {
+ case string:
+ options.Branding = v
+ }
+
switch v := m["dimmerDelay"].(type) {
case float64:
options.DimmerDelay = uint(v)
@@ -112,6 +119,11 @@ func (options *Options) FromMap(m map[string]interface{}) *Options {
options.DuplicateDetectionTimeFrame = defaults.options.duplicateDetectionTimeFrame
}
+ switch v := m["email"].(type) {
+ case string:
+ options.Email = v
+ }
+
switch v := m["keypadBeeps"].(type) {
case string:
options.KeypadBeeps = v
@@ -221,7 +233,7 @@ func (options *Options) Read(db *Database) error {
err = db.Sql.QueryRow("select `val` from `rdioScannerConfigs` where `key` = 'options'").Scan(&s)
if err == nil {
- var m map[string]interface{}
+ var m map[string]any
if err = json.Unmarshal([]byte(s), &m); err == nil {
switch v := m["afsSystems"].(type) {
@@ -239,6 +251,11 @@ func (options *Options) Read(db *Database) error {
options.AutoPopulate = v
}
+ switch v := m["branding"].(type) {
+ case string:
+ options.Branding = v
+ }
+
switch v := m["dimmerDelay"].(type) {
case float64:
options.DimmerDelay = uint(v)
@@ -254,6 +271,11 @@ func (options *Options) Read(db *Database) error {
options.DuplicateDetectionTimeFrame = uint(v)
}
+ switch v := m["email"].(type) {
+ case string:
+ options.Email = v
+ }
+
switch v := m["keypadBeeps"].(type) {
case string:
options.KeypadBeeps = v
@@ -350,13 +372,15 @@ func (options *Options) Write(db *Database) error {
db.Sql.Exec("insert into `rdioScannerConfigs` (`key`, `val`) values (?, ?)", "adminPasswordNeedChange", string(b))
}
- if b, err = json.Marshal(map[string]interface{}{
+ if b, err = json.Marshal(map[string]any{
"afsSystems": options.AfsSystems,
"audioConversion": options.AudioConversion,
"autoPopulate": options.AutoPopulate,
+ "branding": options.Branding,
"dimmerDelay": options.DimmerDelay,
"disableDuplicateDetection": options.DisableDuplicateDetection,
"duplicateDetectionTimeFrame": options.DuplicateDetectionTimeFrame,
+ "email": options.Email,
"keypadBeeps": options.KeypadBeeps,
"maxClients": options.MaxClients,
"playbackGoesLive": options.PlaybackGoesLive,
diff --git a/server/parsers.go b/server/parsers.go
index fc53776..129894d 100644
--- a/server/parsers.go
+++ b/server/parsers.go
@@ -101,10 +101,10 @@ func ParseSdrTrunkMeta(call *Call, controller *Controller) error {
s = regexp.MustCompile(`(\[.+\])`).FindStringSubmatch(m.Title())
if len(s) > 1 && len(s[1]) > 0 {
- var f interface{}
+ var f any
if err = json.Unmarshal([]byte(s[1]), &f); err == nil {
switch v := f.(type) {
- case []interface{}:
+ case []any:
patches := []uint{}
for _, patch := range v {
switch v := patch.(type) {
@@ -151,15 +151,15 @@ func ParseMultipartContent(call *Call, p *multipart.Part, b []byte) {
}
case "frequencies":
- var f interface{}
+ var f any
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
- case []interface{}:
- var frequencies = []map[string]interface{}{}
+ case []any:
+ var frequencies = []map[string]any{}
for _, f := range v {
- freq := map[string]interface{}{}
+ freq := map[string]any{}
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
switch v := v["errorCount"].(type) {
case float64:
if v >= 0 {
@@ -204,12 +204,12 @@ func ParseMultipartContent(call *Call, p *multipart.Part, b []byte) {
case "patches", "patched_talkgroups":
var (
- f interface{}
+ f any
patches = []uint{}
)
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
- case []interface{}:
+ case []any:
for _, patch := range v {
switch v := patch.(type) {
case float64:
@@ -229,17 +229,17 @@ func ParseMultipartContent(call *Call, p *multipart.Part, b []byte) {
case "sources":
var (
- f interface{}
+ f any
units *Units
)
if err := json.Unmarshal(b, &f); err == nil {
switch v := f.(type) {
- case []interface{}:
- var sources = []map[string]interface{}{}
+ case []any:
+ var sources = []map[string]any{}
for _, f := range v {
- src := map[string]interface{}{}
+ src := map[string]any{}
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
switch v := v["pos"].(type) {
case float64:
if v >= 0 {
@@ -306,7 +306,7 @@ func ParseMultipartContent(call *Call, p *multipart.Part, b []byte) {
}
func ParseTrunkRecorderMeta(call *Call, b []byte) error {
- m := map[string]interface{}{}
+ m := map[string]any{}
if err := json.Unmarshal(b, &m); err != nil {
return err
@@ -320,12 +320,12 @@ func ParseTrunkRecorderMeta(call *Call, b []byte) error {
}
switch v := m["freqList"].(type) {
- case []interface{}:
- freqs := []map[string]interface{}{}
+ case []any:
+ freqs := []map[string]any{}
for _, f := range v {
- freq := map[string]interface{}{}
+ freq := map[string]any{}
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
switch v := v["error_count"].(type) {
case float64:
if v >= 0 {
@@ -368,7 +368,7 @@ func ParseTrunkRecorderMeta(call *Call, b []byte) error {
}
switch v := m["patched_talkgroups"].(type) {
- case []interface{}:
+ case []any:
patches := []uint{}
for _, f := range v {
switch v := f.(type) {
@@ -384,12 +384,12 @@ func ParseTrunkRecorderMeta(call *Call, b []byte) error {
}
switch v := m["srcList"].(type) {
- case []interface{}:
- sources := []map[string]interface{}{}
+ case []any:
+ sources := []map[string]any{}
for _, f := range v {
- source := map[string]interface{}{}
+ source := map[string]any{}
switch v := f.(type) {
- case map[string]interface{}:
+ case map[string]any:
switch v := v["pos"].(type) {
case float64:
if v >= 0 {
diff --git a/server/scheduler.go b/server/scheduler.go
index 43e5ac0..de51f44 100644
--- a/server/scheduler.go
+++ b/server/scheduler.go
@@ -25,7 +25,7 @@ import (
type Scheduler struct {
Controller *Controller
Ticker *time.Ticker
- cancel chan interface{}
+ cancel chan any
mutex sync.Mutex
started bool
}
@@ -33,7 +33,7 @@ type Scheduler struct {
func NewScheduler(controller *Controller) *Scheduler {
return &Scheduler{
Controller: controller,
- cancel: make(chan interface{}),
+ cancel: make(chan any),
}
}
@@ -42,9 +42,6 @@ func (scheduler *Scheduler) pruneDatabase() error {
return nil
}
- scheduler.Controller.IngestLock()
- defer scheduler.Controller.IngestUnlock()
-
scheduler.Controller.Logs.LogEvent(LogLevelInfo, "database pruning")
if err := scheduler.Controller.Calls.Prune(scheduler.Controller.Database, scheduler.Controller.Options.PruneDays); err != nil {
diff --git a/server/system.go b/server/system.go
index a79e44a..d75ff2d 100644
--- a/server/system.go
+++ b/server/system.go
@@ -30,9 +30,9 @@ type System struct {
AutoPopulate bool `json:"autoPopulate"`
Blacklists Blacklists `json:"blacklists"`
Label string `json:"label"`
- Led interface{} `json:"led"`
+ Led any `json:"led"`
Order uint `json:"order"`
- RowId interface{} `json:"_id"`
+ RowId any `json:"_id"`
Talkgroups *Talkgroups `json:"talkgroups"`
Units *Units `json:"units"`
}
@@ -44,7 +44,7 @@ func NewSystem() *System {
}
}
-func (system *System) FromMap(m map[string]interface{}) *System {
+func (system *System) FromMap(m map[string]any) *System {
switch v := m["_id"].(type) {
case float64:
system.RowId = uint(v)
@@ -81,19 +81,19 @@ func (system *System) FromMap(m map[string]interface{}) *System {
}
switch v := m["talkgroups"].(type) {
- case []interface{}:
+ case []any:
system.Talkgroups.FromMap(v)
}
switch v := m["units"].(type) {
- case []interface{}:
+ case []any:
system.Units.FromMap(v)
}
return system
}
-type SystemMap map[string]interface{}
+type SystemMap map[string]any
type Systems struct {
List []*System
@@ -107,7 +107,7 @@ func NewSystems() *Systems {
}
}
-func (systems *Systems) FromMap(f []interface{}) *Systems {
+func (systems *Systems) FromMap(f []any) *Systems {
systems.mutex.Lock()
defer systems.mutex.Unlock()
@@ -115,7 +115,7 @@ func (systems *Systems) FromMap(f []interface{}) *Systems {
for _, r := range f {
switch m := r.(type) {
- case map[string]interface{}:
+ case map[string]any:
system := NewSystem()
system.FromMap(m)
systems.List = append(systems.List, system)
@@ -141,7 +141,7 @@ NextId:
return 0
}
-func (systems *Systems) GetSystem(f interface{}) (system *System, ok bool) {
+func (systems *Systems) GetSystem(f any) (system *System, ok bool) {
systems.mutex.Lock()
defer systems.mutex.Unlock()
@@ -187,10 +187,10 @@ func (systems *Systems) GetScopedSystems(client *Client, groups *Groups, tags *T
}
}
- case []interface{}:
+ case []any:
for _, fSystem := range v {
switch v := fSystem.(type) {
- case map[string]interface{}:
+ case map[string]any:
var (
mSystemId = v["id"]
mTalkgroups = v["talkgroups"]
@@ -216,7 +216,7 @@ func (systems *Systems) GetScopedSystems(client *Client, groups *Groups, tags *T
continue
}
- case []interface{}:
+ case []any:
rawSystem := *system
rawSystem.Talkgroups = NewTalkgroups()
for _, fTalkgroupId := range v {
diff --git a/server/tag.go b/server/tag.go
index 5135e36..7994a2e 100644
--- a/server/tag.go
+++ b/server/tag.go
@@ -24,11 +24,11 @@ import (
)
type Tag struct {
- Id interface{} `json:"_id"`
- Label string `json:"label"`
+ Id any `json:"_id"`
+ Label string `json:"label"`
}
-func (tag *Tag) FromMap(m map[string]interface{}) *Tag {
+func (tag *Tag) FromMap(m map[string]any) *Tag {
switch v := m["_id"].(type) {
case float64:
tag.Id = uint(v)
@@ -54,7 +54,7 @@ func NewTags() *Tags {
}
}
-func (tags *Tags) FromMap(f []interface{}) *Tags {
+func (tags *Tags) FromMap(f []any) *Tags {
tags.mutex.Lock()
defer tags.mutex.Unlock()
@@ -62,7 +62,7 @@ func (tags *Tags) FromMap(f []interface{}) *Tags {
for _, r := range f {
switch m := r.(type) {
- case map[string]interface{}:
+ case map[string]any:
tag := &Tag{}
tag.FromMap(m)
tags.List = append(tags.List, tag)
@@ -72,7 +72,7 @@ func (tags *Tags) FromMap(f []interface{}) *Tags {
return tags
}
-func (tags *Tags) GetTag(f interface{}) (tag *Tag, ok bool) {
+func (tags *Tags) GetTag(f any) (tag *Tag, ok bool) {
tags.mutex.Lock()
defer tags.mutex.Unlock()
diff --git a/server/talkgroup.go b/server/talkgroup.go
index eb6fbb5..06432de 100644
--- a/server/talkgroup.go
+++ b/server/talkgroup.go
@@ -25,19 +25,19 @@ import (
)
type Talkgroup struct {
- Frequency interface{} `json:"frequency"`
+ Frequency any `json:"frequency"`
group string
- GroupId uint `json:"groupId"`
- Id uint `json:"id"`
- Label string `json:"label"`
- Led interface{} `json:"led"`
- Name string `json:"name"`
- Order uint `json:"order"`
- TagId uint `json:"tagId"`
+ GroupId uint `json:"groupId"`
+ Id uint `json:"id"`
+ Label string `json:"label"`
+ Led any `json:"led"`
+ Name string `json:"name"`
+ Order uint `json:"order"`
+ TagId uint `json:"tagId"`
tag string
}
-func (talkgroup *Talkgroup) FromMap(m map[string]interface{}) *Talkgroup {
+func (talkgroup *Talkgroup) FromMap(m map[string]any) *Talkgroup {
switch v := m["id"].(type) {
case float64:
talkgroup.Id = uint(v)
@@ -91,7 +91,7 @@ func (talkgroup *Talkgroup) FromMap(m map[string]interface{}) *Talkgroup {
return talkgroup
}
-type TalkgroupMap map[string]interface{}
+type TalkgroupMap map[string]any
type Talkgroups struct {
List []*Talkgroup
@@ -105,7 +105,7 @@ func NewTalkgroups() *Talkgroups {
}
}
-func (talkgroups *Talkgroups) FromMap(f []interface{}) *Talkgroups {
+func (talkgroups *Talkgroups) FromMap(f []any) *Talkgroups {
talkgroups.mutex.Lock()
defer talkgroups.mutex.Unlock()
@@ -113,7 +113,7 @@ func (talkgroups *Talkgroups) FromMap(f []interface{}) *Talkgroups {
for _, r := range f {
switch m := r.(type) {
- case map[string]interface{}:
+ case map[string]any:
talkgroup := &Talkgroup{}
talkgroup.FromMap(m)
talkgroups.List = append(talkgroups.List, talkgroup)
@@ -123,7 +123,7 @@ func (talkgroups *Talkgroups) FromMap(f []interface{}) *Talkgroups {
return talkgroups
}
-func (talkgroups *Talkgroups) GetTalkgroup(f interface{}) (system *Talkgroup, ok bool) {
+func (talkgroups *Talkgroups) GetTalkgroup(f any) (system *Talkgroup, ok bool) {
talkgroups.mutex.Lock()
defer talkgroups.mutex.Unlock()
diff --git a/server/unit.go b/server/unit.go
index a64f784..1351761 100644
--- a/server/unit.go
+++ b/server/unit.go
@@ -30,7 +30,7 @@ type Unit struct {
Order uint `json:"order"`
}
-func (unit *Unit) FromMap(m map[string]interface{}) *Unit {
+func (unit *Unit) FromMap(m map[string]any) *Unit {
switch v := m["id"].(type) {
case float64:
unit.Id = uint(v)
@@ -78,7 +78,7 @@ func (units *Units) Add(id uint, label string) (*Units, bool) {
return units, added
}
-func (units *Units) FromMap(f []interface{}) *Units {
+func (units *Units) FromMap(f []any) *Units {
units.mutex.Lock()
defer units.mutex.Unlock()
@@ -86,7 +86,7 @@ func (units *Units) FromMap(f []interface{}) *Units {
for _, r := range f {
switch m := r.(type) {
- case map[string]interface{}:
+ case map[string]any:
unit := &Unit{}
unit.FromMap(m)
units.List = append(units.List, unit)
diff --git a/server/version.go b/server/version.go
index 70b2904..f04878d 100644
--- a/server/version.go
+++ b/server/version.go
@@ -15,4 +15,4 @@
package main
-const Version = "6.4.5"
+const Version = "6.5.0"