diff --git a/irc/channel.go b/irc/channel.go index 1cf3db39..362178ad 100644 --- a/irc/channel.go +++ b/irc/channel.go @@ -23,6 +23,17 @@ type ChannelCommand interface { HandleChannel(channel *Channel) } +func IsChannel(target string) bool { + if target == "" { + return false + } + switch target[0] { + case '&', '#', '+', '!': + return true + } + return false +} + // NewChannel creates a new channel from a `Server` and a `name` // string, which must be unique on the server. func NewChannel(s *Server, name string) *Channel { @@ -106,6 +117,11 @@ func (channel *Channel) String() string { return channel.Id() } +// +func (channel *Channel) ModeString() string { + return "" +} + func (channel *Channel) Join(client *Client) { channel.members[client] = true client.channels[channel] = true diff --git a/irc/commands.go b/irc/commands.go index adea373c..11a9059e 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -348,11 +348,7 @@ func NewPrivMsgCommand(args []string) (EditableCommand, error) { } func (m *PrivMsgCommand) TargetIsChannel() bool { - switch m.target[0] { - case '&', '#', '+', '!': - return true - } - return false + return IsChannel(m.target) } // TOPIC [newtopic] @@ -428,11 +424,22 @@ func stringToRunes(str string) <-chan rune { return runes } -func NewModeCommand(args []string) (EditableCommand, error) { - if len(args) == 0 { - return nil, NotEnoughArgsError - } +type ChannelModeCommand struct { + BaseCommand + channel string +} +// MODE *( ( "-" / "+" ) * * ) +func NewChannelModeCommand(args []string) (EditableCommand, error) { + cmd := &ChannelModeCommand{ + channel: args[0], + } + // TODO implement channel mode changes + return cmd, nil +} + +// MODE *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) ) +func NewUserModeCommand(args []string) (EditableCommand, error) { cmd := &ModeCommand{ nickname: args[0], changes: make([]ModeChange, @@ -460,12 +467,25 @@ func NewModeCommand(args []string) (EditableCommand, error) { return cmd, nil } +func NewModeCommand(args []string) (EditableCommand, error) { + if len(args) == 0 { + return nil, NotEnoughArgsError + } + + if IsChannel(args[0]) { + return NewChannelModeCommand(args) + } else { + return NewUserModeCommand(args) + } +} + type WhoisCommand struct { BaseCommand target string masks []string } +// [ ] *( "," ) func NewWhoisCommand(args []string) (EditableCommand, error) { if len(args) < 1 { return nil, NotEnoughArgsError diff --git a/irc/reply.go b/irc/reply.go index ec1335ba..f17da108 100644 --- a/irc/reply.go +++ b/irc/reply.go @@ -234,6 +234,11 @@ func RplEndOfWhois(server *Server) Reply { return NewNumericReply(server, RPL_ENDOFWHOIS, ":End of WHOIS list") } +func RplChannelModeIs(server *Server, channel *Channel) Reply { + return NewNumericReply(server, RPL_CHANNELMODEIS, "%s %s", + channel.name, channel.ModeString()) +} + // errors (also numeric) func ErrAlreadyRegistered(source Identifier) Reply { @@ -261,8 +266,8 @@ func ErrNeedMoreParams(source Identifier, command string) Reply { "%s :Not enough parameters", command) } -func ErrNoSuchChannel(source Identifier, channel string) Reply { - return NewNumericReply(source, ERR_NOSUCHCHANNEL, +func ErrNoSuchChannel(server *Server, channel string) Reply { + return NewNumericReply(server, ERR_NOSUCHCHANNEL, "%s :No such channel", channel) } @@ -311,3 +316,8 @@ func ErrRestricted(server *Server) Reply { func ErrNoSuchServer(server *Server, target string) Reply { return NewNumericReply(server, ERR_NOSUCHSERVER, "%s :No such server", target) } + +func ErrUserNotInChannel(server *Server, nick string, channel *Channel) Reply { + return NewNumericReply(server, ERR_USERNOTINCHANNEL, + "%s %s :They aren't on that channel", nick, channel.name) +} diff --git a/irc/server.go b/irc/server.go index f0fd6067..21cdadff 100644 --- a/irc/server.go +++ b/irc/server.go @@ -299,3 +299,14 @@ func (m *WhoisCommand) HandleServer(server *Server) { } client.replies <- RplEndOfWhois(server) } + +func (msg *ChannelModeCommand) HandleServer(server *Server) { + client := msg.Client() + channel := server.channels[msg.channel] + if channel == nil { + client.replies <- ErrNoSuchChannel(server, msg.channel) + return + } + + client.replies <- RplChannelModeIs(server, channel) +}