From 24f4b6b8f500f0bccb406b4c8dbc86f06211527a Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Wed, 19 Apr 2023 18:04:10 -0600 Subject: [PATCH] v01 config has gm.hotwords.[].{call,args} and impl tap to link /gm/rpc/someoneSaidAlias to button pushes --- src/device/input/parse/v01/config.go | 10 ++++ src/device/input/parse/v01/server.go | 27 +++++++++- src/device/input/parse/v01/server_test.go | 56 +++++++++++++------- src/device/input/parse/v01/testdata/v01.yaml | 8 +++ src/device/input/parse/v01/v01.go | 7 +++ 5 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/device/input/parse/v01/config.go b/src/device/input/parse/v01/config.go index 2f4ca37..f65356a 100644 --- a/src/device/input/parse/v01/config.go +++ b/src/device/input/parse/v01/config.go @@ -15,6 +15,16 @@ type ( Players []configPlayer Quiet bool Broadcast configBroadcast + GM configGM + } + + configGM struct { + Hotwords map[string]configGMHotword + } + + configGMHotword struct { + Call string + Args []string } configBroadcast struct { diff --git a/src/device/input/parse/v01/server.go b/src/device/input/parse/v01/server.go index 34e8b03..d1cb451 100644 --- a/src/device/input/parse/v01/server.go +++ b/src/device/input/parse/v01/server.go @@ -7,6 +7,7 @@ import ( "io" "log" "math/rand" + "mayhem-party/src/device/input/button" "mayhem-party/src/device/input/wrap" "net/http" "os" @@ -178,7 +179,7 @@ func (v01 *V01) serveGM(w http.ResponseWriter, r *http.Request) { case "/gm/rpc/status": v01.serveGMStatus(w) case "/gm/rpc/broadcastSomeoneSaidAlias": - v01.serveGMSomeoneSaidAlias(w, r) + v01.serveGMSomeoneSaid(w, r) case "/gm/rpc/fillNonPlayerAliases": v01.serveGMFillNonPlayerAliases(w, r) case "/gm/rpc/vote": @@ -223,6 +224,30 @@ func (v01 *V01) serveGMStatus(w io.Writer) { w.Write(b) } +func (v01 *V01) serveGMSomeoneSaid(w http.ResponseWriter, r *http.Request) { + if gmHotword, ok := v01.cfg.GM.Hotwords[r.URL.Query().Get("message")]; ok { + v01.serveGMSomeoneSaidGMHotword(w, r, gmHotword) + } + v01.serveGMSomeoneSaidAlias(w, r) +} + +func (v01 *V01) serveGMSomeoneSaidGMHotword(w http.ResponseWriter, r *http.Request, gmHotword configGMHotword) { + switch gmHotword.Call { + case "tap": + args := append([]string{}, gmHotword.Args...) + if len(args) < 1 || len(args[0]) < 1 { + return + } + btn := args[0][0] + go func() { + v01.alt <- []button.Button{button.Button{Down: true, Char: btn}} + v01.alt <- []button.Button{button.Button{Down: false, Char: btn}} + }() + default: + http.NotFound(w, r) + } +} + func (v01 *V01) serveGMSomeoneSaidAlias(w http.ResponseWriter, r *http.Request) { v01.cfg.Quiet = true for k, v := range v01.cfg.Users { diff --git a/src/device/input/parse/v01/server_test.go b/src/device/input/parse/v01/server_test.go index 84bbc92..22a13f3 100644 --- a/src/device/input/parse/v01/server_test.go +++ b/src/device/input/parse/v01/server_test.go @@ -96,12 +96,8 @@ func TestServeGM(t *testing.T) { t.Run("status", func(t *testing.T) { v01 := NewV01(ctx, nil) var result struct { - Players int `yaml:"Players"` - Users map[string]struct { - Player int - Lag string - IdleFor string `yaml:"idle_for"` - } `yaml:"Users"` + Players int `yaml:"Players"` + Users map[string]string `yaml:"Users"` } t.Run("empty", func(t *testing.T) { @@ -157,22 +153,46 @@ func TestServeGM(t *testing.T) { if len(result.Users) != 7 { t.Error(result.Users) } - if d, err := time.ParseDuration(result.Users["bel"].Lag); err != nil { - t.Error(err) - } else if d != time.Second { - t.Error(d) - } - if d, err := time.ParseDuration(result.Users["bel"].IdleFor); err != nil { - t.Error(err) - } else if d < time.Minute || d > 2*time.Minute { - t.Error(d) - } - if result.Users["bel"].Player != 3 { - t.Error(result.Users["bel"].Player) + if result.Users["bel"] == "" || result.Users["bel"] == "..." { + t.Error(result.Users["bel"]) } }) }) + t.Run("broadcastSomeoneSaidAlias to hotword tap", func(t *testing.T) { + v01 := NewV01(ctx, nil) + v01.cfg.GM = configGM{ + Hotwords: map[string]configGMHotword{ + "hotword": configGMHotword{ + Call: "tap", + Args: []string{"a"}, + }, + }, + } + do(v01, "/gm/rpc/broadcastSomeoneSaidAlias?message=hotword", "") + for i := 0; i < 2; i++ { + select { + case btn := <-v01.alt: + if len(btn) != 1 { + t.Error(btn) + } else if btn[0].Down != (i == 0) { + t.Error(btn[0]) + } else if btn[0].Char != 'a' { + t.Error(btn[0].Char) + } + case <-time.After(time.Second): + t.Fatal("nothing in alt") + } + } + do(v01, "/gm/rpc/broadcastSomeoneSaidAlias?message=hotword", "") + time.Sleep(time.Millisecond * 150) + if got := v01.Read(); len(got) != 1 || !got[0].Down || got[0].Char != 'a' { + t.Error(got) + } else if got := v01.Read(); len(got) != 1 || got[0].Down || got[0].Char != 'a' { + t.Error(got) + } + }) + t.Run("broadcastSomeoneSaidAlias", func(t *testing.T) { v01 := NewV01(ctx, nil) v01.cfg.Quiet = false diff --git a/src/device/input/parse/v01/testdata/v01.yaml b/src/device/input/parse/v01/testdata/v01.yaml index ae71f84..a169eda 100644 --- a/src/device/input/parse/v01/testdata/v01.yaml +++ b/src/device/input/parse/v01/testdata/v01.yaml @@ -18,3 +18,11 @@ players: quiet: false broadcast: message: hi +gm: + hotwords: + coin: + call: tap + args: ['!'] + star: + call: tap + args: ['?'] diff --git a/src/device/input/parse/v01/v01.go b/src/device/input/parse/v01/v01.go index d0a4ebe..95e647f 100644 --- a/src/device/input/parse/v01/v01.go +++ b/src/device/input/parse/v01/v01.go @@ -26,6 +26,7 @@ type ( src raw.Raw cfg config telemetryc chan message + alt chan []button.Button } ) @@ -41,6 +42,7 @@ func NewV01(ctx context.Context, src raw.Raw) *V01 { src: src, cfg: cfg, telemetryc: make(chan message), + alt: make(chan []button.Button, 2), } go result.listen() go result.dotelemetry() @@ -58,6 +60,11 @@ func (v01 *V01) Close() { } func (v01 *V01) Read() []button.Button { + select { + case alt := <-v01.alt: + return alt + default: + } line := v01.src.Read() var msg message if err := json.Unmarshal(line, &msg); err != nil {