diff --git a/gateway/gateway.go b/gateway/gateway.go index c5c86a7..e43ebe1 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -474,7 +474,8 @@ func (g *Gateway) start(ctx context.Context) error { // Expect either READY or RESUMED before continuing. wsutil.WSDebug("Waiting for either READY or RESUMED.") - // WaitForEvent should + // WaitForEvent should until the bot becomes ready or resumes (if a + // previous ready event has already been called). err := wsutil.WaitForEvent(ctx, g, ch, func(op *wsutil.OP) bool { switch op.EventName { case "READY": diff --git a/gateway/op.go b/gateway/op.go index 617d3cb..01ed3b4 100644 --- a/gateway/op.go +++ b/gateway/op.go @@ -85,10 +85,10 @@ func (g *Gateway) HandleOP(op *wsutil.OP) error { // Check if we know the event fn, ok := EventCreator[op.EventName] if !ok { - return fmt.Errorf( - "unknown event %s: %s", - op.EventName, string(op.Data), - ) + return &wsutil.UnknownEventError{ + Name: op.EventName, + Data: op.Data, + } } // Make a new pointer to the event diff --git a/utils/wsutil/op.go b/utils/wsutil/op.go index b0f8d29..117ce13 100644 --- a/utils/wsutil/op.go +++ b/utils/wsutil/op.go @@ -66,6 +66,25 @@ func AssertEvent(ev Event, code OPCode, v interface{}) (*OP, error) { return op, nil } +// UnknownEventError is required by HandleOP if an event is encountered that is +// not known. Internally, unknown events are logged and ignored. It is not a +// fatal error. +type UnknownEventError struct { + Name string + Data json.Raw +} + +// Error formats the unknown event error to with the event name and payload +func (err UnknownEventError) Error() string { + return fmt.Sprintf("unknown event %s: %s", err.Name, string(err.Data)) +} + +// IsBrokenConnection returns true if the error is a broken connection error. +func IsUnknownEvent(err error) bool { + var uevent *UnknownEventError + return errors.As(err, &uevent) +} + type EventHandler interface { HandleOP(op *OP) error } @@ -98,6 +117,11 @@ func WaitForEvent(ctx context.Context, h EventHandler, ch <-chan Event, fn func( // also prevent a race condition with things that need Ready after // Open(). if err := h.HandleOP(o); err != nil { + // Explicitly ignore events we don't know. + if IsUnknownEvent(err) { + WSError(err) + continue + } return err }