diff --git a/README.md b/README.md index 3ea3af4..f97a73e 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,11 @@ rbot.conf and auth.conf will be copied. Configure those and then run the bot: ### Flags -Access is configured in auth.conf, is per-channel, based on ident and host; nick is ignored. The owner is configured per server and other access is configured per channel. Owners can use any commands. +Access is configured in auth.conf, is per-channel, based on ident and host; nick is ignored. The owner is configured per server and other access is configured per channel. Owners can use any commands. Ignores are checked before access. The following is a description of the commands enabled by each flag: -- `a`: add remove +- `a`: add remove ignore unignore - `o`: op halfop deop dehalfop kick|k ban|b unban|u kb - `h`: halfop|hop dehalfop|dehop kick|k ban|b unban|u kb (hop and dehop can only be used on yourself and you cannot kick or kb people with o or h) - `v`: voice, devoice @@ -43,6 +43,8 @@ Access related commands: - `add raylu t`: gives raylu the t flag - `remove raylu t`: removes the t flag from raylu - `remove raylu`: removes all of raylu's flags +- `ignore raylu`: ignores all messages from raylu's host on this network +- `unignore raylu`: unignore raylu - `list`: lists all users and their access - `list raylu`: searches the access list for raylu diff --git a/auth.go b/auth.go index 12ebe93..e322651 100644 --- a/auth.go +++ b/auth.go @@ -10,13 +10,38 @@ import ( const authFile = "auth.conf" var auth *config.Config +var ignores map[string]map[string]bool //network -> host -> true func readAuth() { var err os.Error auth, err = config.ReadDefault(authFile) - if (err != nil) { + if err != nil { panic(fmt.Sprintf("Auth config error: %s", err)) } + + if ignores == nil { + ignores = make(map[string]map[string]bool) + // parse ignores + for _, s := range auth.Sections() { + if strings.Index(s ," ") > -1 { + // this is a channel + continue + } + hosts, err := auth.Options(s) + if err != nil { + panic(fmt.Sprintf("Ignore config error in %s: %s", s, err)) + } + if ignores[s] == nil { + ignores[s] = make(map[string]bool) + } + for _, h := range hosts { + if h == "owner" { + continue + } + ignores[s][h] = true + } + } + } } func user(nick *irc.Nick) string { @@ -55,7 +80,6 @@ func addAccess(conn *irc.Conn, channel, nick, flags string) (string, string) { return user, nflags } - func removeAccess(conn *irc.Conn, channel, nick, flags string) (string, string) { n := conn.GetNick(nick) if n == nil { @@ -81,7 +105,6 @@ func removeAccess(conn *irc.Conn, channel, nick, flags string) (string, string) return user, nflags } - func removeUser(conn *irc.Conn, channel, nick string) (string, bool) { n := conn.GetNick(nick) if n == nil { @@ -117,6 +140,36 @@ func hasAccess(conn *irc.Conn, nick *irc.Nick, channel, flag string) bool { return false } +func addIgnore(conn *irc.Conn, channel string, n *irc.Nick) bool { + if ignores[conn.Network][n.Host] { + return false + } + ignores[conn.Network][n.Host] = true + auth.AddOption(conn.Network, n.Host, "z") + if updateAuth() != nil { + say(conn, channel, "Error while writing to %s", authFile) + } + + return true +} +func removeIgnore(conn *irc.Conn, channel, nick string) (string, bool) { + n := conn.GetNick(nick) + if n == nil { + return "", false + } + + if _, ok := ignores[conn.Network][n.Host]; !ok { + return n.Host, false + } + ignores[conn.Network][n.Host] = false, false + auth.RemoveOption(conn.Network, n.Host) + if updateAuth() != nil { + say(conn, channel, "Error while writing to %s", authFile) + } + + return n.Host, true +} + func updateAuth() os.Error { if err := auth.WriteFile(authFile, 0644, ""); err != nil { return err diff --git a/cmd-access.go b/cmd-access.go index fdb8b5e..6b5f4c1 100644 --- a/cmd-access.go +++ b/cmd-access.go @@ -77,6 +77,46 @@ func flags(conn *irc.Conn, nick *irc.Nick, args, target string) { } } +func ignore(conn *irc.Conn, nick *irc.Nick, args, target string) { + channel, args := parseAccess(conn, nick, target, args, "a") + if channel == "" { + return + } + + n := conn.GetNick(strings.TrimSpace(args)) + if n == nil { + say(conn, target, "Could not find nick %s", args) + return + } + if nick == n { + say(conn, target, "%s: you cannot ignore yourself", nick.Nick) + } + owner, _ := auth.String(conn.Network, "owner") + if owner == user(n) { + return + } + + if addIgnore(conn, channel, n) { + say(conn, target, "Ignoring %s", n.Host) + } else { + say(conn, target, "%s is already ignored", n.Host) + } +} +func unignore(conn *irc.Conn, nick *irc.Nick, args, target string) { + channel, args := parseAccess(conn, nick, target, args, "a") + if channel == "" { + return + } + host, success := removeIgnore(conn, channel, strings.TrimSpace(args)) + if host == "" { + say(conn, target, "Could not find nick %s", args) + } else if !success { + say(conn, target, "%s was not ignored", host) + } else { + say(conn, target, "Unignored %s", host) + } +} + func accesslist(conn *irc.Conn, nick *irc.Nick, args, target string) { channel, args := parseAccess(conn, nick, target, args, "") if channel == "" { diff --git a/handler.go b/handler.go index e864976..45d3427 100644 --- a/handler.go +++ b/handler.go @@ -14,6 +14,8 @@ var commands = map [string]func(*irc.Conn, *irc.Nick, string, string) { "flags": flags, "add": add, "remove": remove, + "ignore": ignore, + "unignore": unignore, "list": accesslist, // admin @@ -52,6 +54,9 @@ func handlePrivmsg(conn *irc.Conn, line *irc.Line) { return } nick.Host = line.Host + if ignores[conn.Network][nick.Host] { + return + } target := line.Args[0] if isChannel(target) {