diff --git a/src/irc/channel.go b/src/irc/channel.go index c3684b40..570a5413 100644 --- a/src/irc/channel.go +++ b/src/irc/channel.go @@ -53,12 +53,12 @@ func NewChannel(s *Server, name string) *Channel { } // Forward `Reply`s to all `User`s of the `Channel`. -func (ch *Channel) receiveReplies(replies <-chan Reply) { +func (channel *Channel) receiveReplies(replies <-chan Reply) { for reply := range replies { if DEBUG_CHANNEL { - log.Printf("%s → %s", ch, reply) + log.Printf("%s → %s", channel, reply) } - for user := range ch.members { + for user := range channel.members { if user != reply.Source() { user.replies <- reply } @@ -66,27 +66,21 @@ func (ch *Channel) receiveReplies(replies <-chan Reply) { } } -func (ch *Channel) receiveCommands(commands <-chan ChannelCommand) { +func (channel *Channel) receiveCommands(commands <-chan ChannelCommand) { for command := range commands { if DEBUG_CHANNEL { - log.Printf("%s ← %s %s", ch, command.Source(), command) + log.Printf("%s ← %s %s", channel, command.Source(), command) } - command.HandleChannel(ch) + command.HandleChannel(channel) } } -func (ch *Channel) Nicks() []string { - nicks := make([]string, len(ch.members)) - i := 0 - for member := range ch.members { - nicks[i] = member.Nick() - i++ - } - return nicks +func (channel *Channel) Nicks() []string { + return channel.members.Nicks() } -func (ch *Channel) IsEmpty() bool { - return len(ch.members) == 0 +func (channel *Channel) IsEmpty() bool { + return len(channel.members) == 0 } func (channel *Channel) GetTopic(replier Replier) { @@ -158,7 +152,7 @@ func (m *PartCommand) HandleChannel(channel *Channel) { channel.members.Remove(user) user.channels.Remove(channel) - if len(channel.members) == 0 { + if channel.IsEmpty() { channel.server.DeleteChannel(channel) } } diff --git a/src/irc/commands.go b/src/irc/commands.go index b22de07f..32dfee52 100644 --- a/src/irc/commands.go +++ b/src/irc/commands.go @@ -45,9 +45,6 @@ func (command *BaseCommand) Client() *Client { } func (command *BaseCommand) SetClient(c *Client) { - if command.client != nil { - panic("SetClient called twice!") - } command.client = c } diff --git a/src/irc/nickserv.go b/src/irc/nickserv.go index 49d3dd35..0f3d0286 100644 --- a/src/irc/nickserv.go +++ b/src/irc/nickserv.go @@ -27,7 +27,7 @@ func (ns *NickServ) SetBase(base *BaseService) { ns.BaseService = *base } -func (ns NickServ) Debug() bool { +func (ns *NickServ) Debug() bool { return DEBUG_NICKSERV } diff --git a/src/irc/reply.go b/src/irc/reply.go index e3d6f229..ba6a036c 100644 --- a/src/irc/reply.go +++ b/src/irc/reply.go @@ -13,7 +13,6 @@ type Identifier interface { } type Replier interface { - Identifier Replies() chan<- Reply } @@ -40,7 +39,10 @@ func NewStringReply(source Identifier, code string, format string, args ...interface{}) *StringReply { message := fmt.Sprintf(format, args...) fullMessage := fmt.Sprintf(":%s %s %s", source.Id(), code, message) - return &StringReply{BaseReply{source, fullMessage}, code} + return &StringReply{ + BaseReply: BaseReply{source, fullMessage}, + code: code, + } } func (reply *StringReply) Format(client *Client) string { @@ -57,9 +59,12 @@ type NumericReply struct { code int } -func NewNumericReply(source Identifier, code int, - format string, args ...interface{}) *NumericReply { - return &NumericReply{BaseReply{source, fmt.Sprintf(format, args...)}, code} +func NewNumericReply(source Identifier, code int, format string, + args ...interface{}) *NumericReply { + return &NumericReply{ + BaseReply: BaseReply{source, fmt.Sprintf(format, args...)}, + code: code, + } } func (reply *NumericReply) Format(client *Client) string { @@ -78,8 +83,8 @@ func RplPrivMsg(source Identifier, target Identifier, message string) Reply { return NewStringReply(source, RPL_PRIVMSG, "%s :%s", target.Nick(), message) } -func RplNick(client *Client, newNick string) Reply { - return NewStringReply(client, RPL_NICK, newNick) +func RplNick(source Identifier, newNick string) Reply { + return NewStringReply(source, RPL_NICK, newNick) } func RplPrivMsgChannel(channel *Channel, source Identifier, message string) Reply { @@ -129,8 +134,7 @@ func RplMyInfo(server *Server) Reply { } func RplUModeIs(server *Server, client *Client) Reply { - return NewNumericReply(server, RPL_UMODEIS, - client.UModeString()) + return NewNumericReply(server, RPL_UMODEIS, client.UModeString()) } func RplNoTopic(channel *Channel) Reply { diff --git a/src/irc/server.go b/src/irc/server.go index 5c6c113e..e76a3988 100644 --- a/src/irc/server.go +++ b/src/irc/server.go @@ -11,7 +11,6 @@ const ( DEBUG_SERVER = true ) -type ClientNameMap map[string]*Client type ChannelNameMap map[string]*Channel type UserNameMap map[string]*User type ServiceNameMap map[string]Service @@ -84,7 +83,7 @@ func (s *Server) GetOrMakeChannel(name string) *Channel { } // Send a message to clients of channels fromClient is a member. -func (s Server) InterestedUsers(fromUser *User) UserSet { +func (s *Server) InterestedUsers(fromUser *User) UserSet { users := make(UserSet) users.Add(fromUser) for channel := range fromUser.channels { @@ -99,16 +98,25 @@ func (s Server) InterestedUsers(fromUser *User) UserSet { // server functionality func (s *Server) tryRegister(c *Client) { - if !c.registered && c.HasNick() && c.HasUsername() && (s.password == nil || c.serverPass) { + if !c.registered && c.HasNick() && c.HasUsername() && s.CheckPassword(c) { c.registered = true - replies := []Reply{RplWelcome(s, c), RplYourHost(s, c), RplCreated(s), RplMyInfo(s)} + replies := []Reply{ + RplWelcome(s, c), + RplYourHost(s, c), + RplCreated(s), + RplMyInfo(s), + } for _, reply := range replies { c.Replies() <- reply } } } -func (s Server) Id() string { +func (s *Server) CheckPassword(c *Client) bool { + return (s.password == nil) || c.serverPass +} + +func (s *Server) Id() string { return s.name } @@ -164,7 +172,19 @@ func (m *NickCommand) HandleServer(s *Server) { return } - c.user.Replies() <- ErrNoPrivileges(s) + user := c.user + if s.users[m.nickname] != nil { + user.Replies() <- ErrNickNameInUse(s, m.nickname) + return + } + + delete(s.users, user.nick) + s.users[m.nickname] = user + reply := RplNick(user, m.nickname) + for iuser := range s.InterestedUsers(user) { + iuser.Replies() <- reply + } + user.nick = m.nickname } func (m *UserMsgCommand) HandleServer(s *Server) { diff --git a/src/irc/user.go b/src/irc/user.go index 507ca202..20023393 100644 --- a/src/irc/user.go +++ b/src/irc/user.go @@ -35,6 +35,16 @@ func (set UserSet) Remove(user *User) { delete(set, user) } +func (set UserSet) Nicks() []string { + nicks := make([]string, len(set)) + i := 0 + for member := range set { + nicks[i] = member.Nick() + i++ + } + return nicks +} + func NewUser(nick string, password string, server *Server) *User { commands := make(chan UserCommand) replies := make(chan Reply)