diff --git a/README.md b/README.md index 37ae3f6..b722be2 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ The config file is a yaml formatted file with the following fields: | `separator` | No | `_` | Yes | used in fallback situations. If set to `-`, the **fallback name** will be like `bob-7247_d2` (where `7247` is the discord user's discriminator, and `_d2` is the suffix) | | `irc_listener_name` | Yes | `~d` | The name of the irc listener | | | `ignored_discord_ids` | Sometimes | | Yes | A list of Discord IDs to not relay to IRC | +| `allowed_discord_ids` | Sometimes | `null` | Yes | A list of Discord IDs to relay to IRC. `null` allows all Discord users to be relayed to IRC | | `puppet_username` | No | username of discord account being puppeted | Yes | username to connect to irc with | | `webirc_pass` | No | | Yes | optional, but recommended for regular (non-simple) usage. this must be obtained by the IRC sysops | | `irc_listener_prejoin_commands` | Yes | | Yes | list of commands for the listener IRC connection to execute (right before joining channels) | diff --git a/bridge/bridge.go b/bridge/bridge.go index e637e9f..5049927 100644 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -31,6 +31,7 @@ type Config struct { PuppetUsername string // Username to connect to IRC with IRCIgnores []glob.Glob DiscordIgnores map[string]struct{} // Discord user IDs to not bridge + DiscordAllowed map[string]struct{} // Discord user IDs to only bridge ConnectionLimit int // number of IRC connections we can spawn IRCPuppetPrejoinCommands []string diff --git a/bridge/irc_manager.go b/bridge/irc_manager.go index 6d5b5a1..696bef9 100644 --- a/bridge/irc_manager.go +++ b/bridge/irc_manager.go @@ -142,6 +142,15 @@ func (m *IRCManager) HandleUser(user DiscordUser) { if m.ircIgnoredDiscord(user.ID) { return } + + // If we have an allowed list of users at all + if allowed := m.bridge.Config.DiscordAllowed; allowed != nil { + // Short-circuit if they aren't in the list + if _, ok := allowed[user.ID]; !ok { + return + } + } + // Does the user exist on the IRC side? if con, ok := m.ircConnections[user.ID]; ok { // Close the connection if they are not diff --git a/config.yml b/config.yml index f8d823b..36683c2 100644 --- a/config.yml +++ b/config.yml @@ -12,10 +12,6 @@ channel_mappings: "#bottest chanKey": 316038111811600387 "#bottest2": 318327329044561920 -# Prevent MEE6 from appearing on IRC -# ignored_discord_ids: -# - 159985870458322944 - suffix: "_d2" separator: "_" irc_listener_name: "_d2" @@ -49,3 +45,11 @@ irc_puppet_prejoin_commands: # This limits to 2 connections (a listener, and one puppet, the rest relayed in simple mode) # connection_limit: 2 + +# Prevent MEE6 from appearing on IRC +# ignored_discord_ids: +# - 159985870458322944 + +# Only allow specific Discord users to appear on IRC +# allowed_discord_ids: +# - 159985870458322944 # Only allow Mee6! diff --git a/main.go b/main.go index a89eda8..255d867 100644 --- a/main.go +++ b/main.go @@ -81,9 +81,10 @@ func main() { webIRCPass := viper.GetString("webirc_pass") // Password for WEBIRC ircIgnores := viper.GetStringSlice("ignored_irc_hostmasks") // IRC hosts to not relay to Discord rawDiscordIgnores := viper.GetStringSlice("ignored_discord_ids") // Ignore these Discord users on IRC - rawIRCFilter := viper.GetStringSlice("irc_message_filter") // Ignore lines containing matched text from IRC - rawDiscordFilter := viper.GetStringSlice("discord_message_filter") // Ignore lines containing matched text from Discord - connectionLimit := viper.GetInt("connection_limit") // Limiter on how many IRC Connections we can spawn + rawDiscordAllowed := viper.GetStringSlice("allowed_discord_ids") + rawIRCFilter := viper.GetStringSlice("irc_message_filter") // Ignore lines containing matched text from IRC + rawDiscordFilter := viper.GetStringSlice("discord_message_filter") // Ignore lines containing matched text from Discord + connectionLimit := viper.GetInt("connection_limit") // Limiter on how many IRC Connections we can spawn // if !*debugMode { *debugMode = viper.GetBool("debug") @@ -137,9 +138,11 @@ func main() { ircFilter := setupFilter(rawIRCFilter) SetLogDebug(*debugMode) - discordIgnores := make(map[string]struct{}, len(rawDiscordIgnores)) - for _, nick := range rawDiscordIgnores { - discordIgnores[nick] = struct{}{} + // Check for nil, as nil means we don't use this list + var discordAllowed map[string]struct{} + if rawDiscordAllowed != nil { + log.Println("allowed_discord_ids is set, so only specific Discord users will be bridged") + discordAllowed = stringSliceToMap(rawDiscordAllowed) } dib, err := bridge.New(&bridge.Config{ @@ -155,7 +158,8 @@ func main() { ConnectionLimit: connectionLimit, IRCIgnores: matchers, IRCFilteredMessages: ircFilter, - DiscordIgnores: discordIgnores, + DiscordIgnores: stringSliceToMap(rawDiscordIgnores), + DiscordAllowed: discordAllowed, DiscordFilteredMessages: discordFilter, PuppetUsername: puppetUsername, WebIRCPass: webIRCPass, @@ -224,11 +228,14 @@ func main() { } rawDiscordIgnores := viper.GetStringSlice("ignored_discord_ids") - discordIgnores := make(map[string]struct{}, len(rawDiscordIgnores)) - for _, nick := range rawDiscordIgnores { - discordIgnores[nick] = struct{}{} + dib.Config.DiscordIgnores = stringSliceToMap(rawDiscordIgnores) + + rawDiscordAllowed := viper.GetStringSlice("allowed_discord_ids") + if rawDiscordAllowed == nil { + dib.Config.DiscordAllowed = nil + } else { + dib.Config.DiscordAllowed = stringSliceToMap(rawDiscordAllowed) } - dib.Config.DiscordIgnores = discordIgnores chans := viper.GetStringMapString("channel_mappings") equalChans := reflect.DeepEqual(chans, channelMappings) @@ -255,6 +262,14 @@ func main() { dib.Close() } +func stringSliceToMap(list []string) map[string]struct{} { + m := make(map[string]struct{}, len(list)) + for _, v := range list { + m[v] = struct{}{} + } + return m +} + func setupHostmaskMatchers(hostmasks []string) []glob.Glob { var matchers []glob.Glob for _, mask := range hostmasks {