diff --git a/api/main.proto b/api/main.proto
index 1a3ee65..df9eb97 100644
--- a/api/main.proto
+++ b/api/main.proto
@@ -2420,6 +2420,7 @@ message GetDevicesReq { optional int32 gameID = 1; }
message GetDevicesRsp {
repeated VenueDevice devices = 1;
google.protobuf.Timestamp serverTime = 2;
+ VenueWiFi wifi = 3; // Entire venue, independent of the game filter.
}
message VenueDevice {
@@ -2442,3 +2443,18 @@ message DeviceConnection {
optional int32 screenID = 9;
string kind = 10; // browser, organizer, team, screen
}
+
+message VenueWiFi {
+ bool enabled = 1;
+ google.protobuf.Timestamp collectedAt = 2;
+ bool stale = 3;
+ bool hasError = 4;
+ repeated WiFiClient clients = 5;
+}
+
+message WiFiClient {
+ string IP = 1;
+ string MAC = 2;
+ string band = 3;
+ optional int32 signal = 4; // dBm; absent when the router does not report it.
+}
diff --git a/cmd/evening_detective_server/cudy.go b/cmd/evening_detective_server/cudy.go
new file mode 100644
index 0000000..561292a
--- /dev/null
+++ b/cmd/evening_detective_server/cudy.go
@@ -0,0 +1,88 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "log"
+ "os"
+ "os/signal"
+ "path/filepath"
+ "strings"
+ "syscall"
+ "time"
+
+ "evening_detective_server/internal/modules/cudy"
+ "evening_detective_server/internal/services/wifi_service"
+)
+
+func collectCudy() {
+ path := os.Getenv("CUDY_SNAPSHOT_FILE")
+ if path == "" {
+ log.Fatal("CUDY_SNAPSHOT_FILE is required")
+ }
+ ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
+ defer stop()
+ snapshot := cudy.Snapshot{}
+ var reader cudy.Reader
+ passwordFile := os.Getenv("CUDY_PASSWORD_FILE")
+ if passwordFile != "" {
+ password, err := os.ReadFile(passwordFile)
+ if err != nil {
+ log.Fatal("cannot read Cudy credential file")
+ }
+ base := os.Getenv("CUDY_URL")
+ if base == "" {
+ base = "http://192.168.10.1"
+ }
+ reader, err = cudy.NewReader(base, strings.TrimRight(string(password), "\r\n"))
+ if err != nil {
+ log.Fatal("invalid Cudy configuration")
+ }
+ snapshot, _ = wifi_service.New(path).Get(ctx)
+ snapshot.Enabled = true
+ }
+ timer := time.NewTicker(10 * time.Second)
+ defer timer.Stop()
+ for {
+ if reader != nil {
+ clients, err := reader.Read(ctx)
+ snapshot.HasError = err != nil
+ if err == nil {
+ snapshot.Clients = clients
+ snapshot.CollectedAt = time.Now().UTC()
+ }
+ }
+ if err := writeCudySnapshot(path, snapshot); err != nil {
+ log.Print("cannot publish Cudy snapshot")
+ }
+ select {
+ case <-ctx.Done():
+ return
+ case <-timer.C:
+ }
+ }
+}
+
+func writeCudySnapshot(path string, snapshot cudy.Snapshot) error {
+ data, err := json.Marshal(snapshot)
+ if err != nil {
+ return err
+ }
+ file, err := os.CreateTemp(filepath.Dir(path), ".cudy-")
+ if err != nil {
+ return err
+ }
+ name := file.Name()
+ defer os.Remove(name)
+ if err = file.Chmod(0644); err == nil {
+ _, err = file.Write(data)
+ }
+ closeErr := file.Close()
+ if err != nil {
+ return err
+ }
+ if closeErr != nil {
+ return closeErr
+ }
+ return os.Rename(name, path)
+}
diff --git a/cmd/evening_detective_server/cudy_test.go b/cmd/evening_detective_server/cudy_test.go
new file mode 100644
index 0000000..a40b583
--- /dev/null
+++ b/cmd/evening_detective_server/cudy_test.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "evening_detective_server/internal/modules/cudy"
+)
+
+func TestAtomicCudySnapshot(t *testing.T) {
+ dir := t.TempDir()
+ path := filepath.Join(dir, "state.json")
+ for _, failed := range []bool{false, true} {
+ snapshot := cudy.Snapshot{Enabled: true, CollectedAt: time.Unix(123, 0), HasError: failed, Clients: []cudy.Client{{MAC: "AA:BB:CC:DD:EE:01"}}}
+ if err := writeCudySnapshot(path, snapshot); err != nil {
+ t.Fatal(err)
+ }
+ data, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ var result cudy.Snapshot
+ if json.Unmarshal(data, &result) != nil || result.HasError != failed || len(result.Clients) != 1 {
+ t.Fatal("snapshot corrupted")
+ }
+ }
+ files, err := os.ReadDir(dir)
+ if err != nil || len(files) != 1 {
+ t.Fatal("temporary snapshots left behind")
+ }
+}
diff --git a/cmd/evening_detective_server/main.go b/cmd/evening_detective_server/main.go
index e3cd81c..4490d37 100644
--- a/cmd/evening_detective_server/main.go
+++ b/cmd/evening_detective_server/main.go
@@ -56,6 +56,7 @@ import (
"evening_detective_server/internal/services/ticket_service"
"evening_detective_server/internal/services/ui_service"
"evening_detective_server/internal/services/users_service"
+ "evening_detective_server/internal/services/wifi_service"
proto "evening_detective_server/proto"
"fmt"
"log"
@@ -89,6 +90,10 @@ const grpcMsgLimit = 257 << 20
func main() {
_ = godotenv.Load()
+ if len(os.Args) == 2 && os.Args[1] == "--collect-cudy" {
+ collectCudy()
+ return
+ }
mode := "prod"
if os.Getenv("APP_MODE") == "venue" {
mode = "venue"
@@ -292,6 +297,7 @@ func main() {
gameResultsService,
gameResultsApplyService,
devicePresenceService,
+ wifi_service.New(os.Getenv("CUDY_SNAPSHOT_FILE")),
),
)
diff --git a/cmd/evening_detective_server/main.swagger.json b/cmd/evening_detective_server/main.swagger.json
index 10187b1..7218d32 100644
--- a/cmd/evening_detective_server/main.swagger.json
+++ b/cmd/evening_detective_server/main.swagger.json
@@ -5056,6 +5056,10 @@
"serverTime": {
"type": "string",
"format": "date-time"
+ },
+ "wifi": {
+ "$ref": "#/definitions/evening_detective_serverVenueWiFi",
+ "description": "Entire venue, independent of the game filter."
}
}
},
@@ -6346,6 +6350,50 @@
}
}
},
+ "evening_detective_serverVenueWiFi": {
+ "type": "object",
+ "properties": {
+ "enabled": {
+ "type": "boolean"
+ },
+ "collectedAt": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "stale": {
+ "type": "boolean"
+ },
+ "hasError": {
+ "type": "boolean"
+ },
+ "clients": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "$ref": "#/definitions/evening_detective_serverWiFiClient"
+ }
+ }
+ }
+ },
+ "evening_detective_serverWiFiClient": {
+ "type": "object",
+ "properties": {
+ "IP": {
+ "type": "string"
+ },
+ "MAC": {
+ "type": "string"
+ },
+ "band": {
+ "type": "string"
+ },
+ "signal": {
+ "type": "integer",
+ "format": "int32",
+ "description": "dBm; absent when the router does not report it."
+ }
+ }
+ },
"protobufAny": {
"type": "object",
"properties": {
diff --git a/internal/app/devices.go b/internal/app/devices.go
index bf33433..9a5f1a8 100644
--- a/internal/app/devices.go
+++ b/internal/app/devices.go
@@ -52,7 +52,9 @@ func (s *server) GetDevices(ctx context.Context, req *proto.GetDevicesReq) (*pro
if err != nil {
return nil, deviceErrorStatus(err)
}
+ wifi, stale := s.wifiService.Get(ctx)
return &proto.GetDevicesRsp{
+ Wifi: mapWiFi(wifi, stale),
Devices: mapVenueDevices(devices),
ServerTime: timestamppb.New(now),
}, nil
diff --git a/internal/app/devices_mapper.go b/internal/app/devices_mapper.go
index fffd6a0..9b66104 100644
--- a/internal/app/devices_mapper.go
+++ b/internal/app/devices_mapper.go
@@ -1,6 +1,7 @@
package app
import (
+ "evening_detective_server/internal/modules/cudy"
"evening_detective_server/internal/services/device_presence_service"
proto "evening_detective_server/proto"
@@ -51,3 +52,29 @@ func mapVenueDevices(devices []device_presence_service.Device) []*proto.VenueDev
}
return result
}
+
+func mapWiFi(snapshot cudy.Snapshot, stale bool) *proto.VenueWiFi {
+ result := &proto.VenueWiFi{
+ Enabled: snapshot.Enabled,
+ Stale: stale,
+ HasError: snapshot.HasError,
+ Clients: make([]*proto.WiFiClient, 0, len(snapshot.Clients)),
+ }
+ if !snapshot.CollectedAt.IsZero() {
+ result.CollectedAt = timestamppb.New(snapshot.CollectedAt)
+ }
+ for _, client := range snapshot.Clients {
+ var signal *int32
+ if client.Signal != nil {
+ value := int32(*client.Signal)
+ signal = &value
+ }
+ result.Clients = append(result.Clients, &proto.WiFiClient{
+ IP: client.IP,
+ MAC: client.MAC,
+ Band: client.Band,
+ Signal: signal,
+ })
+ }
+ return result
+}
diff --git a/internal/app/devices_test.go b/internal/app/devices_test.go
index 43c6376..0ddb3e1 100644
--- a/internal/app/devices_test.go
+++ b/internal/app/devices_test.go
@@ -2,15 +2,21 @@ package app
import (
"context"
+ "encoding/json"
"errors"
+ "os"
+ "path/filepath"
"strings"
"testing"
+ "time"
+ "evening_detective_server/internal/modules/cudy"
"evening_detective_server/internal/modules/processor_jwt"
"evening_detective_server/internal/services/device_presence_service"
"evening_detective_server/internal/services/game_service"
"evening_detective_server/internal/services/screen_service"
"evening_detective_server/internal/services/team_service"
+ "evening_detective_server/internal/services/wifi_service"
proto "evening_detective_server/proto"
"github.com/google/uuid"
@@ -97,3 +103,32 @@ func TestDeviceErrors(t *testing.T) {
}
}
}
+
+func TestWiFiUsesExistingPresencePermissions(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "state.json")
+ signal := -65
+ snapshot := cudy.Snapshot{Enabled: true, CollectedAt: time.Now().UTC(), Clients: []cudy.Client{{IP: "192.168.10.9", MAC: "AA:BB:CC:DD:EE:01", Band: "5 GHz", Signal: &signal}}}
+ data, err := json.Marshal(snapshot)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := os.WriteFile(path, data, 0600); err != nil {
+ t.Fatal(err)
+ }
+ s := &server{devicePresenceService: device_presence_service.NewDevicePresenceService(true, nil, nil, nil), wifiService: wifi_service.New(path)}
+ for _, role := range []string{"organizer", "developer", "admin"} {
+ ctx := processor_jwt.ContextWithClaims(context.Background(), &processor_jwt.JWTClaims{Roles: []string{role}})
+ result, err := s.GetDevices(ctx, &proto.GetDevicesReq{})
+ if err != nil || !result.Wifi.Enabled || result.Wifi.Stale || len(result.Wifi.Clients) != 1 || result.Wifi.Clients[0].GetSignal() != -65 {
+ t.Fatalf("Wi-Fi for %s: %v, %v", role, result, err)
+ }
+ }
+ if _, err := s.GetDevices(context.Background(), &proto.GetDevicesReq{}); status.Code(err) != codes.PermissionDenied {
+ t.Fatal(err)
+ }
+ s.devicePresenceService = device_presence_service.NewDevicePresenceService(false, nil, nil, nil)
+ ctx := processor_jwt.ContextWithClaims(context.Background(), &processor_jwt.JWTClaims{Roles: []string{"developer"}})
+ if _, err := s.GetDevices(ctx, &proto.GetDevicesReq{}); status.Code(err) != codes.FailedPrecondition {
+ t.Fatal("prod exposes Wi-Fi", err)
+ }
+}
diff --git a/internal/app/server.go b/internal/app/server.go
index 7139ec0..35b09cd 100644
--- a/internal/app/server.go
+++ b/internal/app/server.go
@@ -21,6 +21,7 @@ import (
"evening_detective_server/internal/services/ticket_service"
"evening_detective_server/internal/services/ui_service"
"evening_detective_server/internal/services/users_service"
+ "evening_detective_server/internal/services/wifi_service"
proto "evening_detective_server/proto"
)
@@ -28,6 +29,7 @@ type server struct {
proto.UnsafeEveningDetectiveServerServer
devicePresenceService *device_presence_service.DevicePresenceService
+ wifiService *wifi_service.Service
usersService *users_service.UsersService
uiService *ui_service.UIService
taskService *task_service.TaskService
@@ -73,9 +75,11 @@ func NewServer(
gameResultsService *game_results_package_service.GameResultsPackageService,
gameResultsApplyService *game_results_package_service.GameResultsApplyService,
devicePresenceService *device_presence_service.DevicePresenceService,
+ wifiService *wifi_service.Service,
) proto.EveningDetectiveServerServer {
return &server{
devicePresenceService: devicePresenceService,
+ wifiService: wifiService,
gameImportService: gameImportService,
gameResultsService: gameResultsService,
gameResultsApplyService: gameResultsApplyService,
diff --git a/internal/modules/cudy/client.go b/internal/modules/cudy/client.go
new file mode 100644
index 0000000..23c73f0
--- /dev/null
+++ b/internal/modules/cudy/client.go
@@ -0,0 +1,175 @@
+package cudy
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+ "io"
+ "net/http"
+ "net/http/cookiejar"
+ "net/netip"
+ "net/url"
+ "strings"
+ "time"
+
+ "golang.org/x/net/html"
+)
+
+var ErrRead = errors.New("не удалось прочитать Wi-Fi Cudy")
+
+const maxBody = 2 << 20
+
+type reader struct {
+ base string
+ password string
+ http *http.Client
+ authenticated bool
+}
+
+func NewReader(base, password string) (Reader, error) {
+ u, err := url.Parse(base)
+ if err != nil || u.User != nil || u.RawQuery != "" || u.Fragment != "" || (u.Path != "" && u.Path != "/") || (u.Scheme != "http" && u.Scheme != "https") {
+ return nil, ErrRead
+ }
+ ip, err := netip.ParseAddr(u.Hostname())
+ if err != nil || (!ip.IsPrivate() && !ip.IsLoopback()) || password == "" {
+ return nil, ErrRead
+ }
+ jar, _ := cookiejar.New(nil)
+ client := &http.Client{Timeout: 5 * time.Second, Jar: jar, Transport: &http.Transport{Proxy: nil}, CheckRedirect: func(req *http.Request, via []*http.Request) error {
+ if len(via) > 5 || req.URL.Host != u.Host || req.URL.Scheme != u.Scheme {
+ return ErrRead
+ }
+ return nil
+ }}
+ return &reader{base: strings.TrimRight(base, "/"), password: password, http: client}, nil
+}
+
+func (r *reader) request(ctx context.Context, path string, form url.Values) ([]byte, int, error) {
+ method := http.MethodGet
+ var body io.Reader
+ if form != nil {
+ method = http.MethodPost
+ body = strings.NewReader(form.Encode())
+ }
+ req, err := http.NewRequestWithContext(ctx, method, r.base+path, body)
+ if err != nil {
+ return nil, 0, ErrRead
+ }
+ if form != nil {
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ }
+ resp, err := r.http.Do(req)
+ if err != nil {
+ if ctx.Err() != nil {
+ return nil, 0, ctx.Err()
+ }
+ return nil, 0, ErrRead
+ }
+ defer resp.Body.Close()
+ data, err := io.ReadAll(io.LimitReader(resp.Body, maxBody+1))
+ if err != nil || len(data) > maxBody {
+ return nil, resp.StatusCode, ErrRead
+ }
+ return data, resp.StatusCode, nil
+}
+
+func (r *reader) login(ctx context.Context) error {
+ data, code, err := r.request(ctx, "/cgi-bin/luci/", nil)
+ if err != nil {
+ return err
+ }
+ if code != http.StatusForbidden && code != http.StatusOK {
+ return ErrRead
+ }
+ doc, err := html.Parse(strings.NewReader(string(data)))
+ if err != nil {
+ return ErrRead
+ }
+ form := url.Values{}
+ walk(doc, func(n *html.Node) {
+ if n.Type == html.ElementNode && n.Data == "input" && attr(n, "type") == "hidden" {
+ switch attr(n, "name") {
+ case "_csrf", "salt", "token":
+ form.Set(attr(n, "name"), attr(n, "value"))
+ }
+ }
+ })
+ if form.Get("salt") == "" || form.Get("_csrf") == "" {
+ return ErrRead
+ }
+ token, code, err := r.request(ctx, "/cgi-bin/luci/admin/get_token", url.Values{})
+ if err != nil {
+ return err
+ }
+ if code != http.StatusOK || len(token) > 256 || len(token) == 0 {
+ return ErrRead
+ }
+ hash := sha256.Sum256([]byte(r.password + form.Get("salt")))
+ hash = sha256.Sum256([]byte(hex.EncodeToString(hash[:]) + strings.TrimSpace(string(token))))
+ form.Set("luci_username", "admin")
+ form.Set("luci_password", hex.EncodeToString(hash[:]))
+ form.Set("token", strings.TrimSpace(string(token)))
+ form.Set("luci_language", "en")
+ data, code, err = r.request(ctx, "/cgi-bin/luci/", form)
+ if err != nil {
+ return err
+ }
+ if code != http.StatusOK || strings.Contains(string(data), "luci_password_login") {
+ return ErrRead
+ }
+ r.authenticated = true
+ return nil
+}
+
+func (r *reader) Read(ctx context.Context) ([]Client, error) {
+ if !r.authenticated {
+ if err := r.login(ctx); err != nil {
+ return nil, err
+ }
+ }
+ data, code, err := r.request(ctx, "/cgi-bin/luci/admin/network/devices/devlist?detail=1", nil)
+ if err != nil {
+ return nil, err
+ }
+ if code == http.StatusForbidden || code == http.StatusUnauthorized || strings.Contains(string(data), "luci_password_login") {
+ r.authenticated = false
+ if err := r.login(ctx); err != nil {
+ return nil, err
+ }
+ data, code, err = r.request(ctx, "/cgi-bin/luci/admin/network/devices/devlist?detail=1", nil)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if code != http.StatusOK {
+ return nil, ErrRead
+ }
+ return parseClients(data)
+}
+
+func attr(n *html.Node, key string) string {
+ for _, a := range n.Attr {
+ if a.Key == key {
+ return a.Val
+ }
+ }
+ return ""
+}
+func walk(n *html.Node, visit func(*html.Node)) {
+ visit(n)
+ for c := n.FirstChild; c != nil; c = c.NextSibling {
+ walk(c, visit)
+ }
+}
+func nodeText(n *html.Node) string {
+ var out strings.Builder
+ walk(n, func(c *html.Node) {
+ if c.Type == html.TextNode {
+ out.WriteString(c.Data)
+ out.WriteByte(' ')
+ }
+ })
+ return strings.TrimSpace(out.String())
+}
diff --git a/internal/modules/cudy/client_parser.go b/internal/modules/cudy/client_parser.go
new file mode 100644
index 0000000..1d49cf9
--- /dev/null
+++ b/internal/modules/cudy/client_parser.go
@@ -0,0 +1,123 @@
+package cudy
+
+import (
+ "net"
+ "net/netip"
+ "sort"
+ "strconv"
+ "strings"
+
+ "golang.org/x/net/html"
+)
+
+func parseClients(data []byte) ([]Client, error) {
+ doc, err := html.Parse(strings.NewReader(string(data)))
+ if err != nil {
+ return nil, ErrRead
+ }
+ clients := []Client{}
+ var table *html.Node
+ walk(doc, func(n *html.Node) {
+ if n.Data == "th" && nodeText(n) == "IP / MAC Address" {
+ for parent := n.Parent; parent != nil; parent = parent.Parent {
+ if parent.Data == "table" {
+ table = parent
+ break
+ }
+ }
+ }
+ })
+ if table == nil {
+ return nil, ErrRead
+ }
+ invalid := false
+ seen := map[string]bool{}
+ walk(table, func(row *html.Node) {
+ if row.Type != html.ElementNode {
+ return
+ }
+ if row.Data != "tr" {
+ return
+ }
+ hasData := false
+ for child := row.FirstChild; child != nil; child = child.NextSibling {
+ hasData = hasData || child.Data == "td"
+ }
+ if !hasData {
+ return
+ }
+ if !strings.HasPrefix(attr(row, "id"), "cbi-table-") {
+ invalid = true
+ return
+ }
+ fields := map[string]*html.Node{}
+ prefix := attr(row, "id") + "-"
+ walk(row, func(n *html.Node) {
+ if n.Data == "div" && strings.HasPrefix(attr(n, "id"), prefix) {
+ fields[strings.TrimPrefix(attr(n, "id"), prefix)] = n
+ }
+ })
+ var band string
+ wired := false
+ if hostname := fields["hostname"]; hostname != nil {
+ walk(hostname, func(n *html.Node) {
+ if n.Data == "span" {
+ label := nodeText(n)
+ wired = wired || label == "Ethernet"
+ if label == "2.4G WiFi" {
+ band = "2.4 GHz"
+ }
+ if label == "5G WiFi" {
+ band = "5 GHz"
+ }
+ }
+ })
+ }
+ // shortcut: stock TR3000 2.5.27 DOM and two bands; update parser fixtures for other firmware.
+ if band == "" {
+ if !wired {
+ invalid = true
+ }
+ return
+ }
+ client := Client{Band: band}
+ if field := fields["ipmac"]; field != nil {
+ walk(field, func(n *html.Node) {
+ if n.Data != "p" || client.MAC != "" {
+ return
+ }
+ for _, value := range strings.Fields(nodeText(n)) {
+ if ip, e := netip.ParseAddr(value); e == nil {
+ client.IP = ip.String()
+ }
+ if mac, e := net.ParseMAC(value); e == nil && len(mac) == 6 {
+ client.MAC = strings.ToUpper(mac.String())
+ }
+ }
+ })
+ }
+ if field := fields["signal"]; field != nil {
+ walk(field, func(n *html.Node) {
+ if n.Data == "p" && client.Signal == nil {
+ parts := strings.Fields(nodeText(n))
+ if len(parts) == 2 && parts[1] == "dBm" {
+ if value, e := strconv.Atoi(parts[0]); e == nil && value >= -120 && value <= 0 {
+ client.Signal = &value
+ }
+ }
+ }
+ })
+ }
+ if client.MAC == "" || seen[client.MAC] {
+ invalid = true
+ return
+ }
+ seen[client.MAC] = true
+ clients = append(clients, client)
+ })
+ if invalid || len(clients) > 1024 {
+ return nil, ErrRead
+ }
+ sort.Slice(clients, func(i, j int) bool { return clients[i].MAC < clients[j].MAC })
+ return clients, nil
+}
diff --git a/internal/modules/cudy/client_test.go b/internal/modules/cudy/client_test.go
new file mode 100644
index 0000000..449eae8
--- /dev/null
+++ b/internal/modules/cudy/client_test.go
@@ -0,0 +1,120 @@
+package cudy
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "strings"
+ "testing"
+)
+
+func clientRow(id, mac, band, signal string) string {
+ return fmt.Sprintf(`
| 192.168.10.9 %s 192.168.10.9 %s | |
`, id, id, band, id, mac, mac, id, signal, signal)
+}
+func clientTable(rows string) string {
+ return `| IP / MAC Address |
` + rows + `
`
+}
+
+func TestParseClients(t *testing.T) {
+ rows := clientRow("1", "AA:BB:CC:DD:EE:02", "2.4G WiFi", "-60 dBm") + clientRow("2", "AA:BB:CC:DD:EE:01", "5G WiFi", "—") + clientRow("3", "AA:BB:CC:DD:EE:03", "Ethernet", "—")
+ clients, err := parseClients([]byte(clientTable(rows)))
+ if err != nil || len(clients) != 2 {
+ t.Fatalf("reading: %v, count %d", err, len(clients))
+ }
+ if clients[0].MAC != "AA:BB:CC:DD:EE:01" || clients[0].Signal != nil || clients[1].Signal == nil || *clients[1].Signal != -60 {
+ t.Fatalf("unexpected snapshot: %+v", clients)
+ }
+ data, _ := json.Marshal(clients)
+ if strings.Contains(string(data), "PRIVATE") {
+ t.Fatal("hostname leaked")
+ }
+ for _, text := range []string{``, clientTable(clientRow("1", "bad", "5G WiFi", "-60 dBm")), clientTable(strings.ReplaceAll(clientRow("1", "AA:BB:CC:DD:EE:01", "5G WiFi", "-60 dBm"), "cbi-table-", "changed-")), clientTable(clientRow("1", "AA:BB:CC:DD:EE:01", "5 GHz", "-60 dBm")), clientTable(clientRow("1", "AA:BB:CC:DD:EE:01", "", "-60 dBm")), clientTable(rows + clientRow("4", "AA:BB:CC:DD:EE:01", "5G WiFi", "-70 dBm"))} {
+ if _, err := parseClients([]byte(text)); !errors.Is(err, ErrRead) {
+ t.Fatalf("invalid DOM accepted: %v", err)
+ }
+ }
+ clients, err = parseClients([]byte(clientTable("")))
+ if err != nil || len(clients) != 0 {
+ t.Fatal("empty table rejected")
+ }
+}
+
+func TestReaderSessionAndSafeErrors(t *testing.T) {
+ sessions := 0
+ expire := false
+ mux := http.NewServeMux()
+ mux.HandleFunc("/cgi-bin/luci/", func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "POST" {
+ if err := r.ParseForm(); err != nil {
+ t.Error(err)
+ }
+ first := sha256.Sum256([]byte("private-password" + "salt"))
+ want := sha256.Sum256([]byte(hex.EncodeToString(first[:]) + "token"))
+ if r.Form.Get("luci_password") != hex.EncodeToString(want[:]) || r.Form.Get("_csrf") != "csrf" || r.Form.Get("luci_language") != "en" {
+ t.Error("incorrect login")
+ }
+ sessions++
+ http.SetCookie(w, &http.Cookie{Name: "sysauth", Value: "session", Path: "/"})
+ fmt.Fprint(w, "authenticated")
+ return
+ }
+ w.WriteHeader(403)
+ fmt.Fprint(w, ``)
+ })
+ mux.HandleFunc("/cgi-bin/luci/admin/get_token", func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "POST" {
+ t.Error("token method")
+ }
+ fmt.Fprint(w, "token")
+ })
+ mux.HandleFunc("/cgi-bin/luci/admin/network/devices/devlist", func(w http.ResponseWriter, r *http.Request) {
+ if r.Method != "GET" || r.URL.RawQuery != "detail=1" {
+ t.Error("not a read-only request")
+ }
+ if _, err := r.Cookie("sysauth"); err != nil {
+ t.Error("session cookie missing")
+ }
+ if expire {
+ expire = false
+ w.WriteHeader(403)
+ return
+ }
+ fmt.Fprint(w, clientTable(clientRow("1", "AA:BB:CC:DD:EE:01", "5G WiFi", "-55 dBm")))
+ })
+ server := httptest.NewServer(mux)
+ defer server.Close()
+ reader, err := NewReader(server.URL, "private-password")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i := 0; i < 2; i++ {
+ if _, err := reader.Read(context.Background()); err != nil {
+ t.Fatal(err)
+ }
+ }
+ if sessions != 1 {
+ t.Fatal("session not reused")
+ }
+ expire = true
+ if _, err := reader.Read(context.Background()); err != nil {
+ t.Fatal(err)
+ }
+ if sessions != 2 {
+ t.Fatal("expired session not refreshed once")
+ }
+ ctx, cancel := context.WithCancel(context.Background())
+ cancel()
+ if _, err := reader.Read(ctx); !errors.Is(err, context.Canceled) {
+ t.Fatal("cancellation lost")
+ }
+ for _, base := range []string{"https://example.com", "http://user:secret@192.168.10.1", "http://192.168.10.1/path", "http://8.8.8.8"} {
+ if _, err := NewReader(base, "secret"); !errors.Is(err, ErrRead) {
+ t.Fatal("untrusted URL accepted")
+ }
+ }
+}
diff --git a/internal/modules/cudy/interface.go b/internal/modules/cudy/interface.go
new file mode 100644
index 0000000..ecbbf1a
--- /dev/null
+++ b/internal/modules/cudy/interface.go
@@ -0,0 +1,26 @@
+// Package cudy reads Wi-Fi clients from the stock TR3000 web interface.
+package cudy
+
+import (
+ "context"
+ "time"
+)
+
+type Client struct {
+ IP string `json:"IP"`
+ MAC string `json:"MAC"`
+ Band string `json:"band"`
+ Signal *int `json:"signal,omitempty"`
+}
+
+// Snapshot holds only the latest sanitized reading, never names or credentials.
+type Snapshot struct {
+ Enabled bool `json:"enabled"`
+ CollectedAt time.Time `json:"collectedAt"`
+ HasError bool `json:"hasError"`
+ Clients []Client `json:"clients"`
+}
+
+type Reader interface {
+ Read(context.Context) ([]Client, error)
+}
diff --git a/internal/services/game_export_service/export_test.go b/internal/services/game_export_service/export_test.go
index 8d74a41..1f55724 100644
--- a/internal/services/game_export_service/export_test.go
+++ b/internal/services/game_export_service/export_test.go
@@ -377,7 +377,7 @@ func verifyExportedGameReads(t *testing.T, f serviceFixture, worker *game_export
games := game_service.NewGameService(f.games, f.teams, f.scenarios, nil, "", actions_repo.NewActionsRepo(f.pool), applications_repo.NewApplicationsRepo(f.pool))
mapRepo := game_map_repo.NewGameMapRepo(f.pool)
server := app.NewServer(nil, nil, nil, nil, games, nil, nil, nil, nil, nil, nil,
- screen_service.NewScreenService(screen_sessions_repo.NewScreenSessionsRepo(f.pool)), nil, nil, map_service.NewMapService(mapRepo), nil, worker, nil, nil, nil, nil)
+ screen_service.NewScreenService(screen_sessions_repo.NewScreenSessionsRepo(f.pool)), nil, nil, map_service.NewMapService(mapRepo), nil, worker, nil, nil, nil, nil, nil)
ctx := processor_jwt.ContextWithClaims(context.Background(), &processor_jwt.JWTClaims{UserID: f.userID, Roles: []string{"organizer"}})
game, err := server.GetGame(ctx, &proto.GetGameReq{ID: int32(f.gameID)})
check(t, err)
diff --git a/internal/services/wifi_service/service.go b/internal/services/wifi_service/service.go
new file mode 100644
index 0000000..ebfd1f1
--- /dev/null
+++ b/internal/services/wifi_service/service.go
@@ -0,0 +1,43 @@
+// Package wifi_service reads the collector's latest snapshot without LAN access.
+package wifi_service
+
+import (
+ "context"
+ "encoding/json"
+ "io"
+ "os"
+ "time"
+
+ "evening_detective_server/internal/modules/cudy"
+)
+
+type Service struct {
+ path string
+ now func() time.Time
+}
+
+func New(path string) *Service { return &Service{path: path, now: time.Now} }
+
+func (s *Service) Get(ctx context.Context) (cudy.Snapshot, bool) {
+ if s == nil || s.path == "" {
+ return cudy.Snapshot{}, false
+ }
+ snapshot := cudy.Snapshot{Enabled: true, HasError: true}
+ if ctx.Err() != nil {
+ return snapshot, true
+ }
+ file, err := os.Open(s.path)
+ if err != nil {
+ return snapshot, true
+ }
+ defer file.Close()
+ data, err := io.ReadAll(io.LimitReader(file, 2<<20+1))
+ if err != nil || len(data) > 2<<20 || json.Unmarshal(data, &snapshot) != nil {
+ return cudy.Snapshot{Enabled: true, HasError: true}, true
+ }
+ if !snapshot.Enabled {
+ return snapshot, false
+ }
+ stale := snapshot.HasError || snapshot.CollectedAt.IsZero() || s.now().Sub(snapshot.CollectedAt) >= 30*time.Second || snapshot.CollectedAt.After(s.now())
+ return snapshot, stale
+}
diff --git a/internal/services/wifi_service/service_test.go b/internal/services/wifi_service/service_test.go
new file mode 100644
index 0000000..4a6f418
--- /dev/null
+++ b/internal/services/wifi_service/service_test.go
@@ -0,0 +1,58 @@
+package wifi_service
+
+import (
+ "context"
+ "encoding/json"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "evening_detective_server/internal/modules/cudy"
+)
+
+func TestSnapshotFreshnessAndFailures(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "state.json")
+ now := time.Unix(1234, 0)
+ service := New(path)
+ service.now = func() time.Time { return now }
+ snapshot := cudy.Snapshot{Enabled: true, CollectedAt: now, Clients: []cudy.Client{{MAC: "AA:BB:CC:DD:EE:01"}}}
+ write := func() {
+ t.Helper()
+ data, _ := json.Marshal(snapshot)
+ if err := os.WriteFile(path, data, 0600); err != nil {
+ t.Fatal(err)
+ }
+ }
+ write()
+ result, stale := service.Get(context.Background())
+ if stale || len(result.Clients) != 1 {
+ t.Fatal("fresh snapshot rejected")
+ }
+ now = now.Add(30 * time.Second)
+ if _, stale = service.Get(context.Background()); !stale {
+ t.Fatal("stale snapshot accepted")
+ }
+ snapshot.HasError = true
+ write()
+ result, stale = service.Get(context.Background())
+ if !stale || !result.HasError || len(result.Clients) != 1 {
+ t.Fatal("failed refresh lost snapshot")
+ }
+ if err := os.WriteFile(path, []byte("bad JSON"), 0600); err != nil {
+ t.Fatal(err)
+ }
+ result, stale = service.Get(context.Background())
+ if !stale || !result.HasError {
+ t.Fatal("corrupt snapshot accepted")
+ }
+ snapshot = cudy.Snapshot{}
+ write()
+ result, stale = service.Get(context.Background())
+ if result.Enabled || stale {
+ t.Fatal("disabled source marked stale")
+ }
+ if result, stale = New("").Get(context.Background()); result.Enabled || stale {
+ t.Fatal("unconfigured source enabled")
+ }
+}
diff --git a/proto/main.pb.go b/proto/main.pb.go
index 99404e8..47ec6f8 100644
--- a/proto/main.pb.go
+++ b/proto/main.pb.go
@@ -12406,6 +12406,7 @@ type GetDevicesRsp struct {
state protoimpl.MessageState `protogen:"open.v1"`
Devices []*VenueDevice `protobuf:"bytes,1,rep,name=devices,proto3" json:"devices,omitempty"`
ServerTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=serverTime,proto3" json:"serverTime,omitempty"`
+ Wifi *VenueWiFi `protobuf:"bytes,3,opt,name=wifi,proto3" json:"wifi,omitempty"` // Entire venue, independent of the game filter.
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -12454,6 +12455,13 @@ func (x *GetDevicesRsp) GetServerTime() *timestamppb.Timestamp {
return nil
}
+func (x *GetDevicesRsp) GetWifi() *VenueWiFi {
+ if x != nil {
+ return x.Wifi
+ }
+ return nil
+}
+
type VenueDevice struct {
state protoimpl.MessageState `protogen:"open.v1"`
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
@@ -12646,6 +12654,150 @@ func (x *DeviceConnection) GetKind() string {
return ""
}
+type VenueWiFi struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ CollectedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=collectedAt,proto3" json:"collectedAt,omitempty"`
+ Stale bool `protobuf:"varint,3,opt,name=stale,proto3" json:"stale,omitempty"`
+ HasError bool `protobuf:"varint,4,opt,name=hasError,proto3" json:"hasError,omitempty"`
+ Clients []*WiFiClient `protobuf:"bytes,5,rep,name=clients,proto3" json:"clients,omitempty"`
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *VenueWiFi) Reset() {
+ *x = VenueWiFi{}
+ mi := &file_main_proto_msgTypes[238]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *VenueWiFi) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*VenueWiFi) ProtoMessage() {}
+
+func (x *VenueWiFi) ProtoReflect() protoreflect.Message {
+ mi := &file_main_proto_msgTypes[238]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use VenueWiFi.ProtoReflect.Descriptor instead.
+func (*VenueWiFi) Descriptor() ([]byte, []int) {
+ return file_main_proto_rawDescGZIP(), []int{238}
+}
+
+func (x *VenueWiFi) GetEnabled() bool {
+ if x != nil {
+ return x.Enabled
+ }
+ return false
+}
+
+func (x *VenueWiFi) GetCollectedAt() *timestamppb.Timestamp {
+ if x != nil {
+ return x.CollectedAt
+ }
+ return nil
+}
+
+func (x *VenueWiFi) GetStale() bool {
+ if x != nil {
+ return x.Stale
+ }
+ return false
+}
+
+func (x *VenueWiFi) GetHasError() bool {
+ if x != nil {
+ return x.HasError
+ }
+ return false
+}
+
+func (x *VenueWiFi) GetClients() []*WiFiClient {
+ if x != nil {
+ return x.Clients
+ }
+ return nil
+}
+
+type WiFiClient struct {
+ state protoimpl.MessageState `protogen:"open.v1"`
+ IP string `protobuf:"bytes,1,opt,name=IP,proto3" json:"IP,omitempty"`
+ MAC string `protobuf:"bytes,2,opt,name=MAC,proto3" json:"MAC,omitempty"`
+ Band string `protobuf:"bytes,3,opt,name=band,proto3" json:"band,omitempty"`
+ Signal *int32 `protobuf:"varint,4,opt,name=signal,proto3,oneof" json:"signal,omitempty"` // dBm; absent when the router does not report it.
+ unknownFields protoimpl.UnknownFields
+ sizeCache protoimpl.SizeCache
+}
+
+func (x *WiFiClient) Reset() {
+ *x = WiFiClient{}
+ mi := &file_main_proto_msgTypes[239]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+}
+
+func (x *WiFiClient) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*WiFiClient) ProtoMessage() {}
+
+func (x *WiFiClient) ProtoReflect() protoreflect.Message {
+ mi := &file_main_proto_msgTypes[239]
+ if x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use WiFiClient.ProtoReflect.Descriptor instead.
+func (*WiFiClient) Descriptor() ([]byte, []int) {
+ return file_main_proto_rawDescGZIP(), []int{239}
+}
+
+func (x *WiFiClient) GetIP() string {
+ if x != nil {
+ return x.IP
+ }
+ return ""
+}
+
+func (x *WiFiClient) GetMAC() string {
+ if x != nil {
+ return x.MAC
+ }
+ return ""
+}
+
+func (x *WiFiClient) GetBand() string {
+ if x != nil {
+ return x.Band
+ }
+ return ""
+}
+
+func (x *WiFiClient) GetSignal() int32 {
+ if x != nil && x.Signal != nil {
+ return *x.Signal
+ }
+ return 0
+}
+
var File_main_proto protoreflect.FileDescriptor
const file_main_proto_rawDesc = "" +
@@ -13433,12 +13585,13 @@ const file_main_proto_rawDesc = "" +
"\b_enabled\"7\n" +
"\rGetDevicesReq\x12\x1b\n" +
"\x06gameID\x18\x01 \x01(\x05H\x00R\x06gameID\x88\x01\x01B\t\n" +
- "\a_gameID\"\x92\x01\n" +
+ "\a_gameID\"\xd1\x01\n" +
"\rGetDevicesRsp\x12E\n" +
"\adevices\x18\x01 \x03(\v2+.crabs.evening_detective_server.VenueDeviceR\adevices\x12:\n" +
"\n" +
"serverTime\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\n" +
- "serverTime\"\x89\x02\n" +
+ "serverTime\x12=\n" +
+ "\x04wifi\x18\x03 \x01(\v2).crabs.evening_detective_server.VenueWiFiR\x04wifi\"\x89\x02\n" +
"\vVenueDevice\x12\x0e\n" +
"\x02ID\x18\x01 \x01(\tR\x02ID\x12<\n" +
"\vfirstSeenAt\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\vfirstSeenAt\x12:\n" +
@@ -13463,7 +13616,20 @@ const file_main_proto_rawDesc = "" +
" \x01(\tR\x04kindB\t\n" +
"\a_gameIDB\t\n" +
"\a_teamIDB\v\n" +
- "\t_screenID*\xf6\x01\n" +
+ "\t_screenID\"\xdb\x01\n" +
+ "\tVenueWiFi\x12\x18\n" +
+ "\aenabled\x18\x01 \x01(\bR\aenabled\x12<\n" +
+ "\vcollectedAt\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\vcollectedAt\x12\x14\n" +
+ "\x05stale\x18\x03 \x01(\bR\x05stale\x12\x1a\n" +
+ "\bhasError\x18\x04 \x01(\bR\bhasError\x12D\n" +
+ "\aclients\x18\x05 \x03(\v2*.crabs.evening_detective_server.WiFiClientR\aclients\"j\n" +
+ "\n" +
+ "WiFiClient\x12\x0e\n" +
+ "\x02IP\x18\x01 \x01(\tR\x02IP\x12\x10\n" +
+ "\x03MAC\x18\x02 \x01(\tR\x03MAC\x12\x12\n" +
+ "\x04band\x18\x03 \x01(\tR\x04band\x12\x1b\n" +
+ "\x06signal\x18\x04 \x01(\x05H\x00R\x06signal\x88\x01\x01B\t\n" +
+ "\a_signal*\xf6\x01\n" +
"\n" +
"ScreenMode\x12\x1b\n" +
"\x17SCREEN_MODE_UNSPECIFIED\x10\x00\x12\x15\n" +
@@ -13799,7 +13965,7 @@ func file_main_proto_rawDescGZIP() []byte {
}
var file_main_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
-var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 238)
+var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 240)
var file_main_proto_goTypes = []any{
(ScreenMode)(0), // 0: crabs.evening_detective_server.ScreenMode
(ScreenTimerState)(0), // 1: crabs.evening_detective_server.ScreenTimerState
@@ -14043,12 +14209,14 @@ var file_main_proto_goTypes = []any{
(*GetDevicesRsp)(nil), // 239: crabs.evening_detective_server.GetDevicesRsp
(*VenueDevice)(nil), // 240: crabs.evening_detective_server.VenueDevice
(*DeviceConnection)(nil), // 241: crabs.evening_detective_server.DeviceConnection
- (*timestamppb.Timestamp)(nil), // 242: google.protobuf.Timestamp
- (*httpbody.HttpBody)(nil), // 243: google.api.HttpBody
+ (*VenueWiFi)(nil), // 242: crabs.evening_detective_server.VenueWiFi
+ (*WiFiClient)(nil), // 243: crabs.evening_detective_server.WiFiClient
+ (*timestamppb.Timestamp)(nil), // 244: google.protobuf.Timestamp
+ (*httpbody.HttpBody)(nil), // 245: google.api.HttpBody
}
var file_main_proto_depIdxs = []int32{
26, // 0: crabs.evening_detective_server.GetUsersRsp.users:type_name -> crabs.evening_detective_server.User
- 242, // 1: crabs.evening_detective_server.User.created_at:type_name -> google.protobuf.Timestamp
+ 244, // 1: crabs.evening_detective_server.User.created_at:type_name -> google.protobuf.Timestamp
26, // 2: crabs.evening_detective_server.GetUserByIDRsp.user:type_name -> crabs.evening_detective_server.User
26, // 3: crabs.evening_detective_server.GetMeRsp.user:type_name -> crabs.evening_detective_server.User
42, // 4: crabs.evening_detective_server.Playlist.tracks:type_name -> crabs.evening_detective_server.PlaylistTrack
@@ -14061,9 +14229,9 @@ var file_main_proto_depIdxs = []int32{
66, // 11: crabs.evening_detective_server.GetScenarioRsp.scenario:type_name -> crabs.evening_detective_server.Scenario
67, // 12: crabs.evening_detective_server.Scenario.story:type_name -> crabs.evening_detective_server.Story
26, // 13: crabs.evening_detective_server.Scenario.author:type_name -> crabs.evening_detective_server.User
- 242, // 14: crabs.evening_detective_server.Scenario.updated_at:type_name -> google.protobuf.Timestamp
- 242, // 15: crabs.evening_detective_server.Scenario.created_at:type_name -> google.protobuf.Timestamp
- 242, // 16: crabs.evening_detective_server.Scenario.published_at:type_name -> google.protobuf.Timestamp
+ 244, // 14: crabs.evening_detective_server.Scenario.updated_at:type_name -> google.protobuf.Timestamp
+ 244, // 15: crabs.evening_detective_server.Scenario.created_at:type_name -> google.protobuf.Timestamp
+ 244, // 16: crabs.evening_detective_server.Scenario.published_at:type_name -> google.protobuf.Timestamp
70, // 17: crabs.evening_detective_server.Story.places:type_name -> crabs.evening_detective_server.Place
69, // 18: crabs.evening_detective_server.Story.introduction:type_name -> crabs.evening_detective_server.Introduction
74, // 19: crabs.evening_detective_server.Story.questions:type_name -> crabs.evening_detective_server.Question
@@ -14080,13 +14248,13 @@ var file_main_proto_depIdxs = []int32{
69, // 30: crabs.evening_detective_server.UpdateScenarioIntroReq.introduction:type_name -> crabs.evening_detective_server.Introduction
74, // 31: crabs.evening_detective_server.AddScenarioQuestionReq.question:type_name -> crabs.evening_detective_server.Question
74, // 32: crabs.evening_detective_server.UpdateScenarioQuestionReq.question:type_name -> crabs.evening_detective_server.Question
- 242, // 33: crabs.evening_detective_server.AddGameReq.start_at:type_name -> google.protobuf.Timestamp
+ 244, // 33: crabs.evening_detective_server.AddGameReq.start_at:type_name -> google.protobuf.Timestamp
108, // 34: crabs.evening_detective_server.GetGamesRsp.games:type_name -> crabs.evening_detective_server.Game
- 242, // 35: crabs.evening_detective_server.Game.start_at:type_name -> google.protobuf.Timestamp
+ 244, // 35: crabs.evening_detective_server.Game.start_at:type_name -> google.protobuf.Timestamp
66, // 36: crabs.evening_detective_server.Game.scenario:type_name -> crabs.evening_detective_server.Scenario
158, // 37: crabs.evening_detective_server.Game.teams:type_name -> crabs.evening_detective_server.Team
- 242, // 38: crabs.evening_detective_server.Game.started_at:type_name -> google.protobuf.Timestamp
- 242, // 39: crabs.evening_detective_server.Game.ended_at:type_name -> google.protobuf.Timestamp
+ 244, // 38: crabs.evening_detective_server.Game.started_at:type_name -> google.protobuf.Timestamp
+ 244, // 39: crabs.evening_detective_server.Game.ended_at:type_name -> google.protobuf.Timestamp
109, // 40: crabs.evening_detective_server.Game.export:type_name -> crabs.evening_detective_server.GameExport
109, // 41: crabs.evening_detective_server.GameExportRsp.export:type_name -> crabs.evening_detective_server.GameExport
0, // 42: crabs.evening_detective_server.ScreenState.mode:type_name -> crabs.evening_detective_server.ScreenMode
@@ -14114,7 +14282,7 @@ var file_main_proto_depIdxs = []int32{
146, // 64: crabs.evening_detective_server.SetScreenPlanStepRsp.plan:type_name -> crabs.evening_detective_server.ScreenPlan
164, // 65: crabs.evening_detective_server.GetScreenResultsRsp.questions:type_name -> crabs.evening_detective_server.ResultsQuestion
165, // 66: crabs.evening_detective_server.GetScreenResultsRsp.teams:type_name -> crabs.evening_detective_server.TeamResult
- 242, // 67: crabs.evening_detective_server.ParticipationRsp.start_at:type_name -> google.protobuf.Timestamp
+ 244, // 67: crabs.evening_detective_server.ParticipationRsp.start_at:type_name -> google.protobuf.Timestamp
71, // 68: crabs.evening_detective_server.Team.applications:type_name -> crabs.evening_detective_server.Application
108, // 69: crabs.evening_detective_server.GetGameRsp.game:type_name -> crabs.evening_detective_server.Game
74, // 70: crabs.evening_detective_server.GetGameAnswersRsp.questions:type_name -> crabs.evening_detective_server.Question
@@ -14123,11 +14291,11 @@ var file_main_proto_depIdxs = []int32{
76, // 73: crabs.evening_detective_server.TeamResult.answers:type_name -> crabs.evening_detective_server.AnswerScore
164, // 74: crabs.evening_detective_server.GetGameResultsRsp.questions:type_name -> crabs.evening_detective_server.ResultsQuestion
165, // 75: crabs.evening_detective_server.GetGameResultsRsp.teams:type_name -> crabs.evening_detective_server.TeamResult
- 242, // 76: crabs.evening_detective_server.GameReview.created_at:type_name -> google.protobuf.Timestamp
+ 244, // 76: crabs.evening_detective_server.GameReview.created_at:type_name -> google.protobuf.Timestamp
167, // 77: crabs.evening_detective_server.CreateGameReviewRsp.review:type_name -> crabs.evening_detective_server.GameReview
167, // 78: crabs.evening_detective_server.GetGameReviewsRsp.reviews:type_name -> crabs.evening_detective_server.GameReview
167, // 79: crabs.evening_detective_server.ModerateGameReviewRsp.review:type_name -> crabs.evening_detective_server.GameReview
- 242, // 80: crabs.evening_detective_server.UpdateGameReq.start_at:type_name -> google.protobuf.Timestamp
+ 244, // 80: crabs.evening_detective_server.UpdateGameReq.start_at:type_name -> google.protobuf.Timestamp
67, // 81: crabs.evening_detective_server.GetTeamStoryRsp.story:type_name -> crabs.evening_detective_server.Story
108, // 82: crabs.evening_detective_server.GetTeamStoryRsp.game:type_name -> crabs.evening_detective_server.Game
200, // 83: crabs.evening_detective_server.GetTeamStoryRsp.actions:type_name -> crabs.evening_detective_server.TeamAction
@@ -14136,249 +14304,252 @@ var file_main_proto_depIdxs = []int32{
215, // 86: crabs.evening_detective_server.IssueGameTicketsRsp.tickets:type_name -> crabs.evening_detective_server.Ticket
220, // 87: crabs.evening_detective_server.GetTicketRsp.ticket:type_name -> crabs.evening_detective_server.TicketPage
220, // 88: crabs.evening_detective_server.AcceptTicketRsp.ticket:type_name -> crabs.evening_detective_server.TicketPage
- 242, // 89: crabs.evening_detective_server.TicketPage.start_at:type_name -> google.protobuf.Timestamp
- 242, // 90: crabs.evening_detective_server.TicketPage.used_at:type_name -> google.protobuf.Timestamp
- 242, // 91: crabs.evening_detective_server.DeveloperTask.createdAt:type_name -> google.protobuf.Timestamp
- 242, // 92: crabs.evening_detective_server.DeveloperTask.updatedAt:type_name -> google.protobuf.Timestamp
+ 244, // 89: crabs.evening_detective_server.TicketPage.start_at:type_name -> google.protobuf.Timestamp
+ 244, // 90: crabs.evening_detective_server.TicketPage.used_at:type_name -> google.protobuf.Timestamp
+ 244, // 91: crabs.evening_detective_server.DeveloperTask.createdAt:type_name -> google.protobuf.Timestamp
+ 244, // 92: crabs.evening_detective_server.DeveloperTask.updatedAt:type_name -> google.protobuf.Timestamp
221, // 93: crabs.evening_detective_server.GetTasksRsp.tasks:type_name -> crabs.evening_detective_server.DeveloperTask
222, // 94: crabs.evening_detective_server.GetTaskAssigneesRsp.assignees:type_name -> crabs.evening_detective_server.TaskAssignee
221, // 95: crabs.evening_detective_server.TaskRsp.task:type_name -> crabs.evening_detective_server.DeveloperTask
- 243, // 96: crabs.evening_detective_server.ApplyGameResultsPackageReq.package:type_name -> google.api.HttpBody
- 242, // 97: crabs.evening_detective_server.DeviceHeartbeatRsp.serverTime:type_name -> google.protobuf.Timestamp
+ 245, // 96: crabs.evening_detective_server.ApplyGameResultsPackageReq.package:type_name -> google.api.HttpBody
+ 244, // 97: crabs.evening_detective_server.DeviceHeartbeatRsp.serverTime:type_name -> google.protobuf.Timestamp
240, // 98: crabs.evening_detective_server.GetDevicesRsp.devices:type_name -> crabs.evening_detective_server.VenueDevice
- 242, // 99: crabs.evening_detective_server.GetDevicesRsp.serverTime:type_name -> google.protobuf.Timestamp
- 242, // 100: crabs.evening_detective_server.VenueDevice.firstSeenAt:type_name -> google.protobuf.Timestamp
- 242, // 101: crabs.evening_detective_server.VenueDevice.lastSeenAt:type_name -> google.protobuf.Timestamp
- 241, // 102: crabs.evening_detective_server.VenueDevice.connections:type_name -> crabs.evening_detective_server.DeviceConnection
- 242, // 103: crabs.evening_detective_server.DeviceConnection.firstSeenAt:type_name -> google.protobuf.Timestamp
- 242, // 104: crabs.evening_detective_server.DeviceConnection.lastSeenAt:type_name -> google.protobuf.Timestamp
- 236, // 105: crabs.evening_detective_server.EveningDetectiveServer.DeviceHeartbeat:input_type -> crabs.evening_detective_server.DeviceHeartbeatReq
- 238, // 106: crabs.evening_detective_server.EveningDetectiveServer.GetDevices:input_type -> crabs.evening_detective_server.GetDevicesReq
- 223, // 107: crabs.evening_detective_server.EveningDetectiveServer.GetTasks:input_type -> crabs.evening_detective_server.GetTasksReq
- 225, // 108: crabs.evening_detective_server.EveningDetectiveServer.GetTaskAssignees:input_type -> crabs.evening_detective_server.GetTaskAssigneesReq
- 227, // 109: crabs.evening_detective_server.EveningDetectiveServer.CreateTask:input_type -> crabs.evening_detective_server.CreateTaskReq
- 228, // 110: crabs.evening_detective_server.EveningDetectiveServer.UpdateTask:input_type -> crabs.evening_detective_server.UpdateTaskReq
- 229, // 111: crabs.evening_detective_server.EveningDetectiveServer.SetTaskStatus:input_type -> crabs.evening_detective_server.SetTaskStatusReq
- 230, // 112: crabs.evening_detective_server.EveningDetectiveServer.DeleteTask:input_type -> crabs.evening_detective_server.DeleteTaskReq
- 155, // 113: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:input_type -> crabs.evening_detective_server.GetParticipationReq
- 156, // 114: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:input_type -> crabs.evening_detective_server.AnswerParticipationReq
- 4, // 115: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq
- 6, // 116: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq
- 8, // 117: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq
- 10, // 118: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq
- 12, // 119: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq
- 14, // 120: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq
- 16, // 121: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:input_type -> crabs.evening_detective_server.DeleteAccountReq
- 18, // 122: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:input_type -> crabs.evening_detective_server.GetTermsReq
- 20, // 123: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:input_type -> crabs.evening_detective_server.GetPrivacyReq
- 22, // 124: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:input_type -> crabs.evening_detective_server.GetConsentReq
- 24, // 125: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:input_type -> crabs.evening_detective_server.GetUsersReq
- 27, // 126: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:input_type -> crabs.evening_detective_server.GetUserByIDReq
- 29, // 127: crabs.evening_detective_server.EveningDetectiveServer.GetMe:input_type -> crabs.evening_detective_server.GetMeReq
- 31, // 128: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:input_type -> crabs.evening_detective_server.ChangeUserPasswordReq
- 33, // 129: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:input_type -> crabs.evening_detective_server.AddUserRoleReq
- 35, // 130: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:input_type -> crabs.evening_detective_server.DeleteUserRoleReq
- 37, // 131: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:input_type -> crabs.evening_detective_server.GetPermissionsReq
- 39, // 132: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:input_type -> crabs.evening_detective_server.UploadFileReq
- 41, // 133: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:input_type -> crabs.evening_detective_server.DownloadFileReq
- 44, // 134: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:input_type -> crabs.evening_detective_server.GetPlaylistsReq
- 46, // 135: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:input_type -> crabs.evening_detective_server.CreatePlaylistReq
- 48, // 136: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:input_type -> crabs.evening_detective_server.UpdatePlaylistReq
- 50, // 137: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:input_type -> crabs.evening_detective_server.DeletePlaylistReq
- 52, // 138: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:input_type -> crabs.evening_detective_server.UploadPlaylistTrackReq
- 54, // 139: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:input_type -> crabs.evening_detective_server.DeletePlaylistTrackReq
- 56, // 140: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:input_type -> crabs.evening_detective_server.SetScenarioPlaylistReq
- 58, // 141: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:input_type -> crabs.evening_detective_server.AddScenarioReq
- 60, // 142: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:input_type -> crabs.evening_detective_server.GetMyScenariosReq
- 62, // 143: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:input_type -> crabs.evening_detective_server.GetScenariosCatalogReq
- 64, // 144: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:input_type -> crabs.evening_detective_server.GetScenarioReq
- 64, // 145: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:input_type -> crabs.evening_detective_server.GetScenarioReq
- 78, // 146: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:input_type -> crabs.evening_detective_server.UpdateScenarioReq
- 80, // 147: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:input_type -> crabs.evening_detective_server.PublicScenarioReq
- 82, // 148: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:input_type -> crabs.evening_detective_server.DraftScenarioReq
- 84, // 149: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:input_type -> crabs.evening_detective_server.DeleteScenarioReq
- 86, // 150: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:input_type -> crabs.evening_detective_server.AddScenarioPlaceReq
- 88, // 151: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:input_type -> crabs.evening_detective_server.UpdateScenarioPlaceReq
- 90, // 152: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:input_type -> crabs.evening_detective_server.DeleteScenarioPlaceReq
- 96, // 153: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:input_type -> crabs.evening_detective_server.AddScenarioQuestionReq
- 98, // 154: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:input_type -> crabs.evening_detective_server.UpdateScenarioQuestionReq
- 100, // 155: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:input_type -> crabs.evening_detective_server.DeleteScenarioQuestionReq
- 211, // 156: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:input_type -> crabs.evening_detective_server.UpdateScenarioBackgroundReq
- 94, // 157: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:input_type -> crabs.evening_detective_server.UpdateScenarioIntroReq
- 92, // 158: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:input_type -> crabs.evening_detective_server.UpdateScenarioConclusionReq
- 102, // 159: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:input_type -> crabs.evening_detective_server.DownloadScenarioArchiveReq
- 243, // 160: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:input_type -> google.api.HttpBody
- 104, // 161: crabs.evening_detective_server.EveningDetectiveServer.AddGame:input_type -> crabs.evening_detective_server.AddGameReq
- 106, // 162: crabs.evening_detective_server.EveningDetectiveServer.GetGames:input_type -> crabs.evening_detective_server.GetGamesReq
- 159, // 163: crabs.evening_detective_server.EveningDetectiveServer.GetGame:input_type -> crabs.evening_detective_server.GetGameReq
- 243, // 164: crabs.evening_detective_server.EveningDetectiveServer.ImportGame:input_type -> google.api.HttpBody
- 233, // 165: crabs.evening_detective_server.EveningDetectiveServer.DownloadGameResultsPackage:input_type -> crabs.evening_detective_server.GameResultsPackageReq
- 234, // 166: crabs.evening_detective_server.EveningDetectiveServer.ApplyGameResultsPackage:input_type -> crabs.evening_detective_server.ApplyGameResultsPackageReq
- 111, // 167: crabs.evening_detective_server.EveningDetectiveServer.StartGameExport:input_type -> crabs.evening_detective_server.StartGameExportReq
- 112, // 168: crabs.evening_detective_server.EveningDetectiveServer.GetGameExport:input_type -> crabs.evening_detective_server.GetGameExportReq
- 213, // 169: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:input_type -> crabs.evening_detective_server.IssueGameTicketsReq
- 216, // 170: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:input_type -> crabs.evening_detective_server.GetTicketReq
- 218, // 171: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:input_type -> crabs.evening_detective_server.AcceptTicketReq
- 115, // 172: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:input_type -> crabs.evening_detective_server.CreateScreenSessionReq
- 117, // 173: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:input_type -> crabs.evening_detective_server.GetScreenStateReq
- 119, // 174: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:input_type -> crabs.evening_detective_server.GetGameScreensReq
- 122, // 175: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:input_type -> crabs.evening_detective_server.GetGameMusicReq
- 124, // 176: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:input_type -> crabs.evening_detective_server.SetGameMusicReq
- 126, // 177: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:input_type -> crabs.evening_detective_server.AdvanceScreenMusicReq
- 128, // 178: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:input_type -> crabs.evening_detective_server.BindScreenReq
- 130, // 179: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:input_type -> crabs.evening_detective_server.UnbindScreenReq
- 132, // 180: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:input_type -> crabs.evening_detective_server.SetScreenSoundReq
- 135, // 181: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:input_type -> crabs.evening_detective_server.GetGameMapReq
- 137, // 182: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:input_type -> crabs.evening_detective_server.UpdateGameMapItemReq
- 139, // 183: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:input_type -> crabs.evening_detective_server.SetScreenModeReq
- 141, // 184: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:input_type -> crabs.evening_detective_server.SetScreenTimerReq
- 143, // 185: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:input_type -> crabs.evening_detective_server.SendScreenCommandReq
- 147, // 186: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:input_type -> crabs.evening_detective_server.GetScreenPlanReq
- 149, // 187: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:input_type -> crabs.evening_detective_server.SaveScreenPlanReq
- 151, // 188: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:input_type -> crabs.evening_detective_server.SetScreenPlanStepReq
- 153, // 189: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:input_type -> crabs.evening_detective_server.GetScreenResultsReq
- 159, // 190: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:input_type -> crabs.evening_detective_server.GetGameReq
- 161, // 191: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:input_type -> crabs.evening_detective_server.GetGameAnswersReq
- 163, // 192: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:input_type -> crabs.evening_detective_server.GetGameResultsReq
- 168, // 193: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:input_type -> crabs.evening_detective_server.CreateGameReviewReq
- 170, // 194: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:input_type -> crabs.evening_detective_server.GetGameReviewsReq
- 171, // 195: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:input_type -> crabs.evening_detective_server.GetScenarioReviewsReq
- 170, // 196: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:input_type -> crabs.evening_detective_server.GetGameReviewsReq
- 172, // 197: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:input_type -> crabs.evening_detective_server.GetReviewsForModerationReq
- 174, // 198: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:input_type -> crabs.evening_detective_server.ModerateGameReviewReq
- 176, // 199: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:input_type -> crabs.evening_detective_server.UpdateGameReq
- 178, // 200: crabs.evening_detective_server.EveningDetectiveServer.StartGame:input_type -> crabs.evening_detective_server.StartGameReq
- 180, // 201: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:input_type -> crabs.evening_detective_server.PauseGameReq
- 182, // 202: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:input_type -> crabs.evening_detective_server.PlayGameReq
- 184, // 203: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:input_type -> crabs.evening_detective_server.FinishGameReq
- 186, // 204: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:input_type -> crabs.evening_detective_server.ResetGameReq
- 188, // 205: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:input_type -> crabs.evening_detective_server.DeleteGameReq
- 190, // 206: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:input_type -> crabs.evening_detective_server.AddTeamReq
- 192, // 207: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:input_type -> crabs.evening_detective_server.UpdateTeamReq
- 194, // 208: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:input_type -> crabs.evening_detective_server.DeleteTeamReq
- 196, // 209: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:input_type -> crabs.evening_detective_server.GiveTeamApplicationsReq
- 198, // 210: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:input_type -> crabs.evening_detective_server.GetTeamStoryReq
- 201, // 211: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:input_type -> crabs.evening_detective_server.AddTeamActionReq
- 203, // 212: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:input_type -> crabs.evening_detective_server.DeleteLastTeamActionReq
- 205, // 213: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:input_type -> crabs.evening_detective_server.GetTeamAnswersReq
- 207, // 214: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:input_type -> crabs.evening_detective_server.SubmitTeamAnswersReq
- 209, // 215: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:input_type -> crabs.evening_detective_server.SetTeamAnswerScoreReq
- 237, // 216: crabs.evening_detective_server.EveningDetectiveServer.DeviceHeartbeat:output_type -> crabs.evening_detective_server.DeviceHeartbeatRsp
- 239, // 217: crabs.evening_detective_server.EveningDetectiveServer.GetDevices:output_type -> crabs.evening_detective_server.GetDevicesRsp
- 224, // 218: crabs.evening_detective_server.EveningDetectiveServer.GetTasks:output_type -> crabs.evening_detective_server.GetTasksRsp
- 226, // 219: crabs.evening_detective_server.EveningDetectiveServer.GetTaskAssignees:output_type -> crabs.evening_detective_server.GetTaskAssigneesRsp
- 231, // 220: crabs.evening_detective_server.EveningDetectiveServer.CreateTask:output_type -> crabs.evening_detective_server.TaskRsp
- 231, // 221: crabs.evening_detective_server.EveningDetectiveServer.UpdateTask:output_type -> crabs.evening_detective_server.TaskRsp
- 231, // 222: crabs.evening_detective_server.EveningDetectiveServer.SetTaskStatus:output_type -> crabs.evening_detective_server.TaskRsp
- 232, // 223: crabs.evening_detective_server.EveningDetectiveServer.DeleteTask:output_type -> crabs.evening_detective_server.DeleteTaskRsp
- 157, // 224: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp
- 157, // 225: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp
- 5, // 226: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp
- 7, // 227: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp
- 9, // 228: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp
- 11, // 229: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp
- 13, // 230: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp
- 15, // 231: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp
- 17, // 232: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:output_type -> crabs.evening_detective_server.DeleteAccountRsp
- 19, // 233: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:output_type -> crabs.evening_detective_server.GetTermsRsp
- 21, // 234: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:output_type -> crabs.evening_detective_server.GetPrivacyRsp
- 23, // 235: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:output_type -> crabs.evening_detective_server.GetConsentRsp
- 25, // 236: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:output_type -> crabs.evening_detective_server.GetUsersRsp
- 28, // 237: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:output_type -> crabs.evening_detective_server.GetUserByIDRsp
- 30, // 238: crabs.evening_detective_server.EveningDetectiveServer.GetMe:output_type -> crabs.evening_detective_server.GetMeRsp
- 32, // 239: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:output_type -> crabs.evening_detective_server.ChangeUserPasswordRsp
- 34, // 240: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:output_type -> crabs.evening_detective_server.AddUserRoleRsp
- 36, // 241: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:output_type -> crabs.evening_detective_server.DeleteUserRoleRsp
- 38, // 242: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:output_type -> crabs.evening_detective_server.GetPermissionsRsp
- 40, // 243: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:output_type -> crabs.evening_detective_server.UploadFileRsp
- 243, // 244: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:output_type -> google.api.HttpBody
- 45, // 245: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:output_type -> crabs.evening_detective_server.GetPlaylistsRsp
- 47, // 246: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:output_type -> crabs.evening_detective_server.CreatePlaylistRsp
- 49, // 247: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:output_type -> crabs.evening_detective_server.UpdatePlaylistRsp
- 51, // 248: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:output_type -> crabs.evening_detective_server.DeletePlaylistRsp
- 53, // 249: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:output_type -> crabs.evening_detective_server.UploadPlaylistTrackRsp
- 55, // 250: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:output_type -> crabs.evening_detective_server.DeletePlaylistTrackRsp
- 57, // 251: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:output_type -> crabs.evening_detective_server.SetScenarioPlaylistRsp
- 59, // 252: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:output_type -> crabs.evening_detective_server.AddScenarioRsp
- 61, // 253: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:output_type -> crabs.evening_detective_server.GetMyScenariosRsp
- 63, // 254: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:output_type -> crabs.evening_detective_server.GetScenariosCatalogRsp
- 65, // 255: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp
- 65, // 256: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp
- 79, // 257: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:output_type -> crabs.evening_detective_server.UpdateScenarioRsp
- 81, // 258: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:output_type -> crabs.evening_detective_server.PublicScenarioRsp
- 83, // 259: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:output_type -> crabs.evening_detective_server.DraftScenarioRsp
- 85, // 260: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:output_type -> crabs.evening_detective_server.DeleteScenarioRsp
- 87, // 261: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:output_type -> crabs.evening_detective_server.AddScenarioPlaceRsp
- 89, // 262: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:output_type -> crabs.evening_detective_server.UpdateScenarioPlaceRsp
- 91, // 263: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:output_type -> crabs.evening_detective_server.DeleteScenarioPlaceRsp
- 97, // 264: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:output_type -> crabs.evening_detective_server.AddScenarioQuestionRsp
- 99, // 265: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:output_type -> crabs.evening_detective_server.UpdateScenarioQuestionRsp
- 101, // 266: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:output_type -> crabs.evening_detective_server.DeleteScenarioQuestionRsp
- 212, // 267: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:output_type -> crabs.evening_detective_server.UpdateScenarioBackgroundRsp
- 95, // 268: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:output_type -> crabs.evening_detective_server.UpdateScenarioIntroRsp
- 93, // 269: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:output_type -> crabs.evening_detective_server.UpdateScenarioConclusionRsp
- 243, // 270: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:output_type -> google.api.HttpBody
- 103, // 271: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:output_type -> crabs.evening_detective_server.UploadScenarioArchiveRsp
- 105, // 272: crabs.evening_detective_server.EveningDetectiveServer.AddGame:output_type -> crabs.evening_detective_server.AddGameRsp
- 107, // 273: crabs.evening_detective_server.EveningDetectiveServer.GetGames:output_type -> crabs.evening_detective_server.GetGamesRsp
- 160, // 274: crabs.evening_detective_server.EveningDetectiveServer.GetGame:output_type -> crabs.evening_detective_server.GetGameRsp
- 110, // 275: crabs.evening_detective_server.EveningDetectiveServer.ImportGame:output_type -> crabs.evening_detective_server.GameImportRsp
- 243, // 276: crabs.evening_detective_server.EveningDetectiveServer.DownloadGameResultsPackage:output_type -> google.api.HttpBody
- 235, // 277: crabs.evening_detective_server.EveningDetectiveServer.ApplyGameResultsPackage:output_type -> crabs.evening_detective_server.GameResultsPackageRsp
- 113, // 278: crabs.evening_detective_server.EveningDetectiveServer.StartGameExport:output_type -> crabs.evening_detective_server.GameExportRsp
- 113, // 279: crabs.evening_detective_server.EveningDetectiveServer.GetGameExport:output_type -> crabs.evening_detective_server.GameExportRsp
- 214, // 280: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:output_type -> crabs.evening_detective_server.IssueGameTicketsRsp
- 217, // 281: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:output_type -> crabs.evening_detective_server.GetTicketRsp
- 219, // 282: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:output_type -> crabs.evening_detective_server.AcceptTicketRsp
- 116, // 283: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:output_type -> crabs.evening_detective_server.CreateScreenSessionRsp
- 118, // 284: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:output_type -> crabs.evening_detective_server.GetScreenStateRsp
- 120, // 285: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:output_type -> crabs.evening_detective_server.GetGameScreensRsp
- 123, // 286: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:output_type -> crabs.evening_detective_server.GetGameMusicRsp
- 125, // 287: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:output_type -> crabs.evening_detective_server.SetGameMusicRsp
- 127, // 288: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:output_type -> crabs.evening_detective_server.AdvanceScreenMusicRsp
- 129, // 289: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:output_type -> crabs.evening_detective_server.BindScreenRsp
- 131, // 290: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:output_type -> crabs.evening_detective_server.UnbindScreenRsp
- 133, // 291: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:output_type -> crabs.evening_detective_server.SetScreenSoundRsp
- 136, // 292: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:output_type -> crabs.evening_detective_server.GetGameMapRsp
- 138, // 293: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:output_type -> crabs.evening_detective_server.UpdateGameMapItemRsp
- 140, // 294: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:output_type -> crabs.evening_detective_server.SetScreenModeRsp
- 142, // 295: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:output_type -> crabs.evening_detective_server.SetScreenTimerRsp
- 144, // 296: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:output_type -> crabs.evening_detective_server.SendScreenCommandRsp
- 148, // 297: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:output_type -> crabs.evening_detective_server.GetScreenPlanRsp
- 150, // 298: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:output_type -> crabs.evening_detective_server.SaveScreenPlanRsp
- 152, // 299: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:output_type -> crabs.evening_detective_server.SetScreenPlanStepRsp
- 154, // 300: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:output_type -> crabs.evening_detective_server.GetScreenResultsRsp
- 243, // 301: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:output_type -> google.api.HttpBody
- 162, // 302: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:output_type -> crabs.evening_detective_server.GetGameAnswersRsp
- 166, // 303: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:output_type -> crabs.evening_detective_server.GetGameResultsRsp
- 169, // 304: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:output_type -> crabs.evening_detective_server.CreateGameReviewRsp
- 173, // 305: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
- 173, // 306: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
- 173, // 307: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
- 173, // 308: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
- 175, // 309: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:output_type -> crabs.evening_detective_server.ModerateGameReviewRsp
- 177, // 310: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:output_type -> crabs.evening_detective_server.UpdateGameRsp
- 179, // 311: crabs.evening_detective_server.EveningDetectiveServer.StartGame:output_type -> crabs.evening_detective_server.StartGameRsp
- 181, // 312: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:output_type -> crabs.evening_detective_server.PauseGameRsp
- 183, // 313: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:output_type -> crabs.evening_detective_server.PlayGameRsp
- 185, // 314: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:output_type -> crabs.evening_detective_server.FinishGameRsp
- 187, // 315: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:output_type -> crabs.evening_detective_server.ResetGameRsp
- 189, // 316: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:output_type -> crabs.evening_detective_server.DeleteGameRsp
- 191, // 317: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:output_type -> crabs.evening_detective_server.AddTeamRsp
- 193, // 318: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:output_type -> crabs.evening_detective_server.UpdateTeamRsp
- 195, // 319: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:output_type -> crabs.evening_detective_server.DeleteTeamRsp
- 197, // 320: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:output_type -> crabs.evening_detective_server.GiveTeamApplicationsRsp
- 199, // 321: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:output_type -> crabs.evening_detective_server.GetTeamStoryRsp
- 202, // 322: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:output_type -> crabs.evening_detective_server.AddTeamActionRsp
- 204, // 323: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:output_type -> crabs.evening_detective_server.DeleteLastTeamActionRsp
- 206, // 324: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:output_type -> crabs.evening_detective_server.GetTeamAnswersRsp
- 208, // 325: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:output_type -> crabs.evening_detective_server.SubmitTeamAnswersRsp
- 210, // 326: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:output_type -> crabs.evening_detective_server.SetTeamAnswerScoreRsp
- 216, // [216:327] is the sub-list for method output_type
- 105, // [105:216] is the sub-list for method input_type
- 105, // [105:105] is the sub-list for extension type_name
- 105, // [105:105] is the sub-list for extension extendee
- 0, // [0:105] is the sub-list for field type_name
+ 244, // 99: crabs.evening_detective_server.GetDevicesRsp.serverTime:type_name -> google.protobuf.Timestamp
+ 242, // 100: crabs.evening_detective_server.GetDevicesRsp.wifi:type_name -> crabs.evening_detective_server.VenueWiFi
+ 244, // 101: crabs.evening_detective_server.VenueDevice.firstSeenAt:type_name -> google.protobuf.Timestamp
+ 244, // 102: crabs.evening_detective_server.VenueDevice.lastSeenAt:type_name -> google.protobuf.Timestamp
+ 241, // 103: crabs.evening_detective_server.VenueDevice.connections:type_name -> crabs.evening_detective_server.DeviceConnection
+ 244, // 104: crabs.evening_detective_server.DeviceConnection.firstSeenAt:type_name -> google.protobuf.Timestamp
+ 244, // 105: crabs.evening_detective_server.DeviceConnection.lastSeenAt:type_name -> google.protobuf.Timestamp
+ 244, // 106: crabs.evening_detective_server.VenueWiFi.collectedAt:type_name -> google.protobuf.Timestamp
+ 243, // 107: crabs.evening_detective_server.VenueWiFi.clients:type_name -> crabs.evening_detective_server.WiFiClient
+ 236, // 108: crabs.evening_detective_server.EveningDetectiveServer.DeviceHeartbeat:input_type -> crabs.evening_detective_server.DeviceHeartbeatReq
+ 238, // 109: crabs.evening_detective_server.EveningDetectiveServer.GetDevices:input_type -> crabs.evening_detective_server.GetDevicesReq
+ 223, // 110: crabs.evening_detective_server.EveningDetectiveServer.GetTasks:input_type -> crabs.evening_detective_server.GetTasksReq
+ 225, // 111: crabs.evening_detective_server.EveningDetectiveServer.GetTaskAssignees:input_type -> crabs.evening_detective_server.GetTaskAssigneesReq
+ 227, // 112: crabs.evening_detective_server.EveningDetectiveServer.CreateTask:input_type -> crabs.evening_detective_server.CreateTaskReq
+ 228, // 113: crabs.evening_detective_server.EveningDetectiveServer.UpdateTask:input_type -> crabs.evening_detective_server.UpdateTaskReq
+ 229, // 114: crabs.evening_detective_server.EveningDetectiveServer.SetTaskStatus:input_type -> crabs.evening_detective_server.SetTaskStatusReq
+ 230, // 115: crabs.evening_detective_server.EveningDetectiveServer.DeleteTask:input_type -> crabs.evening_detective_server.DeleteTaskReq
+ 155, // 116: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:input_type -> crabs.evening_detective_server.GetParticipationReq
+ 156, // 117: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:input_type -> crabs.evening_detective_server.AnswerParticipationReq
+ 4, // 118: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq
+ 6, // 119: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq
+ 8, // 120: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq
+ 10, // 121: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq
+ 12, // 122: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq
+ 14, // 123: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq
+ 16, // 124: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:input_type -> crabs.evening_detective_server.DeleteAccountReq
+ 18, // 125: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:input_type -> crabs.evening_detective_server.GetTermsReq
+ 20, // 126: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:input_type -> crabs.evening_detective_server.GetPrivacyReq
+ 22, // 127: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:input_type -> crabs.evening_detective_server.GetConsentReq
+ 24, // 128: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:input_type -> crabs.evening_detective_server.GetUsersReq
+ 27, // 129: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:input_type -> crabs.evening_detective_server.GetUserByIDReq
+ 29, // 130: crabs.evening_detective_server.EveningDetectiveServer.GetMe:input_type -> crabs.evening_detective_server.GetMeReq
+ 31, // 131: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:input_type -> crabs.evening_detective_server.ChangeUserPasswordReq
+ 33, // 132: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:input_type -> crabs.evening_detective_server.AddUserRoleReq
+ 35, // 133: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:input_type -> crabs.evening_detective_server.DeleteUserRoleReq
+ 37, // 134: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:input_type -> crabs.evening_detective_server.GetPermissionsReq
+ 39, // 135: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:input_type -> crabs.evening_detective_server.UploadFileReq
+ 41, // 136: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:input_type -> crabs.evening_detective_server.DownloadFileReq
+ 44, // 137: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:input_type -> crabs.evening_detective_server.GetPlaylistsReq
+ 46, // 138: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:input_type -> crabs.evening_detective_server.CreatePlaylistReq
+ 48, // 139: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:input_type -> crabs.evening_detective_server.UpdatePlaylistReq
+ 50, // 140: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:input_type -> crabs.evening_detective_server.DeletePlaylistReq
+ 52, // 141: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:input_type -> crabs.evening_detective_server.UploadPlaylistTrackReq
+ 54, // 142: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:input_type -> crabs.evening_detective_server.DeletePlaylistTrackReq
+ 56, // 143: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:input_type -> crabs.evening_detective_server.SetScenarioPlaylistReq
+ 58, // 144: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:input_type -> crabs.evening_detective_server.AddScenarioReq
+ 60, // 145: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:input_type -> crabs.evening_detective_server.GetMyScenariosReq
+ 62, // 146: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:input_type -> crabs.evening_detective_server.GetScenariosCatalogReq
+ 64, // 147: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:input_type -> crabs.evening_detective_server.GetScenarioReq
+ 64, // 148: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:input_type -> crabs.evening_detective_server.GetScenarioReq
+ 78, // 149: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:input_type -> crabs.evening_detective_server.UpdateScenarioReq
+ 80, // 150: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:input_type -> crabs.evening_detective_server.PublicScenarioReq
+ 82, // 151: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:input_type -> crabs.evening_detective_server.DraftScenarioReq
+ 84, // 152: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:input_type -> crabs.evening_detective_server.DeleteScenarioReq
+ 86, // 153: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:input_type -> crabs.evening_detective_server.AddScenarioPlaceReq
+ 88, // 154: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:input_type -> crabs.evening_detective_server.UpdateScenarioPlaceReq
+ 90, // 155: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:input_type -> crabs.evening_detective_server.DeleteScenarioPlaceReq
+ 96, // 156: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:input_type -> crabs.evening_detective_server.AddScenarioQuestionReq
+ 98, // 157: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:input_type -> crabs.evening_detective_server.UpdateScenarioQuestionReq
+ 100, // 158: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:input_type -> crabs.evening_detective_server.DeleteScenarioQuestionReq
+ 211, // 159: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:input_type -> crabs.evening_detective_server.UpdateScenarioBackgroundReq
+ 94, // 160: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:input_type -> crabs.evening_detective_server.UpdateScenarioIntroReq
+ 92, // 161: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:input_type -> crabs.evening_detective_server.UpdateScenarioConclusionReq
+ 102, // 162: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:input_type -> crabs.evening_detective_server.DownloadScenarioArchiveReq
+ 245, // 163: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:input_type -> google.api.HttpBody
+ 104, // 164: crabs.evening_detective_server.EveningDetectiveServer.AddGame:input_type -> crabs.evening_detective_server.AddGameReq
+ 106, // 165: crabs.evening_detective_server.EveningDetectiveServer.GetGames:input_type -> crabs.evening_detective_server.GetGamesReq
+ 159, // 166: crabs.evening_detective_server.EveningDetectiveServer.GetGame:input_type -> crabs.evening_detective_server.GetGameReq
+ 245, // 167: crabs.evening_detective_server.EveningDetectiveServer.ImportGame:input_type -> google.api.HttpBody
+ 233, // 168: crabs.evening_detective_server.EveningDetectiveServer.DownloadGameResultsPackage:input_type -> crabs.evening_detective_server.GameResultsPackageReq
+ 234, // 169: crabs.evening_detective_server.EveningDetectiveServer.ApplyGameResultsPackage:input_type -> crabs.evening_detective_server.ApplyGameResultsPackageReq
+ 111, // 170: crabs.evening_detective_server.EveningDetectiveServer.StartGameExport:input_type -> crabs.evening_detective_server.StartGameExportReq
+ 112, // 171: crabs.evening_detective_server.EveningDetectiveServer.GetGameExport:input_type -> crabs.evening_detective_server.GetGameExportReq
+ 213, // 172: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:input_type -> crabs.evening_detective_server.IssueGameTicketsReq
+ 216, // 173: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:input_type -> crabs.evening_detective_server.GetTicketReq
+ 218, // 174: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:input_type -> crabs.evening_detective_server.AcceptTicketReq
+ 115, // 175: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:input_type -> crabs.evening_detective_server.CreateScreenSessionReq
+ 117, // 176: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:input_type -> crabs.evening_detective_server.GetScreenStateReq
+ 119, // 177: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:input_type -> crabs.evening_detective_server.GetGameScreensReq
+ 122, // 178: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:input_type -> crabs.evening_detective_server.GetGameMusicReq
+ 124, // 179: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:input_type -> crabs.evening_detective_server.SetGameMusicReq
+ 126, // 180: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:input_type -> crabs.evening_detective_server.AdvanceScreenMusicReq
+ 128, // 181: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:input_type -> crabs.evening_detective_server.BindScreenReq
+ 130, // 182: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:input_type -> crabs.evening_detective_server.UnbindScreenReq
+ 132, // 183: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:input_type -> crabs.evening_detective_server.SetScreenSoundReq
+ 135, // 184: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:input_type -> crabs.evening_detective_server.GetGameMapReq
+ 137, // 185: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:input_type -> crabs.evening_detective_server.UpdateGameMapItemReq
+ 139, // 186: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:input_type -> crabs.evening_detective_server.SetScreenModeReq
+ 141, // 187: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:input_type -> crabs.evening_detective_server.SetScreenTimerReq
+ 143, // 188: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:input_type -> crabs.evening_detective_server.SendScreenCommandReq
+ 147, // 189: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:input_type -> crabs.evening_detective_server.GetScreenPlanReq
+ 149, // 190: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:input_type -> crabs.evening_detective_server.SaveScreenPlanReq
+ 151, // 191: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:input_type -> crabs.evening_detective_server.SetScreenPlanStepReq
+ 153, // 192: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:input_type -> crabs.evening_detective_server.GetScreenResultsReq
+ 159, // 193: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:input_type -> crabs.evening_detective_server.GetGameReq
+ 161, // 194: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:input_type -> crabs.evening_detective_server.GetGameAnswersReq
+ 163, // 195: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:input_type -> crabs.evening_detective_server.GetGameResultsReq
+ 168, // 196: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:input_type -> crabs.evening_detective_server.CreateGameReviewReq
+ 170, // 197: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:input_type -> crabs.evening_detective_server.GetGameReviewsReq
+ 171, // 198: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:input_type -> crabs.evening_detective_server.GetScenarioReviewsReq
+ 170, // 199: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:input_type -> crabs.evening_detective_server.GetGameReviewsReq
+ 172, // 200: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:input_type -> crabs.evening_detective_server.GetReviewsForModerationReq
+ 174, // 201: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:input_type -> crabs.evening_detective_server.ModerateGameReviewReq
+ 176, // 202: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:input_type -> crabs.evening_detective_server.UpdateGameReq
+ 178, // 203: crabs.evening_detective_server.EveningDetectiveServer.StartGame:input_type -> crabs.evening_detective_server.StartGameReq
+ 180, // 204: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:input_type -> crabs.evening_detective_server.PauseGameReq
+ 182, // 205: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:input_type -> crabs.evening_detective_server.PlayGameReq
+ 184, // 206: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:input_type -> crabs.evening_detective_server.FinishGameReq
+ 186, // 207: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:input_type -> crabs.evening_detective_server.ResetGameReq
+ 188, // 208: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:input_type -> crabs.evening_detective_server.DeleteGameReq
+ 190, // 209: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:input_type -> crabs.evening_detective_server.AddTeamReq
+ 192, // 210: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:input_type -> crabs.evening_detective_server.UpdateTeamReq
+ 194, // 211: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:input_type -> crabs.evening_detective_server.DeleteTeamReq
+ 196, // 212: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:input_type -> crabs.evening_detective_server.GiveTeamApplicationsReq
+ 198, // 213: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:input_type -> crabs.evening_detective_server.GetTeamStoryReq
+ 201, // 214: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:input_type -> crabs.evening_detective_server.AddTeamActionReq
+ 203, // 215: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:input_type -> crabs.evening_detective_server.DeleteLastTeamActionReq
+ 205, // 216: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:input_type -> crabs.evening_detective_server.GetTeamAnswersReq
+ 207, // 217: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:input_type -> crabs.evening_detective_server.SubmitTeamAnswersReq
+ 209, // 218: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:input_type -> crabs.evening_detective_server.SetTeamAnswerScoreReq
+ 237, // 219: crabs.evening_detective_server.EveningDetectiveServer.DeviceHeartbeat:output_type -> crabs.evening_detective_server.DeviceHeartbeatRsp
+ 239, // 220: crabs.evening_detective_server.EveningDetectiveServer.GetDevices:output_type -> crabs.evening_detective_server.GetDevicesRsp
+ 224, // 221: crabs.evening_detective_server.EveningDetectiveServer.GetTasks:output_type -> crabs.evening_detective_server.GetTasksRsp
+ 226, // 222: crabs.evening_detective_server.EveningDetectiveServer.GetTaskAssignees:output_type -> crabs.evening_detective_server.GetTaskAssigneesRsp
+ 231, // 223: crabs.evening_detective_server.EveningDetectiveServer.CreateTask:output_type -> crabs.evening_detective_server.TaskRsp
+ 231, // 224: crabs.evening_detective_server.EveningDetectiveServer.UpdateTask:output_type -> crabs.evening_detective_server.TaskRsp
+ 231, // 225: crabs.evening_detective_server.EveningDetectiveServer.SetTaskStatus:output_type -> crabs.evening_detective_server.TaskRsp
+ 232, // 226: crabs.evening_detective_server.EveningDetectiveServer.DeleteTask:output_type -> crabs.evening_detective_server.DeleteTaskRsp
+ 157, // 227: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp
+ 157, // 228: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp
+ 5, // 229: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp
+ 7, // 230: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp
+ 9, // 231: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp
+ 11, // 232: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp
+ 13, // 233: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp
+ 15, // 234: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp
+ 17, // 235: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:output_type -> crabs.evening_detective_server.DeleteAccountRsp
+ 19, // 236: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:output_type -> crabs.evening_detective_server.GetTermsRsp
+ 21, // 237: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:output_type -> crabs.evening_detective_server.GetPrivacyRsp
+ 23, // 238: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:output_type -> crabs.evening_detective_server.GetConsentRsp
+ 25, // 239: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:output_type -> crabs.evening_detective_server.GetUsersRsp
+ 28, // 240: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:output_type -> crabs.evening_detective_server.GetUserByIDRsp
+ 30, // 241: crabs.evening_detective_server.EveningDetectiveServer.GetMe:output_type -> crabs.evening_detective_server.GetMeRsp
+ 32, // 242: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:output_type -> crabs.evening_detective_server.ChangeUserPasswordRsp
+ 34, // 243: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:output_type -> crabs.evening_detective_server.AddUserRoleRsp
+ 36, // 244: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:output_type -> crabs.evening_detective_server.DeleteUserRoleRsp
+ 38, // 245: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:output_type -> crabs.evening_detective_server.GetPermissionsRsp
+ 40, // 246: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:output_type -> crabs.evening_detective_server.UploadFileRsp
+ 245, // 247: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:output_type -> google.api.HttpBody
+ 45, // 248: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:output_type -> crabs.evening_detective_server.GetPlaylistsRsp
+ 47, // 249: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:output_type -> crabs.evening_detective_server.CreatePlaylistRsp
+ 49, // 250: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:output_type -> crabs.evening_detective_server.UpdatePlaylistRsp
+ 51, // 251: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:output_type -> crabs.evening_detective_server.DeletePlaylistRsp
+ 53, // 252: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:output_type -> crabs.evening_detective_server.UploadPlaylistTrackRsp
+ 55, // 253: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:output_type -> crabs.evening_detective_server.DeletePlaylistTrackRsp
+ 57, // 254: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:output_type -> crabs.evening_detective_server.SetScenarioPlaylistRsp
+ 59, // 255: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:output_type -> crabs.evening_detective_server.AddScenarioRsp
+ 61, // 256: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:output_type -> crabs.evening_detective_server.GetMyScenariosRsp
+ 63, // 257: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:output_type -> crabs.evening_detective_server.GetScenariosCatalogRsp
+ 65, // 258: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp
+ 65, // 259: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp
+ 79, // 260: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:output_type -> crabs.evening_detective_server.UpdateScenarioRsp
+ 81, // 261: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:output_type -> crabs.evening_detective_server.PublicScenarioRsp
+ 83, // 262: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:output_type -> crabs.evening_detective_server.DraftScenarioRsp
+ 85, // 263: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:output_type -> crabs.evening_detective_server.DeleteScenarioRsp
+ 87, // 264: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:output_type -> crabs.evening_detective_server.AddScenarioPlaceRsp
+ 89, // 265: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:output_type -> crabs.evening_detective_server.UpdateScenarioPlaceRsp
+ 91, // 266: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:output_type -> crabs.evening_detective_server.DeleteScenarioPlaceRsp
+ 97, // 267: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:output_type -> crabs.evening_detective_server.AddScenarioQuestionRsp
+ 99, // 268: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:output_type -> crabs.evening_detective_server.UpdateScenarioQuestionRsp
+ 101, // 269: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:output_type -> crabs.evening_detective_server.DeleteScenarioQuestionRsp
+ 212, // 270: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:output_type -> crabs.evening_detective_server.UpdateScenarioBackgroundRsp
+ 95, // 271: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:output_type -> crabs.evening_detective_server.UpdateScenarioIntroRsp
+ 93, // 272: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:output_type -> crabs.evening_detective_server.UpdateScenarioConclusionRsp
+ 245, // 273: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:output_type -> google.api.HttpBody
+ 103, // 274: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:output_type -> crabs.evening_detective_server.UploadScenarioArchiveRsp
+ 105, // 275: crabs.evening_detective_server.EveningDetectiveServer.AddGame:output_type -> crabs.evening_detective_server.AddGameRsp
+ 107, // 276: crabs.evening_detective_server.EveningDetectiveServer.GetGames:output_type -> crabs.evening_detective_server.GetGamesRsp
+ 160, // 277: crabs.evening_detective_server.EveningDetectiveServer.GetGame:output_type -> crabs.evening_detective_server.GetGameRsp
+ 110, // 278: crabs.evening_detective_server.EveningDetectiveServer.ImportGame:output_type -> crabs.evening_detective_server.GameImportRsp
+ 245, // 279: crabs.evening_detective_server.EveningDetectiveServer.DownloadGameResultsPackage:output_type -> google.api.HttpBody
+ 235, // 280: crabs.evening_detective_server.EveningDetectiveServer.ApplyGameResultsPackage:output_type -> crabs.evening_detective_server.GameResultsPackageRsp
+ 113, // 281: crabs.evening_detective_server.EveningDetectiveServer.StartGameExport:output_type -> crabs.evening_detective_server.GameExportRsp
+ 113, // 282: crabs.evening_detective_server.EveningDetectiveServer.GetGameExport:output_type -> crabs.evening_detective_server.GameExportRsp
+ 214, // 283: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:output_type -> crabs.evening_detective_server.IssueGameTicketsRsp
+ 217, // 284: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:output_type -> crabs.evening_detective_server.GetTicketRsp
+ 219, // 285: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:output_type -> crabs.evening_detective_server.AcceptTicketRsp
+ 116, // 286: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:output_type -> crabs.evening_detective_server.CreateScreenSessionRsp
+ 118, // 287: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:output_type -> crabs.evening_detective_server.GetScreenStateRsp
+ 120, // 288: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:output_type -> crabs.evening_detective_server.GetGameScreensRsp
+ 123, // 289: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:output_type -> crabs.evening_detective_server.GetGameMusicRsp
+ 125, // 290: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:output_type -> crabs.evening_detective_server.SetGameMusicRsp
+ 127, // 291: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:output_type -> crabs.evening_detective_server.AdvanceScreenMusicRsp
+ 129, // 292: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:output_type -> crabs.evening_detective_server.BindScreenRsp
+ 131, // 293: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:output_type -> crabs.evening_detective_server.UnbindScreenRsp
+ 133, // 294: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:output_type -> crabs.evening_detective_server.SetScreenSoundRsp
+ 136, // 295: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:output_type -> crabs.evening_detective_server.GetGameMapRsp
+ 138, // 296: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:output_type -> crabs.evening_detective_server.UpdateGameMapItemRsp
+ 140, // 297: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:output_type -> crabs.evening_detective_server.SetScreenModeRsp
+ 142, // 298: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:output_type -> crabs.evening_detective_server.SetScreenTimerRsp
+ 144, // 299: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:output_type -> crabs.evening_detective_server.SendScreenCommandRsp
+ 148, // 300: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:output_type -> crabs.evening_detective_server.GetScreenPlanRsp
+ 150, // 301: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:output_type -> crabs.evening_detective_server.SaveScreenPlanRsp
+ 152, // 302: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:output_type -> crabs.evening_detective_server.SetScreenPlanStepRsp
+ 154, // 303: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:output_type -> crabs.evening_detective_server.GetScreenResultsRsp
+ 245, // 304: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:output_type -> google.api.HttpBody
+ 162, // 305: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:output_type -> crabs.evening_detective_server.GetGameAnswersRsp
+ 166, // 306: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:output_type -> crabs.evening_detective_server.GetGameResultsRsp
+ 169, // 307: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:output_type -> crabs.evening_detective_server.CreateGameReviewRsp
+ 173, // 308: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
+ 173, // 309: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
+ 173, // 310: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
+ 173, // 311: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp
+ 175, // 312: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:output_type -> crabs.evening_detective_server.ModerateGameReviewRsp
+ 177, // 313: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:output_type -> crabs.evening_detective_server.UpdateGameRsp
+ 179, // 314: crabs.evening_detective_server.EveningDetectiveServer.StartGame:output_type -> crabs.evening_detective_server.StartGameRsp
+ 181, // 315: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:output_type -> crabs.evening_detective_server.PauseGameRsp
+ 183, // 316: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:output_type -> crabs.evening_detective_server.PlayGameRsp
+ 185, // 317: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:output_type -> crabs.evening_detective_server.FinishGameRsp
+ 187, // 318: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:output_type -> crabs.evening_detective_server.ResetGameRsp
+ 189, // 319: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:output_type -> crabs.evening_detective_server.DeleteGameRsp
+ 191, // 320: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:output_type -> crabs.evening_detective_server.AddTeamRsp
+ 193, // 321: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:output_type -> crabs.evening_detective_server.UpdateTeamRsp
+ 195, // 322: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:output_type -> crabs.evening_detective_server.DeleteTeamRsp
+ 197, // 323: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:output_type -> crabs.evening_detective_server.GiveTeamApplicationsRsp
+ 199, // 324: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:output_type -> crabs.evening_detective_server.GetTeamStoryRsp
+ 202, // 325: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:output_type -> crabs.evening_detective_server.AddTeamActionRsp
+ 204, // 326: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:output_type -> crabs.evening_detective_server.DeleteLastTeamActionRsp
+ 206, // 327: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:output_type -> crabs.evening_detective_server.GetTeamAnswersRsp
+ 208, // 328: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:output_type -> crabs.evening_detective_server.SubmitTeamAnswersRsp
+ 210, // 329: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:output_type -> crabs.evening_detective_server.SetTeamAnswerScoreRsp
+ 219, // [219:330] is the sub-list for method output_type
+ 108, // [108:219] is the sub-list for method input_type
+ 108, // [108:108] is the sub-list for extension type_name
+ 108, // [108:108] is the sub-list for extension extendee
+ 0, // [0:108] is the sub-list for field type_name
}
func init() { file_main_proto_init() }
@@ -14399,13 +14570,14 @@ func file_main_proto_init() {
file_main_proto_msgTypes[233].OneofWrappers = []any{}
file_main_proto_msgTypes[234].OneofWrappers = []any{}
file_main_proto_msgTypes[237].OneofWrappers = []any{}
+ file_main_proto_msgTypes[239].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_main_proto_rawDesc), len(file_main_proto_rawDesc)),
NumEnums: 4,
- NumMessages: 238,
+ NumMessages: 240,
NumExtensions: 0,
NumServices: 1,
},