2020-10-01 20:50:56 +00:00
|
|
|
package bmumble
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"layeh.com/gumble/gumble"
|
|
|
|
|
|
|
|
"github.com/42wim/matterbridge/bridge/config"
|
|
|
|
"github.com/42wim/matterbridge/bridge/helper"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (b *Bmumble) handleServerConfig(event *gumble.ServerConfigEvent) {
|
|
|
|
b.serverConfigUpdate <- *event
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Bmumble) handleTextMessage(event *gumble.TextMessageEvent) {
|
|
|
|
sender := "unknown"
|
|
|
|
if event.TextMessage.Sender != nil {
|
|
|
|
sender = event.TextMessage.Sender.Name
|
|
|
|
}
|
2020-12-03 21:25:33 +00:00
|
|
|
// If the text message is received before receiving a ServerSync
|
|
|
|
// and UserState, Client.Self or Self.Channel are nil
|
|
|
|
if event.Client.Self == nil || event.Client.Self.Channel == nil {
|
|
|
|
b.Log.Warn("Connection bootstrap not finished, discarding text message")
|
|
|
|
return
|
|
|
|
}
|
2020-10-01 20:50:56 +00:00
|
|
|
// Convert Mumble HTML messages to markdown
|
|
|
|
parts, err := b.convertHTMLtoMarkdown(event.TextMessage.Message)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Error(err)
|
|
|
|
}
|
|
|
|
now := time.Now().UTC()
|
|
|
|
for i, part := range parts {
|
|
|
|
// Construct matterbridge message and pass on to the gateway
|
|
|
|
rmsg := config.Message{
|
|
|
|
Channel: strconv.FormatUint(uint64(event.Client.Self.Channel.ID), 10),
|
|
|
|
Username: sender,
|
|
|
|
UserID: sender + "@" + b.Host,
|
|
|
|
Account: b.Account,
|
|
|
|
}
|
|
|
|
if part.Image == nil {
|
|
|
|
rmsg.Text = part.Text
|
|
|
|
} else {
|
2023-03-10 21:57:35 +00:00
|
|
|
fileExt := part.FileExtension
|
|
|
|
if fileExt == ".jfif" {
|
|
|
|
fileExt = ".jpg"
|
|
|
|
}
|
|
|
|
if fileExt == ".jpe" {
|
|
|
|
fileExt = ".jpg"
|
|
|
|
}
|
|
|
|
fname := b.Account + "_" + strconv.FormatInt(now.UnixNano(), 10) + "_" + strconv.Itoa(i) + fileExt
|
2020-10-01 20:50:56 +00:00
|
|
|
rmsg.Extra = make(map[string][]interface{})
|
|
|
|
if err = helper.HandleDownloadSize(b.Log, &rmsg, fname, int64(len(part.Image)), b.General); err != nil {
|
|
|
|
b.Log.WithError(err).Warn("not including image in message")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
helper.HandleDownloadData(b.Log, &rmsg, fname, "", "", &part.Image, b.General)
|
|
|
|
}
|
|
|
|
b.Log.Debugf("Sending message to gateway: %+v", rmsg)
|
|
|
|
b.Remote <- rmsg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Bmumble) handleConnect(event *gumble.ConnectEvent) {
|
|
|
|
// Set the user's "bio"/comment
|
|
|
|
if comment := b.GetString("UserComment"); comment != "" && event.Client.Self != nil {
|
|
|
|
event.Client.Self.SetComment(comment)
|
|
|
|
}
|
|
|
|
// No need to talk or listen
|
|
|
|
event.Client.Self.SetSelfDeafened(true)
|
|
|
|
// if the Channel variable is set, this is a reconnect -> rejoin channel
|
|
|
|
if b.Channel != nil {
|
|
|
|
if err := b.doJoin(event.Client, *b.Channel); err != nil {
|
|
|
|
b.Log.Error(err)
|
|
|
|
}
|
|
|
|
b.Remote <- config.Message{
|
|
|
|
Username: "system",
|
|
|
|
Text: "rejoin",
|
|
|
|
Channel: "",
|
|
|
|
Account: b.Account,
|
|
|
|
Event: config.EventRejoinChannels,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-26 23:17:11 +00:00
|
|
|
func (b *Bmumble) handleJoinLeave(event *gumble.UserChangeEvent) {
|
|
|
|
// Ignore events happening before setup is done
|
|
|
|
if b.Channel == nil {
|
2020-10-01 20:50:56 +00:00
|
|
|
return
|
|
|
|
}
|
2022-11-26 23:17:11 +00:00
|
|
|
if b.GetBool("nosendjoinpart") {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
b.Log.Debugf("Received gumble user change event: %+v", event)
|
|
|
|
|
|
|
|
text := ""
|
|
|
|
switch {
|
|
|
|
case event.Type&gumble.UserChangeKicked > 0:
|
|
|
|
text = " was kicked"
|
|
|
|
case event.Type&gumble.UserChangeBanned > 0:
|
|
|
|
text = " was banned"
|
|
|
|
case event.Type&gumble.UserChangeDisconnected > 0:
|
|
|
|
if event.User.Channel != nil && event.User.Channel.ID == *b.Channel {
|
|
|
|
text = " left"
|
|
|
|
}
|
|
|
|
case event.Type&gumble.UserChangeConnected > 0:
|
|
|
|
if event.User.Channel != nil && event.User.Channel.ID == *b.Channel {
|
|
|
|
text = " joined"
|
|
|
|
}
|
|
|
|
case event.Type&gumble.UserChangeChannel > 0:
|
|
|
|
// Treat Mumble channel changes the same as connects/disconnects; as far as matterbridge is concerned, they are identical
|
|
|
|
if event.User.Channel != nil && event.User.Channel.ID == *b.Channel {
|
|
|
|
text = " joined"
|
|
|
|
} else {
|
|
|
|
text = " left"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if text != "" {
|
|
|
|
b.Remote <- config.Message{
|
|
|
|
Username: "system",
|
|
|
|
Text: event.User.Name + text,
|
|
|
|
Channel: strconv.FormatUint(uint64(*b.Channel), 10),
|
|
|
|
Account: b.Account,
|
|
|
|
Event: config.EventJoinLeave,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Bmumble) handleUserModified(event *gumble.UserChangeEvent) {
|
|
|
|
// Ignore events happening before setup is done
|
|
|
|
if b.Channel == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if event.Type&gumble.UserChangeChannel > 0 {
|
|
|
|
// Someone attempted to move the user out of the configured channel; attempt to join back
|
2020-10-01 20:50:56 +00:00
|
|
|
if err := b.doJoin(event.Client, *b.Channel); err != nil {
|
|
|
|
b.Log.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-26 23:17:11 +00:00
|
|
|
func (b *Bmumble) handleUserChange(event *gumble.UserChangeEvent) {
|
|
|
|
// The UserChangeEvent is used for both the gumble client itself as well as other clients
|
|
|
|
if event.User != event.Client.Self {
|
|
|
|
// other users
|
|
|
|
b.handleJoinLeave(event)
|
|
|
|
} else {
|
|
|
|
// gumble user
|
|
|
|
b.handleUserModified(event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-01 20:50:56 +00:00
|
|
|
func (b *Bmumble) handleDisconnect(event *gumble.DisconnectEvent) {
|
|
|
|
b.connected <- *event
|
|
|
|
}
|