2020-10-29 02:21:07 -04:00
package main
import (
"flag"
"log"
"os"
"os/signal"
2021-01-16 13:40:12 -05:00
"runtime/pprof"
2020-10-29 02:21:07 -04:00
"strconv"
2021-01-06 19:12:56 -05:00
"sync"
2021-01-04 21:23:52 -05:00
"syscall"
2020-10-29 02:21:07 -04:00
"time"
"github.com/bwmarrin/discordgo"
"github.com/joho/godotenv"
"layeh.com/gumble/gumble"
2021-01-06 19:12:56 -05:00
"layeh.com/gumble/gumbleutil"
2020-10-29 02:21:07 -04:00
_ "layeh.com/gumble/opus"
)
2021-01-09 18:18:31 -05:00
var (
// Build vars
version string
commit string
date string
)
2020-10-29 02:21:07 -04:00
func main ( ) {
2021-01-09 18:18:31 -05:00
log . Println ( "Mumble-Discord-Bridge" )
log . Println ( "v" + version + " " + commit + " " + date )
2020-10-29 02:21:07 -04:00
godotenv . Load ( )
mumbleAddr := flag . String ( "mumble-address" , lookupEnvOrString ( "MUMBLE_ADDRESS" , "" ) , "MUMBLE_ADDRESS, mumble server address, example example.com" )
mumblePort := flag . Int ( "mumble-port" , lookupEnvOrInt ( "MUMBLE_PORT" , 64738 ) , "MUMBLE_PORT mumble port" )
2021-01-16 14:04:52 -05:00
mumbleUsername := flag . String ( "mumble-username" , lookupEnvOrString ( "MUMBLE_USERNAME" , "Discord" ) , "MUMBLE_USERNAME, mumble username" )
2020-10-29 02:21:07 -04:00
mumblePassword := flag . String ( "mumble-password" , lookupEnvOrString ( "MUMBLE_PASSWORD" , "" ) , "MUMBLE_PASSWORD, mumble password, optional" )
2020-11-28 03:46:21 -05:00
mumbleInsecure := flag . Bool ( "mumble-insecure" , lookupEnvOrBool ( "MUMBLE_INSECURE" , false ) , "mumble insecure, env alt MUMBLE_INSECURE" )
2021-01-03 20:21:55 -05:00
mumbleChannel := flag . String ( "mumble-channel" , lookupEnvOrString ( "MUMBLE_CHANNEL" , "" ) , "mumble channel to start in" )
2020-10-29 02:21:07 -04:00
discordToken := flag . String ( "discord-token" , lookupEnvOrString ( "DISCORD_TOKEN" , "" ) , "DISCORD_TOKEN, discord bot token" )
discordGID := flag . String ( "discord-gid" , lookupEnvOrString ( "DISCORD_GID" , "" ) , "DISCORD_GID, discord gid" )
discordCID := flag . String ( "discord-cid" , lookupEnvOrString ( "DISCORD_CID" , "" ) , "DISCORD_CID, discord cid" )
2021-01-12 10:40:12 -05:00
discordCommand := flag . String ( "discord-command" , lookupEnvOrString ( "DISCORD_COMMAND" , "mumble-discord" ) , "DISCORD_COMMAND,Discord command string, env alt DISCORD_COMMAND, optional, defaults to mumble-discord" )
2021-01-16 14:04:52 -05:00
mode := flag . String ( "mode" , lookupEnvOrString ( "MODE" , "constant" ) , "MODE,determine which mode the bridge starts in" )
2021-01-12 10:40:12 -05:00
nice := flag . Bool ( "nice" , lookupEnvOrBool ( "NICE" , false ) , "NICE,whether the bridge should automatically try to 'nice' itself" )
2021-01-16 14:06:58 -05:00
cpuprofile := flag . String ( "cpuprofile" , "" , "write cpu profile to `file`" )
2020-10-29 02:21:07 -04:00
flag . Parse ( )
log . Printf ( "app.config %v\n" , getConfig ( flag . CommandLine ) )
if * mumbleAddr == "" {
log . Fatalln ( "missing mumble address" )
}
if * mumbleUsername == "" {
log . Fatalln ( "missing mumble username" )
}
if * discordToken == "" {
log . Fatalln ( "missing discord bot token" )
}
if * discordGID == "" {
log . Fatalln ( "missing discord gid" )
}
if * discordCID == "" {
log . Fatalln ( "missing discord cid" )
}
2021-01-05 12:16:51 -05:00
if * mode == "" {
log . Fatalln ( "missing mode set" )
2021-01-04 21:23:52 -05:00
}
2021-01-12 10:40:12 -05:00
if * nice {
err := syscall . Setpriority ( syscall . PRIO_PROCESS , os . Getpid ( ) , - 5 )
if err != nil {
log . Println ( "Unable to set priority. " , err )
}
2020-10-29 02:21:07 -04:00
}
2021-01-16 13:40:12 -05:00
if * cpuprofile != "" {
f , err := os . Create ( * cpuprofile )
if err != nil {
log . Fatal ( "could not create CPU profile: " , err )
}
defer f . Close ( ) // error handling omitted for example
if err := pprof . StartCPUProfile ( f ) ; err != nil {
log . Fatal ( "could not start CPU profile: " , err )
}
defer pprof . StopCPUProfile ( )
2020-10-29 02:21:07 -04:00
}
2021-01-05 20:21:08 -05:00
//Connect to discord
2020-10-29 02:21:07 -04:00
discord , err := discordgo . New ( "Bot " + * discordToken )
if err != nil {
log . Println ( err )
return
}
2020-11-04 01:12:43 -05:00
2021-01-05 12:16:51 -05:00
// Mumble setup
2020-11-04 01:12:43 -05:00
config := gumble . NewConfig ( )
config . Username = * mumbleUsername
config . Password = * mumblePassword
config . AudioInterval = time . Millisecond * 10
2021-01-05 13:16:03 -05:00
// Bridge setup
2021-01-05 20:25:38 -05:00
BridgeConf := & BridgeConfig {
2020-12-29 15:14:19 -05:00
Config : config ,
MumbleAddr : * mumbleAddr + ":" + strconv . Itoa ( * mumblePort ) ,
MumbleInsecure : * mumbleInsecure ,
2021-01-03 20:21:55 -05:00
MumbleChannel : * mumbleChannel ,
2021-01-03 15:32:59 -05:00
Command : * discordCommand ,
GID : * discordGID ,
CID : * discordCID ,
2020-11-28 03:46:21 -05:00
}
2021-01-05 20:25:38 -05:00
Bridge := & BridgeState {
2021-01-03 15:32:59 -05:00
ActiveConn : make ( chan bool ) ,
Connected : false ,
MumbleUserCount : 0 ,
DiscordUserCount : 0 ,
2021-01-05 11:41:33 -05:00
DiscordUsers : make ( map [ string ] bool ) ,
2021-01-06 19:12:56 -05:00
MumbleUsers : make ( map [ string ] bool ) ,
2021-01-03 15:32:59 -05:00
}
2021-01-06 19:12:56 -05:00
ul := & sync . Mutex { }
cl := & sync . Mutex { }
l := & Listener { BridgeConf , Bridge , ul , cl }
2020-11-28 03:46:21 -05:00
2021-01-05 20:21:08 -05:00
// Discord setup
// Open Websocket
2021-01-16 14:04:52 -05:00
discord . LogLevel = 1
2021-01-05 20:21:08 -05:00
discord . StateEnabled = true
discord . Identify . Intents = discordgo . MakeIntent ( discordgo . IntentsAllWithoutPrivileged )
2021-01-16 14:04:52 -05:00
discord . ShouldReconnectOnError = true
2021-01-05 20:21:08 -05:00
// register handlers
discord . AddHandler ( l . ready )
discord . AddHandler ( l . messageCreate )
discord . AddHandler ( l . guildCreate )
discord . AddHandler ( l . voiceUpdate )
err = discord . Open ( )
2021-01-06 19:12:56 -05:00
l . BridgeConf . Config . Attach ( gumbleutil . Listener {
Connect : l . mumbleConnect ,
UserChange : l . mumbleUserChange ,
} )
2020-11-04 01:12:43 -05:00
if err != nil {
log . Println ( err )
return
}
2021-01-05 20:21:08 -05:00
defer discord . Close ( )
2020-11-04 01:12:43 -05:00
2021-01-05 20:21:08 -05:00
log . Println ( "Discord Bot Connected" )
log . Printf ( "Discord bot looking for command !%v" , * discordCommand )
2021-01-05 12:16:51 -05:00
switch * mode {
case "auto" :
log . Println ( "bridge starting in automatic mode" )
2021-01-03 15:45:12 -05:00
Bridge . AutoChan = make ( chan bool )
2021-01-08 14:38:21 -05:00
Bridge . Mode = bridgeModeAuto
2021-01-05 20:21:08 -05:00
go AutoBridge ( discord , l )
2021-01-05 12:16:51 -05:00
case "manual" :
log . Println ( "bridge starting in manual mode" )
2021-01-08 14:38:21 -05:00
Bridge . Mode = bridgeModeManual
2021-01-05 12:16:51 -05:00
case "constant" :
log . Println ( "bridge starting in constant mode" )
2021-01-08 14:38:21 -05:00
Bridge . Mode = bridgeModeConstant
2021-01-05 19:43:55 -05:00
go startBridge ( discord , * discordGID , * discordCID , l , make ( chan bool ) )
2021-01-05 12:16:51 -05:00
default :
discord . Close ( )
log . Fatalln ( "invalid bridge mode set" )
2020-10-29 02:21:07 -04:00
}
2021-01-05 12:16:51 -05:00
2021-01-05 20:25:38 -05:00
go discordStatusUpdate ( discord , * mumbleAddr , strconv . Itoa ( * mumblePort ) , l )
2020-12-29 15:14:19 -05:00
sc := make ( chan os . Signal , 1 )
signal . Notify ( sc , syscall . SIGINT , syscall . SIGTERM , os . Interrupt , os . Kill )
<- sc
log . Println ( "Bot shutting down" )
2020-10-29 02:21:07 -04:00
}