diff --git a/CHANGELOG.md b/CHANGELOG.md index d888f4e..3a8ecb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ Updates are listed in reverse chronological order. - a copy of each deleted message is now send via DM to the author (suggested by CommanderLook) - seasonal fluff - finally use gofmt +- better logging of own messages +- redirect function is much cleaner now +- commands can be limited to certain channels ### 1.3 - use global array of pointers to commands to allow easier modification and avoid unnecessary memcpy diff --git a/command.go b/command.go index 2f9a8b1..2e8b2b6 100644 --- a/command.go +++ b/command.go @@ -40,7 +40,8 @@ type Command struct { AdminOnly bool IgnoreCase bool // for custom commands that go beyond prints and deletions - Function func(*discordgo.Session, *discordgo.MessageCreate) + Function func(*discordgo.Session, *discordgo.MessageCreate) + AllowedChannels mapset.Set // allowed everywhere if blank UsersOnCooldown mapset.Set // don’t set this manually (it’s overwritten anyway) } @@ -114,10 +115,7 @@ func evaluateMessage(s *discordgo.Session, m *discordgo.MessageCreate) { Sets command cooldowns if necessary and also clears them again. */ func executeCommand(session *discordgo.Session, message *discordgo.MessageCreate, command *Command) { - if isAdmin(message.Author) || // no restrictions for admins - (!command.AdminOnly && (isDM(session, message) || !command.UsersOnCooldown.Contains(message.Author.ID)) && - (!command.DMOnly || isDM(session, message))) { - + if commandAllowed(session, message, command) { log.Printf("Executed command %s triggered by user %s", command.Trigger, userToString(message.Author)) if command.Cooldown > 0 && !isDM(session, message) && !isAdmin(message.Author) { command.UsersOnCooldown.Add(message.Author.ID) @@ -143,6 +141,35 @@ func executeCommand(session *discordgo.Session, message *discordgo.MessageCreate } } +/* + * Check if a user has the permission to trigger a given command. + * To be honest, this whole logic is a mess, but I don’t know a better way to handle it. + */ +func commandAllowed(session *discordgo.Session, message *discordgo.MessageCreate, command *Command) bool { + // no restrictions for admins + if isAdmin(message.Author) { + return true + } + // blacklist admin commands for everyone else + if command.AdminOnly { + return false + } + // cooldowns are irrelevant in DMs + if !isDM(session, message) && command.UsersOnCooldown.Contains(message.Author.ID) { + return false + } + // the command is not limited to DMs or we are inside a DM chat + if command.DMOnly && !isDM(session, message) { + return false + } + // no allowed channels = all channels are allowed. + // DMs are whitelisted by default + if command.AllowedChannels.Cardinality() != 0 && !command.AllowedChannels.Contains(message.ChannelID) && !isDM(session, message) { + return false + } + return true +} + func removeCooldown(command *Command, uid string) { time.Sleep(time.Duration(command.Cooldown) * time.Second) if command.UsersOnCooldown.Contains(uid) {