From 624c6f3ed7f6231cf896fdc9b93e36a57f503127 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 29 Aug 2013 17:57:33 +0100 Subject: [PATCH] Added the /MODE command, but it's sloppy. --- client.go | 2 +- rosella.go | 11 ++++++ server.go | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index 52a88de..6d6619f 100644 --- a/client.go +++ b/client.go @@ -172,7 +172,7 @@ func (c *Client) reply(code replyCode, args ...string) { case rplOper: c.outputChan <- fmt.Sprintf(":%s 381 %s :You are now an operator", c.server.name, c.nick) case rplChannelModeIs: - c.outputChan <- fmt.Sprintf(":%s 324 %s %s %s", c.server.name, c.nick, args[0], args[1]) + c.outputChan <- fmt.Sprintf(":%s 324 %s %s %s %s", c.server.name, c.nick, args[0], args[1], args[2]) case errMoreArgs: c.outputChan <- fmt.Sprintf(":%s 461 %s :Not enough params", c.server.name, c.nick) case errNoNick: diff --git a/rosella.go b/rosella.go index de7f159..5c1ce3c 100644 --- a/rosella.go +++ b/rosella.go @@ -79,6 +79,17 @@ func (m *ClientMode) Prefix() string { } } +func (m *ClientMode) String() string { + modeStr := "" + if m.operator { + modeStr += "o" + } + if m.voice { + modeStr += "v" + } + return modeStr +} + type signalCode int const ( diff --git a/server.go b/server.go index bc36a52..19c36f9 100644 --- a/server.go +++ b/server.go @@ -171,8 +171,6 @@ func (s *Server) handleEvent(e Event) { for _, c := range channel.clientMap { if c != e.client { c.reply(rplMsg, e.client.nick, args[0], message) - e.client.reply(errCannotSend, args[0]) - return } } } else if clientExists { @@ -308,6 +306,113 @@ func (s *Server) handleEvent(e Event) { e.client.reply(errNoSuchNick, nick) } + case command == "MODE": + if e.client.registered == false { + e.client.reply(errNotReg) + return + } + + if len(args) < 1 { + e.client.reply(errMoreArgs) + return + } + + channelKey := strings.ToLower(args[0]) + + channel, channelExists := s.channelMap[channelKey] + if !channelExists { + e.client.reply(errNoSuchNick, args[0]) + return + } + mode := channel.mode + + if len(args) == 1 { + //No more args, they just want the mode + e.client.reply(rplChannelModeIs, args[0], mode.String(), "") + return + } + + if cm, ok := channel.modeMap[strings.ToLower(e.client.nick)]; !ok || !cm.operator { + //Not an operator + e.client.reply(errNoPriv) + return + } + + hasClient := false + var oldClientMode, newClientMode *ClientMode + var targetClient *Client + if len(args) >= 3 { + clientKey := strings.ToLower(args[2]) + oldClientMode, hasClient = channel.modeMap[clientKey] + if hasClient { + targetClient = channel.clientMap[clientKey] + newClientMode = new(ClientMode) + *newClientMode = *oldClientMode + } + } + + mod := strings.ToLower(args[1]) + if strings.HasPrefix(mod, "+") { + for _, char := range mod { + switch char { + case 'a': + mode.anonymous = true + case 's': + mode.secret = true + case 't': + mode.topicLocked = true + case 'm': + mode.moderated = true + case 'n': + mode.noExternal = true + case 'o': + if hasClient { + newClientMode.operator = true + } + case 'v': + if hasClient { + newClientMode.voice = true + } + } + } + } else if strings.HasPrefix(mod, "-") { + for _, char := range mod { + switch char { + case 'a': + mode.anonymous = false + case 's': + mode.secret = false + case 't': + mode.topicLocked = false + case 'm': + mode.moderated = false + case 'n': + mode.noExternal = false + case 'o': + if hasClient { + newClientMode.operator = false + } + case 'v': + if hasClient { + newClientMode.voice = false + } + } + } + } + + if hasClient { + *oldClientMode = *newClientMode + } + channel.mode = mode + + for _, client := range channel.clientMap { + if hasClient { + client.reply(rplChannelModeIs, args[0], args[1], targetClient.nick) + } else { + client.reply(rplChannelModeIs, args[0], args[1], "") + } + } + default: e.client.reply(errUnknownCommand, command) }