From 72875efb8964194101dd94e2c2646b63357c1ac7 Mon Sep 17 00:00:00 2001 From: Justin Date: Sat, 8 Aug 2015 10:57:25 -0700 Subject: [PATCH] Added support for IRC LIST command --- channel.go | 16 ++++++++++++++ commands.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/channel.go b/channel.go index d54fac6..3f28eea 100644 --- a/channel.go +++ b/channel.go @@ -1,6 +1,7 @@ package irc import ( + "strconv" "strings" "sync" @@ -350,6 +351,7 @@ func (c *Channel) TopicCommand(client *Client, topic string) { //Client is trying to get topic if len(topic) == 0 { //Get channels topic + if len(c.Topic) == 0 { // No topic is not set m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_NOTOPIC, Params: []string{c.Name}, Trailing: "No topic is set"} client.Encode(&m) @@ -449,3 +451,17 @@ func (c *Channel) GetLimit() int { return val.(int) } + +// ListMessage creates and returns the message that should be sent for an IRC LIST query +func (c *Channel) ListMessage(client *Client) (m *irc.Message) { + + if c.HasMode(ChannelModeSecret) && !c.HasMember(client) { // If channel is secret and client isn't a member, don't reveal it + return + } + m = &irc.Message{Prefix: c.Server.Prefix, Command: irc.RPL_LIST, Params: []string{client.Nickname, c.Name, strconv.Itoa(c.GetMemberCount())}, Trailing: c.Topic + " "} + if c.HasMode(ChannelModePrivate) && !c.HasMember(client) { // If channel is private and client isn't a member, don't return topic + m.Trailing = " " + return + } + return +} diff --git a/commands.go b/commands.go index 0502c8f..4a9333f 100644 --- a/commands.go +++ b/commands.go @@ -359,7 +359,7 @@ func TopicHandler(message *irc.Message, client *Client) { channelName := message.Params[0] channel, ok := client.Server.GetChannel(channelName) - if !ok { + if !ok || channel.HasMode(ChannelModeSecret) { m := irc.Message{Prefix: client.Server.Prefix, Command: irc.ERR_NOSUCHCHANNEL, Params: []string{client.Nickname, channelName}, Trailing: "No such channel"} client.Encode(&m) return @@ -625,6 +625,29 @@ func ChannelModeHandler(message *irc.Message, client *Client) { if modifier == ModeModifierAdd { needsArgs = append(needsArgs, fullFlag{modifier, flag, ""}) } + default: + found := channel.HasMode(flag) + if modifier == ModeModifierAdd { + + if !found { + if flag == ChannelModePrivate && channel.HasMode(ChannelModeSecret) { + // Secret and private can't both be set + continue + } + if flag == ChannelModeSecret && channel.HasMode(ChannelModePrivate) { + // Secret and private can't both be set + channel.RemoveMode(ChannelModePrivate) + } + channel.AddMode(flag) + changes = append(changes, fullFlag{modifier, flag, ""}) + } + + } else { + if found { + channel.RemoveMode(flag) + changes = append(changes, fullFlag{modifier, flag, ""}) + } + } } } @@ -678,3 +701,39 @@ func NamesHandler(message *irc.Message, client *Client) { func MOTDHandler(message *irc.Message, client *Client) { client.MOTD() } + +// ListHandler is a specialized CommandHandler to respond to channel IRC LIST commands from a client +// Implemented according to RFC 1459 Section 4.2.6 and RFC 2812 Section 3.2.6 +func ListHandler(message *irc.Message, client *Client) { + + /* Deprecated in RFC 2812 + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_LISTSTART, Params: []string{client.Nickname, "Channel :Users Name"}} + client.Encode(&m) + */ + + if len(message.Params) == 0 || len(message.Params[0]) == 0 { // Send LIST response for all channels + for _, ch := range client.Server.channels { + m := ch.ListMessage(client) + if m != nil { + fmt.Println(m.String()) + client.Encode(m) + } + + } + } else { + channelNames := strings.Split(message.Params[0], ",") + for _, channelName := range channelNames { + ch, ok := client.Server.GetChannel(channelName) + if ok { + m := ch.ListMessage(client) + if m != nil { + fmt.Println(m.String()) + client.Encode(m) + } + } + + } + } + m := irc.Message{Prefix: client.Server.Prefix, Command: irc.RPL_LISTEND, Params: []string{client.Nickname}, Trailing: "End of LIST"} + client.Encode(&m) +}