diff --git a/irc/channel.go b/irc/channel.go index 809a0df8..604e87f4 100644 --- a/irc/channel.go +++ b/irc/channel.go @@ -55,11 +55,13 @@ func (channel *Channel) Destroy() error { return nil } -func (channel *Channel) Reply(reply Reply) error { +func (channel *Channel) Reply(replies ...Reply) error { if channel.replies == nil { return ErrAlreadyDestroyed } - channel.replies <- reply + for _, reply := range replies { + channel.replies <- reply + } return nil } diff --git a/irc/client.go b/irc/client.go index 69f57b5e..5b74320e 100644 --- a/irc/client.go +++ b/irc/client.go @@ -11,23 +11,24 @@ import ( ) type Client struct { - away bool - channels ChannelSet - conn net.Conn - hostname string - idleTimer *time.Timer - invisible bool - nick string - operator bool - quitTimer *time.Timer - realname string - recv *bufio.Reader - registered bool - replies chan<- Reply - send *bufio.Writer - server *Server - serverPass bool - username string + away bool + awayMessage string + channels ChannelSet + conn net.Conn + hostname string + idleTimer *time.Timer + invisible bool + nick string + operator bool + quitTimer *time.Timer + realname string + recv *bufio.Reader + registered bool + replies chan<- Reply + send *bufio.Writer + server *Server + serverPass bool + username string } func NewClient(server *Server, conn net.Conn) *Client { diff --git a/irc/commands.go b/irc/commands.go index 9bbb994c..62676a2d 100644 --- a/irc/commands.go +++ b/irc/commands.go @@ -18,6 +18,7 @@ var ( NotEnoughArgsError = errors.New("not enough arguments") ErrParseCommand = errors.New("failed to parse message") parseCommandFuncs = map[string]parseCommandFunc{ + "AWAY": NewAwayCommand, "CAP": NewCapCommand, "JOIN": NewJoinCommand, "MODE": NewModeCommand, @@ -609,3 +610,24 @@ func NewProxyCommand(args []string) (editableCommand, error) { destPort: args[4], }, nil } + +type AwayCommand struct { + BaseCommand + text string + away bool +} + +func (msg *AwayCommand) String() string { + return fmt.Sprintf("AWAY(%s)", msg.text) +} + +func NewAwayCommand(args []string) (editableCommand, error) { + cmd := &AwayCommand{} + + if len(args) > 0 { + cmd.text = args[0] + cmd.away = true + } + + return cmd, nil +} diff --git a/irc/reply.go b/irc/reply.go index 1d52b579..f275e373 100644 --- a/irc/reply.go +++ b/irc/reply.go @@ -252,8 +252,23 @@ func RplBanList(channel *Channel, ban UserMask) Reply { } func RplEndOfBanList(channel *Channel) Reply { - return NewNumericReply(channel.server, RPL_ENDOFBANLIST, "%s :End of channel ban list", - channel.name) + return NewNumericReply(channel.server, RPL_ENDOFBANLIST, + "%s :End of channel ban list", channel.name) +} + +func RplNowAway(server *Server) Reply { + return NewNumericReply(server, RPL_NOWAWAY, + ":You have been marked as being away") +} + +func RplUnAway(server *Server) Reply { + return NewNumericReply(server, RPL_UNAWAY, + ":You are no longer marked as being away") +} + +func RplAway(server *Server, client *Client) Reply { + return NewNumericReply(server, RPL_AWAY, + "%s :%s", client.nick, client.awayMessage) } // errors (also numeric) diff --git a/irc/server.go b/irc/server.go index afe337e1..f519cb72 100644 --- a/irc/server.go +++ b/irc/server.go @@ -147,12 +147,12 @@ func (s *Server) tryRegister(c *Client) { RplYourHost(s), RplCreated(s), RplMyInfo(s)) - server.MOTD(c) + s.MOTD(c) } } func (server *Server) MOTD(client *Client) { - c.Reply(ErrNoMOTD(server)) + client.Reply(ErrNoMOTD(server)) } func (s *Server) Id() string { @@ -305,6 +305,9 @@ func (m *PrivMsgCommand) HandleServer(s *Server) { return } target.Reply(RplPrivMsg(m.Client(), target, m.message)) + if target.away { + m.Client().Reply(RplAway(s, target)) + } } func (m *ModeCommand) HandleServer(s *Server) { @@ -407,3 +410,15 @@ func (msg *CapCommand) HandleServer(server *Server) { func (msg *ProxyCommand) HandleServer(server *Server) { msg.Client().hostname = LookupHostname(msg.sourceIP) } + +func (msg *AwayCommand) HandleServer(server *Server) { + client := msg.Client() + client.away = msg.away + client.awayMessage = msg.text + + if client.away { + client.Reply(RplNowAway(server)) + } else { + client.Reply(RplUnAway(server)) + } +} diff --git a/irc/types.go b/irc/types.go index 3ecd248d..585f99b2 100644 --- a/irc/types.go +++ b/irc/types.go @@ -108,7 +108,7 @@ type Identifier interface { } type Replier interface { - Reply(Reply) error + Reply(...Reply) error } type Reply interface {