diff --git a/downstream.go b/downstream.go index 72445ff..df5ffeb 100644 --- a/downstream.go +++ b/downstream.go @@ -246,6 +246,52 @@ func (c *downstreamConn) handleMessageRegistered(msg *irc.Message) error { c.user.forEachUpstream(func(uc *upstreamConn) { uc.messages <- msg }) + case "MODE": + var name string + if err := parseMessageParams(msg, &name); err != nil { + return err + } + + var modeStr string + if len(msg.Params) > 1 { + modeStr = msg.Params[1] + } + + if msg.Prefix.Name != name { + ch, err := c.user.getChannel(name) + if err != nil { + return err + } + + if modeStr != "" { + ch.conn.messages <- msg + } else { + c.messages <- &irc.Message{ + Prefix: c.srv.prefix(), + Command: irc.RPL_CHANNELMODEIS, + Params: []string{ch.Name, string(ch.modes)}, + } + } + } else { + if name != c.nick { + return ircError{&irc.Message{ + Command: irc.ERR_USERSDONTMATCH, + Params: []string{c.nick, "Cannot change mode for other users"}, + }} + } + + if modeStr != "" { + c.user.forEachUpstream(func(uc *upstreamConn) { + uc.messages <- msg + }) + } else { + c.messages <- &irc.Message{ + Prefix: c.srv.prefix(), + Command: irc.RPL_UMODEIS, + Params: []string{""}, // TODO + } + } + } default: c.logger.Printf("unhandled message: %v", msg) return newUnknownCommandError(msg.Command) diff --git a/server.go b/server.go index c57102a..ef5d4e5 100644 --- a/server.go +++ b/server.go @@ -59,6 +59,27 @@ func (u *user) forEachDownstream(f func(dc *downstreamConn)) { u.lock.Unlock() } +func (u *user) getChannel(name string) (*upstreamChannel, error) { + var channel *upstreamChannel + var err error + u.forEachUpstream(func(uc *upstreamConn) { + if err != nil { + return + } + if ch, ok := uc.channels[name]; ok { + if channel != nil { + err = fmt.Errorf("ambiguous channel name %q", name) + } else { + channel = ch + } + } + }) + if channel == nil { + return nil, fmt.Errorf("unknown channel %q", name) + } + return channel, nil +} + type Upstream struct { Addr string Nick string diff --git a/upstream.go b/upstream.go index 6c6a9a1..5c17b1a 100644 --- a/upstream.go +++ b/upstream.go @@ -14,6 +14,7 @@ import ( type upstreamChannel struct { Name string + conn *upstreamConn Topic string TopicWho string TopicTime time.Time @@ -126,11 +127,11 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error { if err := ch.modes.Apply(modeStr); err != nil { return err } - - c.user.forEachDownstream(func(dc *downstreamConn) { - dc.messages <- msg - }) } + + c.user.forEachDownstream(func(dc *downstreamConn) { + dc.messages <- msg + }) case "NOTICE": c.logger.Print(msg) case irc.RPL_WELCOME: @@ -182,6 +183,7 @@ func (c *upstreamConn) handleMessage(msg *irc.Message) error { c.logger.Printf("joined channel %q", ch) c.channels[ch] = &upstreamChannel{ Name: ch, + conn: c, Members: make(map[string]membership), } } else {