Fix channel name handling (support channel IDs and full channel paths)

This commit is contained in:
s3lph 2020-09-27 01:34:09 +02:00
parent b0a4536072
commit 5afd40fc63
4 changed files with 64 additions and 14 deletions

View File

@ -53,7 +53,7 @@ func (b *Bmumble) handleConnect(event *gumble.ConnectEvent) {
event.Client.Self.SetSelfDeafened(true)
event.Client.Self.SetSelfMuted(true)
// if the Channel variable is set, this is a reconnect -> rejoin channel
if b.Channel != "" {
if b.Channel != nil {
if err := b.doJoin(event.Client, b.Channel); err != nil {
b.Log.Error(err)
}
@ -73,7 +73,7 @@ func (b *Bmumble) handleUserChange(event *gumble.UserChangeEvent) {
return
}
// Someone attempted to move the user out of the configured channel; attempt to join back
if b.Channel != "" && b.Channel != event.Client.Self.Channel.Name {
if b.Channel != nil {
if err := b.doJoin(event.Client, b.Channel); err != nil {
b.Log.Error(err)
}

View File

@ -1,12 +1,18 @@
package bmumble
import (
"errors"
"fmt"
"mime"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"layeh.com/gumble/gumble"
"layeh.com/gumble/gumbleutil"
"github.com/42wim/matterbridge/bridge/config"
"github.com/mattn/godown"
"github.com/vincent-petithory/dataurl"
@ -47,8 +53,6 @@ func (b *Bmumble) tokenize(t *string) ([]MessagePart, error) {
var parts []MessagePart
for {
tokens := p.FindStringSubmatch(remaining)
b.Log.Debugf("### tokens: %#v", tokens)
if tokens == nil {
// no match -> remaining string is non-image text
pre := strings.TrimSpace(remaining)
@ -57,6 +61,7 @@ func (b *Bmumble) tokenize(t *string) ([]MessagePart, error) {
}
return parts, nil
}
// tokens[1] is the text before the image
if len(tokens[1]) > 0 {
pre := strings.TrimSpace(tokens[1])
@ -142,3 +147,43 @@ func (b *Bmumble) extractFiles(msg *config.Message) []config.Message {
msg.Extra["file"] = nil
return messages
}
func (b *Bmumble) parseChannelPath(client *gumble.Client, name string) ([]string, error) {
if strings.HasPrefix(name, "ID:") {
if channelId, err := strconv.ParseUint(name[3:], 10, 32); err == nil {
if c, ok := client.Channels[uint32(channelId)]; ok {
return gumbleutil.ChannelPath(c)[1:], nil
}
b.Log.Fatalf("No channel with ID %d", channelId)
return nil, errors.New("no such channel: " + name)
} else {
b.Log.WithError(err).Fatalf("Cannot parse channel ID: %s", name)
return nil, err
}
} else {
if !strings.HasPrefix(name, "/") {
return nil, errors.New("channel path must start with a '/': " + name)
}
// Special treatment for the root channel: empty slice
if name == "/" {
return make([]string, 0), nil
}
// Discard first token, which is the empty string before the leading /
tokens := strings.Split(name, "/")
var channelPath []string
for _, token := range tokens[1:] {
// Urldecode each token and append it to the path
if channelName, err := url.PathUnescape(token); err == nil && len(channelName) > 0 {
channelPath = append(channelPath, channelName)
} else {
b.Log.WithError(err).Fatalf("Error while decoding path component '%s'", token)
return nil, err
}
}
c := client.Channels.Find(channelPath...)
if c == nil {
return nil, errors.New("no such channel: " + name)
}
return gumbleutil.ChannelPath(c)[1:], nil
}
}

View File

@ -4,6 +4,7 @@ import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
"net"
"strconv"
@ -26,7 +27,7 @@ type Bmumble struct {
client *gumble.Client
Nick string
Host string
Channel string
Channel []string
local chan config.Message
running chan error
connected chan gumble.DisconnectEvent
@ -75,12 +76,15 @@ func (b *Bmumble) Disconnect() error {
}
func (b *Bmumble) JoinChannel(channel config.ChannelInfo) error {
if b.Channel != "" && channel.Name != b.Channel {
b.Log.Fatalf("Cannot join channel '%s', already joined to channel '%s'", channel.Name, b.Channel)
channelPath, err := b.parseChannelPath(b.client, channel.Name)
if err != nil {
return err
}
if b.Channel != nil {
b.Log.Fatalf("Cannot join channel '%v', already joined to channel '%v'", channel.Name, b.Channel)
return errors.New("the Mumble bridge can only join a single channel")
}
b.Channel = channel.Name
return b.doJoin(b.client, channel.Name)
return b.doJoin(b.client, channelPath)
}
func (b *Bmumble) Send(msg config.Message) (string, error) {
@ -186,13 +190,13 @@ func (b *Bmumble) doConnect() error {
return nil
}
func (b *Bmumble) doJoin(client *gumble.Client, name string) error {
c := client.Channels.Find(name)
func (b *Bmumble) doJoin(client *gumble.Client, channelPath []string) error {
c := client.Channels.Find(channelPath...)
if c == nil {
return errors.New("No such channel: " + name)
return errors.New(fmt.Sprintf("no such channel: %v", channelPath))
}
b.Channel = gumbleutil.ChannelPath(c)[1:]
client.Self.Move(c)
b.Channel = c.Name
return nil
}

View File

@ -1791,7 +1791,8 @@ enable=true
# -------------------------------------------------------------------------------------------------------------------------------------
# msteams | threadId | 19:82abcxx@thread.skype | You'll find the threadId in the URL
# -------------------------------------------------------------------------------------------------------------------------------------
# mumble | channel name | General | The channel name, as shown in Mumble
# mumble | channel id | ID:42 | The channel ID, as shown in the channel's "Edit" window
# | channel path | /A%20channel/a%20subchannel | The urlencoded channel path, as contained in the channel's URL
# -------------------------------------------------------------------------------------------------------------------------------------
# rocketchat | channel | #channel | # is required for private channels too
# -------------------------------------------------------------------------------------------------------------------------------------