diff --git a/cmd-op.go b/cmd-op.go index fecca56..ce14f11 100644 --- a/cmd-op.go +++ b/cmd-op.go @@ -160,17 +160,25 @@ func unban(conn *irc.Conn, nick *irc.Nick, args, target string) { return } + ch := conn.GetChannel(channel) + if ch == nil { + say(conn, target , "%s: Unable to get channel information about %s", nick.Nick, channel) + return + } bans := strings.TrimSpace(args) split := strings.Fields(bans) for i, ban := range(split) { if strings.Index(ban, "@") != -1 { + // it's already a host, do nothing continue } - n := conn.GetNick(ban) - if n == nil { - continue + if b, ok := ch.Bans[ban]; ok { + // we've seen this nick banned before + split[i] = b + } else if n := conn.GetNick(ban); n != nil { + // the user is in one of our channels, here's our best guess + split[i] = "*!*@" + n.Host } - split[i] = "*!*@" + n.Host } bans = strings.Join(split, " ") modestring := "-" + strings.Repeat("b", len(bans)) + " " + bans diff --git a/irc/handlers.go b/irc/handlers.go index cc84c9a..5166de1 100644 --- a/irc/handlers.go +++ b/irc/handlers.go @@ -288,6 +288,22 @@ func (conn *Conn) setupEvents() { } else { conn.error("irc.MODE(): buh? not enough arguments to process MODE %s %s%s", ch.Name, modestr, m) } + case 'b': + if len(modeargs) != 0 { + // we only care about host bans + if modeop && strings.HasPrefix(modeargs[0], "*!*@") { + for n, _ := range ch.Nicks { + if modeargs[0][4:] == n.Host { + ch.AddBan(n.Nick, modeargs[0]) + } + } + } else if !modeop { + ch.DeleteBan(modeargs[0]) + } + modeargs = modeargs[1:len(modeargs)] + } else { + conn.error("irc.MODE(): buh? not enough arguments to process MODE %s %s%s", ch.Name, modestr, m) + } } } } else if n := conn.GetNick(line.Args[0]); n != nil { diff --git a/irc/nickchan.go b/irc/nickchan.go index a050373..27fdca2 100644 --- a/irc/nickchan.go +++ b/irc/nickchan.go @@ -13,6 +13,7 @@ type Channel struct { Name, Topic string Modes *ChanMode Nicks map[*Nick]*ChanPrivs + Bans map[string]string conn *Conn } @@ -103,6 +104,7 @@ func (conn *Conn) GetChannel(c string) *Channel { func (ch *Channel) initialise() { ch.Modes = new(ChanMode) ch.Nicks = make(map[*Nick]*ChanPrivs) + ch.Bans = make(map[string]string) } // Associates an *irc.Nick with an *irc.Channel using a shared *irc.ChanPrivs @@ -132,6 +134,18 @@ func (ch *Channel) DelNick(n *Nick) { // consistency, and this would mean spewing an error message every delete } +func (ch *Channel) AddBan(nick, ban string) { + ch.Bans[nick] = ban +} + +func (ch *Channel) DeleteBan(ban string) { + for n, b := range ch.Bans { + if b == ban { + ch.Bans[n] = "", false // see go issue 1249 + } + } +} + // Stops the channel from being tracked by state tracking handlers. Also calls // n.DelChannel(ch) for all nicks that are associated with the channel. func (ch *Channel) Delete() {