42wim/matterbridge

View on GitHub
bridge/mumble/handlers.go

Summary

Maintainability
A
0 mins
Test Coverage
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
    }
    // 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
    }
    // 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 {
            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
            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,
        }
    }
}

func (b *Bmumble) handleJoinLeave(event *gumble.UserChangeEvent) {
    // Ignore events happening before setup is done
    if b.Channel == nil {
        return
    }
    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
        if err := b.doJoin(event.Client, *b.Channel); err != nil {
            b.Log.Error(err)
        }
    }
}

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)
    }
}

func (b *Bmumble) handleDisconnect(event *gumble.DisconnectEvent) {
    b.connected <- *event
}