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

View File

@ -1,12 +1,18 @@
package bmumble package bmumble
import ( import (
"errors"
"fmt" "fmt"
"mime" "mime"
"net/http" "net/http"
"net/url"
"regexp" "regexp"
"strconv"
"strings" "strings"
"layeh.com/gumble/gumble"
"layeh.com/gumble/gumbleutil"
"github.com/42wim/matterbridge/bridge/config" "github.com/42wim/matterbridge/bridge/config"
"github.com/mattn/godown" "github.com/mattn/godown"
"github.com/vincent-petithory/dataurl" "github.com/vincent-petithory/dataurl"
@ -47,8 +53,6 @@ func (b *Bmumble) tokenize(t *string) ([]MessagePart, error) {
var parts []MessagePart var parts []MessagePart
for { for {
tokens := p.FindStringSubmatch(remaining) tokens := p.FindStringSubmatch(remaining)
b.Log.Debugf("### tokens: %#v", tokens)
if tokens == nil { if tokens == nil {
// no match -> remaining string is non-image text // no match -> remaining string is non-image text
pre := strings.TrimSpace(remaining) pre := strings.TrimSpace(remaining)
@ -57,6 +61,7 @@ func (b *Bmumble) tokenize(t *string) ([]MessagePart, error) {
} }
return parts, nil return parts, nil
} }
// tokens[1] is the text before the image // tokens[1] is the text before the image
if len(tokens[1]) > 0 { if len(tokens[1]) > 0 {
pre := strings.TrimSpace(tokens[1]) pre := strings.TrimSpace(tokens[1])
@ -142,3 +147,43 @@ func (b *Bmumble) extractFiles(msg *config.Message) []config.Message {
msg.Extra["file"] = nil msg.Extra["file"] = nil
return messages 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/tls"
"crypto/x509" "crypto/x509"
"errors" "errors"
"fmt"
"io/ioutil" "io/ioutil"
"net" "net"
"strconv" "strconv"
@ -26,7 +27,7 @@ type Bmumble struct {
client *gumble.Client client *gumble.Client
Nick string Nick string
Host string Host string
Channel string Channel []string
local chan config.Message local chan config.Message
running chan error running chan error
connected chan gumble.DisconnectEvent connected chan gumble.DisconnectEvent
@ -75,12 +76,15 @@ func (b *Bmumble) Disconnect() error {
} }
func (b *Bmumble) JoinChannel(channel config.ChannelInfo) error { func (b *Bmumble) JoinChannel(channel config.ChannelInfo) error {
if b.Channel != "" && channel.Name != b.Channel { channelPath, err := b.parseChannelPath(b.client, channel.Name)
b.Log.Fatalf("Cannot join channel '%s', already joined to channel '%s'", channel.Name, b.Channel) 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") return errors.New("the Mumble bridge can only join a single channel")
} }
b.Channel = channel.Name return b.doJoin(b.client, channelPath)
return b.doJoin(b.client, channel.Name)
} }
func (b *Bmumble) Send(msg config.Message) (string, error) { func (b *Bmumble) Send(msg config.Message) (string, error) {
@ -186,13 +190,13 @@ func (b *Bmumble) doConnect() error {
return nil return nil
} }
func (b *Bmumble) doJoin(client *gumble.Client, name string) error { func (b *Bmumble) doJoin(client *gumble.Client, channelPath []string) error {
c := client.Channels.Find(name) c := client.Channels.Find(channelPath...)
if c == nil { 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) client.Self.Move(c)
b.Channel = c.Name
return nil return nil
} }

View File

@ -1791,7 +1791,8 @@ enable=true
# ------------------------------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------------------------------
# msteams | threadId | 19:82abcxx@thread.skype | You'll find the threadId in the URL # 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 # rocketchat | channel | #channel | # is required for private channels too
# ------------------------------------------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------------------------------