diff --git a/channel.go b/channel.go index 3f28eea..eb149f8 100644 --- a/channel.go +++ b/channel.go @@ -465,3 +465,30 @@ func (c *Channel) ListMessage(client *Client) (m *irc.Message) { } return } + +// Kick provides the capability for operators to kick members out of the channel +func (c *Channel) Kick(client *Client, kicked []string, message string) { + if !c.HasMember(client) { + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NOTONCHANNEL, Params: []string{client.Nickname, c.Name}, Trailing: "You're not on that channel"} + client.Encode(&m) + return + } + if !c.MemberHasMode(client, ChannelModeOperator) { + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_CHANOPRIVSNEEDED, Params: []string{client.Nickname, c.Name}, Trailing: "You're not channel operator"} + client.Encode(&m) + return + } + + for _, kickedName := range kicked { + kickedClient, ok := c.Server.GetClientByNick(kickedName) + if !ok { + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_USERNOTINCHANNEL, Params: []string{client.Nickname, kickedName, c.Name}, Trailing: "They aren't on that channel"} + client.Encode(&m) + return + } + m := irc.Message{Prefix: client.Prefix, Command: irc.KICK, Params: []string{c.Name, kickedName}, Trailing: message} + c.SendMessage(&m) + c.RemoveMember(kickedClient) + kickedClient.RemoveChannel(c) + } +} diff --git a/commands.go b/commands.go index 2a46a78..0d8642c 100644 --- a/commands.go +++ b/commands.go @@ -816,3 +816,44 @@ func ListHandler(message *irc.Message, client *Client) { m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_LISTEND, Params: []string{client.Nickname}, Trailing: "End of LIST"} client.Encode(&m) } + +// KickHandler is a specialized CommandHandler to respond to channel IRC KICK commands from a client +// Implemented according to RFC 1459 Section 4.2.8 and RFC 2812 Section 3.2.8 +func KickHandler(message *irc.Message, client *Client) { + if len(message.Params) == 0 { + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NEEDMOREPARAMS, Trailing: "Not enough parameters"} + client.Encode(&m) + return + } + channels := strings.Split(message.Params[0], ",") + nicks := strings.Split(message.Params[1], ",") + if len(channels) != 1 && len(channels) != len(nicks) { + //"For the message to be syntactically correct, there MUST be either one channel parameter and multiple user parameter, or as many channel parameters as there are user parameters." + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NEEDMOREPARAMS, Trailing: "Not enough parameters"} + client.Encode(&m) + return + } + comment := message.Trailing + if len(message.Params) == 3 { + comment = message.Params[2] + } + if len(channels) == 1 { + ch, ok := client.Server.GetChannel(channels[0]) + if ok { + ch.Kick(client, nicks, comment) + } else { + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NOSUCHCHANNEL, Params: []string{client.Nickname, channels[0]}, Trailing: "No such channel"} + client.Encode(&m) + } + return + } + for i, channel := range channels { + ch, ok := client.Server.GetChannel(channel) + if ok { + ch.Kick(client, []string{nicks[i]}, comment) + } else { + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NOSUCHCHANNEL, Params: []string{client.Nickname, channel}, Trailing: "No such channel"} + client.Encode(&m) + } + } +}