Merge branch 'main' of github.com:stryan/mumble-discord-bridge
This commit is contained in:
commit
812733d669
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ mumble-discord-bridge
|
||||
dist
|
||||
bridge
|
||||
.prof
|
||||
cert.pem
|
3
Makefile
3
Makefile
@ -6,6 +6,9 @@ mumble-discord-bridge: $(GOFILES)
|
||||
dev: $(GOFILES)
|
||||
goreleaser build --skip-validate --rm-dist && sudo ./dist/mumble-discord-bridge_linux_amd64/mumble-discord-bridge
|
||||
|
||||
dev-race: $(GOFILES)
|
||||
go run -race *.go
|
||||
|
||||
dev-profile: $(GOFILES)
|
||||
goreleaser build --skip-validate --rm-dist && sudo ./dist/mumble-discord-bridge_linux_amd64/mumble-discord-bridge -cpuprofile cpu.prof
|
||||
|
||||
|
35
README.md
35
README.md
@ -27,11 +27,13 @@ Usage of ./mumble-discord-bridge:
|
||||
-mumble-address string
|
||||
MUMBLE_ADDRESS, mumble server address, example example.com, required
|
||||
-mumble-channel string
|
||||
MUMBLE_CHANNEL, mumble channel to start in, optional
|
||||
MUMBLE_CHANNEL, mumble channel to start in, using '/' to separate nested channels, optional
|
||||
-mumble-disable-text
|
||||
MUMBLE_DISABLE_TEXT, disable sending text to mumble, (default false)
|
||||
-mumble-insecure
|
||||
MUMBLE_INSECURE, mumble insecure, optional
|
||||
-mumble-certificate
|
||||
MUMBLE_CERTIFICATE, mumble client certificate, optional
|
||||
-mumble-password string
|
||||
MUMBLE_PASSWORD, mumble password, optional
|
||||
-mumble-port int
|
||||
@ -40,6 +42,8 @@ Usage of ./mumble-discord-bridge:
|
||||
MUMBLE_USERNAME, mumble username, (default: discord) (default "Discord")
|
||||
-nice
|
||||
NICE, whether the bridge should automatically try to 'nice' itself, (default false)
|
||||
-debug
|
||||
DEBUG_LEVEL, DISCORD debug level, optional (default: 1)
|
||||
```
|
||||
|
||||
The bridge can be run with the follow modes:
|
||||
@ -74,7 +78,31 @@ The guide below provides information on how to setup a Discord bot.
|
||||
|
||||
[Create a Discord Bot](https://discordpy.readthedocs.io/en/latest/discord.html)
|
||||
|
||||
Individual Discord servers need to invite the bot before it can connect.
|
||||
Individual Discord servers need to invite the bot before it can connect.
|
||||
The bot requires the following permissions:
|
||||
* View Channels
|
||||
* See Messages
|
||||
* Read Message History
|
||||
* Voice Channel Connect
|
||||
* Voice Channel Speak
|
||||
* Voice Channel Use Voice Activity
|
||||
|
||||
### Finding Discord CID and GID
|
||||
|
||||
Discord GID is a unique ID linked to one Discord Server, also called Guild. CID is similarly a unique ID for a Discord Channel. To find these you need to set Discord into developer Mode.
|
||||
|
||||
[Instructions to enable Discord Developer Mode](https://discordia.me/en/developer-mode)
|
||||
|
||||
Then you can get the GID by right-clicking your server and selecting Copy-ID. Similarly the CID can be found right clicking the voice channel and selecting Copy ID.
|
||||
|
||||
### Generating Mumble Client (Optional)
|
||||
|
||||
Optionally you can specify a client certificate for mumble [Mumble Certificates](https://wiki.mumble.info/wiki/Mumble_Certificates)
|
||||
If you don't have a client certificate, you can generate one with this command:
|
||||
|
||||
``` bash
|
||||
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout cert.pem -out cert.pem -subj "/CN=mumble-discord-bridge"
|
||||
```
|
||||
|
||||
### Binary
|
||||
|
||||
@ -141,6 +169,9 @@ Audio leveling from Discord needs to be improved.
|
||||
|
||||
Delays in connecting to Mumble (such as from external authentication plugins) may result in extra error messages on initial connection.
|
||||
|
||||
There is an issue seen with Mumble-Server (murmur) 1.3.0 in which the bridge will loose the ability to send messages client after prolonged periods of connectivity.
|
||||
This issue has been appears to be resolved by murmur 1.3.4.
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the MIT License. See LICENSE for more information.
|
||||
|
34
bridge.go
34
bridge.go
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
@ -34,6 +35,9 @@ type BridgeState struct {
|
||||
// Wait for bridge to exit cleanly
|
||||
WaitExit *sync.WaitGroup
|
||||
|
||||
// Bridge State Mutex
|
||||
BridgeMutex sync.Mutex
|
||||
|
||||
// Bridge connection
|
||||
Connected bool
|
||||
|
||||
@ -70,6 +74,9 @@ type BridgeState struct {
|
||||
// Mumble Duplex and Event Listener
|
||||
MumbleStream *MumbleDuplex
|
||||
MumbleListener *MumbleListener
|
||||
|
||||
// Discord Voice channel to join
|
||||
DiscordChannelID string
|
||||
}
|
||||
|
||||
// startBridge established the voice connection
|
||||
@ -90,7 +97,12 @@ func (b *BridgeState) startBridge() {
|
||||
|
||||
// DISCORD Connect Voice
|
||||
log.Println("Attempting to join Discord voice channel")
|
||||
b.DiscordVoice, err = b.DiscordSession.ChannelVoiceJoin(b.BridgeConfig.GID, b.BridgeConfig.CID, false, false)
|
||||
if b.DiscordChannelID == "" {
|
||||
log.Println("Tried to start bridge but no Discord channel specified")
|
||||
return
|
||||
}
|
||||
b.DiscordVoice, err = b.DiscordSession.ChannelVoiceJoin(b.BridgeConfig.GID, b.DiscordChannelID, false, false)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
b.DiscordVoice.Disconnect()
|
||||
@ -111,6 +123,16 @@ func (b *BridgeState) startBridge() {
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
}
|
||||
|
||||
if b.BridgeConfig.MumbleCertificate != "" {
|
||||
keyFile := b.BridgeConfig.MumbleCertificate
|
||||
if certificate, err := tls.LoadX509KeyPair(keyFile, keyFile); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
tlsConfig.Certificates = append(tlsConfig.Certificates, certificate)
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Attempting to join Mumble")
|
||||
b.MumbleClient, err = gumble.DialWithDialer(new(net.Dialer), b.BridgeConfig.MumbleAddr, b.BridgeConfig.MumbleConfig, &tlsConfig)
|
||||
|
||||
@ -149,6 +171,7 @@ func (b *BridgeState) startBridge() {
|
||||
go b.DiscordStream.discordSendPCM(ctx, &wg, cancel, toDiscord)
|
||||
|
||||
// Monitor Mumble
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
wg.Add(1)
|
||||
ticker := time.NewTicker(500 * time.Millisecond)
|
||||
@ -170,7 +193,9 @@ func (b *BridgeState) startBridge() {
|
||||
}
|
||||
}()
|
||||
|
||||
b.BridgeMutex.Lock()
|
||||
b.Connected = true
|
||||
b.BridgeMutex.Unlock()
|
||||
|
||||
// Hold until cancelled or external die request
|
||||
select {
|
||||
@ -181,7 +206,10 @@ func (b *BridgeState) startBridge() {
|
||||
cancel()
|
||||
}
|
||||
|
||||
b.BridgeMutex.Lock()
|
||||
b.Connected = false
|
||||
b.BridgeMutex.Unlock()
|
||||
|
||||
wg.Wait()
|
||||
log.Println("Terminating Bridge")
|
||||
b.MumbleUsersMutex.Lock()
|
||||
@ -202,6 +230,7 @@ func (b *BridgeState) discordStatusUpdate() {
|
||||
b.DiscordSession.UpdateListeningStatus("an error pinging mumble")
|
||||
} else {
|
||||
b.MumbleUsersMutex.Lock()
|
||||
b.BridgeMutex.Lock()
|
||||
b.MumbleUserCount = resp.ConnectedUsers
|
||||
if b.Connected {
|
||||
b.MumbleUserCount = b.MumbleUserCount - 1
|
||||
@ -215,6 +244,7 @@ func (b *BridgeState) discordStatusUpdate() {
|
||||
status = fmt.Sprintf("%v users in Mumble\n", b.MumbleUserCount)
|
||||
}
|
||||
}
|
||||
b.BridgeMutex.Unlock()
|
||||
b.MumbleUsersMutex.Unlock()
|
||||
b.DiscordSession.UpdateListeningStatus(status)
|
||||
}
|
||||
@ -238,6 +268,7 @@ func (b *BridgeState) AutoBridge() {
|
||||
|
||||
b.MumbleUsersMutex.Lock()
|
||||
b.DiscordUsersMutex.Lock()
|
||||
b.BridgeMutex.Lock()
|
||||
|
||||
if !b.Connected && b.MumbleUserCount > 0 && len(b.DiscordUsers) > 0 {
|
||||
log.Println("users detected in mumble and discord, bridging")
|
||||
@ -248,6 +279,7 @@ func (b *BridgeState) AutoBridge() {
|
||||
b.BridgeDie <- true
|
||||
}
|
||||
|
||||
b.BridgeMutex.Unlock()
|
||||
b.MumbleUsersMutex.Unlock()
|
||||
b.DiscordUsersMutex.Unlock()
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ type BridgeConfig struct {
|
||||
MumbleConfig *gumble.Config
|
||||
MumbleAddr string
|
||||
MumbleInsecure bool
|
||||
MumbleChannel string
|
||||
MumbleCertificate string
|
||||
MumbleChannel []string
|
||||
MumbleDisableText bool
|
||||
Command string
|
||||
GID string
|
||||
|
@ -24,7 +24,7 @@ func (l *DiscordListener) guildCreate(s *discordgo.Session, event *discordgo.Gui
|
||||
}
|
||||
|
||||
for _, vs := range event.VoiceStates {
|
||||
if vs.ChannelID == l.Bridge.BridgeConfig.CID {
|
||||
if vs.ChannelID == l.Bridge.DiscordChannelID {
|
||||
if s.State.User.ID == vs.UserID {
|
||||
// Ignore bot
|
||||
continue
|
||||
@ -49,11 +49,13 @@ func (l *DiscordListener) guildCreate(s *discordgo.Session, event *discordgo.Gui
|
||||
l.Bridge.DiscordUsersMutex.Unlock()
|
||||
|
||||
// If connected to mumble inform users of Discord users
|
||||
l.Bridge.BridgeMutex.Lock()
|
||||
if l.Bridge.Connected && !l.Bridge.BridgeConfig.MumbleDisableText {
|
||||
l.Bridge.MumbleClient.Do(func() {
|
||||
l.Bridge.MumbleClient.Self.Channel.Send(fmt.Sprintf("%v has joined Discord\n", u.Username), false)
|
||||
})
|
||||
}
|
||||
l.Bridge.BridgeMutex.Unlock()
|
||||
|
||||
}
|
||||
}
|
||||
@ -61,10 +63,6 @@ func (l *DiscordListener) guildCreate(s *discordgo.Session, event *discordgo.Gui
|
||||
|
||||
func (l *DiscordListener) messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
|
||||
if l.Bridge.Mode == bridgeModeConstant {
|
||||
return
|
||||
}
|
||||
|
||||
// Ignore all messages created by the bot itself
|
||||
if m.Author.ID == s.State.User.ID {
|
||||
return
|
||||
@ -83,11 +81,26 @@ func (l *DiscordListener) messageCreate(s *discordgo.Session, m *discordgo.Messa
|
||||
return
|
||||
}
|
||||
prefix := "!" + l.Bridge.BridgeConfig.Command
|
||||
|
||||
if l.Bridge.Mode == bridgeModeConstant && strings.HasPrefix(m.Content, prefix) {
|
||||
l.Bridge.DiscordSession.ChannelMessageSend(m.ChannelID, "Constant mode enabled, manual commands can not be entered")
|
||||
return
|
||||
}
|
||||
|
||||
l.Bridge.BridgeMutex.Lock()
|
||||
bridgeConnected := l.Bridge.Connected
|
||||
l.Bridge.BridgeMutex.Unlock()
|
||||
|
||||
if strings.HasPrefix(m.Content, prefix+" link") {
|
||||
// Look for the message sender in that guild's current voice states.
|
||||
for _, vs := range g.VoiceStates {
|
||||
if bridgeConnected {
|
||||
l.Bridge.DiscordSession.ChannelMessageSend(m.ChannelID, "Bridge already running, unlink first")
|
||||
return
|
||||
}
|
||||
if vs.UserID == m.Author.ID {
|
||||
log.Printf("Trying to join GID %v and VID %v\n", g.ID, vs.ChannelID)
|
||||
l.Bridge.DiscordChannelID = vs.ChannelID
|
||||
go l.Bridge.startBridge()
|
||||
return
|
||||
}
|
||||
@ -96,8 +109,12 @@ func (l *DiscordListener) messageCreate(s *discordgo.Session, m *discordgo.Messa
|
||||
|
||||
if strings.HasPrefix(m.Content, prefix+" unlink") {
|
||||
// Look for the message sender in that guild's current voice states.
|
||||
if !bridgeConnected {
|
||||
l.Bridge.DiscordSession.ChannelMessageSend(m.ChannelID, "Bridge is not currently running")
|
||||
return
|
||||
}
|
||||
for _, vs := range g.VoiceStates {
|
||||
if vs.UserID == m.Author.ID {
|
||||
if vs.UserID == m.Author.ID && vs.ChannelID == l.Bridge.DiscordChannelID {
|
||||
log.Printf("Trying to leave GID %v and VID %v\n", g.ID, vs.ChannelID)
|
||||
l.Bridge.BridgeDie <- true
|
||||
return
|
||||
@ -107,6 +124,10 @@ func (l *DiscordListener) messageCreate(s *discordgo.Session, m *discordgo.Messa
|
||||
|
||||
if strings.HasPrefix(m.Content, prefix+" refresh") {
|
||||
// Look for the message sender in that guild's current voice states.
|
||||
if !bridgeConnected {
|
||||
l.Bridge.DiscordSession.ChannelMessageSend(m.ChannelID, "Bridge is not currently running")
|
||||
return
|
||||
}
|
||||
for _, vs := range g.VoiceStates {
|
||||
if vs.UserID == m.Author.ID {
|
||||
log.Printf("Trying to refresh GID %v and VID %v\n", g.ID, vs.ChannelID)
|
||||
@ -122,10 +143,14 @@ func (l *DiscordListener) messageCreate(s *discordgo.Session, m *discordgo.Messa
|
||||
|
||||
if strings.HasPrefix(m.Content, prefix+" auto") {
|
||||
if l.Bridge.Mode != bridgeModeAuto {
|
||||
l.Bridge.DiscordSession.ChannelMessageSend(m.ChannelID, "Auto mode enabled")
|
||||
l.Bridge.Mode = bridgeModeAuto
|
||||
l.Bridge.DiscordChannelID = l.Bridge.BridgeConfig.CID
|
||||
l.Bridge.AutoChanDie = make(chan bool)
|
||||
go l.Bridge.AutoBridge()
|
||||
} else {
|
||||
l.Bridge.DiscordSession.ChannelMessageSend(m.ChannelID, "Auto mode disabled")
|
||||
l.Bridge.DiscordChannelID = ""
|
||||
l.Bridge.AutoChanDie <- true
|
||||
l.Bridge.Mode = bridgeModeManual
|
||||
}
|
||||
@ -152,7 +177,7 @@ func (l *DiscordListener) voiceUpdate(s *discordgo.Session, event *discordgo.Voi
|
||||
|
||||
// Sync the channel voice states to the local discordUsersMap
|
||||
for _, vs := range g.VoiceStates {
|
||||
if vs.ChannelID == l.Bridge.BridgeConfig.CID {
|
||||
if vs.ChannelID == l.Bridge.DiscordChannelID {
|
||||
if s.State.User.ID == vs.UserID {
|
||||
// Ignore bot
|
||||
continue
|
||||
@ -176,11 +201,13 @@ func (l *DiscordListener) voiceUpdate(s *discordgo.Session, event *discordgo.Voi
|
||||
seen: true,
|
||||
dm: dm,
|
||||
}
|
||||
l.Bridge.BridgeMutex.Lock()
|
||||
if l.Bridge.Connected && !l.Bridge.BridgeConfig.MumbleDisableText {
|
||||
l.Bridge.MumbleClient.Do(func() {
|
||||
l.Bridge.MumbleClient.Self.Channel.Send(fmt.Sprintf("%v has joined Discord\n", u.Username), false)
|
||||
})
|
||||
}
|
||||
l.Bridge.BridgeMutex.Unlock()
|
||||
} else {
|
||||
du := l.Bridge.DiscordUsers[vs.UserID]
|
||||
du.seen = true
|
||||
@ -192,13 +219,15 @@ func (l *DiscordListener) voiceUpdate(s *discordgo.Session, event *discordgo.Voi
|
||||
|
||||
// Remove users that are no longer connected
|
||||
for id := range l.Bridge.DiscordUsers {
|
||||
if l.Bridge.DiscordUsers[id].seen == false {
|
||||
if !l.Bridge.DiscordUsers[id].seen {
|
||||
log.Println("User left Discord channel " + l.Bridge.DiscordUsers[id].username)
|
||||
l.Bridge.BridgeMutex.Lock()
|
||||
if l.Bridge.Connected && !l.Bridge.BridgeConfig.MumbleDisableText {
|
||||
l.Bridge.MumbleClient.Do(func() {
|
||||
l.Bridge.MumbleClient.Self.Channel.Send(fmt.Sprintf("%v has left Discord channel\n", l.Bridge.DiscordUsers[id].username), false)
|
||||
})
|
||||
}
|
||||
l.Bridge.BridgeMutex.Unlock()
|
||||
delete(l.Bridge.DiscordUsers, id)
|
||||
}
|
||||
}
|
||||
|
30
discord.go
30
discord.go
@ -23,9 +23,8 @@ type fromDiscord struct {
|
||||
type DiscordDuplex struct {
|
||||
Bridge *BridgeState
|
||||
|
||||
discordMutex sync.Mutex
|
||||
discordMixerMutex sync.Mutex
|
||||
fromDiscordMap map[uint32]fromDiscord
|
||||
discordMutex sync.Mutex
|
||||
fromDiscordMap map[uint32]fromDiscord
|
||||
}
|
||||
|
||||
// OnError gets called by dgvoice when an error is encountered.
|
||||
@ -87,8 +86,9 @@ func (dd *DiscordDuplex) discordSendPCM(ctx context.Context, wg *sync.WaitGroup,
|
||||
continue
|
||||
}
|
||||
|
||||
if dd.Bridge.DiscordVoice.Ready == false || dd.Bridge.DiscordVoice.OpusSend == nil {
|
||||
if lastReady == true {
|
||||
dd.Bridge.DiscordVoice.RWMutex.RLock()
|
||||
if !dd.Bridge.DiscordVoice.Ready || dd.Bridge.DiscordVoice.OpusSend == nil {
|
||||
if lastReady {
|
||||
OnError(fmt.Sprintf("Discordgo not ready for opus packets. %+v : %+v", dd.Bridge.DiscordVoice.Ready, dd.Bridge.DiscordVoice.OpusSend), nil)
|
||||
readyTimeout = time.AfterFunc(30*time.Second, func() {
|
||||
log.Println("set ready timeout")
|
||||
@ -96,13 +96,15 @@ func (dd *DiscordDuplex) discordSendPCM(ctx context.Context, wg *sync.WaitGroup,
|
||||
})
|
||||
lastReady = false
|
||||
}
|
||||
continue
|
||||
} else if lastReady == false {
|
||||
} else if !lastReady {
|
||||
fmt.Println("Discordgo ready to send opus packets")
|
||||
lastReady = true
|
||||
readyTimeout.Stop()
|
||||
} else {
|
||||
dd.Bridge.DiscordVoice.OpusSend <- opus
|
||||
}
|
||||
dd.Bridge.DiscordVoice.OpusSend <- opus
|
||||
dd.Bridge.DiscordVoice.RWMutex.RUnlock()
|
||||
|
||||
} else {
|
||||
if streaming {
|
||||
dd.Bridge.DiscordVoice.Speaking(false)
|
||||
@ -123,8 +125,9 @@ func (dd *DiscordDuplex) discordReceivePCM(ctx context.Context, wg *sync.WaitGro
|
||||
wg.Add(1)
|
||||
|
||||
for {
|
||||
if dd.Bridge.DiscordVoice.Ready == false || dd.Bridge.DiscordVoice.OpusRecv == nil {
|
||||
if lastReady == true {
|
||||
dd.Bridge.DiscordVoice.RWMutex.RLock()
|
||||
if !dd.Bridge.DiscordVoice.Ready || dd.Bridge.DiscordVoice.OpusRecv == nil {
|
||||
if lastReady {
|
||||
OnError(fmt.Sprintf("Discordgo not to receive opus packets. %+v : %+v", dd.Bridge.DiscordVoice.Ready, dd.Bridge.DiscordVoice.OpusSend), nil)
|
||||
readyTimeout = time.AfterFunc(30*time.Second, func() {
|
||||
log.Println("set ready timeout")
|
||||
@ -133,11 +136,12 @@ func (dd *DiscordDuplex) discordReceivePCM(ctx context.Context, wg *sync.WaitGro
|
||||
lastReady = false
|
||||
}
|
||||
continue
|
||||
} else if lastReady == false {
|
||||
} else if !lastReady {
|
||||
fmt.Println("Discordgo ready to receive packets")
|
||||
lastReady = true
|
||||
readyTimeout.Stop()
|
||||
}
|
||||
dd.Bridge.DiscordVoice.RWMutex.RUnlock()
|
||||
|
||||
var ok bool
|
||||
var p *discordgo.Packet
|
||||
@ -222,7 +226,7 @@ func (dd *DiscordDuplex) fromDiscordMixer(ctx context.Context, wg *sync.WaitGrou
|
||||
for i := range dd.fromDiscordMap {
|
||||
if len(dd.fromDiscordMap[i].pcm) > 0 {
|
||||
sendAudio = true
|
||||
if dd.fromDiscordMap[i].streaming == false {
|
||||
if !dd.fromDiscordMap[i].streaming {
|
||||
x := dd.fromDiscordMap[i]
|
||||
x.streaming = true
|
||||
dd.fromDiscordMap[i] = x
|
||||
@ -231,7 +235,7 @@ func (dd *DiscordDuplex) fromDiscordMixer(ctx context.Context, wg *sync.WaitGrou
|
||||
x1 := (<-dd.fromDiscordMap[i].pcm)
|
||||
internalMixerArr = append(internalMixerArr, x1)
|
||||
} else {
|
||||
if dd.fromDiscordMap[i].streaming == true {
|
||||
if dd.fromDiscordMap[i].streaming {
|
||||
x := dd.fromDiscordMap[i]
|
||||
x.streaming = false
|
||||
dd.fromDiscordMap[i] = x
|
||||
|
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module git.saintnet.tech/stryan/yammerbot
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/bwmarrin/discordgo v0.22.0
|
||||
github.com/bwmarrin/discordgo v0.23.2
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/joho/godotenv v1.3.0
|
||||
|
23
go.sum
23
go.sum
@ -1,13 +1,23 @@
|
||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/bwmarrin/discordgo v0.22.0 h1:uBxY1HmlVCsW1IuaPjpCGT6A2DBwRn0nvOguQIxDdFM=
|
||||
github.com/bwmarrin/discordgo v0.22.0/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
||||
github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4=
|
||||
github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/dchote/go-openal v0.0.0-20171116030048-f4a9a141d372/go.mod h1:74z+CYu2/mx4N+mcIS/rsvfAxBPBV9uv8zRAnwyFkdI=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473 h1:4cmBvAEBNJaGARUEs3/suWRyfyBfhf7I60WBZq+bv2w=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -30,42 +40,54 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210108172913-0df2131ae363/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 h1:5Beo0mZN8dRzgrMMkDp0jc8YXQKx9DiJ2k1dkvGsn5A=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
@ -78,6 +100,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
layeh.com/gopus v0.0.0-20161224163843-0ebf989153aa h1:WNU4LYsgD2UHxgKgB36mL6iMAMOvr127alafSlgBbiA=
|
||||
layeh.com/gopus v0.0.0-20161224163843-0ebf989153aa/go.mod h1:AOef7vHz0+v4sWwJnr0jSyHiX/1NgsMoaxl+rEPz/I0=
|
||||
|
19
main.go
19
main.go
@ -8,6 +8,7 @@ import (
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -38,7 +39,8 @@ func main() {
|
||||
mumbleUsername := flag.String("mumble-username", lookupEnvOrString("MUMBLE_USERNAME", "Discord"), "MUMBLE_USERNAME, mumble username, (default: discord)")
|
||||
mumblePassword := flag.String("mumble-password", lookupEnvOrString("MUMBLE_PASSWORD", ""), "MUMBLE_PASSWORD, mumble password, optional")
|
||||
mumbleInsecure := flag.Bool("mumble-insecure", lookupEnvOrBool("MUMBLE_INSECURE", false), " MUMBLE_INSECURE, mumble insecure, optional")
|
||||
mumbleChannel := flag.String("mumble-channel", lookupEnvOrString("MUMBLE_CHANNEL", ""), "MUMBLE_CHANNEL, mumble channel to start in, optional")
|
||||
mumbleCertificate := flag.String("mumble-certificate", lookupEnvOrString("MUMBLE_CERTIFICATE", ""), "MUMBLE_CERTIFICATE, client certificate to use when connecting to the Mumble server")
|
||||
mumbleChannel := flag.String("mumble-channel", lookupEnvOrString("MUMBLE_CHANNEL", ""), "MUMBLE_CHANNEL, mumble channel to start in, using '/' to separate nested channels, optional")
|
||||
mumbleDisableText := flag.Bool("mumble-disable-text", lookupEnvOrBool("MUMBLE_DISABLE_TEXT", false), "MUMBLE_DISABLE_TEXT, disable sending text to mumble, (default false)")
|
||||
discordToken := flag.String("discord-token", lookupEnvOrString("DISCORD_TOKEN", ""), "DISCORD_TOKEN, discord bot token, required")
|
||||
discordGID := flag.String("discord-gid", lookupEnvOrString("DISCORD_GID", ""), "DISCORD_GID, discord gid, required")
|
||||
@ -47,6 +49,7 @@ func main() {
|
||||
discordDisableText := flag.Bool("discord-disable-text", lookupEnvOrBool("DISCORD_DISABLE_TEXT", false), "DISCORD_DISABLE_TEXT, disable sending direct messages to discord, (default false)")
|
||||
mode := flag.String("mode", lookupEnvOrString("MODE", "constant"), "MODE, [constant, manual, auto] determine which mode the bridge starts in, (default constant)")
|
||||
nice := flag.Bool("nice", lookupEnvOrBool("NICE", false), "NICE, whether the bridge should automatically try to 'nice' itself, (default false)")
|
||||
debug := flag.Int("debug-level", lookupEnvOrInt("DEBUG", 1), "DEBUG_LEVEL, Discord debug level, optional, (default 1)")
|
||||
|
||||
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to `file`")
|
||||
|
||||
@ -99,7 +102,8 @@ func main() {
|
||||
// MumbleConfig: config,
|
||||
MumbleAddr: *mumbleAddr + ":" + strconv.Itoa(*mumblePort),
|
||||
MumbleInsecure: *mumbleInsecure,
|
||||
MumbleChannel: *mumbleChannel,
|
||||
MumbleCertificate: *mumbleCertificate,
|
||||
MumbleChannel: strings.Split(*mumbleChannel, "/"),
|
||||
MumbleDisableText: *mumbleDisableText,
|
||||
Command: *discordCommand,
|
||||
GID: *discordGID,
|
||||
@ -135,7 +139,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
Bridge.DiscordSession.LogLevel = 1
|
||||
Bridge.DiscordSession.LogLevel = *debug
|
||||
Bridge.DiscordSession.StateEnabled = true
|
||||
Bridge.DiscordSession.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAllWithoutPrivileged)
|
||||
Bridge.DiscordSession.ShouldReconnectOnError = true
|
||||
@ -163,6 +167,7 @@ func main() {
|
||||
log.Println("bridge starting in automatic mode")
|
||||
Bridge.AutoChanDie = make(chan bool)
|
||||
Bridge.Mode = bridgeModeAuto
|
||||
Bridge.DiscordChannelID = Bridge.BridgeConfig.CID
|
||||
go Bridge.AutoBridge()
|
||||
case "manual":
|
||||
log.Println("bridge starting in manual mode")
|
||||
@ -170,6 +175,7 @@ func main() {
|
||||
case "constant":
|
||||
log.Println("bridge starting in constant mode")
|
||||
Bridge.Mode = bridgeModeConstant
|
||||
Bridge.DiscordChannelID = Bridge.BridgeConfig.CID
|
||||
go func() {
|
||||
for {
|
||||
Bridge.startBridge()
|
||||
@ -188,13 +194,14 @@ func main() {
|
||||
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
|
||||
<-sc
|
||||
|
||||
// Signal the bridge to exit cleanly
|
||||
Bridge.BridgeDie <- true
|
||||
|
||||
log.Println("OS Signal. Bot shutting down")
|
||||
|
||||
// Wait or the bridge to exit cleanly
|
||||
Bridge.BridgeMutex.Lock()
|
||||
if Bridge.Connected {
|
||||
//TODO BridgeDie occasionally panics on send to closed channel
|
||||
Bridge.BridgeDie <- true
|
||||
Bridge.WaitExit.Wait()
|
||||
}
|
||||
Bridge.BridgeMutex.Unlock()
|
||||
}
|
||||
|
@ -13,12 +13,10 @@ type MumbleListener struct {
|
||||
}
|
||||
|
||||
func (l *MumbleListener) mumbleConnect(e *gumble.ConnectEvent) {
|
||||
if l.Bridge.BridgeConfig.MumbleChannel != "" {
|
||||
//join specified channel
|
||||
startingChannel := e.Client.Channels.Find(l.Bridge.BridgeConfig.MumbleChannel)
|
||||
if startingChannel != nil {
|
||||
e.Client.Self.Move(startingChannel)
|
||||
}
|
||||
//join specified channel
|
||||
startingChannel := e.Client.Channels.Find(l.Bridge.BridgeConfig.MumbleChannel...)
|
||||
if startingChannel != nil {
|
||||
e.Client.Self.Move(startingChannel)
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,22 +43,23 @@ func (l *MumbleListener) mumbleUserChange(e *gumble.UserChangeEvent) {
|
||||
e.User.Send("Mumble-Discord-Bridge v" + version)
|
||||
|
||||
// Tell the user who is connected to discord
|
||||
l.Bridge.DiscordUsersMutex.Lock()
|
||||
if len(l.Bridge.DiscordUsers) == 0 {
|
||||
e.User.Send("No users connected to Discord")
|
||||
} else {
|
||||
s := "Connected to Discord: "
|
||||
|
||||
arr := []string{}
|
||||
l.Bridge.DiscordUsersMutex.Lock()
|
||||
for u := range l.Bridge.DiscordUsers {
|
||||
arr = append(arr, l.Bridge.DiscordUsers[u].username)
|
||||
}
|
||||
|
||||
s = s + strings.Join(arr[:], ",")
|
||||
|
||||
l.Bridge.DiscordUsersMutex.Unlock()
|
||||
e.User.Send(s)
|
||||
}
|
||||
l.Bridge.DiscordUsersMutex.Unlock()
|
||||
|
||||
}
|
||||
|
||||
// Send discord a notice
|
||||
|
23
mumble.go
23
mumble.go
@ -29,21 +29,18 @@ func (m MumbleDuplex) OnAudioStream(e *gumble.AudioStreamEvent) {
|
||||
mutex.Unlock()
|
||||
|
||||
go func() {
|
||||
// TODO kill go routine on cleanup
|
||||
log.Println("new mumble audio stream", e.User.Name)
|
||||
for {
|
||||
select {
|
||||
case p := <-e.C:
|
||||
// log.Println("audio packet", p.Sender.Name, len(p.AudioBuffer))
|
||||
name := e.User.Name
|
||||
log.Println("new mumble audio stream", name)
|
||||
for p := range e.C {
|
||||
// log.Println("audio packet", p.Sender.Name, len(p.AudioBuffer))
|
||||
|
||||
// 480 per 10ms
|
||||
for i := 0; i < len(p.AudioBuffer)/480; i++ {
|
||||
localMumbleArray <- p.AudioBuffer[480*i : 480*(i+1)]
|
||||
}
|
||||
// 480 per 10ms
|
||||
for i := 0; i < len(p.AudioBuffer)/480; i++ {
|
||||
localMumbleArray <- p.AudioBuffer[480*i : 480*(i+1)]
|
||||
}
|
||||
}
|
||||
log.Println("mumble audio stream ended", name)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func (m MumbleDuplex) fromMumbleMixer(ctx context.Context, wg *sync.WaitGroup, toDiscord chan []int16) {
|
||||
@ -70,7 +67,7 @@ func (m MumbleDuplex) fromMumbleMixer(ctx context.Context, wg *sync.WaitGroup, t
|
||||
for i := 0; i < len(fromMumbleArr); i++ {
|
||||
if len(fromMumbleArr[i]) > 0 {
|
||||
sendAudio = true
|
||||
if mumbleStreamingArr[i] == false {
|
||||
if !mumbleStreamingArr[i] {
|
||||
mumbleStreamingArr[i] = true
|
||||
// log.Println("mumble starting", i)
|
||||
}
|
||||
@ -78,7 +75,7 @@ func (m MumbleDuplex) fromMumbleMixer(ctx context.Context, wg *sync.WaitGroup, t
|
||||
x1 := (<-fromMumbleArr[i])
|
||||
internalMixerArr = append(internalMixerArr, x1)
|
||||
} else {
|
||||
if mumbleStreamingArr[i] == true {
|
||||
if mumbleStreamingArr[i] {
|
||||
mumbleStreamingArr[i] = false
|
||||
// log.Println("mumble stopping", i)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user