package main import ( "flag" "fmt" "github.com/gorcon/rcon" "log" "os" "os/signal" "slices" "syscall" "github.com/bwmarrin/discordgo" ) // Variables used for command line parameters var ( Token string MemberRole string GuildID string RCONServer string RCONPassword string ) // Command vairables var ( commands = []*discordgo.ApplicationCommand{ { Name: "welcome", Description: "Welcome a new member to the Server, giving them full membership permission.", Options: []*discordgo.ApplicationCommandOption{ { Name: "user", Description: "User to welcome as a new member.", Type: discordgo.ApplicationCommandOptionUser, Required: true, }, }, }, { Name: "whitelist", Description: "Whitelist a user on the minecraft server.", Options: []*discordgo.ApplicationCommandOption{ { Name: "username", Description: "Username to whitelist", Type: discordgo.ApplicationCommandOptionString, Required: true, }, { Name: "bedrock", Description: "Is this a bedrock user?", Type: discordgo.ApplicationCommandOptionBoolean, Required: false, }, }, }, } commandHandlers = map[string]func(s *discordgo.Session, i *discordgo.InteractionCreate){ "welcome": func(s *discordgo.Session, i *discordgo.InteractionCreate) { caller, _ := s.GuildMember(i.GuildID, i.Member.User.ID) // check if the user is a member if !slices.Contains(caller.Roles, MemberRole) { s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "Only Members are allowed to run this command", }, }) return } options := i.ApplicationCommandData().Options new := options[0].UserValue(s) s.GuildMemberRoleAdd(i.GuildID, new.ID, MemberRole) s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: fmt.Sprintf("Welcome %s, you are now a member!", new.Mention()), }, }) }, "whitelist": func(s *discordgo.Session, i *discordgo.InteractionCreate) { caller, err := s.GuildMember(i.GuildID, i.Member.User.ID) // check if the user is a member if !slices.Contains(caller.Roles, MemberRole) { s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "Only Members are allowed to run this command", }, }) return } opts := i.ApplicationCommandData().Options name := opts[0].StringValue() bedrock := false if len(opts) > 1 { bedrock = opts[1].BoolValue() } con, err := rcon.Dial(RCONServer, RCONPassword) if err != nil { log.Printf("Could not connect to RCON server") s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "Failed to whitelist, server may be down?", }, }) return } err = nil if bedrock { _, err = con.Execute(fmt.Sprintf("fwhitelist add %s", name)) } else { _, err = con.Execute(fmt.Sprintf("whitelist add %s", name)) } con.Close() if err != nil { s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: "Ups! Something went wrong!", }, }) return } log.Printf("Whitelisted %s, on behalf of %s.", name, i.Member.User.ID) s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: fmt.Sprintf("`%s` should now be whitelisted!", name), }, }) }, } ) // parse CLI arguments func init() { flag.StringVar(&Token, "t", "", "Bot Token") flag.StringVar(&MemberRole, "r", "", "ID of the member role") flag.StringVar(&GuildID, "g", "", "Id of the Guild") flag.StringVar(&RCONServer, "rs", "", "RCON server to connect to") flag.StringVar(&RCONPassword, "rp", "", "Password for the RCON server") flag.Parse() } func main() { bot, err := discordgo.New("Bot " + Token) if err != nil { log.Panicf("Could not create bot!") } bot.AddHandler(func(s *discordgo.Session, i *discordgo.InteractionCreate) { if h, ok := commandHandlers[i.ApplicationCommandData().Name]; ok { h(s, i) } }) // Open a websocket connection to Discord and begin listening. err = bot.Open() if err != nil { log.Panicf("Error connecting to discord: %s", err) return } log.Println("Adding commands...") registeredCommands := make([]*discordgo.ApplicationCommand, len(commands)) for i, v := range commands { cmd, err := bot.ApplicationCommandCreate(bot.State.User.ID, GuildID, v) if err != nil { log.Panicf("Cannot create '%v' command: %v", v.Name, err) } registeredCommands[i] = cmd } log.Println("Bot is now running. Press CTRL-C to exit.") sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) <-sc log.Println("Exiting") err = bot.Close() if err != nil { log.Printf("Failed to shut down gracefully! %s", err) } }