2020-10-29 02:21:07 -04:00
package main
import (
"flag"
2021-01-19 01:06:08 -05:00
"fmt"
2020-10-29 02:21:07 -04:00
"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-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-19 01:06:08 -05:00
var err error
fmt . Println ( "Mumble-Discord-Bridge" )
fmt . Println ( "v" + version + " " + commit + " " + date )
2021-01-09 18:18:31 -05:00
2020-10-29 02:21:07 -04:00
godotenv . Load ( )
2021-01-19 01:06:08 -05:00
mumbleAddr := flag . String ( "mumble-address" , lookupEnvOrString ( "MUMBLE_ADDRESS" , "" ) , "MUMBLE_ADDRESS, mumble server address, example example.com, required" )
mumblePort := flag . Int ( "mumble-port" , lookupEnvOrInt ( "MUMBLE_PORT" , 64738 ) , "MUMBLE_PORT, mumble port, (default 64738)" )
mumbleUsername := flag . String ( "mumble-username" , lookupEnvOrString ( "MUMBLE_USERNAME" , "Discord" ) , "MUMBLE_USERNAME, mumble username, (default: discord)" )
2020-10-29 02:21:07 -04:00
mumblePassword := flag . String ( "mumble-password" , lookupEnvOrString ( "MUMBLE_PASSWORD" , "" ) , "MUMBLE_PASSWORD, mumble password, optional" )
2021-01-19 01:06:08 -05:00
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" )
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" )
discordCID := flag . String ( "discord-cid" , lookupEnvOrString ( "DISCORD_CID" , "" ) , "DISCORD_CID, discord cid, required" )
discordCommand := flag . String ( "discord-command" , lookupEnvOrString ( "DISCORD_COMMAND" , "mumble-discord" ) , "DISCORD_COMMAND, Discord command string, env alt DISCORD_COMMAND, optional, (defaults mumble-discord)" )
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)" )
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-19 01:06:08 -05:00
// Optional CPU Profiling
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-19 01:06:08 -05:00
// BRIDGE SETUP
Bridge := & BridgeState {
BridgeConfig : & BridgeConfig {
// MumbleConfig: config,
MumbleAddr : * mumbleAddr + ":" + strconv . Itoa ( * mumblePort ) ,
MumbleInsecure : * mumbleInsecure ,
MumbleChannel : * mumbleChannel ,
MumbleDisableText : * mumbleDisableText ,
Command : * discordCommand ,
GID : * discordGID ,
CID : * discordCID ,
DiscordDisableText : * discordDisableText ,
} ,
Connected : false ,
DiscordUsers : make ( map [ string ] discordUser ) ,
MumbleUsers : make ( map [ string ] bool ) ,
}
// MUMBLE SETUP
MumbleConfig := gumble . NewConfig ( )
Bridge . BridgeConfig . MumbleConfig = MumbleConfig
MumbleConfig . Username = * mumbleUsername
MumbleConfig . Password = * mumblePassword
MumbleConfig . AudioInterval = time . Millisecond * 10
Bridge . MumbleListener = & MumbleListener {
Bridge : Bridge ,
}
MumbleConfig . Attach ( gumbleutil . Listener {
Connect : Bridge . MumbleListener . mumbleConnect ,
UserChange : Bridge . MumbleListener . mumbleUserChange ,
} )
// DISCORD SETUP
2021-01-05 20:21:08 -05:00
//Connect to discord
2021-01-19 01:06:08 -05:00
Bridge . DiscordSession , err = discordgo . New ( "Bot " + * discordToken )
2020-10-29 02:21:07 -04:00
if err != nil {
log . Println ( err )
return
}
2020-11-04 01:12:43 -05:00
2021-01-19 01:06:08 -05:00
Bridge . DiscordSession . LogLevel = 1
Bridge . DiscordSession . StateEnabled = true
Bridge . DiscordSession . Identify . Intents = discordgo . MakeIntent ( discordgo . IntentsAllWithoutPrivileged )
Bridge . DiscordSession . ShouldReconnectOnError = true
2021-01-05 20:21:08 -05:00
// register handlers
2021-01-19 01:06:08 -05:00
Bridge . DiscordListener = & DiscordListener {
Bridge : Bridge ,
}
Bridge . DiscordSession . AddHandler ( Bridge . DiscordListener . ready )
Bridge . DiscordSession . AddHandler ( Bridge . DiscordListener . messageCreate )
Bridge . DiscordSession . AddHandler ( Bridge . DiscordListener . guildCreate )
Bridge . DiscordSession . AddHandler ( Bridge . DiscordListener . voiceUpdate )
// Open Discord websocket
err = Bridge . DiscordSession . Open ( )
2020-11-04 01:12:43 -05:00
if err != nil {
log . Println ( err )
return
}
2021-01-19 01:06:08 -05:00
defer Bridge . DiscordSession . 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-19 01:06:08 -05:00
Bridge . AutoChanDie = make ( chan bool )
2021-01-08 14:38:21 -05:00
Bridge . Mode = bridgeModeAuto
2021-01-19 01:06:08 -05:00
go Bridge . AutoBridge ( )
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-19 01:06:08 -05:00
go Bridge . startBridge ( )
2021-01-05 12:16:51 -05:00
default :
2021-01-19 01:06:08 -05:00
Bridge . DiscordSession . Close ( )
2021-01-05 12:16:51 -05:00
log . Fatalln ( "invalid bridge mode set" )
2020-10-29 02:21:07 -04:00
}
2021-01-05 12:16:51 -05:00
2021-01-19 01:06:08 -05:00
go Bridge . discordStatusUpdate ( )
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
}