145 lines
2.7 KiB
Go
145 lines
2.7 KiB
Go
package talkgroups
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"dynatron.me/x/stillbox/internal/jsontypes"
|
|
"dynatron.me/x/stillbox/pkg/database"
|
|
)
|
|
|
|
type ImportSource string
|
|
|
|
const (
|
|
ImportSrcRadioReference ImportSource = "radioreference"
|
|
)
|
|
|
|
var (
|
|
ErrBadImportType = errors.New("unknown import type")
|
|
)
|
|
|
|
type importer interface {
|
|
importTalkgroups(ctx context.Context, sys int, r io.Reader) ([]Talkgroup, error)
|
|
}
|
|
|
|
type ImportJob struct {
|
|
Type ImportSource `json:"type"`
|
|
SystemID int `json:"systemID"`
|
|
Body string `json:"body"`
|
|
|
|
importer `json:"-"`
|
|
}
|
|
|
|
func (ij *ImportJob) Import(ctx context.Context) ([]Talkgroup, error) {
|
|
r := bytes.NewReader([]byte(ij.Body))
|
|
|
|
switch ij.Type {
|
|
case ImportSrcRadioReference:
|
|
ij.importer = new(radioReferenceImporter)
|
|
default:
|
|
return nil, ErrBadImportType
|
|
}
|
|
|
|
return ij.importTalkgroups(ctx, ij.SystemID, r)
|
|
}
|
|
|
|
type radioReferenceImporter struct {
|
|
}
|
|
|
|
type rrState int
|
|
|
|
const (
|
|
rrsInitial rrState = iota
|
|
rrsGroupDesc
|
|
rrsTG
|
|
)
|
|
|
|
var rrRE = regexp.MustCompile(`DEC\s+HEX\s+Mode\s+Alpha Tag\s+Description\s+Tag`)
|
|
|
|
func (rr *radioReferenceImporter) importTalkgroups(ctx context.Context, sys int, r io.Reader) ([]Talkgroup, error) {
|
|
sc := bufio.NewScanner(r)
|
|
tgs := make([]Talkgroup, 0, 8)
|
|
sysn, has := StoreFrom(ctx).SystemName(ctx, sys)
|
|
if !has {
|
|
return nil, ErrNoSuchSystem
|
|
}
|
|
|
|
importedFrom := jsontypes.Metadata{
|
|
"from": "RadioReference",
|
|
"time": time.Now(),
|
|
}
|
|
|
|
var groupName string
|
|
state := rrsInitial
|
|
for sc.Scan() {
|
|
if err := ctx.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ln := strings.Trim(sc.Text(), " \t\r\n")
|
|
|
|
switch state {
|
|
case rrsInitial:
|
|
groupName = ln
|
|
state++
|
|
case rrsGroupDesc:
|
|
if rrRE.MatchString(ln) {
|
|
state++
|
|
}
|
|
case rrsTG:
|
|
fields := strings.Split(ln, "\t")
|
|
if len(fields) != 6 {
|
|
state = rrsGroupDesc
|
|
groupName = ln
|
|
continue
|
|
}
|
|
tgid, err := strconv.Atoi(fields[0])
|
|
if err != nil {
|
|
continue
|
|
}
|
|
metadata := jsontypes.Metadata{
|
|
"imported": importedFrom,
|
|
}
|
|
tgt := TG(sys, tgid)
|
|
mode := fields[2]
|
|
if strings.Contains(mode, "E") {
|
|
metadata["encrypted"] = true
|
|
}
|
|
tags := []string{fields[5]}
|
|
gn := groupName // must take a copy
|
|
tgs = append(tgs, Talkgroup{
|
|
Talkgroup: database.Talkgroup{
|
|
ID: uuid.New(),
|
|
Tgid: int32(tgt.Talkgroup),
|
|
SystemID: int32(tgt.System),
|
|
Name: &fields[4],
|
|
AlphaTag: &fields[3],
|
|
TgGroup: &gn,
|
|
Metadata: metadata,
|
|
Tags: tags,
|
|
Weight: 1.0,
|
|
},
|
|
System: database.System{
|
|
ID: sys,
|
|
Name: sysn,
|
|
},
|
|
})
|
|
|
|
}
|
|
}
|
|
|
|
if err := sc.Err(); err != nil {
|
|
return tgs, err
|
|
}
|
|
|
|
return tgs, nil
|
|
}
|