diff --git a/client.go b/client.go index 8f9c65a..aae3d3c 100644 --- a/client.go +++ b/client.go @@ -230,14 +230,7 @@ func (b *Barnard) Log(s string) { } func (b *Barnard) OnTextMessage(e *gumble.TextMessageEvent) { - var public = false - for _, c := range e.Channels { - if c.Name == b.Client.Self.Channel.Name { - public = true - break - } - } - if public { + if b.isPublicTextMessage(e) { sender := "Server" if e.Sender != nil { sender = e.Sender.Name @@ -256,6 +249,28 @@ func (b *Barnard) OnTextMessage(e *gumble.TextMessageEvent) { } } +// isPublicTextMessage reports whether a message targets the current channel, +// either directly or through a recursive channel-tree recipient. +func (b *Barnard) isPublicTextMessage(e *gumble.TextMessageEvent) bool { + if e == nil || b.Client == nil || b.Client.Self == nil || b.Client.Self.Channel == nil { + return false + } + current := b.Client.Self.Channel + for _, channel := range e.Channels { + if sameChannel(channel, current) { + return true + } + } + for _, root := range e.Trees { + for channel := current; channel != nil; channel = channel.Parent { + if sameChannel(channel, root) { + return true + } + } + } + return false +} + func (b *Barnard) OnUserChange(e *gumble.UserChangeEvent) { notification, hasNotification := b.userChangeNotification(e) if e.User != nil { diff --git a/client_notification_test.go b/client_notification_test.go index 8e88a8f..143036a 100644 --- a/client_notification_test.go +++ b/client_notification_test.go @@ -83,6 +83,20 @@ func TestServerAddressDefaultsPortWithoutBreakingIPv6(t *testing.T) { } } +func TestPublicTextMessageTargetsChannelIDsAndTrees(t *testing.T) { + root := &gumble.Channel{ID: 1, Name: "Root"} + current := &gumble.Channel{ID: 2, Name: "Room", Parent: root} + b := &Barnard{Client: &gumble.Client{Self: &gumble.User{Channel: current}}} + + if !b.isPublicTextMessage(&gumble.TextMessageEvent{TextMessage: gumble.TextMessage{Trees: []*gumble.Channel{root}}}) { + t.Fatal("recursive message to an ancestor was not public") + } + other := &gumble.Channel{ID: 3, Name: "Room"} + if b.isPublicTextMessage(&gumble.TextMessageEvent{TextMessage: gumble.TextMessage{Channels: []*gumble.Channel{other}}}) { + t.Fatal("message to a different channel with the same name was public") + } +} + func TestPublicServerMessageDoesNotPanic(t *testing.T) { channel := &gumble.Channel{ID: 1, Name: "Current"} b := &Barnard{